X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=sfa%2Futil%2Fapi.py;h=dca8f51e94d36696b5c5d47c2e7febe7d0ca9295;hb=57b6a99255d4a88be9c0f910f8524677e34ff4bc;hp=5c5813fb3c1f317dddd64119c62dbdfb48af9358;hpb=2f0e1e03cfe5982a322d0ee1e24ac9751029df33;p=sfa.git diff --git a/sfa/util/api.py b/sfa/util/api.py index 5c5813fb..dca8f51e 100644 --- a/sfa/util/api.py +++ b/sfa/util/api.py @@ -1,24 +1,19 @@ # # SFA XML-RPC and SOAP interfaces # -### $Id$ -### $URL$ -# -import sys -import os -import traceback import string import xmlrpclib +from sfa.util.faults import SfaNotImplemented, SfaAPIError, SfaInvalidAPIMethod, SfaFault +from sfa.util.config import Config +from sfa.util.sfalogging import logger from sfa.trust.auth import Auth -from sfa.util.config import * -from sfa.util.faults import * -from sfa.util.debug import * -from sfa.trust.credential import * -from sfa.trust.certificate import * -from sfa.util.namespace import * -from sfa.util.sfalogging import * +from sfa.util.cache import Cache +from sfa.trust.certificate import Keypair, Certificate + +# this is wrong all right, but temporary +from sfa.managers.import_manager import import_manager # See "2.2 Characters" in the XML specification: # @@ -95,14 +90,33 @@ def import_deep(name): mod = getattr(mod, comp) return mod +class ManagerWrapper: + """ + This class acts as a wrapper around an SFA interface manager module, but + can be used with any python module. The purpose of this class is raise a + SfaNotImplemented exception if someone attempts to use an attribute + (could be a callable) thats not available in the library by checking the + library using hasattr. This helps to communicate better errors messages + to the users and developers in the event that a specifiec operation + is not implemented by a libarary and will generally be more helpful than + the standard AttributeError + """ + def __init__(self, manager, interface): + self.manager = manager + self.interface = interface + + def __getattr__(self, method): + if not hasattr(self.manager, method): + raise SfaNotImplemented(method, self.interface) + return getattr(self.manager, method) + class BaseAPI: - cache = None protocol = None def __init__(self, config = "/etc/sfa/sfa_config.py", encoding = "utf-8", methods='sfa.methods', peer_cert = None, interface = None, - key_file = None, cert_file = None, cache = cache): + key_file = None, cert_file = None, cache = None): self.encoding = encoding @@ -113,7 +127,6 @@ class BaseAPI: # Better just be documenting the API if config is None: return - # Load configuration self.config = Config(config) self.auth = Auth(peer_cert) @@ -124,19 +137,44 @@ class BaseAPI: self.cert_file = cert_file self.cert = Certificate(filename=self.cert_file) self.cache = cache + if self.cache is None: + self.cache = Cache() self.credential = None self.source = None self.time_format = "%Y-%m-%d %H:%M:%S" - self.logger=get_sfa_logger() - + self.logger = logger + # load registries from sfa.server.registry import Registries - self.registries = Registries(self) + self.registries = Registries() # load aggregates from sfa.server.aggregate import Aggregates - self.aggregates = Aggregates(self) + self.aggregates = Aggregates() + + + 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 callable(self, method): """ @@ -192,9 +230,12 @@ class BaseAPI: try: result = self.call(source, method, *args) + except SfaFault, fault: + result = fault except Exception, fault: - traceback.print_exc(file = log) - result = fault + logger.log_exc("BaseAPI.handle has caught Exception") + result = SfaAPIError(fault) + # Return result response = self.prepare_response(result, method) @@ -206,7 +247,7 @@ class BaseAPI: """ if self.protocol == 'xmlrpclib': - if not isinstance(result, Exception): + if not isinstance(result, SfaFault): result = (result,) response = xmlrpclib.dumps(result, methodresponse = True, encoding = self.encoding, allow_none = 1) elif self.protocol == 'soap': @@ -220,3 +261,14 @@ class BaseAPI: raise result return response + + def get_cached_server_version(self, server): + cache_key = server.url + "-version" + server_version = None + if self.cache: + server_version = self.cache.get(cache_key) + if not server_version: + server_version = server.GetVersion() + # cache version for 24 hours + self.cache.add(cache_key, server_version, ttl= 60*60*24) + return server_version