more pep8-friendly
[sfa.git] / sfa / server / sfaapi.py
index 48ff6e5..231fdeb 100644 (file)
@@ -1,38 +1,58 @@
-from sfa.util.faults import SfaAPIError
+# pylint: disable=c0111
+
+import os
+import os.path
+import datetime
+
+from sfa.util.faults import SfaFault, RecordNotFound
+from sfa.util.genicode import GENICODE
 from sfa.util.config import Config
 from sfa.util.cache import Cache
 from sfa.util.config import Config
 from sfa.util.cache import Cache
+
 from sfa.trust.auth import Auth
 from sfa.trust.certificate import Keypair, Certificate
 from sfa.trust.credential import Credential
 from sfa.trust.auth import Auth
 from sfa.trust.certificate import Keypair, Certificate
 from sfa.trust.credential import Credential
-# this is wrong all right, but temporary 
-from sfa.managers.managerwrapper import ManagerWrapper, import_manager
+from sfa.trust.rights import determine_rights
+from sfa.util.version import version_core
 from sfa.server.xmlrpcapi import XmlrpcApi
 from sfa.server.xmlrpcapi import XmlrpcApi
-import os
-import datetime
+from sfa.client.return_value import ReturnValue
+
+from sfa.storage.alchemy import alchemy
 
 ####################
 
 ####################
-class SfaApi (XmlrpcApi): 
-    
+
+
+class SfaApi(XmlrpcApi):
     """
     """
-    An SfaApi instance is a basic xmlrcp service
+    An SfaApi instance is a basic xmlrpc service
     augmented with the local cryptographic material and hrn
     augmented with the local cryptographic material and hrn
-    It also has the notion of neighbour sfa services 
-    as defined in /etc/sfa/{aggregates,registries}.xml
-    It has no a priori knowledge of the underlying testbed
+
+    It also has the notion of its own interface (a string describing
+    whether we run a registry, aggregate or slicemgr) and has
+    the notion of neighbour sfa services as defined
+    in /etc/sfa/{aggregates,registries}.xml
+
+    Finally it contains a cache instance
+
+    It gets augmented by the generic layer with
+    (*) an instance of manager (actually a manager module for now)
+        beware that this is shared among all instances of api
+    (*) an instance of a testbed driver
     """
 
     """
 
-    def __init__ (self, encoding="utf-8", methods='sfa.methods', 
-                  config = "/etc/sfa/sfa_config.py", 
-                  peer_cert = None, interface = None, 
-                  key_file = None, cert_file = None, cache = None):
-        
-        XmlrpcApi.__init__ (self, encoding)
-        
+    def __init__(self, encoding="utf-8", methods='sfa.methods',
+                 config="/etc/sfa/sfa_config",
+                 peer_cert=None, interface=None,
+                 key_file=None, cert_file=None, cache=None):
+
+        XmlrpcApi.__init__(self, encoding)
+
         # we may be just be documenting the API
         if config is None:
             return
         # Load configuration
         self.config = Config(config)
         # we may be just be documenting the API
         if config is None:
             return
         # Load configuration
         self.config = Config(config)
+        self.credential = None
         self.auth = Auth(peer_cert)
         self.interface = interface
         self.hrn = self.config.SFA_INTERFACE_HRN
         self.auth = Auth(peer_cert)
         self.interface = interface
         self.hrn = self.config.SFA_INTERFACE_HRN
@@ -43,46 +63,25 @@ class SfaApi (XmlrpcApi):
         self.cache = cache
         if self.cache is None:
             self.cache = Cache()
         self.cache = cache
         if self.cache is None:
             self.cache = Cache()
-        self.credential = None
 
         # load registries
         from sfa.server.registry import Registries
 
         # load registries
         from sfa.server.registry import Registries
-        self.registries = Registries() 
+        self.registries = Registries()
 
         # load aggregates
         from sfa.server.aggregate import Aggregates
         self.aggregates = Aggregates()
 
 
         # load aggregates
         from sfa.server.aggregate import Aggregates
         self.aggregates = Aggregates()
 
