[OVN] Add the network type to the ``Logical_Switch`` register

Now the ``Logical_Switch`` register (that represents an OVN network),
stored the network type in the "external_ids" field.

Related-Bug: #2056558
Change-Id: I9e55a7412d841b7b59602c56c3a4e2f9c954aeed
This commit is contained in:
Rodolfo Alonso Hernandez 2024-03-10 15:47:09 +00:00 committed by Rodolfo Alonso
parent e8468a6dd6
commit f82c650c8c
5 changed files with 87 additions and 10 deletions

View File

@ -40,6 +40,7 @@ from neutron.conf.plugins.ml2.drivers.ovn import ovn_conf
from neutron.db import l3_attrs_db
from neutron.db import ovn_hash_ring_db as hash_ring_db
from neutron.db import ovn_revision_numbers_db as revision_numbers_db
from neutron.objects import network as network_obj
from neutron.objects import ports as ports_obj
from neutron.objects import router as router_obj
from neutron.objects import servicetype as servicetype_obj
@ -1228,6 +1229,30 @@ class DBInconsistenciesPeriodics(SchemaAwarePeriodicsBase):
raise periodics.NeverAgain()
# TODO(ralonsoh): Remove this method in the E cycle (SLURP release)
@has_lock_periodic(spacing=600, run_immediately=True)
def set_network_type(self):
"""Add the network type to the Logical_Switch registers"""
context = n_context.get_admin_context()
net_segments = network_obj.NetworkSegment.get_objects(context)
net_segments = {seg.network_id: seg.network_type
for seg in net_segments}
cmds = []
for ls in self._nb_idl.ls_list().execute(check_error=True):
if ovn_const.OVN_NETTYPE_EXT_ID_KEY not in ls.external_ids:
net_id = ls.name.replace('neutron-', '')
external_ids = {
ovn_const.OVN_NETTYPE_EXT_ID_KEY: net_segments[net_id]}
cmds.append(self._nb_idl.db_set(
'Logical_Switch', ls.uuid, ('external_ids', external_ids)))
if cmds:
with self._nb_idl.transaction(check_error=True) as txn:
for cmd in cmds:
txn.add(cmd)
raise periodics.NeverAgain()
class HashRingHealthCheckPeriodics(object):

View File

@ -1647,12 +1647,14 @@ class OVNClient(object):
for net in networks) else 'false'
return reside_redir_ch
def _gen_router_port_options(self, port, network=None):
def _gen_router_port_options(self, port):
options = {}
admin_context = n_context.get_admin_context()
if network is None:
network = self._plugin.get_network(admin_context,
port['network_id'])
ls_name = utils.ovn_name(port['network_id'])
ls = self._nb_idl.ls_get(ls_name).execute(check_error=True)
network_type = ls.external_ids[ovn_const.OVN_NETTYPE_EXT_ID_KEY]
network_mtu = int(
ls.external_ids[ovn_const.OVN_NETWORK_MTU_EXT_ID_KEY])
# For VLAN type networks we need to set the
# "reside-on-redirect-chassis" option so the routing for this
# logical router port is centralized in the chassis hosting the
@ -1660,7 +1662,7 @@ class OVNClient(object):
# https://github.com/openvswitch/ovs/commit/85706c34d53d4810f54bec1de662392a3c06a996
# FIXME(ltomasbo): Once Bugzilla 2162756 is fixed the
# is_provider_network check should be removed
if network.get(pnet.NETWORK_TYPE) == const.TYPE_VLAN:
if network_type == const.TYPE_VLAN:
reside_redir_ch = self._get_reside_redir_for_gateway_port(
port['device_id'])
options[ovn_const.LRP_OPTIONS_RESIDE_REDIR_CH] = reside_redir_ch
@ -1682,10 +1684,10 @@ class OVNClient(object):
admin_context, filters={'id': network_ids})
if ovn_conf.is_ovn_emit_need_to_frag_enabled():
for net in networks:
if net['mtu'] > network['mtu']:
if net['mtu'] > network_mtu:
options[
ovn_const.OVN_ROUTER_PORT_GW_MTU_OPTION] = str(
network['mtu'])
network_mtu)
break
if ovn_conf.is_ovn_distributed_floating_ip():
# NOTE(ltomasbo): For VLAN type networks connected through
@ -2002,7 +2004,11 @@ class OVNClient(object):
ovn_const.OVN_REV_NUM_EXT_ID_KEY: str(
utils.get_revision_number(network, ovn_const.TYPE_NETWORKS)),
ovn_const.OVN_AZ_HINTS_EXT_ID_KEY:
','.join(common_utils.get_az_hints(network))}}
','.join(common_utils.get_az_hints(network)),
# NOTE(ralonsoh): it is not considered the case of multiple
# segments.
ovn_const.OVN_NETTYPE_EXT_ID_KEY: network.get(pnet.NETWORK_TYPE),
}}
# Enable IGMP snooping if igmp_snooping_enable is enabled in Neutron
vlan_transparent = (
@ -2057,7 +2063,7 @@ class OVNClient(object):
commands = []
for port in ports:
lrp_name = utils.ovn_lrouter_port_name(port['id'])
options = self._gen_router_port_options(port, prov_net)
options = self._gen_router_port_options(port)
commands.append(self._nb_idl.lrp_set_options(lrp_name, **options))
self._transaction(commands, txn=txn)

View File

@ -1220,6 +1220,21 @@ class TestMaintenance(_TestMaintenanceHelper):
lr = self.nb_api.lookup('Logical_Router', utils.ovn_name(router['id']))
self.assertEqual([], lr.ports[0].gateway_chassis)
def test_set_network_type(self):
net1 = self._create_network(uuidutils.generate_uuid())
ls_name = utils.ovn_name(net1['id'])
self.nb_api.db_remove(
'Logical_Switch', ls_name, 'external_ids',
ovn_const.OVN_NETTYPE_EXT_ID_KEY).execute(check_error=True)
ls = self.nb_api.lookup('Logical_Switch', ls_name)
self.assertIsNone(ls.external_ids.get(
ovn_const.OVN_NETTYPE_EXT_ID_KEY))
self.assertRaises(periodics.NeverAgain, self.maint.set_network_type)
ls = self.nb_api.lookup('Logical_Switch', ls_name)
self.assertEqual(net1[provnet_apidef.NETWORK_TYPE],
ls.external_ids.get(ovn_const.OVN_NETTYPE_EXT_ID_KEY))
class TestLogMaintenance(_TestMaintenanceHelper,
test_log_driver.LogApiTestCaseBase):

View File

@ -2565,6 +2565,12 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase):
network['network']['mtu'] = new_mtu
fake_ctx = mock.MagicMock(current=network['network'])
fake_ctx.plugin_context.session.is_active = False
external_ids = {
ovn_const.OVN_NETTYPE_EXT_ID_KEY: const.TYPE_GENEVE,
ovn_const.OVN_NETWORK_MTU_EXT_ID_KEY: str(new_mtu),
}
self.nb_ovn.ls_get.return_value.execute.return_value = (
mock.Mock(external_ids=external_ids))
self.mech_driver.update_network_postcommit(fake_ctx)

