From 66f962d9b90d081fb029b455e12c625a9738ff92 Mon Sep 17 00:00:00 2001 From: Vasyl Saienko Date: Fri, 13 Jan 2017 15:58:06 +0200 Subject: [PATCH] Implement interface attach/detach in ironic virt driver This patch implements attach_interface, detach_interface methods in Ironic virt driver. Implements: blueprint ironic-hotplug-interfaces Co-Authored-By: Vladyslav Drok Depends-On: Idc9dc37b11950e3aa2864a0a90d6ec2e307926a3 Change-Id: I48c4706b3eb6e0a5105e463236870921d55dbd93 --- nova/tests/unit/virt/ironic/test_driver.py | 17 +++++--- nova/virt/ironic/driver.py | 40 ++++++++++++++++++- ...ch-support-in-ironic-cb2bf11f3875350a.yaml | 18 +++++++++ 3 files changed, 69 insertions(+), 6 deletions(-) create mode 100644 releasenotes/notes/add-interface-attach-detach-support-in-ironic-cb2bf11f3875350a.yaml diff --git a/nova/tests/unit/virt/ironic/test_driver.py b/nova/tests/unit/virt/ironic/test_driver.py index 0cefb721f6a7..1762ef0bd3de 100644 --- a/nova/tests/unit/virt/ironic/test_driver.py +++ b/nova/tests/unit/virt/ironic/test_driver.py @@ -129,11 +129,6 @@ class IronicDriverTestCase(test.NoDBTestCase): 'supports_migrate_to_same_host'], 'Driver capabilities for ' '\'supports_migrate_to_same_host\' is invalid') - self.assertFalse(self.driver.capabilities[ - 'supports_attach_interface'], - 'Driver capabilities for ' - '\'supports_attach_interface\' ' - 'is invalid') def test__get_hypervisor_type(self): self.assertEqual('ironic', self.driver._get_hypervisor_type()) @@ -1724,6 +1719,18 @@ class IronicDriverTestCase(test.NoDBTestCase): self.driver.unplug_vifs(instance, network_info) self.assertFalse(mock_vdet.called) + @mock.patch.object(ironic_driver.IronicDriver, 'plug_vifs') + def test_attach_interface(self, mock_pv): + self.driver.attach_interface('fake_context', 'fake_instance', + 'fake_image_meta', 'fake_vif') + mock_pv.assert_called_once_with('fake_instance', ['fake_vif']) + + @mock.patch.object(ironic_driver.IronicDriver, 'unplug_vifs') + def test_detach_interface(self, mock_uv): + self.driver.detach_interface('fake_context', 'fake_instance', + 'fake_vif') + mock_uv.assert_called_once_with('fake_instance', ['fake_vif']) + @mock.patch.object(firewall.NoopFirewallDriver, 'unfilter_instance', create=True) def test_unfilter_instance(self, mock_ui): diff --git a/nova/virt/ironic/driver.py b/nova/virt/ironic/driver.py index 742541788656..cf60361b1877 100644 --- a/nova/virt/ironic/driver.py +++ b/nova/virt/ironic/driver.py @@ -129,7 +129,7 @@ class IronicDriver(virt_driver.ComputeDriver): capabilities = {"has_imagecache": False, "supports_recreate": False, "supports_migrate_to_same_host": False, - "supports_attach_interface": False + "supports_attach_interface": True } def __init__(self, virtapi, read_only=False): @@ -1302,6 +1302,44 @@ class IronicDriver(virt_driver.ComputeDriver): node = self._get_node(instance.node) self._unplug_vifs(node, instance, network_info) + def attach_interface(self, context, instance, image_meta, vif): + """Use hotplug to add a network interface to a running instance. + The counter action to this is :func:`detach_interface`. + + :param context: The request context. + :param nova.objects.instance.Instance instance: + The instance which will get an additional network interface. + :param nova.objects.ImageMeta image_meta: + The metadata of the image of the instance. + :param nova.network.model.VIF vif: + The object which has the information about the interface to attach. + :raise nova.exception.NovaException: If the attach fails. + :returns: None + """ + # NOTE(vdrok): instance info cache gets updated by the network-changed + # event from neutron or by _heal_instance_info_cache periodic task. In + # both cases, this is done asynchronously, so the cache may not be up + # to date immediately after attachment. + self.plug_vifs(instance, [vif]) + + def detach_interface(self, context, instance, vif): + """Use hotunplug to remove a network interface from a running instance. + The counter action to this is :func:`attach_interface`. + + :param context: The request context. + :param nova.objects.instance.Instance instance: + The instance which gets a network interface removed. + :param nova.network.model.VIF vif: + The object which has the information about the interface to detach. + :raise nova.exception.NovaException: If the detach fails. + :returns: None + """ + # NOTE(vdrok): instance info cache gets updated by the network-changed + # event from neutron or by _heal_instance_info_cache periodic task. In + # both cases, this is done asynchronously, so the cache may not be up + # to date immediately after detachment. + self.unplug_vifs(instance, [vif]) + def rebuild(self, context, instance, image_meta, injected_files, admin_password, bdms, detach_block_devices, attach_block_devices, network_info=None, diff --git a/releasenotes/notes/add-interface-attach-detach-support-in-ironic-cb2bf11f3875350a.yaml b/releasenotes/notes/add-interface-attach-detach-support-in-ironic-cb2bf11f3875350a.yaml new file mode 100644 index 000000000000..8c31544d8b46 --- /dev/null +++ b/releasenotes/notes/add-interface-attach-detach-support-in-ironic-cb2bf11f3875350a.yaml @@ -0,0 +1,18 @@ +--- +features: + - | + Adds interface attach/detach support to baremetal nodes using ironic virt + driver. Note that the instance info cache update relies on getting a + ``network-changed`` event from neutron, or on the periodic task healing + the instance info cache, both of which are asynchronous. This means that + nova's cached network information (which is what is sent e.g. in the + ``GET /servers`` responses) may not be up to date immediately after the + attachment or detachment. +upgrade: + - | + Interface attachment/detachment for ironic virt driver was implemented in + in-tree network interfaces in ironic version 8.0, and this release is + required for nova's interface attachment feature to work. Prior to that + release, calling VIF attach on an active ironic node using in-tree network + interfaces would be basically a noop. It should not be an issue during the + upgrade though, as it is required to upgrade ironic before nova.