2010-06-24 08:33:58 +04:00
#!/usr/bin/env python
2009-12-28 03:04:33 +03:00
# Unix SMB/CIFS implementation.
# Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2009
2011-05-20 00:17:07 +04:00
# Copyright (C) Theresa Halloran <theresahalloran@gmail.com> 2011
2011-07-18 23:45:39 +04:00
# Copyright (C) Giampaolo Lauria <lauria2@yahoo.com> 2011
2009-12-28 03:04:33 +03:00
#
# 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
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
2010-11-29 06:11:57 +03:00
import optparse , samba
2010-03-01 06:39:53 +03:00
from samba import getopt as options
2010-11-29 06:11:57 +03:00
from ldb import LdbError
import sys , traceback
2009-12-28 15:53:18 +03:00
class Option ( optparse . Option ) :
pass
2011-07-18 19:30:23 +04:00
2009-12-28 03:04:33 +03:00
class Command ( object ) :
2011-07-19 02:34:45 +04:00
""" A samba-tool command. """
2011-07-28 22:21:40 +04:00
2009-12-28 03:04:33 +03:00
def _get_description ( self ) :
2009-12-28 18:05:04 +03:00
return self . __doc__ . splitlines ( ) [ 0 ] . rstrip ( " \n " )
2009-12-28 15:53:18 +03:00
2011-07-28 22:21:40 +04:00
description = property ( _get_description )
2009-12-28 15:53:18 +03:00
2011-07-28 22:21:40 +04:00
# synopsis must be defined in all subclasses in order to provide the command usage
2011-09-09 07:26:04 +04:00
synopsis = " Please provide synopsis for this command. "
2011-07-30 01:04:45 +04:00
# long_description is a string describing the command in details
long_description = " "
2011-07-28 22:21:40 +04:00
takes_args = [ ]
takes_options = [ ]
takes_optiongroups = {
" sambaopts " : options . SambaOptions ,
" credopts " : options . CredentialsOptions ,
" versionopts " : options . VersionOptions ,
}
outf = sys . stdout
2009-12-28 03:04:33 +03:00
2009-12-30 23:06:21 +03:00
def usage ( self , * args ) :
2009-12-28 18:48:07 +03:00
parser , _ = self . _create_parser ( )
parser . print_usage ( )
2009-12-28 03:21:27 +03:00
2010-11-29 06:11:57 +03:00
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
if force_traceback or samba . get_debug_level ( ) > = 3 :
traceback . print_tb ( etraceback )
2011-07-21 04:29:21 +04:00
sys . exit ( 1 )
2010-11-29 06:11:57 +03:00
2009-12-28 18:48:07 +03:00
def _create_parser ( self ) :
2011-09-09 07:27:13 +04:00
parser = optparse . OptionParser ( usage = self . synopsis ,
2011-07-30 01:04:45 +04:00
description = self . long_description )
2009-12-28 18:48:07 +03:00
parser . add_options ( self . takes_options )
optiongroups = { }
for name , optiongroup in self . takes_optiongroups . iteritems ( ) :
optiongroups [ name ] = optiongroup ( parser )
parser . add_option_group ( optiongroups [ name ] )
return parser , optiongroups
2009-12-28 18:05:04 +03:00
def message ( self , text ) :
print text
2009-12-28 15:53:18 +03:00
def _run ( self , * argv ) :
2009-12-28 18:48:07 +03:00
parser , optiongroups = self . _create_parser ( )
opts , args = parser . parse_args ( list ( argv ) )
# Filter out options from option groups
2009-12-28 23:07:25 +03:00
args = args [ 1 : ]
2009-12-28 18:48:07 +03:00
kwargs = dict ( opts . __dict__ )
for option_group in parser . option_groups :
for option in option_group . option_list :
2010-04-09 04:37:20 +04:00
if option . dest is not None :
del kwargs [ option . dest ]
2009-12-28 18:48:07 +03:00
kwargs . update ( optiongroups )
2011-07-19 00:48:03 +04:00
# 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
2009-12-30 22:40:11 +03:00
min_args = 0
max_args = 0
2011-07-19 00:48:03 +04:00
undetermined_max_args = False
2009-12-30 21:53:05 +03:00
for i , arg in enumerate ( self . takes_args ) :
2011-07-19 00:48:03 +04:00
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 ( )
2009-12-28 18:48:07 +03:00
return - 1
2011-07-19 00:48:03 +04:00
2009-12-28 22:37:48 +03:00
try :
return self . run ( * args , * * kwargs )
2010-11-29 06:11:57 +03:00
except Exception , e :
self . show_command_error ( e )
2009-12-28 22:37:48 +03:00
return - 1
2009-12-28 15:53:18 +03:00
2009-12-28 03:04:33 +03:00
def run ( self ) :
""" Run the command. This should be overriden by all subclasses. """
raise NotImplementedError ( self . run )
2011-07-18 19:30:23 +04:00
2009-12-28 15:53:18 +03:00
class SuperCommand ( Command ) :
2011-07-19 02:34:45 +04:00
""" A samba-tool command with subcommands. """
2009-12-28 15:53:18 +03:00
subcommands = { }
2009-12-30 23:06:21 +03:00
def _run ( self , myname , subcommand = None , * args ) :
2010-11-28 02:52:09 +03:00
if subcommand in self . subcommands :
return self . subcommands [ subcommand ] . _run ( subcommand , * args )
2011-07-29 05:44:06 +04:00
if ( myname == " samba-tool " ) :
usage = " samba-tool <subcommand> "
else :
usage = " samba-tool %s <subcommand> " % myname
print " Usage: %s [options] " % usage
2010-11-28 02:52:09 +03:00
print " Available subcommands: "
2011-07-21 06:15:33 +04:00
subcmds = self . subcommands . keys ( )
subcmds . sort ( )
2011-09-09 07:24:10 +04:00
max_length = max ( map ( lambda c : len ( c ) , subcmds ) )
2011-07-21 06:15:33 +04:00
for cmd in subcmds :
2011-08-02 01:47:31 +04:00
print " %*s - %s " % ( - max_length , cmd , self . subcommands [ cmd ] . description )
2011-07-18 23:45:39 +04:00
if subcommand in [ None ] :
2011-07-21 06:21:17 +04:00
raise CommandError ( " You must specify a subcommand " )
if subcommand in [ ' help ' , ' -h ' , ' --help ' ] :
2011-07-29 05:44:06 +04:00
print " For more help on a specific subcommand, please type: %s (-h|--help) " % usage
2009-12-28 15:53:18 +03:00
return 0
2011-07-21 06:21:17 +04:00
raise CommandError ( " No such subcommand ' %s ' " % subcommand )
2009-12-30 23:06:21 +03:00
2009-12-28 15:53:18 +03:00
2011-07-18 19:30:23 +04:00
2009-12-28 18:05:04 +03:00
class CommandError ( Exception ) :
2011-07-19 02:34:45 +04:00
''' an exception class for samba-tool cmd errors '''
2010-11-29 06:11:57 +03:00
def __init__ ( self , message , inner_exception = None ) :
self . message = message
self . inner_exception = inner_exception
self . exception_info = sys . exc_info ( )