[OVN] Migrate "reside-on-redirect-chassis" for distributed FIP

This patch complement the changes made at
8287654127 by creating a maintenance task
resposible for migrating the "reside-on-redirect-chassis" option value
for existing router ports when the deployment is updated.

Change-Id: I0c623a101357226ec0b4e3e42b829303846b6f6b
Related-Bug: #1920976
Signed-off-by: Lucas Alvares Gomes <lucasagomes@gmail.com>
This commit is contained in:
Lucas Alvares Gomes 2022-01-28 15:57:45 +00:00
parent a88a8ab413
commit 5bef868477
4 changed files with 88 additions and 3 deletions

View File

@ -285,6 +285,8 @@ LSP_OPTIONS_VIRTUAL_IP_KEY = 'virtual-ip'
LSP_OPTIONS_MCAST_FLOOD_REPORTS = 'mcast_flood_reports'
LSP_OPTIONS_MCAST_FLOOD = 'mcast_flood'
LRP_OPTIONS_RESIDE_REDIR_CH = 'reside-on-redirect-chassis'
# Port Binding types
PB_TYPE_PATCH = 'patch'
PB_TYPE_VIRTUAL = 'virtual'

View File

@ -21,6 +21,7 @@ import threading
from futurist import periodics
from neutron_lib.api.definitions import external_net
from neutron_lib.api.definitions import provider_net as pnet
from neutron_lib.api.definitions import segment as segment_def
from neutron_lib import constants as n_const
from neutron_lib import context as n_context
@ -769,6 +770,41 @@ class DBInconsistenciesPeriodics(SchemaAwarePeriodicsBase):
txn.add(cmd)
raise periodics.NeverAgain()
# A static spacing value is used here, but this method will only run
# once per lock due to the use of periodics.NeverAgain().
@periodics.periodic(spacing=600, run_immediately=True)
def check_vlan_distributed_ports(self):
"""Check VLAN distributed ports
Check for the option "reside-on-redirect-chassis" value for
distributed VLAN ports.
"""
if not self.has_lock:
return
context = n_context.get_admin_context()
cmds = []
# Get router ports belonging to VLAN networks
vlan_nets = self._ovn_client._plugin.get_networks(
context, {pnet.NETWORK_TYPE: [n_const.TYPE_VLAN]})
vlan_net_ids = [vn['id'] for vn in vlan_nets]
router_ports = self._ovn_client._plugin.get_ports(
context, {'network_id': vlan_net_ids,
'device_owner': n_const.ROUTER_PORT_OWNERS})
expected_value = ('false' if ovn_conf.is_ovn_distributed_floating_ip()
else 'true')
for rp in router_ports:
lrp_name = utils.ovn_lrouter_port_name(rp['id'])
lrp = self._nb_idl.get_lrouter_port(lrp_name)
if lrp.options.get(
ovn_const.LRP_OPTIONS_RESIDE_REDIR_CH) != expected_value:
opt = {ovn_const.LRP_OPTIONS_RESIDE_REDIR_CH: expected_value}
cmds.append(self._nb_idl.db_set(
'Logical_Router_Port', lrp_name, ('options', opt)))
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

@ -1414,9 +1414,10 @@ class OVNClient(object):
# logical router port is centralized in the chassis hosting the
# distributed gateway port.
# https://github.com/openvswitch/ovs/commit/85706c34d53d4810f54bec1de662392a3c06a996
if (network.get(pnet.NETWORK_TYPE) == const.TYPE_VLAN and
not ovn_conf.is_ovn_distributed_floating_ip()):
options['reside-on-redirect-chassis'] = 'true'
if network.get(pnet.NETWORK_TYPE) == const.TYPE_VLAN:
options[ovn_const.LRP_OPTIONS_RESIDE_REDIR_CH] = (
'false' if ovn_conf.is_ovn_distributed_floating_ip()
else 'true')
is_gw_port = const.DEVICE_OWNER_ROUTER_GW == port.get(
'device_owner')

View File

@ -543,3 +543,49 @@ class TestDBInconsistenciesPeriodics(testlib_api.SqlTestCaseLight,
expected_calls = [mock.call('QoS', qoses1[0].uuid,
('external_ids', external_ids))]
nb_idl.db_set.assert_has_calls(expected_calls)
def _test_check_vlan_distributed_ports(self, opt_value=None):
fake_net0 = {'id': 'net0'}
fake_net1 = {'id': 'net1'}
fake_port0 = {'id': 'port0'}
fake_port1 = {'id': 'port1'}
self.fake_ovn_client._plugin.get_networks.return_value = [
fake_net0, fake_net1]
self.fake_ovn_client._plugin.get_ports.return_value = [
fake_port0, fake_port1]
fake_lrp = fakes.FakeOvsdbRow.create_one_ovsdb_row(
attrs={
'name': 'lrp',
'options': {constants.LRP_OPTIONS_RESIDE_REDIR_CH: opt_value}})
self.fake_ovn_client._nb_idl.get_lrouter_port.return_value = fake_lrp
# Invoke the periodic method, it meant to run only once at startup
# so NeverAgain will be raised at the end
self.assertRaises(periodics.NeverAgain,
self.periodic.check_vlan_distributed_ports)
def test_check_vlan_distributed_ports_expected_value(self):
cfg.CONF.set_override('enable_distributed_floating_ip', 'False',
group='ovn')
self._test_check_vlan_distributed_ports(opt_value='true')
# If the "reside-on-redirect-chassis" option value do match
# the expected value, assert we do not update the database
self.assertFalse(
self.fake_ovn_client._nb_idl.db_set.called)
def test_check_vlan_distributed_ports_non_expected_value(self):
cfg.CONF.set_override('enable_distributed_floating_ip', 'False',
group='ovn')
self._test_check_vlan_distributed_ports(opt_value='false')
# If the "reside-on-redirect-chassis" option value does not match
# the expected value, assert we update the database
opt = {constants.LRP_OPTIONS_RESIDE_REDIR_CH: 'true'}
expected_calls = [
mock.call('Logical_Router_Port', 'lrp-port0', ('options', opt)),
mock.call('Logical_Router_Port', 'lrp-port1', ('options', opt))]
self.fake_ovn_client._nb_idl.db_set.assert_has_calls(
expected_calls)