summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2013-08-12 09:23:29 +0000
committerGerrit Code Review <review@openstack.org>2013-08-12 09:23:29 +0000
commitc7236958d0402a7ea60483a34dbc9c1dac189d8a (patch)
tree7431eed2101a5873aaa4b84f251e02f16431e209
parenta7d7eb660e1e8d5bb0f849956737b5cf3ddb4139 (diff)
parent2abb40f9e9143e1d68c15966c88de91c09ea2054 (diff)
downloadoslo-messaging-c7236958d0402a7ea60483a34dbc9c1dac189d8a.tar.gz
Merge "Add a context serialization hook"
-rw-r--r--oslo/messaging/notify/notifier.py1
-rw-r--r--oslo/messaging/rpc/client.py12
-rw-r--r--oslo/messaging/rpc/dispatcher.py1
-rw-r--r--oslo/messaging/rpc/server.py3
-rw-r--r--oslo/messaging/serializer.py26
-rw-r--r--tests/test_notifier.py10
-rw-r--r--tests/test_rpc_client.py9
-rw-r--r--tests/test_rpc_dispatcher.py14
-rw-r--r--tests/test_rpc_server.py8
9 files changed, 68 insertions, 16 deletions
diff --git a/oslo/messaging/notify/notifier.py b/oslo/messaging/notify/notifier.py
index 4a5b87b..66f23f3 100644
--- a/oslo/messaging/notify/notifier.py
+++ b/oslo/messaging/notify/notifier.py
@@ -129,6 +129,7 @@ class Notifier(object):
def _notify(self, ctxt, event_type, payload, priority):
payload = self._serializer.serialize_entity(ctxt, payload)
+ ctxt = self._serializer.serialize_context(ctxt)
msg = dict(message_id=uuidutils.generate_uuid(),
publisher_id=self.publisher_id,
diff --git a/oslo/messaging/rpc/client.py b/oslo/messaging/rpc/client.py
index e1854ed..3d2e896 100644
--- a/oslo/messaging/rpc/client.py
+++ b/oslo/messaging/rpc/client.py
@@ -129,6 +129,8 @@ class _CallContext(object):
def cast(self, ctxt, method, **kwargs):
"""Invoke a method and return immediately. See RPCClient.cast()."""
msg = self._make_message(ctxt, method, kwargs)
+ ctxt = self.serializer.serialize_context(ctxt)
+
if self.version_cap:
self._check_version_cap(msg.get('version'))
try:
@@ -149,6 +151,7 @@ class _CallContext(object):
def call(self, ctxt, method, **kwargs):
"""Invoke a method and wait for a reply. See RPCClient.call()."""
msg = self._make_message(ctxt, method, kwargs)
+ msg_ctxt = self.serializer.serialize_context(ctxt)
timeout = self.timeout
if self.timeout is None:
@@ -160,7 +163,7 @@ class _CallContext(object):
self._check_version_cap(msg.get('version'))
try:
- result = self.transport._send(self.target, ctxt, msg,
+ result = self.transport._send(self.target, msg_ctxt, msg,
wait_for_reply=True, timeout=timeout)
except driver_base.TransportDriverError as ex:
raise ClientSendError(self.target, ex)
@@ -335,6 +338,9 @@ class RPCClient(object):
Method arguments must either be primitive types or types supported by
the client's serializer (if any).
+ Similarly, the request context must be a dict unless the client's
+ serializer supports serializing another type.
+
:param ctxt: a request context dict
:type ctxt: dict
:param method: the method name
@@ -348,7 +354,9 @@ class RPCClient(object):
"""Invoke a method and wait for a reply.
Method arguments must either be primitive types or types supported by
- the client's serializer (if any).
+ the client's serializer (if any). Similarly, the request context must
+ be a dict unless the client's serializer supports serializing another
+ type.
The semantics of how any errors raised by the remote RPC endpoint
method are handled are quite subtle.
diff --git a/oslo/messaging/rpc/dispatcher.py b/oslo/messaging/rpc/dispatcher.py
index bcf0864..183b7ca 100644
--- a/oslo/messaging/rpc/dispatcher.py
+++ b/oslo/messaging/rpc/dispatcher.py
@@ -86,6 +86,7 @@ class RPCDispatcher(object):
return utils.version_is_compatible(endpoint_version, version)
def _dispatch(self, endpoint, method, ctxt, args):
+ ctxt = self.serializer.deserialize_context(ctxt)
new_args = dict()
for argname, arg in args.iteritems():
new_args[argname] = self.serializer.deserialize_entity(ctxt, arg)
diff --git a/oslo/messaging/rpc/server.py b/oslo/messaging/rpc/server.py
index 8c86ce4..690b03d 100644
--- a/oslo/messaging/rpc/server.py
+++ b/oslo/messaging/rpc/server.py
@@ -86,7 +86,8 @@ supplied by the client.
Parameters to the method invocation are primitive types and so must be the
return values from the methods. By supplying a serializer object, a server can
-deserialize arguments from - serialize return values to - primitive types.
+deserialize a request context and arguments from - and serialize return values
+to - primitive types.
"""
__all__ = [
diff --git a/oslo/messaging/serializer.py b/oslo/messaging/serializer.py
index c69c70b..d52eb83 100644
--- a/oslo/messaging/serializer.py
+++ b/oslo/messaging/serializer.py
@@ -27,7 +27,7 @@ class Serializer(object):
def serialize_entity(self, ctxt, entity):
"""Serialize something to primitive form.
- :param context: Request context
+ :param ctxt: Request context, in deserialized form
:param entity: Entity to be serialized
:returns: Serialized form of entity
"""
@@ -36,11 +36,27 @@ class Serializer(object):
def deserialize_entity(self, ctxt, entity):
"""Deserialize something from primitive form.
- :param context: Request context
+ :param ctxt: Request context, in deserialized form
:param entity: Primitive to be deserialized
:returns: Deserialized form of entity
"""
+ @abc.abstractmethod
+ def serialize_context(self, ctxt):
+ """Serialize a request context into a dictionary.
+
+ :param ctxt: Request context
+ :returns: Serialized form of context
+ """
+
+ @abc.abstractmethod
+ def deserialize_context(self, ctxt):
+ """Deserialize a dictionary into a request context.
+
+ :param ctxt: Request context dictionary
+ :returns: Deserialized form of entity
+ """
+
class NoOpSerializer(Serializer):
"""A serializer that does nothing."""
@@ -50,3 +66,9 @@ class NoOpSerializer(Serializer):
def deserialize_entity(self, ctxt, entity):
return entity
+
+ def serialize_context(self, ctxt):
+ return ctxt
+
+ def deserialize_context(self, ctxt):
+ return ctxt
diff --git a/tests/test_notifier.py b/tests/test_notifier.py
index 4a7ed29..6ee2842 100644
--- a/tests/test_notifier.py
+++ b/tests/test_notifier.py
@@ -201,12 +201,15 @@ class TestSerializer(test_utils.BaseTestCase):
timeutils.set_time_override()
+ self.mox.StubOutWithMock(serializer, 'serialize_context')
self.mox.StubOutWithMock(serializer, 'serialize_entity')
- serializer.serialize_entity({}, 'bar').AndReturn('sbar')
+ serializer.serialize_context(dict(user='bob')).\
+ AndReturn(dict(user='alice'))
+ serializer.serialize_entity(dict(user='bob'), 'bar').AndReturn('sbar')
self.mox.ReplayAll()
- notifier.info({}, 'test.notify', 'bar')
+ notifier.info(dict(user='bob'), 'test.notify', 'bar')
message = {
'message_id': str(message_id),
@@ -217,7 +220,8 @@ class TestSerializer(test_utils.BaseTestCase):
'timestamp': str(timeutils.utcnow.override_time),
}
- self.assertEquals(_impl_test.NOTIFICATIONS, [({}, message, 'INFO')])
+ self.assertEquals(_impl_test.NOTIFICATIONS,
+ [(dict(user='alice'), message, 'INFO')])
class TestLogNotifier(test_utils.BaseTestCase):
diff --git a/tests/test_rpc_client.py b/tests/test_rpc_client.py
index 14ddf53..194dc57 100644
--- a/tests/test_rpc_client.py
+++ b/tests/test_rpc_client.py
@@ -295,11 +295,14 @@ class TestSerializer(test_utils.BaseTestCase):
msg = dict(method='foo',
args=dict([(k, 's' + v) for k, v in self.args.items()]))
kwargs = dict(wait_for_reply=True, timeout=None) if self.call else {}
- transport._send(messaging.Target(), self.ctxt, msg, **kwargs).\
- AndReturn(self.retval)
+ transport._send(messaging.Target(),
+ dict(user='alice'),
+ msg,
+ **kwargs).AndReturn(self.retval)
self.mox.StubOutWithMock(serializer, 'serialize_entity')
self.mox.StubOutWithMock(serializer, 'deserialize_entity')
+ self.mox.StubOutWithMock(serializer, 'serialize_context')
for arg in self.args:
serializer.serialize_entity(self.ctxt, arg).AndReturn('s' + arg)
@@ -308,6 +311,8 @@ class TestSerializer(test_utils.BaseTestCase):
serializer.deserialize_entity(self.ctxt, self.retval).\
AndReturn('d' + self.retval)
+ serializer.serialize_context(self.ctxt).AndReturn(dict(user='alice'))
+
self.mox.ReplayAll()
method = client.call if self.call else client.cast
diff --git a/tests/test_rpc_dispatcher.py b/tests/test_rpc_dispatcher.py
index 0dbce62..5b367b9 100644
--- a/tests/test_rpc_dispatcher.py
+++ b/tests/test_rpc_dispatcher.py
@@ -128,29 +128,33 @@ class TestSerializer(test_utils.BaseTestCase):
scenarios = [
('no_args_or_retval',
- dict(ctxt={}, args={}, retval=None)),
+ dict(ctxt={}, dctxt={}, args={}, retval=None)),
('args_and_retval',
dict(ctxt=dict(user='bob'),
+ dctxt=dict(user='alice'),
args=dict(a='a', b='b', c='c'),
retval='d')),
]
def test_serializer(self):
endpoint = _FakeEndpoint()
- serializer = msg_serializer.NoOpSerializer
+ serializer = msg_serializer.NoOpSerializer()
dispatcher = messaging.RPCDispatcher([endpoint], serializer)
self.mox.StubOutWithMock(endpoint, 'foo')
args = dict([(k, 'd' + v) for k, v in self.args.items()])
- endpoint.foo(self.ctxt, **args).AndReturn(self.retval)
+ endpoint.foo(self.dctxt, **args).AndReturn(self.retval)
self.mox.StubOutWithMock(serializer, 'serialize_entity')
self.mox.StubOutWithMock(serializer, 'deserialize_entity')
+ self.mox.StubOutWithMock(serializer, 'deserialize_context')
+
+ serializer.deserialize_context(self.ctxt).AndReturn(self.dctxt)
for arg in self.args:
- serializer.deserialize_entity(self.ctxt, arg).AndReturn('d' + arg)
+ serializer.deserialize_entity(self.dctxt, arg).AndReturn('d' + arg)
- serializer.serialize_entity(self.ctxt, self.retval).\
+ serializer.serialize_entity(self.dctxt, self.retval).\
AndReturn('s' + self.retval if self.retval else None)
self.mox.ReplayAll()
diff --git a/tests/test_rpc_server.py b/tests/test_rpc_server.py
index 4d28a79..394bf99 100644
--- a/tests/test_rpc_server.py
+++ b/tests/test_rpc_server.py
@@ -51,6 +51,12 @@ class ServerSetupMixin(object):
def deserialize_entity(self, ctxt, entity):
return 'd' + (entity or '')
+ def serialize_context(self, ctxt):
+ return dict([(k, 's' + v) for k, v in ctxt.items()])
+
+ def deserialize_context(self, ctxt):
+ return dict([(k, 'd' + v) for k, v in ctxt.items()])
+
def __init__(self):
self.serializer = self.TestSerializer()
@@ -254,7 +260,7 @@ class TestRPCServer(test_utils.BaseTestCase, ServerSetupMixin):
self.assertEqual(client.call({'dsa': 'b'},
'ctxt_check',
key='a'),
- 'dsb')
+ 'dsdsb')
self._stop_server(client, server_thread)