diff options
Diffstat (limited to 'src/sbin')
-rwxr-xr-x | src/sbin/bcfg2-admin | 4 | ||||
-rwxr-xr-x | src/sbin/bcfg2-build-reports | 2 | ||||
-rwxr-xr-x | src/sbin/bcfg2-crypt | 6 | ||||
-rwxr-xr-x | src/sbin/bcfg2-info | 82 | ||||
-rwxr-xr-x | src/sbin/bcfg2-lint | 18 | ||||
-rwxr-xr-x | src/sbin/bcfg2-report-collector | 10 | ||||
-rwxr-xr-x | src/sbin/bcfg2-reports | 3 | ||||
-rwxr-xr-x | src/sbin/bcfg2-server | 33 | ||||
-rwxr-xr-x | src/sbin/bcfg2-test | 17 | ||||
-rwxr-xr-x | src/sbin/bcfg2-yum-helper | 103 |
10 files changed, 167 insertions, 111 deletions
diff --git a/src/sbin/bcfg2-admin b/src/sbin/bcfg2-admin index 31e49c00b..14d188342 100755 --- a/src/sbin/bcfg2-admin +++ b/src/sbin/bcfg2-admin @@ -83,7 +83,7 @@ def main(): raise SystemExit(1) mode = mode_cls(setup) try: - mode(setup['args'][1:]) + return mode(setup['args'][1:]) finally: mode.shutdown() else: @@ -93,6 +93,6 @@ def main(): if __name__ == '__main__': try: - main() + sys.exit(main()) except KeyboardInterrupt: raise SystemExit(1) diff --git a/src/sbin/bcfg2-build-reports b/src/sbin/bcfg2-build-reports index 27e7c2475..1c9e9ad97 100755 --- a/src/sbin/bcfg2-build-reports +++ b/src/sbin/bcfg2-build-reports @@ -13,7 +13,7 @@ import sys from time import asctime, strptime from lxml.etree import XML, XSLT, parse, Element, ElementTree, SubElement, tostring, XMLSyntaxError # Compatibility imports -from Bcfg2.Compat import ConfigParser +from Bcfg2.Compat import ConfigParser, cmp def generatereport(rspec, nrpt): """ diff --git a/src/sbin/bcfg2-crypt b/src/sbin/bcfg2-crypt index eae316da5..aad89882f 100755 --- a/src/sbin/bcfg2-crypt +++ b/src/sbin/bcfg2-crypt @@ -161,8 +161,8 @@ class Encryptor(object): continue except TypeError: pchunk = None - for pname, passphrase in \ - Bcfg2.Encryption.get_passphrases(self.setup).items(): + passphrases = Bcfg2.Encryption.get_passphrases(self.setup) + for pname, passphrase in passphrases.items(): self.logger.debug("Trying passphrase %s" % pname) try: pchunk = self._decrypt(chunk, passphrase) @@ -341,7 +341,7 @@ class PropertiesEncryptor(Encryptor): # actually need to unchunk anything xdata = data[0] # find root element - while xdata.getparent() != None: + while xdata.getparent() is not None: xdata = xdata.getparent() return lxml.etree.tostring(xdata, xml_declaration=False, diff --git a/src/sbin/bcfg2-info b/src/sbin/bcfg2-info index cfcc95be2..133e1ccb3 100755 --- a/src/sbin/bcfg2-info +++ b/src/sbin/bcfg2-info @@ -120,7 +120,6 @@ class InfoCore(cmd.Cmd, Bcfg2.Server.Core.BaseCore): Bcfg2.Server.Core.BaseCore.__init__(self, setup=setup) self.prompt = '> ' self.cont = True - self.fam.handle_events_in_interval(4) def _get_client_list(self, hostglobs): """ given a host glob, get a list of clients that match it """ @@ -232,10 +231,14 @@ class InfoCore(cmd.Cmd, Bcfg2.Server.Core.BaseCore): print("Refusing to write files outside of /tmp without -f " "option") return - lxml.etree.ElementTree(self.BuildConfiguration(client)).write( - ofile, - encoding='UTF-8', xml_declaration=True, - pretty_print=True) + try: + lxml.etree.ElementTree(self.BuildConfiguration(client)).write( + ofile, + encoding='UTF-8', xml_declaration=True, + pretty_print=True) + except IOError: + err = sys.exc_info()[1] + print("Failed to write File %s: %s" % (ofile, err)) else: print(self._get_usage(self.do_build)) @@ -380,7 +383,7 @@ Bcfg2 client itself.""") xml_declaration=False).decode('UTF-8') except Exception: print("Failed to build entry %s for host %s: %s" % - (fname, client, traceback.format_exc().splitlines()[-1])) + (fname, client, traceback.format_exc().splitlines()[-1])) raise try: if outfile: @@ -458,9 +461,7 @@ Bcfg2 client itself.""") def do_clients(self, _): """ clients - Print out client/profile info """ data = [('Client', 'Profile')] - clist = self.metadata.clients - clist.sort() - for client in clist: + for client in sorted(self.metadata.list_clients()): imd = self.metadata.get_initial_metadata(client) data.append((client, imd.profile)) print_tabular(data) @@ -468,19 +469,17 @@ Bcfg2 client itself.""") def do_config(self, _): """ config - Print out the current configuration of Bcfg2""" output = [ - ('Description', 'Value'), - ('Path Bcfg2 repository', self.setup['repo']), - ('Plugins', self.setup['plugins']), - ('Password', self.setup['password']), - ('Server Metadata Connector', self.setup['mconnect']), - ('Filemonitor', self.setup['filemonitor']), - ('Server address', self.setup['location']), - ('Path to key', self.setup['key']), - ('Path to SSL certificate', self.setup['cert']), - ('Path to SSL CA certificate', self.setup['ca']), - ('Protocol', self.setup['protocol']), - ('Logging', self.setup['logging']) - ] + ('Description', 'Value'), + ('Path Bcfg2 repository', self.setup['repo']), + ('Plugins', self.setup['plugins']), + ('Password', self.setup['password']), + ('Filemonitor', self.setup['filemonitor']), + ('Server address', self.setup['location']), + ('Path to key', self.setup['key']), + ('Path to SSL certificate', self.setup['cert']), + ('Path to SSL CA certificate', self.setup['ca']), + ('Protocol', self.setup['protocol']), + ('Logging', self.setup['logging'])] print_tabular(output) def do_probes(self, args): @@ -607,7 +606,7 @@ Bcfg2 client itself.""") # Dump all mappings unless type specified data = [('Plugin', 'Type', 'Name')] arglen = len(args.split()) - for generator in self.generators: + for generator in self.plugins_by_type(Bcfg2.Server.Plugin.Generator): if arglen == 0: etypes = list(generator.Entries.keys()) else: @@ -631,30 +630,34 @@ Bcfg2 client itself.""") self.fam.debug = True def do_packageresolve(self, args): - """ packageresolve <hostname> <package> [<package>...] - - Resolve the specified set of packages """ + """ packageresolve <hostname> [<package> [<package>...]] - + Resolve packages for the given host, optionally specifying a + set of packages """ arglist = args.split(" ") - if len(arglist) < 2: + if len(arglist) < 1: print(self._get_usage(self.do_packageresolve)) return - if 'Packages' not in self.plugins: + try: + pkgs = self.plugins['Packages'] + except KeyError: print("Packages plugin not enabled") return - self.plugins['Packages'].toggle_debug() - - indep = lxml.etree.Element("Independent") - structures = [lxml.etree.Element("Bundle", name="packages")] - for arg in arglist[1:]: - lxml.etree.SubElement(structures[0], "Package", name=arg) + pkgs.toggle_debug() hostname = arglist[0] metadata = self.build_metadata(hostname) - # pylint: disable=W0212 - self.plugins['Packages']._build_packages(metadata, indep, structures) - # pylint: enable=W0212 + indep = lxml.etree.Element("Independent") + if len(arglist) > 1: + structures = [lxml.etree.Element("Bundle", name="packages")] + for arg in arglist[1:]: + lxml.etree.SubElement(structures[0], "Package", name=arg) + else: + structures = self.GetStructures(metadata) + pkgs._build_packages(metadata, indep, # pylint: disable=W0212 + structures) print("%d new packages added" % len(indep.getchildren())) if len(indep.getchildren()): print(" %s" % "\n ".join(lxml.etree.tostring(p) @@ -713,6 +716,8 @@ Bcfg2 client itself.""") def run(self, args): # pylint: disable=W0221 try: + self.load_plugins() + self.fam.handle_events_in_interval(1) if args: self.onecmd(" ".join(args)) else: @@ -739,7 +744,7 @@ def build_usage(): # shim for python 2.4, __func__ is im_func funcattr = getattr(attr, "__func__", getattr(attr, "im_func", None)) - if (funcattr != None and + if (funcattr is not None and funcattr.func_name not in cmd_blacklist and funcattr.func_name.startswith("do_") and funcattr.func_doc): @@ -754,8 +759,7 @@ def main(): optinfo = dict(profile=Bcfg2.Options.CORE_PROFILE, interactive=Bcfg2.Options.INTERACTIVE, interpreter=Bcfg2.Options.INTERPRETER) - optinfo.update(Bcfg2.Options.CLI_COMMON_OPTIONS) - optinfo.update(Bcfg2.Options.SERVER_COMMON_OPTIONS) + optinfo.update(Bcfg2.Options.INFO_COMMON_OPTIONS) setup = Bcfg2.Options.OptionParser(optinfo) setup.hm = "\n".join([" bcfg2-info [options] [command <command args>]", "Options:", diff --git a/src/sbin/bcfg2-lint b/src/sbin/bcfg2-lint index 430c4c54f..ab3b6450f 100755 --- a/src/sbin/bcfg2-lint +++ b/src/sbin/bcfg2-lint @@ -3,6 +3,7 @@ """This tool examines your Bcfg2 specifications for errors.""" import sys +import time import inspect import logging import Bcfg2.Logger @@ -52,22 +53,27 @@ def run_plugin(plugin, plugin_name, setup=None, errorhandler=None, args.append(setup) # python 2.5 doesn't support mixing *magic and keyword arguments - return plugin(*args, **dict(files=files, errorhandler=errorhandler)).Run() + start = time.time() + rv = plugin(*args, **dict(files=files, errorhandler=errorhandler)).Run() + LOGGER.debug(" Ran %s in %0.2f seconds" % (plugin_name, + time.time() - start)) + return rv def get_errorhandler(setup): """ get a Bcfg2.Server.Lint.ErrorHandler object """ if setup.cfp.has_section("errors"): - conf = dict(setup.cfp.items("errors")) + errors = dict(setup.cfp.items("errors")) else: - conf = None - return Bcfg2.Server.Lint.ErrorHandler(config=conf) + errors = None + return Bcfg2.Server.Lint.ErrorHandler(errors=errors) def load_server(setup): """ load server """ core = Bcfg2.Server.Core.BaseCore(setup) - core.fam.handle_events_in_interval(4) + core.load_plugins() + core.fam.handle_events_in_interval(0.1) return core @@ -92,7 +98,7 @@ def load_plugins(setup): elif setup['lint_plugins']: plugin_list = setup['lint_plugins'] else: - plugin_list = Bcfg2.Server.Lint.__all__ + plugin_list = Bcfg2.Server.Lint.plugins allplugins = dict() for plugin in plugin_list: diff --git a/src/sbin/bcfg2-report-collector b/src/sbin/bcfg2-report-collector index a0ee2259a..594be13bf 100755 --- a/src/sbin/bcfg2-report-collector +++ b/src/sbin/bcfg2-report-collector @@ -12,12 +12,10 @@ from Bcfg2.Reporting.Collector import ReportingCollector, ReportingError def main(): logger = logging.getLogger('bcfg2-report-collector') - optinfo = dict( - daemon=Bcfg2.Options.DAEMON, - repo=Bcfg2.Options.SERVER_REPOSITORY, - filemonitor=Bcfg2.Options.SERVER_FILEMONITOR, - web_configfile=Bcfg2.Options.WEB_CFILE, - ) + optinfo = dict(daemon=Bcfg2.Options.DAEMON, + repo=Bcfg2.Options.SERVER_REPOSITORY, + filemonitor=Bcfg2.Options.SERVER_FILEMONITOR, + web_configfile=Bcfg2.Options.WEB_CFILE) optinfo.update(Bcfg2.Options.CLI_COMMON_OPTIONS) optinfo.update(Bcfg2.Options.REPORTING_COMMON_OPTIONS) setup = Bcfg2.Options.OptionParser(optinfo) diff --git a/src/sbin/bcfg2-reports b/src/sbin/bcfg2-reports index 2c4a918be..bb45e0009 100755 --- a/src/sbin/bcfg2-reports +++ b/src/sbin/bcfg2-reports @@ -233,7 +233,8 @@ def main(): try: entries = [l.strip().split(":") for l in open(options.file)] - except IOError, err: + except IOError: + err = sys.exc_info()[1] print("Cannot read entries from %s: %s" % (options.file, err)) return 2 diff --git a/src/sbin/bcfg2-server b/src/sbin/bcfg2-server index cdca71e74..4c4a71fa7 100755 --- a/src/sbin/bcfg2-server +++ b/src/sbin/bcfg2-server @@ -24,21 +24,32 @@ def main(): print("Could not read %s" % setup['configfile']) sys.exit(1) - if setup['backend'] not in ['best', 'cherrypy', 'builtin']: + # TODO: normalize case of various core modules so we can add a new + # core without modifying this script + backends = dict(cherrypy='CherryPyCore', + builtin='BuiltinCore', + best='BuiltinCore', + multiprocessing='MultiprocessingCore') + + if setup['backend'] not in backends: print("Unknown server backend %s, using 'best'" % setup['backend']) setup['backend'] = 'best' - if setup['backend'] == 'cherrypy': - try: - from Bcfg2.Server.CherryPyCore import Core - except ImportError: - err = sys.exc_info()[1] - print("Unable to import CherryPy server core: %s" % err) - raise - elif setup['backend'] == 'builtin' or setup['backend'] == 'best': - from Bcfg2.Server.BuiltinCore import Core + + coremodule = backends[setup['backend']] + try: + corecls = getattr(__import__("Bcfg2.Server.%s" % coremodule).Server, + coremodule).Core + except ImportError: + err = sys.exc_info()[1] + print("Unable to import %s server core: %s" % (setup['backend'], err)) + raise + except AttributeError: + err = sys.exc_info()[1] + print("Unable to load %s server core: %s" % (setup['backend'], err)) + raise try: - core = Core(setup) + core = corecls(setup) core.run() except CoreInitError: msg = sys.exc_info()[1] diff --git a/src/sbin/bcfg2-test b/src/sbin/bcfg2-test index 6eaf0cc33..d7a1894f0 100755 --- a/src/sbin/bcfg2-test +++ b/src/sbin/bcfg2-test @@ -5,6 +5,7 @@ without failures""" import os import sys +import signal import fnmatch import logging import Bcfg2.Logger @@ -155,6 +156,7 @@ class ClientTest(TestCase): def get_core(setup): """ Get a server core, with events handled """ core = Bcfg2.Server.Core.BaseCore(setup) + core.load_plugins() core.fam.handle_events_in_interval(0.1) return core @@ -189,9 +191,23 @@ def run_child(setup, clients, queue): core.shutdown() +def get_sigint_handler(core): + """ Get a function that handles SIGINT/Ctrl-C by shutting down the + core and exiting properly.""" + + def hdlr(sig, frame): # pylint: disable=W0613 + """ Handle SIGINT/Ctrl-C by shutting down the core and exiting + properly. """ + core.shutdown() + os._exit(1) # pylint: disable=W0212 + + return hdlr + + def parse_args(): """ Parse command line arguments. """ optinfo = dict(Bcfg2.Options.TEST_COMMON_OPTIONS) + optinfo.update(Bcfg2.Options.CLI_COMMON_OPTIONS) optinfo.update(Bcfg2.Options.SERVER_COMMON_OPTIONS) setup = Bcfg2.Options.OptionParser(optinfo) @@ -245,6 +261,7 @@ def main(): setup = parse_args() logger = logging.getLogger(sys.argv[0]) core = get_core(setup) + signal.signal(signal.SIGINT, get_sigint_handler(core)) if setup['args']: clients = setup['args'] diff --git a/src/sbin/bcfg2-yum-helper b/src/sbin/bcfg2-yum-helper index 7e5c03fd5..4ef531d39 100755 --- a/src/sbin/bcfg2-yum-helper +++ b/src/sbin/bcfg2-yum-helper @@ -9,33 +9,13 @@ import os import sys import yum import logging +import Bcfg2.Logger from optparse import OptionParser try: import json except ImportError: import simplejson as json -LOGGER = None - - -def get_logger(verbose=0): - """ set up logging according to the verbose level given on the - command line """ - global LOGGER - if LOGGER is None: - LOGGER = logging.getLogger(sys.argv[0]) - stderr = logging.StreamHandler() - if verbose: - level = logging.DEBUG - else: - level = logging.WARNING - LOGGER.setLevel(level) - LOGGER.addHandler(stderr) - syslog = logging.handlers.SysLogHandler("/dev/log") - syslog.setFormatter(logging.Formatter("%(name)s: %(message)s")) - LOGGER.addHandler(syslog) - return LOGGER - def pkg_to_tuple(package): """ json doesn't distinguish between tuples and lists, but yum @@ -76,7 +56,7 @@ class DepSolver(object): except AttributeError: self.yumbase._getConfig(cfgfile, debuglevel=verbose) # pylint: enable=E1121,W0212 - self.logger = get_logger(verbose) + self.logger = logging.getLogger(self.__class__.__name__) self._groups = None def get_groups(self): @@ -220,7 +200,17 @@ def main(): parser.add_option("-v", "--verbose", help="Verbosity level", action="count") (options, args) = parser.parse_args() - logger = get_logger(options.verbose) + + if options.verbose: + level = logging.DEBUG + clevel = logging.DEBUG + else: + level = logging.WARNING + clevel = logging.INFO + Bcfg2.Logger.setup_logging('bcfg2-yum-helper', to_syslog=True, + to_console=clevel, level=level) + logger = logging.getLogger('bcfg2-yum-helper') + try: cmd = args[0] except IndexError: @@ -231,29 +221,58 @@ def main(): logger.error("Config file %s not found" % options.config) return 1 + # pylint: disable=W0702 + rv = 0 depsolver = DepSolver(options.config, options.verbose) if cmd == "clean": - depsolver.clean_cache() - print(json.dumps(True)) + try: + depsolver.clean_cache() + print(json.dumps(True)) + except: + logger.error("Unexpected error cleaning cache: %s" % + sys.exc_info()[1], exc_info=1) + print(json.dumps(False)) + rv = 2 elif cmd == "complete": - data = json.loads(sys.stdin.read()) - depsolver.groups = data['groups'] - (packages, unknown) = depsolver.complete([pkg_to_tuple(p) - for p in data['packages']]) - print(json.dumps(dict(packages=list(packages), - unknown=list(unknown)))) + try: + data = json.loads(sys.stdin.read()) + except: + logger.error("Unexpected error decoding JSON input: %s" % + sys.exc_info()[1]) + rv = 2 + try: + depsolver.groups = data['groups'] + (packages, unknown) = depsolver.complete( + [pkg_to_tuple(p) for p in data['packages']]) + print(json.dumps(dict(packages=list(packages), + unknown=list(unknown)))) + except: + logger.error("Unexpected error completing package set: %s" % + sys.exc_info()[1], exc_info=1) + print(json.dumps(dict(packages=[], unknown=data['packages']))) + rv = 2 elif cmd == "get_groups": - data = json.loads(sys.stdin.read()) - rv = dict() - for gdata in data: - if "type" in gdata: - packages = depsolver.get_group(gdata['group'], - ptype=gdata['type']) - else: - packages = depsolver.get_group(gdata['group']) - rv[gdata['group']] = list(packages) - print(json.dumps(rv)) - + try: + data = json.loads(sys.stdin.read()) + rv = dict() + for gdata in data: + if "type" in gdata: + packages = depsolver.get_group(gdata['group'], + ptype=gdata['type']) + else: + packages = depsolver.get_group(gdata['group']) + rv[gdata['group']] = list(packages) + print(json.dumps(rv)) + except: + logger.error("Unexpected error getting groups: %s" % + sys.exc_info()[1], exc_info=1) + print(json.dumps(dict())) + rv = 2 + else: + logger.error("Unknown command %s" % cmd) + print(json.dumps(None)) + rv = 2 + return rv if __name__ == '__main__': sys.exit(main()) |