X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=monitor%2Fwrapper%2Fplc.py;h=8113c57579dabe9a8cc4593625194fbc679fc3b9;hb=db2f841a5e31ce2d95919fee68e729813c600e26;hp=783efbc744634df1b9b2a1286861f98fa8bd9546;hpb=e811d83a1664a222bed13266703d2aa4f1a1900d;p=monitor.git diff --git a/monitor/wrapper/plc.py b/monitor/wrapper/plc.py index 783efbc..8113c57 100644 --- a/monitor/wrapper/plc.py +++ b/monitor/wrapper/plc.py @@ -12,19 +12,37 @@ import xml, xmlrpclib import logging import time import traceback +from datetime import datetime + +# note: this needs to be consistent with the value in PLEWWW/planetlab/includes/plc_functions.php +PENDING_CONSORTIUM_ID = 0 +# not used in monitor +#APPROVED_CONSORTIUM_ID = 999999 + try: - import config + from monitor import config debug = config.debug + XMLRPC_SERVER=config.API_SERVER except: debug = False + # NOTE: this host is used by default when there are no auth files. + XMLRPC_SERVER="https://boot.planet-lab.org/PLCAPI/" + logger = logging.getLogger("monitor") class Auth: - def __init__(self): - self.auth = {'AuthMethod': "anonymous"} + def __init__(self, username=None, password=None, **kwargs): + if 'session' in kwargs: + self.auth= { 'AuthMethod' : 'session', + 'session' : kwargs['session'] } + else: + if username==None and password==None: + self.auth = {'AuthMethod': "anonymous"} + else: + self.auth = {'Username' : username, + 'AuthMethod' : 'password', + 'AuthString' : password} -# NOTE: this host is used by default when there are no auth files. -XMLRPC_SERVER="https://boot.planet-lab.org/PLCAPI/" # NOTE: by default, use anonymous access, but if auth files are # configured, use them, with their auth definitions. @@ -43,7 +61,7 @@ except: auth = Auth() auth.server = XMLRPC_SERVER -api = xmlrpclib.Server(auth.server, verbose=False, allow_none=True) +global_error_count = 0 class PLC: def __init__(self, auth, url): @@ -56,16 +74,104 @@ class PLC: if method is None: raise AssertionError("method does not exist") - return lambda *params : method(self.auth, *params) + try: + return lambda *params : method(self.auth, *params) + except xmlrpclib.ProtocolError: + traceback.print_exc() + global_error_count += 1 + if global_error_count >= 10: + print "maximum error count exceeded; exiting..." + sys.exit(1) + else: + print "%s errors have occurred" % global_error_count + raise Exception("ProtocolError continuing") def __repr__(self): return self.api.__repr__() + +api = PLC(auth.auth, auth.server) + + def getAPI(url): return xmlrpclib.Server(url, verbose=False, allow_none=True) -def getAuthAPI(): - return PLC(auth.auth, auth.server) +def getNodeAPI(session): + nodeauth = Auth(session=session) + return PLC(nodeauth.auth, auth.server) + +def getAuthAPI(url=None): + if url: + return PLC(auth.auth, url) + else: + return PLC(auth.auth, auth.server) + +def getCachedAuthAPI(): + return CachedPLC(auth.auth, auth.server) + +def getSessionAPI(session, server): + nodeauth = Auth(session=session) + return PLC(nodeauth.auth, server) +def getUserAPI(username, password, server): + auth = Auth(username,password) + return PLC(auth.auth, server) + +def getTechEmails(loginbase): + """ + For the given site, return all user email addresses that have the 'tech' role. + """ + api = getAuthAPI() + # get site details. + s = api.GetSites(loginbase)[0] + # get people at site + p = api.GetPersons(s['person_ids']) + # pull out those with the right role. + emails = [] + for person in filter(lambda x: 'tech' in x['roles'], p): + if not isPersonExempt(person['email']): + emails.append(person['email']) + #emails = [ person['email'] for person in filter(lambda x: 'tech' in x['roles'], p) ] + return emails + +def getPIEmails(loginbase): + """ + For the given site, return all user email addresses that have the 'tech' role. + """ + api = getAuthAPI() + # get site details. + s = api.GetSites(loginbase)[0] + # get people at site + p = api.GetPersons(s['person_ids']) + # pull out those with the right role. + #emails = [ person['email'] for person in filter(lambda x: 'pi' in x['roles'], p) ] + emails = [] + for person in filter(lambda x: 'pi' in x['roles'], p): + if not isPersonExempt(person['email']): + emails.append(person['email']) + return emails + +def getSliceUserEmails(loginbase): + """ + For the given site, return all user email addresses that have the 'tech' role. + """ + api = getAuthAPI() + # get site details. + s = api.GetSites(loginbase)[0] + # get people at site + slices = api.GetSlices(s['slice_ids']) + people = [] + for slice in slices: + people += api.GetPersons(slice['person_ids']) + # pull out those with the right role. + #emails = [ person['email'] for person in filter(lambda x: 'pi' in x['roles'], people) ] + + emails = [] + for person in people: + if not isPersonExempt(person['email']): + emails.append(person['email']) + + unique_emails = [ x for x in set(emails) ] + return unique_emails ''' Returns list of nodes in dbg as reported by PLC @@ -84,19 +190,20 @@ def nodesDbg(): Returns loginbase for given nodename ''' def siteId(nodename): - api = xmlrpclib.Server(auth.server, verbose=False) - anon = {'AuthMethod': "anonymous"} - site_id = api.GetNodes (anon, {"hostname": nodename}, ['site_id']) + api = xmlrpclib.Server(auth.server, verbose=False, allow_none=True) + site_id = api.GetNodes (auth.auth, {"hostname": nodename}, ['site_id']) if len(site_id) == 1: - loginbase = api.GetSites (anon, site_id[0], ["login_base"]) + loginbase = api.GetSites (auth.auth, site_id[0], ["login_base"]) return loginbase[0]['login_base'] + else: + print "Not nodes returned!!!!" ''' Returns list of slices for a site. ''' def slices(loginbase): siteslices = [] - api = xmlrpclib.Server(auth.server, verbose=False) + api = xmlrpclib.Server(auth.server, verbose=False, allow_none=True) sliceids = api.GetSites (auth.auth, {"login_base" : loginbase}, ["slice_ids"])[0]['slice_ids'] for slice in api.GetSlices(auth.auth, {"slice_id" : sliceids}, ["name"]): siteslices.append(slice['name']) @@ -106,11 +213,18 @@ def slices(loginbase): Returns dict of PCU info of a given node. ''' def getpcu(nodename): - api = xmlrpclib.Server(auth.server, verbose=False) + api = xmlrpclib.Server(auth.server, verbose=False, allow_none=True) anon = {'AuthMethod': "anonymous"} - nodeinfo = api.GetNodes(auth.auth, {"hostname": nodename}, ["pcu_ids", "ports"])[0] + try: + nodeinfo = api.GetNodes(auth.auth, {"hostname": nodename}, ["pcu_ids", "ports"])[0] + except IndexError: + logger.info("Can not find node: %s" % nodename) + return False if nodeinfo['pcu_ids']: + print nodeinfo sitepcu = api.GetPCUs(auth.auth, nodeinfo['pcu_ids'])[0] + print sitepcu + print nodeinfo["ports"] sitepcu[nodename] = nodeinfo["ports"][0] return sitepcu else: @@ -138,6 +252,7 @@ def getSiteNodes(loginbase, fields=None): print "getSiteNodes: %s" % exc return nodelist + def getPersons(filter=None, fields=None): api = xmlrpclib.Server(auth.server, verbose=False, allow_none=True) persons = [] @@ -174,17 +289,33 @@ def getSiteNodes2(loginbase): def getNodeNetworks(filter=None): api = xmlrpclib.Server(auth.server, verbose=False, allow_none=True) - nodenetworks = api.GetNodeNetworks(auth.auth, filter, None) + nodenetworks = api.GetInterfaces(auth.auth, filter, None) return nodenetworks def getNodes(filter=None, fields=None): api = xmlrpclib.Server(auth.server, verbose=False, allow_none=True) nodes = api.GetNodes(auth.auth, filter, fields) #['boot_state', 'hostname', - #'site_id', 'date_created', 'node_id', 'version', 'nodenetwork_ids', + #'site_id', 'date_created', 'node_id', 'version', 'interface_ids', #'last_updated', 'peer_node_id', 'ssh_rsa_key' ]) return nodes + +# Check if the site is a pending site that needs to be approved. +def isPendingSite(loginbase): + api = xmlrpclib.Server(auth.server, verbose=False) + try: + site = api.GetSites(auth.auth, loginbase)[0] + except Exception, exc: + logger.info("ERROR: No site %s" % loginbase) + return False + + if not site['enabled'] and site['ext_consortium_id'] == PENDING_CONSORTIUM_ID: + return True + + return False + + ''' Sets boot state of a node. ''' @@ -217,19 +348,40 @@ def nodePOD(nodename): ''' Freeze all site slices. ''' -def suspendSlices(nodename): +def suspendSiteSlices(loginbase): + if isPendingSite(loginbase): + msg = "INFO: suspendSiteSlices: Pending Site (%s)" % loginbase + print msg + logger.info(msg) + return + api = xmlrpclib.Server(auth.server, verbose=False) - for slice in slices(siteId(nodename)): + for slice in slices(loginbase): logger.info("Suspending slice %s" % slice) try: if not debug: - api.AddSliceAttribute(auth.auth, slice, "enabled", "0") + if not isSliceExempt(slice): + api.AddSliceAttribute(auth.auth, slice, "enabled", "0") except Exception, exc: logger.info("suspendSlices: %s" % exc) -def enableSlices(nodename): +''' +Freeze all site slices. +''' +def suspendSlices(nodename): + loginbase = siteId(nodename) + suspendSiteSlices(loginbase) + + +def enableSiteSlices(loginbase): + if isPendingSite(loginbase): + msg = "INFO: enableSiteSlices: Pending Site (%s)" % loginbase + print msg + logger.info(msg) + return + api = xmlrpclib.Server(auth.server, verbose=False, allow_none=True) - for slice in slices(siteId(nodename)): + for slice in slices(loginbase): logger.info("Enabling slices %s" % slice) try: if not debug: @@ -243,9 +395,14 @@ def enableSlices(nodename): logger.info("Deleted enable=0 attribute from slice %s" % slice) api.DeleteSliceAttribute(auth.auth, attr['slice_attribute_id']) except Exception, exc: - logger.info("enableSlices: %s" % exc) + logger.info("enableSiteSlices: %s" % exc) print "exception: %s" % exc +def enableSlices(nodename): + loginbase = siteId(nodename) + enableSiteSlices(loginbase) + + #I'm commenting this because this really should be a manual process. #''' #Enable suspended site slices. @@ -256,34 +413,82 @@ def enableSlices(nodename): # logger.info("Suspending slice %s" % slice) # api.SliceAttributeAdd(auth.auth, slice, "plc_slice_state", {"state" : "suspended"}) # -def enableSliceCreation(nodename): +def enableSiteSliceCreation(loginbase): + if isPendingSite(loginbase): + msg = "INFO: enableSiteSliceCreation: Pending Site (%s)" % loginbase + print msg + logger.info(msg) + return + api = xmlrpclib.Server(auth.server, verbose=False, allow_none=True) try: - loginbase = siteId(nodename) logger.info("Enabling slice creation for site %s" % loginbase) if not debug: - logger.info("\tcalling UpdateSite(%s, enabled=True)" % loginbase) - api.UpdateSite(auth.auth, loginbase, {'enabled': True}) + site = api.GetSites(auth.auth, loginbase)[0] + if site['enabled'] == False: + logger.info("\tcalling UpdateSite(%s, enabled=True)" % loginbase) + api.UpdateSite(auth.auth, loginbase, {'enabled': True}) except Exception, exc: - print "ERROR: enableSliceCreation: %s" % exc - logger.info("ERROR: enableSliceCreation: %s" % exc) + print "ERROR: enableSiteSliceCreation: %s" % exc + logger.info("ERROR: enableSiteSliceCreation: %s" % exc) + +def enableSliceCreation(nodename): + loginbase = siteId(nodename) + enableSiteSliceCreation(loginbase) + +def isTagCurrent(tags): + if len(tags) > 0: + for tag in tags: + until = tag['value'] + if datetime.strptime(until, "%Y%m%d") > datetime.now(): + # NOTE: the 'exempt_until' time is beyond current time + return True + return False + +def isPersonExempt(email): + tags = api.GetPersonTags({'email' : email, 'tagname' : 'exempt_person_until'}) + return isTagCurrent(tags) + +def isNodeExempt(hostname): + tags = api.GetNodeTags({'hostname' : hostname, 'tagname' : 'exempt_node_until'}) + return isTagCurrent(tags) + +def isSliceExempt(slicename): + tags = api.GetSliceTags({'name' : slicename, 'tagname' : 'exempt_slice_until'}) + return isTagCurrent(tags) + +def isSiteExempt(loginbase): + tags = api.GetSiteTags({'login_base' : loginbase, 'tagname' : 'exempt_site_until'}) + return isTagCurrent(tags) ''' -Removes ability to create slices. Returns previous max_slices +Removes site's ability to create slices. Returns previous max_slices ''' -def removeSliceCreation(nodename): - print "removeSliceCreation(%s)" % nodename +def removeSiteSliceCreation(loginbase): + #print "removeSiteSliceCreation(%s)" % loginbase + + if isPendingSite(loginbase): + msg = "INFO: removeSiteSliceCreation: Pending Site (%s)" % loginbase + print msg + logger.info(msg) + return + api = xmlrpclib.Server(auth.server, verbose=False) try: - loginbase = siteId(nodename) - #numslices = api.GetSites(auth.auth, {"login_base": loginbase}, - # ["max_slices"])[0]['max_slices'] logger.info("Removing slice creation for site %s" % loginbase) if not debug: - #api.UpdateSite(auth.auth, loginbase, {'max_slices': 0}) - api.UpdateSite(auth.auth, loginbase, {'enabled': False}) + if not isSiteExempt(loginbase): + api.UpdateSite(auth.auth, loginbase, {'enabled': False}) except Exception, exc: - logger.info("removeSliceCreation: %s" % exc) + logger.info("removeSiteSliceCreation: %s" % exc) + +''' +Removes ability to create slices. Returns previous max_slices +''' +def removeSliceCreation(nodename): + loginbase = siteId(nodename) + removeSiteSliceCreation(loginbase) + ''' QED