Merge "[OVN] Add missing LSP device_owner info in trunk driver"

This commit is contained in:
Zuul 2023-02-20 21:46:57 +00:00 committed by Gerrit Code Review
commit 8455edda46
8 changed files with 69 additions and 31 deletions

View File

@ -40,16 +40,23 @@ class API(api.API, metaclass=abc.ABCMeta):
""" """
@abc.abstractmethod @abc.abstractmethod
def set_lswitch_port(self, lport_name, if_exists=True, **columns): def set_lswitch_port(self, lport_name, external_ids_update=None,
if_exists=True, **columns):
"""Create a command to set OVN logical switch port fields """Create a command to set OVN logical switch port fields
:param lport_name: The name of the lport :param lport_name: The name of the lport
:type lport_name: string :type lport_name: string
:param external_ids_update: Dictionary of keys to be updated
individually in the external IDs dictionary.
If "external_ids" is defined in "columns",
"external_ids" will override any
"external_ids_update" value.
:type external_ids_update: dictionary
:param if_exists: Do not fail if lport does not exist
:type if_exists: bool
:param columns: Dictionary of port columns :param columns: Dictionary of port columns
Supported columns: macs, external_ids, Supported columns: macs, external_ids,
parent_name, tag, enabled parent_name, tag, enabled
:param if_exists: Do not fail if lport does not exist
:type if_exists: bool
:type columns: dictionary :type columns: dictionary
:returns: :class:`Command` with no result :returns: :class:`Command` with no result
""" """

View File

@ -148,9 +148,10 @@ class AddLSwitchPortCommand(command.BaseCommand):
class SetLSwitchPortCommand(command.BaseCommand): class SetLSwitchPortCommand(command.BaseCommand):
def __init__(self, api, lport, if_exists, **columns): def __init__(self, api, lport, external_ids_update, if_exists, **columns):
super(SetLSwitchPortCommand, self).__init__(api) super(SetLSwitchPortCommand, self).__init__(api)
self.lport = lport self.lport = lport
self.external_ids_update = external_ids_update
self.columns = columns self.columns = columns
self.if_exists = if_exists self.if_exists = if_exists
@ -195,6 +196,12 @@ class SetLSwitchPortCommand(command.BaseCommand):
for uuid in cur_port_dhcp_opts - new_port_dhcp_opts: for uuid in cur_port_dhcp_opts - new_port_dhcp_opts:
self.api._tables['DHCP_Options'].rows[uuid].delete() self.api._tables['DHCP_Options'].rows[uuid].delete()
external_ids_update = self.external_ids_update or {}
external_ids = getattr(port, 'external_ids', {})
for k, v in external_ids_update.items():
external_ids[k] = v
port.external_ids = external_ids
for col, val in self.columns.items(): for col, val in self.columns.items():
setattr(port, col, val) setattr(port, col, val)

View File

@ -277,8 +277,9 @@ class OvsdbNbOvnIdl(nb_impl_idl.OvnNbApiIdlImpl, Backend):
return cmd.AddLSwitchPortCommand(self, lport_name, lswitch_name, return cmd.AddLSwitchPortCommand(self, lport_name, lswitch_name,
may_exist, **columns) may_exist, **columns)
def set_lswitch_port(self, lport_name, if_exists=True, **columns): def set_lswitch_port(self, lport_name, external_ids_update=None,
return cmd.SetLSwitchPortCommand(self, lport_name, if_exists=True, **columns):
return cmd.SetLSwitchPortCommand(self, lport_name, external_ids_update,
if_exists, **columns) if_exists, **columns)
def update_lswitch_qos_options(self, port, if_exists=True, **qos): def update_lswitch_qos_options(self, port, if_exists=True, **qos):

View File

