diff options
Diffstat (limited to 'src/lib/Bcfg2/Server/Plugins/Metadata.py')
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/Metadata.py | 72 |
1 files changed, 48 insertions, 24 deletions
diff --git a/src/lib/Bcfg2/Server/Plugins/Metadata.py b/src/lib/Bcfg2/Server/Plugins/Metadata.py index 970126b80..77e433ab1 100644 --- a/src/lib/Bcfg2/Server/Plugins/Metadata.py +++ b/src/lib/Bcfg2/Server/Plugins/Metadata.py @@ -6,14 +6,13 @@ import copy import fcntl import lxml.etree import os -import os.path import socket import sys import time - +import Bcfg2.Server import Bcfg2.Server.FileMonitor import Bcfg2.Server.Plugin - +from Bcfg2.version import Bcfg2VersionInfo def locked(fd): """Aquire a lock on a file""" @@ -36,16 +35,20 @@ class MetadataRuntimeError(Exception): pass -class XMLMetadataConfig(Bcfg2.Server.Plugin.SingleXMLFileBacked): +class XMLMetadataConfig(Bcfg2.Server.Plugin.XMLFileBacked): """Handles xml config files and all XInclude statements""" def __init__(self, metadata, watch_clients, basefile): - Bcfg2.Server.Plugin.SingleXMLFileBacked.__init__(self, - os.path.join(metadata.data, - basefile), - metadata.core.fam) + # we tell XMLFileBacked _not_ to add a monitor for this + # file, because the main Metadata plugin has already added + # one. then we immediately set should_monitor to the proper + # value, so that XIinclude'd files get properly watched + fpath = os.path.join(metadata.data, basefile) + Bcfg2.Server.Plugin.XMLFileBacked.__init__(self, fpath, + fam=metadata.core.fam) + self.should_monitor = watch_clients self.metadata = metadata + self.fam = metadata.core.fam self.basefile = basefile - self.should_monitor = watch_clients self.data = None self.basedata = None self.basedir = metadata.data @@ -65,16 +68,11 @@ class XMLMetadataConfig(Bcfg2.Server.Plugin.SingleXMLFileBacked): raise MetadataRuntimeError return self.basedata - def add_monitor(self, fpath, fname): - """Add a fam monitor for an included file""" - if self.should_monitor: - self.metadata.core.fam.AddMonitor(fpath, self.metadata) - self.extras.append(fname) - def load_xml(self): """Load changes from XML""" try: - xdata = lxml.etree.parse(os.path.join(self.basedir, self.basefile)) + xdata = lxml.etree.parse(os.path.join(self.basedir, self.basefile), + parser=Bcfg2.Server.XMLParser) except lxml.etree.XMLSyntaxError: self.logger.error('Failed to parse %s' % self.basefile) return @@ -145,7 +143,8 @@ class XMLMetadataConfig(Bcfg2.Server.Plugin.SingleXMLFileBacked): for included in self.extras: try: xdata = lxml.etree.parse(os.path.join(self.basedir, - included)) + included), + parser=Bcfg2.Server.XMLParser) cli = xdata.xpath(xpath) if len(cli) > 0: return {'filename': os.path.join(self.basedir, @@ -172,8 +171,8 @@ class XMLMetadataConfig(Bcfg2.Server.Plugin.SingleXMLFileBacked): class ClientMetadata(object): """This object contains client metadata.""" - def __init__(self, client, profile, groups, bundles, - aliases, addresses, categories, uuid, password, query): + def __init__(self, client, profile, groups, bundles, aliases, addresses, + categories, uuid, password, version, query): self.hostname = client self.profile = profile self.bundles = bundles @@ -184,6 +183,11 @@ class ClientMetadata(object): self.uuid = uuid self.password = password self.connectors = [] + self.version = version + try: + self.version_info = Bcfg2VersionInfo(version) + except: + self.version_info = None self.query = query def inGroup(self, group): @@ -249,6 +253,7 @@ class Metadata(Bcfg2.Server.Plugin.Plugin, self.aliases = {} self.groups = {} self.cgroups = {} + self.versions = {} self.public = [] self.private = [] self.profiles = [] @@ -282,7 +287,8 @@ class Metadata(Bcfg2.Server.Plugin.Plugin, def get_groups(self): '''return groups xml tree''' - groups_tree = lxml.etree.parse(os.path.join(self.data, "groups.xml")) + groups_tree = lxml.etree.parse(os.path.join(self.data, "groups.xml"), + parser=Bcfg2.Server.XMLParser) root = groups_tree.getroot() return root @@ -412,6 +418,8 @@ class Metadata(Bcfg2.Server.Plugin.Plugin, self.floating.append(clname) if 'password' in client.attrib: self.passwords[clname] = client.get('password') + if 'version' in client.attrib: + self.versions[clname] = client.get('version') self.raliases[clname] = set() for alias in client.findall('Alias'): @@ -537,6 +545,20 @@ class Metadata(Bcfg2.Server.Plugin.Plugin, self.clients[client] = profile self.clients_xml.write() + def set_version(self, client, version): + """Set group parameter for provided client.""" + self.logger.info("Asserting client %s version to %s" % (client, version)) + if client in self.clients: + self.logger.info("Setting version on client %s to %s" % + (client, version)) + self.update_client(client, dict(version=version)) + else: + msg = "Cannot set version on non-existent client %s" % client + self.logger.error(msg) + raise MetadataConsistencyError(msg) + self.versions[client] = version + self.clients_xml.write() + def resolve_client(self, addresspair, cleanup_cache=False): """Lookup address locally or in DNS to get a hostname.""" if addresspair in self.session_cache: @@ -575,9 +597,9 @@ class Metadata(Bcfg2.Server.Plugin.Plugin, return self.aliases[cname] return cname except socket.herror: - warning = "address resolution error for %s" % (address) + warning = "address resolution error for %s" % address self.logger.warning(warning) - raise MetadataConsistencyError + raise MetadataConsistencyError(warning) def get_initial_metadata(self, client): """Return the metadata for a given client.""" @@ -599,6 +621,7 @@ class Metadata(Bcfg2.Server.Plugin.Plugin, [bundles, groups, categories] = self.groups[self.default] aliases = self.raliases.get(client, set()) addresses = self.raddresses.get(client, set()) + version = self.versions.get(client, None) newgroups = set(groups) newbundles = set(bundles) newcategories = {} @@ -622,7 +645,7 @@ class Metadata(Bcfg2.Server.Plugin.Plugin, [newgroups.add(g) for g in ngroups if g not in newgroups] newcategories.update(ncategories) return ClientMetadata(client, profile, newgroups, newbundles, aliases, - addresses, newcategories, uuid, password, + addresses, newcategories, uuid, password, version, self.query) def get_all_group_names(self): @@ -792,7 +815,8 @@ class Metadata(Bcfg2.Server.Plugin.Plugin, def include_group(group): return not only_client or group in clientmeta.groups - groups_tree = lxml.etree.parse(os.path.join(self.data, "groups.xml")) + groups_tree = lxml.etree.parse(os.path.join(self.data, "groups.xml"), + parser=Bcfg2.Server.XMLParser) try: groups_tree.xinclude() except lxml.etree.XIncludeError: |