diff options
author | Narayan Desai <desai@mcs.anl.gov> | 2011-06-22 17:01:40 -0500 |
---|---|---|
committer | Narayan Desai <desai@mcs.anl.gov> | 2011-06-22 17:01:40 -0500 |
commit | 4849378a62ab0dbf72f8ce4e6b2073dc73f2337a (patch) | |
tree | 14945dd6045c438f5dbc8e96f023258d31e1adf9 /src/sbin | |
parent | 8d08d5195fa0b6f503752273183948e5d24f33d6 (diff) | |
parent | 2db056574f5f55c3c802da63abe7e3de10db5d76 (diff) | |
download | bcfg2-4849378a62ab0dbf72f8ce4e6b2073dc73f2337a.tar.gz bcfg2-4849378a62ab0dbf72f8ce4e6b2073dc73f2337a.tar.bz2 bcfg2-4849378a62ab0dbf72f8ce4e6b2073dc73f2337a.zip |
Merge branch 'master' of git.mcs.anl.gov:bcfg2
Diffstat (limited to 'src/sbin')
-rwxr-xr-x | src/sbin/bcfg2 | 22 | ||||
-rwxr-xr-x | src/sbin/bcfg2-info | 19 | ||||
-rwxr-xr-x | src/sbin/bcfg2-lint | 23 | ||||
-rwxr-xr-x | src/sbin/bcfg2-reports | 145 | ||||
-rwxr-xr-x | src/sbin/bcfg2-server | 2 |
5 files changed, 162 insertions, 49 deletions
diff --git a/src/sbin/bcfg2 b/src/sbin/bcfg2 index 7f7d8f5c6..5ddfd8791 100755 --- a/src/sbin/bcfg2 +++ b/src/sbin/bcfg2 @@ -7,6 +7,7 @@ import fcntl import logging import os import signal +import socket import stat import sys import tempfile @@ -75,6 +76,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) @@ -178,10 +180,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: @@ -197,6 +200,13 @@ class Client: self.logger.error("Failed to download probes from bcfg2") self.logger.error(flt.faultString) raise SystemExit(1) + except (Bcfg2.Proxy.CertificateError, + socket.gaierror, + socket.error): + e = sys.exc_info()[1] + self.logger.error("Failed to download probes from bcfg2: %s" + % e) + raise SystemExit(1) times['probe_download'] = time.time() @@ -243,7 +253,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) @@ -252,7 +262,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" % diff --git a/src/sbin/bcfg2-info b/src/sbin/bcfg2-info index 161fee441..07953ae69 100755 --- a/src/sbin/bcfg2-info +++ b/src/sbin/bcfg2-info @@ -375,21 +375,21 @@ 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%s" % client_meta.hostname) + print("Profile:\t%s" % client_meta.profile) + print("Groups:\t\t%s" % 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%s" % 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) for conn in client_meta.connectors: if getattr(client_meta, conn): - print("%s:\t" % (conn), getattr(client_meta, conn)) + print("%s:\t%s" % (conn, getattr(client_meta, conn))) print("=" * 80) def do_mappings(self, args): @@ -487,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 index 6bc34433e..464e839e5 100755 --- a/src/sbin/bcfg2-lint +++ b/src/sbin/bcfg2-lint @@ -50,10 +50,13 @@ def run_plugin(plugin, plugin_name, setup=None, errorhandler=None, errorhandler = get_errorhandler(config) if config is not None and config.has_section(plugin_name): - args.append(dict(config.items(plugin_name), **setup)) + 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 @@ -181,8 +184,20 @@ if __name__ == '__main__': config=config, setup=setup) if serverplugins: - run_server_plugins(serverplugins, errorhandler=errorhandler, - config=config, setup=setup) + 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) diff --git a/src/sbin/bcfg2-reports b/src/sbin/bcfg2-reports index 20288fc5e..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)) @@ -104,6 +134,7 @@ def print_entry(item, max_name): 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 != "": @@ -147,33 +184,45 @@ elif '-h' in args: 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:") @@ -183,6 +232,15 @@ elif singlehost != "": 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:") @@ -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 f4bd5e5b7..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'], |