Skip to content

Commit 35fb52f

Browse files
juliakregerElod Illes
authored andcommitted
Ignore plug_vifs on the ironic driver
When the nova-compute service starts, by default it attempts to startup instance configuration states for aspects such as networking. This is fine in most cases, and makes a lot of sense if the nova-compute service is just managing virtual machines on a hypervisor. This is done, one instance at a time. However, when the compute driver is ironic, the networking is managed as part of the physical machine lifecycle potentially all the way into committed switch configurations. As such, there is no need to attempt to call ``plug_vifs`` on every single instance managed by the nova-compute process which is backed by Ironic. Additionally, using ironic tends to manage far more physical machines per nova-compute service instance then when when operating co-installed with a hypervisor. Often this means a cluster of a thousand machines, with three controllers, will see thousands of un-needed API calls upon service start, which elongates the entire process and negatively impacts operations. In essence, nova.virt.ironic's plug_vifs call now does nothing, and merely issues a debug LOG entry when called. Closes-Bug: #1777608 Change-Id: Iba87cef50238c5b02ab313f2311b826081d5b4ab (cherry picked from commit 7f81cf2) (cherry picked from commit eb6d70f) (cherry picked from commit f210115)
1 parent 4b9eba6 commit 35fb52f

File tree

3 files changed

+47
-18
lines changed

3 files changed

+47
-18
lines changed

nova/tests/unit/virt/ironic/test_driver.py

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2018,17 +2018,12 @@ def test_plug_vifs_with_port(self, mock_vatt):
20182018
@mock.patch.object(ironic_driver.IronicDriver, '_plug_vifs')
20192019
def test_plug_vifs(self, mock__plug_vifs):
20202020
node_id = 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee'
2021-
node = _get_cached_node(id=node_id)
2022-
2023-
self.mock_conn.get_node.return_value = node
20242021
instance = fake_instance.fake_instance_obj(self.ctx,
20252022
node=node_id)
20262023
network_info = utils.get_test_network_info()
20272024
self.driver.plug_vifs(instance, network_info)
20282025

2029-
self.mock_conn.get_node.assert_called_once_with(
2030-
node_id, fields=ironic_driver._NODE_FIELDS)
2031-
mock__plug_vifs.assert_called_once_with(node, instance, network_info)
2026+
mock__plug_vifs.assert_not_called()
20322027

20332028
@mock.patch.object(FAKE_CLIENT.node, 'vif_attach')
20342029
def test_plug_vifs_multiple_ports(self, mock_vatt):
@@ -2162,11 +2157,17 @@ def test_unplug_vifs_no_network_info(self, mock_vdet):
21622157
self.driver.unplug_vifs(instance, network_info)
21632158
self.assertFalse(mock_vdet.called)
21642159

