Exemplo n.º 1
0
 def _to_remote_error(self, error):
     """Converts the given exception to the one with the _Remote suffix."""
     exc_info = (type(error), error, None)
     serialized = rpc_common.serialize_remote_exception(exc_info)
     remote_error = rpc_common.deserialize_remote_exception(
         serialized, ["heat.common.exception"])
     return remote_error
Exemplo n.º 2
0
 def _to_remote_error(self, error):
     '''Converts the given exception to one with the _Remote suffix.'''
     exc_info = (type(error), error, None)
     serialized = rpc_common.serialize_remote_exception(exc_info)
     remote_error = rpc_common.deserialize_remote_exception(
         serialized, ["senlin.common.exception"])
     return remote_error
Exemplo n.º 3
0
 def _to_remote_error(self, error):
     '''Converts the given exception to one with the _Remote suffix.'''
     exc_info = (type(error), error, None)
     serialized = rpc_common.serialize_remote_exception(exc_info)
     remote_error = rpc_common.deserialize_remote_exception(
         serialized, ["senlin.common.exception"])
     return remote_error
Exemplo n.º 4
0
    def test_should_not_ignore_parent_classes_even_for_remote_ones(self):
        # We want tracebacks
        cfg.CONF.set_override('debug', True)

        error = ClusterNotFoundChild(cluster='a')
        exc_info = (type(error), error, None)
        serialized = rpc_common.serialize_remote_exception(exc_info)
        remote_error = rpc_common.deserialize_remote_exception(
            serialized, ["senlin.tests.unit.middleware.test_fault_middleware"])

        wrapper = fault.FaultWrapper(None)
        msg = wrapper._error(remote_error)
        expected_message, expected_traceback = six.text_type(remote_error).\
            split('\n', 1)
        expected = {
            'code': 404,
            'error': {
                'code': 404,
                'message': expected_message,
                'traceback': expected_traceback,
                'type': 'ClusterNotFoundChild'
            },
            'explanation': 'The resource could not be found.',
            'title': 'Not Found'
        }
        self.assertEqual(expected, msg)
Exemplo n.º 5
0
    def remote_exception_helper(self, name, error):
        exc_info = (type(error), error, None)

        serialized = rpc_common.serialize_remote_exception(exc_info)
        remote_error = rpc_common.deserialize_remote_exception(
            serialized, name)
        wrapper = fault.FaultWrapper(None)
        msg = wrapper._error(remote_error)
        print msg
        errmsg = {
            'code': 500,
            'error': {'message': msg['response']['error']['message'],
                      'traceback': None,
                      'type': 'RemoteError'},
            'explanation': msg['response']['explanation'],
            'title': 'Internal Server Error'}
        expected = {
            'success': False,
            'response': errmsg,
            'install': {
                'success': False,
                'response': ''
            },
            'test': {
                'success': False,
                'response': ''
            },
            'deploy': {
                'success': False,
                'response': ''
            }
        }
        self.assertEqual(expected, msg)
Exemplo n.º 6
0
 def _to_remote_error(self, error):
     """Converts the given exception to the one with the _Remote suffix."""
     exc_info = (type(error), error, None)
     serialized = rpc_common.serialize_remote_exception(exc_info)
     remote_error = rpc_common.deserialize_remote_exception(
         serialized, ["heat.common.exception"])
     return remote_error
Exemplo n.º 7
0
 def test_remote_exception(self):
     # We want tracebacks
     cfg.CONF.set_override('debug', True)
     error = validator_exc.InvalidContentType(content_type='a')
     exc_info = (type(error), error, None)
     serialized = rpc_common.serialize_remote_exception(exc_info)
     remote_error = rpc_common.deserialize_remote_exception(
         serialized, ["validator.common.exception"])
     wrapper = fault.FaultWrapper(None)
     msg = wrapper._error(remote_error)
     expected_message, expected_traceback = six.text_type(
         remote_error).split('\n', 1)
     error = {u'code': 500,
              u'error': {u'message': u'Invalid content type %(content_type)s',
                         u'traceback': u'InvalidContentType: Invalid content type a\n',
                         u'type': 'InvalidContentType'},
              u'explanation': 'The server has either erred or is incapable of performing the requested operation.',
              u'title': 'Internal Server Error'}
     expected = {
         'success': False,
         'response': error,
         'install': {
             'success': False,
             'response': ''
         },
         'test': {
             'success': False,
             'response': ''
         },
         'deploy': {
             'success': False,
             'response': ''
         }
     }
     self.assertEqual(expected, msg)