+        # filled later on by generic/Generic
+        self.manager = None
+        self._dbsession = None
 
 
-    def get_interface_manager(self, manager_base = 'sfa.managers'):
-        """
-        Returns the appropriate manager module for this interface.
-        Modules are usually found in sfa/managers/
-        """
-        manager=None
-        if self.interface in ['registry']:
-            manager=import_manager ("registry",  self.config.SFA_REGISTRY_TYPE)
-        elif self.interface in ['aggregate']:
-            manager=import_manager ("aggregate", self.config.SFA_AGGREGATE_TYPE)
-        elif self.interface in ['slicemgr', 'sm']:
-            manager=import_manager ("slice",     self.config.SFA_SM_TYPE)
-        elif self.interface in ['component', 'cm']:
-            manager=import_manager ("component", self.config.SFA_CM_TYPE)
-        if not manager:
-            raise SfaAPIError("No manager for interface: %s" % self.interface)  
-            
-        # this isnt necessary but will help to produce better error messages
-        # if someone tries to access an operation this manager doesn't implement  
-        manager = ManagerWrapper(manager, self.interface)
-
-        return manager
-
-    def get_server(self, interface, cred, timeout=30):
+    def server_proxy(self, interface, cred, timeout=30):
         """
         Returns a connection to the specified interface. Use the specified
         """
         Returns a connection to the specified interface. Use the specified
-        credential to determine the caller and look for the caller's key/cert 
-        in the registry hierarchy cache. 
-        """       
+        credential to determine the caller and look for the caller's key/cert
+        in the registry hierarchy cache.
+        """
         from sfa.trust.hierarchy import Hierarchy
         if not isinstance(cred, Credential):
             cred_obj = Credential(string=cred)
         from sfa.trust.hierarchy import Hierarchy
         if not isinstance(cred, Credential):
             cred_obj = Credential(string=cred)
@@ -93,99 +92,113 @@ class SfaApi (XmlrpcApi):
         auth_info = hierarchy.get_auth_info(caller_gid.get_hrn())
         key_file = auth_info.get_privkey_filename()
         cert_file = auth_info.get_gid_filename()
         auth_info = hierarchy.get_auth_info(caller_gid.get_hrn())
         key_file = auth_info.get_privkey_filename()
         cert_file = auth_info.get_gid_filename()
-        server = interface.get_server(key_file, cert_file, timeout)
+        server = interface.server_proxy(key_file, cert_file, timeout)
         return server
         return server
-               
-        
-    def getCredential(self):
+
+    def dbsession(self):
+        if self._dbsession is None:
+            self._dbsession = alchemy.session()
+        return self._dbsession
+
+    def close_dbsession(self):
+        if self._dbsession is None:
+            return
+        alchemy.close_session(self._dbsession)
+        self._dbsession = None
+
+    def getCredential(self, minimumExpiration=0):
         """
         """
-        Return a valid credential for this interface. 
+        Return a valid credential for this interface.
         """
         type = 'authority'
         path = self.config.SFA_DATA_DIR
         filename = ".".join([self.interface, self.hrn, type, "cred"])
         """
         type = 'authority'
         path = self.config.SFA_DATA_DIR
         filename = ".".join([self.interface, self.hrn, type, "cred"])
-        cred_filename = path + os.sep + filename
+        cred_filename = os.path.join(path, filename)
         cred = None
         if os.path.isfile(cred_filename):
         cred = None
         if os.path.isfile(cred_filename):
-            cred = Credential(filename = cred_filename)
+            cred = Credential(filename=cred_filename)
             # make sure cred isnt expired
             if not cred.get_expiration or \
             # make sure cred isnt expired
             if not cred.get_expiration or \
-               datetime.datetime.utcnow() < cred.get_expiration():    
+               datetime.datetime.utcnow() + datetime.timedelta(seconds=minimumExpiration) < cred.get_expiration():
                 return cred.save_to_string(save_parents=True)
 
         # get a new credential
         if self.interface in ['registry']:
                 return cred.save_to_string(save_parents=True)
 
         # get a new credential
         if self.interface in ['registry']:
