diff --git a/doc/source/notifications.rst b/doc/source/notifications.rst index 4b9a93bda13f..1cbbeb0ac460 100644 --- a/doc/source/notifications.rst +++ b/doc/source/notifications.rst @@ -40,8 +40,8 @@ Notifier object to emit notifications. The configuration of the returned Notifier object depends on the parameters of the get_notifier call and the value of the oslo.messaging configuration options `driver` and `topics`. There are notification configuration options in Nova which are specific for -certain notification types like `notify_on_state_change`, -`notify_api_faults`, `default_notification_level`, etc. +certain notification types like `notifications.notify_on_state_change`, +`notifications.notify_on_api_faults`, `notifications.default_level`, etc. The structure of the payload of the unversioned notifications is defined in the code that emits the notification and no documentation or enforced backward @@ -97,9 +97,10 @@ notification payload: * a major version bump indicates a backward incompatible change of the payload which can mean removed fields, type change, etc in the payload. -There is a Nova configuration parameter `notification_format` that can be used -to specify which notifications are emitted by Nova. The possible values are -`unversioned`, `versioned`, `both` and the default value is `both`. +There is a Nova configuration parameter `notifications.notification_format` +that can be used to specify which notifications are emitted by Nova. The +possible values are `unversioned`, `versioned`, `both` and the default value +is `both`. How to add a new versioned notification ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/nova/conf/notifications.py b/nova/conf/notifications.py index 3ce17c588624..f2025efc22de 100644 --- a/nova/conf/notifications.py +++ b/nova/conf/notifications.py @@ -16,10 +16,21 @@ from oslo_config import cfg +notifications_group = cfg.OptGroup( + name='notifications', + title='Notifications options', + help=""" +Most of the actions in Nova which manipulate the system state generate +notifications which are posted to the messaging component (e.g. RabbitMQ) and +can be consumed by any service outside the Openstack. More technical details +at http://docs.openstack.org/developer/nova/notifications.html +""") + ALL_OPTS = [ cfg.StrOpt( 'notify_on_state_change', choices=(None, 'vm_state', 'vm_and_task_state'), + deprecated_group='default', help=""" If set, send compute.instance.update notifications on instance state changes. @@ -35,22 +46,27 @@ Possible values: """), cfg.BoolOpt( - 'notify_api_faults', + 'notify_on_api_faults', default=False, + deprecated_group='default', + deprecated_name='notify_api_faults', help=""" If enabled, send api.fault notifications on caught exceptions in the API service. """), cfg.StrOpt( - 'default_notification_level', + 'default_level', default='INFO', choices=('DEBUG', 'INFO', 'WARN', 'ERROR', 'CRITICAL'), + deprecated_group='default', + deprecated_name='default_notification_level', help="Default notification level for outgoing notifications."), cfg.StrOpt( 'default_publisher_id', default='$my_ip', + deprecated_group='default', help=""" Default publisher_id for outgoing notifications. If you consider routing notifications using different publisher, change this value accordingly. @@ -68,6 +84,7 @@ Related options: 'notification_format', choices=['unversioned', 'versioned', 'both'], default='both', + deprecated_group='default', help=""" Specifies which notification format shall be used by nova. @@ -89,9 +106,9 @@ http://docs.openstack.org/developer/nova/notifications.html def register_opts(conf): - conf.register_opts(ALL_OPTS) + conf.register_group(notifications_group) + conf.register_opts(ALL_OPTS, group=notifications_group) -# TODO(johngarbutt): we should move this to a notification group. def list_opts(): - return {'DEFAULT': ALL_OPTS} + return {notifications_group: ALL_OPTS} diff --git a/nova/notifications/base.py b/nova/notifications/base.py index d22b98604982..5d37f03d45f1 100644 --- a/nova/notifications/base.py +++ b/nova/notifications/base.py @@ -69,10 +69,10 @@ def notify_decorator(name, fn): common_context.get_current() or nova.context.RequestContext()) - notifier = rpc.get_notifier('api', - publisher_id=(CONF.default_publisher_id - or CONF.host)) - method = getattr(notifier, CONF.default_notification_level.lower(), + notifier = rpc.get_notifier('api', publisher_id=( + CONF.notifications.default_publisher_id or CONF.host)) + method = getattr(notifier, + CONF.notifications.default_level.lower(), notifier.info) method(ctxt, name, body) @@ -83,7 +83,7 @@ def notify_decorator(name, fn): def send_api_fault(url, status, exception): """Send an api.fault notification.""" - if not CONF.notify_api_faults: + if not CONF.notifications.notify_on_api_faults: return payload = {'url': url, 'exception': six.text_type(exception), @@ -101,7 +101,7 @@ def send_update(context, old_instance, new_instance, service="compute", in that instance """ - if not CONF.notify_on_state_change: + if not CONF.notifications.notify_on_state_change: # skip all this if updates are disabled return @@ -117,7 +117,7 @@ def send_update(context, old_instance, new_instance, service="compute", if old_vm_state != new_vm_state: # yes, the vm state is changing: update_with_state_change = True - elif (CONF.notify_on_state_change == "vm_and_task_state" and + elif (CONF.notifications.notify_on_state_change == "vm_and_task_state" and old_task_state != new_task_state): # yes, the task state is changing: update_with_state_change = True @@ -153,7 +153,7 @@ def send_update_with_states(context, instance, old_vm_state, new_vm_state, are any, in the instance """ - if not CONF.notify_on_state_change: + if not CONF.notifications.notify_on_state_change: # skip all this if updates are disabled return @@ -168,8 +168,8 @@ def send_update_with_states(context, instance, old_vm_state, new_vm_state, if old_vm_state != new_vm_state: # yes, the vm state is changing: fire_update = True - elif (CONF.notify_on_state_change == "vm_and_task_state" and - old_task_state != new_task_state): + elif (CONF.notifications.notify_on_state_change == "vm_and_task_state" + and old_task_state != new_task_state): # yes, the task state is changing: fire_update = True diff --git a/nova/rpc.py b/nova/rpc.py index 8963557952dd..21345b18ef38 100644 --- a/nova/rpc.py +++ b/nova/rpc.py @@ -75,12 +75,12 @@ def init(conf): NOTIFICATION_TRANSPORT = messaging.get_notification_transport( conf, allowed_remote_exmods=exmods, aliases=TRANSPORT_ALIASES) serializer = RequestContextSerializer(JsonPayloadSerializer()) - if conf.notification_format == 'unversioned': + if conf.notifications.notification_format == 'unversioned': LEGACY_NOTIFIER = messaging.Notifier(NOTIFICATION_TRANSPORT, serializer=serializer) NOTIFIER = messaging.Notifier(NOTIFICATION_TRANSPORT, serializer=serializer, driver='noop') - elif conf.notification_format == 'both': + elif conf.notifications.notification_format == 'both': LEGACY_NOTIFIER = messaging.Notifier(NOTIFICATION_TRANSPORT, serializer=serializer) NOTIFIER = messaging.Notifier(NOTIFICATION_TRANSPORT, diff --git a/nova/tests/functional/notification_sample_tests/test_instance.py b/nova/tests/functional/notification_sample_tests/test_instance.py index a6fac9e184c6..53af3def779a 100644 --- a/nova/tests/functional/notification_sample_tests/test_instance.py +++ b/nova/tests/functional/notification_sample_tests/test_instance.py @@ -147,7 +147,8 @@ class TestInstanceNotificationSample( # for notification samples that expect instance.info_cache.network_info # to be set. self.useFixture(fixtures.SpawnIsSynchronousFixture()) - self.flags(notify_on_state_change='vm_and_task_state') + self.flags(notify_on_state_change='vm_and_task_state', + group='notifications') server = self._boot_a_server( extra_params={'networks': [{'port': self.neutron.port_1['id']}]}) diff --git a/nova/tests/unit/compute/test_compute.py b/nova/tests/unit/compute/test_compute.py index cc40216be683..78f7daca3a0f 100644 --- a/nova/tests/unit/compute/test_compute.py +++ b/nova/tests/unit/compute/test_compute.py @@ -8744,7 +8744,7 @@ class ComputeAPITestCase(BaseTestCase): def test_instance_metadata(self): meta_changes = [None] - self.flags(notify_on_state_change='vm_state') + self.flags(notify_on_state_change='vm_state', group='notifications') def fake_change_instance_metadata(inst, ctxt, diff, instance=None, instance_uuid=None): diff --git a/nova/tests/unit/test_notifications.py b/nova/tests/unit/test_notifications.py index ac6a6b52fcac..749048664cf2 100644 --- a/nova/tests/unit/test_notifications.py +++ b/nova/tests/unit/test_notifications.py @@ -56,8 +56,9 @@ class NotificationsTestCase(test.TestCase): self.addCleanup(fake_notifier.reset) self.flags(network_manager='nova.network.manager.FlatManager', - notify_on_state_change="vm_and_task_state", host='testhost') + self.flags(notify_on_state_change="vm_and_task_state", + group='notifications') self.flags(api_servers=['http://localhost:9292'], group='glance') @@ -91,12 +92,12 @@ class NotificationsTestCase(test.TestCase): return inst def test_send_api_fault_disabled(self): - self.flags(notify_api_faults=False) + self.flags(notify_on_api_faults=False, group='notifications') notifications.send_api_fault("http://example.com/foo", 500, None) self.assertEqual(0, len(fake_notifier.NOTIFICATIONS)) def test_send_api_fault(self): - self.flags(notify_api_faults=True) + self.flags(notify_on_api_faults=True, group='notifications') exception = None try: # Get a real exception with a call stack. @@ -115,7 +116,7 @@ class NotificationsTestCase(test.TestCase): self.assertIsNotNone(n.payload['exception']) def test_send_api_fault_fresh_context(self): - self.flags(notify_api_faults=True) + self.flags(notify_on_api_faults=True, group='notifications') exception = None try: # Get a real exception with a call stack. @@ -136,7 +137,7 @@ class NotificationsTestCase(test.TestCase): self.assertEqual(ctxt, n.context) def test_send_api_fault_fake_context(self): - self.flags(notify_api_faults=True) + self.flags(notify_on_api_faults=True, group='notifications') exception = None try: # Get a real exception with a call stack. @@ -159,7 +160,7 @@ class NotificationsTestCase(test.TestCase): self.assertEqual(ctxt, n.context) def test_send_api_fault_admin_context(self): - self.flags(notify_api_faults=True) + self.flags(notify_on_api_faults=True, group='notifications') exception = None try: # Get a real exception with a call stack. @@ -184,7 +185,7 @@ class NotificationsTestCase(test.TestCase): def test_notif_disabled(self): # test config disable of the notifications - self.flags(notify_on_state_change=None) + self.flags(notify_on_state_change=None, group='notifications') old = copy.copy(self.instance) self.instance.vm_state = vm_states.ACTIVE @@ -205,7 +206,7 @@ class NotificationsTestCase(test.TestCase): def test_task_notif(self): # test config disable of just the task state notifications - self.flags(notify_on_state_change="vm_state") + self.flags(notify_on_state_change="vm_state", group='notifications') # we should not get a notification on task stgate chagne now old = copy.copy(self.instance) @@ -224,7 +225,8 @@ class NotificationsTestCase(test.TestCase): self.assertEqual(0, len(fake_notifier.VERSIONED_NOTIFICATIONS)) # ok now enable task state notifications and re-try - self.flags(notify_on_state_change="vm_and_task_state") + self.flags(notify_on_state_change="vm_and_task_state", + group='notifications') notifications.send_update(self.context, old, self.instance) self.assertEqual(1, len(fake_notifier.NOTIFICATIONS)) @@ -375,7 +377,8 @@ class NotificationsTestCase(test.TestCase): @mock.patch.object(objects.BandwidthUsageList, 'get_by_uuids') def test_task_update_with_states(self, mock_bandwidth_list): - self.flags(notify_on_state_change="vm_and_task_state") + self.flags(notify_on_state_change="vm_and_task_state", + group='notifications') mock_bandwidth_list.return_value = [self.get_fake_bandwidth()] fake_net_info = fake_network.fake_get_instance_nw_info(self, 1, 1) self.instance.info_cache.network_info = fake_net_info diff --git a/nova/tests/unit/test_notifier.py b/nova/tests/unit/test_notifier.py index b72c38631226..d77f69d30a62 100644 --- a/nova/tests/unit/test_notifier.py +++ b/nova/tests/unit/test_notifier.py @@ -46,7 +46,7 @@ class TestNotifier(test.NoDBTestCase): for config in cases: mock_notifier.reset_mock() mock_notifier.side_effect = ['first', 'second'] - conf.notification_format = config + conf.notifications.notification_format = config rpc.init(conf) self.assertEqual(cases[config], mock_notifier.call_args_list) self.assertEqual('first', rpc.LEGACY_NOTIFIER) diff --git a/nova/tests/unit/test_rpc.py b/nova/tests/unit/test_rpc.py index 13afcdad3dbe..c71551193f0e 100644 --- a/nova/tests/unit/test_rpc.py +++ b/nova/tests/unit/test_rpc.py @@ -273,7 +273,7 @@ class TestRPC(testtools.TestCase): conf = mock.Mock() conf.transport_url = None - conf.notification_format = notif_format + conf.notifications.notification_format = notif_format mock_exmods.return_value = ['foo'] mock_noti_trans.return_value = notif_transport mock_ser.return_value = serializer diff --git a/releasenotes/notes/move-notifications-opts-to-notifications-group-7dc9e76673472b8b.yaml b/releasenotes/notes/move-notifications-opts-to-notifications-group-7dc9e76673472b8b.yaml new file mode 100644 index 000000000000..400a1ea12c45 --- /dev/null +++ b/releasenotes/notes/move-notifications-opts-to-notifications-group-7dc9e76673472b8b.yaml @@ -0,0 +1,11 @@ +--- +upgrade: + - | + Following Notifications related configuration options have been moved from + the ``DEFAULT`` group to the ``notifications`` group: + + - ``notify_on_state_change`` + - ``notify_on_api_faults`` (was ``notify_api_faults``) + - ``default_level`` (was ``default_notification_level``) + - ``default_publisher_id`` + - ``notification_format``