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]
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]
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']
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']
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))
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
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
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
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))
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))
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))
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))
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))
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'})
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'})
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))
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))
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]
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]
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))