diff --git a/doc/notification_samples/instance-create-end.json b/doc/notification_samples/instance-create-end.json index 963085f0d9..422d3ed607 100644 --- a/doc/notification_samples/instance-create-end.json +++ b/doc/notification_samples/instance-create-end.json @@ -25,6 +25,18 @@ "device_name": "tapce531f90-19" } }], + "keypairs": [{ + "nova_object.name": "KeypairPayload", + "nova_object.namespace": "nova", + "nova_object.version": "1.0", + "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" + } + }], "kernel_id":"", "launched_at":"2012-10-29T13:42:11Z", "image_uuid": "155d900f-4e14-4e4c-a73d-069cbf4541e6", @@ -68,7 +80,7 @@ }, "nova_object.name":"InstanceCreatePayload", "nova_object.namespace":"nova", - "nova_object.version":"1.2" + "nova_object.version":"1.3" }, "priority":"INFO", "publisher_id":"nova-compute:compute" diff --git a/doc/notification_samples/instance-create-error.json b/doc/notification_samples/instance-create-error.json index 3df344d93a..099c926ceb 100644 --- a/doc/notification_samples/instance-create-error.json +++ b/doc/notification_samples/instance-create-error.json @@ -22,6 +22,18 @@ "host":"compute", "host_name":"some-server", "ip_addresses": [], + "keypairs": [{ + "nova_object.name": "KeypairPayload", + "nova_object.namespace": "nova", + "nova_object.version": "1.0", + "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" + } + }], "kernel_id":"", "launched_at":null, "image_uuid": "155d900f-4e14-4e4c-a73d-069cbf4541e6", @@ -65,7 +77,7 @@ }, "nova_object.name":"InstanceCreatePayload", "nova_object.namespace":"nova", - "nova_object.version":"1.2" + "nova_object.version":"1.3" }, "priority":"ERROR", "publisher_id":"nova-compute:compute" diff --git a/doc/notification_samples/instance-create-start.json b/doc/notification_samples/instance-create-start.json index 58c66cafd4..1ca808bfb3 100644 --- a/doc/notification_samples/instance-create-start.json +++ b/doc/notification_samples/instance-create-start.json @@ -12,6 +12,18 @@ "host":null, "host_name":"some-server", "ip_addresses": [], + "keypairs": [{ + "nova_object.name": "KeypairPayload", + "nova_object.namespace": "nova", + "nova_object.version": "1.0", + "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" + } + }], "kernel_id":"", "launched_at":null, "image_uuid": "155d900f-4e14-4e4c-a73d-069cbf4541e6", @@ -55,7 +67,7 @@ }, "nova_object.name":"InstanceCreatePayload", "nova_object.namespace":"nova", - "nova_object.version":"1.2" + "nova_object.version":"1.3" }, "priority":"INFO", "publisher_id":"nova-compute:compute" diff --git a/nova/notifications/objects/instance.py b/nova/notifications/objects/instance.py index 7b9b3f4880..11540bf165 100644 --- a/nova/notifications/objects/instance.py +++ b/nova/notifications/objects/instance.py @@ -12,6 +12,7 @@ from nova.notifications.objects import base from nova.notifications.objects import flavor as flavor_payload +from nova.notifications.objects import keypair as keypair_payload from nova.objects import base as nova_base from nova.objects import fields @@ -162,12 +163,19 @@ class InstanceCreatePayload(InstanceActionPayload): # payload is created as a child of it so that the # instance.create notification using this new payload does not # have decreasing version. - VERSION = '1.2' + # 1.3: Add keypairs field + VERSION = '1.3' + + fields = { + 'keypairs': fields.ListOfObjectsField('KeypairPayload') + } def __init__(self, instance, fault): super(InstanceCreatePayload, self).__init__( - instance=instance, - fault=fault) + instance=instance, + fault=fault) + self.keypairs = [keypair_payload.KeypairPayload(keypair=keypair) + for keypair in instance.keypairs] @nova_base.NovaObjectRegistry.register_notification diff --git a/nova/tests/functional/notification_sample_tests/notification_sample_base.py b/nova/tests/functional/notification_sample_tests/notification_sample_base.py index 5045d394dd..d31c2dae11 100644 --- a/nova/tests/functional/notification_sample_tests/notification_sample_base.py +++ b/nova/tests/functional/notification_sample_tests/notification_sample_base.py @@ -24,6 +24,7 @@ from nova.tests import fixtures as nova_fixtures from nova.tests.functional.api import client as api_client from nova.tests.functional import integrated_helpers from nova.tests.unit.api.openstack.compute import test_services +from nova.tests.unit import fake_crypto from nova.tests.unit import fake_notifier import nova.tests.unit.image.fake @@ -160,6 +161,13 @@ class NotificationSampleTestBase(test.TestCase, # Ignore the create flavor notification fake_notifier.reset() + keypair_req = { + "keypair": { + "name": "my-key", + "public_key": fake_crypto.get_ssh_public_key() + }} + self.api.post_keypair(keypair_req) + server = self._build_minimal_create_server_request( self.api, 'some-server', image_uuid='155d900f-4e14-4e4c-a73d-069cbf4541e6', @@ -171,6 +179,7 @@ class NotificationSampleTestBase(test.TestCase, if extra_params: extra_params['return_reservation_id'] = True + extra_params['key_name'] = 'my-key' server.update(extra_params) post = {'server': server} diff --git a/nova/tests/unit/compute/test_compute.py b/nova/tests/unit/compute/test_compute.py index b4b77e1ef1..58a5ebd236 100644 --- a/nova/tests/unit/compute/test_compute.py +++ b/nova/tests/unit/compute/test_compute.py @@ -302,6 +302,7 @@ class BaseTestCase(test.TestCase): inst.updated_at = timeutils.utcnow() inst.launched_at = timeutils.utcnow() inst.security_groups = objects.SecurityGroupList(objects=[]) + inst.keypairs = objects.KeyPairList(objects=[]) inst.flavor = flavor inst.old_flavor = None inst.new_flavor = None diff --git a/nova/tests/unit/compute/test_compute_utils.py b/nova/tests/unit/compute/test_compute_utils.py index d9447727ca..1c9887e513 100644 --- a/nova/tests/unit/compute/test_compute_utils.py +++ b/nova/tests/unit/compute/test_compute_utils.py @@ -40,6 +40,7 @@ from nova.objects import fields from nova import rpc from nova import test from nova.tests.unit import fake_block_device +from nova.tests.unit import fake_crypto from nova.tests.unit import fake_instance from nova.tests.unit import fake_network from nova.tests.unit import fake_notifier @@ -385,6 +386,9 @@ class DefaultDeviceNamesForInstanceTestCase(test.NoDBTestCase): class UsageInfoTestCase(test.TestCase): def setUp(self): + self.public_key = fake_crypto.get_ssh_public_key() + self.fingerprint = '1e:2c:9b:56:79:4b:45:77:f9:ca:7a:98:2c:b0:d5:3c' + def fake_get_nw_info(cls, ctxt, instance): self.assertTrue(ctxt.is_admin) return fake_network.fake_get_instance_nw_info(self, 1, 1) @@ -519,6 +523,53 @@ class UsageInfoTestCase(test.TestCase): self.assertEqual(payload['image_uuid'], uuids.fake_image_ref) def test_notify_about_instance_create(self): + keypair = objects.KeyPair(name='my-key', user_id='fake', type='ssh', + public_key=self.public_key, + fingerprint=self.fingerprint) + keypairs = objects.KeyPairList(objects=[keypair]) + instance = create_instance(self.context, params={'keypairs': keypairs}) + + compute_utils.notify_about_instance_create( + self.context, + instance, + host='fake-compute', + phase='start') + + self.assertEqual(1, len(fake_notifier.VERSIONED_NOTIFICATIONS)) + notification = fake_notifier.VERSIONED_NOTIFICATIONS[0] + + self.assertEqual('INFO', notification['priority']) + self.assertEqual('instance.create.start', notification['event_type']) + self.assertEqual('nova-compute:fake-compute', + notification['publisher_id']) + + payload = notification['payload']['nova_object.data'] + self.assertEqual('fake', payload['tenant_id']) + self.assertEqual('fake', payload['user_id']) + self.assertEqual(instance['uuid'], payload['uuid']) + + flavorid = flavors.get_flavor_by_name('m1.tiny')['flavorid'] + flavor = payload['flavor']['nova_object.data'] + self.assertEqual(flavorid, str(flavor['flavorid'])) + + keypairs_payload = payload['keypairs'] + self.assertEqual(1, len(keypairs_payload)) + keypair_data = keypairs_payload[0]['nova_object.data'] + self.assertEqual(keypair_data, + {'name': 'my-key', + 'user_id': 'fake', + 'type': 'ssh', + 'public_key': self.public_key, + 'fingerprint': self.fingerprint}) + + for attr in ('display_name', 'created_at', 'launched_at', + 'state', 'task_state', 'display_description', 'locked', + 'auto_disk_config'): + self.assertIn(attr, payload, "Key %s not in payload" % attr) + + self.assertEqual(uuids.fake_image_ref, payload['image_uuid']) + + def test_notify_about_instance_create_without_keypair(self): instance = create_instance(self.context) compute_utils.notify_about_instance_create( @@ -544,6 +595,7 @@ class UsageInfoTestCase(test.TestCase): flavor = payload['flavor']['nova_object.data'] self.assertEqual(flavorid, str(flavor['flavorid'])) + self.assertEqual(0, len(payload['keypairs'])) for attr in ('display_name', 'created_at', 'launched_at', 'state', 'task_state', 'display_description', 'locked', 'auto_disk_config'): diff --git a/nova/tests/unit/notifications/objects/test_notification.py b/nova/tests/unit/notifications/objects/test_notification.py index 70b18607a4..5f5ac6f180 100644 --- a/nova/tests/unit/notifications/objects/test_notification.py +++ b/nova/tests/unit/notifications/objects/test_notification.py @@ -382,7 +382,7 @@ notification_object_data = { '1.0-a73147b93b520ff0061865849d3dfa56', 'InstanceActionVolumeSwapPayload': '1.2-d7925b763e0795f8e5c1aa0e95bd67bd', 'InstanceCreateNotification': '1.0-a73147b93b520ff0061865849d3dfa56', - 'InstanceCreatePayload': '1.2-b7b2481bcd0e1edcc1970ef7150df5aa', + 'InstanceCreatePayload': '1.3-f365937eb5a0547055a679d1a99b7aeb', 'InstancePayload': '1.2-a1988f6fe728bd4b478353a85c48ad55', 'InstanceStateUpdatePayload': '1.0-07e111c0fa0f6db0f79b0726d593e3da', 'InstanceUpdateNotification': '1.0-a73147b93b520ff0061865849d3dfa56',