コード例 #1
0
    def dispatch(self, ctxt, version, method, namespace, **kwargs):
        """Dispatch a message based on a requested version.

        :param ctxt: The request context
        :param version: The requested API version from the incoming message
        :param method: The method requested to be called by the incoming
                       message.
        :param namespace: The namespace for the requested method.  If None,
                          the dispatcher will look for a method on a callback
                          object with no namespace set.
        :param kwargs: A dict of keyword arguments to be passed to the method.

        :returns: Whatever is returned by the underlying method that gets
                  called.
        """
        if not version:
            version = '1.0'

        had_compatible = False
        for proxyobj in self.callbacks:
            # Check for namespace compatibility
            try:
                cb_namespace = proxyobj.RPC_API_NAMESPACE
            except AttributeError:
                cb_namespace = None

            if namespace != cb_namespace:
                continue

            # Check for version compatibility
            try:
                rpc_api_version = proxyobj.RPC_API_VERSION
            except AttributeError:
                rpc_api_version = '1.0'

            is_compatible = rpc_common.version_is_compatible(rpc_api_version,
                                                             version)
            had_compatible = had_compatible or is_compatible

            if not hasattr(proxyobj, method):
                continue
            if is_compatible:
                kwargs = self._deserialize_args(ctxt, kwargs)
                result = getattr(proxyobj, method)(ctxt, **kwargs)
                return self.serializer.serialize_entity(ctxt, result)

        if had_compatible:
            raise AttributeError("No such RPC function '%s'" % method)
        else:
            raise rpc_common.UnsupportedRpcVersion(version=version)