View File

@ -339,6 +339,12 @@ class TestOVNL3RouterPlugin(test_mech_driver.Ml2PluginV2TestCase):
'neutron.plugins.ml2.drivers.ovn.mech_driver.ovsdb.ovn_client.'
'OVNClient._get_router_gw_ports',
return_value=self.fake_ext_gw_ports)
ext_ids = {
ovn_const.OVN_NETTYPE_EXT_ID_KEY: constants.TYPE_GENEVE,
ovn_const.OVN_NETWORK_MTU_EXT_ID_KEY: 9000,
}
self.l3_inst._nb_ovn.ls_get.return_value.execute.return_value = (
mock.Mock(external_ids=ext_ids))
def test__plugin_driver(self):
# No valid mech drivers should raise an exception.
@ -744,6 +750,12 @@ class TestOVNL3RouterPlugin(test_mech_driver.Ml2PluginV2TestCase):
fake_network_vlan = self.fake_network
fake_network_vlan[pnet.NETWORK_TYPE] = constants.TYPE_VLAN
gn.return_value = fake_network_vlan
ext_ids = {
ovn_const.OVN_NETTYPE_EXT_ID_KEY: constants.TYPE_VLAN,
ovn_const.OVN_NETWORK_MTU_EXT_ID_KEY: 1500,
}
self.l3_inst._nb_ovn.ls_get.return_value.execute.return_value = (
mock.Mock(external_ids=ext_ids))
payload = self._create_payload_for_router_interface(router_id)
self.ovn_drv._process_add_router_interface(resources.ROUTER_INTERFACE,
@ -1915,13 +1927,20 @@ class TestOVNL3RouterPlugin(test_mech_driver.Ml2PluginV2TestCase):
ari.return_value = self.fake_router_interface_info
grps.return_value = [interface_info]
self.get_router.return_value = self.fake_router_with_ext_gw
network_attrs = {'id': 'prov-net', 'mtu': 1200}
mtu = 1200
network_attrs = {'id': 'prov-net', 'mtu': mtu}
prov_net = fake_resources.FakeNetwork.create_one_network(
attrs=network_attrs).info()
self.fake_router_port['device_owner'] = (
constants.DEVICE_OWNER_ROUTER_GW)
gn.return_value = prov_net
gns.return_value = [self.fake_network]
ext_ids = {
ovn_const.OVN_NETTYPE_EXT_ID_KEY: constants.TYPE_GENEVE,
ovn_const.OVN_NETWORK_MTU_EXT_ID_KEY: mtu,
}
self.l3_inst._nb_ovn.ls_get.return_value.execute.return_value = (
mock.Mock(external_ids=ext_ids))
payload = self._create_payload_for_router_interface(router_id)
self.ovn_drv._process_add_router_interface(resources.ROUTER_INTERFACE,
@ -2119,6 +2138,12 @@ class OVNL3ExtrarouteTests(test_l3_gw.ExtGwModeIntTestCase,
self.l3_inst._nb_ovn.db_get.return_value.execute.return_value = ext_ids
self.l3_inst._nb_ovn.lookup.return_value = mock.Mock(
external_ids=ext_ids)
ext_ids = {
ovn_const.OVN_NETTYPE_EXT_ID_KEY: constants.TYPE_GENEVE,
ovn_const.OVN_NETWORK_MTU_EXT_ID_KEY: 9000,
}
self.l3_inst._nb_ovn.ls_get.return_value.execute.return_value = (
mock.Mock(external_ids=ext_ids))
# Note(dongj): According to bug #1657693, status of an unassociated
# floating IP is set to DOWN. Revise expected_status to DOWN for related