-            cred =  self.__getCredentialRaw()
+            cred = self._getCredentialRaw()
         else:
         else:
-            cred =  self.__getCredential()
+            cred = self._getCredential()
         cred.save_to_file(cred_filename, save_parents=True)
 
         return cred.save_to_string(save_parents=True)
 
         cred.save_to_file(cred_filename, save_parents=True)
 
         return cred.save_to_string(save_parents=True)
 
-
     def getDelegatedCredential(self, creds):
         """
         Attempt to find a credential delegated to us in
         the specified list of creds.
         """
         from sfa.trust.hierarchy import Hierarchy
     def getDelegatedCredential(self, creds):
         """
         Attempt to find a credential delegated to us in
         the specified list of creds.
         """
         from sfa.trust.hierarchy import Hierarchy
-        if creds and not isinstance(creds, list): 
+        if creds and not isinstance(creds, list):
             creds = [creds]
         hierarchy = Hierarchy()
             creds = [creds]
         hierarchy = Hierarchy()
-                
+
         delegated_cred = None
         for cred in creds:
         delegated_cred = None
         for cred in creds:
-            if hierarchy.auth_exists(Credential(string=cred).get_gid_caller().get_hrn()):
+            if hierarchy.auth_exists(Credential(cred=cred).get_gid_caller().get_hrn()):
                 delegated_cred = cred
                 break
         return delegated_cred
                 delegated_cred = cred
                 break
         return delegated_cred
-    def __getCredential(self):
-        """ 
-        Get our credential from a remote registry 
+
+    def _getCredential(self):
+        """
+        Get our credential from a remote registry
         """
         from sfa.server.registry import Registries
         registries = Registries()
         """
         from sfa.server.registry import Registries
         registries = Registries()
-        registry = registries.get_server(self.hrn, self.key_file, self.cert_file)
-        cert_string=self.cert.save_to_string(save_parents=True)
+        registry = registries.server_proxy(
+            self.hrn, self.key_file, self.cert_file)
+        cert_string = self.cert.save_to_string(save_parents=True)
         # get self credential
         # get self credential
-        self_cred = registry.GetSelfCredential(cert_string, self.hrn, 'authority')
+        self_cred = registry.GetSelfCredential(
+            cert_string, self.hrn, 'authority')
         # get credential
         cred = registry.GetCredential(self_cred, self.hrn, 'authority')
         return Credential(string=cred)
 
         # get credential
         cred = registry.GetCredential(self_cred, self.hrn, 'authority')
         return Credential(string=cred)
 
-    def __getCredentialRaw(self):
+    def _getCredentialRaw(self):
         """
         Get our current credential directly from the local registry.
         """
 
         hrn = self.hrn
         auth_hrn = self.auth.get_authority(hrn)
         """
         Get our current credential directly from the local registry.
         """
 
         hrn = self.hrn
         auth_hrn = self.auth.get_authority(hrn)
-    
+
         # is this a root or sub authority
         if not auth_hrn or hrn == self.config.SFA_INTERFACE_HRN:
             auth_hrn = hrn
         auth_info = self.auth.get_auth_info(auth_hrn)
         # is this a root or sub authority
         if not auth_hrn or hrn == self.config.SFA_INTERFACE_HRN:
             auth_hrn = hrn
         auth_info = self.auth.get_auth_info(auth_hrn)
-        table = self.SfaTable()
-        records = table.findObjects({'hrn': hrn, 'type': 'authority+sa'})
-        if not records:
-            raise RecordNotFound
-        record = records[0]
-        type = record['type']
+        # xxx although unlikely we might want to check for a potential leak
+        dbsession = self.dbsession()
+        from sfa.storage.model import RegRecord
+        record = dbsession.query(RegRecord).filter_by(
+            type='authority+sa', hrn=hrn).first()
+        if not record:
+            raise RecordNotFound(hrn)
+        type = record.type
         object_gid = record.get_gid_object()
         object_gid = record.get_gid_object()
