206c19e99e
Notifications are an unusual case in that we need users to manually opt in to new incompatible message formats by editing configuration because there may be external consumers expecting the old format. Add a send_notification() method to the driver interface and add a format version paramater to the method, to make it clear that this version selection is specifically for notifications. In the case of the rabbit/qpid drivers, the 2.0 format is where we added the message envelope. Change-Id: Ib4925c308b1252503749962aa16f043281f2b429
263 lines
7.7 KiB
Python
263 lines
7.7 KiB
Python
|
|
# Copyright 2013 Red Hat, Inc.
|
|
#
|
|
# 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 logging
|
|
import sys
|
|
import uuid
|
|
|
|
import fixtures
|
|
import testscenarios
|
|
|
|
from oslo import messaging
|
|
from oslo.messaging.notify import _impl_messaging
|
|
from oslo.messaging.notify import _impl_test
|
|
from oslo.messaging.notify import notifier as msg_notifier
|
|
from oslo.messaging.openstack.common import jsonutils
|
|
from oslo.messaging.openstack.common import timeutils
|
|
from oslo.messaging import serializer as msg_serializer
|
|
from tests import utils as test_utils
|
|
|
|
load_tests = testscenarios.load_tests_apply_scenarios
|
|
|
|
|
|
class _FakeTransport(object):
|
|
|
|
def __init__(self, conf):
|
|
self.conf = conf
|
|
|
|
def _send_notification(self, target, ctxt, message, version):
|
|
pass
|
|
|
|
|
|
class _ReRaiseLoggedExceptionsFixture(fixtures.Fixture):
|
|
|
|
"""Record logged exceptions and re-raise in cleanup.
|
|
|
|
The notifier just logs notification send errors so, for the sake of
|
|
debugging test failures, we record any exceptions logged and re-raise them
|
|
during cleanup.
|
|
"""
|
|
|
|
class FakeLogger(object):
|
|
|
|
def __init__(self):
|
|
self.exceptions = []
|
|
|
|
def exception(self, msg, *args, **kwargs):
|
|
self.exceptions.append(sys.exc_info()[1])
|
|
|
|
def setUp(self):
|
|
super(_ReRaiseLoggedExceptionsFixture, self).setUp()
|
|
|
|
self.logger = self.FakeLogger()
|
|
|
|
def reraise_exceptions():
|
|
for ex in self.logger.exceptions:
|
|
raise ex
|
|
|
|
self.addCleanup(reraise_exceptions)
|
|
|
|
|
|
class TestMessagingNotifier(test_utils.BaseTestCase):
|
|
|
|
_v1 = [
|
|
('v1', dict(v1=True)),
|
|
('not_v1', dict(v1=False)),
|
|
]
|
|
|
|
_v2 = [
|
|
('v2', dict(v2=True)),
|
|
('not_v2', dict(v2=False)),
|
|
]
|
|
|
|
_topics = [
|
|
('no_topics', dict(topics=[])),
|
|
('single_topic', dict(topics=['notifications'])),
|
|
('multiple_topic2', dict(topics=['foo', 'bar'])),
|
|
]
|
|
|
|
_priority = [
|
|
('debug', dict(priority='debug')),
|
|
('info', dict(priority='info')),
|
|
('warn', dict(priority='warn')),
|
|
('error', dict(priority='error')),
|
|
('critical', dict(priority='critical')),
|
|
]
|
|
|
|
_payload = [
|
|
('payload', dict(payload={'foo': 'bar'})),
|
|
]
|
|
|
|
_context = [
|
|
('ctxt', dict(ctxt={'user': 'bob'})),
|
|
]
|
|
|
|
@classmethod
|
|
def generate_scenarios(cls):
|
|
cls.scenarios = testscenarios.multiply_scenarios(cls._v1,
|
|
cls._v2,
|
|
cls._topics,
|
|
cls._priority,
|
|
cls._payload,
|
|
cls._context)
|
|
|
|
def setUp(self):
|
|
super(TestMessagingNotifier, self).setUp()
|
|
|
|
self.conf.register_opts(msg_notifier._notifier_opts)
|
|
|
|
self.addCleanup(timeutils.clear_time_override)
|
|
|
|
self.logger = self.useFixture(_ReRaiseLoggedExceptionsFixture()).logger
|
|
self.stubs.Set(_impl_messaging, 'LOG', self.logger)
|
|
self.stubs.Set(msg_notifier, '_LOG', self.logger)
|
|
|
|
def test_notifier(self):
|
|
drivers = []
|
|
if self.v1:
|
|
drivers.append('messaging')
|
|
if self.v2:
|
|
drivers.append('messagingv2')
|
|
|
|
self.config(notification_driver=drivers)
|
|
self.config(notification_topics=self.topics)
|
|
|
|
transport = _FakeTransport(self.conf)
|
|
|
|
notifier = messaging.Notifier(transport, 'test.localhost')
|
|
|
|
self.mox.StubOutWithMock(transport, '_send_notification')
|
|
|
|
message_id = uuid.uuid4()
|
|
self.mox.StubOutWithMock(uuid, 'uuid4')
|
|
uuid.uuid4().AndReturn(message_id)
|
|
|
|
timeutils.set_time_override()
|
|
|
|
message = {
|
|
'message_id': str(message_id),
|
|
'publisher_id': 'test.localhost',
|
|
'event_type': 'test.notify',
|
|
'priority': self.priority.upper(),
|
|
'payload': self.payload,
|
|
'timestamp': str(timeutils.utcnow.override_time),
|
|
}
|
|
|
|
sends = []
|
|
if self.v1:
|
|
sends.append(dict(version=1.0))
|
|
if self.v2:
|
|
sends.append(dict(version=2.0))
|
|
|
|
for send_kwargs in sends:
|
|
for topic in self.topics:
|
|
target = messaging.Target(topic='%s.%s' % (topic,
|
|
self.priority))
|
|
transport._send_notification(target, self.ctxt, message,
|
|
**send_kwargs)
|
|
|
|
self.mox.ReplayAll()
|
|
|
|
method = getattr(notifier, self.priority)
|
|
method(self.ctxt, 'test.notify', self.payload)
|
|
|
|
|
|
TestMessagingNotifier.generate_scenarios()
|
|
|
|
|
|
class TestSerializer(test_utils.BaseTestCase):
|
|
|
|
def setUp(self):
|
|
super(TestSerializer, self).setUp()
|
|
self.addCleanup(_impl_test.reset)
|
|
self.addCleanup(timeutils.clear_time_override)
|
|
|
|
def test_serializer(self):
|
|
transport = _FakeTransport(self.conf)
|
|
|
|
serializer = msg_serializer.NoOpSerializer()
|
|
|
|
notifier = messaging.Notifier(transport,
|
|
'test.localhost',
|
|
driver='test',
|
|
topic='test',
|
|
serializer=serializer)
|
|
|
|
message_id = uuid.uuid4()
|
|
self.mox.StubOutWithMock(uuid, 'uuid4')
|
|
uuid.uuid4().AndReturn(message_id)
|
|
|
|
timeutils.set_time_override()
|
|
|
|
self.mox.StubOutWithMock(serializer, 'serialize_entity')
|
|
serializer.serialize_entity({}, 'bar').AndReturn('sbar')
|
|
|
|
self.mox.ReplayAll()
|
|
|
|
notifier.info({}, 'test.notify', 'bar')
|
|
|
|
message = {
|
|
'message_id': str(message_id),
|
|
'publisher_id': 'test.localhost',
|
|
'event_type': 'test.notify',
|
|
'priority': 'INFO',
|
|
'payload': 'sbar',
|
|
'timestamp': str(timeutils.utcnow.override_time),
|
|
}
|
|
|
|
self.assertEquals(_impl_test.NOTIFICATIONS, [({}, message, 'INFO')])
|
|
|
|
|
|
class TestLogNotifier(test_utils.BaseTestCase):
|
|
|
|
def setUp(self):
|
|
super(TestLogNotifier, self).setUp()
|
|
self.conf.register_opts(msg_notifier._notifier_opts)
|
|
self.addCleanup(timeutils.clear_time_override)
|
|
|
|
def test_notifier(self):
|
|
self.config(notification_driver=['log'])
|
|
|
|
transport = _FakeTransport(self.conf)
|
|
|
|
notifier = messaging.Notifier(transport, 'test.localhost')
|
|
|
|
message_id = uuid.uuid4()
|
|
self.mox.StubOutWithMock(uuid, 'uuid4')
|
|
uuid.uuid4().AndReturn(message_id)
|
|
|
|
timeutils.set_time_override()
|
|
|
|
message = {
|
|
'message_id': str(message_id),
|
|
'publisher_id': 'test.localhost',
|
|
'event_type': 'test.notify',
|
|
'priority': 'INFO',
|
|
'payload': 'bar',
|
|
'timestamp': str(timeutils.utcnow.override_time),
|
|
}
|
|
|
|
logger = self.mox.CreateMockAnything()
|
|
|
|
self.mox.StubOutWithMock(logging, 'getLogger')
|
|
logging.getLogger('oslo.messaging.notification.test.notify').\
|
|
AndReturn(logger)
|
|
|
|
logger.info(jsonutils.dumps(message))
|
|
|
|
self.mox.ReplayAll()
|
|
|
|
notifier.info({}, 'test.notify', 'bar')
|