From 0340d412bef0d52da996ab901b12bf15c3015d9e 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. Conflicts: neutron/services/trunk/drivers/ovn/trunk_driver.py The conflict is related to the code added by https://github.com/openstack/neutron/commit/6ada9124143f42311951a75b5d586bbab4451ce6 Closes-Bug: #1957161 Change-Id: I26c43c2909b635e8b21306ea1880da3877477a17 (cherry picked from commit 15d6cfffc9f3c63a7bac75f8d04beaae82ddc794) --- neutron/services/trunk/drivers/ovn/trunk_driver.py | 12 ++++++++++-- .../services/trunk/drivers/ovn/test_trunk_driver.py | 6 +++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/neutron/services/trunk/drivers/ovn/trunk_driver.py b/neutron/services/trunk/drivers/ovn/trunk_driver.py index bd6323d86e1..3059356da54 100644 --- a/neutron/services/trunk/drivers/ovn/trunk_driver.py +++ b/neutron/services/trunk/drivers/ovn/trunk_driver.py @@ -45,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 @@ -58,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) @@ -71,6 +75,10 @@ class OVNTrunkHandler(object): # NOTE(flaviof): We expect binding's host to be set. Otherwise, # sub-port will not transition from DOWN to ACTIVE. 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 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 30afad8d048..ebe7db239e6 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):