Exemplo n.º 8
0
    def test_should_not_ignore_parent_classes_even_for_remote_ones(self):
        # We want tracebacks
        cfg.CONF.set_override('debug', True)

        error = ClusterNotFoundChild(cluster='a')
        exc_info = (type(error), error, None)
        serialized = rpc_common.serialize_remote_exception(exc_info)
        remote_error = rpc_common.deserialize_remote_exception(
            serialized, ["senlin.tests.middleware.test_fault_middleware"])

        wrapper = fault.FaultWrapper(None)
        msg = wrapper._error(remote_error)
        expected_message, expected_traceback = six.text_type(remote_error).\
            split('\n', 1)
        expected = {
            'code': 404,
            'error': {
                'code': 404,
                'message': expected_message,
                'traceback': expected_traceback,
                'type': 'ClusterNotFoundChild'
            },
            'explanation': 'The resource could not be found.',
            'title': 'Not Found'
        }
        self.assertEqual(expected, msg)
Exemplo n.º 9
0
def to_remote_error(error):
    '''Prepend the given exception with the _Remote suffix.'''

    exc_info = (type(error), error, None)
    serialized = rpc_common.serialize_remote_exception(exc_info)
    remote_error = rpc_common.deserialize_remote_exception(
        serialized, ["senlin.common.exception"])
    return remote_error
Exemplo n.º 10
0
def unmarshal_response(message, allowed):
    # TODO(kgiusti) This may fail to unpack and raise an exception. Need to
    # communicate this to the caller!
    data = jsonutils.loads(message.body)
    failure = data.get('failure')
    if failure is not None:
        raise common.deserialize_remote_exception(failure, allowed)
    return data.get("response")
Exemplo n.º 11
0
def to_remote_error(error):
    '''Prepend the given exception with the _Remote suffix.'''

    exc_info = (type(error), error, None)
    serialized = rpc_common.serialize_remote_exception(exc_info)
    remote_error = rpc_common.deserialize_remote_exception(
        serialized, ["senlin.common.exception"])
    return remote_error
Exemplo n.º 12
0
    def _process_reply(self, data):
        self.msg_id_cache.check_duplicate_message(data)
        if data["failure"]:
            failure = data["failure"]
            result = rpc_common.deserialize_remote_exception(failure, self.allowed_remote_exmods)
        else:
            result = data.get("result", None)

        ending = data.get("ending", False)
        return result, ending
Exemplo n.º 13
0
    def _process_reply(self, data):
        self.msg_id_cache.check_duplicate_message(data)
        if data['failure']:
            failure = data['failure']
            result = rpc_common.deserialize_remote_exception(
                failure, self.allowed_remote_exmods)
        else:
            result = data.get('result', None)

        ending = data.get('ending', False)
        return result, ending
Exemplo n.º 14
0
 def _process_reply(self, data):
     result = None
     ending = False
     self.msg_id_cache.check_duplicate_message(data)
     if data['failure']:
         failure = data['failure']
         result = rpc_common.deserialize_remote_exception(
             failure, self.allowed_remote_exmods)
     elif data.get('ending', False):
         ending = True
     else:
         result = data['result']
     return result, ending
    def send_request(self, request):
        reply_future = self.sender.send_request(request)
        try:
            reply = reply_future.result(timeout=request.timeout)
        except futures.TimeoutError:
            raise oslo_messaging.MessagingTimeout("Timeout %s seconds was reached" % request.timeout)
        finally:
            self.reply_waiter.untrack_id(request.message_id)

        LOG.debug("Received reply %s", reply)
        if reply[zmq_names.FIELD_FAILURE]:
            raise rpc_common.deserialize_remote_exception(reply[zmq_names.FIELD_FAILURE], request.allowed_remote_exmods)
        else:
            return reply[zmq_names.FIELD_REPLY]
