Ensure ovn loadbalancer FIPs are centralized upon neutron restarts
When neutron server restarts the mac address for NAT entries related to ovn-lb FIPs gets re-added, distributing the traffic that should be centralized and therefore breaking the connectivity. This happens due to the port being down. This patch is ensuring the MAC entry is only being readded in case the port is UP Closes-Bug: #2042938 Change-Id: I6203009750a4e589eeb808f842cb522d61476179
This commit is contained in:
parent
b1585c52dc
commit
f2a3020cf0
|
@ -1079,7 +1079,7 @@ class OVNMechanismDriver(api.MechanismDriver):
|
|||
# See doc/source/design/ovn_worker.rst for more details.
|
||||
return [worker.MaintenanceWorker()]
|
||||
|
||||
def _update_dnat_entry_if_needed(self, port_id):
|
||||
def _update_dnat_entry_if_needed(self, port_id, up=True):
|
||||
"""Update DNAT entry if using distributed floating ips."""
|
||||
if not self.nb_ovn:
|
||||
self.nb_ovn = self._ovn_client._nb_idl
|
||||
|
@ -1101,13 +1101,14 @@ class OVNMechanismDriver(api.MechanismDriver):
|
|||
nat['external_mac']})).execute()
|
||||
|
||||
if ovn_conf.is_ovn_distributed_floating_ip():
|
||||
mac = nat['external_ids'].get(ovn_const.OVN_FIP_EXT_MAC_KEY)
|
||||
if mac and nat['external_mac'] != mac:
|
||||
LOG.debug("Setting external_mac of port %s to %s",
|
||||
port_id, mac)
|
||||
self.nb_ovn.db_set(
|
||||
'NAT', nat['_uuid'], ('external_mac', mac)).execute(
|
||||
check_error=True)
|
||||
if up:
|
||||
mac = nat['external_ids'].get(ovn_const.OVN_FIP_EXT_MAC_KEY)
|
||||
if mac and nat['external_mac'] != mac:
|
||||
LOG.debug("Setting external_mac of port %s to %s",
|
||||
port_id, mac)
|
||||
self.nb_ovn.db_set(
|
||||
'NAT', nat['_uuid'], ('external_mac', mac)).execute(
|
||||
check_error=True)
|
||||
else:
|
||||
if nat['external_mac']:
|
||||
LOG.debug("Clearing up external_mac of port %s", port_id)
|
||||
|
@ -1170,7 +1171,7 @@ class OVNMechanismDriver(api.MechanismDriver):
|
|||
# to prevent another entity from bypassing the block with its own
|
||||
# port status update.
|
||||
LOG.info("OVN reports status down for port: %s", port_id)
|
||||
self._update_dnat_entry_if_needed(port_id)
|
||||
self._update_dnat_entry_if_needed(port_id, False)
|
||||
admin_context = n_context.get_admin_context()
|
||||
try:
|
||||
db_port = ml2_db.get_port(admin_context, port_id)
|
||||
|
|
|
@ -1123,7 +1123,7 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase):
|
|||
resources.PORT,
|
||||
provisioning_blocks.L2_AGENT_ENTITY
|
||||
)
|
||||
ude.assert_called_once_with(port1['port']['id'])
|
||||
ude.assert_called_once_with(port1['port']['id'], False)
|
||||
|
||||
# If the port does NOT bellong to compute, do not notify Nova
|
||||
# about it's status changes
|
||||
|
@ -1174,7 +1174,7 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase):
|
|||
resources.PORT,
|
||||
provisioning_blocks.L2_AGENT_ENTITY
|
||||
)
|
||||
ude.assert_called_once_with(port1['port']['id'])
|
||||
ude.assert_called_once_with(port1['port']['id'], False)
|
||||
|
||||
def test_bind_port_unsupported_vnic_type(self):
|
||||
fake_port = fakes.FakePort.create_one_port(
|
||||
|
@ -2430,7 +2430,7 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase):
|
|||
self.assertTrue(agent.alive, "Agent of type %s alive=%s" % (
|
||||
agent.agent_type, agent.alive))
|
||||
|
||||
def _test__update_dnat_entry_if_needed(self, dvr=True):
|
||||
def _test__update_dnat_entry_if_needed(self, up=True, dvr=True):
|
||||
if dvr:
|
||||
ovn_conf.cfg.CONF.set_override(
|
||||
'enable_distributed_floating_ip', True, group='ovn')
|
||||
|
@ -2446,25 +2446,33 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase):
|
|||
fake_db_find.execute.return_value = [nat_row]
|
||||
self.nb_ovn.db_find.return_value = fake_db_find
|
||||
|
||||
self.mech_driver._update_dnat_entry_if_needed(port_id)
|
||||
self.mech_driver._update_dnat_entry_if_needed(port_id, up=up)
|
||||
|
||||
if dvr:
|
||||
if up and dvr:
|
||||
# Assert that we are setting the external_mac in the NAT table
|
||||
self.nb_ovn.db_set.assert_called_once_with(
|
||||
'NAT', fake_nat_uuid, ('external_mac', fake_ext_mac_key))
|
||||
self.nb_ovn.db_clear.assert_not_called()
|
||||
else:
|
||||
self.nb_ovn.db_set.assert_not_called()
|
||||
# Assert that we are cleaning the external_mac from the NAT table
|
||||
self.nb_ovn.db_clear.assert_called_once_with(
|
||||
'NAT', fake_nat_uuid, 'external_mac')
|
||||
if dvr:
|
||||
self.nb_ovn.db_set.assert_not_called()
|
||||
else:
|
||||
# Assert that we are cleaning the external_mac from the NAT
|
||||
# table
|
||||
self.nb_ovn.db_clear.assert_called_once_with(
|
||||
'NAT', fake_nat_uuid, 'external_mac')
|
||||
|
||||
def test__update_dnat_entry_if_needed_dvr(self):
|
||||
def test__update_dnat_entry_if_needed_up_dvr(self):
|
||||
self._test__update_dnat_entry_if_needed()
|
||||
|
||||
def test__update_dnat_entry_if_needed_no_dvr(self):
|
||||
def test__update_dnat_entry_if_needed_up_no_dvr(self):
|
||||
self._test__update_dnat_entry_if_needed(dvr=False)
|
||||
|
||||
def test__update_dnat_entry_if_needed_down_dvr(self):
|
||||
self._test__update_dnat_entry_if_needed(up=False)
|
||||
|
||||
def test__update_dnat_entry_if_needed_down_no_dvr(self):
|
||||
self._test__update_dnat_entry_if_needed(up=False, dvr=False)
|
||||
|
||||
@mock.patch('neutron.plugins.ml2.drivers.ovn.mech_driver.ovsdb.'
|
||||
'ovn_client.OVNClient._get_router_ports')
|
||||
def _test_update_network_fragmentation(self, new_mtu, expected_opts, grps):
|
||||
|
|
Loading…
Reference in New Issue