- check if the site is in 'pending' state on all site actions
[monitor.git] / monitor / wrapper / plc.py
index 255e3c1..8c3e0c6 100644 (file)
@@ -14,25 +14,35 @@ import time
 import traceback
 from monitor import database
 
 import traceback
 from monitor import database
 
+# 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:
        from monitor import config
        debug = config.debug
 try:
        from monitor import config
        debug = config.debug
+       XMLRPC_SERVER=config.API_SERVER
 except:
        debug = False
 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:
 logger = logging.getLogger("monitor")
        
 class Auth:
-       def __init__(self, username=None, password=None):
-               if username==None and password==None:
-                       self.auth = {'AuthMethod': "anonymous"}
+       def __init__(self, username=None, password=None, **kwargs):
+               if 'session' in kwargs:
+                       self.auth= { 'AuthMethod' : 'session',
+                                       'session' : kwargs['session'] }
                else:
                else:
-                       self.auth = {'Username' : username,
-                               'AuthMethod' : 'password',
-                                               'AuthString' : password}
-                       
+                       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.
 
 # NOTE: by default, use anonymous access, but if auth files are 
 #       configured, use them, with their auth definitions.
@@ -51,7 +61,7 @@ except:
                auth = Auth()
                auth.server = XMLRPC_SERVER
 
                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):
 
 class PLC:
        def __init__(self, auth, url):
@@ -64,11 +74,22 @@ class PLC:
                if method is None:
                        raise AssertionError("method does not exist")
 
                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__()
 
 
        def __repr__(self):
                return self.api.__repr__()
 
+
 class CachedPLC(PLC):
 
        def _param_to_str(self, name, *params):
 class CachedPLC(PLC):
 
        def _param_to_str(self, name, *params):
@@ -87,6 +108,11 @@ class CachedPLC(PLC):
                def run_or_returncached(*params):
                        cachename = self._param_to_str(name, *params)
                        #print "cachename is %s" % cachename
                def run_or_returncached(*params):
                        cachename = self._param_to_str(name, *params)
                        #print "cachename is %s" % cachename
+                       if hasattr(config, 'refresh'):
+                               refresh = config.refresh
+                       else:
+                               refresh = False
+
                        if 'Get' in name:
                                if not database.cachedRecently(cachename):
                                        load_old_cache = False
                        if 'Get' in name:
                                if not database.cachedRecently(cachename):
                                        load_old_cache = False
@@ -95,12 +121,12 @@ class CachedPLC(PLC):
                                        except:
                                                print "Call %s FAILED: Using old cached data" % cachename
                                                load_old_cache = True
                                        except:
                                                print "Call %s FAILED: Using old cached data" % cachename
                                                load_old_cache = True
-                                               
+
                                        if load_old_cache:
                                                values = database.dbLoad(cachename)
                                        else:
                                                database.dbDump(cachename, values)
                                        if load_old_cache:
                                                values = database.dbLoad(cachename)
                                        else:
                                                database.dbDump(cachename, values)
-                                               
+
                                        return values
                                else:
                                        values = database.dbLoad(cachename)
                                        return values
                                else:
                                        values = database.dbLoad(cachename)
@@ -110,16 +136,33 @@ class CachedPLC(PLC):
 
                return run_or_returncached
 
 
                return run_or_returncached
 
+api = PLC(auth.auth, auth.server)
+cacheapi = CachedPLC(auth.auth, auth.server)
+
 
 def getAPI(url):
        return xmlrpclib.Server(url, verbose=False, allow_none=True)
 
 
 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 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.
 def getTechEmails(loginbase):
        """
                For the given site, return all user email addresses that have the 'tech' role.
@@ -150,7 +193,7 @@ def getSliceUserEmails(loginbase):
        """
                For the given site, return all user email addresses that have the 'tech' role.
        """
        """
                For the given site, return all user email addresses that have the 'tech' role.
        """
-       #api = getAuthAPI()
+       api = getAuthAPI()
        # get site details.
        s = api.GetSites(loginbase)[0]
        # get people at site
        # get site details.
        s = api.GetSites(loginbase)[0]
        # get people at site
@@ -207,7 +250,10 @@ def getpcu(nodename):
        anon = {'AuthMethod': "anonymous"}
        nodeinfo = api.GetNodes(auth.auth, {"hostname": nodename}, ["pcu_ids", "ports"])[0]
        if nodeinfo['pcu_ids']:
        anon = {'AuthMethod': "anonymous"}
        nodeinfo = api.GetNodes(auth.auth, {"hostname": nodename}, ["pcu_ids", "ports"])[0]
        if nodeinfo['pcu_ids']:
+               print nodeinfo
                sitepcu = api.GetPCUs(auth.auth, nodeinfo['pcu_ids'])[0]
                sitepcu = api.GetPCUs(auth.auth, nodeinfo['pcu_ids'])[0]
+               print sitepcu
+               print nodeinfo["ports"]
                sitepcu[nodename] = nodeinfo["ports"][0]
                return sitepcu
        else:
                sitepcu[nodename] = nodeinfo["ports"][0]
                return sitepcu
        else:
@@ -272,17 +318,33 @@ def getSiteNodes2(loginbase):
 
 def getNodeNetworks(filter=None):
        api = xmlrpclib.Server(auth.server, verbose=False, allow_none=True)
 
 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', 
        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
 
                        #'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:
+                login.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.
 '''
 '''
 Sets boot state of a node.
 '''
@@ -315,9 +377,15 @@ def nodePOD(nodename):
 '''
 Freeze all site slices.
 '''
 '''
 Freeze all site slices.
 '''
-def suspendSlices(nodename):
+def suspendSiteSlices(loginbase):
+        if isPendingSite(loginbase):
+                msg = "INFO: enableSiteSlices: Pending Site (%s)" % loginbase
+                print msg
+                logger.info(msg)
+                return
+
        api = xmlrpclib.Server(auth.server, verbose=False)
        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:
                logger.info("Suspending slice %s" % slice)
                try:
                        if not debug:
@@ -325,9 +393,23 @@ def suspendSlices(nodename):
                except Exception, exc:
                        logger.info("suspendSlices:  %s" % exc)
 
                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)
        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:
                logger.info("Enabling slices %s" % slice)
                try:
                        if not debug:
@@ -341,9 +423,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("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
 
                        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.
 #I'm commenting this because this really should be a manual process.  
 #'''
 #Enable suspended site slices.
@@ -354,34 +441,54 @@ def enableSlices(nodename):
 #              logger.info("Suspending slice %s" % slice)
 #              api.SliceAttributeAdd(auth.auth, slice, "plc_slice_state", {"state" : "suspended"})
 #
 #              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:
        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})
        except Exception, exc:
                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})
        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)
 
 '''
 
 '''
-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:
        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:
                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})
        except Exception, exc:
                        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
 
 '''
 QED