Esempio n. 1
0
class _AviaryCommon(object):
    def __init__(self, name, locator, 
                 key="", cert="", root_cert="", domain_verify=True):

        self.transports = TransportFactory(key, cert, root_cert, domain_verify)

        # Log init messages from TransportFactory
        self.transports.log_details(log, "AviaryOperations")
        self.name = name

        # Put this here to be referenced by AviaryOperations types
        self.locator = locator

        self.type_to_aviary = self._type_to_aviary()
        self.aviary_to_type = self._aviary_to_type()

    def get_datadir(self, datadir, subdir):
        if not type(datadir) in (tuple, list):
            datadir = [datadir]

        # Find the first element in datadir that is a valid
        # path.  If the path has a subdirectory called 
        # "subdir", consider that part of the path.
        for d in datadir:
            if os.path.isdir(d):
                s = os.path.join(d, subdir)
                if os.path.isdir(s):
                    return s
                return d
        # Hmm, well, just return the first one since we're
        # going to get an error anyway.
        return datadir[0]

    @classmethod
    def _type_to_aviary(cls):
        # Need to be able to turn simple Python types into Aviary types for attributes
        return {int: "INTEGER", float: "FLOAT", str: "STRING", bool: "BOOLEAN"}

    @classmethod
    def _aviary_to_type(cls):
        return {"INTEGER": int, "FLOAT": float, "STRING": str, "BOOLEAN": bool}

    def _set_client_info(self, client, refresh=False):
        scheme, host = client.server_list.find_server(client.service_name, 
                                                      refresh)

        # Have to set the URL for the method.  This might go away someday...
        client.set_options(location=host+client.method_name)

        # Since we pool the clients and reuse them for different requests
        # and since its possible to be using servers with different schemes,
        # we have to always reset the transport here.
        the_transport = self.transports.get_transport(scheme)
        client.set_options(transport=the_transport)

    def _setup_client(self, client, server_list, name, meth_name):
        # Look up the host and construct the URL.
        # Store information in the client so that retry is possible.
        client.server_list = server_list
        client.service_name = name
        client.method_name = meth_name

        # This is initial setup before a call so we want to try a 
        # refresh on the server list if our service comes up missing
        self._set_client_info(client, refresh="on_no_host")
        return client

    @classmethod
    def _get_status(cls, result):
        # For Aviary operations, if the operation
        # did not work the reason is in the text field.
        # In cumin, we want to pass any error text as
        # the status parameter to callbacks
        if result.code != "OK":
            return result.text
        return result.code

    @classmethod
    def _cb_args_dataless(cls, result):
        # Marshal data in result for passing to standard callback.
        # This routine is for results that contain status only, no data.
        if isinstance(result, Exception):
            status = result
        else:
            status = _AviaryCommon._get_status(result)
        return (status, None)

    @classmethod
    def _pretty_result(cls, result, host):
        if isinstance(result, urllib2.URLError):
            return Exception("Trouble reaching host %s, %s" % (host, result.reason))
        elif isinstance(result, Exception):
            if hasattr(result, "args"):
                reason = result.args
            else:
                reason = str(result)
            return Exception("Operation failed on host %s, %s" % (host, reason))
        return result

    def call_client_retry(self, client, meth_name, *meth_args, **meth_kwargs):
        # If we fail with a urllib2.URLError (or anything similar) then try
        # attempt to get a new endpoint and try again.
        meth = getattr(client.service, meth_name)
        try:
            result = meth(*meth_args, **meth_kwargs)
        except Exception, e:
            # If we get an exception, our endpoint may have moved 
            # (probably due to a restart on the condor side)
            # Let's get new endpoints, reset the client, 
            # and try again.
            if client.server_list.should_retry:
                log.debug("AviaryOperations: received %s, retrying %s"\
                              % (str(e), client.options.location))
                self._set_client_info(client, refresh=True)
                result = meth(*meth_args, **meth_kwargs)
            else:
                raise e
        return result