From 2045b75bea6e570df372ea6bdd2a9c9af1da0a57 Mon Sep 17 00:00:00 2001 From: Edwin Zhai Date: Tue, 21 Jul 2015 10:10:21 +0800 Subject: [PATCH] Fix notify_decorator errors * getattr is built-in function, so should not be used as attribute. * When ctxt is None, rpc.get_notifier('api').info(ctxt, name, body) leads NoneType exception at context.to_dict(). So we need guarantee one valid context here. Closes-Bug: #1476931 Change-Id: I25953467aca641448d25b2d63352f756ec3655aa --- nova/notifications.py | 10 ++++++---- nova/tests/unit/test_notifications.py | 24 ++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/nova/notifications.py b/nova/notifications.py index 09332938bdb4..574bd2166efb 100644 --- a/nova/notifications.py +++ b/nova/notifications.py @@ -80,14 +80,16 @@ def notify_decorator(name, fn): for key in kwarg: body['kwarg'][key] = kwarg[key] - ctxt = common_context.get_context_from_function_and_args( - fn, args, kwarg) + ctxt = (common_context.get_context_from_function_and_args( + fn, args, kwarg) or + common_context.get_current() or + nova.context.RequestContext()) notifier = rpc.get_notifier('api', publisher_id=(CONF.default_publisher_id or CONF.host)) - method = notifier.getattr(CONF.default_notification_level.lower(), - 'info') + method = getattr(notifier, CONF.default_notification_level.lower(), + 'info') method(ctxt, name, body) return fn(*args, **kwarg) diff --git a/nova/tests/unit/test_notifications.py b/nova/tests/unit/test_notifications.py index 0b2db10a2da9..463e3f68988c 100644 --- a/nova/tests/unit/test_notifications.py +++ b/nova/tests/unit/test_notifications.py @@ -70,6 +70,8 @@ class NotificationsTestCase(test.TestCase): self.instance = self._wrapped_create() + self.decorated_function_called = False + def _wrapped_create(self, params=None): instance_type = flavors.get_flavor_by_name('m1.tiny') inst = objects.Instance(image_ref=1, @@ -462,6 +464,28 @@ class NotificationsTestCase(test.TestCase): self.assertEqual(0, len(fake_notifier.NOTIFICATIONS)) self.assertEqual(0, mock_log_exception.call_count) + def _decorated_function(self, arg1, arg2): + self.decorated_function_called = True + + def test_notify_decorator(self): + func_name = self._decorated_function.__name__ + + # Decorated with notify_decorator like monkey_patch + self._decorated_function = notifications.notify_decorator( + func_name, + self._decorated_function) + + ctxt = o_context.RequestContext() + + self._decorated_function(1, ctxt) + + self.assertEqual(1, len(fake_notifier.NOTIFICATIONS)) + n = fake_notifier.NOTIFICATIONS[0] + self.assertEqual(n.priority, 'INFO') + self.assertEqual(n.event_type, func_name) + self.assertEqual(n.context, ctxt) + self.assertTrue(self.decorated_function_called) + class NotificationsFormatTestCase(test.NoDBTestCase):