summaryrefslogtreecommitdiffstats
path: root/src/lib/Server/Plugin.py
diff options
context:
space:
mode:
authorNarayan Desai <desai@mcs.anl.gov>2006-04-10 20:01:43 +0000
committerNarayan Desai <desai@mcs.anl.gov>2006-04-10 20:01:43 +0000
commit4521ebcfcf106db5a67cf126bf94d0cd987cebc4 (patch)
tree6141b504a1885db71149af98ec8c9eea5e57853e /src/lib/Server/Plugin.py
parent9a2c22595a8261462ed17e7fc9df49cc4d7ba77f (diff)
downloadbcfg2-4521ebcfcf106db5a67cf126bf94d0cd987cebc4.tar.gz
bcfg2-4521ebcfcf106db5a67cf126bf94d0cd987cebc4.tar.bz2
bcfg2-4521ebcfcf106db5a67cf126bf94d0cd987cebc4.zip
* Fix schema validation for host specific service entries
* Move to using generic rule-based core (in preparation for the rules plugin) git-svn-id: https://svn.mcs.anl.gov/repos/bcfg/trunk/bcfg2@1827 ce84e21b-d406-0410-9b95-82705330c041
Diffstat (limited to 'src/lib/Server/Plugin.py')
-rw-r--r--src/lib/Server/Plugin.py77
1 files changed, 51 insertions, 26 deletions
diff --git a/src/lib/Server/Plugin.py b/src/lib/Server/Plugin.py
index 4c4406747..dad8bec46 100644
--- a/src/lib/Server/Plugin.py
+++ b/src/lib/Server/Plugin.py
@@ -191,13 +191,14 @@ class StructFile(XMLFileBacked):
logger.error("File %s got null match" % (self.name))
return []
-class LNode:
+class INode:
'''LNodes provide lists of things available at a particular group intersection'''
raw = {'Client':"lambda x:'%s' == x.hostname and predicate(x)",
'Group':"lambda x:'%s' in x.groups and predicate(x)"}
- __leaf__ = './Child'
+ containers = ['Group', 'Client']
+ ignore = []
- def __init__(self, data, plist, parent=None):
+ def __init__(self, data, idict, parent=None):
self.data = data
self.contents = {}
if parent == None:
@@ -209,30 +210,46 @@ class LNode:
else:
raise Exception
mytype = self.__class__
- self.children = [mytype(child, plist, self) for child in data.getchildren()
- if child.tag in ['Group', 'Client']]
- for leaf in data.findall(self.__leaf__):
- self.contents[leaf.get('name')] = leaf.attrib
- if leaf.get('name') not in plist:
- plist.append(leaf.get('name'))
+ self.children = []
+ for item in data.getchildren():
+ if item.tag in self.ignore:
+ continue
+ elif item.tag in self.containers:
+ self.children.append(mytype(item, idict, self))
+ else:
+ try:
+ self.contents[item.tag][item.get('name')] = item.attrib
+ except KeyError:
+ self.contents[item.tag] = {item.get('name'):item.attrib}
+ if item.text:
+ self.contents[item.tag]['__text__'] = item.text
+ try:
+ idict[item.tag].append(item.get('name'))
+ except KeyError:
+ idict[item.tag] = [item.get('name')]
def Match(self, metadata, data):
'''Return a dictionary of package mappings'''
if self.predicate(metadata):
- data.update(self.contents)
+ for key in self.contents:
+ try:
+ data[key].update(self.contents[key])
+ except:
+ data[key] = {}
+ data[key].update(self.contents[key])
for child in self.children:
child.Match(metadata, data)
class XMLSrc(XMLFileBacked):
'''XMLSrc files contain a LNode hierarchy that returns matching entries'''
- __node__ = LNode
+ __node__ = INode
def __init__(self, filename):
XMLFileBacked.__init__(self, filename)
- self.names = []
+ self.items = {}
self.cache = None
self.pnode = None
- self.priority = '1000'
+ self.priority = -1
def HandleEvent(self, event=None):
'''Read file upon update'''
@@ -241,15 +258,18 @@ class XMLSrc(XMLFileBacked):
except IOError:
logger.error("Failed to read file %s" % (self.name))
return
- self.names = []
+ self.items = {}
try:
xdata = lxml.etree.XML(data)
except lxml.etree.XMLSyntaxError:
logger.error("Failed to parse file %s" % (self.name))
return
- self.pnode = self.__node__(xdata, self.names)
+ self.pnode = self.__node__(xdata, self.items)
self.cache = None
- self.priority = xdata.get('priority')
+ try:
+ self.priority = int(xdata.get('priority'))
+ except:
+ logger.error("Got bogus priority %s for file %s" % (xdata.get('priority'), self.name))
del xdata, data
def Cache(self, metadata):
@@ -263,27 +283,29 @@ class XMLSrc(XMLFileBacked):
self.pnode.Match(metadata, cache[1])
self.cache = cache
-class XMLPrioDir(Plugin, DirectoryBacked):
+class PrioDir(Plugin, DirectoryBacked):
'''This is a generator that handles package assignments'''
- __name__ = 'XMLPrioDir'
+ __name__ = 'PrioDir'
__child__ = XMLSrc
- __element__ = 'Dummy'
def __init__(self, core, datastore):
Plugin.__init__(self, core, datastore)
- self.Entries[self.__element__] = {}
try:
DirectoryBacked.__init__(self, self.data, self.core.fam)
except OSError:
- self.logger.error("Failed to load %s indices" % (self.__element__.lower()))
+ self.logger.error("Failed to load %s indices" % (self.__name__))
raise PluginInitError
def HandleEvent(self, event):
'''Handle events and update dispatch table'''
DirectoryBacked.HandleEvent(self, event)
for src in self.entries.values():
- for child in src.names:
- self.Entries[self.__element__][child] = self.BindEntry
+ for itype, children in src.items.iteritems():
+ for child in children:
+ try:
+ self.Entries[itype][child] = self.BindEntry
+ except KeyError:
+ self.Entries[itype] = {child: self.BindEntry}
def BindEntry(self, entry, metadata):
'''Check package lists of package entries'''
@@ -293,7 +315,7 @@ class XMLPrioDir(Plugin, DirectoryBacked):
self.logger.error("Called before data loaded")
raise PluginExecutionError
matching = [src for src in self.entries.values()
- if src.cache[1].has_key(name)]
+ if src.cache[1].has_key(entry.tag) and src.cache[1][entry.tag].has_key(name)]
if len(matching) == 0:
raise PluginExecutionError
elif len(matching) == 1:
@@ -302,9 +324,12 @@ class XMLPrioDir(Plugin, DirectoryBacked):
prio = [int(src.priority) for src in matching]
if prio.count(max(prio)) > 1:
self.logger.error("Found conflicting %s sources with same priority for %s, pkg %s" %
- (self.__element__.lower(), metadata.hostname, entry.get('name')))
+ (entry.tag.lower(), metadata.hostname, entry.get('name')))
raise PluginExecutionError
index = prio.index(max(prio))
- data = matching[index].cache[1][name]
+ data = matching[index].cache[1][entry.tag][name]
[entry.attrib.__setitem__(key, data[key]) for key in data.keys()]
+ if data.has_key('__text__'):
+ del entry.attrib['__text__']
+ entry.text = data['__text__']