Ignore:
Timestamp:
Nov 20, 2008 7:14:58 PM (15 years ago)
Author:
Ted Faber <faber@…>
Branches:
axis_example, compt_changes, info-ops, master, version-1.30, version-2.00, version-3.01, version-3.02
Children:
cfabc40
Parents:
c922f23
Message:

Unify the code for calling SOAP and XMLRPC services into a couple classes.
Before there were slightly different semantics everywhere.

Also make the handlers classes rather than the output of stub compiling
functions.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • fedd/fedd_allocate_project.py

    rc922f23 r058f58e  
    7474        # Internal services are SOAP only
    7575        self.soap_services = {\
    76                 "AllocateProject": make_soap_handler(\
     76                "AllocateProject": soap_handler(\
    7777                AllocateProjectRequestMessage.typecode,\
    7878                self.dynamic_project, AllocateProjectResponseMessage,\
    7979                "AllocateProjectResponseBody"),
    80                 "StaticProject": make_soap_handler(\
     80                "StaticProject": soap_handler(\
    8181                StaticProjectRequestMessage.typecode,\
    8282                self.static_project, StaticProjectResponseMessage,\
    8383                "StaticProjectResponseBody"),\
    84                 "ReleaseProject": make_soap_handler(\
     84                "ReleaseProject": soap_handler(\
    8585                ReleaseProjectRequestMessage.typecode,\
    8686                self.release_project, ReleaseProjectResponseMessage,\
     
    345345        return { 'project': req['ReleaseProjectRequestBody']['project']}
    346346
    347 def make_proxy(method, req_name, req_alloc, resp_name):
    348     """
    349     Construct the proxy calling function from the given parameters.
    350     """
    351 
    352     # Define the proxy, NB, the parameters to make_proxy are visible to the
    353     # definition of proxy.
    354     def proxy(self, req, fedid=None):
    355         """
    356         Send req on to a remote project instantiator.
    357 
    358         Req is just the message to be sent.  This function re-wraps it.
    359         It also rethrows any faults.
    360         """
    361 
    362         # No retry loop here.  Proxy servers must correctly authenticate
    363         # themselves without help
    364         try:
    365             ctx = fedd_ssl_context(self.cert_file, self.trusted_certs,
    366                     password=self.cert_pwd)
    367         except SSL.SSLError:
    368             raise service_error(service_error.server_config,
    369                     "Server certificates misconfigured")
    370 
    371         loc = feddInternalServiceLocator();
    372         port = loc.getfeddInternalPortType(self.url,
    373                 transport=M2Crypto.httpslib.HTTPSConnection,
    374                 transdict={ 'ssl_context' : ctx })
    375 
    376         if req.has_key(req_name):
    377             req = req[req_name]
    378         else:
    379             raise service_error(service_error.req, "Bad formated request");
    380 
    381         # Reconstruct the full request message
    382         msg = req_alloc()
    383         set_elem = getattr(msg, "set_element_%s" % req_name)
    384         set_elem(pack_soap(msg, req_name, req))
    385         try:
    386             mattr = getattr(port, method)
    387             resp = mattr(msg)
    388         except ZSI.ParseException, e:
    389             raise service_error(service_error.proxy,
    390                     "Bad format message (XMLRPC??): %s" % str(e))
    391         except ZSI.FaultException, e:
    392             resp = e.fault.detail[0]
    393 
    394         r = unpack_soap(resp)
    395 
    396         if r.has_key(resp_name):
    397             return r[resp_name]
    398         else:
    399             raise service_error(service_error.proxy, "Bad proxy response")
    400     # NB: end of proxy function definition     
    401     return proxy
    402 
    403347class fedd_allocate_project_remote:
    404348    """
    405349    Allocate projects on a remote machine using the internal SOAP interface
    406350    """
    407     dynamic_project = make_proxy("AllocateProject",
    408             "AllocateProjectRequestBody", AllocateProjectRequestMessage,
    409             "AllocateProjectResponseBody")
    410     static_project = make_proxy("StaticProject",
    411             "StaticProjectRequestBody", StaticProjectRequestMessage,
    412             "StaticProjectResponseBody")
    413     release_project = make_proxy("ReleaseProject",
    414             "ReleaseProjectRequestBody", ReleaseProjectRequestMessage,
    415             "ReleaseProjectResponseBody")
    416 
     351    class proxy(service_caller):
     352        """
     353        This class is a proxy functor (callable) that has the same signature as
     354        a function called by soap_handler or xmlrpc_handler, but that used the
     355        service_caller class to call the function remotely.
     356        """
     357
     358        def __init__(self, url, cert_file, cert_pwd, trusted_certs,
     359                method, req_name, req_alloc, resp_name):
     360            service_caller.__init__(self, method, 'getfeddInternalPortType',
     361                    feddInternalServiceLocator, req_alloc, req_name)
     362            self.url = url
     363            self.cert_file = cert_file
     364            self.cert_pwd = cert_pwd
     365            self.trusted_certs = trusted_certs
     366            self.resp_name = resp_name
     367            # Calling the proxy object directly invokes the proxy_call method,
     368            # not the service_call method.
     369            self.__call__ = self.proxy_call
     370           
     371
     372        # Define the proxy, NB, the parameters to make_proxy are visible to the
     373        # definition of proxy.
     374        def proxy_call(self, req, fedid=None):
     375            """
     376            Send req on to a remote project instantiator.
     377
     378            Req is just the message to be sent.  This function re-wraps it.
     379            It also rethrows any faults.
     380            """
     381
     382            if req.has_key(self.request_body_name):
     383                req = req[self.request_body_name]
     384            else:
     385                raise service_error(service_error.req, "Bad formated request");
     386
     387            r = self.call_service(self.url, req, self.cert_file, self.cert_pwd,
     388                    self.trusted_certs)
     389            if r.has_key(self.resp_name):
     390                return r[self.resp_name]
     391            else:
     392                raise service_error(service_error.protocol,
     393                        "Bad proxy response")
     394
     395    # back to defining the fedd_allocate_project_remote class
    417396    def __init__(self, config):
    418397        """
     
    457436        self.log = logging.getLogger("fedd.allocate.remote")
    458437        set_log_level(config, "access", self.log)
     438        # The specializations of the proxy functions
     439        self.dynamic_project = self.proxy(self.url, self.cert_file,
     440                self.cert_pwd, self.trusted_certs, "AllocateProject",
     441                "AllocateProjectRequestBody", AllocateProjectRequestMessage,
     442                "AllocateProjectResponseBody")
     443        self.static_project = self.proxy(self.url, self.cert_file,
     444                self.cert_pwd, self.trusted_certs, "StaticProject",
     445                "StaticProjectRequestBody", StaticProjectRequestMessage,
     446                "StaticProjectResponseBody")
     447        self.release_project = self.proxy(self.url, self.cert_file,
     448                self.cert_pwd, self.trusted_certs, "ReleaseProject",
     449                "ReleaseProjectRequestBody", ReleaseProjectRequestMessage,
     450                "ReleaseProjectResponseBody")
     451
Note: See TracChangeset for help on using the changeset viewer.