Ejemplo n.º 1
0
def _call(addr, context, msg_id, topic, msg, timeout=None):
    # 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 = str(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,
            'context': mcontext,
            'topic': reply_topic,
            '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" %
                                   CONF.rpc_zmq_ipc_dir,
                                   zmq.SUB,
                                   subscribe=msg_id,
                                   bind=False)

            LOG.debug(_("Sending cast"))
            _cast(addr, context, msg_id, topic, payload)

            LOG.debug(_("Cast sent; Waiting reply"))
            # Blocks until receives reply
            msg = msg_waiter.recv()
            LOG.debug(_("Received message: %s"), msg)
            LOG.debug(_("Unpacking response"))
            responses = _deserialize(msg[-1])
        # ZMQError trumps the Timeout error.
        except zmq.ZMQError:
            raise RPCException("ZMQ Socket Error")
        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(CONF, resp['exc'])

    return responses[-1]
Ejemplo n.º 2
0
def _call(addr, context, msg_id, topic, msg, timeout=None):
    # timeout_response is how long we wait for a response
    timeout = timeout or FLAGS.rpc_response_timeout

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

    # Replies always come into the reply service.
    # We require that FLAGS.host is a FQDN, IP, or resolvable hostname.
    reply_topic = "zmq_replies.%s" % FLAGS.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,
            'context': mcontext,
            'topic': reply_topic,
            '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" % FLAGS.rpc_zmq_ipc_dir,
                zmq.SUB, subscribe=msg_id, bind=False
            )

            LOG.debug(_("Sending cast"))
            _cast(addr, context, msg_id, topic, payload)

            LOG.debug(_("Cast sent; Waiting reply"))
            # Blocks until receives reply
            msg = msg_waiter.recv()
            LOG.debug(_("Received message: %s"), msg)
            LOG.debug(_("Unpacking response"))
            responses = _deserialize(msg[-1])
        # ZMQError trumps the Timeout error.
        except zmq.ZMQError:
            raise RPCException("ZMQ Socket Error")
        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(FLAGS, resp['exc'])

    return responses[-1]
Ejemplo n.º 3
0
    def __call__(self, data):
        """The consume() callback will call this.  Store the result."""
        if data['failure']:
            failure = data['failure']
            self._result = rpc_common.deserialize_remote_exception(self._conf,
                    failure)

        elif data.get('ending', False):
            self._got_ending = True
        else:
            self._result = data['result']
Ejemplo n.º 4
0
    def __call__(self, data):
        """The consume() callback will call this.  Store the result."""
        if data['failure']:
            failure = data['failure']
            self._result = rpc_common.deserialize_remote_exception(
                self._conf, failure)

        elif data.get('ending', False):
            self._got_ending = True
        else:
            self._result = data['result']
Ejemplo n.º 5
0
    def test_deserialize_remote_exception_bad_module(self):
        failure = {
            'class': 'popen2',
            'module': 'os',
            'kwargs': {'cmd': '/bin/echo failed'},
            'message': 'foo',
        }
        serialized = jsonutils.dumps(failure)

        after_exc = rpc_common.deserialize_remote_exception(FLAGS, serialized)
        self.assertTrue(isinstance(after_exc, rpc_common.RemoteError))
Ejemplo n.º 6
0
    def test_deserialize_remote_exception_bad_module(self):
        failure = {
            'class': 'popen2',
            'module': 'os',
            'kwargs': {'cmd': '/bin/echo failed'},
            'message': 'foo',
        }
        serialized = jsonutils.dumps(failure)

        after_exc = rpc_common.deserialize_remote_exception(FLAGS, serialized)
        self.assertTrue(isinstance(after_exc, rpc_common.RemoteError))
Ejemplo n.º 7
0
 def _process_data(self, data):
     result = None
     if data['failure']:
         failure = data['failure']
         result = rpc_common.deserialize_remote_exception(self._conf,
                                                          failure)
     elif data.get('ending', False):
         self._got_ending = True
     else:
         result = data['result']
     return result
Ejemplo n.º 8
0
 def _process_data(self, data):
     result = None
     self.msg_id_cache.check_duplicate_message(data)
     if data['failure']:
         failure = data['failure']
         result = rpc_common.deserialize_remote_exception(
             self._conf, failure)
     elif data.get('ending', False):
         self._got_ending = True
     else:
         result = data['result']
     return result
Ejemplo n.º 9
0
 def _process_data(self, data):
     result = None
     self.msg_id_cache.check_duplicate_message(data)
     if data['failure']:
         failure = data['failure']
         result = rpc_common.deserialize_remote_exception(self._conf,
                                                          failure)
     elif data.get('ending', False):
         self._got_ending = True
     else:
         result = data['result']
     return result
Ejemplo n.º 10
0
    def test_deserialize_remote_exception(self):
        failure = {
            "class": "NotImplementedError",
            "module": "exceptions",
            "message": "",
            "tb": ["raise NotImplementedError"],
        }
        serialized = jsonutils.dumps(failure)

        after_exc = rpc_common.deserialize_remote_exception(FLAGS, serialized)
        self.assertTrue(isinstance(after_exc, NotImplementedError))
        # assure the traceback was added
        self.assertTrue("raise NotImplementedError" in unicode(after_exc))
