diff options
author | Zuul <zuul@review.opendev.org> | 2022-09-24 12:56:40 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2022-09-24 12:56:40 +0000 |
commit | e5ab8d85c383e69fef9dd5a25defb3356bfe1f65 (patch) | |
tree | e56e5720d0edce31b57d613896b30ce136dc1cf0 | |
parent | 9cd3a05798d99d5f58e142616af601918ca2cb74 (diff) | |
parent | 6e1b7d15d7d68f2d409ce34e9a518c6aa0289022 (diff) | |
download | neutron-e5ab8d85c383e69fef9dd5a25defb3356bfe1f65.tar.gz |
Merge "[ovn] Specify port type if it's a router port when updating" into stable/ussuri
3 files changed, 77 insertions, 0 deletions
diff --git a/neutron/common/ovn/constants.py b/neutron/common/ovn/constants.py index 776df5a911..4597848802 100644 --- a/neutron/common/ovn/constants.py +++ b/neutron/common/ovn/constants.py @@ -288,6 +288,7 @@ PORT_SECURITYGROUPS = 'security_groups' LSP_TYPE_LOCALNET = 'localnet' LSP_TYPE_VIRTUAL = 'virtual' LSP_TYPE_EXTERNAL = 'external' +LSP_TYPE_ROUTER = 'router' LSP_OPTIONS_VIRTUAL_PARENTS_KEY = 'virtual-parents' LSP_OPTIONS_VIRTUAL_IP_KEY = 'virtual-ip' LSP_OPTIONS_MCAST_FLOOD_REPORTS = 'mcast_flood_reports' diff --git a/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovn_client.py b/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovn_client.py index 7d76accd2b..c8eccd6e29 100644 --- a/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovn_client.py +++ b/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovn_client.py @@ -491,6 +491,13 @@ class OVNClient(object): txn.add(check_rev_cmd) columns_dict = {} if utils.is_lsp_router_port(port): + # It is needed to specify the port type, if not specified + # the AddLSwitchPortCommand will trigger a change + # on the northd status column from UP to DOWN, triggering a + # LogicalSwitchPortUpdateDownEvent, that will most likely + # cause a revision conflict. + # https://bugs.launchpad.net/neutron/+bug/1955578 + columns_dict['type'] = ovn_const.LSP_TYPE_ROUTER port_info.options.update( self._nb_idl.get_router_port_options(port['id'])) else: diff --git a/neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/test_mech_driver.py b/neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/test_mech_driver.py index 5ee1ea8ea1..0157c689d6 100644 --- a/neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/test_mech_driver.py +++ b/neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/test_mech_driver.py @@ -34,6 +34,7 @@ from neutron.db import ovn_revision_numbers_db as db_rev from neutron.plugins.ml2.drivers.ovn.mech_driver import mech_driver from neutron.plugins.ml2.drivers.ovn.mech_driver.ovsdb import impl_idl_ovn from neutron.plugins.ml2.drivers.ovn.mech_driver.ovsdb import ovn_client +from neutron.plugins.ml2.drivers.ovn.mech_driver.ovsdb import ovsdb_monitor from neutron.tests import base as tests_base from neutron.tests.functional import base @@ -507,6 +508,74 @@ class TestExternalPorts(base.TestOVNFunctionalBase): self.assertEqual(str(self.default_ch_grp.uuid), str(ovn_port.ha_chassis_group[0].uuid)) + def _create_router_port(self, vnic_type): + net_id = self.n1['network']['id'] + port_data = { + 'port': {'network_id': net_id, + 'tenant_id': self._tenant_id, + portbindings.VNIC_TYPE: 'normal'}} + + # Create port + port_req = self.new_create_request('ports', port_data, self.fmt) + port_res = port_req.get_response(self.api) + port = self.deserialize(self.fmt, port_res)['port'] + + # Update it as lsp port + port_upt_data = { + 'port': {'device_owner': "network:router_gateway"} + } + port_req = self.new_update_request( + 'ports', port_upt_data, port['id'], self.fmt) + port_res = port_req.get_response(self.api) + + def test_add_external_port_avoid_flapping(self): + class LogicalSwitchPortUpdateUpEventTest(event.RowEvent): + def __init__(self): + self.count = 0 + table = 'Logical_Switch_Port' + events = (self.ROW_UPDATE,) + super(LogicalSwitchPortUpdateUpEventTest, self).__init__( + events, table, (('up', '=', True),), + old_conditions=(('up', '=', False),)) + + def run(self, event, row, old): + self.count += 1 + + def get_count(self): + return self.count + + class LogicalSwitchPortUpdateDownEventTest(event.RowEvent): + def __init__(self): + self.count = 0 + table = 'Logical_Switch_Port' + events = (self.ROW_UPDATE,) + super(LogicalSwitchPortUpdateDownEventTest, self).__init__( + events, table, (('up', '=', False),), + old_conditions=(('up', '=', True),)) + + def run(self, event, row, old): + self.count += 1 + + def get_count(self): + return self.count + + og_up_event = ovsdb_monitor.LogicalSwitchPortUpdateUpEvent(None) + og_down_event = ovsdb_monitor.LogicalSwitchPortUpdateDownEvent(None) + test_down_event = LogicalSwitchPortUpdateDownEventTest() + test_up_event = LogicalSwitchPortUpdateUpEventTest() + self.nb_api.idl.notify_handler.unwatch_events( + [og_up_event, og_down_event]) + self.nb_api.idl.notify_handler.watch_events( + [test_down_event, test_up_event]) + # Creating a port the same way as the osp cli cmd + # openstack router add port ROUTER PORT + # shouldn't trigger an status flapping (up -> down -> up) + # it should be created with status false and then change the + # status as up, triggering only a LogicalSwitchPortUpdateUpEvent. + self._create_router_port(portbindings.VNIC_DIRECT) + self.assertEqual(test_down_event.get_count(), 0) + self.assertEqual(test_up_event.get_count(), 1) + def test_external_port_create_vnic_direct(self): self._test_external_port_create(portbindings.VNIC_DIRECT) |