Exemplo n.º 16
0
    def remote_exception_helper(self, name, error):
        error.args = ()
        exc_info = (type(error), error, None)

        serialized = rpc_common.serialize_remote_exception(exc_info)
        remote_error = rpc_common.deserialize_remote_exception(
            serialized, name)
        wrapper = fault.FaultWrapper(None)
        msg = wrapper._error(remote_error)
        expected = {'code': 500,
                    'error': {'traceback': None,
                              'type': 'RemoteError'},
                    'explanation': msg['explanation'],
                    'title': 'Internal Server Error'}
        self.assertEqual(expected, msg)
Exemplo n.º 17
0
    def send_request(self, request):
        reply_future = self.sender.send_request(request)
        try:
            reply = reply_future.result(timeout=request.timeout)
        except futures.TimeoutError:
            raise oslo_messaging.MessagingTimeout(
                "Timeout %s seconds was reached" % request.timeout)
        finally:
            self.reply_waiter.untrack_id(request.message_id)

        LOG.debug("Received reply %s", reply)
        if reply[zmq_names.FIELD_FAILURE]:
            raise rpc_common.deserialize_remote_exception(
                reply[zmq_names.FIELD_FAILURE], request.allowed_remote_exmods)
        else:
            return reply[zmq_names.FIELD_REPLY]
Exemplo n.º 18
0
    def remote_exception_helper(self, name, error):
        if six.PY3:
            error.args = ()
        exc_info = (type(error), error, None)

        serialized = rpc_common.serialize_remote_exception(exc_info)
        remote_error = rpc_common.deserialize_remote_exception(
            serialized, name)
        wrapper = fault.FaultWrapper(None)
        msg = wrapper._error(remote_error)
        expected = {'code': 500,
                    'error': {'traceback': None,
                              'type': 'RemoteError'},
                    'explanation': msg['explanation'],
                    'title': 'Internal Server Error'}
        self.assertEqual(expected, msg)
Exemplo n.º 19
0
    def remote_exception_helper(self, name, error):
        if six.PY3:
            error.args = ()
        exc_info = (type(error), error, None)

        serialized = rpc_common.serialize_remote_exception(exc_info)
        remote_error = rpc_common.deserialize_remote_exception(serialized, name)
        wrapper = fault.FaultWrapper(None)
        msg = wrapper._error(remote_error)
        expected = {
            "code": 500,
            "error": {"message": msg["error"]["message"], "traceback": None, "type": "RemoteError"},
            "explanation": msg["explanation"],
            "title": "Internal Server Error",
        }
        self.assertEqual(expected, msg)
Exemplo n.º 20
0
    def _receive_reply(socket, request):
        def _receive_method(socket):
            return socket.recv_pyobj()

        # NOTE(ozamiatin): Check for retry here (no retries now)
        with contextlib.closing(zmq_async.get_reply_poller()) as poller:
            poller.register(socket, recv_method=_receive_method)
            reply, socket = poller.poll(timeout=request.timeout)
            if reply is None:
                raise oslo_messaging.MessagingTimeout(
                    "Timeout %s seconds was reached" % request.timeout)
            if reply[zmq_names.FIELD_FAILURE]:
                raise rpc_common.deserialize_remote_exception(
                    reply[zmq_names.FIELD_FAILURE],
                    request.allowed_remote_exmods)
            else:
                return reply[zmq_names.FIELD_REPLY]
