Add tags to instance.create Notification

This patch added a new field 'tags' to InstanceCreatePayload.

Partial-implement: bp additional-notification-fields-for-searchlight
Partial-implement: blueprint support-tag-instance-when-boot

Change-Id: Iefaa9da4e136fd5e823bf7b11c8aa5b4cd6d7de8
This commit is contained in:
Kevin_Zheng 2017-04-21 16:43:48 +08:00 committed by Matt Riedemann
parent 0cb765b19b
commit f665565d69
12 changed files with 72 additions and 12 deletions

View File

@ -52,6 +52,7 @@
"state":"active",
"task_state":null,
"power_state":"running",
"tags":["tag"],
"tenant_id":"6f70656e737461636b20342065766572",
"terminated_at":null,
"auto_disk_config":"MANUAL",
@ -82,7 +83,7 @@
},
"nova_object.name":"InstanceCreatePayload",
"nova_object.namespace":"nova",
"nova_object.version":"1.5"
"nova_object.version":"1.6"
},
"priority":"INFO",
"publisher_id":"nova-compute:compute"

View File

@ -49,6 +49,7 @@
"state":"building",
"task_state":null,
"power_state":"pending",
"tags":["tag"],
"tenant_id":"6f70656e737461636b20342065766572",
"terminated_at":null,
"auto_disk_config":"MANUAL",
@ -79,7 +80,7 @@
},
"nova_object.name":"InstanceCreatePayload",
"nova_object.namespace":"nova",
"nova_object.version":"1.5"
"nova_object.version":"1.6"
},
"priority":"ERROR",
"publisher_id":"nova-compute:compute"

View File

@ -39,6 +39,7 @@
"state":"building",
"task_state":null,
"power_state":"pending",
"tags":["tag"],
"tenant_id":"6f70656e737461636b20342065766572",
"terminated_at":null,
"auto_disk_config":"MANUAL",
@ -69,7 +70,7 @@
},
"nova_object.name":"InstanceCreatePayload",
"nova_object.namespace":"nova",
"nova_object.version":"1.5"
"nova_object.version":"1.6"
},
"priority":"INFO",
"publisher_id":"nova-compute:compute"

View File

@ -1011,6 +1011,12 @@ class ComputeTaskManager(base.Base):
cell, instance.flavor, instance.uuid, block_device_mapping)
instance_tags = self._create_tags(cctxt, instance.uuid, tags)
# TODO(Kevin Zheng): clean this up once instance.create() handles
# tags; we do this so the instance.create notification in
# build_and_run_instance in nova-compute doesn't lazy-load tags
instance.tags = instance_tags if instance_tags \
else objects.TagList()
# Update mapping for instance. Normally this check is guarded by
# a try/except but if we're here we know that a newer nova-api
# handled the build process and would have created the mapping

View File

@ -187,10 +187,12 @@ class InstanceCreatePayload(InstanceActionPayload):
# 1.3: Add keypairs field
# 1.4: Add key_name field to InstancePayload
# 1.5: Add BDM related data to InstancePayload
VERSION = '1.5'
# 1.6: Add tags field to InstanceCreatePayload
VERSION = '1.6'
fields = {
'keypairs': fields.ListOfObjectsField('KeypairPayload')
'keypairs': fields.ListOfObjectsField('KeypairPayload'),
'tags': fields.ListOfStringsField(),
}
def __init__(self, instance, fault):
@ -199,6 +201,8 @@ class InstanceCreatePayload(InstanceActionPayload):
fault=fault)
self.keypairs = [keypair_payload.KeypairPayload(keypair=keypair)
for keypair in instance.keypairs]
self.tags = [instance_tag.tag
for instance_tag in instance.tags]
@nova_base.NovaObjectRegistry.register_notification

View File

@ -156,7 +156,8 @@ class TestInstanceNotificationSample(
def test_create_delete_server(self):
server = self._boot_a_server(
extra_params={'networks': [{'port': self.neutron.port_1['id']}]})
extra_params={'networks': [{'port': self.neutron.port_1['id']}],
'tags': ['tag']})
self._attach_volume_to_server(server, self.cinder.SWAP_OLD_VOL)
self.api.delete_server(server['id'])
self._wait_until_deleted(server)
@ -191,7 +192,8 @@ class TestInstanceNotificationSample(
server = self._boot_a_server(
expected_status='ERROR',
extra_params={'networks': [{'port': self.neutron.port_1['id']}]})
extra_params={'networks': [{'port': self.neutron.port_1['id']}],
'tags': ['tag']})
self.assertEqual(2, len(fake_notifier.VERSIONED_NOTIFICATIONS))