Ejemplo n.º 11
0
    def test_deserialize_remote_exception(self):
        failure = {
            'class': 'NotImplementedError',
            'module': 'exceptions',
            'message': '',
            'tb': ['raise NotImplementedError'],
        }
        serialized = jsonutils.dumps(failure)

        after_exc = rpc_common.deserialize_remote_exception(FLAGS, serialized)
        self.assertTrue(isinstance(after_exc, NotImplementedError))
        #assure the traceback was added
        self.assertTrue('raise NotImplementedError' in unicode(after_exc))
Ejemplo n.º 12
0
    def test_deserialize_remote_exception(self):
        failure = {
            'class': 'NotImplementedError',
            'module': 'exceptions',
            'message': '',
            'tb': ['raise NotImplementedError'],
        }
        serialized = jsonutils.dumps(failure)

        after_exc = rpc_common.deserialize_remote_exception(FLAGS, serialized)
        self.assertTrue(isinstance(after_exc, NotImplementedError))
        #assure the traceback was added
        self.assertTrue('raise NotImplementedError' in unicode(after_exc))
Ejemplo n.º 13
0
    def test_deserialize_remote_custom_exception(self):
        failure = {
            "class": "OpenstackException",
            "module": "openstack.common.exception",
            "message": exception.OpenstackException.message,
            "tb": ["raise OpenstackException"],
        }
        serialized = jsonutils.dumps(failure)

        after_exc = rpc_common.deserialize_remote_exception(FLAGS, serialized)
        self.assertTrue(isinstance(after_exc, exception.OpenstackException))
        self.assertTrue("An unknown" in unicode(after_exc))
        # assure the traceback was added
        self.assertTrue("raise OpenstackException" in unicode(after_exc))
Ejemplo n.º 14
0
    def test_deserialize_remote_exception_user_defined_exception(self):
        """Ensure a user defined exception can be deserialized."""
        self.config(allowed_rpc_exception_modules=[self.__class__.__module__])
        failure = {
            'class': 'FakeUserDefinedException',
            'module': self.__class__.__module__,
            'tb': ['raise FakeUserDefinedException'],
        }
        serialized = jsonutils.dumps(failure)

        after_exc = rpc_common.deserialize_remote_exception(FLAGS, serialized)
        self.assertTrue(isinstance(after_exc, FakeUserDefinedException))
        #assure the traceback was added
        self.assertTrue('raise FakeUserDefinedException' in unicode(after_exc))
Ejemplo n.º 15
0
    def test_deserialize_remote_exception_user_defined_exception(self):
        """Ensure a user defined exception can be deserialized."""
        self.config(allowed_rpc_exception_modules=[self.__class__.__module__])
        failure = {
            'class': 'FakeUserDefinedException',
            'module': self.__class__.__module__,
            'tb': ['raise FakeUserDefinedException'],
        }
        serialized = jsonutils.dumps(failure)

        after_exc = rpc_common.deserialize_remote_exception(FLAGS, serialized)
        self.assertTrue(isinstance(after_exc, FakeUserDefinedException))
        #assure the traceback was added
        self.assertTrue('raise FakeUserDefinedException' in unicode(after_exc))
Ejemplo n.º 16
0
    def test_deserialize_remote_custom_exception(self):
        failure = {
            'class': 'OpenstackException',
            'module': 'openstack.common.exception',
            'message': exception.OpenstackException.message,
            'tb': ['raise OpenstackException'],
        }
        serialized = jsonutils.dumps(failure)

        after_exc = rpc_common.deserialize_remote_exception(FLAGS, serialized)
        self.assertTrue(isinstance(after_exc, exception.OpenstackException))
        self.assertTrue('An unknown' in unicode(after_exc))
        #assure the traceback was added
        self.assertTrue('raise OpenstackException' in unicode(after_exc))
Ejemplo n.º 17
0
    def test_deserialize_remote_custom_exception(self):
        failure = {
            'class': 'OpenstackException',
            'module': 'openstack.common.exception',
            'message': exception.OpenstackException.message,
            'tb': ['raise OpenstackException'],
        }
        serialized = jsonutils.dumps(failure)

        after_exc = rpc_common.deserialize_remote_exception(FLAGS, serialized)
        self.assertTrue(isinstance(after_exc, exception.OpenstackException))
        self.assertTrue('An unknown' in unicode(after_exc))
        #assure the traceback was added
        self.assertTrue('raise OpenstackException' in unicode(after_exc))
Ejemplo n.º 18
0
    def test_deserialize_remote_exception_args_and_kwargs(self):
        """
        Ensure a user defined exception will be supplied the correct args and
        kwargs while being deserialized.
        """
        self.config(allowed_rpc_exception_modules=[self.__class__.__module__])
        failure = {
            'class': 'FakeUserDefinedException',
            'module': self.__class__.__module__,
            'tb': ['raise FakeUserDefinedException'],
            'args': (u'fakearg',),
            'kwargs': {u'fakekwarg': u'fake'},
        }
        serialized = jsonutils.dumps(failure)

        after_exc = rpc_common.deserialize_remote_exception(FLAGS, serialized)
        self.assertTrue(isinstance(after_exc, FakeUserDefinedException))
        self.assertEqual(after_exc.args, (u'fakearg',))
        self.assertEqual(after_exc.kwargs, {u'fakekwarg': u'fake'})