Exemplo n.º 21
0
 def test_remote_exception(self):
     # We want tracebacks
     cfg.CONF.set_override("debug", True)
     error = heat_exc.EntityNotFound(entity="Stack", name="a")
     exc_info = (type(error), error, None)
     serialized = rpc_common.serialize_remote_exception(exc_info)
     remote_error = rpc_common.deserialize_remote_exception(serialized, ["heat.common.exception"])
     wrapper = fault.FaultWrapper(None)
     msg = wrapper._error(remote_error)
     expected_message, expected_traceback = six.text_type(remote_error).split("\n", 1)
     expected = {
         "code": 404,
         "error": {"message": expected_message, "traceback": expected_traceback, "type": "EntityNotFound"},
         "explanation": "The resource could not be found.",
         "title": "Not Found",
     }
     self.assertEqual(expected, msg)
Exemplo n.º 22
0
    def _receive_reply(socket, request):

        def _receive_method(socket):
            return socket.recv_pyobj()

        # NOTE(ozamiatin): Check for retry here (no retries now)
        with contextlib.closing(zmq_async.get_reply_poller()) as poller:
            poller.register(socket, recv_method=_receive_method)
            reply, socket = poller.poll(timeout=request.timeout)
            if reply is None:
                raise oslo_messaging.MessagingTimeout(
                    "Timeout %s seconds was reached" % request.timeout)
            if reply[zmq_names.FIELD_FAILURE]:
                raise rpc_common.deserialize_remote_exception(
                    reply[zmq_names.FIELD_FAILURE],
                    request.allowed_remote_exmods)
            else:
                return reply[zmq_names.FIELD_REPLY]
Exemplo n.º 23
0
 def test_remote_exception(self):
     # We want tracebacks
     cfg.CONF.set_override('debug', True)
     error = heat_exc.EntityNotFound(entity='Stack', name='a')
     exc_info = (type(error), error, None)
     serialized = rpc_common.serialize_remote_exception(exc_info)
     remote_error = rpc_common.deserialize_remote_exception(
         serialized, ["heat.common.exception"])
     wrapper = fault.FaultWrapper(None)
     msg = wrapper._error(remote_error)
     expected_message, expected_traceback = str(
         remote_error).split('\n', 1)
     expected = {'code': 404,
                 'error': {'message': expected_message,
                           'traceback': expected_traceback,
                           'type': 'EntityNotFound'},
                 'explanation': 'The resource could not be found.',
                 'title': 'Not Found'}
     self.assertEqual(expected, msg)
Exemplo n.º 24
0
    def test_should_not_ignore_parent_classes_even_for_remote_ones(self):
        # We want tracebacks
        cfg.CONF.set_override('debug', True)

        error = StackNotFoundChild(stack_name='a')
        exc_info = (type(error), error, None)
        serialized = rpc_common.serialize_remote_exception(exc_info)
        remote_error = rpc_common.deserialize_remote_exception(
            serialized, ["validator.tests.test_fault_middleware"])

        wrapper = fault.FaultWrapper(None)
        msg = wrapper._error(remote_error)
        expected_message, expected_traceback = six.text_type(
            remote_error).split('\n', 1)
        error = {u'code': 500,
                 u'error': {
                     u'message': u"Remote error: StackNotFoundChild "
                                 u"The %(entity)s (%(name)s) could not be "
                                 u"found.\n[u'StackNotFoundChild: "
                                 u"The %(entity)s (%(name)s) "
                                 u"could not be found.\\n'].",
                     u'traceback': 'None\n',
                     u'type': 'RemoteError'},
                 u'explanation': 'The server has either erred or is incapable '
                                 'of performing the requested operation.',
                 u'title': 'Internal Server Error'}
        expected = {
            'success': False,
            'response': error,
            'install': {
                'success': False,
                'response': ''
            },
            'test': {
                'success': False,
                'response': ''
            },
            'deploy': {
                'success': False,
                'response': ''
            }
        }
        self.assertEqual(expected, msg)
