From edca0b698637c3fd0a70af7e4752a46afca938d3 Mon Sep 17 00:00:00 2001 From: Narayan Desai Date: Mon, 23 Jan 2006 22:35:40 +0000 Subject: last step of repo switches git-svn-id: https://svn.mcs.anl.gov/repos/bcfg/trunk/bcfg2@1716 ce84e21b-d406-0410-9b95-82705330c041 --- src/sbin/Bcfg2Server | 289 --------------------------------------------------- 1 file changed, 289 deletions(-) delete mode 100644 src/sbin/Bcfg2Server (limited to 'src/sbin/Bcfg2Server') diff --git a/src/sbin/Bcfg2Server b/src/sbin/Bcfg2Server deleted file mode 100644 index c1b93644b..000000000 --- a/src/sbin/Bcfg2Server +++ /dev/null @@ -1,289 +0,0 @@ -#!/usr/bin/env python - -'''The XML-RPC Bcfg2 Server''' -__revision__ = '$Revision:$' - -from getopt import getopt, GetoptError -from sys import argv, exc_info -from syslog import openlog, LOG_LOCAL0, syslog, LOG_INFO, LOG_ERR -from Bcfg2.Server.Core import Core, CoreInitError -from Bcfg2.Server.Metadata import MetadataConsistencyError -from Bcfg2.Server.Component import Component -from threading import Lock -from select import select, error as selecterror -from signal import signal, SIGINT, SIGTERM -from traceback import extract_tb -from xmlrpclib import Fault -from socket import gethostbyaddr, herror -from lxml.etree import XML, Element, tostring -from M2Crypto.SSL import SSLError - -import os, sys - -def daemonize(filename): - '''Do the double fork/setsession dance''' - # Fork once - if os.fork() != 0: - os._exit(0) - os.setsid() # Create new session - pid = os.fork() - if pid != 0: - pidfile = open(filename, "w") - pidfile.write("%i" % pid) - pidfile.close() - os._exit(0) - os.chdir("/") - os.umask(0) - - null = open("/dev/null", "w+") - - os.dup2(null.fileno(), sys.__stdin__.fileno()) - os.dup2(null.fileno(), sys.__stdout__.fileno()) - os.dup2(null.fileno(), sys.__stderr__.fileno()) - - -def critical_error(operation): - '''Print tracebacks in unexpected cases''' - syslog(LOG_ERR, "Traceback information (please include in any bug report):") - (ttype, value, trace) = exc_info() - for line in extract_tb(trace): - syslog(LOG_ERR, "File %s, line %i, in %s\n %s" % (line)) - syslog(LOG_ERR, "%s: %s" % (ttype, value)) - warning_error("An unexpected failure occurred in %s" % (operation) ) - raise Fault, (7, "Critical unexpected failure: %s" % (operation)) - -def fatal_error(message): - '''Signal a fatal error''' - syslog(LOG_ERR, "Fatal error: %s" % (message)) - raise SystemExit, 1 - -def warning_error(message): - '''Warn about a problem but continue''' - syslog(LOG_ERR,"Warning: %s\n" % (message)) - -def usage_error(message, opt, vopt, descs, argDescs): - '''Die because script was called the wrong way''' - print "Usage error: %s" % (message) - print_usage(opt, vopt, descs, argDescs) - raise SystemExit, 2 - -verboseMode = False - -def verbose(message): - '''Conditionally output information in verbose mode''' - global verboseMode - - if(verboseMode == True): - syslog(LOG_INFO, "%s" % (message)) - -def print_usage(opt, vopt, descs, argDescs): - print "Bcfg2Server usage:" - for arg in opt.iteritems(): - print " -%s\t\t\t%s" % (arg[0], descs[arg[0]]) - for arg in vopt.iteritems(): - print " -%s %s\t%s" % (arg[0], argDescs[arg[0]], descs[arg[0]]) - -def dgetopt(arglist, opt, vopt, descs, argDescs): - '''parse options into a dictionary''' - global verboseMode - - ret = {} - for optname in opt.values() + vopt.values(): - ret[optname] = False - - gstr = "".join(opt.keys()) + "".join([optionkey + ':' for optionkey in vopt.keys()]) - try: - ginfo = getopt(arglist, gstr) - except GetoptError, gerr: - usage_error(gerr, opt, vopt, descs, argDescs) - - for (gopt, garg) in ginfo[0]: - option = gopt[1:] - if opt.has_key(option): - ret[opt[option]] = True - else: - ret[vopt[option]] = garg - - if ret["help"] == True: - print_usage(opt, vopt, descs, argDescs) - raise SystemExit, 0 - - if ret["verbose"] == True: - verboseMode = True - - return ret - -class Bcfg2(Component): - """The Bcfg2 Server component providing XML-RPC access to Bcfg methods""" - __name__ = 'bcfg2' - __implementation__ = 'bcfg2' - - request_queue_size = 15 - - def __init__(self, setup): - Component.__init__(self, setup) - self.shut = False - # set shutdown handlers for sigint and sigterm - signal(SIGINT, self.start_shutdown) - signal(SIGTERM, self.start_shutdown) - try: - self.Core = Core(setup, setup['configfile']) - self.CoreLock = Lock() - except CoreInitError, msg: - fatal_error(msg) - - self.funcs.update({ - "GetConfig": self.Bcfg2GetConfig, - "GetProbes": self.Bcfg2GetProbes, - "RecvProbeData": self.Bcfg2RecvProbeData, - "RecvStats": self.Bcfg2RecvStats - }) - for plugin in self.Core.plugins.values(): - for method in plugin.__rmi__: - self.register_function(getattr(self.Core.plugins[plugin.__name__], method), - "%s.%s" % (plugin.__name__, method)) - - def get_request(self): - '''We need to do work between requests, so select with timeout instead of blocking in accept''' - rsockinfo = [] - famfd = self.Core.fam.fileno() - while self.socket not in rsockinfo: - if self.shut: - raise SSLError - try: - rsockinfo = select([self.socket, famfd], [], [], 15)[0] - except selecterror: - raise SSLError - - if famfd in rsockinfo: - self.Core.fam.Service() - if self.socket in rsockinfo: - # workaround for m2crypto 0.15 bug - self.socket.postConnectionCheck = None - return self.socket.accept() - - def serve_forever(self): - """Handle one request at a time until doomsday.""" - while not self.shut: - self.handle_request() - - def start_shutdown(self, signum, frame): - '''Shutdown on unexpected signals''' - self.shut = True - - def handle_error(self): - '''Catch error path for clean exit''' - return False - - def resolve_client(self, client): - try: - return gethostbyaddr(client)[0] - except herror: - warning = "host resolution error for %s" % (client) - warning_error(warning) - raise Fault, (5, warning) - - def Bcfg2GetProbes(self, address): - '''Fetch probes for a particular client''' - client = self.resolve_client(address[0]) - resp = Element('probes') - - try: - meta = self.Core.metadata.FetchMetadata(client) - - for generator in self.Core.generators: - for probe in generator.GetProbes(meta): - resp.append(probe) - return tostring(resp) - except MetadataConsistencyError: - warning = 'metadata consistency error' - warning_error(warning) - raise Fault, (6, warning) - except: - critical_error("determining client probes") - - - def Bcfg2RecvProbeData(self, address, probedata): - '''Receive probe data from clients''' - client = self.resolve_client(address[0]) - - for data in probedata: - try: - [generator] = [gen for gen in self.Core.generators if gen.__name__ == data.get('source')] - generator.ReceiveData(client, data) - except IndexError: - warning_error("Failed to locate plugin %s" % (data.get('source'))) - except: - critical_error("probe data receipt") - return True - - def Bcfg2GetConfig(self, address, image=False, profile=False): - '''Build config for a client''' - client = self.resolve_client(address[0]) - - if image and profile: - try: - self.Core.metadata.set_group(client, profile) - except MetadataConsistencyError: - warning = 'metadata consistency error' - warning_error(warning) - raise Fault, (6, warning) - return tostring(self.Core.BuildConfiguration(client)) - - def Bcfg2RecvStats(self, address, stats): - '''Act on statistics upload''' - sdata = XML(stats) - state = sdata.find(".//Statistics") - # Versioned stats to prevent tied client/server upgrade - if state.get('version') >= '2.0': - client = self.resolve_client(address[0]) - - # Update statistics - self.Core.stats.updateStats(sdata, client) - - verbose("Client %s reported state %s" % - (client, state.attrib['state'])) - return "" - -if __name__ == '__main__': - openlog("Bcfg2", 0, LOG_LOCAL0) - options = { - 'v':'verbose', - 'd':'debug', - 'h':'help' - } - doptions = { - 'D':'daemon', - 'c':'configfile', - 'C':'client' - } - - descriptions = { - 'v': "enable verbose output", - 'd': "enable debugging output", - 'D': "daemonise the server, storing PID", - 'c': "set the server's config file", - 'C': "always return the given client's config (debug only)", - 'h': "display this usage information" - } - - argDescriptions = { - 'D': " ", - 'c': "", - 'C': "" - } - - ssetup = dgetopt(argv[1:], options, doptions, - descriptions, argDescriptions) - if ssetup['daemon']: - daemonize(ssetup['daemon']) - if not ssetup['configfile']: - ssetup['configfile'] = '/etc/bcfg2.conf' - s = Bcfg2(ssetup) - while not s.shut: - try: - s.serve_forever() - except: - critical_error("service loop") - - syslog(LOG_INFO, "Shutting down") -- cgit v1.2.3-1-g7c22