diff --git a/karbor/rpc.py b/karbor/rpc.py index cb9e262d..37b6d7aa 100644 --- a/karbor/rpc.py +++ b/karbor/rpc.py @@ -26,13 +26,14 @@ __all__ = [ from oslo_config import cfg import oslo_messaging as messaging from oslo_messaging.rpc import dispatcher -from oslo_serialization import jsonutils import karbor.context import karbor.exception +from karbor import utils CONF = cfg.CONF TRANSPORT = None +NOTIFICATION_TRANSPORT = None NOTIFIER = None ALLOWED_EXMODS = [ @@ -42,16 +43,24 @@ EXTRA_EXMODS = [] def init(conf): - if initialized(): - return - global TRANSPORT, NOTIFIER + global TRANSPORT, NOTIFICATION_TRANSPORT, NOTIFIER exmods = get_allowed_exmods() TRANSPORT = messaging.get_rpc_transport(conf, allowed_remote_exmods=exmods) + NOTIFICATION_TRANSPORT = messaging.get_notification_transport( + conf, + allowed_remote_exmods=exmods) - serializer = RequestContextSerializer(JsonPayloadSerializer()) - NOTIFIER = messaging.Notifier(TRANSPORT, serializer=serializer) + # get_notification_transport has loaded oslo_messaging_notifications config + # group, so we can now check if notifications are actually enabled. + if utils.notifications_enabled(conf): + json_serializer = messaging.JsonPayloadSerializer() + serializer = RequestContextSerializer(json_serializer) + NOTIFIER = messaging.Notifier(NOTIFICATION_TRANSPORT, + serializer=serializer) + else: + NOTIFIER = utils.DO_NOTHING def initialized(): @@ -59,11 +68,12 @@ def initialized(): def cleanup(): - global TRANSPORT, NOTIFIER + global TRANSPORT, NOTIFICATION_TRANSPORT, NOTIFIER assert TRANSPORT is not None - assert NOTIFIER is not None + TRANSPORT.cleanup() - TRANSPORT = NOTIFIER = None + NOTIFICATION_TRANSPORT.cleanup() + TRANSPORT = NOTIFICATION_TRANSPORT = NOTIFIER = None def set_defaults(control_exchange): @@ -82,12 +92,6 @@ def get_allowed_exmods(): return ALLOWED_EXMODS + EXTRA_EXMODS -class JsonPayloadSerializer(messaging.NoOpSerializer): - @staticmethod - def serialize_entity(context, entity): - return jsonutils.to_primitive(entity, convert_instances=True) - - class RequestContextSerializer(messaging.Serializer): def __init__(self, base): diff --git a/karbor/tests/unit/test_rpc.py b/karbor/tests/unit/test_rpc.py new file mode 100644 index 00000000..5422b505 --- /dev/null +++ b/karbor/tests/unit/test_rpc.py @@ -0,0 +1,47 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import mock + +from oslo_config import cfg + +from karbor import rpc +from karbor.tests import base + + +CONF = cfg.CONF + + +class RPCAPITestCase(base.TestCase): + """Tests RPCAPI mixin aggregating stuff related to RPC compatibility.""" + + def setUp(self): + super(RPCAPITestCase, self).setUp() + + @mock.patch('oslo_messaging.JsonPayloadSerializer', wraps=True) + def test_init_no_notifications(self, serializer_mock): + """Test short-circuiting notifications with default and noop driver.""" + driver = ['noop'] + self.override_config('driver', driver, + group='oslo_messaging_notifications') + rpc.init(CONF) + self.assertEqual(rpc.utils.DO_NOTHING, rpc.NOTIFIER) + serializer_mock.assert_not_called() + + @mock.patch.object(rpc, 'messaging') + def test_init_notifications(self, messaging_mock): + self.override_config('driver', ['test'], + group='oslo_messaging_notifications') + rpc.init(CONF) + self.assertTrue(messaging_mock.JsonPayloadSerializer.called) + self.assertTrue(messaging_mock.Notifier.called) + self.assertEqual(rpc.NOTIFIER, messaging_mock.Notifier.return_value) diff --git a/karbor/utils.py b/karbor/utils.py index 7a5a9faf..6dc54a9f 100644 --- a/karbor/utils.py +++ b/karbor/utils.py @@ -192,3 +192,24 @@ def tempdir(**kwargs): except OSError as e: LOG.debug('Could not remove tmpdir: %s', six.text_type(e)) + + +class DoNothing(str): + """Class that literally does nothing. + + We inherit from str in case it's called with json.dumps. + """ + def __call__(self, *args, **kwargs): + return self + + def __getattr__(self, name): + return self + + +DO_NOTHING = DoNothing() + + +def notifications_enabled(conf): + """Check if oslo notifications are enabled.""" + notifications_driver = set(conf.oslo_messaging_notifications.driver) + return notifications_driver and notifications_driver != {'noop'}