From 1b18110a1df54b38a6fa5062ad025c19b33e6014 Mon Sep 17 00:00:00 2001 From: Narayan Desai Date: Tue, 11 Apr 2006 14:22:13 +0000 Subject: Switch to new option parsing lib git-svn-id: https://svn.mcs.anl.gov/repos/bcfg/trunk/bcfg2@1834 ce84e21b-d406-0410-9b95-82705330c041 --- src/sbin/bcfg2 | 221 +++++++++++--------------------------------------- src/sbin/bcfg2-server | 89 +++++--------------- 2 files changed, 68 insertions(+), 242 deletions(-) diff --git a/src/sbin/bcfg2 b/src/sbin/bcfg2 index 5afa9d7e5..0720d1b53 100755 --- a/src/sbin/bcfg2 +++ b/src/sbin/bcfg2 @@ -3,10 +3,11 @@ '''Bcfg2 Client''' __revision__ = '$Revision$' -from ConfigParser import ConfigParser, NoSectionError, NoOptionError from lxml.etree import Element, XML, tostring, XMLSyntaxError -import getopt, logging, os, signal, sys, tempfile, time, traceback, xmlrpclib +import logging, os, signal, sys, tempfile, time, traceback, xmlrpclib +import Bcfg2.Options + try: import Bcfg2.Client.Proxy, Bcfg2.Logging except KeyError: @@ -19,7 +20,7 @@ def cb_sigint_handler(signum, frame): class Client: ''' The main bcfg2 client class ''' - def __init__(self, args): + def __init__(self): level = 30 if '-v' in sys.argv: level = 20 @@ -29,82 +30,53 @@ class Client: self.logger = logging.getLogger('bcfg2') self.toolset = None self.config = None - self.options = { - 'verbose': 'v', - 'quick': 'q', - 'debug': 'd', - 'dryrun': 'n', - 'build': 'B', - 'paranoid': 'P', - 'bundle': 'b', - 'file': 'f', - 'cache': 'c', - 'profile': 'p', - 'image': 'i', - 'remove': 'r', - 'help': 'h', - 'setup': 's', - 'server': 'S', - 'user': 'u', - 'password': 'x', - 'retries': 'R' - } - self.argOptions = { - 'v': 'verbose', - 'q': 'quick', - 'd': 'debug', - 'n': 'dryrun', - 'B': 'build', - 'P': 'paranoid', - 'b': 'bundle', - 'f': 'file', - 'c': 'cache', - 'p': 'profile', - 'r': 'remove', - 'h': 'help', - 's': 'setup', - 'S': 'server', - 'u': 'user', - 'x': 'password', - 'R': 'retries' - } - self.descriptions = { - 'verbose': "enable verbose output", - 'quick': "disable some checksum verification", - 'debug': "enable debugging output", - 'dryrun': "do not actually change the system", - 'build': "disable service control (implies -q)", - 'paranoid': "make automatic backups of config files", - 'bundle': "only configure the given bundle", - 'file': "configure from a file rather than querying the server", - 'cache': "store the configuration in a file", - 'image': "assert the given image for the host", - 'profile': "assert the given profile for the host", - 'remove': "force removal of additional configuration items", - 'help': "print this help message", - 'setup': "use given setup file (default /etc/bcfg2.conf)", - 'server': 'the server hostname to connect to', - 'user': 'the user to provide for authentication', - 'password': 'the password to use', - 'retries': 'the number of times to retry network communication' - } - self.argumentDescriptions = { - 'bundle': "", - 'file': "", - 'cache': "", - 'profile': "", - 'remove': "(packages | services | all)", - 'setup': "", - 'server': ' ', - 'user': ' ', - 'password': ' ', - 'retries': '' + + optinfo = { + # 'optname': (('-a', argdesc, optdesc), + # env, cfpath, default, boolean)), + 'verbose':(('-v', False,"enable verbose output"), + False, False, False, True), + 'quick':(('-q', False, "disable some checksum verification"), + False, False, False, True), + 'debug':(('-d', False, "enable debugging output"), + False, False, False, True), + 'dryrun':(('-n', False, "do not actually change the system"), + False, False, False, True), + 'build': (('-B', False, "run in build mode"), + False, False, False, True), + 'paranoid':(('-P', False, "make automatic backups of config files"), + False, False, False, True), + 'bundle':(('-b', '', "only configure the given bundle"), + False, False, False, False), + 'file': (('-f', "", "configure from a file rather than querying the server"), + False, False, False, False), + 'cache': (('-c', "", "store the configuration in a file"), + False, False, False, False), + 'profile': (('-p', '', "assert the given profile for the host"), + False, False, False, False), + 'remove': (('-r', '(packages|services|all)', "force removal of additional configuration items"), + False, False, False, False), + 'help': (('-h', False, "print this help message"), + False, False, False, False), + 'setup': (('-C', '', "use given config file (default /etc/bcfg2.conf)"), + False, False, '/etc/bcfg2.conf', False), + 'server': (('-S', '', 'the server hostname to connect to'), + False, ('components', 'bcfg2'), 'https://localhost:6789', False), + 'user': (('-u', '', 'the user to provide for authentication'), + False, ('communication', 'user'), 'root', False), + 'password': (('-x', '', 'the password to provide for authentication'), + False, ('communication', 'password'), 'password', False), + 'retries': (('-R', '', 'the number of times to retry network communication'), + False, ('communication', 'retries'), '3', False), } - self.setup = {} - self.get_setup(args) + + self.setup = Bcfg2.Options.OptionParser('bcfg2', optinfo).parse() self.logger.debug(self.setup) if self.setup['remove'] not in [False, 'all', 'services', 'packages']: self.logger.error("Got unknown argument %s for -r" % (self.setup['remove'])) + if (self.setup["file"] != False) and (self.setup["cache"] != False): + print "cannot use -f and -c together" + raise SystemExit, 1 def load_toolset(self, toolset_name): '''Import client toolset modules''' @@ -168,103 +140,6 @@ class Client: print "Fatal error: %s" % (message) raise SystemExit, 1 - def usage_error(self, message): - '''Die because script was called the wrong way''' - print "Usage error: %s" % (message) - self.print_usage() - raise SystemExit, 2 - - def print_usage(self): - ''' Display usage information for bcfg2 ''' - print "bcfg2 usage:" - for arg in self.options.iteritems(): - if self.argumentDescriptions.has_key(arg[0]): - print " -%s %s\t%s" % (arg[1], - self.argumentDescriptions[arg[0]], - self.descriptions[arg[0]]) - else: - print " -%s\t\t\t%s" % (arg[1], self.descriptions[arg[0]]) - - def fill_setup_from_file(self, setup_file, ret): - ''' Read any missing configuration information from a file''' - default = { - 'server': 'http://localhost:6789/', - 'user': 'root', - 'retries': '6' - } - config_locations = { - 'server': ('components', 'bcfg2'), - 'user': ('communication', 'user'), - 'password': ('communication', 'password'), - 'retries': ('communicaton', 'retries') - } - - self.logger.debug(self.setup) - - config_parser = None - - for (key, (section, option)) in config_locations.iteritems(): - try: - if not (ret.has_key(key) and ret[key]): - if config_parser == None: - self.logger.debug("no %s provided, reading setup info from %s" % - (key, setup_file)) - config_parser = ConfigParser() - config_parser.read(setup_file) - try: - ret[key] = config_parser.get(section, option) - except (NoSectionError, NoOptionError): - if default.has_key(key): - ret[key] = default[key] - else: - self.fatal_error( - "%s does not contain a value for %s (in %s)" % - (setup_file, option, section)) - except IOError, io_error: - self.fatal_error("unable to read %s: %s" % - (setup_file, io_error)) - except SystemExit: - raise - except: - self.critical_error("reading config file") - - def get_setup(self, args): - '''parse options into a dictionary''' - - for option in self.options.keys(): - self.setup[option] = False - - gstr = "".join([self.options[option] for option in self.options if - option not in self.argumentDescriptions] + - ["%s:" % (self.options[option]) for option in self.options if - option in self.argumentDescriptions]) - - try: - ginfo = getopt.getopt(args, gstr) - except getopt.GetoptError, gerr: - self.usage_error(gerr) - - for (gopt, garg) in ginfo[0]: - option = self.argOptions[gopt[1:]] - if self.argumentDescriptions.has_key(option): - self.setup[option] = garg - else: - self.setup[option] = True - - if (self.setup["file"] != False) and (self.setup["cache"] != False): - self.usage_error("cannot use -f and -c together") - - if self.setup["help"] == True: - self.print_usage() - raise SystemExit, 0 - - if self.setup["setup"]: - setup_file = self.setup["setup"] - else: - setup_file = '/etc/bcfg2.conf' - - self.fill_setup_from_file(setup_file, self.setup) - def run(self): ''' Perform client execution phase ''' times = {} @@ -398,4 +273,4 @@ class Client: if __name__ == '__main__': signal.signal(signal.SIGINT, cb_sigint_handler) - Client(sys.argv[1:]).run() + Client().run() diff --git a/src/sbin/bcfg2-server b/src/sbin/bcfg2-server index 2b0d71d55..daa79d090 100755 --- a/src/sbin/bcfg2-server +++ b/src/sbin/bcfg2-server @@ -8,8 +8,8 @@ from Bcfg2.Server.Metadata import MetadataConsistencyError from xmlrpclib import Fault from lxml.etree import XML, Element, tostring -import getopt, logging, os, select, signal, socket, sys -import Bcfg2.Logging, Bcfg2.Server.Component +import logging, os, select, signal, socket, sys +import Bcfg2.Logging, Bcfg2.Options, Bcfg2.Server.Component logger = logging.getLogger('bcfg2-server') @@ -39,42 +39,6 @@ def critical_error(operation): logger.error(operation, exc_info=1) raise Fault, (7, "Critical unexpected failure: %s" % (operation)) -def fatal_error(message): - '''Signal a fatal error''' - logger.critical("Fatal error: %s" % (message)) - raise SystemExit, 1 - -def usage(message, opts, vopts, odescs, vargDescs): - '''print usage message''' - logger.critical(message) - [logger.critical(" -%s\t\t\t%s" % (arg, odescs[arg])) for arg in opts] - [logger.critical(" -%s %s\t%s" % (arg, vargDescs[arg], odescs[arg])) for arg in vopts] - raise SystemExit, 2 - -def dgetopt(arglist, opt, vopt, descs, argDescs): - '''parse options into a dictionary''' - ret = {} - for optname in opt.values() + vopt.values(): - ret[optname] = False - - gstr = "".join(opt.keys()) + "".join([optionkey + ':' for optionkey in vopt.keys()]) - try: - ginfo = getopt.getopt(arglist, gstr) - except getopt.GetoptError, gerr: - usage("Usage error: %s" % gerr, opt, vopt, descs, argDescs) - - for (gopt, garg) in ginfo[0]: - option = gopt[1:] - if opt.has_key(option): - ret[opt[option]] = True - else: - ret[vopt[option]] = garg - - if ret["help"] == True: - usage("Usage information", opt, vopt, descs, argDescs) - - return ret - class Bcfg2Serv(Bcfg2.Server.Component.Component): """The Bcfg2 Server component providing XML-RPC access to Bcfg methods""" __name__ = 'bcfg2' @@ -85,17 +49,18 @@ class Bcfg2Serv(Bcfg2.Server.Component.Component): def __init__(self, setup): try: Bcfg2.Server.Component.Component.__init__(self, setup) + self.shut = False except Bcfg2.Server.Component.ComponentInitError: self.shut = True - return - self.shut = False + # set shutdown handlers for sigint and sigterm signal.signal(signal.SIGINT, self.start_shutdown) signal.signal(signal.SIGTERM, self.start_shutdown) try: self.Core = Core(setup, setup['configfile']) except CoreInitError, msg: - fatal_error(msg) + logger.critical("Fatal error: %s" % (msg)) + raise SystemExit, 1 self.funcs.update({ "AssertProfile": self.Bcfg2AssertProfile, @@ -205,39 +170,25 @@ if __name__ == '__main__': Bcfg2.Logging.setup_logging('bcfg2-server', to_console=False) else: Bcfg2.Logging.setup_logging('bcfg2-server') - - options = { - 'v':'verbose', - 'd':'debug', - 'h':'help' - } - doptions = { - 'D':'daemon', - 'c':'configfile', - 'C':'client' - } - - descriptions = { - 'v': "enable verbose output", - 'd': "enable debugging output", - 'D': "daemonise the server, storing PID", - 'c': "set the server's config file", - 'C': "always return the given client's config (debug only)", - 'h': "display this usage information" - } - argDescriptions = { - 'D': " ", - 'c': "", - 'C': "" + optinfo = { + 'verbose': (('-v', False, 'enable verbose output'), + False, False, False, True), + 'debug': (('-d', False, 'enable debugging output'), + False, False, False, True), + 'help': (('-h', False, 'display this usage information'), + False, False, False, True), + 'daemon': (('-D', '', 'daemonize the server, storing PID'), + False, False, False, False), + 'configfile': (('-C', '', 'use this config file'), + False, False, '/etc/bcfg2.conf', False), + 'client': (('-c', '', 'hard set the client name (for debugging)'), + False, False, False, False) } - ssetup = dgetopt(sys.argv[1:], options, doptions, - descriptions, argDescriptions) + ssetup = Bcfg2.Options.OptionParser('bcfg2', optinfo).parse() if ssetup['daemon']: daemonize(ssetup['daemon']) - if not ssetup['configfile']: - ssetup['configfile'] = '/etc/bcfg2.conf' s = Bcfg2Serv(ssetup) while not s.shut: try: -- cgit v1.2.3-1-g7c22