From 090d58d23dd4586d7cd27660e6e00a3ade7a8375 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9la=20Vancsics?= Date: Thu, 27 Apr 2017 17:02:40 +0200 Subject: [PATCH] Transform aggregate.update_metadata notification The aggregate.update_metadata.start and aggregate.update_metadata.end notifications has been transformed to the versioned notification framework. Co-Authored-By: Takashi Natsume Change-Id: Iab73b1351a50869620334f692aaefb566ba4ddf8 Implements: bp versioned-notification-transformation-rocky --- .../aggregate-update_metadata-end.json | 13 ++++++++ .../aggregate-update_metadata-start.json | 8 +++++ nova/notifications/objects/aggregate.py | 2 ++ nova/notifications/objects/base.py | 4 ++- nova/objects/aggregate.py | 10 ++++++ nova/objects/fields.py | 3 +- .../test_aggregate.py | 31 +++++++++++++++++++ nova/tests/unit/compute/test_compute.py | 16 ++++++++-- .../objects/test_notification.py | 2 +- nova/tests/unit/objects/test_aggregate.py | 15 ++++++++- nova/tests/unit/virt/xenapi/test_xenapi.py | 3 +- 11 files changed, 100 insertions(+), 7 deletions(-) create mode 100644 doc/notification_samples/aggregate-update_metadata-end.json create mode 100644 doc/notification_samples/aggregate-update_metadata-start.json diff --git a/doc/notification_samples/aggregate-update_metadata-end.json b/doc/notification_samples/aggregate-update_metadata-end.json new file mode 100644 index 000000000000..1bcb0a8e93c6 --- /dev/null +++ b/doc/notification_samples/aggregate-update_metadata-end.json @@ -0,0 +1,13 @@ +{ + "priority": "INFO", + "payload": { + "$ref": "common_payloads/AggregatePayload.json#", + "nova_object.data": { + "metadata": { + "availability_zone": "AZ-1" + } + } + }, + "event_type": "aggregate.update_metadata.end", + "publisher_id": "nova-api:fake-mini" +} diff --git a/doc/notification_samples/aggregate-update_metadata-start.json b/doc/notification_samples/aggregate-update_metadata-start.json new file mode 100644 index 000000000000..68bd9e507855 --- /dev/null +++ b/doc/notification_samples/aggregate-update_metadata-start.json @@ -0,0 +1,8 @@ +{ + "priority": "INFO", + "payload": { + "$ref": "common_payloads/AggregatePayload.json#" + }, + "event_type": "aggregate.update_metadata.start", + "publisher_id": "nova-api:fake-mini" +} diff --git a/nova/notifications/objects/aggregate.py b/nova/notifications/objects/aggregate.py index 3efa292ec91c..8698ee890f94 100644 --- a/nova/notifications/objects/aggregate.py +++ b/nova/notifications/objects/aggregate.py @@ -50,6 +50,8 @@ class AggregatePayload(base.NotificationPayloadBase): @base.notification_sample('aggregate-add_host-end.json') @base.notification_sample('aggregate-remove_host-start.json') @base.notification_sample('aggregate-remove_host-end.json') +@base.notification_sample('aggregate-update_metadata-start.json') +@base.notification_sample('aggregate-update_metadata-end.json') @nova_base.NovaObjectRegistry.register_notification class AggregateNotification(base.NotificationBase): # Version 1.0: Initial version diff --git a/nova/notifications/objects/base.py b/nova/notifications/objects/base.py index 8ad69fcbd4f1..07ba263d5220 100644 --- a/nova/notifications/objects/base.py +++ b/nova/notifications/objects/base.py @@ -54,7 +54,9 @@ class EventType(NotificationObject): # NotificationActionField enum # Version 1.8: IMPORT value is added to NotificationActionField enum # Version 1.9: ADD_MEMBER value is added to NotificationActionField enum - VERSION = '1.9' + # Version 1.10: UPDATE_METADATA value is added to the + # NotificationActionField enum + VERSION = '1.10' fields = { 'object': fields.StringField(nullable=False), diff --git a/nova/objects/aggregate.py b/nova/objects/aggregate.py index dfe3f890e068..0f6ca130a278 100644 --- a/nova/objects/aggregate.py +++ b/nova/objects/aggregate.py @@ -347,6 +347,11 @@ class Aggregate(base.NovaPersistentObject, base.NovaObject): compute_utils.notify_about_aggregate_update(self._context, "updatemetadata.start", payload) + compute_utils.notify_about_aggregate_action( + context=self._context, + aggregate=self, + action=fields.NotificationAction.UPDATE_METADATA, + phase=fields.NotificationPhase.START) to_add = {} for key, value in updates.items(): if value is None: @@ -365,6 +370,11 @@ class Aggregate(base.NovaPersistentObject, base.NovaObject): compute_utils.notify_about_aggregate_update(self._context, "updatemetadata.end", payload) + compute_utils.notify_about_aggregate_action( + context=self._context, + aggregate=self, + action=fields.NotificationAction.UPDATE_METADATA, + phase=fields.NotificationPhase.END) self.obj_reset_changes(fields=['metadata']) @base.remotable diff --git a/nova/objects/fields.py b/nova/objects/fields.py index c86f9499f4a5..b19422edfec9 100644 --- a/nova/objects/fields.py +++ b/nova/objects/fields.py @@ -827,6 +827,7 @@ class NotificationAction(BaseNovaEnum): ADD_HOST = 'add_host' REMOVE_HOST = 'remove_host' ADD_MEMBER = 'add_member' + UPDATE_METADATA = 'update_metadata' ALL = (UPDATE, EXCEPTION, DELETE, PAUSE, UNPAUSE, RESIZE, VOLUME_SWAP, SUSPEND, POWER_ON, REBOOT, SHUTDOWN, SNAPSHOT, INTERFACE_ATTACH, @@ -837,7 +838,7 @@ class NotificationAction(BaseNovaEnum): LIVE_MIGRATION_ROLLBACK_DEST, REBUILD, INTERFACE_DETACH, RESIZE_CONFIRM, RESIZE_PREP, RESIZE_REVERT, SHELVE_OFFLOAD, SOFT_DELETE, TRIGGER_CRASH_DUMP, UNRESCUE, UNSHELVE, ADD_HOST, - REMOVE_HOST, ADD_MEMBER) + REMOVE_HOST, ADD_MEMBER, UPDATE_METADATA) # TODO(rlrossit): These should be changed over to be a StateMachine enum from diff --git a/nova/tests/functional/notification_sample_tests/test_aggregate.py b/nova/tests/functional/notification_sample_tests/test_aggregate.py index 61a4a20565b9..95cb8775cf3c 100644 --- a/nova/tests/functional/notification_sample_tests/test_aggregate.py +++ b/nova/tests/functional/notification_sample_tests/test_aggregate.py @@ -105,3 +105,34 @@ class TestAggregateNotificationSample( actual=fake_notifier.VERSIONED_NOTIFICATIONS[3]) self.admin_api.delete_aggregate(aggregate['id']) + + def test_aggregate_update_metadata(self): + aggregate_req = { + "aggregate": { + "name": "my-aggregate", + "availability_zone": "nova"}} + aggregate = self.admin_api.post_aggregate(aggregate_req) + + set_metadata_req = { + "set_metadata": { + "metadata": { + "availability_zone": "AZ-1" + } + } + } + fake_notifier.reset() + self.admin_api.post_aggregate_action(aggregate['id'], set_metadata_req) + + self.assertEqual(2, len(fake_notifier.VERSIONED_NOTIFICATIONS)) + self._verify_notification( + 'aggregate-update_metadata-start', + replacements={ + 'uuid': aggregate['uuid'], + 'id': aggregate['id']}, + actual=fake_notifier.VERSIONED_NOTIFICATIONS[0]) + self._verify_notification( + 'aggregate-update_metadata-end', + replacements={ + 'uuid': aggregate['uuid'], + 'id': aggregate['id']}, + actual=fake_notifier.VERSIONED_NOTIFICATIONS[1]) diff --git a/nova/tests/unit/compute/test_compute.py b/nova/tests/unit/compute/test_compute.py index 9aa46134b194..fb4096736ebe 100644 --- a/nova/tests/unit/compute/test_compute.py +++ b/nova/tests/unit/compute/test_compute.py @@ -11687,7 +11687,8 @@ class ComputeAPIAggrTestCase(BaseTestCase): self.api.update_aggregate, self.context, aggr2.id, metadata) - def test_update_aggregate_metadata(self): + @mock.patch('nova.compute.utils.notify_about_aggregate_action') + def test_update_aggregate_metadata(self, mock_notify): # Ensure metadata can be updated. aggr = self.api.create_aggregate(self.context, 'fake_aggregate', 'fake_zone') @@ -11706,6 +11707,11 @@ class ComputeAPIAggrTestCase(BaseTestCase): msg = fake_notifier.NOTIFICATIONS[1] self.assertEqual(msg.event_type, 'aggregate.updatemetadata.end') + mock_notify.assert_has_calls([ + mock.call(context=self.context, aggregate=aggr, + action='update_metadata', phase='start'), + mock.call(context=self.context, aggregate=aggr, + action='update_metadata', phase='end')]) fake_notifier.NOTIFICATIONS = [] metadata['foo_key1'] = None expected_payload_meta_data = {'foo_key1': None, @@ -11724,7 +11730,8 @@ class ComputeAPIAggrTestCase(BaseTestCase): matchers.DictMatches({'availability_zone': 'fake_zone', 'foo_key2': 'foo_value2'})) - def test_update_aggregate_metadata_no_az(self): + @mock.patch('nova.compute.utils.notify_about_aggregate_action') + def test_update_aggregate_metadata_no_az(self, mock_notify): # Ensure metadata without availability zone can be # updated,even the aggregate contains hosts belong # to another availability zone @@ -11746,6 +11753,11 @@ class ComputeAPIAggrTestCase(BaseTestCase): msg = fake_notifier.NOTIFICATIONS[1] self.assertEqual(msg.event_type, 'aggregate.updatemetadata.end') + mock_notify.assert_has_calls([ + mock.call(context=self.context, aggregate=aggr2, + action='update_metadata', phase='start'), + mock.call(context=self.context, aggregate=aggr2, + action='update_metadata', phase='end')]) self.assertThat(aggr2.metadata, matchers.DictMatches({'foo_key2': 'foo_value3'})) diff --git a/nova/tests/unit/notifications/objects/test_notification.py b/nova/tests/unit/notifications/objects/test_notification.py index 44205bc02597..237bc29ded1b 100644 --- a/nova/tests/unit/notifications/objects/test_notification.py +++ b/nova/tests/unit/notifications/objects/test_notification.py @@ -373,7 +373,7 @@ notification_object_data = { 'AuditPeriodPayload': '1.0-2b429dd307b8374636703b843fa3f9cb', 'BandwidthPayload': '1.0-ee2616a7690ab78406842a2b68e34130', 'BlockDevicePayload': '1.0-29751e1b6d41b1454e36768a1e764df8', - 'EventType': '1.9-0ef3553b1d64b4cf92780776eda80883', + 'EventType': '1.10-2a6ab743d767837366ab1aec387d7c3b', 'ExceptionNotification': '1.0-a73147b93b520ff0061865849d3dfa56', 'ExceptionPayload': '1.0-27db46ee34cd97e39f2643ed92ad0cc5', 'FlavorNotification': '1.0-a73147b93b520ff0061865849d3dfa56', diff --git a/nova/tests/unit/objects/test_aggregate.py b/nova/tests/unit/objects/test_aggregate.py index cf78d22b7570..3544f8bd5620 100644 --- a/nova/tests/unit/objects/test_aggregate.py +++ b/nova/tests/unit/objects/test_aggregate.py @@ -122,7 +122,13 @@ class _TestAggregateObject(object): @mock.patch('nova.objects.aggregate._metadata_delete_from_db') @mock.patch('nova.objects.aggregate._metadata_add_to_db') - def test_update_metadata_api(self, mock_api_metadata_add, + @mock.patch('nova.compute.utils.notify_about_aggregate_action') + @mock.patch('oslo_versionedobjects.base.VersionedObject.' + 'obj_from_primitive') + def test_update_metadata_api(self, + mock_obj_from_primitive, + mock_notify, + mock_api_metadata_add, mock_api_metadata_delete): fake_notifier.NOTIFICATIONS = [] agg = aggregate.Aggregate() @@ -130,6 +136,8 @@ class _TestAggregateObject(object): agg.id = 123 agg.metadata = {'foo': 'bar'} agg.obj_reset_changes() + mock_obj_from_primitive.return_value = agg + agg.update_metadata({'todelete': None, 'toadd': 'myval'}) self.assertEqual(2, len(fake_notifier.NOTIFICATIONS)) msg = fake_notifier.NOTIFICATIONS[0] @@ -138,6 +146,11 @@ class _TestAggregateObject(object): msg.payload['meta_data']) msg = fake_notifier.NOTIFICATIONS[1] self.assertEqual('aggregate.updatemetadata.end', msg.event_type) + mock_notify.assert_has_calls([ + mock.call(context=self.context, aggregate=agg, + action='update_metadata', phase='start'), + mock.call(context=self.context, aggregate=agg, + action='update_metadata', phase='end')]) self.assertEqual({'todelete': None, 'toadd': 'myval'}, msg.payload['meta_data']) self.assertEqual({'foo': 'bar', 'toadd': 'myval'}, agg.metadata) diff --git a/nova/tests/unit/virt/xenapi/test_xenapi.py b/nova/tests/unit/virt/xenapi/test_xenapi.py index c597ba8b6a1d..9f67a8957cc9 100644 --- a/nova/tests/unit/virt/xenapi/test_xenapi.py +++ b/nova/tests/unit/virt/xenapi/test_xenapi.py @@ -3293,7 +3293,8 @@ class XenAPIAggregateTestCase(stubs.XenAPITestBase): self.conn.remove_from_aggregate, self.context, aggregate, 'fake_host') - def test_add_aggregate_host_raise_err(self): + @mock.patch('nova.compute.utils.notify_about_aggregate_action') + def test_add_aggregate_host_raise_err(self, mock_notify): # Ensure the undo operation works correctly on add. def fake_driver_add_to_aggregate(context, aggregate, host, **_ignore): raise exception.AggregateError(