conf: added notifications group

Notifications related configuration options have been moved from the
default group to the ``notifications`` group.
Also, ``default_notification_level`` has been renamed to avoid naming
redundancy.

Blueprint centralize-config-options-ocata

Change-Id: I09dc358fabc84f7bf37d40d48b0652a10d9b8903
This commit is contained in:
Maciej Szankin
2016-11-01 13:56:50 +01:00
parent 53b46aa794
commit c5cb7e459c
10 changed files with 69 additions and 36 deletions

View File

@@ -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 Notifier object depends on the parameters of the get_notifier call and the
value of the oslo.messaging configuration options `driver` and `topics`. value of the oslo.messaging configuration options `driver` and `topics`.
There are notification configuration options in Nova which are specific for There are notification configuration options in Nova which are specific for
certain notification types like `notify_on_state_change`, certain notification types like `notifications.notify_on_state_change`,
`notify_api_faults`, `default_notification_level`, etc. `notifications.notify_on_api_faults`, `notifications.default_level`, etc.
The structure of the payload of the unversioned notifications is defined in the The structure of the payload of the unversioned notifications is defined in the
code that emits the notification and no documentation or enforced backward 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 * a major version bump indicates a backward incompatible change of the payload
which can mean removed fields, type change, etc in 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 There is a Nova configuration parameter `notifications.notification_format`
to specify which notifications are emitted by Nova. The possible values are that can be used to specify which notifications are emitted by Nova. The
`unversioned`, `versioned`, `both` and the default value is `both`. possible values are `unversioned`, `versioned`, `both` and the default value
is `both`.
How to add a new versioned notification How to add a new versioned notification
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@@ -16,10 +16,21 @@
from oslo_config import cfg 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 = [ ALL_OPTS = [
cfg.StrOpt( cfg.StrOpt(
'notify_on_state_change', 'notify_on_state_change',
choices=(None, 'vm_state', 'vm_and_task_state'), choices=(None, 'vm_state', 'vm_and_task_state'),
deprecated_group='default',
help=""" help="""
If set, send compute.instance.update notifications on instance state If set, send compute.instance.update notifications on instance state
changes. changes.
@@ -35,22 +46,27 @@ Possible values:
"""), """),
cfg.BoolOpt( cfg.BoolOpt(
'notify_api_faults', 'notify_on_api_faults',
default=False, default=False,
deprecated_group='default',
deprecated_name='notify_api_faults',
help=""" help="""
If enabled, send api.fault notifications on caught exceptions in the If enabled, send api.fault notifications on caught exceptions in the
API service. API service.
"""), """),
cfg.StrOpt( cfg.StrOpt(
'default_notification_level', 'default_level',
default='INFO', default='INFO',
choices=('DEBUG', 'INFO', 'WARN', 'ERROR', 'CRITICAL'), choices=('DEBUG', 'INFO', 'WARN', 'ERROR', 'CRITICAL'),
deprecated_group='default',
deprecated_name='default_notification_level',
help="Default notification level for outgoing notifications."), help="Default notification level for outgoing notifications."),
cfg.StrOpt( cfg.StrOpt(
'default_publisher_id', 'default_publisher_id',
default='$my_ip', default='$my_ip',
deprecated_group='default',
help=""" help="""
Default publisher_id for outgoing notifications. If you consider routing Default publisher_id for outgoing notifications. If you consider routing
notifications using different publisher, change this value accordingly. notifications using different publisher, change this value accordingly.
@@ -68,6 +84,7 @@ Related options:
'notification_format', 'notification_format',
choices=['unversioned', 'versioned', 'both'], choices=['unversioned', 'versioned', 'both'],
default='both', default='both',
deprecated_group='default',
help=""" help="""
Specifies which notification format shall be used by nova. 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): 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(): def list_opts():
return {'DEFAULT': ALL_OPTS} return {notifications_group: ALL_OPTS}

View File

@@ -69,10 +69,10 @@ def notify_decorator(name, fn):
common_context.get_current() or common_context.get_current() or
nova.context.RequestContext()) nova.context.RequestContext())
notifier = rpc.get_notifier('api', notifier = rpc.get_notifier('api', publisher_id=(
publisher_id=(CONF.default_publisher_id CONF.notifications.default_publisher_id or CONF.host))
or CONF.host)) method = getattr(notifier,
method = getattr(notifier, CONF.default_notification_level.lower(), CONF.notifications.default_level.lower(),
notifier.info) notifier.info)
method(ctxt, name, body) method(ctxt, name, body)
@@ -83,7 +83,7 @@ def notify_decorator(name, fn):
def send_api_fault(url, status, exception): def send_api_fault(url, status, exception):
"""Send an api.fault notification.""" """Send an api.fault notification."""
if not CONF.notify_api_faults: if not CONF.notifications.notify_on_api_faults:
return return
payload = {'url': url, 'exception': six.text_type(exception), 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 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 # skip all this if updates are disabled
return return
@@ -117,7 +117,7 @@ def send_update(context, old_instance, new_instance, service="compute",
if old_vm_state != new_vm_state: if old_vm_state != new_vm_state:
# yes, the vm state is changing: # yes, the vm state is changing:
update_with_state_change = True 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): old_task_state != new_task_state):
# yes, the task state is changing: # yes, the task state is changing:
update_with_state_change = True 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 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 # skip all this if updates are disabled
return 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: if old_vm_state != new_vm_state:
# yes, the vm state is changing: # yes, the vm state is changing:
fire_update = True fire_update = True
elif (CONF.notify_on_state_change == "vm_and_task_state" and elif (CONF.notifications.notify_on_state_change == "vm_and_task_state"
old_task_state != new_task_state): and old_task_state != new_task_state):
# yes, the task state is changing: # yes, the task state is changing:
fire_update = True fire_update = True

View File

@@ -75,12 +75,12 @@ def init(conf):
NOTIFICATION_TRANSPORT = messaging.get_notification_transport( NOTIFICATION_TRANSPORT = messaging.get_notification_transport(
conf, allowed_remote_exmods=exmods, aliases=TRANSPORT_ALIASES) conf, allowed_remote_exmods=exmods, aliases=TRANSPORT_ALIASES)
serializer = RequestContextSerializer(JsonPayloadSerializer()) serializer = RequestContextSerializer(JsonPayloadSerializer())
if conf.notification_format == 'unversioned': if conf.notifications.notification_format == 'unversioned':
LEGACY_NOTIFIER = messaging.Notifier(NOTIFICATION_TRANSPORT, LEGACY_NOTIFIER = messaging.Notifier(NOTIFICATION_TRANSPORT,
serializer=serializer) serializer=serializer)
NOTIFIER = messaging.Notifier(NOTIFICATION_TRANSPORT, NOTIFIER = messaging.Notifier(NOTIFICATION_TRANSPORT,
serializer=serializer, driver='noop') serializer=serializer, driver='noop')
elif conf.notification_format == 'both': elif conf.notifications.notification_format == 'both':
LEGACY_NOTIFIER = messaging.Notifier(NOTIFICATION_TRANSPORT, LEGACY_NOTIFIER = messaging.Notifier(NOTIFICATION_TRANSPORT,
serializer=serializer) serializer=serializer)
NOTIFIER = messaging.Notifier(NOTIFICATION_TRANSPORT, NOTIFIER = messaging.Notifier(NOTIFICATION_TRANSPORT,

View File

@@ -147,7 +147,8 @@ class TestInstanceNotificationSample(
# for notification samples that expect instance.info_cache.network_info # for notification samples that expect instance.info_cache.network_info
# to be set. # to be set.
self.useFixture(fixtures.SpawnIsSynchronousFixture()) 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( server = self._boot_a_server(
extra_params={'networks': [{'port': self.neutron.port_1['id']}]}) extra_params={'networks': [{'port': self.neutron.port_1['id']}]})

View File

@@ -8744,7 +8744,7 @@ class ComputeAPITestCase(BaseTestCase):
def test_instance_metadata(self): def test_instance_metadata(self):
meta_changes = [None] 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, def fake_change_instance_metadata(inst, ctxt, diff, instance=None,
instance_uuid=None): instance_uuid=None):

View File

@@ -56,8 +56,9 @@ class NotificationsTestCase(test.TestCase):
self.addCleanup(fake_notifier.reset) self.addCleanup(fake_notifier.reset)
self.flags(network_manager='nova.network.manager.FlatManager', self.flags(network_manager='nova.network.manager.FlatManager',
notify_on_state_change="vm_and_task_state",
host='testhost') host='testhost')
self.flags(notify_on_state_change="vm_and_task_state",
group='notifications')
self.flags(api_servers=['http://localhost:9292'], group='glance') self.flags(api_servers=['http://localhost:9292'], group='glance')
@@ -91,12 +92,12 @@ class NotificationsTestCase(test.TestCase):
return inst return inst
def test_send_api_fault_disabled(self): 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) notifications.send_api_fault("http://example.com/foo", 500, None)
self.assertEqual(0, len(fake_notifier.NOTIFICATIONS)) self.assertEqual(0, len(fake_notifier.NOTIFICATIONS))
def test_send_api_fault(self): def test_send_api_fault(self):
self.flags(notify_api_faults=True) self.flags(notify_on_api_faults=True, group='notifications')
exception = None exception = None
try: try:
# Get a real exception with a call stack. # Get a real exception with a call stack.
@@ -115,7 +116,7 @@ class NotificationsTestCase(test.TestCase):
self.assertIsNotNone(n.payload['exception']) self.assertIsNotNone(n.payload['exception'])
def test_send_api_fault_fresh_context(self): 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 exception = None
try: try:
# Get a real exception with a call stack. # Get a real exception with a call stack.
@@ -136,7 +137,7 @@ class NotificationsTestCase(test.TestCase):
self.assertEqual(ctxt, n.context) self.assertEqual(ctxt, n.context)
def test_send_api_fault_fake_context(self): 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 exception = None
try: try:
# Get a real exception with a call stack. # Get a real exception with a call stack.
@@ -159,7 +160,7 @@ class NotificationsTestCase(test.TestCase):
self.assertEqual(ctxt, n.context) self.assertEqual(ctxt, n.context)
def test_send_api_fault_admin_context(self): 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 exception = None
try: try:
# Get a real exception with a call stack. # Get a real exception with a call stack.
@@ -184,7 +185,7 @@ class NotificationsTestCase(test.TestCase):
def test_notif_disabled(self): def test_notif_disabled(self):
# test config disable of the notifications # 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) old = copy.copy(self.instance)
self.instance.vm_state = vm_states.ACTIVE self.instance.vm_state = vm_states.ACTIVE
@@ -205,7 +206,7 @@ class NotificationsTestCase(test.TestCase):
def test_task_notif(self): def test_task_notif(self):
# test config disable of just the task state notifications # 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 # we should not get a notification on task stgate chagne now
old = copy.copy(self.instance) old = copy.copy(self.instance)
@@ -224,7 +225,8 @@ class NotificationsTestCase(test.TestCase):
self.assertEqual(0, len(fake_notifier.VERSIONED_NOTIFICATIONS)) self.assertEqual(0, len(fake_notifier.VERSIONED_NOTIFICATIONS))
# ok now enable task state notifications and re-try # 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) notifications.send_update(self.context, old, self.instance)
self.assertEqual(1, len(fake_notifier.NOTIFICATIONS)) self.assertEqual(1, len(fake_notifier.NOTIFICATIONS))
@@ -375,7 +377,8 @@ class NotificationsTestCase(test.TestCase):
@mock.patch.object(objects.BandwidthUsageList, 'get_by_uuids') @mock.patch.object(objects.BandwidthUsageList, 'get_by_uuids')
def test_task_update_with_states(self, mock_bandwidth_list): 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()] mock_bandwidth_list.return_value = [self.get_fake_bandwidth()]
fake_net_info = fake_network.fake_get_instance_nw_info(self, 1, 1) fake_net_info = fake_network.fake_get_instance_nw_info(self, 1, 1)
self.instance.info_cache.network_info = fake_net_info self.instance.info_cache.network_info = fake_net_info

View File

@@ -46,7 +46,7 @@ class TestNotifier(test.NoDBTestCase):
for config in cases: for config in cases:
mock_notifier.reset_mock() mock_notifier.reset_mock()
mock_notifier.side_effect = ['first', 'second'] mock_notifier.side_effect = ['first', 'second']
conf.notification_format = config conf.notifications.notification_format = config
rpc.init(conf) rpc.init(conf)
self.assertEqual(cases[config], mock_notifier.call_args_list) self.assertEqual(cases[config], mock_notifier.call_args_list)
self.assertEqual('first', rpc.LEGACY_NOTIFIER) self.assertEqual('first', rpc.LEGACY_NOTIFIER)

View File

@@ -273,7 +273,7 @@ class TestRPC(testtools.TestCase):
conf = mock.Mock() conf = mock.Mock()
conf.transport_url = None conf.transport_url = None
conf.notification_format = notif_format conf.notifications.notification_format = notif_format
mock_exmods.return_value = ['foo'] mock_exmods.return_value = ['foo']
mock_noti_trans.return_value = notif_transport mock_noti_trans.return_value = notif_transport
mock_ser.return_value = serializer mock_ser.return_value = serializer

View File

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