Merge commit 'release-4-0-0alpha15' into master4-tmp
[amitay/samba.git] / source4 / scripting / python / samba / netcmd / __init__.py
1 #!/usr/bin/env python
2
3 # Unix SMB/CIFS implementation.
4 # Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2009
5 # Copyright (C) Theresa Halloran <theresahalloran@gmail.com> 2011
6 #
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3 of the License, or
10 # (at your option) any later version.
11 #
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 # GNU General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License
18 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 #
20
21 import optparse, samba
22 from samba import getopt as options
23 from ldb import LdbError
24 import sys, traceback
25
26
27 class Option(optparse.Option):
28     pass
29
30
31 class Command(object):
32     """A net command."""
33
34     def _get_description(self):
35         return self.__doc__.splitlines()[0].rstrip("\n")
36
37     def _get_name(self):
38         name = self.__class__.__name__
39         if name.startswith("cmd_"):
40             return name[4:]
41         return name
42
43     name = property(_get_name)
44
45     def usage(self, *args):
46         parser, _ = self._create_parser()
47         parser.print_usage()
48
49     description = property(_get_description)
50
51     def _get_synopsis(self):
52         ret = self.name
53         if self.takes_args:
54             ret += " " + " ".join([x.upper() for x in self.takes_args])
55         return ret
56
57     def show_command_error(self, e):
58         '''display a command error'''
59         if isinstance(e, CommandError):
60             (etype, evalue, etraceback) = e.exception_info
61             inner_exception = e.inner_exception
62             message = e.message
63             force_traceback = False
64         else:
65             (etype, evalue, etraceback) = sys.exc_info()
66             inner_exception = e
67             message = "uncaught exception"
68             force_traceback = True
69
70         if isinstance(inner_exception, LdbError):
71             (ldb_ecode, ldb_emsg) = inner_exception
72             print >>sys.stderr, "ERROR(ldb): %s - %s" % (message, ldb_emsg)
73         elif isinstance(inner_exception, AssertionError):
74             print >>sys.stderr, "ERROR(assert): %s" % message
75             force_traceback = True
76         elif isinstance(inner_exception, RuntimeError):
77             print >>sys.stderr, "ERROR(runtime): %s - %s" % (message, evalue)
78         elif type(inner_exception) is Exception:
79             print >>sys.stderr, "ERROR(exception): %s - %s" % (message, evalue)
80             force_traceback = True
81         elif inner_exception is None:
82             print >>sys.stderr, "ERROR: %s" % (message)
83         else:
84             print >>sys.stderr, "ERROR(%s): %s - %s" % (str(etype), message, evalue)
85             force_traceback = True
86
87         if force_traceback or samba.get_debug_level() >= 3:
88             traceback.print_tb(etraceback)
89
90
91     synopsis = property(_get_synopsis)
92
93     outf = sys.stdout
94
95     takes_args = []
96     takes_options = []
97     takes_optiongroups = {}
98
99     def _create_parser(self):
100         parser = optparse.OptionParser(self.synopsis)
101         parser.prog = "net"
102         parser.add_options(self.takes_options)
103         optiongroups = {}
104         for name, optiongroup in self.takes_optiongroups.iteritems():
105             optiongroups[name] = optiongroup(parser)
106             parser.add_option_group(optiongroups[name])
107         return parser, optiongroups
108
109     def message(self, text):
110         print text
111
112     def _run(self, *argv):
113         parser, optiongroups = self._create_parser()
114         opts, args = parser.parse_args(list(argv))
115         # Filter out options from option groups
116         args = args[1:]
117         kwargs = dict(opts.__dict__)
118         for option_group in parser.option_groups:
119             for option in option_group.option_list:
120                 if option.dest is not None:
121                     del kwargs[option.dest]
122         kwargs.update(optiongroups)
123         min_args = 0
124         max_args = 0
125         for i, arg in enumerate(self.takes_args):
126             if arg[-1] not in ("?", "*"):
127                 min_args += 1
128             max_args += 1
129             if arg[-1] == "*":
130                 max_args = -1
131         if len(args) < min_args or (max_args != -1 and len(args) > max_args):
132             self.usage(*args)
133             return -1
134         try:
135             return self.run(*args, **kwargs)
136         except Exception, e:
137             self.show_command_error(e)
138             return -1
139
140     def run(self):
141         """Run the command. This should be overriden by all subclasses."""
142         raise NotImplementedError(self.run)
143
144
145 class SuperCommand(Command):
146     """A command with subcommands."""
147
148     subcommands = {}
149
150     def _run(self, myname, subcommand=None, *args):
151         if subcommand in self.subcommands:
152             return self.subcommands[subcommand]._run(subcommand, *args)
153         print "Available subcommands:"
154         for cmd in self.subcommands:
155             print "\t%-20s - %s" % (cmd, self.subcommands[cmd].description)
156         if subcommand in [None, 'help', '-h', '--help' ]:
157             return 0
158         raise CommandError("No such subcommand '%s'" % subcommand)
159
160     def usage(self, myname, subcommand=None, *args):
161         if subcommand is None or not subcommand in self.subcommands:
162             print "Usage: %s (%s) [options]" % (myname,
163                 " | ".join(self.subcommands.keys()))
164         else:
165             return self.subcommands[subcommand].usage(*args)
166
167
168 class CommandError(Exception):
169     '''an exception class for netcmd errors'''
170     def __init__(self, message, inner_exception=None):
171         self.message = message
172         self.inner_exception = inner_exception
173         self.exception_info = sys.exc_info()
174
175
176 commands = {}
177 from samba.netcmd.pwsettings import cmd_pwsettings
178 commands["pwsettings"] = cmd_pwsettings()
179 from samba.netcmd.domainlevel import cmd_domainlevel
180 commands["domainlevel"] = cmd_domainlevel()
181 from samba.netcmd.setpassword import cmd_setpassword
182 commands["setpassword"] = cmd_setpassword()
183 from samba.netcmd.newuser import cmd_newuser
184 commands["newuser"] = cmd_newuser()
185 from samba.netcmd.netacl import cmd_acl
186 commands["acl"] = cmd_acl()
187 from samba.netcmd.fsmo import cmd_fsmo
188 commands["fsmo"] = cmd_fsmo()
189 from samba.netcmd.export import cmd_export
190 commands["export"] = cmd_export()
191 from samba.netcmd.time import cmd_time
192 commands["time"] = cmd_time()
193 from samba.netcmd.user import cmd_user
194 commands["user"] = cmd_user()
195 from samba.netcmd.vampire import cmd_vampire
196 commands["vampire"] = cmd_vampire()
197 from samba.netcmd.machinepw import cmd_machinepw
198 commands["machinepw"] = cmd_machinepw()
199 from samba.netcmd.spn import cmd_spn
200 commands["spn"] = cmd_spn()
201 from samba.netcmd.group import cmd_group
202 commands["group"] = cmd_group()
203 from samba.netcmd.join import cmd_join
204 commands["join"] = cmd_join()
205 from samba.netcmd.rodc import cmd_rodc
206 commands["rodc"] = cmd_rodc()
207 from samba.netcmd.drs import cmd_drs
208 commands["drs"] = cmd_drs()
209 from samba.netcmd.gpo import cmd_gpo
210 commands["gpo2"] = cmd_gpo()
211 from samba.netcmd.ldapcmp import cmd_ldapcmp
212 commands["ldapcmp"] = cmd_ldapcmp()
213 from samba.netcmd.testparm import cmd_testparm
214 commands["testparm"] =  cmd_testparm()
215 from samba.netcmd.dbcheck import cmd_dbcheck
216 commands["dbcheck"] =  cmd_dbcheck()