Short-circuit notifications when not enabled

In Mitaka oslo messaging introduced the transport_url specific for
notifications under the oslo_messaging_notifications section, but some
projects still use the default transport_url defined in the DEFAULT
section. Use messaging notifications transport instead of default.

This patch proposes short-circuiting notification methods as much as
possible to optimize code execution when Karbor has no notification
transport mechanism configured.

The NOTIFIER only be inited only if notifications are actually
enabled.

Change-Id: Id9419ddd801bf9d8ac13c4a73a91e39fd763cb2b
Closes-Bug: #1719786
This commit is contained in:
chenying 2017-09-27 14:54:28 +08:00
parent 3f3df9b761
commit 2f529a62bf
3 changed files with 87 additions and 15 deletions

View File

@ -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):

View File

@ -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)

View File

@ -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'}