Allow detach vif in available state

Allow detaching vif in available state to avoid mac
confict during node rescheduling

Change-Id: I9b55054a97256cecb9d41029f03b1dfdf69c253c
Closes-Bug: 2109300
This commit is contained in:
Kaifeng Wang
2025-04-27 20:24:23 +08:00
parent c525a16b06
commit 42163f0c40
4 changed files with 17 additions and 4 deletions

View File

@@ -594,7 +594,8 @@ class NeutronVIFPortIDMixin(VIFPortIDMixin):
# NOTE(vsaienko): allow to unplug VIFs from ACTIVE instance. # NOTE(vsaienko): allow to unplug VIFs from ACTIVE instance.
# NOTE(TheJulia): Also ensure that we delete the vif when in # NOTE(TheJulia): Also ensure that we delete the vif when in
# DELETING state. # DELETING state.
if task.node.provision_state in [states.ACTIVE, states.DELETING]: if task.node.provision_state in [states.ACTIVE, states.DELETING,
states.AVAILABLE]:
neutron.unbind_neutron_port(vif_id, context=task.context) neutron.unbind_neutron_port(vif_id, context=task.context)
def get_node_network_data(self, task): def get_node_network_data(self, task):

View File

@@ -121,7 +121,9 @@ class TestNetwork(db_base.DbTestCase):
def test_get_node_vif_ids_during_rescuing(self): def test_get_node_vif_ids_during_rescuing(self):
self._test_get_node_vif_ids_multitenancy('rescuing_vif_port_id') self._test_get_node_vif_ids_multitenancy('rescuing_vif_port_id')
def test_remove_vifs_from_node(self): @mock.patch.object(neutron_common, 'unbind_neutron_port',
autospec=True)
def test_remove_vifs_from_node(self, mock_unp):
db_utils.create_test_port( db_utils.create_test_port(
node_id=self.node.id, address='aa:bb:cc:dd:ee:ff', node_id=self.node.id, address='aa:bb:cc:dd:ee:ff',
internal_info={driver_common.TENANT_VIF_KEY: 'test-vif-A'}) internal_info={driver_common.TENANT_VIF_KEY: 'test-vif-A'})
@@ -134,6 +136,7 @@ class TestNetwork(db_base.DbTestCase):
result = network.get_node_vif_ids(task) result = network.get_node_vif_ids(task)
self.assertEqual({}, result['ports']) self.assertEqual({}, result['ports'])
self.assertEqual({}, result['portgroups']) self.assertEqual({}, result['portgroups'])
self.assertTrue(mock_unp.called)
class TestRemoveVifsTestCase(db_base.DbTestCase): class TestRemoveVifsTestCase(db_base.DbTestCase):

View File

@@ -939,7 +939,7 @@ class TestNeutronVifPortIDMixin(db_base.DbTestCase):
with task_manager.acquire(self.context, self.node.id) as task: with task_manager.acquire(self.context, self.node.id) as task:
self.interface.vif_detach(task, 'fake_vif_id') self.interface.vif_detach(task, 'fake_vif_id')
mock_get.assert_called_once_with(self.interface, task, 'fake_vif_id') mock_get.assert_called_once_with(self.interface, task, 'fake_vif_id')
self.assertFalse(mock_unp.called) self.assertTrue(mock_unp.called)
mock_clear.assert_called_once_with(self.port) mock_clear.assert_called_once_with(self.port)
@mock.patch.object(common.VIFPortIDMixin, '_clear_vif_from_port_like_obj', @mock.patch.object(common.VIFPortIDMixin, '_clear_vif_from_port_like_obj',
@@ -954,7 +954,7 @@ class TestNeutronVifPortIDMixin(db_base.DbTestCase):
with task_manager.acquire(self.context, self.node.id) as task: with task_manager.acquire(self.context, self.node.id) as task:
self.interface.vif_detach(task, 'fake_vif_id') self.interface.vif_detach(task, 'fake_vif_id')
mock_get.assert_called_once_with(self.interface, task, 'fake_vif_id') mock_get.assert_called_once_with(self.interface, task, 'fake_vif_id')
self.assertFalse(mock_unp.called) self.assertTrue(mock_unp.called)
mock_clear.assert_called_once_with(pg) mock_clear.assert_called_once_with(pg)
@mock.patch.object(common.VIFPortIDMixin, '_clear_vif_from_port_like_obj', @mock.patch.object(common.VIFPortIDMixin, '_clear_vif_from_port_like_obj',

View File

@@ -0,0 +1,9 @@
---
fixes:
- |
Fix an issue in the OpenStack Nova-integrated installation that
mac address may conflict at Neutron service during baremetal instance
re-scheduling, by allowing VIFs to be unplugged when a node is in
the AVAILABLE state. See bug
`bug 2109300 <https://bugs.launchpad.net/ironic/+bug/2109300>`_
for more details.