summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--schemas/deps.xsd52
-rw-r--r--src/lib/Server/Core.py5
-rw-r--r--src/lib/Server/Plugins/Deps.py92
-rw-r--r--src/sbin/bcfg2-repo-validate3
4 files changed, 151 insertions, 1 deletions
diff --git a/schemas/deps.xsd b/schemas/deps.xsd
new file mode 100644
index 000000000..19ec5af2d
--- /dev/null
+++ b/schemas/deps.xsd
@@ -0,0 +1,52 @@
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xml:lang="en">
+
+ <xsd:annotation>
+ <xsd:documentation>
+ dependency schema for bcfg2
+ Narayan Desai, Argonne National Laboratory
+ </xsd:documentation>
+ </xsd:annotation>
+
+ <xsd:complexType name='StructureEntry'>
+ <xsd:choice minOccurs='0' maxOccurs='unbounded'>
+ <xsd:element name='Package' type='StructureEntry'/>
+ <xsd:element name='Service' type='StructureEntry'/>
+ <xsd:element name='ConfigFile' type='StructureEntry'/>
+ <xsd:element name='Directory' type='StructureEntry'/>
+ <xsd:element name='SymLink' type='StructureEntry'/>
+ <xsd:element name='Permissions' type='StructureEntry'/>
+ <xsd:element name='PostInstall' type='StructureEntry'/>
+ </xsd:choice>
+ <xsd:attribute type='xsd:string' name='name' use='required'/>
+ </xsd:complexType>
+
+ <xsd:complexType name='GroupType'>
+ <xsd:choice minOccurs='0' maxOccurs='unbounded'>
+ <xsd:element name='Package' type='StructureEntry'/>
+ <xsd:element name='Service' type='StructureEntry'/>
+ <xsd:element name='ConfigFile' type='StructureEntry'/>
+ <xsd:element name='Directory' type='StructureEntry'/>
+ <xsd:element name='SymLink' type='StructureEntry'/>
+ <xsd:element name='Permissions' type='StructureEntry'/>
+ <xsd:element name='PostInstall' type='StructureEntry'/>
+ <xsd:element name='Group' type='GroupType'/>
+ </xsd:choice>
+ <xsd:attribute type='xsd:string' name='name' use='required'/>
+ </xsd:complexType>
+
+ <xsd:element name='Dependencies'>
+ <xsd:complexType>
+ <xsd:choice minOccurs='0' maxOccurs='unbounded'>
+ <xsd:element name='Package' type='StructureEntry'/>
+ <xsd:element name='Service' type='StructureEntry'/>
+ <xsd:element name='ConfigFile' type='StructureEntry'/>
+ <xsd:element name='Directory' type='StructureEntry'/>
+ <xsd:element name='SymLink' type='StructureEntry'/>
+ <xsd:element name='Permission' type='StructureEntry'/>
+ <xsd:element name='PostInstall' type='StructureEntry'/>
+ <xsd:element name='Group' type='GroupType'/>
+ </xsd:choice>
+ <xsd:attribute type='xsd:string' name='priority' use='required'/>
+ </xsd:complexType>
+ </xsd:element>
+</xsd:schema> \ No newline at end of file
diff --git a/src/lib/Server/Core.py b/src/lib/Server/Core.py
index e417f9aa0..6f11e83e7 100644
--- a/src/lib/Server/Core.py
+++ b/src/lib/Server/Core.py
@@ -293,6 +293,11 @@ class Core(object):
except:
logger.error("error in GetStructures", exc_info=1)
return lxml.etree.Element("error", type='structure error')
+
+ if self.plugins.has_key('Deps'):
+ # do prereq processing
+ prereqs = self.plugins['Deps'].GeneratePrereqs(structures, meta)
+ structures.append(prereqs)
for astruct in structures:
try:
diff --git a/src/lib/Server/Plugins/Deps.py b/src/lib/Server/Plugins/Deps.py
new file mode 100644
index 000000000..945c53e70
--- /dev/null
+++ b/src/lib/Server/Plugins/Deps.py
@@ -0,0 +1,92 @@
+'''This plugin provides automatic dependency handling'''
+__revision__ = '$Revision:$'
+
+import Bcfg2.Server.Plugin, lxml.etree
+
+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 = {}
+ if parent == None:
+ self.predicate = lambda x:True
+ else:
+ predicate = parent.predicate
+ if data.tag in self.raw.keys():
+ self.predicate = eval(self.raw[data.tag] % (data.get('name')), {'predicate':predicate})
+ else:
+ raise Exception
+ mytype = self.__class__
+ self.children = []
+ for item in data.getchildren():
+ if item.tag in self.containers:
+ self.children.append(mytype(item, idict, self))
+ else:
+ data = [(child.tag, child.get('name')) for child in item.getchildren()]
+ try:
+ self.contents[item.tag][item.get('name')] = data
+ except KeyError:
+ self.contents[item.tag] = {item.get('name'):data}
+
+class DepXMLSrc(Bcfg2.Server.Plugin.XMLSrc):
+ __node__ = DNode
+
+class Deps(Bcfg2.Server.Plugin.PrioDir):
+ __name__ = 'Deps'
+ __version__ = '$Id:$'
+ __author__ = 'bcfg-dev@mcs.anl.gov'
+ __child__ = DepXMLSrc
+
+ def __init__(self, core, datastore):
+ Bcfg2.Server.Plugin.PrioDir.__init__(self, core, datastore)
+ self.cache = {}
+
+ def HandleEvent(self, event):
+ self.cache = {}
+ Bcfg2.Server.Plugin.PrioDir.HandleEvent(self, event)
+
+ def GeneratePrereqs(self, structures, metadata):
+ entries = []
+ prereqs = []
+ for structure in structures:
+ for entry in structure.getchildren():
+ if (entry.tag, entry.get('name')) not in entries:
+ entries.append((entry.tag, entry.get('name')))
+ entries.sort()
+ entries = tuple(entries)
+ gdata = metadata.groups[:]
+ gdata.sort()
+ gdata = tuple(gdata)
+ if self.cache.has_key((entries, gdata)):
+ prereqs = self.cache[(entries, gdata)]
+ else:
+ [src.Cache(metadata) for src in self.entries.values()]
+
+ for entry in entries:
+ matching = [src for src in self.entries.values()
+ if src.cache and src.cache[1].has_key(entry[0])
+ and src.cache[1][entry[0]].has_key(entry[1])]
+ if len(matching) > 1:
+ 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" %
+ (entry[0].lower(), metadata.hostname, entry[1]))
+ raise PluginExecutionError
+ index = prio.index(max(prio))
+ matching = [matching[index]]
+
+ if not matching:
+ continue
+ elif len(matching) == 1:
+ for prq in src.cache[1][entry[0]][entry[1]]:
+ if prq not in prereqs:
+ prereqs.append(prq)
+ self.cache[(entries, gdata)] = prereqs
+
+ newstruct = lxml.etree.Element("Independant")
+ for tag, name in prereqs:
+ lxml.etree.SubElement(newstruct, tag, name=name)
+ return newstruct
diff --git a/src/sbin/bcfg2-repo-validate b/src/sbin/bcfg2-repo-validate
index 2ec7a20b4..360dbf45f 100644
--- a/src/sbin/bcfg2-repo-validate
+++ b/src/sbin/bcfg2-repo-validate
@@ -31,7 +31,8 @@ if __name__ == '__main__':
'base':("%s/Base/*.xml", "%s/base.xsd"),
'base':("%s/Rules/*.xml", "%s/rules.xsd"),
'imageinfo':("%s/etc/reports.xml", "%s/report-configuration.xsd"),
- 'services':("%s/Svcmgr/*.xml", "%s/services.xsd")}
+ 'services':("%s/Svcmgr/*.xml", "%s/services.xsd"),
+ 'deps':("%s/Deps/*.xml", "%s/deps.xsd")}
failures = 0
for k, (spec, schemaname) in filesets.iteritems():