Browse Source

Do not perform port update in case of baremetal instance.

In case of a baremetal instance, the instance's port binding:host_id
gets updated during instance reboot to the nova compute host id by
the periodic task: _heal_instance_info_cache. This regression was
introduced in commit: I75fd15ac2a29e420c09499f2c41d11259ca811ae

This is an un-desirable change as ironic virt driver did the original
port binding, nova should not update the value.
In case of a baremetal port, the binding:host_id represents the ironic
node_uuid. In case of a SmartNIC(baremetal) port[1] the binding:host_id
represent the SmartNIC hostname and it MUST not change since ironic
relies on that information as well as the Neutron agent that runs on
the SmartNIC.

A new API method was added, "manages_port_bindings()", to ComputeDriver
that defaults to False, and overriden in IronicDriver to True.

A call to this API method is now made in _heal_instance_info_cache() to
prevent port update for instance ports in case the underlying
ComputeDriver manages the port binding.

[1] I658754f7f8c74087b0aabfdef222a2c0b5698541

Change-Id: I47d1aba17cd2e9fff67846cc243c8fbd9ac21659
Closes-Bug: #1822801
(cherry picked from commit 091aa32896)
tags/19.0.1
Hamdy Khader 3 months ago
parent
commit
7cd816f43a

+ 7
- 1
nova/compute/manager.py View File

@@ -7204,8 +7204,14 @@ class ComputeManager(manager.Manager):
7204 7204
         binding_failed or unbound binding:vif_type for any of the instances
7205 7205
         ports.
7206 7206
         """
7207
-        if not utils.is_neutron():
7207
+        # Only update port bindings if compute manager does manage port
7208
+        # bindings instead of the compute driver. For example IronicDriver
7209
+        # manages the port binding for baremetal instance ports, hence,
7210
+        # external intervention with the binding is not desired.
7211
+        if (not utils.is_neutron() or
7212
+                self.driver.manages_network_binding_host_id()):
7208 7213
             return False
7214
+
7209 7215
         search_opts = {'device_id': instance.uuid,
7210 7216
                        'fields': ['binding:host_id', 'binding:vif_type']}
7211 7217
         ports = self.network_api.list_ports(context, **search_opts)

+ 13
- 0
nova/tests/unit/compute/test_compute.py View File

@@ -7267,6 +7267,19 @@ class ComputeTestCase(BaseTestCase,
7267 7267
             self.assertTrue(val)
7268 7268
             mock_list_ports.assert_called_once_with(ctxt, **search_opts)
7269 7269
 
7270
+    def test_require_nw_info_update_for_baremetal(self):
7271
+        """Tests _require_nw_info_update for baremetal instance,
7272
+        expected behavior is to return False.
7273
+        """
7274
+        compute_mgr = compute_manager.ComputeManager('ironic.IronicDriver')
7275
+        with mock.patch.object(compute_mgr, 'network_api') as \
7276
+                network_api_mock:
7277
+            ctxt = context.get_admin_context()
7278
+            instance = self._create_fake_instance_obj()
7279
+            val = compute_mgr._require_nw_info_update(ctxt, instance)
7280
+            self.assertFalse(val)
7281
+            network_api_mock.assert_not_called()
7282
+
7270 7283
     def _heal_instance_info_cache(self,
7271 7284
                                   _get_instance_nw_info_raise=False,
7272 7285
                                   _get_instance_nw_info_raise_cache=False,

+ 13
- 0
nova/virt/driver.py View File

@@ -1843,6 +1843,19 @@ class ComputeDriver(object):
1843 1843
         """
1844 1844
         return instance.get('host')
1845 1845
 
1846
+    def manages_network_binding_host_id(self):
1847
+        """Compute driver manages port bindings.
1848
+
1849
+        Used to indicate whether or not the compute driver is responsible
1850
+        for managing port binding details, such as the host_id.
1851
+        By default the ComputeManager will manage port bindings and the
1852
+        host_id associated with a binding using the network API.
1853
+        However, some backends, like Ironic, will manage the port binding
1854
+        host_id out-of-band and the compute service should not override what
1855
+        is set by the backing hypervisor.
1856
+        """
1857
+        return False
1858
+
1846 1859
 
1847 1860
 def load_compute_driver(virtapi, compute_driver=None):
1848 1861
     """Load a compute driver module.

+ 5
- 0
nova/virt/ironic/driver.py View File

@@ -2176,3 +2176,8 @@ class IronicDriver(virt_driver.ComputeDriver):
2176 2176
         timer.start(interval=CONF.ironic.api_retry_interval).wait()
2177 2177
         LOG.info('Successfully unrescued Ironic node %(node)s',
2178 2178
                  {'node': node_uuid}, instance=instance)
2179
+
2180
+    def manages_network_binding_host_id(self):
2181
+        """IronicDriver manages port bindings for baremetal instances.
2182
+        """
2183
+        return True

Loading…
Cancel
Save