2165-
@mock.patch.object(ironic_driver.IronicDriver, 'plug_vifs')
2160+
@mock.patch.object(ironic_driver.IronicDriver, '_plug_vifs')
21662161
def test_attach_interface(self, mock_pv):
2167-
self.driver.attach_interface('fake_context', 'fake_instance',
2162+
node_uuid = 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee'
2163+
node = _get_cached_node(uuid=node_uuid)
2164+
instance = fake_instance.fake_instance_obj(self.ctx,
2165+
node=node_uuid)
2166+
self.mock_conn.get_node.return_value = node
2167+
2168+
self.driver.attach_interface('fake_context', instance,
21682169
'fake_image_meta', 'fake_vif')
2169-
mock_pv.assert_called_once_with('fake_instance', ['fake_vif'])
2170+
mock_pv.assert_called_once_with(node, instance, ['fake_vif'])
21702171

21712172
@mock.patch.object(ironic_driver.IronicDriver, 'unplug_vifs')
21722173
def test_detach_interface(self, mock_uv):
@@ -2459,25 +2460,31 @@ def test_get_volume_connector_no_ip_without_mac(self):
24592460
def test_get_volume_connector_no_ip_no_fixed_ip(self):
24602461
self._test_get_volume_connector_no_ip(False, no_fixed_ip=True)
24612462

2462-
@mock.patch.object(ironic_driver.IronicDriver, 'plug_vifs')
2463+
@mock.patch.object(ironic_driver.IronicDriver, '_plug_vifs')
24632464
def test_prepare_networks_before_block_device_mapping(self, mock_pvifs):
2465+
node_uuid = 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee'
2466+
node = _get_cached_node(uuid=node_uuid)
2467+
self.mock_conn.get_node.return_value = node
24642468
instance = fake_instance.fake_instance_obj(self.ctx)
24652469
network_info = utils.get_test_network_info()
24662470
self.driver.prepare_networks_before_block_device_mapping(instance,
24672471
network_info)
2468-
mock_pvifs.assert_called_once_with(instance, network_info)
2472+
mock_pvifs.assert_called_once_with(node, instance, network_info)
24692473

2470-
@mock.patch.object(ironic_driver.IronicDriver, 'plug_vifs')
2474+
@mock.patch.object(ironic_driver.IronicDriver, '_plug_vifs')
24712475
def test_prepare_networks_before_block_device_mapping_error(self,
24722476
mock_pvifs):
2477+
node_uuid = 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee'
2478+
node = _get_cached_node(uuid=node_uuid)
2479+
self.mock_conn.get_node.return_value = node
24732480
instance = fake_instance.fake_instance_obj(self.ctx)
24742481
network_info = utils.get_test_network_info()
24752482
mock_pvifs.side_effect = ironic_exception.BadRequest('fake error')
24762483
self.assertRaises(
24772484
ironic_exception.BadRequest,
24782485
self.driver.prepare_networks_before_block_device_mapping,
24792486
instance, network_info)
2480-
mock_pvifs.assert_called_once_with(instance, network_info)
2487+
mock_pvifs.assert_called_once_with(node, instance, network_info)
24812488

24822489
@mock.patch.object(ironic_driver.IronicDriver, 'unplug_vifs')
24832490
def test_clean_networks_preparation(self, mock_upvifs):

nova/virt/ironic/driver.py

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1623,13 +1623,21 @@ def _unplug_vifs(self, node, instance, network_info):
16231623
def plug_vifs(self, instance, network_info):
16241624
"""Plug VIFs into networks.
16251625
1626+
This method is present for compatability. Any call will result
1627+
in a DEBUG log entry being generated, and will otherwise be
1628+
ignored, as Ironic manages VIF attachments through a node
1629+
lifecycle. Please see ``attach_interface``, which is the
1630+
proper and current method to utilize.
1631+
16261632
:param instance: The instance object.
16271633
:param network_info: Instance network information.
16281634
16291635
"""
1630-
# instance.node is the ironic node's UUID.
1631-
node = self._get_node(instance.node)
1632-
self._plug_vifs(node, instance, network_info)
1636+
LOG.debug('VIF plug called for instance %(instance)s on node '
1637+
'%(node)s, however Ironic manages VIF attachments '
1638+
'for nodes.',
1639+
{'instance': instance.uuid,
1640+
'node': instance.node})
16331641

16341642
def unplug_vifs(self, instance, network_info):
16351643
"""Unplug VIFs from networks.
@@ -1660,7 +1668,8 @@ def attach_interface(self, context, instance, image_meta, vif):
16601668
# event from neutron or by _heal_instance_info_cache periodic task. In
16611669
# both cases, this is done asynchronously, so the cache may not be up
16621670
# to date immediately after attachment.
1663-
self.plug_vifs(instance, [vif])
1671+
node = self._get_node(instance.node)
1672+
self._plug_vifs(node, instance, [vif])
16641673

16651674
def detach_interface(self, context, instance, vif):
16661675
"""Use hotunplug to remove a network interface from a running instance.
@@ -1977,7 +1986,9 @@ def prepare_networks_before_block_device_mapping(self, instance,
19771986
"""
19781987

19791988
try:
1980-
self.plug_vifs(instance, network_info)
1989+
node = self._get_node(instance.node)
1990+
self._plug_vifs(node, instance, network_info)
1991+
19811992
except Exception:
19821993
with excutils.save_and_reraise_exception():
19831994
LOG.error("Error preparing deploy for instance "
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
fixes:
3+
- |
4+
Fixes slow compute restart when using the ``nova.virt.ironic`` compute
5+
driver where the driver was previously attempting to attach VIFS on
6+
start-up via the ``plug_vifs`` driver method. This method has grown
7+
otherwise unused since the introduction of the ``attach_interface``
8+
method of attaching VIFs. As Ironic manages the attachment of VIFs to
9+
baremetal nodes in order to align with the security requirements of a
10+
physical baremetal node's lifecycle. The ironic driver now ignores calls
11+
to the ``plug_vifs`` method.

0 commit comments

Comments
 (0)