Exemplo n.º 25
0
 def test_remote_exception(self):
     # We want tracebacks
     cfg.CONF.set_override('debug', True)
     error = heat_exc.EntityNotFound(entity='Stack', name='a')
     exc_info = (type(error), error, None)
     serialized = rpc_common.serialize_remote_exception(exc_info)
     remote_error = rpc_common.deserialize_remote_exception(
         serialized, ["heat.common.exception"])
     wrapper = fault.FaultWrapper(None)
     msg = wrapper._error(remote_error)
     expected_message, expected_traceback = six.text_type(
         remote_error).split('\n', 1)
     expected = {'code': 404,
                 'error': {'message': expected_message,
                           'traceback': expected_traceback,
                           'type': 'EntityNotFound'},
                 'explanation': 'The resource could not be found.',
                 'title': 'Not Found'}
     self.assertEqual(expected, msg)
    def _recv_reply(self, request):
        reply_future, = self.receiver.track_request(request)

        try:
            _, reply = reply_future.result(timeout=request.timeout)
        except AssertionError:
            LOG.error(_LE("Message format error in reply for %s"),
                      request.message_id)
            return None
        except futures.TimeoutError:
            self._raise_timeout(request)
        finally:
            self.receiver.untrack_request(request)

        if reply.failure:
            raise rpc_common.deserialize_remote_exception(
                reply.failure, request.allowed_remote_exmods)
        else:
            return reply.reply_body
    def send_request(self, request):
        reply_future = self.sender.send_request(request)
        try:
            reply = reply_future.result(timeout=request.timeout)
            LOG.debug("Received reply %s", request.message_id)
        except AssertionError:
            LOG.error(_LE("Message format error in reply %s"), request.message_id)
            return None
        except futures.TimeoutError:
            raise oslo_messaging.MessagingTimeout(
                "Timeout %(tout)s seconds was reached for message %(id)s"
                % {"tout": request.timeout, "id": request.message_id}
            )
        finally:
            self.reply_waiter.untrack_id(request.message_id)

        if reply.failure:
            raise rpc_common.deserialize_remote_exception(reply.failure, request.allowed_remote_exmods)
        else:
            return reply.reply_body
    def receive_reply(self, socket, request):
        self.receiver.register_socket(socket)
        _, reply_future = self.receiver.track_request(request)

        try:
            reply = reply_future.result(timeout=request.timeout)
            self._check_reply(reply, request)
        except AssertionError:
            LOG.error(_LE("Message format error in reply for %s"),
                      request.message_id)
            return None
        except futures.TimeoutError:
            self._raise_timeout(request)
        finally:
            self._finally_unregister(socket, request)

        if reply.failure:
            raise rpc_common.deserialize_remote_exception(
                reply.failure, request.allowed_remote_exmods)
        else:
            return reply.reply_body
Exemplo n.º 29
0
 def test_remote_exception(self):
     cfg.CONF.set_override('debug', True, enforce_type=True)
     error = senlin_exc.ClusterNotFound(cluster='a')
     exc_info = (type(error), error, None)
     serialized = rpc_common.serialize_remote_exception(exc_info)
     remote_error = rpc_common.deserialize_remote_exception(
         serialized, ["senlin.common.exception"])
     wrapper = fault.FaultWrapper(None)
     msg = wrapper._error(remote_error)
     expected_message = six.text_type(remote_error).split('\n', 1)[0]
     expected = {
         'code': 404,
         'error': {
             'code': 404,
             'message': expected_message,
             'type': 'ClusterNotFound'
         },
         'explanation': 'The resource could not be found.',
         'title': 'Not Found'
     }
     self.assertEqual(expected, msg)
