deeper pass on xmlrpclib vs xmlrpc.client as well as configparser
[sfa.git] / sfa / server / sfaapi.py
index 7085037..499e3bd 100644 (file)
@@ -1,24 +1,25 @@
 import os, os.path
 import datetime
 
 import os, os.path
 import datetime
 
-from sfa.util.faults import SfaAPIError
+from sfa.util.faults import SfaFault, SfaAPIError, 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.rights import determine_rights
 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.server.xmlrpcapi import XmlrpcApi
+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
     augmented with the local cryptographic material and hrn
 
     It also has the notion of its own interface (a string describing
@@ -30,12 +31,12 @@ class SfaApi (XmlrpcApi):
 
     It gets augmented by the generic layer with 
     (*) an instance of manager (actually a manager module for now)
 
     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', 
     """
 
     def __init__ (self, encoding="utf-8", methods='sfa.methods', 
-                  config = "/etc/sfa/sfa_config.py", 
+                  config = "/etc/sfa/sfa_config", 
                   peer_cert = None, interface = None, 
                   key_file = None, cert_file = None, cache = None):
         
                   peer_cert = None, interface = None, 
                   key_file = None, cert_file = None, cache = None):
         
@@ -68,6 +69,7 @@ class SfaApi (XmlrpcApi):
         
         # filled later on by generic/Generic
         self.manager=None
         
         # filled later on by generic/Generic
         self.manager=None
+        self._dbsession=None
 
     def server_proxy(self, interface, cred, timeout=30):
         """
 
     def server_proxy(self, interface, cred, timeout=30):
         """
@@ -88,10 +90,19 @@ class SfaApi (XmlrpcApi):
         server = interface.server_proxy(key_file, cert_file, timeout)
         return server
                
         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
         """
         type = 'authority'
         path = self.config.SFA_DATA_DIR
@@ -102,14 +113,14 @@ class SfaApi (XmlrpcApi):
             cred = Credential(filename = cred_filename)
             # make sure cred isnt expired
             if not cred.get_expiration or \
             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']:
                 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)
@@ -127,12 +138,12 @@ class SfaApi (XmlrpcApi):
                 
         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):
+    def _getCredential(self):
         """ 
         Get our credential from a remote registry 
         """
         """ 
         Get our credential from a remote registry 
         """
@@ -146,7 +157,7 @@ class SfaApi (XmlrpcApi):
         cred = registry.GetCredential(self_cred, self.hrn, 'authority')
         return Credential(string=cred)
 
         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.
         """
         """
         Get our current credential directly from the local registry.
         """
@@ -158,14 +169,13 @@ class SfaApi (XmlrpcApi):
         if not auth_hrn or hrn == self.config.SFA_INTERFACE_HRN:
             auth_hrn = hrn
         auth_info = self.auth.get_auth_info(auth_hrn)
         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.set_gid_caller(object_gid)
         object_gid = record.get_gid_object()
         new_cred = Credential(subject = object_gid.get_subject())
         new_cred.set_gid_caller(object_gid)
@@ -201,7 +211,54 @@ 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
             self.cache.add(cache_key, server_version, ttl= 60*60*24)
         return server_version
             # cache version for 24 hours
             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, 
+            '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)
+