From 15d6cfffc9f3c63a7bac75f8d04beaae82ddc794 Mon Sep 17 00:00:00 2001 From: Luis Tomas Bolivar Date: Wed, 12 Jan 2022 11:45:53 +0100 Subject: [PATCH] Ensure subports status is aligned with parent port Subports of a trunk should have the same status as the parent port. However, with ovn, if the parent port is in DOWN status, the subports are transitioned to ACTIVE as soon as they are attached to the trunk. This patch ensure the status set on the subports when being attached matches the one on the parent port. Closes-Bug: #1957161 Change-Id: I26c43c2909b635e8b21306ea1880da3877477a17 --- neutron/services/trunk/drivers/ovn/trunk_driver.py | 13 ++++++++----- .../services/trunk/drivers/ovn/test_trunk_driver.py | 6 +++++- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/neutron/services/trunk/drivers/ovn/trunk_driver.py b/neutron/services/trunk/drivers/ovn/trunk_driver.py index d5ee3f9b395..7be9e430180 100644 --- a/neutron/services/trunk/drivers/ovn/trunk_driver.py +++ b/neutron/services/trunk/drivers/ovn/trunk_driver.py @@ -14,7 +14,6 @@ from neutron_lib.api.definitions import portbindings from neutron_lib.callbacks import events from neutron_lib.callbacks import registry from neutron_lib.callbacks import resources -from neutron_lib import constants as n_consts from neutron_lib import context as n_context from neutron_lib.db import api as db_api from neutron_lib import exceptions as n_exc @@ -46,10 +45,13 @@ class OVNTrunkHandler(object): def _set_sub_ports(self, parent_port, subports): txn = self.plugin_driver.nb_ovn.transaction context = n_context.get_admin_context() + db_parent_port = port_obj.Port.get_object(context, id=parent_port) + parent_port_status = db_parent_port.status for port in subports: with db_api.CONTEXT_WRITER.using(context), ( txn(check_error=True)) as ovn_txn: - self._set_binding_profile(context, port, parent_port, ovn_txn) + self._set_binding_profile(context, port, parent_port, + parent_port_status, ovn_txn) def _unset_sub_ports(self, subports): txn = self.plugin_driver.nb_ovn.transaction @@ -59,7 +61,8 @@ class OVNTrunkHandler(object): txn(check_error=True)) as ovn_txn: self._unset_binding_profile(context, port, ovn_txn) - def _set_binding_profile(self, context, subport, parent_port, ovn_txn): + def _set_binding_profile(self, context, subport, parent_port, + parent_port_status, ovn_txn): LOG.debug("Setting parent %s for subport %s", parent_port, subport.port_id) db_port = port_obj.Port.get_object(context, id=subport.port_id) @@ -74,8 +77,8 @@ class OVNTrunkHandler(object): db_port.device_owner = trunk_consts.TRUNK_SUBPORT_OWNER # NOTE(ksambor): When sub-port was created and event was process # without binding profile this port will end forever in DOWN - # status so we need to switch it here - db_port.status = n_consts.PORT_STATUS_ACTIVE + # status so we need to switch it here to the parent port status + db_port.status = parent_port_status for binding in db_port.bindings: binding.profile['parent_name'] = parent_port binding.profile['tag'] = subport.segmentation_id diff --git a/neutron/tests/unit/services/trunk/drivers/ovn/test_trunk_driver.py b/neutron/tests/unit/services/trunk/drivers/ovn/test_trunk_driver.py index 98a810b38e8..621b815f448 100644 --- a/neutron/tests/unit/services/trunk/drivers/ovn/test_trunk_driver.py +++ b/neutron/tests/unit/services/trunk/drivers/ovn/test_trunk_driver.py @@ -41,6 +41,8 @@ class TestTrunkHandler(base.BaseTestCase): self.handler = trunk_driver.OVNTrunkHandler(self.plugin_driver) self.trunk_1 = mock.Mock() self.trunk_1.port_id = "trunk-1" + self.trunk_1_obj = self._get_fake_port_obj( + port_id='trunk-1') self.trunk_2 = mock.Mock() self.trunk_2.port_id = "trunk-2" @@ -77,7 +79,8 @@ class TestTrunkHandler(base.BaseTestCase): "neutron.objects.ports.Port.get_object").start() self.mock_get_port.side_effect = lambda ctxt, id: ( self.sub_port_1_obj if id == 'sub_port_1' else ( - self.sub_port_2_obj if id == 'sub_port_2' else None)) + self.sub_port_2_obj if id == 'sub_port_2' else + self.trunk_1_obj if id == 'trunk-1' else None)) self.mock_port_update = mock.patch( "neutron.objects.ports.Port.update").start() self.mock_update_pb = mock.patch( @@ -91,6 +94,7 @@ class TestTrunkHandler(base.BaseTestCase): port = Port() port.id = port_id port.bindings = [PortBinding(profile={}, host='foo.com')] + port.status = 'ACTIVE' return port def _assert_calls(self, mock, expected_calls):