#!/usr/bin/env python # Contributed by Robert Gogolok # TODO: # - export plugins # - document usage '''This tool exports the bcfg2 configuration for the specified client to an output directory. First the specified output directory is created. Then for every entry of the specified host the appropriate directory under the output directory is created. The metadata information get stored in an index file in the output directory. The format of the index file is: user,group,permission,/path/to/file ''' __revision__ = '$Revision: 221 $' import logging, lxml.etree, Bcfg2.Logging, Bcfg2.Server.Core import Bcfg2.Server.Plugins.Metadata, Bcfg2.Server.Plugin import sys,os,time,errno from optparse import OptionParser DEFAULT_BCFG2_CONFIGFILE = "/etc/bcfg2.conf" DEFAULT_FAM_STEPS = 20 DEFAULT_INDEX_FILE = "index.txt" TOOLNAME = "bcfg2-export-config" def buildConfiguration(core, client): '''Build client configuration.''' return core.BuildConfiguration(client) def write_entry(indexfile, user, group, permission, path): '''Write an entry to the file listing ConfigFile entries in outputdir.''' f = open(outputdir + '/%s' % indexfile, 'a') f.write("%s,%s,%s,%s\n" % (user, group, permission, path)) f.close() logger.info("Wrote entry." ) class ConfigFileNotBuild(Exception): def __init__(self, value): self.value = value def __str__(self): return repr(self.value) def handleConfigFileEntry(indexfile, cfg): '''Store file content of an ... entry in the appropriate directory under the output directory.''' name = cfg.get('name') permission = cfg.get('perms').rjust(4,'0') user = cfg.get('owner') group = cfg.get('group') logger.info("\nHandling ConfigFile entry %s >>>" % name) # directory creation logger.info("Creating directory %s" % ( os.path.dirname(outputdir + name)) ) try: os.makedirs(os.path.dirname(outputdir + name)) except OSError,err: if err.errno != errno.EEXIST: raise except: logger.error("Fatal error during directory creation!") raise # write config file f = open(outputdir + name, "w" ) try: f.write(cfg.text) except: # plugin throw an exception and therefore there is no content => None raise ConfigFileNotBuild(name) f.close() # write entry try: write_entry(indexfile, user, group, permission, name) except: logger.error("Writing entry to configfiles failed!") raise logger.info("<<<") if __name__ == '__main__': Bcfg2.Logging.setup_logging('%s' % TOOLNAME, to_syslog=False) logger = logging.getLogger('%s' % TOOLNAME) # parse command line options, arguments parser = OptionParser(usage = "%prog [options] client outputdir", version = __revision__) parser.add_option("-C", "--config-file", action="store", dest="configfile", help="Use given bcfg2.conf file, by default %s" % DEFAULT_BCFG2_CONFIGFILE) parser.add_option("-f", "--fam-steps", action="store", dest="famsteps", type = "int", help="How many times to handle fam/gamin events, by default %s" % DEFAULT_FAM_STEPS) parser.add_option("-i", "--index-filename", action="store", dest="indexfile", help="Filename for index of exported ConfigFile entries, by default %s" % DEFAULT_INDEX_FILE) parser.set_defaults(configfile=DEFAULT_BCFG2_CONFIGFILE, famsteps = DEFAULT_FAM_STEPS, indexfile = DEFAULT_INDEX_FILE) (options, args) = parser.parse_args() # ensure client hostname and outputdir is given if len(args) != 2: parser.error("incorrect number of arguments.") client = args[0] outputdir = args[1] # stop if output directory exists if os.path.exists(outputdir): logger.error("Output directory already exists, won't override!") raise SystemExit, 1 logger.info("Generating configuration for %s" % client) # load Bcfg2 Core try: logger.debug("Trying to load core...") bcore = Bcfg2.Server.Core.Core({}, options.configfile) except Bcfg2.Server.Core.CoreInitError, msg: logger.error("Core load failed because %s" % msg) raise SystemExit, 1 else: logger.debug("Core loaded.") # FAM service handling for i in range(options.famsteps): logger.info("FAM service handling: %s to go..." % str(options.famsteps - i) ) bcore.fam.Service() time.sleep(0.5) # get configuration for client try: client_config = buildConfiguration( bcore, client) except: logger.error("Building client configuration failed. Exiting...") raise SystemExit, 1 # client could be without a group, not listed in client.xml ... if client_config.tag == 'error': logger.error("Building client configuration failed. Exiting...") raise SystemExit, 1 # handle entries for configfile in [cfile for cfile in client_config.findall(".//ConfigFile")]: try: handleConfigFileEntry(options.indexfile, configfile) except ConfigFileNotBuild, e: logger.error("Error: Plugin failed to generate file content for ConfigFile %s !" % e) raise SystemExit, 1 except: logger.error("unknown error, I give up") raise SystemExit, 1