summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZuul <zuul@review.opendev.org>2022-09-24 12:56:40 +0000
committerGerrit Code Review <review@openstack.org>2022-09-24 12:56:40 +0000
commite5ab8d85c383e69fef9dd5a25defb3356bfe1f65 (patch)
treee56e5720d0edce31b57d613896b30ce136dc1cf0
parent9cd3a05798d99d5f58e142616af601918ca2cb74 (diff)
parent6e1b7d15d7d68f2d409ce34e9a518c6aa0289022 (diff)
downloadneutron-e5ab8d85c383e69fef9dd5a25defb3356bfe1f65.tar.gz
Merge "[ovn] Specify port type if it's a router port when updating" into stable/ussuri
-rw-r--r--neutron/common/ovn/constants.py1
-rw-r--r--neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovn_client.py7
-rw-r--r--neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/test_mech_driver.py69
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)