summaryrefslogtreecommitdiffstats
path: root/src/sbin
diff options
context:
space:
mode:
Diffstat (limited to 'src/sbin')
-rwxr-xr-xsrc/sbin/bcfg2-admin4
-rwxr-xr-xsrc/sbin/bcfg2-build-reports2
-rwxr-xr-xsrc/sbin/bcfg2-crypt6
-rwxr-xr-xsrc/sbin/bcfg2-info82
-rwxr-xr-xsrc/sbin/bcfg2-lint18
-rwxr-xr-xsrc/sbin/bcfg2-report-collector10
-rwxr-xr-xsrc/sbin/bcfg2-reports3
-rwxr-xr-xsrc/sbin/bcfg2-server33
-rwxr-xr-xsrc/sbin/bcfg2-test17
-rwxr-xr-xsrc/sbin/bcfg2-yum-helper103
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())