Exemplo n.º 30
0
 def test_remote_exception(self):
     cfg.CONF.set_override('debug', True)
     error = senlin_exc.ResourceNotFound(type='cluster', id='a')
     exc_info = (type(error), error, None)
     serialized = rpc_common.serialize_remote_exception(exc_info)
     remote_error = rpc_common.deserialize_remote_exception(
         serialized, ["senlin.common.exception"])
     wrapper = fault.FaultWrapper(None)
     msg = wrapper._error(remote_error)
     expected_message = six.text_type(remote_error).split('\n', 1)[0]
     expected = {
         'code': 404,
         'error': {
             'code': 404,
             'message': expected_message,
             'type': 'ResourceNotFound'
         },
         'explanation': 'The resource could not be found.',
         'title': 'Not Found'
     }
     self.assertEqual(expected, msg)
    def test_deserialize_remote_exception(self):
        failure = {
            'class': self.clsname,
            'module': self.modname,
            'message': 'test',
            'tb': ['traceback\ntraceback\n'],
            'args': self.args,
            'kwargs': self.kwargs,
        }

        serialized = jsonutils.dumps(failure)

        ex = exceptions.deserialize_remote_exception(serialized, self.allowed)

        self.assertIsInstance(ex, self.cls)
        self.assertEqual(self.remote_name, ex.__class__.__name__)
        self.assertEqual(self.str, str(ex))
        if hasattr(self, 'msg'):
            self.assertEqual(self.msg, str(ex))
            self.assertEqual((self.msg, ) + self.remote_args, ex.args)
        else:
            self.assertEqual(self.remote_args, ex.args)
    def receive_reply(self, socket, request):
        self.receiver.register_socket(socket)
        reply_future = \
            self.receiver.track_request(request)[zmq_names.REPLY_TYPE]

        try:
            reply_id, reply = reply_future.result(timeout=request.timeout)
            self._check_received_data(reply_id, reply, request)
        except AssertionError:
            LOG.error(_LE("Message format error in reply for %s"),
                      request.message_id)
            return None
        except futures.TimeoutError:
            self._raise_timeout(request)
        finally:
            self._finally_unregister(socket, request)

        if reply.failure:
            raise rpc_common.deserialize_remote_exception(
                reply.failure, request.allowed_remote_exmods)
        else:
            return reply.reply_body
    def test_deserialize_remote_exception(self):
        failure = {
            'class': self.clsname,
            'module': self.modname,
            'message': 'test',
            'tb': ['traceback\ntraceback\n'],
            'args': self.args,
            'kwargs': self.kwargs,
        }

        serialized = jsonutils.dumps(failure)

        ex = exceptions.deserialize_remote_exception(serialized, self.allowed)

        self.assertIsInstance(ex, self.cls)
        self.assertEqual(self.remote_name, ex.__class__.__name__)
        self.assertEqual(self.str, six.text_type(ex))
        if hasattr(self, 'msg'):
            self.assertEqual(self.msg, six.text_type(ex))
            self.assertEqual((self.msg,) + self.remote_args, ex.args)
        else:
            self.assertEqual(self.remote_args, ex.args)
    def send_request(self, request):
        reply_future = self.sender.send_request(request)
        try:
            reply = reply_future.result(timeout=request.timeout)
            LOG.debug("Received reply %s", request.message_id)
        except AssertionError:
            LOG.error(_LE("Message format error in reply %s"),
                      request.message_id)
            return None
        except futures.TimeoutError:
            raise oslo_messaging.MessagingTimeout(
                "Timeout %(tout)s seconds was reached for message %(id)s" % {
                    "tout": request.timeout,
                    "id": request.message_id
                })
        finally:
            self.reply_waiter.untrack_id(request.message_id)

        if reply.failure:
            raise rpc_common.deserialize_remote_exception(
                reply.failure, request.allowed_remote_exmods)
        else:
            return reply.reply_body
