Merge "Add separate instance.create payload type"

This commit is contained in:
Jenkins 2017-06-19 17:40:38 +00:00 committed by Gerrit Code Review
commit fad9e1a476
9 changed files with 115 additions and 35 deletions

View File

@ -66,7 +66,7 @@
"user_id":"fake",
"uuid":"178b0921-8f85-4257-88b6-2e743b5a975c"
},
"nova_object.name":"InstanceActionPayload",
"nova_object.name":"InstanceCreatePayload",
"nova_object.namespace":"nova",
"nova_object.version":"1.2"
},

View File

@ -63,7 +63,7 @@
"user_id":"fake",
"uuid":"178b0921-8f85-4257-88b6-2e743b5a975c"
},
"nova_object.name":"InstanceActionPayload",
"nova_object.name":"InstanceCreatePayload",
"nova_object.namespace":"nova",
"nova_object.version":"1.2"
},

View File

@ -53,7 +53,7 @@
"user_id":"fake",
"uuid":"178b0921-8f85-4257-88b6-2e743b5a975c"
},
"nova_object.name":"InstanceActionPayload",
"nova_object.name":"InstanceCreatePayload",
"nova_object.namespace":"nova",
"nova_object.version":"1.2"
},

View File

@ -1918,9 +1918,8 @@ class ComputeManager(manager.Manager):
image_name = image.get('name')
self._notify_about_instance_usage(context, instance, 'create.start',
extra_usage_info={'image_name': image_name})
compute_utils.notify_about_instance_action(
compute_utils.notify_about_instance_create(
context, instance, self.host,
action=fields.NotificationAction.CREATE,
phase=fields.NotificationPhase.START)
# NOTE(mikal): cache the keystone roles associated with the instance
@ -1966,17 +1965,15 @@ class ComputeManager(manager.Manager):
with excutils.save_and_reraise_exception():
self._notify_about_instance_usage(context, instance,
'create.error', fault=e)
compute_utils.notify_about_instance_action(
compute_utils.notify_about_instance_create(
context, instance, self.host,
action=fields.NotificationAction.CREATE,
phase=fields.NotificationPhase.ERROR, exception=e)
except exception.ComputeResourcesUnavailable as e:
LOG.debug(e.format_message(), instance=instance)
self._notify_about_instance_usage(context, instance,
'create.error', fault=e)
compute_utils.notify_about_instance_action(
compute_utils.notify_about_instance_create(
context, instance, self.host,
action=fields.NotificationAction.CREATE,
phase=fields.NotificationPhase.ERROR, exception=e)
raise exception.RescheduledException(
instance_uuid=instance.uuid, reason=e.format_message())
@ -1985,9 +1982,8 @@ class ComputeManager(manager.Manager):
LOG.debug(e.format_message(), instance=instance)
self._notify_about_instance_usage(context, instance,
'create.error', fault=e)
compute_utils.notify_about_instance_action(
compute_utils.notify_about_instance_create(
context, instance, self.host,
action=fields.NotificationAction.CREATE,
phase=fields.NotificationPhase.ERROR, exception=e)
except (exception.FixedIpLimitExceeded,
exception.NoMoreNetworks, exception.NoMoreFixedIps) as e:
@ -1995,9 +1991,8 @@ class ComputeManager(manager.Manager):
instance=instance)
self._notify_about_instance_usage(context, instance,
'create.error', fault=e)
compute_utils.notify_about_instance_action(
compute_utils.notify_about_instance_create(
context, instance, self.host,
action=fields.NotificationAction.CREATE,
phase=fields.NotificationPhase.ERROR, exception=e)
msg = _('Failed to allocate the network(s) with error %s, '
'not rescheduling.') % e.format_message()
@ -2011,9 +2006,8 @@ class ComputeManager(manager.Manager):
instance=instance)
self._notify_about_instance_usage(context, instance,
'create.error', fault=e)
compute_utils.notify_about_instance_action(
compute_utils.notify_about_instance_create(
context, instance, self.host,
action=fields.NotificationAction.CREATE,
phase=fields.NotificationPhase.ERROR, exception=e)
msg = _('Failed to allocate the network(s), not rescheduling.')
raise exception.BuildAbortException(instance_uuid=instance.uuid,
@ -2029,18 +2023,16 @@ class ComputeManager(manager.Manager):
exception.InvalidInput) as e:
self._notify_about_instance_usage(context, instance,
'create.error', fault=e)
compute_utils.notify_about_instance_action(
compute_utils.notify_about_instance_create(
context, instance, self.host,
action=fields.NotificationAction.CREATE,
phase=fields.NotificationPhase.ERROR, exception=e)
raise exception.BuildAbortException(instance_uuid=instance.uuid,
reason=e.format_message())
except Exception as e:
self._notify_about_instance_usage(context, instance,
'create.error', fault=e)
compute_utils.notify_about_instance_action(
compute_utils.notify_about_instance_create(
context, instance, self.host,
action=fields.NotificationAction.CREATE,
phase=fields.NotificationPhase.ERROR, exception=e)
raise exception.RescheduledException(
instance_uuid=instance.uuid, reason=six.text_type(e))
@ -2073,18 +2065,16 @@ class ComputeManager(manager.Manager):
with excutils.save_and_reraise_exception():
self._notify_about_instance_usage(context, instance,
'create.error', fault=e)
compute_utils.notify_about_instance_action(
compute_utils.notify_about_instance_create(
context, instance, self.host,
action=fields.NotificationAction.CREATE,
phase=fields.NotificationPhase.ERROR, exception=e)
self._update_scheduler_instance_info(context, instance)
self._notify_about_instance_usage(context, instance, 'create.end',
extra_usage_info={'message': _('Success')},
network_info=network_info)
compute_utils.notify_about_instance_action(context, instance,
self.host, action=fields.NotificationAction.CREATE,
phase=fields.NotificationPhase.END)
compute_utils.notify_about_instance_create(context, instance,
self.host, phase=fields.NotificationPhase.END)
@contextlib.contextmanager
def _build_resources(self, context, instance, requested_networks,

View File

@ -365,6 +365,34 @@ def notify_about_instance_action(context, instance, host, action, phase=None,
notification.emit(context)
def notify_about_instance_create(context, instance, host, phase=None,
binary='nova-compute', exception=None):
"""Send versioned notification about instance creation
:param context: the request context
:param instance: the instance being created
:param host: the host emitting the notification
:param phase: the phase of the creation
:param binary: the binary emitting the notification
:param exception: the thrown exception (used in error notifications)
"""
fault, priority = _get_fault_and_priority_from_exc(exception)
payload = instance_notification.InstanceCreatePayload(
instance=instance,
fault=fault)
notification = instance_notification.InstanceCreateNotification(
context=context,
priority=priority,
publisher=notification_base.NotificationPublisher(
host=host, binary=binary),
event_type=notification_base.EventType(
object='instance',
action=fields.NotificationAction.CREATE,
phase=phase),
payload=payload)
notification.emit(context)
def notify_about_volume_attach_detach(context, instance, host, action, phase,
binary='nova-compute', volume_id=None,
exception=None):

View File

@ -153,6 +153,23 @@ class InstanceActionVolumeSwapPayload(InstanceActionPayload):
self.new_volume_id = new_volume_id
@nova_base.NovaObjectRegistry.register_notification
class InstanceCreatePayload(InstanceActionPayload):
# No SCHEMA as all the additional fields are calculated
# Version 1.2: Initial version. It starts at 1.2 to match with the version
# of the InstanceActionPayload at the time when this specific
# 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'
def __init__(self, instance, fault):
super(InstanceCreatePayload, self).__init__(
instance=instance,
fault=fault)
@nova_base.NovaObjectRegistry.register_notification
class InstanceUpdatePayload(InstancePayload):
# Version 1.0: Initial version
@ -339,9 +356,6 @@ 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-create-start.json')
@base.notification_sample('instance-create-end.json')
@base.notification_sample('instance-create-error.json')
@nova_base.NovaObjectRegistry.register_notification
class InstanceActionNotification(base.NotificationBase):
# Version 1.0: Initial version
@ -389,3 +403,16 @@ class InstanceActionVolumeNotification(base.NotificationBase):
fields = {
'payload': fields.ObjectField('InstanceActionVolumePayload')
}
@base.notification_sample('instance-create-start.json')
@base.notification_sample('instance-create-end.json')
@base.notification_sample('instance-create-error.json')
@nova_base.NovaObjectRegistry.register_notification
class InstanceCreateNotification(base.NotificationBase):
# Version 1.0: Initial version
VERSION = '1.0'
fields = {
'payload': fields.ObjectField('InstanceCreatePayload')
}

View File

@ -4360,7 +4360,7 @@ class ComputeManagerBuildInstanceTestCase(test.NoDBTestCase):
'_shutdown_instance'),
mock.patch.object(self.compute,
'_validate_instance_group_policy'),
mock.patch('nova.compute.utils.notify_about_instance_action')
mock.patch('nova.compute.utils.notify_about_instance_create')
) as (spawn, save,
_build_networks_for_instance, _notify_about_instance_usage,
_shutdown_instance, _validate_instance_group_policy,
@ -4387,9 +4387,9 @@ class ComputeManagerBuildInstanceTestCase(test.NoDBTestCase):
mock_notify.assert_has_calls([
mock.call(self.context, self.instance, 'fake-mini',
action='create', phase='start'),
phase='start'),
mock.call(self.context, self.instance, 'fake-mini',
action='create', phase='error', exception=exc)])
phase='error', exception=exc)])
save.assert_has_calls([
mock.call(),
@ -4797,10 +4797,10 @@ class ComputeManagerBuildInstanceTestCase(test.NoDBTestCase):
self.context, mock.sentinel.instance,
requested_networks=requested_networks)
@mock.patch('nova.compute.utils.notify_about_instance_action')
@mock.patch('nova.compute.utils.notify_about_instance_create')
@mock.patch.object(manager.ComputeManager, '_instance_update')
def test_launched_at_in_create_end_notification(self,
mock_instance_update, mock_notify_instance_action):
mock_instance_update, mock_notify_instance_create):
def fake_notify(*args, **kwargs):
if args[2] == 'create.end':
@ -4829,11 +4829,11 @@ class ComputeManagerBuildInstanceTestCase(test.NoDBTestCase):
mock_notify.call_count - 1]
self.assertEqual(expected_call, create_end_call)
mock_notify_instance_action.assert_has_calls([
mock_notify_instance_create.assert_has_calls([
mock.call(self.context, self.instance, 'fake-mini',
action='create', phase='start'),
phase='start'),
mock.call(self.context, self.instance, 'fake-mini',
action='create', phase='end')])
phase='end')])
def test_access_ip_set_when_instance_set_to_active(self):

View File

@ -518,6 +518,39 @@ class UsageInfoTestCase(test.TestCase):
self.assertEqual(payload['image_uuid'], uuids.fake_image_ref)
def test_notify_about_instance_create(self):
instance = create_instance(self.context)
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']))
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_volume_swap(self):
instance = create_instance(self.context)

View File

@ -381,6 +381,8 @@ notification_object_data = {
'InstanceActionVolumeSwapNotification':
'1.0-a73147b93b520ff0061865849d3dfa56',
'InstanceActionVolumeSwapPayload': '1.2-d7925b763e0795f8e5c1aa0e95bd67bd',
'InstanceCreateNotification': '1.0-a73147b93b520ff0061865849d3dfa56',
'InstanceCreatePayload': '1.2-b7b2481bcd0e1edcc1970ef7150df5aa',
'InstancePayload': '1.2-a1988f6fe728bd4b478353a85c48ad55',
'InstanceStateUpdatePayload': '1.0-07e111c0fa0f6db0f79b0726d593e3da',
'InstanceUpdateNotification': '1.0-a73147b93b520ff0061865849d3dfa56',