From a489dfa7da273a324908f569ec65ca666d858779 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9la=20Vancsics?= Date: Thu, 11 May 2017 09:40:55 +0200 Subject: [PATCH] Transform keypair.delete notification The keypair.delete.start and keypair.delete.end notifications has been transformed to the versioned notification framework. Change-Id: I48f28a56f9232faf52f458588500a9d77eb6b679 Implements: bp versioned-notification-transformation-queens --- .../keypair-delete-end.json | 17 +++++++++++++++++ .../keypair-delete-start.json | 17 +++++++++++++++++ nova/compute/api.py | 11 +++++++++++ nova/notifications/objects/keypair.py | 2 ++ nova/tests/functional/api/client.py | 3 +++ .../notification_sample_tests/test_keypair.py | 19 ++++++++++++++++++- .../api/openstack/compute/test_keypairs.py | 6 +++++- nova/tests/unit/compute/test_keypairs.py | 16 +++++++++++++--- 8 files changed, 86 insertions(+), 5 deletions(-) create mode 100644 doc/notification_samples/keypair-delete-end.json create mode 100644 doc/notification_samples/keypair-delete-start.json diff --git a/doc/notification_samples/keypair-delete-end.json b/doc/notification_samples/keypair-delete-end.json new file mode 100644 index 000000000000..2ae248829135 --- /dev/null +++ b/doc/notification_samples/keypair-delete-end.json @@ -0,0 +1,17 @@ +{ + "priority": "INFO", + "payload": { + "nova_object.version": "1.0", + "nova_object.namespace": "nova", + "nova_object.name": "KeypairPayload", + "nova_object.data": { + "user_id": "fake", + "name": "my-key", + "fingerprint": "1e:2c:9b:56:79:4b:45:77:f9:ca:7a:98:2c:b0:d5:3c", + "public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDx8nkQv/zgGgB4rMYmIf+6A4l6Rr+o/6lHBQdW5aYd44bd8JttDCE/F/pNRr0lRE+PiqSPO8nDPHw0010JeMH9gYgnnFlyY3/OcJ02RhIPyyxYpv9FhY+2YiUkpwFOcLImyrxEsYXpD/0d3ac30bNH6Sw9JD9UZHYcpSxsIbECHw== Generated-by-Nova", + "type": "ssh" + } + }, + "event_type": "keypair.delete.end", + "publisher_id": "nova-api:fake-mini" +} \ No newline at end of file diff --git a/doc/notification_samples/keypair-delete-start.json b/doc/notification_samples/keypair-delete-start.json new file mode 100644 index 000000000000..393ef63646bc --- /dev/null +++ b/doc/notification_samples/keypair-delete-start.json @@ -0,0 +1,17 @@ +{ + "priority": "INFO", + "payload": { + "nova_object.version": "1.0", + "nova_object.namespace": "nova", + "nova_object.name": "KeypairPayload", + "nova_object.data": { + "user_id": "fake", + "name": "my-key", + "fingerprint": "1e:2c:9b:56:79:4b:45:77:f9:ca:7a:98:2c:b0:d5:3c", + "public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDx8nkQv/zgGgB4rMYmIf+6A4l6Rr+o/6lHBQdW5aYd44bd8JttDCE/F/pNRr0lRE+PiqSPO8nDPHw0010JeMH9gYgnnFlyY3/OcJ02RhIPyyxYpv9FhY+2YiUkpwFOcLImyrxEsYXpD/0d3ac30bNH6Sw9JD9UZHYcpSxsIbECHw== Generated-by-Nova", + "type": "ssh" + } + }, + "event_type": "keypair.delete.start", + "publisher_id": "nova-api:fake-mini" +} \ No newline at end of file diff --git a/nova/compute/api.py b/nova/compute/api.py index ec4927e8fda5..77a7598684cb 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -4904,7 +4904,18 @@ class KeypairAPI(base.Base): def delete_key_pair(self, context, user_id, key_name): """Delete a keypair by name.""" self._notify(context, 'delete.start', key_name) + keypair = self.get_key_pair(context, user_id, key_name) + compute_utils.notify_about_keypair_action( + context=context, + keypair=keypair, + action=fields_obj.NotificationAction.DELETE, + phase=fields_obj.NotificationPhase.START) objects.KeyPair.destroy_by_name(context, user_id, key_name) + compute_utils.notify_about_keypair_action( + context=context, + keypair=keypair, + action=fields_obj.NotificationAction.DELETE, + phase=fields_obj.NotificationPhase.END) self._notify(context, 'delete.end', key_name) def get_key_pairs(self, context, user_id, limit=None, marker=None): diff --git a/nova/notifications/objects/keypair.py b/nova/notifications/objects/keypair.py index 44df1a0732b2..cb419530219f 100644 --- a/nova/notifications/objects/keypair.py +++ b/nova/notifications/objects/keypair.py @@ -41,6 +41,8 @@ class KeypairPayload(base.NotificationPayloadBase): @base.notification_sample('keypair-create-start.json') @base.notification_sample('keypair-create-end.json') +@base.notification_sample('keypair-delete-start.json') +@base.notification_sample('keypair-delete-end.json') @nova_base.NovaObjectRegistry.register_notification class KeypairNotification(base.NotificationBase): # Version 1.0: Initial version diff --git a/nova/tests/functional/api/client.py b/nova/tests/functional/api/client.py index 82bc563119c2..59f813c1c11b 100644 --- a/nova/tests/functional/api/client.py +++ b/nova/tests/functional/api/client.py @@ -430,6 +430,9 @@ class TestOpenStackClient(object): def post_keypair(self, keypair): return self.api_post('/os-keypairs', keypair).body['keypair'] + def delete_keypair(self, keypair_name): + self.api_delete('/os-keypairs/%s' % keypair_name) + def get_active_migrations(self, server_id): return self.api_get('/servers/%s/migrations' % server_id).body['migrations'] diff --git a/nova/tests/functional/notification_sample_tests/test_keypair.py b/nova/tests/functional/notification_sample_tests/test_keypair.py index 195e4b79a325..a0421be3cf47 100644 --- a/nova/tests/functional/notification_sample_tests/test_keypair.py +++ b/nova/tests/functional/notification_sample_tests/test_keypair.py @@ -17,7 +17,7 @@ from nova.tests.unit import fake_notifier class TestKeypairNotificationSample( notification_sample_base.NotificationSampleTestBase): - def test_keypair_create(self): + def test_keypair_create_delete(self): keypair_req = { "keypair": { "name": "my-key", @@ -38,3 +38,20 @@ class TestKeypairNotificationSample( "public_key": keypair['public_key'] }, actual=fake_notifier.VERSIONED_NOTIFICATIONS[1]) + + self.api.delete_keypair(keypair['name']) + self.assertEqual(4, len(fake_notifier.VERSIONED_NOTIFICATIONS)) + self._verify_notification( + 'keypair-delete-start', + replacements={ + "fingerprint": keypair['fingerprint'], + "public_key": keypair['public_key'] + }, + actual=fake_notifier.VERSIONED_NOTIFICATIONS[2]) + self._verify_notification( + 'keypair-delete-end', + replacements={ + "fingerprint": keypair['fingerprint'], + "public_key": keypair['public_key'] + }, + actual=fake_notifier.VERSIONED_NOTIFICATIONS[3]) diff --git a/nova/tests/unit/api/openstack/compute/test_keypairs.py b/nova/tests/unit/api/openstack/compute/test_keypairs.py index 63b5343d467f..c16856b9d4c1 100644 --- a/nova/tests/unit/api/openstack/compute/test_keypairs.py +++ b/nova/tests/unit/api/openstack/compute/test_keypairs.py @@ -21,6 +21,7 @@ import webob from nova.api.openstack.compute import keypairs as keypairs_v21 from nova.api.openstack import wsgi as os_wsgi from nova.compute import api as compute_api +from nova import context as nova_context from nova import exception from nova import objects from nova import policy @@ -271,7 +272,10 @@ class KeypairsTestV21(test.TestCase): self.assertIn("Key pair 'create_duplicate' already exists.", ex.explanation) - def test_keypair_delete(self): + @mock.patch('nova.objects.KeyPair.get_by_name') + def test_keypair_delete(self, mock_get_by_name): + mock_get_by_name.return_value = objects.KeyPair( + nova_context.get_admin_context(), **fake_keypair('FAKE')) self.controller.delete(self.req, 'FAKE') def test_keypair_get_keypair_not_found(self): diff --git a/nova/tests/unit/compute/test_keypairs.py b/nova/tests/unit/compute/test_keypairs.py index e2376d827aa1..4f22be32f4c1 100644 --- a/nova/tests/unit/compute/test_keypairs.py +++ b/nova/tests/unit/compute/test_keypairs.py @@ -28,6 +28,7 @@ from nova.tests.unit.compute import test_compute from nova.tests.unit import fake_crypto from nova.tests.unit import fake_notifier from nova.tests.unit.objects import test_keypair +from nova.tests.unit import utils as test_utils CONF = cfg.CONF @@ -243,14 +244,23 @@ class GetKeypairsTestCase(KeypairAPITestCase): class DeleteKeypairTestCase(KeypairAPITestCase): - def test_success(self): - self.keypair_api.get_key_pair(self.ctxt, self.ctxt.user_id, - self.existing_key_name) + @mock.patch('nova.compute.utils.notify_about_keypair_action') + def test_success(self, mock_notify): self.keypair_api.delete_key_pair(self.ctxt, self.ctxt.user_id, self.existing_key_name) self.assertRaises(exception.KeypairNotFound, self.keypair_api.get_key_pair, self.ctxt, self.ctxt.user_id, self.existing_key_name) + match_by_name = test_utils.CustomMockCallMatcher( + lambda keypair: keypair['name'] == self.existing_key_name) + + mock_notify.assert_has_calls([ + mock.call(context=self.ctxt, + keypair=match_by_name, + action='delete', phase='start'), + mock.call(context=self.ctxt, + keypair=match_by_name, + action='delete', phase='end')]) self._check_notifications(action='delete', key_name=self.existing_key_name)