Add instance.interface_detach notification

Based on the following discussion:
http://lists.openstack.org/pipermail/openstack-dev/2017-September/121978.html

removeFixedIp action is deprecated, so instead of transforming its
notification, the instance.interface_detach versioned notification is
introduced.

Change-Id: Id4fa9eba59ef958ce514d9eb43346adf095b8b6e
Implements: blueprint versioned-notification-transformation-queens
This commit is contained in:
Előd Illés 2017-09-21 18:29:39 +02:00
parent 5a70f23ec5
commit 08599b0892
9 changed files with 259 additions and 11 deletions

View File

@ -0,0 +1,93 @@
{
"publisher_id": "nova-compute:compute",
"event_type": "instance.interface_detach.end",
"priority": "INFO",
"payload": {
"nova_object.data": {
"fault": null,
"ramdisk_id": "",
"kernel_id": "",
"progress": 0,
"deleted_at": null,
"reservation_id": "r-xweiyxxa",
"created_at": "2012-10-29T13:42:11Z",
"uuid": "cb968404-7797-4896-9164-bbb1a1f9530b",
"display_description": "some-server",
"node": "fake-mini",
"os_type": null,
"host_name": "some-server",
"locked": false,
"user_id": "fake",
"ip_addresses": [
{
"nova_object.data": {
"device_name": "tapce531f90-19",
"address": "192.168.1.3",
"version": 4,
"label": "private-network",
"port_uuid": "ce531f90-199f-48c0-816c-13e38010b442",
"mac": "fa:16:3e:4c:2c:30",
"meta": {}
},
"nova_object.name": "IpPayload",
"nova_object.namespace": "nova",
"nova_object.version": "1.0"
}
],
"architecture": "x86_64",
"display_name": "some-server",
"launched_at": "2012-10-29T13:42:11Z",
"updated_at": "2012-10-29T13:42:11Z",
"key_name": "my-key",
"auto_disk_config": "MANUAL",
"block_devices": [
{
"nova_object.data": {
"boot_index": null,
"delete_on_termination": false,
"device_name": "/dev/sdb",
"tag": null,
"volume_id": "a07f71dc-8151-4e7d-a0cc-cd24a3f11113"
},
"nova_object.name": "BlockDevicePayload",
"nova_object.namespace": "nova",
"nova_object.version": "1.0"
}
],
"flavor": {
"nova_object.data": {
"swap": 0,
"rxtx_factor": 1.0,
"memory_mb": 512,
"name": "test_flavor",
"vcpu_weight": 0,
"root_gb": 1,
"vcpus": 1,
"is_public": true,
"ephemeral_gb": 0,
"extra_specs": {
"hw:watchdog_action": "disabled"
},
"disabled": false,
"projects": null,
"flavorid": "a22d5517-147c-4147-a0d1-e698df5cd4e3"
},
"nova_object.name": "FlavorPayload",
"nova_object.namespace": "nova",
"nova_object.version": "1.3"
},
"image_uuid": "155d900f-4e14-4e4c-a73d-069cbf4541e6",
"power_state": "running",
"metadata": {},
"tenant_id": "6f70656e737461636b20342065766572",
"terminated_at": null,
"task_state": null,
"host": "compute",
"state": "active",
"availability_zone": "nova"
},
"nova_object.name": "InstanceActionPayload",
"nova_object.namespace": "nova",
"nova_object.version": "1.5"
}
}

View File

@ -0,0 +1,107 @@
{
"priority": "INFO",
"event_type": "instance.interface_detach.start",
"payload": {
"nova_object.name": "InstanceActionPayload",
"nova_object.version": "1.5",
"nova_object.namespace": "nova",
"nova_object.data": {
"power_state": "running",
"host_name": "some-server",
"reservation_id": "r-f8grvm0d",
"metadata": {},
"os_type": null,
"display_description": "some-server",
"ramdisk_id": "",
"deleted_at": null,
"launched_at": "2012-10-29T13:42:11Z",
"updated_at": "2012-10-29T13:42:11Z",
"key_name": "my-key",
"auto_disk_config": "MANUAL",
"block_devices": [
{
"nova_object.data": {
"boot_index": null,
"delete_on_termination": false,
"device_name": "/dev/sdb",
"tag": null,
"volume_id": "a07f71dc-8151-4e7d-a0cc-cd24a3f11113"
},
"nova_object.name": "BlockDevicePayload",
"nova_object.namespace": "nova",
"nova_object.version": "1.0"
}
],
"availability_zone": "nova",
"display_name": "some-server",
"fault": null,
"locked": false,
"ip_addresses": [
{
"nova_object.name": "IpPayload",
"nova_object.version": "1.0",
"nova_object.namespace": "nova",
"nova_object.data": {
"label": "private-network",
"mac": "fa:16:3e:4c:2c:30",
"version": 4,
"address": "192.168.1.3",
"meta": {},
"port_uuid": "ce531f90-199f-48c0-816c-13e38010b442",
"device_name": "tapce531f90-19"
}
},
{
"nova_object.data": {
"device_name": "tap88dae9fa-0d",
"address": "192.168.1.30",
"version": 4,
"label": "private-network",
"port_uuid": "88dae9fa-0dc6-49e3-8c29-3abc41e99ac9",
"mac": "00:0c:29:0d:11:74",
"meta": {}
},
"nova_object.name": "IpPayload",
"nova_object.namespace": "nova",
"nova_object.version": "1.0"
}
],
"kernel_id": "",
"progress": 0,
"tenant_id": "6f70656e737461636b20342065766572",
"state": "active",
"task_state": null,
"uuid": "edbe0f81-b150-4fce-9258-4e03bb2ecb41",
"user_id": "fake",
"created_at": "2012-10-29T13:42:11Z",
"image_uuid": "155d900f-4e14-4e4c-a73d-069cbf4541e6",
"node": "fake-mini",
"flavor": {
"nova_object.name": "FlavorPayload",
"nova_object.version": "1.3",
"nova_object.namespace": "nova",
"nova_object.data": {
"vcpu_weight": 0,
"memory_mb": 512,
"name": "test_flavor",
"root_gb": 1,
"extra_specs": {
"hw:watchdog_action": "disabled"
},
"disabled": false,
"rxtx_factor": 1.0,
"vcpus": 1,
"is_public": true,
"swap": 0,
"flavorid": "a22d5517-147c-4147-a0d1-e698df5cd4e3",
"projects": null,
"ephemeral_gb": 0
}
},
"host": "compute",
"terminated_at": null,
"architecture": "x86_64"
}
},
"publisher_id": "nova-compute:compute"
}

View File

@ -5283,6 +5283,12 @@ class ComputeManager(manager.Manager):
if condemned is None:
raise exception.PortNotFound(_("Port %s is not "
"attached") % port_id)
compute_utils.notify_about_instance_action(
context, instance, self.host,
action=fields.NotificationAction.INTERFACE_DETACH,
phase=fields.NotificationPhase.START)
try:
self.driver.detach_interface(context, instance, condemned)
except exception.NovaException as ex:
@ -5303,6 +5309,11 @@ class ComputeManager(manager.Manager):
{'port_id': port_id, 'error': ex},
instance=instance)
compute_utils.notify_about_instance_action(
context, instance, self.host,
action=fields.NotificationAction.INTERFACE_DETACH,
phase=fields.NotificationPhase.END)
def _get_compute_info(self, context, host):
return objects.ComputeNode.get_first_node_by_host_for_old_compat(
context, host)

View File

@ -50,7 +50,9 @@ class EventType(NotificationObject):
# NotificationActionField enum
# Version 1.6: ADD_FIX_IP replaced with INTERFACE_ATTACH in
# NotificationActionField enum
VERSION = '1.6'
# Version 1.7: REMOVE_FIXED_IP replaced with INTERFACE_DETACH in
# NotificationActionField enum
VERSION = '1.7'
fields = {
'object': fields.StringField(nullable=False),

View File

@ -427,8 +427,8 @@ class InstanceStateUpdatePayload(base.NotificationPayloadBase):
@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-remove_fixed_ip-start.json')
# @base.notification_sample('instance-remove_fixed_ip-end.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')
# @base.notification_sample('instance-resize_confirm-end.json')
# @base.notification_sample('instance-resize_prep-start.json')

View File

@ -834,7 +834,7 @@ class NotificationAction(BaseNovaEnum):
LIVE_MIGRATION_ROLLBACK_DEST = 'live_migration_rollback_dest'
LIVE_MIGRATION_ROLLBACK = 'live_migration_rollback'
REBUILD = 'rebuild'
REMOVE_FIXED_IP = 'remove_fixed_ip'
INTERFACE_DETACH = 'interface_detach'
RESIZE_CONFIRM = 'resize_confirm'
RESIZE_PREP = 'resize_prep'
RESIZE_REVERT = 'resize_revert'
@ -852,7 +852,7 @@ class NotificationAction(BaseNovaEnum):
VOLUME_DETACH, CREATE, EVACUATE, RESIZE_FINISH,
LIVE_MIGRATION_ABORT, LIVE_MIGRATION_POST_DEST, LIVE_MIGRATION_POST,
LIVE_MIGRATION_PRE, LIVE_MIGRATION_ROLLBACK,
LIVE_MIGRATION_ROLLBACK_DEST, REBUILD, REMOVE_FIXED_IP,
LIVE_MIGRATION_ROLLBACK_DEST, REBUILD, INTERFACE_DETACH,
RESIZE_CONFIRM, RESIZE_PREP, RESIZE_REVERT, SHELVE_OFFLOAD,
SOFT_DELETE, TRIGGER_CRASH_DUMP, UNRESCUE, UNSHELVE, ADD_HOST,
REMOVE_HOST)

View File

@ -149,7 +149,7 @@ class TestInstanceNotificationSample(
self._test_unrescue_server,
self._test_soft_delete_server,
self._test_attach_volume_error,
self._test_interface_attach,
self._test_interface_attach_and_detach,
]
for action in actions:
@ -1144,7 +1144,7 @@ class TestInstanceNotificationSample(
'uuid': server['id']},
actual=fake_notifier.VERSIONED_NOTIFICATIONS[1])
def _test_interface_attach(self, server):
def _test_interface_attach_and_detach(self, server):
post = {
'interfaceAttachment': {
'net_id': fixtures.NeutronFixture.network_1['id']
@ -1165,3 +1165,24 @@ class TestInstanceNotificationSample(
'reservation_id': server['reservation_id'],
'uuid': server['id']},
actual=fake_notifier.VERSIONED_NOTIFICATIONS[1])
fake_notifier.reset()
self.assertEqual(0, len(fake_notifier.VERSIONED_NOTIFICATIONS))
self.api.detach_interface(
server['id'],
fixtures.NeutronFixture.port_2['id'])
self._wait_for_notification('instance.interface_detach.end')
self.assertEqual(2, len(fake_notifier.VERSIONED_NOTIFICATIONS))
self._verify_notification(
'instance-interface_detach-start',
replacements={
'reservation_id': server['reservation_id'],
'uuid': server['id']},
actual=fake_notifier.VERSIONED_NOTIFICATIONS[0])
self._verify_notification(
'instance-interface_detach-end',
replacements={
'reservation_id': server['reservation_id'],
'uuid': server['id']},
actual=fake_notifier.VERSIONED_NOTIFICATIONS[1])

View File

@ -9985,7 +9985,8 @@ class ComputeAPITestCase(BaseTestCase):
mock.call(self.context, instance, self.compute.host,
action='interface_attach', phase='start')])
def test_detach_interface(self):
@mock.patch.object(compute_utils, 'notify_about_instance_action')
def test_detach_interface(self, mock_notify):
nwinfo, port_id = self.test_attach_interface()
self.stub_out('nova.network.api.API.'
'deallocate_port_for_instance',
@ -9997,6 +9998,11 @@ class ComputeAPITestCase(BaseTestCase):
nwinfo)
self.compute.detach_interface(self.context, instance, port_id)
self.assertEqual(self.compute.driver._interfaces, {})
mock_notify.assert_has_calls([
mock.call(self.context, instance, self.compute.host,
action='interface_detach', phase='start'),
mock.call(self.context, instance, self.compute.host,
action='interface_detach', phase='end')])
def test_detach_interface_failed(self):
nwinfo, port_id = self.test_attach_interface()
@ -10008,15 +10014,19 @@ class ComputeAPITestCase(BaseTestCase):
nwinfo)
with test.nested(
mock.patch.object(compute_utils, 'notify_about_instance_action'),
mock.patch.object(self.compute.driver, 'detach_interface',
side_effect=exception.NovaException('detach_failed')),
mock.patch.object(self.compute.network_api,
'deallocate_port_for_instance')) as (
mock_detach, mock_deallocate):
mock_notify, mock_detach, mock_deallocate):
self.assertRaises(exception.InterfaceDetachFailed,
self.compute.detach_interface, self.context,
instance, port_id)
self.assertFalse(mock_deallocate.called)
mock_notify.assert_has_calls([
mock.call(self.context, instance, self.compute.host,
action='interface_detach', phase='start')])
@mock.patch.object(compute_manager.LOG, 'warning')
def test_detach_interface_deallocate_port_for_instance_failed(self,
@ -10035,12 +10045,13 @@ class ComputeAPITestCase(BaseTestCase):
# NovaExceptions.
error = neutron_exceptions.PortNotFoundClient()
with test.nested(
mock.patch.object(compute_utils, 'notify_about_instance_action'),
mock.patch.object(self.compute.driver, 'detach_interface'),
mock.patch.object(self.compute.network_api,
'deallocate_port_for_instance',
side_effect=error),
mock.patch.object(self.compute, '_instance_update')) as (
mock_detach, mock_deallocate, mock_instance_update):
mock_notify, mock_detach, mock_deallocate, mock_instance_update):
ex = self.assertRaises(neutron_exceptions.PortNotFoundClient,
self.compute.detach_interface, self.context,
instance, port_id)
@ -10048,6 +10059,9 @@ class ComputeAPITestCase(BaseTestCase):
mock_deallocate.assert_called_once_with(
self.context, instance, port_id)
self.assertEqual(1, warn_mock.call_count)
mock_notify.assert_has_calls([
mock.call(self.context, instance, self.compute.host,
action='interface_detach', phase='start')])
def test_attach_volume(self):
fake_bdm = fake_block_device.FakeDbBlockDeviceDict(

View File

@ -373,7 +373,7 @@ notification_object_data = {
'AuditPeriodPayload': '1.0-2b429dd307b8374636703b843fa3f9cb',
'BandwidthPayload': '1.0-ee2616a7690ab78406842a2b68e34130',
'BlockDevicePayload': '1.0-29751e1b6d41b1454e36768a1e764df8',
'EventType': '1.6-7d6ac2f1335a814202c2f7878b2ef978',
'EventType': '1.7-3a3b2d10c77bc2ad7c3a4dd7ff2d9d9b',
'ExceptionNotification': '1.0-a73147b93b520ff0061865849d3dfa56',
'ExceptionPayload': '1.0-27db46ee34cd97e39f2643ed92ad0cc5',
'FlavorNotification': '1.0-a73147b93b520ff0061865849d3dfa56',