summaryrefslogtreecommitdiffstats
path: root/src/lib/Bcfg2/Server/Plugins/Metadata.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/Bcfg2/Server/Plugins/Metadata.py')
-rw-r--r--src/lib/Bcfg2/Server/Plugins/Metadata.py72
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: