Merge "[ovn] Specify port type if it's a router port when updating" into stable/xena
This commit is contained in:
@@ -291,6 +291,7 @@ LSP_TYPE_LOCALNET = 'localnet'
|
|||||||
LSP_TYPE_VIRTUAL = 'virtual'
|
LSP_TYPE_VIRTUAL = 'virtual'
|
||||||
LSP_TYPE_EXTERNAL = 'external'
|
LSP_TYPE_EXTERNAL = 'external'
|
||||||
LSP_TYPE_LOCALPORT = 'localport'
|
LSP_TYPE_LOCALPORT = 'localport'
|
||||||
|
LSP_TYPE_ROUTER = 'router'
|
||||||
LSP_OPTIONS_VIRTUAL_PARENTS_KEY = 'virtual-parents'
|
LSP_OPTIONS_VIRTUAL_PARENTS_KEY = 'virtual-parents'
|
||||||
LSP_OPTIONS_VIRTUAL_IP_KEY = 'virtual-ip'
|
LSP_OPTIONS_VIRTUAL_IP_KEY = 'virtual-ip'
|
||||||
LSP_OPTIONS_MCAST_FLOOD_REPORTS = 'mcast_flood_reports'
|
LSP_OPTIONS_MCAST_FLOOD_REPORTS = 'mcast_flood_reports'
|
||||||
|
|||||||
@@ -563,6 +563,13 @@ class OVNClient(object):
|
|||||||
txn.add(check_rev_cmd)
|
txn.add(check_rev_cmd)
|
||||||
columns_dict = {}
|
columns_dict = {}
|
||||||
if utils.is_lsp_router_port(port):
|
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(
|
port_info.options.update(
|
||||||
self._nb_idl.get_router_port_options(port['id']))
|
self._nb_idl.get_router_port_options(port['id']))
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -36,6 +36,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 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 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 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 import base as tests_base
|
||||||
from neutron.tests.functional import base
|
from neutron.tests.functional import base
|
||||||
|
|
||||||
@@ -505,6 +506,74 @@ class TestExternalPorts(base.TestOVNFunctionalBase):
|
|||||||
self.assertEqual(utils.ovn_name(net_id),
|
self.assertEqual(utils.ovn_name(net_id),
|
||||||
str(ovn_port.ha_chassis_group[0].name))
|
str(ovn_port.ha_chassis_group[0].name))
|
||||||
|
|
||||||
|
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):
|
def test_external_port_create_vnic_direct(self):
|
||||||
self._test_external_port_create(portbindings.VNIC_DIRECT)
|
self._test_external_port_create(portbindings.VNIC_DIRECT)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user