diff options
author | Jack Neely <jjneely@ncsu.edu> | 2011-06-10 13:29:23 -0400 |
---|---|---|
committer | Jack Neely <jjneely@ncsu.edu> | 2011-06-10 13:29:23 -0400 |
commit | 90c85147bacea14771abf8faa1fc5f185418d14b (patch) | |
tree | b10e06fc80ed714f5376b169e32b8953479211f1 /src/sbin | |
parent | 4f3da4543ec4e8c3c4776ae2ee3611e47ce78525 (diff) | |
parent | ce6a228d33ace4136dc2b5388c64795dfbd26ffb (diff) | |
download | bcfg2-90c85147bacea14771abf8faa1fc5f185418d14b.tar.gz bcfg2-90c85147bacea14771abf8faa1fc5f185418d14b.tar.bz2 bcfg2-90c85147bacea14771abf8faa1fc5f185418d14b.zip |
Merge branch 'master' of github.com:solj/bcfg2
Diffstat (limited to 'src/sbin')
-rwxr-xr-x | src/sbin/bcfg2 | 43 | ||||
-rwxr-xr-x | src/sbin/bcfg2-admin | 10 | ||||
-rwxr-xr-x | src/sbin/bcfg2-build-reports | 62 | ||||
-rwxr-xr-x | src/sbin/bcfg2-info | 113 | ||||
-rwxr-xr-x | src/sbin/bcfg2-lint | 209 | ||||
-rwxr-xr-x | src/sbin/bcfg2-ping-sweep | 2 | ||||
l---------[-rwxr-xr-x] | src/sbin/bcfg2-repo-validate | 228 | ||||
-rwxr-xr-x | src/sbin/bcfg2-reports | 161 | ||||
-rwxr-xr-x | src/sbin/bcfg2-server | 5 |
9 files changed, 464 insertions, 369 deletions
diff --git a/src/sbin/bcfg2 b/src/sbin/bcfg2 index 9bc50fe65..534ab8238 100755 --- a/src/sbin/bcfg2 +++ b/src/sbin/bcfg2 @@ -3,18 +3,20 @@ """Bcfg2 Client""" __revision__ = '$Revision$' +import fcntl import logging import os import signal +import stat import sys import tempfile import time -import xmlrpclib -import fcntl import Bcfg2.Options import Bcfg2.Client.XML import Bcfg2.Client.Frame import Bcfg2.Client.Tools +# Compatibility imports +from Bcfg2.Bcfg2Py3k import xmlrpclib import Bcfg2.Proxy import Bcfg2.Logger @@ -73,6 +75,7 @@ class Client: 'certificate': Bcfg2.Options.CLIENT_CERT, 'ca': Bcfg2.Options.CLIENT_CA, 'serverCN': Bcfg2.Options.CLIENT_SCNS, + 'timeout': Bcfg2.Options.CLIENT_TIMEOUT, } self.setup = Bcfg2.Options.OptionParser(optinfo) @@ -106,7 +109,12 @@ class Client: raise SystemExit(0) if self.setup['remove'] and 'services' in self.setup['remove']: self.logger.error("Service removal is nonsensical, disable services to get former behavior") - if self.setup['remove'] not in [False, 'all', 'services', 'packages']: + if self.setup['remove'] not in [False, + 'all', + 'Services', + 'Packages', + '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") @@ -130,7 +138,9 @@ class Client: script.write(probe.text) script.close() os.close(scripthandle) - os.chmod(script.name, 0755) + os.chmod(script.name, stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH | + stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH | + stat.S_IWUSR) # 0755 ret.text = os.popen(script.name).read().strip() self.logger.info("Probe %s has result:\n%s" % (name, ret.text)) finally: @@ -169,10 +179,11 @@ class Client: proxy = Bcfg2.Proxy.ComponentProxy(self.setup['server'], self.setup['user'], self.setup['password'], - key = self.setup['key'], - cert = self.setup['certificate'], - ca = self.setup['ca'], - allowedServerCNs = self.setup['serverCN']) + key=self.setup['key'], + cert=self.setup['certificate'], + ca=self.setup['ca'], + allowedServerCNs=self.setup['serverCN'], + timeout=self.setup['timeout']) if self.setup['profile']: try: @@ -183,7 +194,8 @@ class Client: try: probe_data = proxy.GetProbes() - except xmlrpclib.Fault, flt: + except xmlrpclib.Fault: + flt = sys.exc_info()[1] self.logger.error("Failed to download probes from bcfg2") self.logger.error(flt.faultString) raise SystemExit(1) @@ -192,7 +204,8 @@ class Client: try: probes = Bcfg2.Client.XML.XML(probe_data) - except Bcfg2.Client.XML.ParseError, syntax_error: + except Bcfg2.Client.XML.ParseError: + syntax_error = sys.exc_info()[1] self.fatal_error( "Server returned invalid probe requests: %s" % (syntax_error)) @@ -223,7 +236,8 @@ class Client: self.setup['decision']) self.logger.info("Got decision list from server:") self.logger.info(self.setup['decision_list']) - except xmlrpclib.Fault, f: + except xmlrpclib.Fault: + f = sys.exc_info()[1] if f.faultCode == 1: print("GetDecisionList method not supported by server") else: @@ -231,7 +245,7 @@ class Client: raise SystemExit(1) try: - rawconfig = proxy.GetConfig() + rawconfig = proxy.GetConfig().encode('UTF-8') except xmlrpclib.Fault: self.logger.error("Failed to download configuration from Bcfg2") raise SystemExit(2) @@ -240,7 +254,7 @@ class Client: if self.setup['cache']: try: - open(self.setup['cache'], 'w').write(rawconfig.encode(self.setup['encoding'])) + open(self.setup['cache'], 'w').write(rawconfig) os.chmod(self.setup['cache'], 33152) except IOError: self.logger.warning("Failed to write config cache file %s" % @@ -249,7 +263,8 @@ class Client: try: self.config = Bcfg2.Client.XML.XML(rawconfig) - except Bcfg2.Client.XML.ParseError, syntax_error: + except Bcfg2.Client.XML.ParseError: + syntax_error = sys.exc_info()[1] self.fatal_error("The configuration could not be parsed: %s" % (syntax_error)) return(1) diff --git a/src/sbin/bcfg2-admin b/src/sbin/bcfg2-admin index 2c9a43859..36be6ab14 100755 --- a/src/sbin/bcfg2-admin +++ b/src/sbin/bcfg2-admin @@ -2,11 +2,12 @@ """bcfg2-admin is a script that helps to administrate a Bcfg2 deployment.""" from optparse import OptionParser -from StringIO import StringIO import logging import Bcfg2.Server.Core import Bcfg2.Logger import Bcfg2.Options +# Compatibility import +from Bcfg2.Bcfg2Py3k import StringIO log = logging.getLogger('bcfg2-admin') @@ -56,14 +57,15 @@ def main(): else: # Print short help for all modes parser.print_help() - print create_description() + print(create_description()) raise SystemExit(0) if args[0] in get_modes(): modname = args[0].capitalize() try: mode_cls = mode_import(modname) - except ImportError, e: + except ImportError: + e = sys.exc_info()[1] log.error("Failed to load admin mode %s: %s" % (modname, e)) raise SystemExit(1) mode = mode_cls(options.configfile) @@ -73,7 +75,7 @@ def main(): else: log.error("Unknown mode %s" % args[0]) parser.print_help() - print create_description() + print(create_description()) raise SystemExit(1) if __name__ == '__main__': diff --git a/src/sbin/bcfg2-build-reports b/src/sbin/bcfg2-build-reports index 231f52105..7122fb300 100755 --- a/src/sbin/bcfg2-build-reports +++ b/src/sbin/bcfg2-build-reports @@ -13,8 +13,9 @@ import os import socket import sys from time import asctime, strptime -from ConfigParser import ConfigParser, NoSectionError, NoOptionError from lxml.etree import XML, XSLT, parse, Element, ElementTree, SubElement, tostring, XMLSyntaxError +# Compatibility imports +from Bcfg2.Bcfg2Py3k import ConfigParser def generatereport(rspec, nrpt): """ @@ -42,9 +43,9 @@ def generatereport(rspec, nrpt): # This line actually sorts from most recent to oldest. statisticslist.sort(lambda y, x: cmp(strptime(x.get("time")), strptime(y.get("time")))) stats = statisticslist[0] - + [node.remove(item) for item in node.findall('Statistics')] - + # Add a good tag if node is good and we wnat to report such. if reportgood == 'Y' and stats.get('state') == 'clean': SubElement(stats,"Good") @@ -52,7 +53,7 @@ def generatereport(rspec, nrpt): [stats.remove(item) for item in stats.findall("Bad") + stats.findall("Modified") if \ item.getchildren() == []] [stats.remove(item) for item in stats.findall("Modified") if reportmodified == 'N'] - + # Test for staleness -if stale add Stale tag. if stats.get("time").find(current_date) == -1: SubElement(stats,"Stale") @@ -64,7 +65,7 @@ def mail(mailbody, confi): try: mailer = confi.get('statistics', 'sendmailpath') - except (NoSectionError, NoOptionError): + except (ConfigParser.NoSectionError, ConfigParser.NoOptionError): mailer = "/usr/sbin/sendmail" # Open a pipe to the mail program and # write the data to the pipe. @@ -72,7 +73,7 @@ def mail(mailbody, confi): pipe.write(mailbody) exitcode = pipe.close() if exitcode: - print "Exit code: %s" % exitcode + print("Exit code: %s" % exitcode) def rss(reportxml, delivery, report): """rss appends a new report to the specified rss file @@ -98,7 +99,7 @@ def rss(reportxml, delivery, report): chantitle = SubElement(channel, "title") chantitle.text = report.attrib['name'] chanlink = SubElement(channel, "link") - + # This can later link to WWW report if one gets published # simultaneously? chanlink.text = "http://www.mcs.anl.gov/cobalt/bcfg2" @@ -119,7 +120,7 @@ def www(reportxml, delivery): """www outputs report to.""" # This can later link to WWW report if one gets published - # simultaneously? + # simultaneously? for destination in delivery.findall('Destination'): fil = open(destination.attrib['address'], 'w') @@ -138,15 +139,15 @@ def pretty_print(element, level=0): """Produce a pretty-printed text representation of element.""" if element.text: fmt = "%s<%%s %%s>%%s</%%s>" % (level*" ") - data = (element.tag, (" ".join(["%s='%s'" % keyval for keyval in element.attrib.iteritems()])), + data = (element.tag, (" ".join(["%s='%s'" % keyval for keyval in list(element.attrib.items())])), element.text, element.tag) if element._children: fmt = "%s<%%s %%s>\n" % (level*" ",) + (len(element._children) * "%s") + "%s</%%s>\n" % (level*" ") - data = (element.tag, ) + (" ".join(["%s='%s'" % keyval for keyval in element.attrib.iteritems()]),) + data = (element.tag, ) + (" ".join(["%s='%s'" % keyval for keyval in list(element.attrib.items())]),) data += tuple([pretty_print(entry, level+2) for entry in element._children]) + (element.tag, ) else: fmt = "%s<%%s %%s/>\n" % (level * " ") - data = (element.tag, " ".join(["%s='%s'" % keyval for keyval in element.attrib.iteritems()])) + data = (element.tag, " ".join(["%s='%s'" % keyval for keyval in list(element.attrib.items())])) return fmt % data @@ -157,14 +158,14 @@ if __name__ == '__main__': cfpath = sys.argv[sys.argv.index('-C') + 1] else: cfpath = '/etc/bcfg2.conf' - c = ConfigParser() + c = ConfigParser.ConfigParser() c.read([cfpath]) configpath = "%s/etc/report-configuration.xml" % c.get('server', 'repository') statpath = "%s/etc/statistics.xml" % c.get('server', 'repository') clientsdatapath = "%s/Metadata/clients.xml" % c.get('server', 'repository') try: prefix = c.get('server', 'prefix') - except (NoSectionError, NoOptionError): + except (ConfigParser.NoSectionError, ConfigParser.NoOptionError): prefix = '/usr' transformpath = "/%s/share/bcfg2/xsl-transforms/" % (prefix) @@ -172,13 +173,14 @@ if __name__ == '__main__': try: opts, args = getopt.getopt(sys.argv[1:], "C:hAc:Ns:", ["help", "all", "config=","no-ping", "stats="]) - except getopt.GetoptError, mesg: + except getopt.GetoptError: + mesg = sys.exc_info()[1] # Print help information and exit: - print "%s\nUsage:\nbcfg2-build-reports [-h][-A (include ALL clients)] [-c <configuration-file>] [-s <statistics-file>][-N (do not ping clients)]" % (mesg) - raise SystemExit, 2 + print("%s\nUsage:\nbcfg2-build-reports [-h][-A (include ALL clients)] [-c <configuration-file>] [-s <statistics-file>][-N (do not ping clients)]" % (mesg)) + raise SystemExit(2) for o, a in opts: if o in ("-h", "--help"): - print "Usage:\nbcfg2-build-reports [-h] [-c <configuration-file>] [-s <statistics-file>]" + print("Usage:\nbcfg2-build-reports [-h] [-c <configuration-file>] [-s <statistics-file>]") raise SystemExit if o in ("-A", "--all"): all=True @@ -205,17 +207,17 @@ if __name__ == '__main__': statsdata = XML(open(statpath).read()) except (IOError, XMLSyntaxError): print("bcfg2-build-reports: Failed to parse %s"%(statpath)) - raise SystemExit, 1 + raise SystemExit(1) try: configdata = XML(open(configpath).read()) except (IOError, XMLSyntaxError): print("bcfg2-build-reports: Failed to parse %s"%(configpath)) - raise SystemExit, 1 + raise SystemExit(1) try: clientsdata = XML(open(clientsdatapath).read()) except (IOError, XMLSyntaxError): print("bcfg2-build-reports: Failed to parse %s"%(clientsdatapath)) - raise SystemExit, 1 + raise SystemExit(1) # Merge data from three sources. nodereport = Element("Report", attrib={"time" : asctime()}) @@ -229,7 +231,7 @@ if __name__ == '__main__': for statel in nod.findall("Statistics"): nodel.append(statel) nodereport.append(nodel) - + if all: for nod in statsdata.findall("Node"): for client in clientsdata.findall("Client"): @@ -242,8 +244,8 @@ if __name__ == '__main__': for statel in nod.findall("Statistics"): nodel.append(statel) nodereport.append(nodel) - - + + for reprt in configdata.findall('Report'): nodereport.set("name", reprt.get("name", default="BCFG Report")) @@ -254,7 +256,7 @@ if __name__ == '__main__': for deliv in reprt.findall('Delivery'): # Is a deepcopy of procnodereport necessary? - + delivtype = deliv.get('type', default='nodes-digest') deliverymechanism = deliv.get('mechanism', default='www') @@ -269,14 +271,14 @@ if __name__ == '__main__': except: print("bcfg2-build-reports: Invalid report type or delivery mechanism.\n Can't find: "\ + transformpath + transform) - raise SystemExit, 1 + raise SystemExit(1) try: # Try to parse stylesheet. stylesheet = XSLT(parse(transformpath + transform)) except: print("bcfg2-build-reports: invalid XSLT transform file.") - raise SystemExit, 1 - + raise SystemExit(1) + if deliverymechanism == 'mail': if delivtype == 'nodes-individual': reportdata = copy.deepcopy(procnodereport) @@ -285,7 +287,7 @@ if __name__ == '__main__': reportdata.append(noden) result = stylesheet.apply(ElementTree(reportdata)) outputstring = stylesheet.tostring(result) - + if not outputstring == None: toastring = '' for desti in deliv.findall("Destination"): @@ -295,13 +297,13 @@ if __name__ == '__main__': outputstring = "To: %s\nFrom: root@%s\n%s"% \ (toastring, socket.getfqdn(), outputstring) mail(outputstring, c) #call function to send - + else: reportdata = copy.deepcopy(procnodereport) result = stylesheet.apply(ElementTree(reportdata)) outputstring = stylesheet.tostring(result) - + if not outputstring == None: toastring = '' for desti in deliv.findall("Destination"): diff --git a/src/sbin/bcfg2-info b/src/sbin/bcfg2-info index a6d236bc8..c36e1af42 100755 --- a/src/sbin/bcfg2-info +++ b/src/sbin/bcfg2-info @@ -27,6 +27,40 @@ import Bcfg2.Server.Plugins.Metadata import Bcfg2.Server.Plugin logger = logging.getLogger('bcfg2-info') +USAGE = """Commands: +build <hostname> <filename> - Build config for hostname, writing to filename +builddir <hostname> <dirname> - Build config for hostname, writing separate files to dirname +buildall <directory> - Build configs for all clients in directory +buildfile <filename> <hostname> - Build config file for hostname (not written to disk) +bundles - Print out group/bundle information +clients - Print out client/profile information +config - Print out the configuration of the Bcfg2 server +debug - Shell out to native python interpreter +event_debug - Display filesystem events as they are processed +generators - List current versions of generators +groups - List groups +help - Print this list of available commands +mappings <type*> <name*> - Print generator mappings for optional type and name +profile <command> <args> - Profile a single bcfg2-info command +quit - Exit the bcfg2-info command line +showentries <hostname> <type> - Show abstract configuration entries for a given host +showclient <client1> <client2> - Show metadata for given hosts +update - Process pending file events +version - Print version of this tool""" + +BUILDDIR_USAGE = """Usage: builddir [-f] <hostname> <output dir> + +Generates a config for client <hostname> and writes the +individual configuration files out separately in a tree +under <output dir>. The <output dir> directory must be +rooted under /tmp unless the -f argument is provided, in +which case it can be located anywhere. + +NOTE: Currently only handles file entries and writes +all content with the default owner and permissions. These +could be much more permissive than would be created by the +Bcfg2 client itself.""" + class mockLog(object): def error(self, *args, **kwargs): @@ -75,7 +109,8 @@ class infoCore(cmd.Cmd, Bcfg2.Server.Core.Core): encoding) if event_debug: self.fam.debug = True - except Bcfg2.Server.Core.CoreInitError, msg: + except Bcfg2.Server.Core.CoreInitError: + msg = sys.exc_info()[1] print("Core load failed because %s" % msg) raise SystemExit(1) self.prompt = '> ' @@ -89,7 +124,7 @@ class infoCore(cmd.Cmd, Bcfg2.Server.Core.Core): try: self.cmdloop('Welcome to bcfg2-info\n' 'Type "help" for more information') - except SystemExit, val: + except SystemExit: raise except Bcfg2.Server.Plugin.PluginExecutionError: continue @@ -106,7 +141,7 @@ class infoCore(cmd.Cmd, Bcfg2.Server.Core.Core): try: opts, _ = getopt.getopt(args.split(), 'nf:') except: - print "Usage: debug [-n] [-f <command list>]" + print("Usage: debug [-n] [-f <command list>]") return self.cont = False scriptmode = False @@ -136,7 +171,7 @@ class infoCore(cmd.Cmd, Bcfg2.Server.Core.Core): Exit program. Usage: [quit|exit] """ - for plugin in self.plugins.values(): + for plugin in list(self.plugins.values()): plugin.shutdown() os._exit(0) @@ -145,27 +180,7 @@ class infoCore(cmd.Cmd, Bcfg2.Server.Core.Core): def do_help(self, _): """Print out usage info.""" - print 'Commands:' - print 'build <hostname> <filename> - Build config for hostname, writing to filename' - print 'builddir <hostname> <dirname> - Build config for hostname, writing separate files to dirname' - print 'buildall <directory> - Build configs for all clients in directory' - print 'buildfile <filename> <hostname> - Build config file for hostname (not written to disk)' - print 'bundles - Print out group/bundle information' - print 'clients - Print out client/profile information' - print 'config - Print out the configuration of the Bcfg2 server' - print 'debug - Shell out to native python interpreter' - print 'event_debug - Display filesystem events as they are processed' - print 'generators - List current versions of generators' - print 'groups - List groups' - print 'help - Print this list of available commands' - print 'mappings <type*> <name*> - Print generator mappings for optional type and name' - print 'profile <command> <args> - Profile a single bcfg2-info command' - print 'quit - Exit the bcfg2-info command line' - print 'showentries <hostname> <type> - Show abstract configuration entries for a given host' - print 'showclient <client1> <client2> - Show metadata for given hosts' - print 'update - Process pending file events' - print 'version - Print version of this tool' - + print(USAGE) def do_update(self, _): """Process pending filesystem events.""" @@ -198,18 +213,7 @@ class infoCore(cmd.Cmd, Bcfg2.Server.Core.Core): def help_builddir(self): """Display help for builddir command.""" - print('Usage: builddir [-f] <hostname> <output dir>') - print('') - print('Generates a config for client <hostname> and writes the') - print('individual configuration files out separately in a tree') - print('under <output dir>. The <output dir> directory must be') - print('rooted under /tmp unless the -f argument is provided, in') - print('which case it can be located anywhere.') - print('') - print('NOTE: Currently only handles file entries and writes') - print('all content with the default owner and permissions. These') - print('could be much more permissive than would be created by the') - print('Bcfg2 client itself.') + print(BUILDDIR_USAGE) def do_builddir(self, args): """Build client configuration as separate files within a dir.""" @@ -238,7 +242,7 @@ class infoCore(cmd.Cmd, Bcfg2.Server.Core.Core): p = Bcfg2.Client.Tools.POSIX.POSIX(log, setup, client_config) states = dict() p.Inventory(states) - p.Install(states.keys(), states) + p.Install(list(states.keys()), states) else: print('Error: Incorrect number of parameters.') self.help_builddir() @@ -262,7 +266,7 @@ class infoCore(cmd.Cmd, Bcfg2.Server.Core.Core): try: metadata = self.build_metadata(client) self.Bind(entry, metadata) - print(lxml.etree.tostring(entry, encoding="UTF-8", + print(lxml.etree.tostring(entry, encoding="UTF-8", xml_declaration=True)) except: print("Failed to build entry %s for host %s" % (fname, client)) @@ -371,22 +375,22 @@ class infoCore(cmd.Cmd, Bcfg2.Server.Core.Core): except: print("Client %s not defined" % client) continue - print "Hostname:\t", client_meta.hostname - print "Profile:\t", client_meta.profile - print "Groups:\t\t", list(client_meta.groups)[0] + print("Hostname:\t", client_meta.hostname) + print("Profile:\t", client_meta.profile) + print("Groups:\t\t", list(client_meta.groups)[0]) for grp in list(client_meta.groups)[1:]: - print '\t\t%s' % grp + print('\t\t%s' % grp) if client_meta.bundles: - print "Bundles:\t", list(client_meta.bundles)[0] + print("Bundles:\t", list(client_meta.bundles)[0]) for bnd in list(client_meta.bundles)[1:]: - print '\t\t%s' % bnd + print('\t\t%s' % bnd) if client_meta.connectors: - print "Connector data" - print "=" * 80 + print("Connector data") + print("=" * 80) for conn in client_meta.connectors: if getattr(client_meta, conn): - print "%s:\t" % (conn), getattr(client_meta, conn) - print "=" * 80 + print("%s:\t" % (conn), getattr(client_meta, conn)) + print("=" * 80) def do_mappings(self, args): """Print out mapping info.""" @@ -402,11 +406,11 @@ class infoCore(cmd.Cmd, Bcfg2.Server.Core.Core): interested = [(etype, [args.split()[1]]) for etype in etypes] else: - interested = [(etype, generator.Entries[etype]) - for etype in etypes + interested = [(etype, generator.Entries[etype]) + for etype in etypes if etype in generator.Entries] for etype, names in interested: - for name in [name for name in names if name in + for name in [name for name in names if name in generator.Entries.get(etype, {})]: data.append((generator.name, etype, name)) printTabular(data) @@ -483,7 +487,10 @@ if __name__ == '__main__': }) setup = Bcfg2.Options.OptionParser(optinfo) setup.parse(sys.argv[1:]) - if setup['profile'] and have_profile: + if setup['args'] and setup['args'][0] == 'help': + print(USAGE) + sys.exit(0) + elif setup['profile'] and have_profile: prof = profile.Profile() loop = prof.runcall(infoCore, setup['repo'], setup['plugins'], setup['password'], setup['encoding'], diff --git a/src/sbin/bcfg2-lint b/src/sbin/bcfg2-lint new file mode 100755 index 000000000..464e839e5 --- /dev/null +++ b/src/sbin/bcfg2-lint @@ -0,0 +1,209 @@ +#!/usr/bin/env python + +"""This tool examines your Bcfg2 specifications for errors.""" +__revision__ = '$Revision$' + +import sys +import inspect +import logging +import Bcfg2.Logger +import Bcfg2.Options +import Bcfg2.Server.Core +import Bcfg2.Server.Lint +# Compatibility imports +from Bcfg2.Bcfg2Py3k import ConfigParser + +logger = logging.getLogger('bcfg2-lint') + +class Parser(ConfigParser.ConfigParser): + def get(self, section, option, default): + """ Override ConfigParser.get: If the request option is not in + the config file then return the value of default rather than + raise an exception. We still raise exceptions on missing + sections. + """ + try: + return ConfigParser.ConfigParser.get(self, section, option) + except (ConfigParser.NoOptionError, ConfigParser.NoSectionError): + return default + +def run_serverless_plugins(plugins, config=None, setup=None, errorhandler=None): + logger.debug("Running serverless plugins") + for plugin_name, plugin in list(plugins.items()): + run_plugin(plugin, plugin_name, errorhandler=errorhandler, + setup=setup, config=config, files=files) + +def run_server_plugins(plugins, config=None, setup=None, errorhandler=None): + core = load_server(setup) + logger.debug("Running server plugins") + for plugin_name, plugin in list(plugins.items()): + run_plugin(plugin, plugin_name, args=[core], errorhandler=errorhandler, + setup=setup, config=config, files=files) + +def run_plugin(plugin, plugin_name, setup=None, errorhandler=None, + args=None, config=None, files=None): + logger.debug(" Running %s" % plugin_name) + if args is None: + args = [] + + if errorhandler is None: + errorhandler = get_errorhandler(config) + + if config is not None and config.has_section(plugin_name): + arg = setup + for key, val in config.items(plugin_name): + arg[key] = val + args.append(arg) + else: + args.append(setup) + + # older versions of python do not support mixing *-magic and + # non-*-magic (e.g., "plugin(*args, files=files)", so we do this + # all with *-magic + kwargs = dict(files=files, errorhandler=errorhandler) + + return plugin(*args, **kwargs).Run() + +def get_errorhandler(config): + """ get a Bcfg2.Server.Lint.ErrorHandler object """ + if config.has_section("errors"): + conf = dict(config.items("errors")) + else: + conf = None + return Bcfg2.Server.Lint.ErrorHandler(config=conf) + +def load_server(setup): + """ load server """ + core = Bcfg2.Server.Core.Core(setup['repo'], setup['plugins'], + setup['password'], setup['encoding']) + if setup['event debug']: + core.fam.debug = True + core.fam.handle_events_in_interval(4) + return core + +if __name__ == '__main__': + optinfo = { + 'configfile': Bcfg2.Options.CFILE, + 'help': Bcfg2.Options.HELP, + 'verbose': Bcfg2.Options.VERBOSE, + } + optinfo.update({ + 'event debug': Bcfg2.Options.DEBUG, + 'encoding': Bcfg2.Options.ENCODING, + # Server options + 'repo': Bcfg2.Options.SERVER_REPOSITORY, + 'plugins': Bcfg2.Options.SERVER_PLUGINS, + 'mconnect': Bcfg2.Options.SERVER_MCONNECT, + 'filemonitor': Bcfg2.Options.SERVER_FILEMONITOR, + 'location': Bcfg2.Options.SERVER_LOCATION, + 'static': Bcfg2.Options.SERVER_STATIC, + 'key': Bcfg2.Options.SERVER_KEY, + 'cert': Bcfg2.Options.SERVER_CERT, + 'ca': Bcfg2.Options.SERVER_CA, + 'password': Bcfg2.Options.SERVER_PASSWORD, + 'protocol': Bcfg2.Options.SERVER_PROTOCOL, + # More options + 'logging': Bcfg2.Options.LOGGING_FILE_PATH, + 'stdin': Bcfg2.Options.FILES_ON_STDIN, + 'schema': Bcfg2.Options.SCHEMA_PATH, + 'config': Bcfg2.Options.Option('Specify bcfg2-lint configuration file', + '/etc/bcfg2-lint.conf', + cmd='--lint-config', + odesc='<conffile>', + long_arg=True), + 'showerrors': Bcfg2.Options.Option('Show error handling', False, + cmd='--list-errors', + long_arg=True), + }) + setup = Bcfg2.Options.OptionParser(optinfo) + setup.parse(sys.argv[1:]) + + log_args = dict(to_syslog=False, to_console=logging.WARNING) + if setup['verbose']: + log_args['to_console'] = logging.DEBUG + Bcfg2.Logger.setup_logging('bcfg2-info', **log_args) + + config = Parser() + config.read(setup['config']) + + if setup['showerrors']: + if config.has_section("errors"): + econf = dict(config.items("errors")) + else: + econf = dict() + + print("%-35s %-35s" % ("Error name", "Handler (Default)")) + for err, default in Bcfg2.Server.Lint.ErrorHandler._errors.items(): + if err in econf and econf[err] != default: + handler = "%s (%s)" % (econf[err], default) + else: + handler = default + print("%-35s %-35s" % (err, handler)) + raise SystemExit(0) + + # get list of plugins to run + if setup['args']: + allplugins = setup['args'] + elif "bcfg2-repo-validate" in sys.argv[0]: + allplugins = 'Duplicates,RequiredAttrs,Validate'.split(',') + else: + allplugins = config.get('lint', 'plugins', + ",".join(Bcfg2.Server.Lint.__all__)).split(',') + + if setup['stdin']: + files = [s.strip() for s in sys.stdin.readlines()] + else: + files = None + + # load plugins + serverplugins = {} + serverlessplugins = {} + for plugin_name in allplugins: + try: + mod = getattr(__import__("Bcfg2.Server.Lint.%s" % + (plugin_name)).Server.Lint, plugin_name) + except ImportError: + try: + mod = __import__(plugin_name) + except Exception: + err = sys.exc_info()[1] + logger.error("Failed to load plugin %s: %s" % (plugin_name, + err)) + raise SystemExit(1) + plugin = getattr(mod, plugin_name) + if [c for c in inspect.getmro(plugin) + if c == Bcfg2.Server.Lint.ServerPlugin]: + serverplugins[plugin_name] = plugin + else: + serverlessplugins[plugin_name] = plugin + + errorhandler = get_errorhandler(config) + + run_serverless_plugins(serverlessplugins, + errorhandler=errorhandler, + config=config, setup=setup) + + if serverplugins: + if errorhandler.errors: + # it would be swell if we could try to start the server + # even if there were errors with the serverless plugins, + # but since XML parsing errors occur in the FAM thread + # (not in the core server thread), there's no way we can + # start the server and try to catch exceptions -- + # bcfg2-lint isn't in the same stack as the exceptions. + # so we're forced to assume that a serverless plugin error + # will prevent the server from starting + print("Serverless plugins encountered errors, skipping server " + "plugins") + else: + run_server_plugins(serverplugins, errorhandler=errorhandler, + config=config, setup=setup) + + if errorhandler.errors or errorhandler.warnings or setup['verbose']: + print("%d errors" % errorhandler.errors) + print("%d warnings" % errorhandler.warnings) + + if errorhandler.errors: + raise SystemExit(2) + elif errorhandler.warnings: + raise SystemExit(3) diff --git a/src/sbin/bcfg2-ping-sweep b/src/sbin/bcfg2-ping-sweep index 718ad69d0..70f718690 100755 --- a/src/sbin/bcfg2-ping-sweep +++ b/src/sbin/bcfg2-ping-sweep @@ -33,7 +33,7 @@ if __name__ == '__main__': osname = uname()[0] while hostlist or pids: - if hostlist and len(pids.keys()) < 15: + if hostlist and len(list(pids.keys())) < 15: host = hostlist.pop() pid = fork() if pid == 0: diff --git a/src/sbin/bcfg2-repo-validate b/src/sbin/bcfg2-repo-validate index 554e4f72b..cea09cda3 100755..120000 --- a/src/sbin/bcfg2-repo-validate +++ b/src/sbin/bcfg2-repo-validate @@ -1,227 +1 @@ -#!/usr/bin/env python - -""" -bcfg2-repo-validate checks all xml files in Bcfg2 -repos against their respective XML schemas. -""" -__revision__ = '$Revision$' - -import glob -import lxml.etree -import os -import sys -import Bcfg2.Options - -if __name__ == '__main__': - opts = {'repo': Bcfg2.Options.SERVER_REPOSITORY, - 'prefix': Bcfg2.Options.INSTALL_PREFIX, - 'verbose': Bcfg2.Options.VERBOSE, - 'configfile': Bcfg2.Options.CFILE} - setup = Bcfg2.Options.OptionParser(opts) - setup.parse(sys.argv[1:]) - verbose = setup['verbose'] - cpath = setup['configfile'] - prefix = setup['prefix'] - schemadir = "%s/share/bcfg2/schemas" % (prefix) - os.chdir(schemadir) - repo = setup['repo'] - - # Get a list of all info.xml files in the bcfg2 repository - info_list = [] - for infodir in ['Cfg', 'TGenshi', 'TCheetah']: - for root, dirs, files in os.walk('%s/%s' % (repo, infodir)): - for filename in files: - if filename == 'info.xml': - info_list.append(os.path.join(root, filename)) - - # get metadata list (with all included files) - metadata_list = glob.glob("%s/Metadata/groups.xml" % repo) - ref_bundles = set() - xdata = lxml.etree.parse("%s/Metadata/groups.xml" % repo) - included = set([ent.get('href') for ent in \ - xdata.findall('./{http://www.w3.org/2001/XInclude}include')]) - while included: - try: - filename = included.pop() - except KeyError: - continue - metadata_list.append("%s/Metadata/%s" % (repo, filename)) - groupdata = lxml.etree.parse("%s/Metadata/%s" % (repo, filename)) - group_ents = [ent.get('href') for ent in \ - groupdata. - findall('./{http://www.w3.org/2001/XInclude}include')] - for ent in group_ents: - included.add(ent) - included.discard(filename) - - # check for multiple default group definitions - default_groups = [] - for grp in lxml.etree.parse("%s/Metadata/groups.xml" \ - % repo).findall('.//Group'): - if grp.get('default') == 'true': - default_groups.append(grp) - if len(default_groups) > 1: - print("*** Warning: Multiple default groups defined") - for grp in default_groups: - print(" %s" % grp.get('name')) - - # get all XIncluded bundles - xdata.xinclude() - for bundle in xdata.findall("//Bundle"): - ref_bundles.add("%s/Bundler/%s" % (repo, bundle.get('name'))) - - # get lists of all other xml files to validate - clients_list = glob.glob("%s/Metadata/clients.xml" % repo) - bundle_list = glob.glob("%s/Bundler/*.xml" % repo) - genshibundle_list = glob.glob("%s/Bundler/*.genshi" % repo) - pkg_list = glob.glob("%s/Pkgmgr/*.xml" % repo) - base_list = glob.glob("%s/Base/*.xml" % repo) - rules_list = glob.glob("%s/Rules/*.xml" % repo) - imageinfo_list = glob.glob("%s/etc/report-configuration.xml" % repo) - services_list = glob.glob("%s/Svcmgr/*.xml" % repo) - deps_list = glob.glob("%s/Deps/*.xml" % repo) - dec_list = glob.glob("%s/Decisions/*" % repo) - pkgcfg_list = glob.glob("%s/Packages/config.xml" % repo) - gp_list = glob.glob('%s/GroupPatterns/config.xml' % repo) - - # verify attributes for configuration entries - # (as defined in doc/server/configurationentries) - # TODO: See if it is possible to do this in the schema instead - required_configuration_attrs = { - 'device': ['name', 'owner', 'group', 'dev_type'], - 'directory': ['name', 'owner', 'group', 'perms'], - 'file': ['name', 'owner', 'group', 'perms'], - 'hardlink': ['name', 'to'], - 'symlink': ['name', 'to'], - 'ignore': ['name'], - 'nonexistent': ['name'], - 'permissions': ['name', 'owner', 'group', 'perms']} - for rfile in rules_list: - try: - xdata = lxml.etree.parse(rfile) - except lxml.etree.XMLSyntaxError, e: - print("Failed to parse %s: %s" % (rfile, e)) - for posixpath in xdata.findall("//Path"): - pathname = posixpath.get('name') - pathtype = posixpath.get('type') - pathset = set(posixpath.attrib.keys()) - try: - required_attrs = set(required_configuration_attrs[pathtype] \ - + ['type']) - except KeyError: - continue - if 'dev_type' in required_attrs: - dev_type = posixpath.get('dev_type') - if dev_type in ['block', 'char']: - # check if major/minor are specified - required_attrs |= set(['major', 'minor']) - if pathset.issuperset(required_attrs): - continue - else: - print("The following required attributes are missing for" - " Path %s in %s: %s" % (pathname, rfile, - [attr for attr in required_attrs.difference(pathset)])) - - # warn on duplicate Pkgmgr entries with the same priority - pset = set() - for plist in pkg_list: - try: - xdata = lxml.etree.parse(plist) - except lxml.etree.XMLSyntaxError, e: - print("Failed to parse %s: %s" % (plist, e)) - # get priority, type, group - priority = xdata.getroot().get('priority') - ptype = xdata.getroot().get('type') - for pkg in xdata.findall("//Package"): - if pkg.getparent().tag == 'Group': - grp = pkg.getparent().get('name') - if type(grp) is not str and grp.getparent().tag == 'Group': - pgrp = grp.getparent().get('name') - else: - pgrp = 'none' - else: - grp = 'none' - pgrp = 'none' - ptuple = (pkg.get('name'), priority, ptype, grp, pgrp) - # check if package is already listed with same priority, - # type, grp - if ptuple in pset: - print("Duplicate Package %s, priority:%s, type:%s"\ - % (pkg.get('name'), priority, ptype)) - else: - pset.add(ptuple) - - filesets = {'metadata': (metadata_list, "%s/metadata.xsd"), - 'clients': (clients_list, "%s/clients.xsd"), - 'info': (info_list, "%s/info.xsd"), - 'bundle': (bundle_list, "%s/bundle.xsd"), - 'pkglist': (pkg_list, "%s/pkglist.xsd"), - 'base': (base_list, "%s/base.xsd"), - 'rules': (rules_list, "%s/rules.xsd"), - 'imageinfo': (imageinfo_list, "%s/report-configuration.xsd"), - 'services': (services_list, "%s/services.xsd"), - 'deps': (deps_list, "%s/deps.xsd"), - 'decisions': (dec_list, "%s/decisions.xsd"), - 'packages': (pkgcfg_list, "%s/packages.xsd"), - 'grouppatterns': (gp_list, "%s/grouppatterns.xsd"), - } - - failures = 0 - for k, (filelist, schemaname) in list(filesets.items()): - try: - schema = lxml.etree.XMLSchema(lxml.etree.parse(open(schemaname%(schemadir)))) - except: - print("Failed to process schema %s" % (schemaname%(schemadir))) - failures = 1 - continue - for filename in filelist: - try: - datafile = lxml.etree.parse(open(filename)) - except SyntaxError: - print("%s ***FAILS*** to parse \t\t<----" % (filename)) - os.system("xmllint %s" % filename) - failures = 1 - continue - except IOError: - print("Failed to open file %s \t\t<---" % (filename)) - failures = 1 - continue - if schema.validate(datafile): - if verbose: - print("%s checks out" % (filename)) - else: - rc = os.system("xmllint --noout --xinclude --schema \ - %s %s > /dev/null 2>/dev/null" % \ - (schemaname % schemadir, filename)) - if rc: - failures = 1 - print("%s ***FAILS*** to verify \t\t<----" % (filename)) - os.system("xmllint --noout --xinclude --schema %s %s" % \ - (schemaname % schemadir, filename)) - elif verbose: - print("%s checks out" % (filename)) - - # print out missing bundle information - if verbose: - print("") - for bundle in ref_bundles: - # check for both regular and genshi bundles - xmlbundle = "%s.xml" % bundle - genshibundle = "%s.genshi" % bundle - allbundles = bundle_list + genshibundle_list - if xmlbundle not in allbundles and \ - genshibundle not in allbundles: - print("*** Warning: Bundle %s referenced, but does not " - "exist." % bundle) - # verify bundle name attribute matches filename - for bundle in (bundle_list + genshibundle_list): - fname = bundle.split('Bundler/')[1].split('.')[0] - xdata = lxml.etree.parse(bundle) - bname = xdata.getroot().get('name') - if fname != bname: - print("The following names are inconsistent:") - print(" Filename is %s" % fname) - print(" Bundle name found in %s is %s" % (fname, bname)) - - - raise SystemExit, failures +bcfg2-lint
\ No newline at end of file diff --git a/src/sbin/bcfg2-reports b/src/sbin/bcfg2-reports index 559e9fb43..9a4c6e60d 100755 --- a/src/sbin/bcfg2-reports +++ b/src/sbin/bcfg2-reports @@ -1,4 +1,4 @@ -#! /usr/bin/env python +#!/usr/bin/env python """Query reporting system for client status.""" __revision__ = '$Revision$' @@ -47,6 +47,23 @@ def statecompare(client1, client2): else: return 0 +def totalcompare(client1, client2): + """Compares two clients by their total entry counts.""" + return cmp(client2.current_interaction.totalcount, \ + client1.current_interaction.totalcount) + +def goodcompare(client1, client2): + """Compares two clients by their good entry counts.""" + return cmp(client2.current_interaction.goodcount, \ + client1.current_interaction.goodcount) + +def badcompare(client1, client2): + """Compares two clients by their bad entry counts.""" + return cmp(client2.current_interaction.totalcount - \ + client2.current_interaction.goodcount, \ + client1.current_interaction.totalcount - \ + client1.current_interaction.goodcount) + def crit_compare(criterion, client1, client2): """Compares two clients by the criteria provided in criterion.""" for crit in criterion: @@ -57,6 +74,12 @@ def crit_compare(criterion, client1, client2): comp = statecompare(client1, client2) elif crit == 'time': comp = timecompare(client1, client2) + elif crit == 'total': + comp = totalcompare(client1, client2) + elif crit == 'good': + comp = goodcompare(client1, client2) + elif crit == 'bad': + comp = badcompare(client1, client2) if comp != 0: return comp @@ -83,6 +106,13 @@ def print_fields(fields, cli, max_name, entrydict): fdata.append("clean") else: fdata.append("dirty") + elif field == 'total': + fdata.append("%5d" % cli.current_interaction.totalcount) + elif field == 'good': + fdata.append("%5d" % cli.current_interaction.goodcount) + elif field == 'bad': + fdata.append("%5d" % cli.current_interaction.totalcount \ + - cli.current_interaction.goodcount) else: try: fdata.append(getattr(cli, field)) @@ -93,17 +123,18 @@ def print_fields(fields, cli, max_name, entrydict): if len(entrydict) > 0: display += " " display += str(entrydict[cli]) - print display + print(display) def print_entry(item, max_name): fmt = ("%%-%ds " % (max_name)) fdata = item.entry.kind + ":" + item.entry.name display = fmt % (fdata) - print display + print(display) fields = "" sort = "" badentry = "" +modifiedentry = "" extraentry = "" expire = "" singlehost = "" @@ -114,8 +145,8 @@ result = list() entrydict = dict() args = sys.argv[1:] -opts, pargs = getopt(args, 'ab:cde:hs:x:', - ['stale', 'sort=', 'fields=', 'badentry=', 'extraentry=']) +opts, pargs = getopt(args, 'ab:cde:hm:s:t:x:', + ['stale', 'sort=', 'fields=', 'badentry=', 'modifiedentry=', 'extraentry=']) for option in opts: if len(option) > 0: @@ -125,11 +156,17 @@ for option in opts: sort = option[1] if option[0] == '--badentry': badentry = option[1] + if option[0] == '--modifiedentry': + modifiedentry = option[1] if option[0] == '--extraentry': extraentry = option[1] if option[0] == '-x': expire = option[1] - if option[0] == '-s' or option[0] == '-b' or option[0] == '-e': + if option[0] == '-s' or \ + option[0] == '-t' or \ + option[0] == '-b' or \ + option[0] == '-m' or \ + option[0] == '-e': singlehost = option[1] if expire != "": @@ -137,55 +174,76 @@ if expire != "": if expire == c_inst.name: if c_inst.expiration == None: c_inst.expiration = datetime.datetime.now() - print "Host expired." + print("Host expired.") else: c_inst.expiration = None - print "Host un-expired." + print("Host un-expired.") c_inst.save() elif '-h' in args: - print """Usage: bcfg2-reports [option] ... + print("""Usage: bcfg2-reports [option] ... Options and arguments (and corresponding environment variables): --a : shows all hosts, including expired hosts --b NAME : single-host mode - shows bad entries from the - current interaction of NAME --c : shows only clean hosts --d : shows only dirty hosts --e NAME : single-host mode - shows extra entries from the - current interaction of NAME --h : shows help and usage info about bcfg2-reports --s NAME : single-host mode - shows bad and extra entries from - the current interaction of NAME --x NAME : toggles expired/unexpired state of NAME ---badentry=KIND,NAME : shows only hosts whose current interaction has bad - entries in of KIND kind and NAME name; if a single - argument ARG1 is given, then KIND,NAME pairs will be - read from a file of name ARG1 ---extraentry=KIND,NAME : shows only hosts whose current interaction has extra - entries in of KIND kind and NAME name; if a single - argument ARG1 is given, then KIND,NAME pairs will be - read from a file of name ARG1 ---fields=ARG1,ARG2,... : only displays the fields ARG1,ARG2,... - (name,time,state) ---sort=ARG1,ARG2,... : sorts output on ARG1,ARG2,... (name,time,state) ---stale : shows hosts which haven't run in the last 24 hours -""" +-a : shows all hosts, including expired hosts +-b NAME : single-host mode - shows bad entries from the + current interaction of NAME +-c : shows only clean hosts +-d : shows only dirty hosts +-e NAME : single-host mode - shows extra entries from the + current interaction of NAME +-h : shows help and usage info about bcfg2-reports +-m NAME : single-host mode - shows modified entries from the + current interaction of NAME +-s NAME : single-host mode - shows bad, modified, and extra + entries from the current interaction of NAME +-t NAME : single-host mode - shows total number of managed and + good entries from the current interaction of NAME +-x NAME : toggles expired/unexpired state of NAME +--badentry=KIND,NAME : shows only hosts whose current interaction has bad + entries in of KIND kind and NAME name; if a single + argument ARG1 is given, then KIND,NAME pairs will be + read from a file of name ARG1 +--modifiedentry=KIND,NAME : shows only hosts whose current interaction has + modified entries in of KIND kind and NAME name; if a + single argument ARG1 is given, then KIND,NAME pairs + will be read from a file of name ARG1 +--extraentry=KIND,NAME : shows only hosts whose current interaction has extra + entries in of KIND kind and NAME name; if a single + argument ARG1 is given, then KIND,NAME pairs will be + read from a file of name ARG1 +--fields=ARG1,ARG2,... : only displays the fields ARG1,ARG2,... + (name,time,state) +--sort=ARG1,ARG2,... : sorts output on ARG1,ARG2,... (name,time,state) +--stale : shows hosts which haven't run in the last 24 hours +""") elif singlehost != "": for c_inst in c_list: if singlehost == c_inst.name: + if '-t' in args: + managed = c_inst.current_interaction.totalcount + good = c_inst.current_interaction.goodcount + print("Total managed entries: %d (good: %d)" % (managed, good)) baditems = c_inst.current_interaction.bad() if len(baditems) > 0 and ('-b' in args or '-s' in args): - print "Bad Entries:" + print("Bad Entries:") max_name = -1 for item in baditems: if len(item.entry.name) > max_name: max_name = len(item.entry.name) for item in baditems: print_entry(item, max_name) + modifieditems = c_inst.current_interaction.modified() + if len(modifieditems) > 0 and ('-m' in args or '-s' in args): + print "Modified Entries:" + max_name = -1 + for item in modifieditems: + if len(item.entry.name) > max_name: + max_name = len(item.entry.name) + for item in modifieditems: + print_entry(item, max_name) extraitems = c_inst.current_interaction.extra() if len(extraitems) > 0 and ('-e' in args or '-s' in args): - print "Extra Entries:" + print("Extra Entries:") max_name = -1 for item in extraitems: if len(item.entry.name) > max_name: @@ -206,6 +264,9 @@ else: if badentry != "": badentry = badentry.split(',') + if modifiedentry != "": + modifiedentry = modifiedentry.split(',') + if extraentry != "": extraentry = extraentry.split(',') @@ -233,7 +294,7 @@ else: for c_inst in c_list: baditems = c_inst.current_interaction.bad() for item in baditems: - if item.name == badentry[1] and item.kind == badentry[0]: + if item.entry.name == badentry[1] and item.entry.kind == badentry[0]: result.append(c_inst) if c_inst in entrydict: entrydict.get(c_inst).append(badentry[1]) @@ -244,7 +305,29 @@ else: for c_inst in c_list: baditems = c_inst.current_interaction.bad() for item in baditems: - if item.name == badentry[1] and item.kind == badentry[0]: + if item.entry.name == badentry[1] and item.entry.kind == badentry[0]: + result.append(c_inst) + break + elif modifiedentry != "": + if len(modifiedentry) == 1: + fileread = fileinput.input(modifiedentry[0]) + for line in fileread: + modifiedentry = line.strip().split(',') + for c_inst in c_list: + modifieditems = c_inst.current_interaction.modified() + for item in modifieditems: + if item.entry.name == modifiedentry[1] and item.entry.kind == modifiedentry[0]: + result.append(c_inst) + if c_inst in entrydict: + entrydict.get(c_inst).append(modifiedentry[1]) + else: + entrydict[c_inst] = [modifiedentry[1]] + break + else: + for c_inst in c_list: + modifieditems = c_inst.current_interaction.modified() + for item in modifieditems: + if item.entry.name == modifiedentry[1] and item.entry.kind == modifiedentry[0]: result.append(c_inst) break elif extraentry != "": @@ -255,7 +338,7 @@ else: for c_inst in c_list: extraitems = c_inst.current_interaction.extra() for item in extraitems: - if item.name == extraentry[1] and item.kind == extraentry[0]: + if item.entry.name == extraentry[1] and item.entry.kind == extraentry[0]: result.append(c_inst) if c_inst in entrydict: entrydict.get(c_inst).append(extraentry[1]) @@ -266,7 +349,7 @@ else: for c_inst in c_list: extraitems = c_inst.current_interaction.extra() for item in extraitems: - if item.name == extraentry[1] and item.kind == extraentry[0]: + if item.entry.name == extraentry[1] and item.entry.kind == extraentry[0]: result.append(c_inst) break diff --git a/src/sbin/bcfg2-server b/src/sbin/bcfg2-server index cf44f1699..546d5a249 100755 --- a/src/sbin/bcfg2-server +++ b/src/sbin/bcfg2-server @@ -35,6 +35,7 @@ if __name__ == '__main__': OPTINFO.update({'key' : Bcfg2.Options.SERVER_KEY, 'cert' : Bcfg2.Options.SERVER_CERT, 'ca' : Bcfg2.Options.SERVER_CA, + 'listen_all' : Bcfg2.Options.SERVER_LISTEN_ALL, 'location' : Bcfg2.Options.SERVER_LOCATION, 'passwd' : Bcfg2.Options.SERVER_PASSWORD, 'static' : Bcfg2.Options.SERVER_STATIC, @@ -51,6 +52,7 @@ if __name__ == '__main__': print("Could not read %s" % setup['configfile']) sys.exit(1) Bcfg2.Component.run_component(Bcfg2.Server.Core.Core, + listen_all=setup['listen_all'], location=setup['location'], daemon = setup['daemon'], pidfile_name = setup['daemon'], @@ -69,7 +71,8 @@ if __name__ == '__main__': certfile=setup['cert'], ca=setup['ca'], ) - except CoreInitError, msg: + except CoreInitError: + msg = sys.exc_info()[1] logger.error(msg) logger.error("exiting") sys.exit(1) |