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 000000000000..e3313c6280b4 --- /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 5364d74713a8..2826c683a590 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 ae97e5fba0bd..e4d6f6971987 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 ce663c6e1b30..c85db2b633f8 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 e2861d53c996..23b4f6520a71 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 dea9b1de8845..e2475f56e719 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 e9bf3162037d..c6c5647f716e 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 0337d57239cb..8b1e5434b0d9 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 000000000000..077586410ef9 --- /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.