-        new_cred = Credential(subject = object_gid.get_subject())
+        new_cred = Credential(subject=object_gid.get_subject())
         new_cred.set_gid_caller(object_gid)
         new_cred.set_gid_object(object_gid)
         new_cred.set_gid_caller(object_gid)
         new_cred.set_gid_object(object_gid)
-        new_cred.set_issuer_keys(auth_info.get_privkey_filename(), auth_info.get_gid_filename())
-        
+        new_cred.set_issuer_keys(
+            auth_info.get_privkey_filename(), auth_info.get_gid_filename())
+
         r1 = determine_rights(type, hrn)
         new_cred.set_privileges(r1)
         new_cred.encode()
         new_cred.sign()
 
         return new_cred
         r1 = determine_rights(type, hrn)
         new_cred.set_privileges(r1)
         new_cred.encode()
         new_cred.sign()
 
         return new_cred
-   
-    def loadCredential (self):
+
+    def loadCredential(self):
         """
         Attempt to load credential from file if it exists. If it doesnt get
         credential from registry.
         """
         Attempt to load credential from file if it exists. If it doesnt get
         credential from registry.
@@ -193,10 +206,11 @@ class SfaApi (XmlrpcApi):
 
         # see if this file exists
         # XX This is really the aggregate's credential. Using this is easier than getting
 
         # see if this file exists
         # XX This is really the aggregate's credential. Using this is easier than getting
-        # the registry's credential from iteslf (ssl errors).   
-        ma_cred_filename = self.config.SFA_DATA_DIR + os.sep + self.interface + self.hrn + ".ma.cred"
+        # the registry's credential from iteslf (ssl errors).
+        filename = self.interface + self.hrn + ".ma.cred"
+        ma_cred_path = os.path.join(self.config.SFA_DATA_DIR, filename)
         try:
         try:
-            self.credential = Credential(filename = ma_cred_filename)
+            self.credential = Credential(filename=ma_cred_path)
         except IOError:
             self.credential = self.getCredentialFromRegistry()
 
         except IOError:
             self.credential = self.getCredentialFromRegistry()
 
@@ -206,7 +220,52 @@ class SfaApi (XmlrpcApi):
         if self.cache:
             server_version = self.cache.get(cache_key)
         if not server_version:
         if self.cache:
             server_version = self.cache.get(cache_key)
         if not server_version:
-            server_version = server.GetVersion()
+            result = server.GetVersion()
+            server_version = ReturnValue.get_value(result)
             # cache version for 24 hours
             # cache version for 24 hours
-            self.cache.add(cache_key, server_version, ttl= 60*60*24)
+            self.cache.add(cache_key, server_version, ttl=60 * 60 * 24)
         return server_version
         return server_version
+
+    def get_geni_code(self, result):
+        code = {
+            'geni_code': GENICODE.SUCCESS,
+            'am_type': 'sfa',
+            'am_code': None,
+        }
+        if isinstance(result, SfaFault):
+            code['geni_code'] = result.faultCode
+            code['am_code'] = result.faultCode
+
+        return code
+
+    def get_geni_value(self, result):
+        value = result
+        if isinstance(result, SfaFault):
+            value = ""
+        return value
+
+    def get_geni_output(self, result):
+        output = ""
+        if isinstance(result, SfaFault):
+            output = result.faultString
+        return output
+
+    def prepare_response_am(self, result):
+        version = version_core()
+        response = {
+            'geni_api': 3,
+            'code': self.get_geni_code(result),
+            'value': self.get_geni_value(result),
+            'output': self.get_geni_output(result),
+        }
+        return response
+
+    def prepare_response(self, result, method=""):
+        """
+        Converts the specified result into a standard GENI compliant
+        response
+        """
+        # as of dec 13 2011 we only support API v2
+        if self.interface.lower() in ['aggregate', 'slicemgr']:
+            result = self.prepare_response_am(result)
+        return XmlrpcApi.prepare_response(self, result, method)