From 4a9d1bac1d78239768a740a7dcc5ae83f8f3d114 Mon Sep 17 00:00:00 2001 From: Rick Bradshow Date: Tue, 22 Aug 2006 20:59:02 +0000 Subject: this is the inclusion of the hot new interpolation capabilities in the Cfg plugin. This includes a built in probe for hostname, and the capability for users to populate a directory of homemade script to be run as Probes. git-svn-id: https://svn.mcs.anl.gov/repos/bcfg/trunk/bcfg2@2089 ce84e21b-d406-0410-9b95-82705330c041 --- src/lib/Server/Plugins/Cfg.py | 52 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 47 insertions(+), 5 deletions(-) diff --git a/src/lib/Server/Plugins/Cfg.py b/src/lib/Server/Plugins/Cfg.py index b94f4f38a..b19fe8c6a 100644 --- a/src/lib/Server/Plugins/Cfg.py +++ b/src/lib/Server/Plugins/Cfg.py @@ -1,12 +1,13 @@ '''This module implements a config file repository''' __revision__ = '$Revision$' -import binascii, logging, os, re, stat, tempfile, Bcfg2.Server.Plugin +import binascii, logging, os, re, stat, tempfile, Bcfg2.Server.Plugin, lxml.etree logger = logging.getLogger('Bcfg2.Plugins.Cfg') specific = re.compile('(.*/)(?P[\S\-.]+)\.((H_(?P\S+))|' + '(G(?P\d+)_(?P\S+)))$') +probeData = {} class SpecificityError(Exception): '''Thrown in case of filename parse failure''' @@ -71,7 +72,7 @@ class ConfigFileEntry(object): all data for all clients.''' info = re.compile('^owner:(\s)*(?P\w+)|group:(\s)*(?P\w+)|' + 'perms:(\s)*(?P\w+)|encoding:(\s)*(?P\w+)|' + - '(?Pparanoid(\s)*)$') + '(?Pparanoid(\s)*)|interpolate:(\s)*(?P\w+)(\s)*$') def __init__(self, path, repopath): object.__init__(self) @@ -80,13 +81,17 @@ class ConfigFileEntry(object): self.fragments = [] self.metadata = {'encoding': 'ascii', 'owner':'root', 'group':'root', 'perms':'0644'} self.paranoid = False - + self.interpolate = False + def read_info(self): '''read in :info metadata''' + self.interpolate = False + self.paranoid = False filename = "%s/:info" % self.repopath for line in open(filename).readlines(): match = self.info.match(line) if not match: + logger.warning("Failed to match line: %s"%line) continue else: mgd = match.groupdict() @@ -100,9 +105,11 @@ class ConfigFileEntry(object): self.metadata['perms'] = mgd['perms'] if len(self.metadata['perms']) == 3: self.metadata['perms'] = "0%s" % (self.metadata['perms']) - elif mgd['paranoid']: + elif mgd['paranoid'] in ["True", "true"]: self.paranoid = True - + elif mgd['interpolate'] in ["True", "true"]: + self.interpolate = True + def AddEntry(self, name): '''add new file additions for a single cf file''' basename = name.split('/')[-1] @@ -196,6 +203,12 @@ class ConfigFileEntry(object): logger.error("Unknown delta type %s" % (delta.op)) [entry.attrib.__setitem__(key, value) for (key, value) in self.metadata.iteritems()] + if self.interpolate: + if metadata.hostname in probeData: + for name, value in probeData[metadata.hostname].iteritems(): + filedata = filedata.replace("@@%s@@"%name, value ) + else: + logger.warning("Cannot interpolate data for client: %s for config file: %s"% (metadata.hostname, basefile.name)) if self.paranoid: entry.attrib['paranoid'] = 'true' if entry.attrib['encoding'] == 'base64': @@ -223,9 +236,36 @@ class Cfg(Bcfg2.Server.Plugin.Plugin): self.famID = {} self.directories = [] self.AddDirectoryMonitor(self.data) + self.interpolate = False #this is true if any file in the repo needs to be interpolated. + self.probes = Bcfg2.Server.Plugin.DirectoryBacked(datastore + '/Probes', self.core.fam ) # eventually flush fam events here so that all entries built here # ready to go + def GetProbes(self, _): + '''Return a set of probes for execution on client''' + ret = [] + bangline = re.compile('^#!(?P(/\w+)+)$') + if self.interpolate: + for name, entry in self.probes.entries.iteritems(): + probe = lxml.etree.Element('probe') + probe.set('name', name ) + probe.set('source', 'Cfg') + probe.text = entry.data + match = bangline.match(entry.data.split('\n')[0]) + if match: + probe.set('interpreter', match.group('interpreter')) + ret.append(probe) + probe = lxml.etree.Element('probe') + probe.set('name', 'hostname') + probe.set('source', 'Cfg') + probe.text = '''/bin/hostname''' + ret.append(probe) + return ret + + def ReceiveData(self, client, data): + '''Receive probe results pertaining to client''' + probeData[client.hostname] = { data.get('name'):data.text } + def AddDirectoryMonitor(self, name): '''Add new directory to FAM structures''' if name not in self.directories: @@ -287,3 +327,5 @@ class Cfg(Bcfg2.Server.Plugin.Plugin): pass else: logger.error("Got unknown event %s %s:%s" % (action, event.requestID, event.filename)) + self.interpolate = len([entry for entry in self.entries.values() if entry.interpolate ]) > 0 + -- cgit v1.2.3-1-g7c22