Exemplo n.º 35
0
def _call(addr,
          context,
          topic,
          msg,
          timeout=None,
          envelope=False,
          allowed_remote_exmods=None):
    allowed_remote_exmods = allowed_remote_exmods or []
    # timeout_response is how long we wait for a response
    timeout = timeout or CONF.rpc_response_timeout

    # The msg_id is used to track replies.
    msg_id = uuid.uuid4().hex

    # Replies always come into the reply service.
    reply_topic = "zmq_replies.%s" % CONF.rpc_zmq_host

    LOG.debug("Creating payload")
    # Curry the original request into a reply method.
    mcontext = RpcContext.marshal(context)
    payload = {
        'method': '-reply',
        'args': {
            'msg_id': msg_id,
            'topic': reply_topic,
            # TODO(ewindisch): safe to remove mcontext in I.
            'msg': [mcontext, msg]
        }
    }

    LOG.debug("Creating queue socket for reply waiter")

    # Messages arriving async.
    # TODO(ewindisch): have reply consumer with dynamic subscription mgmt
    with Timeout(timeout, exception=rpc_common.Timeout):
        try:
            msg_waiter = ZmqSocket("ipc://%s/zmq_topic_zmq_replies.%s" %
                                   (CONF.rpc_zmq_ipc_dir, CONF.rpc_zmq_host),
                                   zmq.SUB,
                                   subscribe=msg_id,
                                   bind=False)

            LOG.debug("Sending cast: %s", topic)
            _cast(addr, context, topic, payload, envelope=envelope)

            LOG.debug("Cast sent; Waiting reply")
            # Blocks until receives reply
            msg = msg_waiter.recv()
            if msg is None:
                raise rpc_common.Timeout()
            LOG.debug("Received message: %s", msg)
            LOG.debug("Unpacking response")

            if msg[2] == 'cast':  # Legacy version
                raw_msg = _deserialize(msg[-1])[-1]
            elif msg[2] == 'impl_zmq_v2':
                rpc_envelope = unflatten_envelope(msg[4:])
                raw_msg = rpc_common.deserialize_msg(rpc_envelope)
            else:
                raise rpc_common.UnsupportedRpcEnvelopeVersion(
                    _("Unsupported or unknown ZMQ envelope returned."))

            responses = raw_msg['args']['response']
        # ZMQError trumps the Timeout error.
        except zmq.ZMQError:
            raise RPCException("ZMQ Socket Error")
        except (IndexError, KeyError):
            raise RPCException(_("RPC Message Invalid."))
        finally:
            if 'msg_waiter' in vars():
                msg_waiter.close()

    # It seems we don't need to do all of the following,
    # but perhaps it would be useful for multicall?
    # One effect of this is that we're checking all
    # responses for Exceptions.
    for resp in responses:
        if isinstance(resp, types.DictType) and 'exc' in resp:
            raise rpc_common.deserialize_remote_exception(
                resp['exc'], allowed_remote_exmods)

    return responses[-1]
Exemplo n.º 36
0
def _call(addr, context, topic, msg, timeout=None,
          envelope=False, allowed_remote_exmods=None):
    allowed_remote_exmods = allowed_remote_exmods or []
    # timeout_response is how long we wait for a response
    timeout = timeout or CONF.rpc_response_timeout

    # The msg_id is used to track replies.
    msg_id = uuid.uuid4().hex

    # Replies always come into the reply service.
    reply_topic = "zmq_replies.%s" % CONF.rpc_zmq_host

    LOG.debug("Creating payload")
    # Curry the original request into a reply method.
    mcontext = RpcContext.marshal(context)
    payload = {
        'method': '-reply',
        'args': {
            'msg_id': msg_id,
            'topic': reply_topic,
            # TODO(ewindisch): safe to remove mcontext in I.
            'msg': [mcontext, msg]
        }
    }

    LOG.debug("Creating queue socket for reply waiter")

    # Messages arriving async.
    # TODO(ewindisch): have reply consumer with dynamic subscription mgmt
    with Timeout(timeout, exception=rpc_common.Timeout):
        try:
            msg_waiter = ZmqSocket(
                "ipc://%s/zmq_topic_zmq_replies.%s" %
                (CONF.rpc_zmq_ipc_dir,
                 CONF.rpc_zmq_host),
                zmq.SUB, subscribe=msg_id, bind=False
            )

            LOG.debug("Sending cast: %s", topic)
            _cast(addr, context, topic, payload, envelope=envelope)

            LOG.debug("Cast sent; Waiting reply")
            # Blocks until receives reply
            msg = msg_waiter.recv()
            if msg is None:
                raise rpc_common.Timeout()
            LOG.debug("Received message: %s", msg)
            LOG.debug("Unpacking response")

            if msg[2] == 'cast':  # Legacy version
                raw_msg = _deserialize(msg[-1])[-1]
            elif msg[2] == 'impl_zmq_v2':
                rpc_envelope = unflatten_envelope(msg[4:])
                raw_msg = rpc_common.deserialize_msg(rpc_envelope)
            else:
                raise rpc_common.UnsupportedRpcEnvelopeVersion(
                    _("Unsupported or unknown ZMQ envelope returned."))

            responses = raw_msg['args']['response']
        # ZMQError trumps the Timeout error.
        except zmq.ZMQError:
            raise RPCException("ZMQ Socket Error")
        except (IndexError, KeyError):
            raise RPCException(_("RPC Message Invalid."))
        finally:
            if 'msg_waiter' in vars():
                msg_waiter.close()

    # It seems we don't need to do all of the following,
    # but perhaps it would be useful for multicall?
    # One effect of this is that we're checking all
    # responses for Exceptions.
    for resp in responses:
        if isinstance(resp, types.DictType) and 'exc' in resp:
            raise rpc_common.deserialize_remote_exception(
                resp['exc'], allowed_remote_exmods)

    return responses[-1]