Ejemplo n.º 19
0
    def test_deserialize_remote_exception_args_and_kwargs(self):
        """
        Ensure a user defined exception will be supplied the correct args and
        kwargs while being deserialized.
        """
        self.config(allowed_rpc_exception_modules=[self.__class__.__module__])
        failure = {
            'class': 'FakeUserDefinedException',
            'module': self.__class__.__module__,
            'tb': ['raise FakeUserDefinedException'],
            'args': ('fakearg',),
            'kwargs': {'fakekwarg': 'fake'},
        }
        serialized = jsonutils.dumps(failure)

        after_exc = rpc_common.deserialize_remote_exception(FLAGS, serialized)
        self.assertTrue(isinstance(after_exc, FakeUserDefinedException))
        self.assertEqual(after_exc.args, ('fakearg',))
        self.assertEqual(after_exc.kwargs, {'fakekwarg': 'fake'})
Ejemplo n.º 20
0
    def test_deserialize_remote_exception_cannot_recreate(self):
        """Ensure a RemoteError is returned on initialization failure.

        If an exception cannot be recreated with it's original class then a
        RemoteError with the exception informations should still be returned.

        """
        self.config(allowed_rpc_exception_modules=[self.__class__.__module__])
        failure = {
            'class': 'FakeIDontExistException',
            'module': self.__class__.__module__,
            'tb': ['raise FakeIDontExistException'],
        }
        serialized = jsonutils.dumps(failure)

        after_exc = rpc_common.deserialize_remote_exception(FLAGS, serialized)
        self.assertTrue(isinstance(after_exc, rpc_common.RemoteError))
        #assure the traceback was added
        self.assertTrue('raise FakeIDontExistException' in unicode(after_exc))
Ejemplo n.º 21
0
    def test_deserialize_remote_custom_exception(self):
        failure = {
            'class': 'OpenstackException',
            'module': 'openstack.common.exception',
            'message': exception.OpenstackException.msg_fmt,
            'tb': ['raise OpenstackException'],
        }
        serialized = jsonutils.dumps(failure)

        after_exc = rpc_common.deserialize_remote_exception(FLAGS, serialized)
        self.assertTrue(isinstance(after_exc, exception.OpenstackException))
        self.assertTrue('An unknown' in six.text_type(after_exc))
        #assure the traceback was added
        self.assertTrue('raise OpenstackException' in six.text_type(after_exc))
        self.assertEqual('OpenstackException_Remote',
                         after_exc.__class__.__name__)
        self.assertEqual('openstack.common.exception_Remote',
                         after_exc.__class__.__module__)
        self.assertTrue(isinstance(after_exc, exception.OpenstackException))
Ejemplo n.º 22
0
    def test_deserialize_remote_exception_cannot_recreate(self):
        """Ensure a RemoteError is returned on initialization failure.

        If an exception cannot be recreated with it's original class then a
        RemoteError with the exception informations should still be returned.

        """
        self.config(allowed_rpc_exception_modules=[self.__class__.__module__])
        failure = {
            'class': 'FakeIDontExistException',
            'module': self.__class__.__module__,
            'tb': ['raise FakeIDontExistException'],
        }
        serialized = jsonutils.dumps(failure)

        after_exc = rpc_common.deserialize_remote_exception(FLAGS, serialized)
        self.assertTrue(isinstance(after_exc, rpc_common.RemoteError))
        #assure the traceback was added
        self.assertTrue('raise FakeIDontExistException' in unicode(after_exc))
Ejemplo n.º 23
0
def _call(addr, context, topic, msg, timeout=None,
          envelope=False):
    # 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"))
            _cast(addr, context, topic, payload, envelope)

            LOG.debug(_("Cast sent; Waiting reply"))
            # Blocks until receives reply
            msg = msg_waiter.recv()
            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(CONF, resp['exc'])

    return responses[-1]
Ejemplo n.º 24
0
def _call(addr, context, topic, msg, timeout=None,
          envelope=False):
    # 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")
            _cast(addr, context, topic, payload, envelope)

            LOG.debug("Cast sent; Waiting reply")
            # Blocks until receives reply
            msg = msg_waiter.recv()
            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(CONF, resp['exc'])

    return responses[-1]
Ejemplo n.º 25
0
    def test_deserialize_remote_exception_bad_module(self):
        failure = {"class": "popen2", "module": "os", "kwargs": {"cmd": "/bin/echo failed"}, "message": "foo"}
        serialized = jsonutils.dumps(failure)

        after_exc = rpc_common.deserialize_remote_exception(FLAGS, serialized)
        self.assertTrue(isinstance(after_exc, rpc_common.RemoteError))