From b35d708ea1e56a8d79b2f4e5651c57ebc99e7f8d Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Wed, 11 Jul 2012 10:48:44 -0400 Subject: added feature to allow clients to declare their version to server --- src/lib/Bcfg2/Server/Core.py | 89 ++++++++++++++++++++++++-------------------- 1 file changed, 49 insertions(+), 40 deletions(-) (limited to 'src/lib/Bcfg2/Server/Core.py') diff --git a/src/lib/Bcfg2/Server/Core.py b/src/lib/Bcfg2/Server/Core.py index e8ebd511d..6dbab64bd 100644 --- a/src/lib/Bcfg2/Server/Core.py +++ b/src/lib/Bcfg2/Server/Core.py @@ -30,7 +30,7 @@ logger = logging.getLogger('Bcfg2.Server.Core') def critical_error(operation): """Log and err, traceback and return an xmlrpc fault to client.""" logger.error(operation, exc_info=1) - raise xmlrpclib.Fault(7, "Critical unexpected failure: %s" % (operation)) + raise xmlrpclib.Fault(xmlrpclib.APPLICATION_ERROR, "Critical unexpected failure: %s" % (operation)) try: import psyco @@ -413,98 +413,108 @@ class Core(Component): state.get('state'))) self.client_run_hook("end_statistics", meta) + def resolve_client(self, address, cleanup_cache=False, metadata=True): + try: + client = self.metadata.resolve_client(address, + cleanup_cache=cleanup_cache) + if metadata: + meta = self.build_metadata(client) + else: + meta = None + except Bcfg2.Server.Plugins.Metadata.MetadataConsistencyError: + critical_error("Client metadata resolution error for %s; " + "check server log" % address[0]) + except Bcfg2.Server.Plugins.Metadata.MetadataRuntimeError: + critical_error('Metadata system runtime failure') + return (client, meta) + # XMLRPC handlers start here + @exposed + def DeclareVersion(self, address, version): + """ declare the client version """ + client, metadata = self.resolve_client(address) + try: + self.metadata.set_version(client, version) + except (Bcfg2.Server.Plugins.Metadata.MetadataConsistencyError, + Bcfg2.Server.Plugins.Metadata.MetadataRuntimeError): + err = sys.exc_info()[1] + critical_error("Unable to set version for %s: %s" % + (client, err)) + return True + @exposed def GetProbes(self, address): """Fetch probes for a particular client.""" resp = lxml.etree.Element('probes') + client, metadata = self.resolve_client(address, cleanup_cache=True) try: - name = self.metadata.resolve_client(address, cleanup_cache=True) - meta = self.build_metadata(name) - for plugin in self.plugins_by_type(Bcfg2.Server.Plugin.Probing): - for probe in plugin.GetProbes(meta): + for probe in plugin.GetProbes(metadata): resp.append(probe) return lxml.etree.tostring(resp, encoding='UTF-8', xml_declaration=True) - except Bcfg2.Server.Plugins.Metadata.MetadataConsistencyError: - warning = 'Client metadata resolution error for %s' % address[0] - self.logger.warning(warning) - raise xmlrpclib.Fault(6, warning + "; check server log") - except Bcfg2.Server.Plugins.Metadata.MetadataRuntimeError: - err_msg = 'Metadata system runtime failure' - self.logger.error(err_msg) - raise xmlrpclib.Fault(6, err_msg) except: - critical_error("Error determining client probes") + critical_error("Error determining probes for %s" % client) @exposed def RecvProbeData(self, address, probedata): """Receive probe data from clients.""" - try: - name = self.metadata.resolve_client(address) - meta = self.build_metadata(name) - except Bcfg2.Server.Plugins.Metadata.MetadataConsistencyError: - warning = 'Metadata consistency error' - self.logger.warning(warning) - raise xmlrpclib.Fault(6, warning) + client, metadata = self.resolve_client(address) # clear dynamic groups - self.metadata.cgroups[meta.hostname] = [] + self.metadata.cgroups[metadata.hostname] = [] try: xpdata = lxml.etree.XML(probedata.encode('utf-8'), parser=Bcfg2.Server.XMLParser) except: - self.logger.error("Failed to parse probe data from client %s" % \ - (address[0])) - return False + critical_error("Failed to parse probe data from client %s" % + client) sources = [] [sources.append(data.get('source')) for data in xpdata if data.get('source') not in sources] for source in sources: if source not in self.plugins: - self.logger.warning("Failed to locate plugin %s" % (source)) + self.logger.warning("Failed to locate plugin %s" % source) continue dl = [data for data in xpdata if data.get('source') == source] try: - self.plugins[source].ReceiveData(meta, dl) + self.plugins[source].ReceiveData(metadata, dl) except: - logger.error("Failed to process probe data from client %s" % \ - (address[0]), exc_info=1) + critical_error("Failed to process probe data from client %s" % + client) return True @exposed def AssertProfile(self, address, profile): """Set profile for a client.""" + client = self.resolve_client(address, metadata=False)[0] try: - client = self.metadata.resolve_client(address) self.metadata.set_profile(client, profile, address) except (Bcfg2.Server.Plugins.Metadata.MetadataConsistencyError, Bcfg2.Server.Plugins.Metadata.MetadataRuntimeError): - warning = 'Metadata consistency error' - self.logger.warning(warning) - raise xmlrpclib.Fault(6, warning) + err = sys.exc_info()[1] + critical_error("Unable to assert profile for %s: %s" % + (client, err)) return True @exposed def GetConfig(self, address, checksum=False): """Build config for a client.""" + client = self.resolve_client(address)[0] try: - client = self.metadata.resolve_client(address) config = self.BuildConfiguration(client) return lxml.etree.tostring(config, encoding='UTF-8', xml_declaration=True) except Bcfg2.Server.Plugins.Metadata.MetadataConsistencyError: - self.logger.warning("Metadata consistency failure for %s" % (address)) - raise xmlrpclib.Fault(6, "Metadata consistency failure") + critical_error("Metadata consistency failure for %s" % client) @exposed def RecvStats(self, address, stats): """Act on statistics upload.""" + client = self.resolve_client(address)[0] sdata = lxml.etree.XML(stats.encode('utf-8'), parser=Bcfg2.Server.XMLParser) - client = self.metadata.resolve_client(address) self.process_statistics(client, sdata) return "" @@ -519,6 +529,5 @@ class Core(Component): @exposed def GetDecisionList(self, address, mode): """Get the data of the decision list.""" - client = self.metadata.resolve_client(address) - meta = self.build_metadata(client) - return self.GetDecisions(meta, mode) + client, metadata = self.resolve_client(address) + return self.GetDecisions(metadata, mode) -- cgit v1.2.3-1-g7c22