more pep8-friendly
[sfa.git] / sfa / server / sfaapi.py
index b0e9330..231fdeb 100644 (file)
@@ -1,46 +1,52 @@
-import os, os.path
+# pylint: disable=c0111
+
+import os
+import os.path
 import datetime
 
-from sfa.util.faults import SfaAPIError
+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.trust.auth import Auth
 from sfa.trust.certificate import Keypair, Certificate
 from sfa.trust.credential import Credential
 from sfa.trust.rights import determine_rights
+from sfa.util.version import version_core
 from sfa.server.xmlrpcapi import XmlrpcApi
-from sfa.util.genicode import GENICODE
+from sfa.client.return_value import ReturnValue
 
-# thgen xxx fixme this is wrong all right, but temporary, will use generic
-from sfa.util.table import SfaTable
+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
 
     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 
+    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 
+    It gets augmented by the generic layer with
     (*) an instance of manager (actually a manager module for now)
-    (*) which in turn holds an instance of a testbed driver
-    For convenience api.manager.driver == api.driver
+        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
@@ -60,21 +66,22 @@ class SfaApi (XmlrpcApi):
 
         # 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()
-        
+
         # filled later on by generic/Generic
-        self.manager=None
+        self.manager = None
+        self._dbsession = None
 
     def server_proxy(self, interface, cred, timeout=30):
         """
         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)
@@ -87,99 +94,111 @@ class SfaApi (XmlrpcApi):
         cert_file = auth_info.get_gid_filename()
         server = interface.server_proxy(key_file, cert_file, timeout)
         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"])
-        cred_filename = os.path.join(path,filename)
+        cred_filename = os.path.join(path, 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 \
-               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']:
-            cred =  self.__getCredentialRaw()
+            cred = self._getCredentialRaw()
         else:
-            cred =  self.__getCredential()
+            cred = self._getCredential()
         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
-        if creds and not isinstance(creds, list): 
+        if creds and not isinstance(creds, list):
             creds = [creds]
         hierarchy = Hierarchy()
-                
+
         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
-    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()
-        registry = registries.server_proxy(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
-        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)
 
-    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)
-    
+
         # 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)
-        # xxx thgen fixme - use SfaTable hardwired for now 
-        #table = self.SfaTable()
-        table = 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()
-        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_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
-   
-    def loadCredential (self):
+
+    def loadCredential(self):
         """
         Attempt to load credential from file if it exists. If it doesnt get
         credential from registry.
@@ -189,9 +208,9 @@ class SfaApi (XmlrpcApi):
         # XX This is really the aggregate's credential. Using this is easier than getting
         # 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)
+        ma_cred_path = os.path.join(self.config.SFA_DATA_DIR, filename)
         try:
-            self.credential = Credential(filename = ma_cred_path)
+            self.credential = Credential(filename=ma_cred_path)
         except IOError:
             self.credential = self.getCredentialFromRegistry()
 
@@ -201,22 +220,22 @@ class SfaApi (XmlrpcApi):
         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
-            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
 
-
     def get_geni_code(self, result):
         code = {
-            'geni_code': GENICODE.SUCCESS, 
+            'geni_code': GENICODE.SUCCESS,
             'am_type': 'sfa',
             'am_code': None,
         }
-        if isinstnace(result, SfaFault):
+        if isinstance(result, SfaFault):
             code['geni_code'] = result.faultCode
-            code['am_code'] = result.faultCode                        
-                
+            code['am_code'] = result.faultCode
+
         return code
 
     def get_geni_value(self, result):
@@ -227,26 +246,26 @@ class SfaApi (XmlrpcApi):
 
     def get_geni_output(self, result):
         output = ""
-        if isinstance(result, SFaFault):
-            output = result.faultString 
+        if isinstance(result, SfaFault):
+            output = result.faultString
         return output
 
-    def prepare_response_v2_am(self, result):
+    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  
+        Converts the specified result into a standard GENI compliant
+        response
         """
-        if self.interface.lower() == 'aggregate': 
-            if hasattr(self.config, 'SFA_AM_API_VERSION') and \
-              self.config.SFA_AM_API_VERSION == "2":
-                result = self.prepare_response_v2_am(result)
+        # 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)
-