class AuthManager(object): """ Manager to maintain multiple credential Handlers, one for each target account. For some handlers, if they need to perform periodic checks, they will be run as threads. Others, which only hold information, will just be objects. """ def __init__(self, factory=None): self.log = logging.getLogger('autopyfactory') self.log.info("Creating new authmanager...") self.aconfig = Config() self.handlers = [] self.factory = factory if factory: self.sleep = int( self.factory.fcl.get('Factory', 'authmanager.sleep')) else: self.sleep = 5 def reconfig(self, newconfig): hdiff = ConfigsDiff(self.aconfig, newconfig) self.aconfig = newconfig self._addhandlers(hdiff.added()) def _addhandlers(self, newsections): for sect in newsections: try: pclass = self.aconfig.get(sect, 'plugin') except Exception, e: self.log.warn("No plugin attribute for section %s" % sect) if pclass == 'X509': self.log.debug("Creating X509 handler for %s" % sect) authpluginname = self.aconfig.get(sect, 'plugin') x509h = pluginmanager.getplugin( ['autopyfactory', 'plugins', 'authmanager', 'auth'], authpluginname, self, self.aconfig, sect) self.handlers.append(x509h) elif pclass == 'SSH': self.log.debug("Creating SSH handler for %s" % sect) authpluginname = self.aconfig.get(sect, 'plugin') sshh = pluginmanager.getplugin( ['autopyfactory', 'plugins', 'authmanager', 'auth'], authpluginname, self, self.aconfig, sect) self.handlers.append(sshh) else: self.log.warn("Unrecognized auth plugin %s" % pclass)
class AuthManager(object): """ Manager to maintain multiple credential Handlers, one for each target account. For some handlers, if they need to perform periodic checks, they will be run as threads. Others, which only hold information, will just be objects. """ def __init__(self, factory=None): self.log = logging.getLogger('autopyfactory') self.log.info("Creating new authmanager...") self.aconfig = Config() self.handlers = [] self.factory = factory if factory: self.sleep = int(self.factory.fcl.get('Factory', 'authmanager.sleep')) else: self.sleep = 5 def reconfig(self, newconfig): hdiff = ConfigsDiff(self.aconfig, newconfig) self.aconfig = newconfig self._addhandlers(hdiff.added()) def _addhandlers(self, newsections): for sect in newsections: try: pclass = self.aconfig.get(sect, 'plugin') except Exception as e: self.log.warn("No plugin attribute for section %s" % sect) if pclass == 'X509': self.log.debug("Creating X509 handler for %s" % sect ) authpluginname = self.aconfig.get(sect, 'plugin') x509h = pluginmanager.getplugin(['autopyfactory', 'plugins', 'authmanager', 'auth'], authpluginname, self, self.aconfig, sect) self.handlers.append(x509h) elif pclass == 'SSH': self.log.debug("Creating SSH handler for %s" % sect ) authpluginname = self.aconfig.get(sect, 'plugin') sshh = pluginmanager.getplugin(['autopyfactory', 'plugins', 'authmanager', 'auth'], authpluginname, self, self.aconfig, sect) self.handlers.append(sshh) else: self.log.warn("Unrecognized auth plugin %s" % pclass ) def activate(self): """ start all Handlers, if needed """ for ah in self.handlers: if isinstance(ah, threading.Thread) : self.log.debug("Handler [%s] is a thread. Starting..." % ah.name) ah.start() else: self.log.debug("Handler [%s] is not a thread. No action." % ah.name) def listNames(self): """ Returns list of valid names of Handlers in this Manager. """ names = [] for h in self.handlers: names.append(h.name) return names # # API for X509Handler # def getProxyPath(self, profilelist): """ Check all the handlers for matching profile name(s). profiles argument is a list """ pp = None for profile in profilelist: self.log.debug("Getting proxy path for profile %s" % profile) ph = None for h in self.handlers: self.log.debug("Finding handler. Checking %s" % h.name) if h.name == profile: ph = h break if ph: self.log.debug("Found handler %s. Getting proxypath..." % ph.name) pp = ph.getProxyPath() self.log.debug("Proxypath is %s" % pp) if pp: break if not pp: subject = "Proxy problem on %s" % self.factory.factoryid messagestring = "Unable to get valid proxy from configured profiles: %s" % profilelist self.factory.sendAdminEmail(subject, messagestring) raise InvalidAuthFailure("Problem getting proxy for profile %s" % profilelist) return pp # # API for SSHKeyHandler # def getSSHKeyPair(self, profile): """ Returns tuple (public, private, pass) key/phrase string from profile. """ pass def getSSHKeyPairPaths(self, profile): """ Returns tuple (public, private, pass) key/passfile paths to files from profile. """ h = self._getHandler(profile) pub = h.getSSHPubKeyFilePath() priv = h.getSSHPrivKeyFilePath() pasf = h.getSSHPassFilePath() self.log.info('Got file paths for pub, priv, pass for SSH profile %s' % profile) return (pub,priv,pasf) def _getHandler(self, profile): """ """ handler = None for h in self.handlers: self.log.debug("Finding handler. Checking %s" % h.name) if h.name == profile: self.log.debug("Found handler for %s" % h.name) handler = h if handler is None: raise InvalidAuthFailure('No handler for %s ' % profile) return handler
class APFGridSubmitter(object): __metaclass__ = APFGridSubmitterSingleton factorymock = None authman = None agis = None logserver = None cleanlogs = None def __init__(self, **kwarg): self.log = core_utils.make_logger(baseLogger) self.config = Config() factoryconffile = os.path.expanduser('~/harvester/etc/autopyfactory/autopyfactory.conf') self.log.debug('Reading config: %s' % factoryconffile) okread = self.config.read(factoryconffile) self.log.debug('Successfully read %s' % okread) # Setup Authmanager authconfigfile = os.path.expanduser(self.config.get('Factory','authConf')) ac = Config() self.log.debug('Reading config: %s' % authconfigfile) okread = ac.read(authconfigfile) self.log.debug('Successfully read %s' % okread) if APFGridSubmitter.authman is None : APFGridSubmitter.authman = AuthManager() APFGridSubmitter.authman.reconfig(ac) self.authman = APFGridSubmitter.authman APFGridSubmitter.authman.activate() # Setup factory mock object. from autopyfactory.factory import Factory if APFGridSubmitter.factorymock is None: APFGridSubmitter.factorymock = Factory.getFactoryMock(fcl=self.config, am=self.authman) # Setup AGIS if APFGridSubmitter.agis is None: APFGridSubmitter.agisobj = Agis(None, self.config, None) self.agisobj = APFGridSubmitter.agisobj self.log.debug("AGIS object: %s" % self.agisobj) # Setup logserver self.log.debug("Handling LogServer...") if self.config.generic_get('Factory', 'logserver.enabled', 'getboolean'): self.log.info("LogServer enabled. Initializing...") self.logserver = LogServer(self.config) self.log.info('LogServer initialized. Starting...') self.logserver.start() self.log.debug('LogServer thread started.') else: self.log.info('LogServer disabled. Not running.') self.log.debug('APFGridSubmitter initialized.') def _print_config(self, config): s="" for section in config.sections(): s+= "[%s]\n" % section for opt in config.options(section): s+="%s = %s\n" % (opt, config.get(section, opt)) return s def submit_workers(self, workspec_list): ''' Submit workers to a scheduling system like batch systems and computing elements. This method takes a list of WorkSpecs as input argument, and returns a list of tuples. Each tuple is composed of a return code and a dialog message. Nth tuple in the returned list corresponds to submission status and dialog message for Nth worker in the given WorkSpec list. A unique identifier is set to WorkSpec.batchID when submission is successful, so that they can be identified in the scheduling system. :param workspec_list: a list of work specs instances :return: A list of tuples. Each tuple is composed of submission status (True for success, False otherwise) and dialog message :rtype: [(bool, string),] For UPQ PQ name, e.g. HARVESTER_BNL_APF_TEST/MCORE SCORE, SCORE_HIMEM, MCORE, and MCORE_HIMEM Workspec AGIS PQ/CEQ attribute. WorkSpec.minRamCount PQ.memory WorkSpec.nCore PQ.corecount WorkSpec.maxDiskCount PQ.maxwdir WorkSpec.maxWalltime PQ.maxtime ''' self.log.debug('start nWorkers={0}'.format(len(workspec_list))) self.log.debug("Update AGIS info...") qc = self.agisobj.getConfig() #self.log.debug('Agis config output %s' % self._print_config(qc)) #self.log.debug('Agis config defaults= %s' % qc.defaults() ) retlist = [] # wsmap is indexed by computing site: # { <computingsite> : [ws1, ws2, ws3 ], # <computingsite2> : [ws4, ws5] # } wsmap = {} jobmap = {} try: self.log.debug("Handling workspec_list with %d items..." % len(workspec_list)) for workSpec in workspec_list: self.log.debug("Worker(workerId=%s queueName=%s computingSite=%s nCore=%s status=%s " % (workSpec.workerID, workSpec.queueName, workSpec.computingSite, workSpec.nCore, workSpec.status) ) try: wslist = wsmap[workSpec.computingSite] wslist.append(workSpec) except KeyError: wsmap[workSpec.computingSite] = [workSpec] self.log.debug("wsmap = %s" % wsmap) for pq in wsmap.keys(): found = False apfqsections = [] for s in qc.sections(): qcq = qc.get(s, 'wmsqueue').strip() self.log.debug('Checking %s' % qcq) if qcq == pq: found = True apfqsections.append(s) self.log.debug("Found a queues config for %s" % pq ) self.log.info("Found %d sections for PQ %s" % (len(apfqsections), pq)) if found: # make apfq and submit self.log.debug("One or more Agis configs found for PQ. Choosing one...") section = random.choice(apfqsections) pqc = qc.getSection(section) ac = os.path.expanduser('~/harvester/etc/autopyfactory/autopyfactory.conf') pqc.set(section, 'factoryconf', ac) self.log.debug("Section config= %s" % pqc) self.log.debug("Making APF queue for PQ %s with label %s"% (pq, section)) apfq = SubmitAPFQueue( pqc, self.authman ) self.log.debug("Successfully made APFQueue") joblist = [] for ws in wsmap[pq]: jobentry = { "+workerid" : ws.workerID } joblist.append(jobentry) self.log.debug("joblist made= %s. Submitting..." % joblist) jobinfo = apfq.submitlist(joblist) self.log.debug("Got jobinfo %s" % jobinfo) wslist = wsmap[pq] self.log.debug("wslist for pq %s is length %s" % (pq, len(wslist))) for i in range(0, len(wslist)): self.log.debug("Setting ws.batchID to %s" % jobinfo[i].jobid ) wslist[i].batchID = jobinfo[i].jobid wslist[i].set_status(WorkSpec.ST_submitted) retlist.append((True, '')) else: self.log.info('No AGIS config found for PQ %s skipping.' % pq) except Exception, e: self.log.error(traceback.format_exc(None)) self.log.debug("return list=%s " % retlist) return retlist
class AuthManager(object): """ Manager to maintain multiple credential Handlers, one for each target account. For some handlers, if they need to perform periodic checks, they will be run as threads. Others, which only hold information, will just be objects. """ def __init__(self, factory=None): self.log = logging.getLogger('autopyfactory') self.log.info("Creating new authmanager...") self.aconfig = Config() self.handlers = [] self.factory = factory if factory: self.sleep = int( self.factory.fcl.get('Factory', 'authmanager.sleep')) else: self.sleep = 5 def reconfig(self, newconfig): self.log.debug("Performing reconfig() for auth handlers...") hdiff = ConfigsDiff(self.aconfig, newconfig) self.aconfig = newconfig self.log.debug("Deleting removed handlers...") self._delhandlers(hdiff.removed()) self.log.debug("Deleting modified handlers...") self._delhandlers(hdiff.modified()) self.log.debug("Re-creating modified handlers...") self._addhandlers(hdiff.modified()) self.log.debug("Adding new handlers...") self._addhandlers(hdiff.added()) self.log.info("Completed reconfig() on auth handlers.") def _addhandlers(self, newsections): for sect in newsections: try: pclass = self.aconfig.get(sect, 'plugin') except Exception as e: self.log.warn("No plugin attribute for section %s" % sect) if pclass == 'X509': self.log.debug("Creating X509 handler for %s" % sect) authpluginname = self.aconfig.get(sect, 'plugin') x509h = pluginmanager.getplugin( ['autopyfactory', 'plugins', 'authmanager', 'auth'], authpluginname, self, self.aconfig, sect) self.handlers.append(x509h) elif pclass == 'SSH' or 'GSISSH': self.log.debug("Creating SSH handler for %s" % sect) authpluginname = self.aconfig.get(sect, 'plugin') sshh = pluginmanager.getplugin( ['autopyfactory', 'plugins', 'authmanager', 'auth'], authpluginname, self, self.aconfig, sect) self.handlers.append(sshh) else: self.log.warn("Unrecognized auth plugin %s" % pclass) def _delhandlers(self, delsections): for sect in delsections: try: handler = self._gethandlerbyname(sect) if handler is not None: if isinstance(handler, threading.Thread): try: handler.join() except Exception: self.log.warning( 'attempt to join() thread for handler %s failed, handler is not active' % handler.name) # In any case, remove the handler object... self.handlers.pop(handler) except Exception: self.log.warning( 'attempt to join() thread for handler %s failed, handler is not active' % handler.name) def _gethandlerbyname(self, name): h = None for h in self.handlers: if h.name == name: self.log.debug("Found handler %s" % name) return h return h def activate(self): """ start all Handlers, if needed """ for ah in self.handlers: if isinstance(ah, threading.Thread): self.log.debug("Handler [%s] is a thread. Starting..." % ah.name) ah.start() else: self.log.debug("Handler [%s] is not a thread. No action." % ah.name) def listNames(self): """ Returns list of valid names of Handlers in this Manager. """ names = [] for h in self.handlers: names.append(h.name) return names # # API for X509Handler # def getProxyPath(self, profilelist): """ Check all the handlers for matching profile name(s). profiles argument is a list """ pp = None for profile in profilelist: self.log.debug("Getting proxy path for profile %s" % profile) ph = None for h in self.handlers: self.log.debug("Finding handler. Checking %s" % h.name) if h.name == profile: ph = h break if ph: self.log.debug("Found handler %s. Getting proxypath..." % ph.name) pp = ph.getProxyPath() self.log.debug("Proxypath is %s" % pp) if pp: break if not pp: subject = "Proxy problem on %s" % self.factory.factoryid messagestring = "Unable to get valid proxy from configured profiles: %s" % profilelist self.factory.sendAdminEmail(subject, messagestring) raise InvalidAuthFailure("Problem getting proxy for profile %s" % profilelist) return pp # # API for SSHKeyHandler # def getSSHKeyPair(self, profile): """ Returns tuple (public, private, pass) key/phrase string from profile. """ pass def getSSHKeyPairPaths(self, profile): """ Returns tuple (public, private, pass) key/passfile paths to files from profile. """ h = self._getHandler(profile) pub = h.getSSHPubKeyFilePath() priv = h.getSSHPrivKeyFilePath() pasf = h.getSSHPassFilePath() self.log.info('Got file paths for pub, priv, pass for SSH profile %s' % profile) return (pub, priv, pasf) # # API for GSISSHKeyHandler # def getGSISSHKey(self, profile): """ Returns GSI proxy string from profile """ pass def getGSISSHKeyPaths(self, profile): """ Returns GSI proxy (private key) from path as a string """ h = self._getHandler(profile) priv = h.getGSISSHPrivKeyFilePath() self.log.info('Got file paths for proxy for GSISSH profile %s' % profile) return priv def _getHandler(self, profile): """ """ handler = None for h in self.handlers: self.log.debug("Finding handler. Checking %s" % h.name) if h.name == profile: self.log.debug("Found handler for %s" % h.name) handler = h if handler is None: raise InvalidAuthFailure('No handler for %s ' % profile) return handler