diff --git a/neutron/plugins/ml2/drivers/l2pop/mech_driver.py b/neutron/plugins/ml2/drivers/l2pop/mech_driver.py index 559cc083872..edd5983f828 100644 --- a/neutron/plugins/ml2/drivers/l2pop/mech_driver.py +++ b/neutron/plugins/ml2/drivers/l2pop/mech_driver.py @@ -73,7 +73,8 @@ class L2populationMechanismDriver(api.MechanismDriver): agent_host = context.host fdb_entries = self._get_agent_fdb( context, context.bottom_bound_segment, port, agent_host) - if port['device_owner'] in l2pop_db.HA_ROUTER_PORTS and fdb_entries: + if fdb_entries and l3_hamode_db.is_ha_router_port( + context, port['device_owner'], port['device_id']): session = db_api.get_reader_session() network_id = port['network_id'] other_fdb_ports = self._get_ha_port_agents_fdb( diff --git a/neutron/tests/unit/plugins/ml2/drivers/l2pop/test_mech_driver.py b/neutron/tests/unit/plugins/ml2/drivers/l2pop/test_mech_driver.py index 3ad213ae7c4..f14e5ea2ad7 100644 --- a/neutron/tests/unit/plugins/ml2/drivers/l2pop/test_mech_driver.py +++ b/neutron/tests/unit/plugins/ml2/drivers/l2pop/test_mech_driver.py @@ -30,6 +30,7 @@ from neutron.db import l3_agentschedulers_db from neutron.db import l3_hamode_db from neutron.extensions import portbindings from neutron.extensions import providernet as pnet +from neutron.plugins.ml2 import db as ml2_db from neutron.plugins.ml2 import driver_context from neutron.plugins.ml2.drivers.l2pop import db as l2pop_db from neutron.plugins.ml2.drivers.l2pop import mech_driver as l2pop_mech_driver @@ -1120,6 +1121,44 @@ class TestL2PopulationRpcTestCase(test_plugin.Ml2PluginV2TestCase): # are raised. l2pop_mech.delete_port_postcommit(port_context) + def test_delete_dvr_snat_port_fdb_entries(self): + l2pop_mech = l2pop_mech_driver.L2populationMechanismDriver() + l2pop_mech.initialize() + + self._setup_l3() + + with self.subnet(network=self._network, enable_dhcp=False) as snet: + host_arg = {portbindings.HOST_ID: HOST, 'admin_state_up': True} + with self.port(subnet=snet, + device_owner=constants.DEVICE_OWNER_ROUTER_SNAT, + arg_list=(portbindings.HOST_ID,), + **host_arg) as p: + device = 'tap' + p['port']['id'] + self.callbacks.update_device_up(self.adminContext, + agent_id=HOST, device=device) + dvr_snat_port = ml2_db.get_port(self.adminContext, + p['port']['id']) + self.mock_fanout.reset_mock() + + context = mock.Mock() + context.current = dvr_snat_port + context.host = HOST + segment = {'network_type': 'vxlan', 'segmentation_id': 1} + context.bottom_bound_segment = segment + + expected = {self._network['network']['id']: + {'segment_id': segment['segmentation_id'], + 'network_type': segment['network_type'], + 'ports': {'20.0.0.1': + [l2pop_rpc.PortInfo( + mac_address=p['port']['mac_address'], + ip_address=p['port']['fixed_ips'][0] + ['ip_address'])]}}} + + l2pop_mech.delete_port_postcommit(context) + self.mock_fanout.assert_called_with( + mock.ANY, 'remove_fdb_entries', expected) + def test_fixed_ips_change_unbound_port_no_rpc(self): l2pop_mech = l2pop_mech_driver.L2populationMechanismDriver() l2pop_mech.initialize()