From 0b9b37fe9ad6ca7c15fdaabcf73afcda01fe6dc6 Mon Sep 17 00:00:00 2001 From: Yikun Jiang Date: Wed, 20 Jun 2018 12:04:55 +0800 Subject: [PATCH] Add instance.unlock notification The instance.unlock versioned notification is introduced in this patch. The unlock operation just changes the instance.locked to False in API, we send the notification after db operation. Change-Id: Ic750c33b4f88ba9c62ea8cba86915c6010f2cd6f blueprint: trigger-notifications-when-lock-unlock-instances --- doc/notification_samples/instance-unlock.json | 8 ++++++++ nova/compute/api.py | 4 ++++ nova/notifications/objects/base.py | 3 ++- nova/notifications/objects/instance.py | 1 + nova/objects/fields.py | 3 ++- .../notification_sample_tests/test_instance.py | 17 +++++++++++++---- nova/tests/unit/compute/test_compute.py | 13 ++++++++----- .../notifications/objects/test_notification.py | 2 +- ...-lock-unlock-instances-5c0bb9262c0b4f0b.yaml | 9 +++++++++ 9 files changed, 48 insertions(+), 12 deletions(-) create mode 100644 doc/notification_samples/instance-unlock.json create mode 100644 releasenotes/notes/trigger-notifications-when-lock-unlock-instances-5c0bb9262c0b4f0b.yaml diff --git a/doc/notification_samples/instance-unlock.json b/doc/notification_samples/instance-unlock.json new file mode 100644 index 0000000000..e3313c6280 --- /dev/null +++ b/doc/notification_samples/instance-unlock.json @@ -0,0 +1,8 @@ +{ + "event_type":"instance.unlock", + "payload":{ + "$ref": "common_payloads/InstanceActionPayload.json#" + }, + "priority":"INFO", + "publisher_id":"nova-api:fake-mini" +} diff --git a/nova/compute/api.py b/nova/compute/api.py index 5364d74713..2826c683a5 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -3847,6 +3847,10 @@ class API(base.Base): instance.save() unlock(self, context, instance) + compute_utils.notify_about_instance_action( + context, instance, CONF.host, + action=fields_obj.NotificationAction.UNLOCK, + source=fields_obj.NotificationSource.API) @check_instance_lock @check_instance_cell diff --git a/nova/notifications/objects/base.py b/nova/notifications/objects/base.py index ae97e5fba0..e4d6f69719 100644 --- a/nova/notifications/objects/base.py +++ b/nova/notifications/objects/base.py @@ -58,7 +58,8 @@ class EventType(NotificationObject): # Version 1.10: UPDATE_METADATA value is added to the # NotificationActionField enum # Version 1.11: LOCK is added to NotificationActionField enum - VERSION = '1.11' + # Version 1.12: UNLOCK is added to NotificationActionField enum + VERSION = '1.12' fields = { 'object': fields.StringField(nullable=False), diff --git a/nova/notifications/objects/instance.py b/nova/notifications/objects/instance.py index ce663c6e1b..c85db2b633 100644 --- a/nova/notifications/objects/instance.py +++ b/nova/notifications/objects/instance.py @@ -541,6 +541,7 @@ class InstanceStateUpdatePayload(base.NotificationPayloadBase): @base.notification_sample('instance-unshelve-start.json') @base.notification_sample('instance-unshelve-end.json') @base.notification_sample('instance-lock.json') +@base.notification_sample('instance-unlock.json') @nova_base.NovaObjectRegistry.register_notification class InstanceActionNotification(base.NotificationBase): # Version 1.0: Initial version diff --git a/nova/objects/fields.py b/nova/objects/fields.py index e2861d53c9..23b4f6520a 100644 --- a/nova/objects/fields.py +++ b/nova/objects/fields.py @@ -822,6 +822,7 @@ class NotificationAction(BaseNovaEnum): ADD_MEMBER = 'add_member' UPDATE_METADATA = 'update_metadata' LOCK = 'lock' + UNLOCK = 'unlock' ALL = (UPDATE, EXCEPTION, DELETE, PAUSE, UNPAUSE, RESIZE, VOLUME_SWAP, SUSPEND, POWER_ON, REBOOT, SHUTDOWN, SNAPSHOT, INTERFACE_ATTACH, @@ -832,7 +833,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, UPDATE_METADATA, LOCK) + REMOVE_HOST, ADD_MEMBER, UPDATE_METADATA, LOCK, UNLOCK) # TODO(rlrossit): These should be changed over to be a StateMachine enum from diff --git a/nova/tests/functional/notification_sample_tests/test_instance.py b/nova/tests/functional/notification_sample_tests/test_instance.py index dea9b1de88..e2475f56e7 100644 --- a/nova/tests/functional/notification_sample_tests/test_instance.py +++ b/nova/tests/functional/notification_sample_tests/test_instance.py @@ -305,7 +305,7 @@ class TestInstanceNotificationSample( self._test_attach_volume_error, self._test_interface_attach_and_detach, self._test_interface_attach_error, - self._test_lock_instance, + self._test_lock_unlock_instance, ] for action in actions: @@ -1663,19 +1663,28 @@ class TestInstanceNotificationSample( 'fault.traceback': self.ANY}, actual=fake_notifier.VERSIONED_NOTIFICATIONS[1]) - def _test_lock_instance(self, server): + def _test_lock_unlock_instance(self, server): self.api.post_server_action(server['id'], {'lock': {}}) self._wait_for_server_parameter(self.api, server, {'locked': True}) - # One versioned notification is generated + self.api.post_server_action(server['id'], {'unlock': {}}) + self._wait_for_server_parameter(self.api, server, {'locked': False}) + # Two versioned notifications are generated # 0. instance-lock + # 1. instance-unlock - self.assertEqual(1, len(fake_notifier.VERSIONED_NOTIFICATIONS)) + self.assertEqual(2, len(fake_notifier.VERSIONED_NOTIFICATIONS)) self._verify_notification( 'instance-lock', replacements={ 'reservation_id': server['reservation_id'], 'uuid': server['id']}, actual=fake_notifier.VERSIONED_NOTIFICATIONS[0]) + self._verify_notification( + 'instance-unlock', + replacements={ + 'reservation_id': server['reservation_id'], + 'uuid': server['id']}, + actual=fake_notifier.VERSIONED_NOTIFICATIONS[1]) class TestInstanceNotificationSampleOldAttachFlow( diff --git a/nova/tests/unit/compute/test_compute.py b/nova/tests/unit/compute/test_compute.py index e9bf316203..c6c5647f71 100644 --- a/nova/tests/unit/compute/test_compute.py +++ b/nova/tests/unit/compute/test_compute.py @@ -11014,23 +11014,26 @@ class ComputeAPITestCase(BaseTestCase): self.context, instance, CONF.host, action='lock', source='nova-api') + @mock.patch('nova.compute.utils.notify_about_instance_action') @mock.patch('nova.context.RequestContext.elevated') @mock.patch('nova.compute.api.API._record_action_start') @mock.patch.object(compute_utils, 'EventReporter') - def test_unlock(self, mock_event, mock_record, mock_elevate): - ctxt = self.context.elevated() - mock_elevate.return_value = ctxt + def test_unlock(self, mock_event, mock_record, mock_elevate, mock_notify): + mock_elevate.return_value = self.context instance = self._create_fake_instance_obj() self.stub_out('nova.network.api.API.deallocate_for_instance', lambda *a, **kw: None) self.compute_api.unlock(self.context, instance) mock_record.assert_called_once_with( - ctxt, instance, instance_actions.UNLOCK + self.context, instance, instance_actions.UNLOCK ) - mock_event.assert_called_once_with(ctxt, + mock_event.assert_called_once_with(self.context, 'api_unlock', CONF.host, instance.uuid) + mock_notify.assert_called_once_with( + self.context, instance, CONF.host, action='unlock', + source='nova-api') def test_add_remove_security_group(self): instance = self._create_fake_instance_obj() diff --git a/nova/tests/unit/notifications/objects/test_notification.py b/nova/tests/unit/notifications/objects/test_notification.py index 0337d57239..8b1e5434b0 100644 --- a/nova/tests/unit/notifications/objects/test_notification.py +++ b/nova/tests/unit/notifications/objects/test_notification.py @@ -369,7 +369,7 @@ notification_object_data = { 'AuditPeriodPayload': '1.0-2b429dd307b8374636703b843fa3f9cb', 'BandwidthPayload': '1.0-ee2616a7690ab78406842a2b68e34130', 'BlockDevicePayload': '1.0-29751e1b6d41b1454e36768a1e764df8', - 'EventType': '1.11-0443197fd02686dacbf1ed7c4345463a', + 'EventType': '1.12-db573dfb0e85f269194dcd3b1628b0d2', 'ExceptionNotification': '1.0-a73147b93b520ff0061865849d3dfa56', 'ExceptionPayload': '1.1-6c43008bd81885a63bc7f7c629f0793b', 'FlavorNotification': '1.0-a73147b93b520ff0061865849d3dfa56', diff --git a/releasenotes/notes/trigger-notifications-when-lock-unlock-instances-5c0bb9262c0b4f0b.yaml b/releasenotes/notes/trigger-notifications-when-lock-unlock-instances-5c0bb9262c0b4f0b.yaml new file mode 100644 index 0000000000..077586410e --- /dev/null +++ b/releasenotes/notes/trigger-notifications-when-lock-unlock-instances-5c0bb9262c0b4f0b.yaml @@ -0,0 +1,9 @@ +--- +features: + - | + The versioned ``instance.lock`` and ``instance.unlock`` notifications have + been added. These notifications are emitted as a result of the respective + server ``lock`` and server ``unlock`` REST API calls. + + See https://docs.openstack.org/nova/latest/reference/notifications.html#existing-versioned-notifications + for notification samples.