Exemple #1
0
    def do_request(self, method, **kwargs):
        """
        Simple do_request override. This method serializes
        the outgoing body and builds the command that will
        be sent.

        :params method: The remote python method to call
        :params kwargs: Dynamic parameters that will be
            passed to the remote method.
        """
        content = self.bulk_request([{'command': method, 'kwargs': kwargs}])

        # NOTE(flaper87): Return the first result if
        # a single command was executed.
        content = content[0]

        # NOTE(flaper87): Check if content is an error
        # and re-raise it if raise_exc is True. Before
        # checking if content contains the '_error' key,
        # verify if it is an instance of dict - since the
        # RPC call may have returned something different.
        if self.raise_exc and (isinstance(content, dict)
                               and '_error' in content):
            error = content['_error']
            try:
                exc_cls = imp.import_class(error['cls'])
                raise exc_cls(error['val'])
            except ImportError:
                # NOTE(flaper87): The exception
                # class couldn't be imported, using
                # a generic exception.
                raise exception.RPCError(**error)
        return content
Exemple #2
0
    def do_request(self, method, **kwargs):
        """
        Simple do_request override. This method serializes
        the outgoing body and builds the command that will
        be sent.

        :params method: The remote python method to call
        :params kwargs: Dynamic parameters that will be
            passed to the remote method.
        """
        content = self.bulk_request([{'command': method,
                                      'kwargs': kwargs}])

        # NOTE(flaper87): Return the first result if
        # a single command was executed.
        content = content[0]
        if self.raise_exc and (content and '_error' in content):
            error = content['_error']
            try:
                exc_cls = imp.import_class(error['cls'])
                raise exc_cls(error['val'])
            except ImportError:
                # NOTE(flaper87): The exception
                # class couldn't be imported, using
                # a generic exception.
                raise exception.RPCError(**error)
        return content
Exemple #3
0
    def __call__(self, req, body):
        """
        Executes the command
        """

        if not isinstance(body, list):
            msg = _("Request must be a list of commands")
            raise exc.HTTPBadRequest(explanation=msg)

        def validate(cmd):
            if not isinstance(cmd, dict):
                msg = _("Bad Command: %s") % str(cmd)
                raise exc.HTTPBadRequest(explanation=msg)

            command, kwargs = cmd.get("command"), cmd.get("kwargs")

            if (not command or not isinstance(command, six.string_types)
                    or (kwargs and not isinstance(kwargs, dict))):
                msg = _("Wrong command structure: %s") % (str(cmd))
                raise exc.HTTPBadRequest(explanation=msg)

            method = self._registered.get(command)
            if not method:
                # Just raise 404 if the user tries to
                # access a private method. No need for
                # 403 here since logically the command
                # is not registered to the rpc dispatcher
                raise exc.HTTPNotFound(explanation=_("Command not found"))

            return True

        # If more than one command were sent then they might
        # be intended to be executed sequentially, that for,
        # lets first verify they're all valid before executing
        # them.
        commands = filter(validate, body)

        results = []
        for cmd in commands:
            # kwargs is not required
            command, kwargs = cmd["command"], cmd.get("kwargs", {})
            method = self._registered[command]
            try:
                result = method(req.context, **kwargs)
            except Exception as e:
                if self.raise_exc:
                    raise

                cls, val = e.__class__, utils.exception_to_str(e)
                msg = (_("RPC Call Error: %(val)s\n%(tb)s") %
                       dict(val=val, tb=traceback.format_exc()))
                LOG.error(msg)

                # NOTE(flaper87): Don't propagate all exceptions
                # but the ones allowed by the user.
                module = cls.__module__
                if module not in CONF.allowed_rpc_exception_modules:
                    cls = exception.RPCError
                    val = six.text_type(exception.RPCError(cls=cls, val=val))

                cls_path = "%s.%s" % (cls.__module__, cls.__name__)
                result = {"_error": {"cls": cls_path, "val": val}}
            results.append(result)
        return results