#!/usr/bin/python -i '''This tool loads the Bcfg2 core into an interactive debugger''' __revision__ = '$Revision$' import logging, lxml.etree, sys, time, Bcfg2.Logging, Bcfg2.Server.Core, Bcfg2.Server.Metadata, Bcfg2.Server.Plugin def printTabular(rows): '''print data in tabular format''' cmax = tuple([max([len(str(row[index])) for row in rows]) + 1 for index in xrange(len(rows[0]))]) fstring = (" %%-%ss |" * len(cmax)) % cmax fstring = ('|'.join([" %%-%ss "] * len(cmax))) % cmax print fstring % rows[0] print (sum(cmax) + (len(cmax) * 2) + (len(cmax) - 1)) * '=' for row in rows[1:]: print fstring % row def getInput(): '''read commands from stdin''' try: return raw_input('> ').split(" ") except KeyboardInterrupt: return [''] except EOFError: return ['quit'] def doShowentries(cmd, core): '''show abstract configuration entries for a given host''' if len(cmd) not in [2, 3]: print "Usage: showentries " return try: meta = core.metadata.get_metadata(cmd[1]) except Bcfg2.Server.Metadata.MetadataConsistencyError: print "Unable to find metadata for host %s" % cmd[1] return structures = core.GetStructures(meta) output = [('entrytype', 'name')] if len(cmd) == 2: for item in structures: for child in item.getchildren(): output.append((child.tag, child.get('name'))) if len(cmd) == 3: for item in structures: for child in item.getchildren(): if child.tag == cmd[2]: output.append((child.tag, child.get('name'))) printTabular(output) def doBuild(cmd, core): '''build client configuration''' if len(cmd) == 3: output = open(cmd[2], 'w') output.write(lxml.etree.tostring(core.BuildConfiguration(cmd[1]))) output.close() else: print 'Usage: build ' def doBuildFile(cmd, core): '''build a config file for client''' if len(cmd) == 3: entry = lxml.etree.Element('ConfigFile', name=cmd[1]) metadata = core.metadata.get_metadata(cmd[2]) core.Bind(entry, metadata) print lxml.etree.tostring(entry) else: print 'Usage: buildfile filename hostname' def doBundles(_, core): '''print out group/bundle info''' data = [('Group', 'Bundles')] groups = core.metadata.groups.keys() groups.sort() for group in groups: data.append((group, ','.join(core.metadata.groups[group][0]))) printTabular(data) def doClients(_, core): '''print out client info''' data = [('Client', 'Profile')] clist = core.metadata.clients.keys() clist.sort() for client in clist: data.append((client, core.metadata.clients[client])) printTabular(data) def doHelp(_, dummy): '''print out usage info''' print 'Commands:' print 'build - build config for hostname, writing to filename' print 'buildfile - build config file for hostname (not written to disk)' print 'bundles - print out group/bundle information' print 'clients - print out client/profile information' print 'debug - shell out to native python interpreter' print 'generators - list current versions of generators' print 'groups - list groups' print 'help - print this text' print 'mappings - print generator mappings for optional type and name' print 'quit' print 'showentries - show abstract configuration entries for a given host' print 'update - process pending file events' print 'version - print version of this tool' def doGenerators(_, core): '''print out generator info''' for generator in core.generators: print generator.__version__ def doGroups(_, core): '''print out group info''' data = [("Groups", "Profile", "Category", "Contains")] grouplist = core.metadata.groups.keys() grouplist.sort() for group in grouplist: if group in core.metadata.profiles: prof = 'yes' else: prof = 'no' if core.metadata.categories.has_key(group): cat = core.metadata.categories[group] else: cat = '' gdata = [grp for grp in core.metadata.groups[group][1]] gdata.remove(group) data.append((group, prof, cat, ','.join(gdata))) printTabular(data) def doMappings(cmd, core): '''print out mapping info''' # dump all mappings unless type specified data = [('Plugin', 'Type', 'Name')] for generator in core.generators: if len(cmd) == 1: etypes = generator.Entries.keys() elif len(cmd) > 1: etypes = [cmd[1]] if len(cmd) == 3: interested = [(etype, [cmd[2]]) for etype in etypes] else: interested = [(etype, generator.Entries[etype].keys()) for etype in etypes if generator.Entries.has_key(etype)] if [etype for (etype, names) in interested if generator.Entries.has_key(etype) and [name for name in names if generator.Entries[etype].has_key(name)]]: for (etype, names) in interested: for name in names: if generator.Entries.has_key(etype) and generator.Entries[etype].has_key(name): data.append((generator.__name__, etype, name)) printTabular(data) def doQuit(cmd, core): '''exit program''' raise SystemExit, 0 def doUpdate(_, core): '''Process pending fs events''' core.fam.Service() def doVersion(_, dummy): '''print out code version''' print __revision__ if __name__ == '__main__': Bcfg2.Logging.setup_logging('bcfg2-info', to_syslog=False) logger = logging.getLogger('bcfg2-info') dispatch = {'build': doBuild, 'buildfile': doBuildFile, 'bundles': doBundles, 'clients': doClients, 'generators': doGenerators, 'groups': doGroups, 'help': doHelp, 'mappings': doMappings, 'quit': doQuit, 'showentries': doShowentries, 'update': doUpdate, 'version': doVersion} if '-c' in sys.argv: cfile = sys.argv[-1] else: cfile = '/etc/bcfg2.conf' try: bcore = Bcfg2.Server.Core.Core({}, cfile) except Bcfg2.Server.Core.CoreInitError, msg: print "Core load failed because %s" % msg raise SystemExit, 1 for i in range(25): bcore.fam.Service() time.sleep(0.5) while True: ucmd = getInput() if ucmd[0] == 'debug': break else: if dispatch.has_key(ucmd[0]): try: dispatch[ucmd[0]](ucmd, bcore) except SystemExit, code: raise SystemExit, code except Bcfg2.Server.Plugin.PluginExecutionError: continue except: logger.error("command failure", exc_info=1) else: print "Unknown command: %s" % ucmd[0]