@ -21,7 +21,7 @@ from neutron_lib.services.trunk import constants as trunk_consts
from oslo_config import cfg from oslo_config import cfg
from oslo_log import log from oslo_log import log
from neutron.common.ovn.constants import OVN_ML2_MECH_DRIVER_NAME from neutron.common.ovn import constants as ovn_const
from neutron.objects import ports as port_obj from neutron.objects import ports as port_obj
from neutron.services.trunk.drivers import base as trunk_base from neutron.services.trunk.drivers import base as trunk_base
@ -94,10 +94,13 @@ class OVNTrunkHandler(object):
LOG.debug("Port not found while trying to set " LOG.debug("Port not found while trying to set "
"binding_profile: %s", subport.port_id) "binding_profile: %s", subport.port_id)
return return
ext_ids = {ovn_const.OVN_DEVICE_OWNER_EXT_ID_KEY: db_port.device_owner}
ovn_txn.add(self.plugin_driver.nb_ovn.set_lswitch_port( ovn_txn.add(self.plugin_driver.nb_ovn.set_lswitch_port(
lport_name=subport.port_id, lport_name=subport.port_id,
parent_name=parent_port, parent_name=parent_port,
tag=subport.segmentation_id)) tag=subport.segmentation_id,
external_ids_update=ext_ids,
))
LOG.debug("Done setting parent %s for subport %s", LOG.debug("Done setting parent %s for subport %s",
parent_port, subport.port_id) parent_port, subport.port_id)
@ -128,11 +131,14 @@ class OVNTrunkHandler(object):
LOG.debug("Port not found while trying to unset " LOG.debug("Port not found while trying to unset "
"binding_profile: %s", subport.port_id) "binding_profile: %s", subport.port_id)
return return
ext_ids = {ovn_const.OVN_DEVICE_OWNER_EXT_ID_KEY: db_port.device_owner}
ovn_txn.add(self.plugin_driver.nb_ovn.set_lswitch_port( ovn_txn.add(self.plugin_driver.nb_ovn.set_lswitch_port(
lport_name=subport.port_id, lport_name=subport.port_id,
parent_name=[], parent_name=[],
up=False, up=False,
tag=[])) tag=[],
external_ids_update=ext_ids,
))
LOG.debug("Done unsetting parent for subport %s", subport.port_id) LOG.debug("Done unsetting parent for subport %s", subport.port_id)
def trunk_created(self, trunk): def trunk_created(self, trunk):
@ -185,7 +191,8 @@ class OVNTrunkDriver(trunk_base.DriverBase):
@property @property
def is_loaded(self): def is_loaded(self):
try: try:
return OVN_ML2_MECH_DRIVER_NAME in cfg.CONF.ml2.mechanism_drivers return (ovn_const.OVN_ML2_MECH_DRIVER_NAME in
cfg.CONF.ml2.mechanism_drivers)
except cfg.NoSuchOptError: except cfg.NoSuchOptError:
return False return False
@ -205,7 +212,7 @@ class OVNTrunkDriver(trunk_base.DriverBase):
@classmethod @classmethod
def create(cls, plugin_driver): def create(cls, plugin_driver):
cls.plugin_driver = plugin_driver cls.plugin_driver = plugin_driver
return cls(OVN_ML2_MECH_DRIVER_NAME, return cls(ovn_const.OVN_ML2_MECH_DRIVER_NAME,
SUPPORTED_INTERFACES, SUPPORTED_INTERFACES,
SUPPORTED_SEGMENTATION_TYPES, SUPPORTED_SEGMENTATION_TYPES,
None, None,

View File

@ -833,12 +833,12 @@ class TestOvnNbSync(base.TestOVNFunctionalBase):
txn.add(self.nb_api.pg_del(pg)) txn.add(self.nb_api.pg_del(pg))
for lport_name in self.reset_lport_dhcpv4_options: for lport_name in self.reset_lport_dhcpv4_options:
txn.add(self.nb_api.set_lswitch_port(lport_name, True, txn.add(self.nb_api.set_lswitch_port(
dhcpv4_options=[])) lport_name, if_exists=True, dhcpv4_options=[]))
for lport_name in self.reset_lport_dhcpv6_options: for lport_name in self.reset_lport_dhcpv6_options:
txn.add(self.nb_api.set_lswitch_port(lport_name, True, txn.add(self.nb_api.set_lswitch_port(
dhcpv6_options=[])) lport_name, if_exists=True, dhcpv6_options=[]))
for dhcp_opts in self.stale_lport_dhcpv4_options: for dhcp_opts in self.stale_lport_dhcpv4_options:
dhcpv4_opts = txn.add(self.nb_api.add_dhcp_options( dhcpv4_opts = txn.add(self.nb_api.add_dhcp_options(
@ -851,7 +851,7 @@ class TestOvnNbSync(base.TestOVNFunctionalBase):
if dhcp_opts['port_id'] in self.orphaned_lport_dhcp_options: if dhcp_opts['port_id'] in self.orphaned_lport_dhcp_options:
continue continue
txn.add(self.nb_api.set_lswitch_port( txn.add(self.nb_api.set_lswitch_port(
lport_name, True, dhcpv4_options=dhcpv4_opts)) lport_name, if_exists=True, dhcpv4_options=dhcpv4_opts))
for dhcp_opts in self.stale_lport_dhcpv6_options: for dhcp_opts in self.stale_lport_dhcpv6_options:
dhcpv6_opts = txn.add(self.nb_api.add_dhcp_options( dhcpv6_opts = txn.add(self.nb_api.add_dhcp_options(
@ -864,7 +864,7 @@ class TestOvnNbSync(base.TestOVNFunctionalBase):
if dhcp_opts['port_id'] in self.orphaned_lport_dhcp_options: if dhcp_opts['port_id'] in self.orphaned_lport_dhcp_options:
continue continue
txn.add(self.nb_api.set_lswitch_port( txn.add(self.nb_api.set_lswitch_port(
lport_name, True, dhcpv6_options=dhcpv6_opts)) lport_name, if_exists=True, dhcpv6_options=dhcpv6_opts))
for row_uuid in self.missed_dhcp_options: for row_uuid in self.missed_dhcp_options:
txn.add(self.nb_api.delete_dhcp_options(row_uuid)) txn.add(self.nb_api.delete_dhcp_options(row_uuid))
@ -881,12 +881,12 @@ class TestOvnNbSync(base.TestOVNFunctionalBase):
for port_id in self.lport_dhcpv4_disabled: for port_id in self.lport_dhcpv4_disabled:
txn.add(self.nb_api.set_lswitch_port( txn.add(self.nb_api.set_lswitch_port(
port_id, True, port_id, if_exists=True,
dhcpv4_options=[self.lport_dhcpv4_disabled[port_id]])) dhcpv4_options=[self.lport_dhcpv4_disabled[port_id]]))
for port_id in self.lport_dhcpv6_disabled: for port_id in self.lport_dhcpv6_disabled:
txn.add(self.nb_api.set_lswitch_port( txn.add(self.nb_api.set_lswitch_port(
port_id, True, port_id, if_exists=True,
dhcpv6_options=[self.lport_dhcpv6_disabled[port_id]])) dhcpv6_options=[self.lport_dhcpv6_disabled[port_id]]))
# Delete the first DNS record and clear the second row records # Delete the first DNS record and clear the second row records

View File

@ -22,6 +22,8 @@ from neutron_lib.plugins import utils
from neutron_lib.services.trunk import constants as trunk_consts from neutron_lib.services.trunk import constants as trunk_consts
from oslo_utils import uuidutils from oslo_utils import uuidutils
from neutron.common.ovn import constants as ovn_const
class TestOVNTrunkDriver(base.TestOVNFunctionalBase): class TestOVNTrunkDriver(base.TestOVNFunctionalBase):
@ -60,18 +62,25 @@ class TestOVNTrunkDriver(base.TestOVNFunctionalBase):
for row in self.nb_api.tables[ for row in self.nb_api.tables[
'Logical_Switch_Port'].rows.values(): 'Logical_Switch_Port'].rows.values():
if row.parent_name and row.tag: if row.parent_name and row.tag:
device_owner = row.external_ids[
ovn_const.OVN_DEVICE_OWNER_EXT_ID_KEY]
ovn_trunk_info.append({'port_id': row.name, ovn_trunk_info.append({'port_id': row.name,
'parent_port_id': row.parent_name, 'parent_port_id': row.parent_name,
'tag': row.tag}) 'tag': row.tag,
'device_owner': device_owner,
})
return ovn_trunk_info return ovn_trunk_info
def _verify_trunk_info(self, trunk, has_items): def _verify_trunk_info(self, trunk, has_items):
ovn_subports_info = self._get_ovn_trunk_info() ovn_subports_info = self._get_ovn_trunk_info()
neutron_subports_info = [] neutron_subports_info = []
for subport in trunk.get('sub_ports', []): for subport in trunk.get('sub_ports', []):
neutron_subports_info.append({'port_id': subport['port_id'], neutron_subports_info.append(
{'port_id': subport['port_id'],
'parent_port_id': [trunk['port_id']], 'parent_port_id': [trunk['port_id']],
'tag': [subport['segmentation_id']]}) 'tag': [subport['segmentation_id']],
'device_owner': trunk_consts.TRUNK_SUBPORT_OWNER,
})
# Check that the subport has the binding is active. # Check that the subport has the binding is active.
binding = obj_reg.load_class('PortBinding').get_object( binding = obj_reg.load_class('PortBinding').get_object(
self.context, port_id=subport['port_id'], host='') self.context, port_id=subport['port_id'], host='')

View File

@ -200,7 +200,8 @@ class TestSetLSwitchPortCommand(TestBaseCommand):
with mock.patch.object(idlutils, 'row_by_value', with mock.patch.object(idlutils, 'row_by_value',
side_effect=idlutils.RowNotFound): side_effect=idlutils.RowNotFound):
cmd = commands.SetLSwitchPortCommand( cmd = commands.SetLSwitchPortCommand(
self.ovn_api, 'fake-lsp', if_exists=if_exists) self.ovn_api, 'fake-lsp', external_ids_update=None,
if_exists=if_exists)
if if_exists: if if_exists:
cmd.run_idl(self.transaction) cmd.run_idl(self.transaction)
else: else:
@ -220,8 +221,8 @@ class TestSetLSwitchPortCommand(TestBaseCommand):
with mock.patch.object(idlutils, 'row_by_value', with mock.patch.object(idlutils, 'row_by_value',
return_value=fake_lsp): return_value=fake_lsp):
cmd = commands.SetLSwitchPortCommand( cmd = commands.SetLSwitchPortCommand(
self.ovn_api, fake_lsp.name, if_exists=True, self.ovn_api, fake_lsp.name, external_ids_update=new_ext_ids,
external_ids=new_ext_ids) if_exists=True, external_ids=new_ext_ids)
cmd.run_idl(self.transaction) cmd.run_idl(self.transaction)
self.assertEqual(new_ext_ids, fake_lsp.external_ids) self.assertEqual(new_ext_ids, fake_lsp.external_ids)
@ -255,7 +256,8 @@ class TestSetLSwitchPortCommand(TestBaseCommand):
with mock.patch.object(idlutils, 'row_by_value', with mock.patch.object(idlutils, 'row_by_value',
return_value=fake_lsp): return_value=fake_lsp):
cmd = commands.SetLSwitchPortCommand( cmd = commands.SetLSwitchPortCommand(
self.ovn_api, fake_lsp.name, if_exists=True, **columns) self.ovn_api, fake_lsp.name, external_ids_update=None,
if_exists=True, **columns)
cmd.run_idl(self.transaction) cmd.run_idl(self.transaction)
if clear_v4_opts and clear_v6_opts: if clear_v4_opts and clear_v6_opts:
@ -307,7 +309,8 @@ class TestSetLSwitchPortCommand(TestBaseCommand):
with mock.patch.object(idlutils, 'row_by_value', with mock.patch.object(idlutils, 'row_by_value',
return_value=fake_lsp): return_value=fake_lsp):
cmd = commands.SetLSwitchPortCommand( cmd = commands.SetLSwitchPortCommand(
self.ovn_api, fake_lsp.name, if_exists=True, self.ovn_api, fake_lsp.name, external_ids_update=ext_ids,
if_exists=True,
external_ids=ext_ids, dhcpv4_options=dhcpv4_opts, external_ids=ext_ids, dhcpv4_options=dhcpv4_opts,
dhcpv6_options=dhcpv6_opts) dhcpv6_options=dhcpv6_opts)
if not isinstance(dhcpv4_opts, list): if not isinstance(dhcpv4_opts, list):

View File

@ -129,7 +129,9 @@ class TestTrunkHandler(base.BaseTestCase):
calls = [mock.call(lport_name=s_port.port_id, calls = [mock.call(lport_name=s_port.port_id,
parent_name=trunk.port_id, parent_name=trunk.port_id,
tag=s_port.segmentation_id) tag=s_port.segmentation_id,
external_ids_update={
'neutron:device_owner': 'trunk:subport'})
for trunk, s_port in [(self.trunk_1, self.sub_port_1), for trunk, s_port in [(self.trunk_1, self.sub_port_1),
(self.trunk_1, self.sub_port_2)]] (self.trunk_1, self.sub_port_2)]]
self._assert_calls(self.plugin_driver.nb_ovn.set_lswitch_port, calls) self._assert_calls(self.plugin_driver.nb_ovn.set_lswitch_port, calls)
@ -196,7 +198,8 @@ class TestTrunkHandler(base.BaseTestCase):
calls = [mock.call(lport_name=s_port.port_id, calls = [mock.call(lport_name=s_port.port_id,
parent_name=[], parent_name=[],
tag=[], tag=[],
up=False) up=False,
external_ids_update={'neutron:device_owner': ''})
for trunk, s_port in [(self.trunk_1, self.sub_port_1), for trunk, s_port in [(self.trunk_1, self.sub_port_1),
(self.trunk_1, self.sub_port_2)]] (self.trunk_1, self.sub_port_2)]]
self._assert_calls(self.plugin_driver.nb_ovn.set_lswitch_port, calls) self._assert_calls(self.plugin_driver.nb_ovn.set_lswitch_port, calls)
@ -225,7 +228,8 @@ class TestTrunkHandler(base.BaseTestCase):
calls = [mock.call(lport_name=s_port.port_id, calls = [mock.call(lport_name=s_port.port_id,
parent_name=[], parent_name=[],
tag=[], tag=[],
up=False) up=False,
external_ids_update={'neutron:device_owner': ''})
for trunk, s_port in [(self.trunk_1, self.sub_port_1)]] for trunk, s_port in [(self.trunk_1, self.sub_port_1)]]
self._assert_calls(self.plugin_driver.nb_ovn.set_lswitch_port, calls) self._assert_calls(self.plugin_driver.nb_ovn.set_lswitch_port, calls)