-#!/usr/bin/python
+#!/usr/bin/env python
# Unix SMB/CIFS implementation.
# Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2009
+# Copyright (C) Theresa Halloran <theresahalloran@gmail.com> 2011
+# Copyright (C) Giampaolo Lauria <lauria2@yahoo.com> 2011
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
-import optparse
+import optparse, samba
from samba import getopt as options
-import sys
+from ldb import LdbError
+import sys, traceback
class Option(optparse.Option):
pass
+
class Command(object):
- """A net command."""
+ """A samba-tool command."""
def _get_description(self):
return self.__doc__.splitlines()[0].rstrip("\n")
description = property(_get_description)
- def _get_synopsis(self):
- ret = self.name
- if self.takes_args:
- ret += " " + " ".join([x.upper() for x in self.takes_args])
- return ret
+ def show_command_error(self, e):
+ '''display a command error'''
+ if isinstance(e, CommandError):
+ (etype, evalue, etraceback) = e.exception_info
+ inner_exception = e.inner_exception
+ message = e.message
+ force_traceback = False
+ else:
+ (etype, evalue, etraceback) = sys.exc_info()
+ inner_exception = e
+ message = "uncaught exception"
+ force_traceback = True
+
+ if isinstance(inner_exception, LdbError):
+ (ldb_ecode, ldb_emsg) = inner_exception
+ print >>sys.stderr, "ERROR(ldb): %s - %s" % (message, ldb_emsg)
+ elif isinstance(inner_exception, AssertionError):
+ print >>sys.stderr, "ERROR(assert): %s" % message
+ force_traceback = True
+ elif isinstance(inner_exception, RuntimeError):
+ print >>sys.stderr, "ERROR(runtime): %s - %s" % (message, evalue)
+ elif type(inner_exception) is Exception:
+ print >>sys.stderr, "ERROR(exception): %s - %s" % (message, evalue)
+ force_traceback = True
+ elif inner_exception is None:
+ print >>sys.stderr, "ERROR: %s" % (message)
+ else:
+ print >>sys.stderr, "ERROR(%s): %s - %s" % (str(etype), message, evalue)
+ force_traceback = True
- synopsis = property(_get_synopsis)
+ if force_traceback or samba.get_debug_level() >= 3:
+ traceback.print_tb(etraceback)
+ sys.exit(1)
+ outf = sys.stdout
+
+ # synopsis must be defined in all subclasses in order to provide the command usage
+ synopsis = ""
takes_args = []
takes_options = []
- takes_optiongroups = {}
+ takes_optiongroups = {
+ "sambaopts": options.SambaOptions,
+ "credopts": options.CredentialsOptions,
+ "versionopts": options.VersionOptions,
+ }
def _create_parser(self):
parser = optparse.OptionParser(self.synopsis)
- parser.prog = "net"
parser.add_options(self.takes_options)
optiongroups = {}
for name, optiongroup in self.takes_optiongroups.iteritems():
kwargs = dict(opts.__dict__)
for option_group in parser.option_groups:
for option in option_group.option_list:
- del kwargs[option.dest]
+ if option.dest is not None:
+ del kwargs[option.dest]
kwargs.update(optiongroups)
+
+ # Check for a min a max number of allowed arguments, whenever possible
+ # The suffix "?" means zero or one occurence
+ # The suffix "+" means at least one occurence
min_args = 0
max_args = 0
+ undetermined_max_args = False
for i, arg in enumerate(self.takes_args):
- if arg[-1] not in ("?", "*"):
- min_args += 1
- max_args += 1
- if arg[-1] == "*":
- max_args = -1
- if len(args) < min_args or (max_args != -1 and len(args) > max_args):
- self.usage(*args)
+ if arg[-1] != "?":
+ min_args += 1
+ if arg[-1] == "+":
+ undetermined_max_args = True
+ else:
+ max_args += 1
+ if (len(args) < min_args) or (undetermined_max_args == False and len(args) > max_args):
+ parser.print_usage()
return -1
+
try:
return self.run(*args, **kwargs)
- except CommandError, e:
- print >>sys.stderr, "ERROR: %s" % e
+ except Exception, e:
+ self.show_command_error(e)
return -1
def run(self):
raise NotImplementedError(self.run)
+
class SuperCommand(Command):
- """A command with subcommands."""
+ """A samba-tool command with subcommands."""
subcommands = {}
def _run(self, myname, subcommand=None, *args):
- if subcommand is None:
- print "Available subcommands:"
- for subcommand in self.subcommands:
- print "\t%s" % subcommand
+ if subcommand in self.subcommands:
+ return self.subcommands[subcommand]._run(subcommand, *args)
+ print "Usage: samba-tool %s <subcommand> [options]" % myname
+ print "Available subcommands:"
+ subcmds = self.subcommands.keys()
+ subcmds.sort()
+ for cmd in subcmds:
+ print " %-20s - %s" % (cmd, self.subcommands[cmd].description)
+ if subcommand in [None]:
+ raise CommandError("You must specify a subcommand")
+ if subcommand in ['help', '-h', '--help']:
+ print "For more help on a specific subcommand, please type: samba-tool %s <subcommand> (-h|--help)" % myname
return 0
- if not subcommand in self.subcommands:
- raise CommandError("No such subcommand '%s'" % subcommand)
- return self.subcommands[subcommand]._run(subcommand, *args)
+ raise CommandError("No such subcommand '%s'" % subcommand)
def usage(self, myname, subcommand=None, *args):
if subcommand is None or not subcommand in self.subcommands:
- print "Usage: %s (%s) [options]" % (myname,
+ print "Usage: samba-tool %s (%s) [options]" % (myname,
" | ".join(self.subcommands.keys()))
else:
return self.subcommands[subcommand].usage(*args)
+
class CommandError(Exception):
- pass
+ '''an exception class for samba-tool cmd errors'''
+ def __init__(self, message, inner_exception=None):
+ self.message = message
+ self.inner_exception = inner_exception
+ self.exception_info = sys.exc_info()
+
commands = {}
-from samba.netcmd.pwsettings import cmd_pwsettings
-commands["pwsettings"] = cmd_pwsettings()
-from samba.netcmd.domainlevel import cmd_domainlevel
-commands["domainlevel"] = cmd_domainlevel()
-from samba.netcmd.setpassword import cmd_setpassword
-commands["setpassword"] = cmd_setpassword()
-from samba.netcmd.setexpiry import cmd_setexpiry
-commands["setexpiry"] = cmd_setexpiry()
-from samba.netcmd.enableaccount import cmd_enableaccount
-commands["enableaccount"] = cmd_enableaccount()
-from samba.netcmd.newuser import cmd_newuser
-commands["newuser"] = cmd_newuser()
from samba.netcmd.netacl import cmd_acl
commands["acl"] = cmd_acl()
from samba.netcmd.fsmo import cmd_fsmo
commands["fsmo"] = cmd_fsmo()
-from samba.netcmd.export import cmd_export
-commands["export"] = cmd_export()
+from samba.netcmd.time import cmd_time
+commands["time"] = cmd_time()
+from samba.netcmd.user import cmd_user
+commands["user"] = cmd_user()
+from samba.netcmd.vampire import cmd_vampire
+commands["vampire"] = cmd_vampire()
+from samba.netcmd.spn import cmd_spn
+commands["spn"] = cmd_spn()
+from samba.netcmd.group import cmd_group
+commands["group"] = cmd_group()
+from samba.netcmd.rodc import cmd_rodc
+commands["rodc"] = cmd_rodc()
+from samba.netcmd.drs import cmd_drs
+commands["drs"] = cmd_drs()
+from samba.netcmd.gpo import cmd_gpo
+commands["gpo2"] = cmd_gpo()
+from samba.netcmd.ldapcmp import cmd_ldapcmp
+commands["ldapcmp"] = cmd_ldapcmp()
+from samba.netcmd.testparm import cmd_testparm
+commands["testparm"] = cmd_testparm()
+from samba.netcmd.dbcheck import cmd_dbcheck
+commands["dbcheck"] = cmd_dbcheck()
+from samba.netcmd.delegation import cmd_delegation
+commands["delegation"] = cmd_delegation()
+from samba.netcmd.domain import cmd_domain
+commands["domain"] = cmd_domain()