diff --git a/doc/notification_samples/instance-lock.json b/doc/notification_samples/instance-lock.json new file mode 100644 index 000000000000..d542d9473600 --- /dev/null +++ b/doc/notification_samples/instance-lock.json @@ -0,0 +1,11 @@ +{ + "event_type":"instance.lock", + "payload":{ + "$ref": "common_payloads/InstanceActionPayload.json#", + "nova_object.data":{ + "locked":true + } + }, + "priority":"INFO", + "publisher_id":"nova-api:fake-mini" +} diff --git a/nova/compute/api.py b/nova/compute/api.py index 75dd17bed945..5364d74713a8 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -3820,6 +3820,10 @@ class API(base.Base): instance.save() lock(self, context, instance) + compute_utils.notify_about_instance_action( + context, instance, CONF.host, + action=fields_obj.NotificationAction.LOCK, + source=fields_obj.NotificationSource.API) def is_expected_locked_by(self, context, instance): is_owner = instance.project_id == context.project_id diff --git a/nova/notifications/objects/base.py b/nova/notifications/objects/base.py index 16b4d51333f8..ae97e5fba0bd 100644 --- a/nova/notifications/objects/base.py +++ b/nova/notifications/objects/base.py @@ -57,7 +57,8 @@ class EventType(NotificationObject): # Version 1.9: ADD_MEMBER value is added to NotificationActionField enum # Version 1.10: UPDATE_METADATA value is added to the # NotificationActionField enum - VERSION = '1.10' + # Version 1.11: LOCK is added to NotificationActionField enum + VERSION = '1.11' fields = { 'object': fields.StringField(nullable=False), diff --git a/nova/notifications/objects/instance.py b/nova/notifications/objects/instance.py index 3daf864b6849..ce663c6e1b30 100644 --- a/nova/notifications/objects/instance.py +++ b/nova/notifications/objects/instance.py @@ -540,6 +540,7 @@ class InstanceStateUpdatePayload(base.NotificationPayloadBase): @base.notification_sample('instance-unrescue-end.json') @base.notification_sample('instance-unshelve-start.json') @base.notification_sample('instance-unshelve-end.json') +@base.notification_sample('instance-lock.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 ab9e8ec69037..e2861d53c996 100644 --- a/nova/objects/fields.py +++ b/nova/objects/fields.py @@ -821,6 +821,7 @@ class NotificationAction(BaseNovaEnum): REMOVE_HOST = 'remove_host' ADD_MEMBER = 'add_member' UPDATE_METADATA = 'update_metadata' + LOCK = 'lock' ALL = (UPDATE, EXCEPTION, DELETE, PAUSE, UNPAUSE, RESIZE, VOLUME_SWAP, SUSPEND, POWER_ON, REBOOT, SHUTDOWN, SNAPSHOT, INTERFACE_ATTACH, @@ -831,7 +832,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) + REMOVE_HOST, ADD_MEMBER, UPDATE_METADATA, LOCK) # 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 c489abb316c3..dea9b1de8845 100644 --- a/nova/tests/functional/notification_sample_tests/test_instance.py +++ b/nova/tests/functional/notification_sample_tests/test_instance.py @@ -305,6 +305,7 @@ class TestInstanceNotificationSample( self._test_attach_volume_error, self._test_interface_attach_and_detach, self._test_interface_attach_error, + self._test_lock_instance, ] for action in actions: @@ -1662,6 +1663,20 @@ class TestInstanceNotificationSample( 'fault.traceback': self.ANY}, actual=fake_notifier.VERSIONED_NOTIFICATIONS[1]) + def _test_lock_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 + # 0. instance-lock + + self.assertEqual(1, 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]) + class TestInstanceNotificationSampleOldAttachFlow( TestInstanceNotificationSample): diff --git a/nova/tests/unit/compute/test_compute.py b/nova/tests/unit/compute/test_compute.py index 17f929ea11e1..e9bf3162037d 100644 --- a/nova/tests/unit/compute/test_compute.py +++ b/nova/tests/unit/compute/test_compute.py @@ -10993,23 +10993,26 @@ class ComputeAPITestCase(BaseTestCase): instance = self.compute_api.get(self.context, instance['uuid']) self.compute_api.reset_network(self.context, instance) + @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_lock(self, mock_event, mock_record, mock_elevate): - ctxt = self.context.elevated() - mock_elevate.return_value = ctxt + def test_lock(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.lock(self.context, instance) mock_record.assert_called_once_with( - ctxt, instance, instance_actions.LOCK + self.context, instance, instance_actions.LOCK ) - mock_event.assert_called_once_with(ctxt, + mock_event.assert_called_once_with(self.context, 'api_lock', CONF.host, instance.uuid) + mock_notify.assert_called_once_with( + self.context, instance, CONF.host, action='lock', + source='nova-api') @mock.patch('nova.context.RequestContext.elevated') @mock.patch('nova.compute.api.API._record_action_start') diff --git a/nova/tests/unit/notifications/objects/test_notification.py b/nova/tests/unit/notifications/objects/test_notification.py index b97633d974ab..0337d57239cb 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.10-2a6ab743d767837366ab1aec387d7c3b', + 'EventType': '1.11-0443197fd02686dacbf1ed7c4345463a', 'ExceptionNotification': '1.0-a73147b93b520ff0061865849d3dfa56', 'ExceptionPayload': '1.1-6c43008bd81885a63bc7f7c629f0793b', 'FlavorNotification': '1.0-a73147b93b520ff0061865849d3dfa56',