Exemplo n.º 37
0
    def call(self, ctxt, method, args):
        """Synchronous Call"""
        # # check if the call has a message saved in cache
        # # key: string concatenation of ctxt + method + args
        # # value: rpc response object
        # key = ""
        # for k, v in ctxt.items():
        #     key += str(k)
        #     key += '#' + str(v) + '#'
        # key += '|' + str(method) + '|'
        # for k, v in args.items():
        #     key += str(k)
        #     key += '#' + str(v) + '#'
        #
        # # check if the method has been called before
        # # and cached
        # if key in self.message_cache:
        #     LOG.debug("Retrieved method {} with args "
        #               "{} from cache".format(method, args))
        #     return self.message_cache[key]

        rpc_start_time = time.time()

        rpc = self.RPC(action=self.RPC.CALL,
                       ctxt=ctxt,
                       method=method,
                       args=args)

        # TODO(jdandrea): Do something if the assert fails.
        assert (rpc.enqueued)

        rpc_id = rpc.id
        topic = self.target.topic
        LOG.info(_LI("Message {} on topic {} enqueued.").format(rpc_id, topic))
        if self.conf.messaging_server.debug:
            LOG.debug("Calling method {} with args {}".format(method, args))

        # Check message status within a thread
        executor = futurist.ThreadPoolExecutor()
        started_at = time.time()
        while (time.time() -
               started_at) <= self.conf.messaging_server.response_timeout:
            fut = executor.submit(self.__check_rpc_status, rpc_id, method)
            rpc = fut.result()
            if rpc and rpc.finished:
                if self.conf.messaging_server.debug:
                    LOG.debug("Message {} method {} response received".format(
                        rpc_id, method))
                break
        executor.shutdown()

        # Get response, delete message, and return response
        if not rpc or not rpc.finished:
            LOG.error(
                _LE("Message {} on topic {} timed out at {} seconds").format(
                    rpc_id, topic,
                    self.conf.messaging_server.response_timeout))
        elif not rpc.ok:
            LOG.error(
                _LE("Message {} on topic {} returned an error").format(
                    rpc_id, topic))
        response = rpc.response
        failure = rpc.failure
        rpc.delete()  # TODO(jdandrea): Put a TTL on the msg instead?
        # self.message_cache[key] = response

        LOG.debug("Elapsed time: {0:.3f} sec".format(time.time() -
                                                     rpc_start_time))
        # If there's a failure, raise it as an exception
        allowed = []
        if failure is not None and failure != '':
            # TODO(jdandrea): Do we need to populate allowed(_remote_exmods)?
            raise rpc_common.deserialize_remote_exception(failure, allowed)
        return response