diff options
Diffstat (limited to 'src/lib/Server/Plugins')
28 files changed, 176 insertions, 119 deletions
diff --git a/src/lib/Server/Plugins/BB.py b/src/lib/Server/Plugins/BB.py index 18719f2be..dd23f6ec9 100644 --- a/src/lib/Server/Plugins/BB.py +++ b/src/lib/Server/Plugins/BB.py @@ -1,4 +1,4 @@ -import lxml.etree +import lxml.etree import Bcfg2.Server.Plugin import glob import os @@ -41,7 +41,7 @@ class BBfile(Bcfg2.Server.Plugin.XMLFileBacked): else: logger.error("%s" % lxml.etree.tostring(node)) self.users[node.get('name')] = node.get('user',"").split(':') - + def enforce_bootlinks(self): for mac, target in self.bootlinks: path = self.tftppath + '/' + mac @@ -53,7 +53,7 @@ class BBfile(Bcfg2.Server.Plugin.XMLFileBacked): os.symlink(target, path) except: logger.error("Failed to modify link %s" % path) - + class BBDirectoryBacked(Bcfg2.Server.Plugin.DirectoryBacked): __child__ = BBfile @@ -71,21 +71,14 @@ class BB(Bcfg2.Server.Plugin.Plugin, self.store = BBDirectoryBacked(self.data, core.fam) def get_additional_data(self, metadata): - + users = {} for user in self.store.entries['bb.xml'].users.get(metadata.hostname.split(".")[0], []): pubkeys = [] for fname in glob.glob('/home/%s/.ssh/*.pub'%user): pubkeys.append(open(fname).read()) - - users[user] = pubkeys - - return dict([('users', users), - ('macs', self.store.entries['bb.xml'].macs)]) - + users[user] = pubkeys - - - - + return dict([('users', users), + ('macs', self.store.entries['bb.xml'].macs)]) diff --git a/src/lib/Server/Plugins/Base.py b/src/lib/Server/Plugins/Base.py index b96c9b3d1..e6f124432 100644 --- a/src/lib/Server/Plugins/Base.py +++ b/src/lib/Server/Plugins/Base.py @@ -6,15 +6,15 @@ import copy import lxml.etree class Base(Bcfg2.Server.Plugin.Plugin, - Bcfg2.Server.Plugin.Structure, + Bcfg2.Server.Plugin.Structure, Bcfg2.Server.Plugin.XMLDirectoryBacked): '''This Structure is good for the pile of independent configs needed for most actual systems''' - name = 'Base' + name = 'Base' __version__ = '$Id$' __author__ = 'bcfg-dev@mcs.anl.gov' __child__ = Bcfg2.Server.Plugin.StructFile - + '''base creates independent clauses based on client metadata''' def __init__(self, core, datastore): Bcfg2.Server.Plugin.Plugin.__init__(self, core, datastore) @@ -26,7 +26,7 @@ class Base(Bcfg2.Server.Plugin.Plugin, except OSError: self.logger.error("Failed to load Base repository") raise Bcfg2.Server.Plugin.PluginInitError - + def BuildStructures(self, metadata): '''Build structures for client described by metadata''' ret = lxml.etree.Element("Independent", version='2.0') diff --git a/src/lib/Server/Plugins/Bundler.py b/src/lib/Server/Plugins/Bundler.py index ee7edb49c..914da3cee 100644 --- a/src/lib/Server/Plugins/Bundler.py +++ b/src/lib/Server/Plugins/Bundler.py @@ -1,11 +1,16 @@ '''This provides bundle clauses with translation functionality''' __revision__ = '$Revision$' -import copy, lxml.etree, Bcfg2.Server.Plugin, re +import copy +import lxml.etree +import re + +import Bcfg2.Server.Plugin try: + import genshi.template + import genshi.template.base import Bcfg2.Server.Plugins.SGenshi - import genshi.template, genshi.template.base have_genshi = True except: have_genshi = False @@ -21,11 +26,11 @@ class Bundler(Bcfg2.Server.Plugin.Plugin, Bcfg2.Server.Plugin.Structure, Bcfg2.Server.Plugin.XMLDirectoryBacked): '''The bundler creates dependent clauses based on the bundle/translation scheme from bcfg1''' - name = 'Bundler' + name = 'Bundler' __version__ = '$Id$' __author__ = 'bcfg-dev@mcs.anl.gov' patterns = re.compile('^(?P<name>.*)\.(xml|genshi)$') - + def __init__(self, core, datastore): Bcfg2.Server.Plugin.Plugin.__init__(self, core, datastore) Bcfg2.Server.Plugin.Structure.__init__(self) @@ -69,4 +74,3 @@ class Bundler(Bcfg2.Server.Plugin.Plugin, self.logger.error("Got multiple matches for bundle %s" \ % (bundlename)) return bundleset - diff --git a/src/lib/Server/Plugins/Cfg.py b/src/lib/Server/Plugins/Cfg.py index d26012205..ace400692 100644 --- a/src/lib/Server/Plugins/Cfg.py +++ b/src/lib/Server/Plugins/Cfg.py @@ -1,7 +1,13 @@ '''This module implements a config file repository''' __revision__ = '$Revision$' -import binascii, logging, os, re, tempfile, Bcfg2.Server.Plugin +import binascii +import logging +import os +import re +import tempfile + +import Bcfg2.Server.Plugin logger = logging.getLogger('Bcfg2.Plugins.Cfg') @@ -148,4 +154,3 @@ class Cfg(Bcfg2.Server.Plugin.GroupSpool, def AcceptPullData(self, specific, new_entry, log): return self.entries[new_entry.get('name')].write_update(specific, new_entry, log) - diff --git a/src/lib/Server/Plugins/DBStats.py b/src/lib/Server/Plugins/DBStats.py index c9d11a1f4..3b6909eda 100644 --- a/src/lib/Server/Plugins/DBStats.py +++ b/src/lib/Server/Plugins/DBStats.py @@ -13,7 +13,7 @@ class DBStats(Bcfg2.Server.Plugin.Plugin, Bcfg2.Server.Plugin.PullSource): name = 'DBStats' __version__ = '$Id$' - + def __init__(self, core, datastore): Bcfg2.Server.Plugin.Plugin.__init__(self, core, datastore) Bcfg2.Server.Plugin.Statistics.__init__(self) @@ -34,7 +34,7 @@ class DBStats(Bcfg2.Server.Plugin.Plugin, e.append(newstats) container = lxml.etree.Element("ConfigStatistics") container.append(e) - + # FIXME need to build a metadata interface to expose a list of clients # FIXME Server processing the request should be mentionned here start = time.time() @@ -71,7 +71,7 @@ class DBStats(Bcfg2.Server.Plugin.Plugin, ret.append(getattr(entry.reason, t)) else: ret.append(getattr(entry.reason, "current_%s" % t)) - + if entry.reason.current_diff != '': ret.append('\n'.join(difflib.restore(\ entry.reason.current_diff.split('\n'), 1))) diff --git a/src/lib/Server/Plugins/Decisions.py b/src/lib/Server/Plugins/Decisions.py index 95db433a7..1aba88840 100644 --- a/src/lib/Server/Plugins/Decisions.py +++ b/src/lib/Server/Plugins/Decisions.py @@ -14,7 +14,7 @@ class DecisionFile(Bcfg2.Server.Plugin.SpecificData): class DecisionSet(Bcfg2.Server.Plugin.EntrySet): def __init__(self, path, fam, encoding): """Container for decision specification files - + Arguments: - `path`: repository path - `fam`: reference to the file monitor @@ -51,7 +51,7 @@ class Decisions(DecisionSet, def __init__(self, core, datastore): """Decisions plugins - + Arguments: - `core`: Bcfg2.Core instance - `datastore`: File repository location @@ -59,4 +59,4 @@ class Decisions(DecisionSet, Bcfg2.Server.Plugin.Plugin.__init__(self, core, datastore) Bcfg2.Server.Plugin.Decision.__init__(self) DecisionSet.__init__(self, self.data, core.fam, core.encoding) - + diff --git a/src/lib/Server/Plugins/Deps.py b/src/lib/Server/Plugins/Deps.py index b6359a476..cdf23833b 100644 --- a/src/lib/Server/Plugins/Deps.py +++ b/src/lib/Server/Plugins/Deps.py @@ -1,13 +1,15 @@ '''This plugin provides automatic dependency handling''' __revision__ = '$Revision$' -import Bcfg2.Server.Plugin, lxml.etree +import lxml.etree + +import Bcfg2.Server.Plugin class DNode(Bcfg2.Server.Plugin.INode): '''DNode provides supports for single predicate types for dependencies''' raw = {'Group':"lambda x:'%s' in x.groups and predicate(x)"} containers = ['Group'] - + def __init__(self, data, idict, parent=None): self.data = data self.contents = {} @@ -49,7 +51,7 @@ class Deps(Bcfg2.Server.Plugin.PrioDir, def HandleEvent(self, event): self.cache = {} Bcfg2.Server.Plugin.PrioDir.HandleEvent(self, event) - + def validate_structures(self, metadata, structures): entries = [] prereqs = [] @@ -67,7 +69,7 @@ class Deps(Bcfg2.Server.Plugin.PrioDir, prereqs = self.cache[(entries, gdata)] else: [src.Cache(metadata) for src in self.entries.values()] - + toexamine = list(entries[:]) while toexamine: entry = toexamine.pop() @@ -91,7 +93,7 @@ class Deps(Bcfg2.Server.Plugin.PrioDir, toexamine.append(prq) prereqs.append(prq) self.cache[(entries, gdata)] = prereqs - + newstruct = lxml.etree.Element("Independent") for tag, name in prereqs: try: diff --git a/src/lib/Server/Plugins/Editor.py b/src/lib/Server/Plugins/Editor.py index 1e84ccb2f..76adaf4cb 100644 --- a/src/lib/Server/Plugins/Editor.py +++ b/src/lib/Server/Plugins/Editor.py @@ -64,7 +64,7 @@ class Editor(Bcfg2.Server.Plugin.GroupSpool, probe = lxml.etree.Element('probe') probe.set('name', name) probe.set('source', "Editor") - probe.text = "cat %s" %name + probe.text = "cat %s" % name probelist.append(probe) return probelist diff --git a/src/lib/Server/Plugins/Fossil.py b/src/lib/Server/Plugins/Fossil.py index 2b17de2c9..82850e602 100644 --- a/src/lib/Server/Plugins/Fossil.py +++ b/src/lib/Server/Plugins/Fossil.py @@ -31,12 +31,12 @@ class Fossil(Bcfg2.Server.Plugin.Plugin, raise Bcfg2.Server.Plugin.PluginInitError logger.debug("Initialized Fossil.py plugin with %(ffile)s at revision %(frev)s" \ - % {'ffile': fossil_file, 'frev': revision} ) + % {'ffile': fossil_file, 'frev': revision}) def get_revision(self): '''Read fossil revision information for the bcfg2 repository''' try: - data = Popen("env LC_ALL=C fossil info", + data = Popen("env LC_ALL=C fossil info", shell=True, cwd=self.datastore, stdout=PIPE).stdout.readlines() diff --git a/src/lib/Server/Plugins/GroupPatterns.py b/src/lib/Server/Plugins/GroupPatterns.py index de25d0143..3801a6a08 100644 --- a/src/lib/Server/Plugins/GroupPatterns.py +++ b/src/lib/Server/Plugins/GroupPatterns.py @@ -1,5 +1,6 @@ +import lxml.etree +import re -import re, lxml.etree import Bcfg2.Server.Plugin class PackedDigitRange(object): diff --git a/src/lib/Server/Plugins/Metadata.py b/src/lib/Server/Plugins/Metadata.py index 609e8ecd4..d78592f14 100644 --- a/src/lib/Server/Plugins/Metadata.py +++ b/src/lib/Server/Plugins/Metadata.py @@ -106,9 +106,9 @@ class Metadata(Bcfg2.Server.Plugin.Plugin, def init_repo(cls, repo, groups, os_selection, clients): path = '%s/%s' % (repo, cls.name) cls.make_path(path) - open("%s/Metadata/groups.xml" % - repo, "w").write(groups % os_selection) - open("%s/Metadata/clients.xml" % + open("%s/Metadata/groups.xml" % + repo, "w").write(groups % os_selection) + open("%s/Metadata/clients.xml" % repo, "w").write(clients % socket.getfqdn()) def get_groups(self): @@ -356,7 +356,7 @@ class Metadata(Bcfg2.Server.Plugin.Plugin, 'cert+password') if 'uuid' in client.attrib: self.uuid[client.get('uuid')] = clname - if client.get('secure', 'false') == 'true' : + if client.get('secure', 'false') == 'true': self.secure.append(clname) if client.get('location', 'fixed') == 'floating': self.floating.append(clname) @@ -478,7 +478,7 @@ class Metadata(Bcfg2.Server.Plugin.Plugin, pretty_print='true')) fcntl.lockf(fd, fcntl.LOCK_UN) datafile.close() - + def locked(self, fd): try: fcntl.lockf(fd, fcntl.LOCK_EX | fcntl.LOCK_NB) @@ -554,7 +554,7 @@ class Metadata(Bcfg2.Server.Plugin.Plugin, all_groups = set() [all_groups.update(g[1]) for g in self.groups.values()] return all_groups - + def get_client_names_by_profiles(self, profiles): return [client for client, profile in self.clients.iteritems() \ if profile in profiles] @@ -583,7 +583,7 @@ class Metadata(Bcfg2.Server.Plugin.Plugin, def merge_additional_data(self, imd, source, data): if not hasattr(imd, source): setattr(imd, source, data) - imd.connectors.append(source) + imd.connectors.append(source) def validate_client_address(self, client, address): '''Check address against client''' @@ -603,7 +603,7 @@ class Metadata(Bcfg2.Server.Plugin.Plugin, self.logger.error("Got request for %s from incorrect address %s" \ % (client, address)) return False - + def AuthenticateConnection(self, cert, user, password, address): '''This function checks auth creds''' if cert: @@ -677,7 +677,7 @@ class Metadata(Bcfg2.Server.Plugin.Plugin, % (client)) cli[0].set('auth', 'cert') self.write_back_clients() - + def viz(self, hosts, bundles, key, colors): '''admin mode viz support''' groups_tree = lxml.etree.parse(self.data + "/groups.xml") @@ -712,7 +712,7 @@ class Metadata(Bcfg2.Server.Plugin.Plugin, if bund.get('name') not in bundles] bundles.sort() for bundle in bundles: - viz_str += '''\t"bundle-%s" [ label="%s", shape="septagon"];\n''' \ + viz_str += '''\t"bundle-%s" [ label="%s", shape="septagon"];\n''' \ % (bundle, bundle) gseen = [] for group in egroups: diff --git a/src/lib/Server/Plugins/NagiosGen.py b/src/lib/Server/Plugins/NagiosGen.py index 8ea0a1547..82326b760 100644 --- a/src/lib/Server/Plugins/NagiosGen.py +++ b/src/lib/Server/Plugins/NagiosGen.py @@ -1,6 +1,11 @@ '''This module implements a Nagios configuration generator''' -import re, os, glob, socket, logging +import glob +import logging +import os +import re +import socket + import Bcfg2.Server.Plugin LOGGER = logging.getLogger('Bcfg2.Plugins.NagiosGen') @@ -20,16 +25,16 @@ class NagiosGen(Bcfg2.Server.Plugin.Plugin, name = 'NagiosGen' __version__ = '0.6' __author__ = 'bcfg-dev@mcs.anl.gov' - + def __init__(self, core, datastore): Bcfg2.Server.Plugin.Plugin.__init__(self, core, datastore) Bcfg2.Server.Plugin.Generator.__init__(self) self.Entries = {'ConfigFile': {'/etc/nagiosgen.status' : self.createhostconfig, '/etc/nagios/nagiosgen.cfg': self.createserverconfig}} - + self.client_attrib = {'encoding': 'ascii', 'owner':'root', \ - 'group':'root', 'perms':'0400'} + 'group':'root', 'perms':'0400'} self.server_attrib = {'encoding': 'ascii', 'owner':'nagios', \ 'group':'nagios', 'perms':'0440'} @@ -39,7 +44,7 @@ class NagiosGen(Bcfg2.Server.Plugin.Plugin, host_groups = [grp for grp in metadata.groups if \ os.path.isfile('%s/%s-group.cfg' % (self.data, grp))] host_config = host_config_fmt % \ - (metadata.hostname, metadata.hostname, host_address ) + (metadata.hostname, metadata.hostname, host_address) if host_groups: host_config += ' hostgroups %s\n' % (",".join(host_groups)) @@ -48,9 +53,9 @@ class NagiosGen(Bcfg2.Server.Plugin.Plugin, 'NagiosGen.xml' in metadata.Properties and \ metadata.Properties['NagiosGen.xml'].data.find(metadata.hostname) \ is not None: - directives = list (metadata.Properties['NagiosGen.xml'].data.find(metadata.hostname)) + directives = list(metadata.Properties['NagiosGen.xml'].data.find(metadata.hostname)) for item in directives: - host_config += ' %-32s %s\n' % ( item.tag, item.text ) + host_config += ' %-32s %s\n' % (item.tag, item.text) else: host_config += ' use default\n' @@ -58,17 +63,17 @@ class NagiosGen(Bcfg2.Server.Plugin.Plugin, host_config += '}\n' entry.text = host_config [entry.attrib.__setitem__(key, value) for \ - (key, value) in self.client_attrib.iteritems()] + (key, value) in self.client_attrib.iteritems()] try: - fileh = open( "%s/%s-host.cfg" % \ - (self.data, metadata.hostname), 'w' ) + fileh = open("%s/%s-host.cfg" % \ + (self.data, metadata.hostname), 'w') fileh.write(host_config) fileh.close() except OSError, ioerr: LOGGER.error("Failed to write %s/%s-host.cfg" % \ (self.data, metadata.hostname)) LOGGER.error(ioerr) - + def createserverconfig(self, entry, _): '''Build monolithic server configuration file''' host_configs = glob.glob('%s/*-host.cfg' % self.data) @@ -76,20 +81,20 @@ class NagiosGen(Bcfg2.Server.Plugin.Plugin, host_data = "" group_data = "" for host in host_configs: - hostfile = open( host, 'r' ) + hostfile = open(host, 'r') host_data += hostfile.read() hostfile.close() for group in group_configs: group_name = re.sub("(-group.cfg|.*/(?=[^/]+))", "", group) if host_data.find(group_name) != -1: - groupfile = open( group, 'r' ) + groupfile = open(group, 'r') group_data += groupfile.read() groupfile.close() entry.text = group_data + host_data [entry.attrib.__setitem__(key, value) for \ - (key, value) in self.server_attrib.iteritems()] + (key, value) in self.server_attrib.iteritems()] try: - fileh = open( "%s/nagiosgen.cfg" % (self.data), 'w' ) + fileh = open("%s/nagiosgen.cfg" % (self.data), 'w') fileh.write(group_data + host_data) fileh.close() except OSError, ioerr: diff --git a/src/lib/Server/Plugins/Ohai.py b/src/lib/Server/Plugins/Ohai.py index ea31b4460..b20218792 100644 --- a/src/lib/Server/Plugins/Ohai.py +++ b/src/lib/Server/Plugins/Ohai.py @@ -11,7 +11,7 @@ class OhaiCache(object): def __setitem__(self, item, value): self.cache[item] = json.loads(value) - file("%s/%s.json" % (self.dirname, item), 'w').write(value) + file("%s/%s.json" % (self.dirname, item), 'w').write(value) def __getitem__(self, item): if item not in self.cache: diff --git a/src/lib/Server/Plugins/POSIXCompat.py b/src/lib/Server/Plugins/POSIXCompat.py index d2e530407..4ea2c490c 100644 --- a/src/lib/Server/Plugins/POSIXCompat.py +++ b/src/lib/Server/Plugins/POSIXCompat.py @@ -15,6 +15,7 @@ COMPAT_DICT = {'configfile': 'ConfigFile', 'permissions': 'Permissions', 'symlink': 'SymLink'} + class POSIXCompat(Bcfg2.Server.Plugin.Plugin, Bcfg2.Server.Plugin.GoalValidator): name = 'POSIXCompat' diff --git a/src/lib/Server/Plugins/Packages.py b/src/lib/Server/Plugins/Packages.py index bf532ee50..7bc9d1e27 100644 --- a/src/lib/Server/Plugins/Packages.py +++ b/src/lib/Server/Plugins/Packages.py @@ -1,9 +1,17 @@ -import copy, gzip, lxml.etree, re, urllib2, logging -import os, cPickle -import Bcfg2.Server.Plugin, Bcfg2.Logger +import cPickle +import copy +import gzip +import logging +import lxml.etree +import os +import re +import urllib2 + +import Bcfg2.Logger +import Bcfg2.Server.Plugin # build sources.list? -# caching for yum +# caching for yum class NoData(Exception): pass @@ -86,7 +94,7 @@ class Source(object): def read_files(self): pass - + def update(self): for url in self.urls: logger.info("Packages: Updating %s" % url) @@ -102,7 +110,7 @@ class Source(object): def applies(self, metadata): return len([g for g in self.basegroups if g in metadata.groups]) != 0 and \ len([g for g in metadata.groups if g in self.groups]) \ - == len(self.groups) + == len(self.groups) def get_arches(self, metadata): return ['global'] + [a for a in self.arches if a in metadata.groups] @@ -219,7 +227,7 @@ class YUMSource(Source): fl = '{http://linux.duke.edu/metadata/filelists}' basegroups = ['redhat', 'centos'] ptype = 'yum' - + def __init__(self, basepath, url, version, arches, components, groups, rawurl): Source.__init__(self, basepath, url, version, arches, components, groups, rawurl) @@ -294,7 +302,7 @@ class YUMSource(Source): continue self.packages[key] = self.packages['global'].difference(self.packages[key]) self.save_state() - + def parse_filelist(self, data, arch): for pkg in data.findall(self.fl + 'package'): for fentry in [fe for fe in pkg.findall(self.fl + 'file') \ @@ -325,7 +333,7 @@ class YUMSource(Source): if entry.get('name').startswith('/'): self.needed_paths.add(entry.get('name')) pro = pdata.find(self.rp + 'provides') - if pro != None: + if pro != None: for entry in pro.getchildren(): prov = entry.get('name') if prov not in self.provides[arch]: @@ -343,7 +351,7 @@ class YUMSource(Source): arches = [a for a in self.arches if a in metadata.groups] if not arches: raise NoData - if required in self.provides['global']: + if required in self.provides['global']: ret.update(Source.get_provides(self, metadata, required)) elif required in self.provides[arches[0]]: ret.update(Source.get_provides(self, metadata, required)) @@ -363,7 +371,7 @@ class YUMSource(Source): class APTSource(Source): basegroups = ['debian', 'ubuntu', 'nexenta'] ptype = 'deb' - + def __init__(self, basepath, url, version, arches, components, groups, rawurl): Source.__init__(self, basepath, url, version, arches, components, groups, rawurl) self.cachefile = self.escape_url(self.url) + '.data' @@ -478,7 +486,7 @@ class Packages(Bcfg2.Server.Plugin.Plugin, name = 'Packages' experimental = True __rmi__ = ['Refresh'] - + def __init__(self, core, datastore): Bcfg2.Server.Plugin.Plugin.__init__(self, core, datastore) Bcfg2.Server.Plugin.StructureValidator.__init__(self) @@ -517,7 +525,7 @@ class Packages(Bcfg2.Server.Plugin.Plugin, entry.set('version', 'auto') for source in self.sources: if [x for x in metadata.groups if x in source.basegroups]: - entry.set('type', source.ptype) + entry.set('type', source.ptype) def complete(self, meta, packages, debug=False): '''Build the transitive closure of all package dependencies diff --git a/src/lib/Server/Plugins/Pkgmgr.py b/src/lib/Server/Plugins/Pkgmgr.py index e154c4449..7c334bea7 100644 --- a/src/lib/Server/Plugins/Pkgmgr.py +++ b/src/lib/Server/Plugins/Pkgmgr.py @@ -147,7 +147,7 @@ class Pkgmgr(Bcfg2.Server.Plugin.PrioDir): [entry.remove(inst) for inst in \ entry.findall('Instance') \ if inst.get('arch') not in arches] - + def HandlesEntry(self, entry, metadata): return entry.tag == 'Package' and entry.get('name').split(':')[0] in self.Entries['Package'].keys() diff --git a/src/lib/Server/Plugins/Probes.py b/src/lib/Server/Plugins/Probes.py index edfee0884..42ae2fe37 100644 --- a/src/lib/Server/Plugins/Probes.py +++ b/src/lib/Server/Plugins/Probes.py @@ -1,4 +1,7 @@ -import Bcfg2.Server.Plugin, lxml.etree, re +import lxml.etree +import re + +import Bcfg2.Server.Plugin specific_probe_matcher = re.compile("(.*/)?(?P<basename>\S+)(.(?P<mode>[GH])_\S+)") probe_matcher = re.compile("(.*/)?(?P<basename>\S+)") @@ -22,7 +25,7 @@ class ProbeSet(Bcfg2.Server.Plugin.EntrySet): ret = [] build = dict() candidates = self.get_matching(metadata) - candidates.sort(lambda x,y: cmp(x.specific, y.specific)) + candidates.sort(lambda x, y: cmp(x.specific, y.specific)) for entry in candidates: rem = specific_probe_matcher.match(entry.name) if not rem: @@ -30,7 +33,7 @@ class ProbeSet(Bcfg2.Server.Plugin.EntrySet): pname = rem.group('basename') if pname not in build: build[pname] = entry - + for (name, entry) in build.iteritems(): probe = lxml.etree.Element('probe') probe.set('name', name.split('/')[-1]) @@ -55,7 +58,7 @@ class Probes(Bcfg2.Server.Plugin.Plugin, Bcfg2.Server.Plugin.Plugin.__init__(self, core, datastore) Bcfg2.Server.Plugin.Connector.__init__(self) Bcfg2.Server.Plugin.Probing.__init__(self) - + try: self.probes = ProbeSet(self.data, core.fam, core.encoding, self.name) @@ -65,7 +68,7 @@ class Probes(Bcfg2.Server.Plugin.Plugin, self.probedata = dict() self.cgroups = dict() self.load_data() - + def write_data(self): '''write probe data out for use with bcfg2-info''' top = lxml.etree.Element("Probed") @@ -125,7 +128,7 @@ class Probes(Bcfg2.Server.Plugin.Plugin, self.probedata[client.hostname] = {data.get('name'): ''} return dlines = data.text.split('\n') - self.logger.debug("%s:probe:%s:%s" % (client.hostname, + self.logger.debug("%s:probe:%s:%s" % (client.hostname, data.get('name'), [line.strip() for line in dlines])) for line in dlines[:]: if line.split(':')[0] == 'group': @@ -135,9 +138,9 @@ class Probes(Bcfg2.Server.Plugin.Plugin, dlines.remove(line) dtext = "\n".join(dlines) try: - self.probedata[client.hostname].update({ data.get('name'):dtext }) + self.probedata[client.hostname].update({data.get('name'):dtext}) except KeyError: - self.probedata[client.hostname] = { data.get('name'):dtext } + self.probedata[client.hostname] = {data.get('name'):dtext} def get_additional_groups(self, meta): return self.cgroups.get(meta.hostname, list()) diff --git a/src/lib/Server/Plugins/Properties.py b/src/lib/Server/Plugins/Properties.py index 498b496ac..fe3b077d5 100644 --- a/src/lib/Server/Plugins/Properties.py +++ b/src/lib/Server/Plugins/Properties.py @@ -1,8 +1,12 @@ -import copy, lxml.etree +import copy +import lxml.etree + import Bcfg2.Server.Plugin + class PropertyFile(Bcfg2.Server.Plugin.XMLFileBacked): '''Class for properties files''' + def Index(self): '''Build data into an xml object''' try: @@ -10,12 +14,17 @@ class PropertyFile(Bcfg2.Server.Plugin.XMLFileBacked): except lxml.etree.XMLSyntaxError: Bcfg2.Server.Plugin.logger.error("Failed to parse %s" % self.name) + class PropDirectoryBacked(Bcfg2.Server.Plugin.DirectoryBacked): __child__ = PropertyFile + class Properties(Bcfg2.Server.Plugin.Plugin, Bcfg2.Server.Plugin.Connector): - '''The properties plugin maps property files into client metadata instances''' + ''' + The properties plugin maps property + files into client metadata instances + ''' name = 'Properties' version = '$Revision$' experimental = True diff --git a/src/lib/Server/Plugins/Rules.py b/src/lib/Server/Plugins/Rules.py index b23a52980..bd0850c49 100644 --- a/src/lib/Server/Plugins/Rules.py +++ b/src/lib/Server/Plugins/Rules.py @@ -3,6 +3,7 @@ __revision__ = '$Revision$' import Bcfg2.Server.Plugin + class Rules(Bcfg2.Server.Plugin.PrioDir): '''This is a generator that handles service assignments''' name = 'Rules' diff --git a/src/lib/Server/Plugins/SGenshi.py b/src/lib/Server/Plugins/SGenshi.py index 6c06a25d0..6f17e5ede 100644 --- a/src/lib/Server/Plugins/SGenshi.py +++ b/src/lib/Server/Plugins/SGenshi.py @@ -1,13 +1,18 @@ '''This module implements a templating generator based on Genshi''' __revision__ = '$Revision$' -import Bcfg2.Server.Plugin, Bcfg2.Server.Plugins.TGenshi -import lxml.etree, logging import genshi.template +import lxml.etree +import logging + +import Bcfg2.Server.Plugin +import Bcfg2.Server.Plugins.TGenshi logger = logging.getLogger('Bcfg2.Plugins.SGenshi') + class SGenshiTemplateFile(Bcfg2.Server.Plugins.TGenshi.TemplateFile): + def get_xml_value(self, metadata): if not hasattr(self, 'template'): logger.error("No parsed template information for %s" % (self.name)) @@ -17,10 +22,12 @@ class SGenshiTemplateFile(Bcfg2.Server.Plugins.TGenshi.TemplateFile): data = stream.render('xml', strip_whitespace=False) return lxml.etree.XML(data) + class SGenshiEntrySet(Bcfg2.Server.Plugin.EntrySet): + def __init__(self, path, fam, encoding): fpattern = '\S+\.xml' - Bcfg2.Server.Plugin.EntrySet.__init__(self, fpattern, path, + Bcfg2.Server.Plugin.EntrySet.__init__(self, fpattern, path, SGenshiTemplateFile, encoding) fam.AddMonitor(path, self) @@ -40,6 +47,7 @@ class SGenshiEntrySet(Bcfg2.Server.Plugin.EntrySet): logger.error("SGenshi: Failed to template file %s" % entry.name) return ret + class SGenshi(SGenshiEntrySet, Bcfg2.Server.Plugin.Plugin, Bcfg2.Server.Plugin.Structure): @@ -58,5 +66,3 @@ class SGenshi(SGenshiEntrySet, logger.error("Failed to load %s repository; disabling %s" \ % (self.name, self.name)) raise Bcfg2.Server.Plugin.PluginInitError - - diff --git a/src/lib/Server/Plugins/SSHbase.py b/src/lib/Server/Plugins/SSHbase.py index 388cc53fc..a3690a05a 100644 --- a/src/lib/Server/Plugins/SSHbase.py +++ b/src/lib/Server/Plugins/SSHbase.py @@ -8,6 +8,7 @@ import tempfile from subprocess import Popen, PIPE import Bcfg2.Server.Plugin + class SSHbase(Bcfg2.Server.Plugin.Plugin, Bcfg2.Server.Plugin.Generator, Bcfg2.Server.Plugin.DirectoryBacked, @@ -54,13 +55,13 @@ class SSHbase(Bcfg2.Server.Plugin.Plugin, self.logger.error(ioerr) raise Bcfg2.Server.Plugin.PluginInitError self.Entries = {'ConfigFile': - {'/etc/ssh/ssh_known_hosts':self.build_skn, - '/etc/ssh/ssh_host_dsa_key':self.build_hk, - '/etc/ssh/ssh_host_rsa_key':self.build_hk, - '/etc/ssh/ssh_host_dsa_key.pub':self.build_hk, - '/etc/ssh/ssh_host_rsa_key.pub':self.build_hk, - '/etc/ssh/ssh_host_key':self.build_hk, - '/etc/ssh/ssh_host_key.pub':self.build_hk}} + {'/etc/ssh/ssh_known_hosts': self.build_skn, + '/etc/ssh/ssh_host_dsa_key': self.build_hk, + '/etc/ssh/ssh_host_rsa_key': self.build_hk, + '/etc/ssh/ssh_host_dsa_key.pub': self.build_hk, + '/etc/ssh/ssh_host_rsa_key.pub': self.build_hk, + '/etc/ssh/ssh_host_key': self.build_hk, + '/etc/ssh/ssh_host_key.pub': self.build_hk}} self.ipcache = {} self.__skn = False @@ -209,7 +210,7 @@ class SSHbase(Bcfg2.Server.Plugin.Plugin, "H_%s" % client]) tempdir = tempfile.mkdtemp() temploc = "%s/%s" % (tempdir, hostkey) - cmd = 'ssh-keygen -q -f %s -N "" -t %s -C root@%s < /dev/null' + cmd = 'ssh-keygen -q -f %s -N "" -t %s -C root@%s < /dev/null' os.system(cmd % (temploc, keytype, client)) open(fileloc, 'w').write(open(temploc).read()) open(publoc, 'w').write(open("%s.pub" % temploc).read()) diff --git a/src/lib/Server/Plugins/Snapshots.py b/src/lib/Server/Plugins/Snapshots.py index 3b2949e7a..871d77b68 100644 --- a/src/lib/Server/Plugins/Snapshots.py +++ b/src/lib/Server/Plugins/Snapshots.py @@ -15,6 +15,7 @@ datafields = {'Package': ['version'], 'Service': ['status'], 'ConfigFile': ['owner', 'group', 'perms']} + def build_snap_ent(entry): basefields = [] if entry.tag in ['Package', 'Service']: @@ -39,17 +40,19 @@ def build_snap_ent(entry): diff = binascii.a2b_base64(entry.get('current_bdiff')) state['contents'] = unicode( \ '\n'.join(difflib.restore(diff.split('\n'), 1))) - + state.update([(key, unicode(entry.get('current_' + key, entry.get(key)))) \ for key in datafields[entry.tag]]) if entry.tag == 'ConfigFile' and entry.get('exists', 'true') == 'false': state = None return [desired, state] + class Snapshots(Bcfg2.Server.Plugin.Statistics, Bcfg2.Server.Plugin.Plugin): name = 'Snapshots' experimental = True + def __init__(self, core, datastore): Bcfg2.Server.Plugin.Plugin.__init__(self, core, datastore) Bcfg2.Server.Plugin.Statistics.__init__(self) diff --git a/src/lib/Server/Plugins/Statistics.py b/src/lib/Server/Plugins/Statistics.py index 90860e3e4..492e06e9c 100644 --- a/src/lib/Server/Plugins/Statistics.py +++ b/src/lib/Server/Plugins/Statistics.py @@ -1,13 +1,18 @@ '''This file manages the statistics collected by the BCFG2 Server''' __revision__ = '$Revision$' +import binascii +import copy +import difflib +import logging from lxml.etree import XML, SubElement, Element, XMLSyntaxError +import lxml.etree +import os from time import asctime, localtime, time, strptime, mktime -import binascii, difflib, logging, lxml.etree, os, copy - import Bcfg2.Server.Plugin + class StatisticsStore(object): '''Manages the memory and file copy of statistics collected about client runs''' __min_write_delay__ = 0 @@ -23,7 +28,7 @@ class StatisticsStore(object): def WriteBack(self, force=0): '''Write statistics changes back to persistent store''' # FIXME switch to a thread writer - if (self.dirty and (self.lastwrite + self.__min_write_delay__ <= time()) ) \ + if (self.dirty and (self.lastwrite + self.__min_write_delay__ <= time())) \ or force: try: fout = open(self.filename + '.new', 'w') @@ -53,11 +58,11 @@ class StatisticsStore(object): def updateStats(self, xml, client): '''Updates the statistics of a current node with new data''' - # Current policy: + # Current policy: # - Keep anything less than 24 hours old # - Keep latest clean run for clean nodes # - Keep latest clean and dirty run for dirty nodes - newstat = xml.find('Statistics') + newstat = xml.find('Statistics') if newstat.get('state') == 'clean': node_dirty = 0 @@ -98,7 +103,6 @@ class StatisticsStore(object): self.dirty = 1 self.WriteBack(force=1) - def isOlderThan24h(self, testTime): '''Helper function to determine if <time> string is older than 24 hours''' now = time() @@ -107,6 +111,7 @@ class StatisticsStore(object): return (now-utime) > secondsPerDay + class Statistics(Bcfg2.Server.Plugin.Plugin, Bcfg2.Server.Plugin.Statistics, Bcfg2.Server.Plugin.PullSource): @@ -129,7 +134,7 @@ class Statistics(Bcfg2.Server.Plugin.Plugin, in rt.findall('Statistics')]) return [stat for stat in rt.findall('Statistics') \ if strptime(stat.get('time')) == maxtime][0] - + def GetExtra(self, client): return [(entry.tag, entry.get('name')) for entry \ in self.FindCurrent(client).xpath('.//Extra/*')] diff --git a/src/lib/Server/Plugins/Svcmgr.py b/src/lib/Server/Plugins/Svcmgr.py index ab951be35..396c5145c 100644 --- a/src/lib/Server/Plugins/Svcmgr.py +++ b/src/lib/Server/Plugins/Svcmgr.py @@ -3,6 +3,7 @@ __revision__ = '$Revision$' import Bcfg2.Server.Plugin + class Svcmgr(Bcfg2.Server.Plugin.PrioDir): '''This is a generator that handles service assignments''' name = 'Svcmgr' diff --git a/src/lib/Server/Plugins/Svn.py b/src/lib/Server/Plugins/Svn.py index d8fd70ead..db90fff3b 100644 --- a/src/lib/Server/Plugins/Svn.py +++ b/src/lib/Server/Plugins/Svn.py @@ -6,6 +6,7 @@ import Bcfg2.Server.Plugin import logging logger = logging.getLogger('Bcfg2.Plugins.Svn') + class Svn(Bcfg2.Server.Plugin.Plugin, Bcfg2.Server.Plugin.Version): name = 'Svn' @@ -42,4 +43,3 @@ class Svn(Bcfg2.Server.Plugin.Plugin, logger.error('''Ran command "svn info %s"''' % (self.datastore)) logger.error("Got output: %s" % data) raise Bcfg2.Server.Plugin.PluginInitError - diff --git a/src/lib/Server/Plugins/TCheetah.py b/src/lib/Server/Plugins/TCheetah.py index 87358684c..9988b80e4 100644 --- a/src/lib/Server/Plugins/TCheetah.py +++ b/src/lib/Server/Plugins/TCheetah.py @@ -15,15 +15,17 @@ except: logger.error("TCheetah: Failed to import Cheetah. Is it installed?") raise + class TemplateFile: '''Template file creates Cheetah template structures for the loaded file''' + def __init__(self, name, specific, encoding): self.name = name self.specific = specific self.encoding = encoding self.template = None self.searchlist = dict() - + def handle_event(self, event): '''Handle all fs events for this template''' if event.code2str() == 'deleted': @@ -36,7 +38,7 @@ class TemplateFile: except Cheetah.Parser.ParseError, perror: logger.error("Cheetah parse error for file %s" % (self.name)) logger.error(perror.report()) - + def bind_entry(self, entry, metadata): '''Build literal file information''' self.template.metadata = metadata @@ -45,11 +47,11 @@ class TemplateFile: self.searchlist['path'] = entry.get('realname', entry.get('name')) self.template.source_path = self.name self.searchlist['source_path'] = self.name - + try: if type(self.template) == unicode: entry.text = self.template - else : + else: entry.text = unicode(str(self.template), self.encoding) except: (a, b, c) = sys.exc_info() diff --git a/src/lib/Server/Plugins/TGenshi.py b/src/lib/Server/Plugins/TGenshi.py index 4bec8b2f1..b38bdfb0b 100644 --- a/src/lib/Server/Plugins/TGenshi.py +++ b/src/lib/Server/Plugins/TGenshi.py @@ -10,10 +10,12 @@ except: have_ntt = False import logging import Bcfg2.Server.Plugin -import genshi.core, genshi.input +import genshi.core +import genshi.input logger = logging.getLogger('Bcfg2.Plugins.TGenshi') + def removecomment(stream): """A genshi filter that removes comments from the stream.""" for kind, data, pos in stream: @@ -21,8 +23,10 @@ def removecomment(stream): continue yield kind, data, pos + class TemplateFile: '''Template file creates Genshi template structures for the loaded file''' + def __init__(self, name, specific, encoding): self.name = name self.specific = specific @@ -43,7 +47,7 @@ class TemplateFile: else: self.template_cls = MarkupTemplate self.HandleEvent = self.handle_event - + def handle_event(self, event=None): '''Handle all fs events for this template''' if event and event.code2str() == 'deleted': @@ -59,7 +63,7 @@ class TemplateFile: logger.error('Genshi template error: %s' % terror) except genshi.input.ParseError, perror: logger.error('Genshi parse error: %s' % perror) - + def bind_entry(self, entry, metadata): '''Build literal file information''' fname = entry.get('realname', entry.get('name')) @@ -96,6 +100,7 @@ class TemplateFile: logger.error('Genshi template loading error: %s' % err) raise Bcfg2.Server.Plugin.PluginExecutionError + class TGenshi(Bcfg2.Server.Plugin.GroupSpool): ''' The TGenshi generator implements a templating diff --git a/src/lib/Server/Plugins/Trigger.py b/src/lib/Server/Plugins/Trigger.py index d73e143ee..b45743134 100644 --- a/src/lib/Server/Plugins/Trigger.py +++ b/src/lib/Server/Plugins/Trigger.py @@ -1,6 +1,7 @@ import os import Bcfg2.Server.Plugin + def async_run(prog, args): pid = os.fork() if pid: @@ -11,6 +12,7 @@ def async_run(prog, args): os.system(" ".join([prog] + args)) os._exit(0) + class Trigger(Bcfg2.Server.Plugin.Plugin, Bcfg2.Server.Plugin.Statistics): name = 'Trigger' |