diff --git a/neutron/plugins/ml2/drivers/ovn/mech_driver/mech_driver.py b/neutron/plugins/ml2/drivers/ovn/mech_driver/mech_driver.py index 3d69a369842..5378c477bc1 100644 --- a/neutron/plugins/ml2/drivers/ovn/mech_driver/mech_driver.py +++ b/neutron/plugins/ml2/drivers/ovn/mech_driver/mech_driver.py @@ -860,9 +860,6 @@ class OVNMechanismDriver(api.MechanismDriver): def _update_dnat_entry_if_needed(self, port_id, up=True): """Update DNAT entry if using distributed floating ips.""" - if not ovn_conf.is_ovn_distributed_floating_ip(): - return - if not self._nb_ovn: self._nb_ovn = self._ovn_client._nb_idl @@ -882,17 +879,20 @@ class OVNMechanismDriver(api.MechanismDriver): {ovn_const.OVN_FIP_EXT_MAC_KEY: nat['external_mac']})).execute() - if up: + if up and ovn_conf.is_ovn_distributed_floating_ip(): mac = nat['external_ids'][ovn_const.OVN_FIP_EXT_MAC_KEY] - 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 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: - LOG.debug("Clearing up external_mac of port %s", port_id) - self._nb_ovn.db_clear( - 'NAT', nat['_uuid'], 'external_mac').execute(check_error=True) + if nat['external_mac']: + LOG.debug("Clearing up external_mac of port %s", port_id) + self._nb_ovn.db_clear( + 'NAT', nat['_uuid'], 'external_mac').execute( + check_error=True) def _should_notify_nova(self, db_port): # NOTE(twilson) It is possible for a test to override a config option diff --git a/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovn_client.py b/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovn_client.py index 875b3d305d7..453a432156c 100644 --- a/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovn_client.py +++ b/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovn_client.py @@ -616,6 +616,8 @@ class OVNClient(object): admin_context = n_context.get_admin_context() fip_db = self._l3_plugin._get_floatingip( admin_context, floatingip['id']) + port_db = self._plugin.get_port( + admin_context, fip_db['floating_port_id']) gw_lrouter_name = utils.ovn_name(router_id) # TODO(chandrav): Since the floating ip port is not @@ -633,18 +635,16 @@ class OVNClient(object): ovn_const.OVN_REV_NUM_EXT_ID_KEY: str(utils.get_revision_number( floatingip, ovn_const.TYPE_FLOATINGIPS)), ovn_const.OVN_FIP_PORT_EXT_ID_KEY: floatingip['port_id'], - ovn_const.OVN_ROUTER_NAME_EXT_ID_KEY: gw_lrouter_name} + ovn_const.OVN_ROUTER_NAME_EXT_ID_KEY: gw_lrouter_name, + ovn_const.OVN_FIP_EXT_MAC_KEY: port_db['mac_address']} columns = {'type': 'dnat_and_snat', 'logical_ip': floatingip['fixed_ip_address'], - 'external_ip': floatingip['floating_ip_address']} + 'external_ip': floatingip['floating_ip_address'], + 'logical_port': floatingip['port_id']} if ovn_conf.is_ovn_distributed_floating_ip(): - port = self._plugin.get_port( - admin_context, fip_db['floating_port_id']) - columns['logical_port'] = floatingip['port_id'] - ext_ids[ovn_const.OVN_FIP_EXT_MAC_KEY] = port['mac_address'] if self._nb_idl.lsp_get_up(floatingip['port_id']).execute(): - columns['external_mac'] = port['mac_address'] + columns['external_mac'] = port_db['mac_address'] # TODO(dalvarez): remove this check once the minimum OVS required # version contains the column (when OVS 2.8.2 is released). diff --git a/neutron/tests/unit/plugins/ml2/drivers/ovn/mech_driver/test_mech_driver.py b/neutron/tests/unit/plugins/ml2/drivers/ovn/mech_driver/test_mech_driver.py index c319db2f6e6..b2b03a58c42 100644 --- a/neutron/tests/unit/plugins/ml2/drivers/ovn/mech_driver/test_mech_driver.py +++ b/neutron/tests/unit/plugins/ml2/drivers/ovn/mech_driver/test_mech_driver.py @@ -1596,7 +1596,8 @@ class TestOVNMechanismDriver(test_plugin.Ml2PluginV2TestCase): fake_nat_uuid = uuidutils.generate_uuid() nat_row = fakes.FakeOvsdbRow.create_one_ovsdb_row( attrs={'_uuid': fake_nat_uuid, 'external_ids': { - ovn_const.OVN_FIP_EXT_MAC_KEY: fake_ext_mac_key}}) + ovn_const.OVN_FIP_EXT_MAC_KEY: fake_ext_mac_key}, + 'external_mac': 'aa:aa:aa:aa:aa:aa'}) fake_db_find = mock.Mock() fake_db_find.execute.return_value = [nat_row] diff --git a/neutron/tests/unit/services/ovn_l3/test_plugin.py b/neutron/tests/unit/services/ovn_l3/test_plugin.py index 14b23eb35d2..690c2667a61 100644 --- a/neutron/tests/unit/services/ovn_l3/test_plugin.py +++ b/neutron/tests/unit/services/ovn_l3/test_plugin.py @@ -893,12 +893,14 @@ class TestOVNL3RouterPlugin(test_mech_driver.Ml2PluginV2TestCase): ovn_const.OVN_FIP_PORT_EXT_ID_KEY: self.fake_floating_ip['port_id'], ovn_const.OVN_ROUTER_NAME_EXT_ID_KEY: utils.ovn_name( - self.fake_floating_ip['router_id'])} + self.fake_floating_ip['router_id']), + ovn_const.OVN_FIP_EXT_MAC_KEY: 'aa:aa:aa:aa:aa:aa'} self.l3_inst._ovn.add_nat_rule_in_lrouter.assert_called_once_with( 'neutron-router-id', type='dnat_and_snat', logical_ip='10.0.0.10', external_ip='192.168.0.10', + logical_port='port_id', external_ids=expected_ext_ids) self.l3_inst._ovn.delete_lswitch_port.assert_called_once_with( 'fip-port-id', 'neutron-fip-net-id') @@ -964,12 +966,14 @@ class TestOVNL3RouterPlugin(test_mech_driver.Ml2PluginV2TestCase): ovn_const.OVN_FIP_PORT_EXT_ID_KEY: self.fake_floating_ip['port_id'], ovn_const.OVN_ROUTER_NAME_EXT_ID_KEY: utils.ovn_name( - self.fake_floating_ip['router_id'])} + self.fake_floating_ip['router_id']), + ovn_const.OVN_FIP_EXT_MAC_KEY: 'aa:aa:aa:aa:aa:aa'} self.l3_inst._ovn.add_nat_rule_in_lrouter.assert_called_once_with( 'neutron-router-id', type='dnat_and_snat', logical_ip='10.0.0.10', external_ip='192.168.0.10', + logical_port='port_id', external_ids=expected_ext_ids) self.l3_inst._ovn.delete_lswitch_port.assert_called_once_with( 'fip-port-id', 'neutron-fip-net-id') @@ -988,12 +992,14 @@ class TestOVNL3RouterPlugin(test_mech_driver.Ml2PluginV2TestCase): ovn_const.OVN_FIP_PORT_EXT_ID_KEY: self.fake_floating_ip['port_id'], ovn_const.OVN_ROUTER_NAME_EXT_ID_KEY: utils.ovn_name( - self.fake_floating_ip['router_id'])} + self.fake_floating_ip['router_id']), + ovn_const.OVN_FIP_EXT_MAC_KEY: 'aa:aa:aa:aa:aa:aa'} self.l3_inst._ovn.add_nat_rule_in_lrouter.assert_called_once_with( 'neutron-router-id', type='dnat_and_snat', logical_ip='10.0.0.10', external_ip='192.168.0.10', + logical_port='port_id', external_ids=expected_ext_ids) self.l3_inst._ovn.delete_lswitch_port.assert_called_once_with( 'fip-port-id', 'neutron-fip-net-id') @@ -1143,12 +1149,14 @@ class TestOVNL3RouterPlugin(test_mech_driver.Ml2PluginV2TestCase): ovn_const.OVN_FIP_PORT_EXT_ID_KEY: self.fake_floating_ip_new['port_id'], ovn_const.OVN_ROUTER_NAME_EXT_ID_KEY: utils.ovn_name( - self.fake_floating_ip_new['router_id'])} + self.fake_floating_ip_new['router_id']), + ovn_const.OVN_FIP_EXT_MAC_KEY: 'aa:aa:aa:aa:aa:aa'} self.l3_inst._ovn.add_nat_rule_in_lrouter.assert_called_once_with( 'neutron-new-router-id', type='dnat_and_snat', logical_ip='10.10.10.10', external_ip='192.168.0.10', + logical_port='new-port_id', external_ids=expected_ext_ids) @mock.patch('neutron.db.extraroute_db.ExtraRoute_dbonly_mixin.' @@ -1165,12 +1173,14 @@ class TestOVNL3RouterPlugin(test_mech_driver.Ml2PluginV2TestCase): ovn_const.OVN_FIP_PORT_EXT_ID_KEY: self.fake_floating_ip_new['port_id'], ovn_const.OVN_ROUTER_NAME_EXT_ID_KEY: utils.ovn_name( - self.fake_floating_ip_new['router_id'])} + self.fake_floating_ip_new['router_id']), + ovn_const.OVN_FIP_EXT_MAC_KEY: 'aa:aa:aa:aa:aa:aa'} self.l3_inst._ovn.add_nat_rule_in_lrouter.assert_called_once_with( 'neutron-new-router-id', type='dnat_and_snat', logical_ip='10.10.10.10', external_ip='192.168.0.10', + logical_port='new-port_id', external_ids=expected_ext_ids) @mock.patch('neutron.db.db_base_plugin_v2.NeutronDbPluginV2.get_network') @@ -1226,12 +1236,14 @@ class TestOVNL3RouterPlugin(test_mech_driver.Ml2PluginV2TestCase): ovn_const.OVN_FIP_PORT_EXT_ID_KEY: self.fake_floating_ip_new['port_id'], ovn_const.OVN_ROUTER_NAME_EXT_ID_KEY: utils.ovn_name( - self.fake_floating_ip_new['router_id'])} + self.fake_floating_ip_new['router_id']), + ovn_const.OVN_FIP_EXT_MAC_KEY: 'aa:aa:aa:aa:aa:aa'} self.l3_inst._ovn.add_nat_rule_in_lrouter.assert_called_once_with( 'neutron-new-router-id', type='dnat_and_snat', logical_ip='10.10.10.10', external_ip='192.168.0.10', + logical_port='foo', external_ids=expected_ext_ids) @mock.patch('neutron.db.extraroute_db.ExtraRoute_dbonly_mixin.' @@ -1257,12 +1269,14 @@ class TestOVNL3RouterPlugin(test_mech_driver.Ml2PluginV2TestCase): ovn_const.OVN_FIP_PORT_EXT_ID_KEY: self.fake_floating_ip_new['port_id'], ovn_const.OVN_ROUTER_NAME_EXT_ID_KEY: utils.ovn_name( - self.fake_floating_ip_new['router_id'])} + self.fake_floating_ip_new['router_id']), + ovn_const.OVN_FIP_EXT_MAC_KEY: 'aa:aa:aa:aa:aa:aa'} self.l3_inst._ovn.add_nat_rule_in_lrouter.assert_called_once_with( 'neutron-new-router-id', type='dnat_and_snat', logical_ip='10.10.10.10', external_ip='192.168.0.10', + logical_port='port_id', external_ids=expected_ext_ids) @mock.patch('neutron.db.l3_db.L3_NAT_dbonly_mixin.get_floatingips')