Merge "Add notification support for trusted_certs"

This commit is contained in:
Zuul 2018-06-14 22:03:44 +00:00 committed by Gerrit Code Review
commit 2d6a838a28
13 changed files with 222 additions and 40 deletions

View File

@ -0,0 +1,11 @@
{
"$ref": "InstanceActionPayload.json",
"nova_object.data": {
"trusted_image_certificates": [
"rebuild-cert-id-1",
"rebuild-cert-id-2"
]
},
"nova_object.name": "InstanceActionRebuildPayload",
"nova_object.version": "1.7"
}

View File

@ -16,8 +16,12 @@
}
}
],
"tags": ["tag"]
"tags": ["tag"],
"trusted_image_certificates": [
"cert-id-1",
"cert-id-2"
]
},
"nova_object.name":"InstanceCreatePayload",
"nova_object.version": "1.8"
"nova_object.version": "1.9"
}

View File

@ -2,7 +2,7 @@
"event_type": "instance.rebuild.end",
"publisher_id": "nova-compute:compute",
"payload": {
"$ref":"common_payloads/InstanceActionPayload.json#",
"$ref":"common_payloads/InstanceActionRebuildPayload.json#",
"nova_object.data": {
"architecture": null,
"image_uuid": "a2459075-d96c-40d5-893e-577ff92e721c"

View File

@ -1,7 +1,7 @@
{
"priority": "ERROR",
"payload": {
"$ref": "common_payloads/InstanceActionPayload.json#",
"$ref": "common_payloads/InstanceActionRebuildPayload.json#",
"nova_object.data": {
"fault": {
"nova_object.name": "ExceptionPayload",

View File

@ -3,7 +3,7 @@
"event_type": "instance.rebuild.start",
"publisher_id": "nova-compute:compute",
"payload": {
"$ref":"common_payloads/InstanceActionPayload.json#",
"$ref":"common_payloads/InstanceActionRebuildPayload.json#",
"nova_object.data": {
"architecture": null,
"image_uuid": "a2459075-d96c-40d5-893e-577ff92e721c",

View File

@ -2777,9 +2777,8 @@ class ComputeManager(manager.Manager):
def _notify_instance_rebuild_error(self, context, instance, error, bdms):
self._notify_about_instance_usage(context, instance,
'rebuild.error', fault=error)
compute_utils.notify_about_instance_action(
compute_utils.notify_about_instance_rebuild(
context, instance, self.host,
action=fields.NotificationAction.REBUILD,
phase=fields.NotificationPhase.ERROR, exception=error, bdms=bdms)
@messaging.expected_exceptions(exception.PreserveEphemeralNotSupported)
@ -3024,9 +3023,8 @@ class ComputeManager(manager.Manager):
# NOTE: image_name is not included in the versioned notification
# because we already provide the image_uuid in the notification
# payload and the image details can be looked up via the uuid.
compute_utils.notify_about_instance_action(
compute_utils.notify_about_instance_rebuild(
context, instance, self.host,
action=fields.NotificationAction.REBUILD,
phase=fields.NotificationPhase.START,
bdms=bdms)
@ -3121,9 +3119,8 @@ class ComputeManager(manager.Manager):
context, instance, "rebuild.end",
network_info=network_info,
extra_usage_info=extra_usage_info)
compute_utils.notify_about_instance_action(
compute_utils.notify_about_instance_rebuild(
context, instance, self.host,
action=fields.NotificationAction.REBUILD,
phase=fields.NotificationPhase.END,
bdms=bdms)

View File

@ -715,6 +715,37 @@ def notify_about_server_group_add_member(context, group_id):
notification.emit(context)
@rpc.if_notifications_enabled
def notify_about_instance_rebuild(context, instance, host, phase=None,
exception=None, bdms=None):
"""Send versioned notification about instance rebuild
:param instance: the instance which the action performed on
:param host: the host emitting the notification
:param phase: the phase of the action
:param exception: the thrown exception (used in error notifications)
:param bdms: BlockDeviceMappingList object for the instance. If it is not
provided then we will load it from the db if so configured
"""
fault, priority = _get_fault_and_priority_from_exc(exception)
payload = instance_notification.InstanceActionRebuildPayload(
context=context,
instance=instance,
fault=fault,
bdms=bdms)
notification = instance_notification.InstanceActionRebuildNotification(
context=context,
priority=priority,
publisher=notification_base.NotificationPublisher(
host=host, source=fields.NotificationSource.COMPUTE),
event_type=notification_base.EventType(
object='instance',
action=fields.NotificationAction.REBUILD,
phase=phase),
payload=payload)
notification.emit(context)
def refresh_info_cache_for_instance(context, instance):
"""Refresh the info cache for an instance.

View File

@ -214,11 +214,15 @@ class InstanceCreatePayload(InstanceActionPayload):
# 1.6: Add tags field to InstanceCreatePayload
# 1.7: Added updated_at field to InstancePayload
# 1.8: Added request_id field to InstancePayload
VERSION = '1.8'
# 1.9: Add trusted_image_certificates field to
# InstanceCreatePayload
VERSION = '1.9'
fields = {
'keypairs': fields.ListOfObjectsField('KeypairPayload'),
'tags': fields.ListOfStringsField(),
'trusted_image_certificates': fields.ListOfStringsField(
nullable=True)
}
def __init__(self, context, instance, fault, bdms):
@ -231,6 +235,9 @@ class InstanceCreatePayload(InstanceActionPayload):
for keypair in instance.keypairs]
self.tags = [instance_tag.tag
for instance_tag in instance.tags]
self.trusted_image_certificates = None
if instance.get("trusted_certs", None):
self.trusted_image_certificates = instance.trusted_certs.ids
@nova_base.NovaObjectRegistry.register_notification
@ -300,6 +307,32 @@ class InstanceActionRescuePayload(InstanceActionPayload):
self.rescue_image_ref = rescue_image_ref
@nova_base.NovaObjectRegistry.register_notification
class InstanceActionRebuildPayload(InstanceActionPayload):
# No SCHEMA as all the additional fields are calculated
# Version 1.7: Initial version. It starts at 1.7 to equal one more than
# the version of the InstanceActionPayload at the time
# when this specific payload is created so that the
# instance.rebuild.* notifications using this new payload
# signal the change of nova_object.name.
VERSION = '1.7'
fields = {
'trusted_image_certificates': fields.ListOfStringsField(
nullable=True)
}
def __init__(self, context, instance, fault, bdms):
super(InstanceActionRebuildPayload, self).__init__(
context=context,
instance=instance,
fault=fault,
bdms=bdms)
self.trusted_image_certificates = None
if instance.get("trusted_certs", None):
self.trusted_image_certificates = instance.trusted_certs.ids
@nova_base.NovaObjectRegistry.register_notification
class IpPayload(base.NotificationPayloadBase):
# Version 1.0: Initial version
@ -491,9 +524,6 @@ class InstanceStateUpdatePayload(base.NotificationPayloadBase):
@base.notification_sample('instance-live_migration_rollback-end.json')
# @base.notification_sample('instance-live_migration_rollback_dest-start.json')
# @base.notification_sample('instance-live_migration_rollback_dest-end.json')
@base.notification_sample('instance-rebuild-start.json')
@base.notification_sample('instance-rebuild-end.json')
@base.notification_sample('instance-rebuild-error.json')
@base.notification_sample('instance-interface_detach-start.json')
@base.notification_sample('instance-interface_detach-end.json')
@base.notification_sample('instance-resize_confirm-start.json')
@ -608,6 +638,19 @@ class InstanceActionRescueNotification(base.NotificationBase):
}
@base.notification_sample('instance-rebuild-start.json')
@base.notification_sample('instance-rebuild-end.json')
@base.notification_sample('instance-rebuild-error.json')
@nova_base.NovaObjectRegistry.register_notification
class InstanceActionRebuildNotification(base.NotificationBase):
# Version 1.0: Initial version
VERSION = '1.0'
fields = {
'payload': fields.ObjectField('InstanceActionRebuildPayload')
}
@nova_base.NovaObjectRegistry.register_notification
class InstanceActionSnapshotPayload(InstanceActionPayload):
# Version 1.6: Initial version. It starts at version 1.6 as

View File

@ -314,9 +314,11 @@ class TestInstanceNotificationSample(
self._wait_for_state_change(self.admin_api, server, 'ACTIVE')
def test_create_delete_server(self):
fake_trusted_certs = ['cert-id-1', 'cert-id-2']
server = self._boot_a_server(
extra_params={'networks': [{'port': self.neutron.port_1['id']}],
'tags': ['tag']})
'tags': ['tag'],
'trusted_image_certificates': fake_trusted_certs})
self._attach_volume_to_server(server, self.cinder.SWAP_OLD_VOL)
self.api.delete_server(server['id'])
self._wait_until_deleted(server)
@ -356,10 +358,12 @@ class TestInstanceNotificationSample(
mock_build.side_effect = _build_resources
fake_trusted_certs = ['cert-id-1', 'cert-id-2']
server = self._boot_a_server(
expected_status='ERROR',
extra_params={'networks': [{'port': self.neutron.port_1['id']}],
'tags': ['tag']})
'tags': ['tag'],
'trusted_image_certificates': fake_trusted_certs})
self.assertEqual(2, len(fake_notifier.VERSIONED_NOTIFICATIONS))
@ -1009,7 +1013,72 @@ class TestInstanceNotificationSample(
post = {
'rebuild': {
'imageRef': 'a2459075-d96c-40d5-893e-577ff92e721c',
'metadata': {}
'metadata': {},
}
}
self.api.post_server_action(server['id'], post)
# Before going back to ACTIVE state
# server state need to be changed to REBUILD state
self._wait_for_state_change(self.api, server,
expected_status='REBUILD')
self._wait_for_state_change(self.api, server,
expected_status='ACTIVE')
# The compute/manager will detach every volume during rebuild
self.assertEqual(5, len(fake_notifier.VERSIONED_NOTIFICATIONS))
self._verify_notification(
'instance-rebuild-start',
replacements={
'reservation_id': server['reservation_id'],
'uuid': server['id'],
'trusted_image_certificates': None},
actual=fake_notifier.VERSIONED_NOTIFICATIONS[1])
self._verify_notification(
'instance-volume_detach-start',
replacements={
'reservation_id': server['reservation_id'],
'task_state': 'rebuilding',
'architecture': None,
'image_uuid': 'a2459075-d96c-40d5-893e-577ff92e721c',
'uuid': server['id']},
actual=fake_notifier.VERSIONED_NOTIFICATIONS[2])
self._verify_notification(
'instance-volume_detach-end',
replacements={
'reservation_id': server['reservation_id'],
'task_state': 'rebuilding',
'architecture': None,
'image_uuid': 'a2459075-d96c-40d5-893e-577ff92e721c',
'uuid': server['id']},
actual=fake_notifier.VERSIONED_NOTIFICATIONS[3])
self._verify_notification(
'instance-rebuild-end',
replacements={
'reservation_id': server['reservation_id'],
'uuid': server['id'],
'trusted_image_certificates': None},
actual=fake_notifier.VERSIONED_NOTIFICATIONS[4])
def test_rebuild_server_with_trusted_cert(self):
# NOTE(gabor_antal): Rebuild changes the image used by the instance,
# therefore the actions tested in test_instance_action had to be in
# specific order. To avoid this problem, rebuild was moved from
# test_instance_action to its own method.
create_trusted_certs = ['cert-id-1', 'cert-id-2']
server = self._boot_a_server(
extra_params={'networks': [{'port': self.neutron.port_1['id']}],
'trusted_image_certificates': create_trusted_certs})
self._attach_volume_to_server(server, self.cinder.SWAP_OLD_VOL)
fake_notifier.reset()
rebuild_trusted_certs = ['rebuild-cert-id-1', 'rebuild-cert-id-2']
post = {
'rebuild': {
'imageRef': 'a2459075-d96c-40d5-893e-577ff92e721c',
'metadata': {},
'trusted_image_certificates': rebuild_trusted_certs,
}
}
self.api.post_server_action(server['id'], post)
@ -1081,7 +1150,8 @@ class TestInstanceNotificationSample(
'instance-rebuild-error',
replacements={
'reservation_id': server['reservation_id'],
'uuid': server['id']},
'uuid': server['id'],
'trusted_image_certificates': None},
actual=notification[0])
def _test_restore_server(self, server):
@ -1573,3 +1643,8 @@ class TestInstanceNotificationSampleOldAttachFlow(
@mock.patch('nova.volume.cinder.API.attach')
def _test_attach_volume_error(self, server, mock_attach):
self._do_test_attach_volume_error(server, mock_attach)
def test_rebuild_server_with_trusted_cert(self):
# Skipping this test as trusted cert support needs a later service
# version than this test class is limited to.
pass

View File

@ -12634,12 +12634,13 @@ class EvacuateHostTestCase(BaseTestCase):
limits = {}
@mock.patch('nova.compute.utils.notify_about_instance_action')
@mock.patch('nova.compute.utils.notify_about_instance_rebuild')
@mock.patch.object(network_api, 'setup_networks_on_host')
@mock.patch.object(network_api, 'setup_instance_network_on_host')
@mock.patch('nova.context.RequestContext.elevated', return_value=ctxt)
def _test_rebuild(mock_context, mock_setup_instance_network_on_host,
mock_setup_networks_on_host, mock_notify,
vm_is_stopped=False):
mock_setup_networks_on_host, mock_notify_rebuild,
mock_notify_action, vm_is_stopped=False):
orig_image_ref = None
image_ref = None
injected_files = None
@ -12652,21 +12653,22 @@ class EvacuateHostTestCase(BaseTestCase):
preserve_ephemeral=False, scheduled_node=node, limits=limits,
request_spec=None)
if vm_states_is_stopped:
mock_notify.assert_has_calls([
mock.call(ctxt, self.inst, self.inst.host,
action='rebuild', phase='start', bdms=bdms),
mock_notify_rebuild.assert_has_calls([
mock.call(ctxt, self.inst, self.inst.host, phase='start',
bdms=bdms),
mock.call(ctxt, self.inst, self.inst.host, phase='end',
bdms=bdms)])
mock_notify_action.assert_has_calls([
mock.call(ctxt, self.inst, self.inst.host,
action='power_off', phase='start'),
mock.call(ctxt, self.inst, self.inst.host,
action='power_off', phase='end'),
mock.call(ctxt, self.inst, self.inst.host,
action='rebuild', phase='end', bdms=bdms)])
action='power_off', phase='end')])
else:
mock_notify.assert_has_calls([
mock.call(ctxt, self.inst, self.inst.host,
action='rebuild', phase='start', bdms=bdms),
mock.call(ctxt, self.inst, self.inst.host,
action='rebuild', phase='end', bdms=bdms)])
mock_notify_rebuild.assert_has_calls([
mock.call(ctxt, self.inst, self.inst.host, phase='start',
bdms=bdms),
mock.call(ctxt, self.inst, self.inst.host, phase='end',
bdms=bdms)])
mock_setup_networks_on_host.assert_called_once_with(
ctxt, self.inst, self.inst.host)

View File

@ -3968,7 +3968,7 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase):
@mock.patch.object(manager.ComputeManager, '_set_migration_status')
@mock.patch.object(manager.ComputeManager,
'_do_rebuild_instance_with_claim')
@mock.patch('nova.compute.utils.notify_about_instance_action')
@mock.patch('nova.compute.utils.notify_about_instance_rebuild')
@mock.patch.object(manager.ComputeManager, '_notify_about_instance_usage')
def _test_rebuild_ex(self, instance, exc,
mock_notify_about_instance_usage,
@ -3986,8 +3986,8 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase):
mock.ANY, instance, 'rebuild.error', fault=mock_rebuild.side_effect
)
mock_notify.assert_called_once_with(
mock.ANY, instance, 'fake-mini', action='rebuild', phase='error',
exception=exc, bdms=None)
mock.ANY, instance, 'fake-mini', phase='error', exception=exc,
bdms=None)
def test_rebuild_deleting(self):
instance = fake_instance.fake_instance_obj(self.context)
@ -4040,7 +4040,7 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase):
'setup_instance_network_on_host')
@mock.patch('nova.network.neutronv2.api.API.setup_networks_on_host')
@mock.patch('nova.objects.instance.Instance.save')
@mock.patch('nova.compute.utils.notify_about_instance_action')
@mock.patch('nova.compute.utils.notify_about_instance_rebuild')
@mock.patch('nova.compute.utils.notify_about_instance_usage')
@mock.patch('nova.compute.utils.notify_usage_exists')
@mock.patch('nova.objects.instance.Instance.image_meta',
@ -4080,7 +4080,7 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase):
'delete_allocation_for_evacuated_instance')
@mock.patch('nova.context.RequestContext.elevated')
@mock.patch('nova.objects.instance.Instance.save')
@mock.patch('nova.compute.utils.notify_about_instance_action')
@mock.patch('nova.compute.utils.notify_about_instance_rebuild')
@mock.patch('nova.compute.utils.notify_about_instance_usage')
@mock.patch('nova.compute.manager.ComputeManager.'
'_validate_instance_group_policy')
@ -4114,8 +4114,8 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase):
mock_delete_allocation.assert_called_once_with(
elevated_context, instance, 'fake-node', node_type='destination')
mock_notify.assert_called_once_with(
elevated_context, instance, 'fake-mini', action='rebuild',
bdms=None, exception=exc, phase='error')
elevated_context, instance, 'fake-mini', bdms=None, exception=exc,
phase='error')
def test_rebuild_node_not_updated_if_not_recreate(self):
node = uuidutils.generate_uuid() # ironic node uuid

View File

@ -376,6 +376,9 @@ notification_object_data = {
'FlavorPayload': '1.4-2e7011b8b4e59167fe8b7a0a81f0d452',
'InstanceActionNotification': '1.0-a73147b93b520ff0061865849d3dfa56',
'InstanceActionPayload': '1.6-e9e4cbb94e07d3bcaa22743f41e094c8',
'InstanceActionRebuildNotification':
'1.0-a73147b93b520ff0061865849d3dfa56',
'InstanceActionRebuildPayload': '1.7-db0d6d549a7932428cdc0c7ca78859b5',
'InstanceActionRescueNotification': '1.0-a73147b93b520ff0061865849d3dfa56',
'InstanceActionRescuePayload': '1.1-99b9b25574b77abf6d3e5a0cea341b06',
'InstanceActionResizePrepNotification':
@ -387,7 +390,7 @@ notification_object_data = {
'1.0-a73147b93b520ff0061865849d3dfa56',
'InstanceActionVolumeSwapPayload': '1.6-bb322fd649d3626c7a83d5f2d9a866d4',
'InstanceCreateNotification': '1.0-a73147b93b520ff0061865849d3dfa56',
'InstanceCreatePayload': '1.8-aab72bba998af21dc2e34b31e3c376ea',
'InstanceCreatePayload': '1.9-1c9f722bf51ddae910fb7e50fff8edd1',
'InstancePayload': '1.6-b1e7818c7adf158e8a6e87e0944b0b21',
'InstanceActionSnapshotNotification':
'1.0-a73147b93b520ff0061865849d3dfa56',

View File

@ -28,3 +28,19 @@ features:
* ``GET /servers/{server_id}``
* ``PUT /servers/{server_id}``
* ``POST /servers/{server_id}/action (rebuild)``
The payload of the ``instance.create.start`` and ``instance.create.end``
and ``instance.create.error`` notifications have been extended with the
``trusted_image_certificates`` field that contains the list of trusted
certificate IDs used when the instance is created.
The payload of the ``instance.rebuild.start`` and ``instance.rebuild.end``
and ``instance.rebuild.error`` notifications have been extended with the
``trusted_image_certificates`` field that contains the list of trusted
certificate IDs used when the instance is rebuilt. This change also causes
the type of the payload object to change from ``InstanceActionPayload``
version 1.6 to ``InstanceActionRebuildPayload`` version 1.7. See the
`notification dev reference`_ for the sample file of
``instance.rebuild.start`` as an example.
.. _notification dev reference: https://docs.openstack.org/developer/nova/notifications.html