View File

@ -5265,7 +5265,7 @@ class ComputeManagerBuildInstanceTestCase(test.NoDBTestCase):
mock.ANY, 'expected_task_state': 'spawning'}
expected_call = mock.call(self.context, self.instance.uuid,
updates, columns_to_join=['metadata', 'system_metadata',
'info_cache'])
'info_cache', 'tags'])
last_update_call = mock_db_update.call_args_list[
mock_db_update.call_count - 1]
self.assertEqual(expected_call, last_update_call)

View File

@ -603,6 +603,47 @@ class UsageInfoTestCase(test.TestCase):
self.assertEqual(uuids.fake_image_ref, payload['image_uuid'])
def test_notify_about_instance_create_with_tags(self):
instance = create_instance(self.context)
# TODO(Kevin Zheng): clean this up to pass tags as params to
# create_instance() once instance.create() handles tags.
instance.tags = objects.TagList(
objects=[objects.Tag(self.context, tag='tag1')])
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']))
self.assertEqual(0, len(payload['keypairs']))
for attr in ('display_name', 'created_at', 'launched_at',
'state', 'task_state', 'display_description', 'locked',
'auto_disk_config', 'tags'):
self.assertIn(attr, payload, "Key %s not in payload" % attr)
self.assertEqual(1, len(payload['tags']))
self.assertEqual('tag1', payload['tags'][0])
self.assertEqual(uuids.fake_image_ref, payload['image_uuid'])
def test_notify_about_volume_swap(self):
instance = create_instance(self.context)

View File

@ -122,6 +122,7 @@ def fake_instance_obj(context, obj_instance_class=None, **updates):
obj_instance_class(), fake_db_instance(**updates),
expected_attrs=expected_attrs)
inst.keypairs = objects.KeyPairList(objects=[])
inst.tags = objects.TagList()
if flavor:
inst.flavor = flavor
# This is needed for instance quota counting until we have the

View File

@ -385,7 +385,7 @@ notification_object_data = {
'1.0-a73147b93b520ff0061865849d3dfa56',
'InstanceActionVolumeSwapPayload': '1.4-8b82cef523c62020c24b3eb1c39ea2ef',
'InstanceCreateNotification': '1.0-a73147b93b520ff0061865849d3dfa56',
'InstanceCreatePayload': '1.5-97e9c0f516a68f20b25ce2f994cab081',
'InstanceCreatePayload': '1.6-b117dd709616d60cf5e126b983c72cd2',
'InstancePayload': '1.4-46d922bd0a5cce46398b0cf7e8735fc4',
'InstanceStateUpdatePayload': '1.0-07e111c0fa0f6db0f79b0726d593e3da',
'InstanceUpdateNotification': '1.0-a73147b93b520ff0061865849d3dfa56',

View File

@ -140,6 +140,9 @@ class _TestBuildRequestObject(object):
# on build_request
fake_req = fake_build_request.fake_db_req()
fields = jsonutils.loads(fake_req['instance'])['nova_object.data']
# TODO(Kevin Zheng): clean up this workaround once
# build_request.get_new_instance() can handle tags.
fields.pop('tags', None)
build_request = objects.BuildRequest._from_db_object(
self.context, objects.BuildRequest(), fake_req)
self.assertEqual(0, len(build_request.instance.obj_what_changed()))

View File

@ -733,11 +733,11 @@ class _TestInstanceObject(object):
mock.call(self.context, inst.uuid,
{'vm_state': 'foo', 'task_state': 'bar',
'cell_name': 'foo!bar@baz'},
columns_to_join=['system_metadata', 'extra',
'extra.flavor']),
columns_to_join=['tags', 'system_metadata',
'extra', 'extra.flavor']),
mock.call(self.context, inst.uuid,
{'vm_state': 'bar', 'task_state': 'foo'},
columns_to_join=['system_metadata'])]
columns_to_join=['system_metadata', 'tags'])]
mock_db_update.assert_has_calls(expected_calls)
def test_skip_cells_api(self):