DVR: Fix binding info for DVR port not found error

Recently we have been seeing an error in neutron associated
with DVR routers, that says 'Binding info for DVR port not
found'.
This error is thrown when the 'get_bound_port_context' is
called when trying to notify_l2pop_port_wiring.
notify_l2pop_port_wiring is intended for router 'HA' ports, so
the get_bound_port_context should be called here only for 'HA'
ports.

This was introduced by a recent refactor in neutron
Icd4cd4e3f735e88299e86468380c5f786e7628fe

Change-Id: I1c636344068518aa26be6c96c598c61b7f0f3563
Closes-Bug: #1702769
This commit is contained in:
Swaminathan Vasudevan 2017-07-06 14:11:50 -07:00 committed by Brian Haley
parent 1a11bc9605
commit 9e9a8a07c3
2 changed files with 56 additions and 6 deletions

View File

@ -302,6 +302,13 @@ class RpcCallbacks(type_tunnel.TunnelRpcCallbackMixin):
'l2population')
if not l2pop_driver:
return
port = ml2_db.get_port(rpc_context, port_id)
if not port:
return
# NOTE: DVR ports are already handled and updated through l2pop
# and so we don't need to update it again here
if port['device_owner'] == n_const.DEVICE_OWNER_DVR_INTERFACE:
return
port_context = plugin.get_bound_port_context(
rpc_context, port_id)
if not port_context:

View File

@ -239,12 +239,19 @@ class TestL2PopulationRpcTestCase(test_plugin.Ml2PluginV2TestCase):
plugin.update_port(self.adminContext, port['id'],
{port_def.RESOURCE_NAME: port})
def _get_first_interface(self, net_id, router_id):
def _get_first_interface(self, net_id, router):
plugin = directory.get_plugin()
device_filter = {'device_id': [router_id],
'device_owner':
[constants.DEVICE_OWNER_HA_REPLICATED_INT]}
return plugin.get_ports(self.adminContext, filters=device_filter)[0]
if router['distributed']:
device_filter = {'device_id': [router['id']],
'device_owner':
[constants.DEVICE_OWNER_DVR_INTERFACE]}
else:
device_filter = {'device_id': [router['id']],
'device_owner':
[constants.DEVICE_OWNER_HA_REPLICATED_INT]}
ports = plugin.get_ports(self.adminContext, filters=device_filter)
if ports:
return ports[0]
def _add_router_interface(self, subnet, router, host):
interface_info = {'subnet_id': subnet['id']}
@ -254,7 +261,7 @@ class TestL2PopulationRpcTestCase(test_plugin.Ml2PluginV2TestCase):
self.adminContext,
{router['id']: n_const.HA_ROUTER_STATE_ACTIVE}, host)
port = self._get_first_interface(subnet['network_id'], router['id'])
port = self._get_first_interface(subnet['network_id'], router)
self.mock_cast.reset_mock()
self.mock_fanout.reset_mock()
@ -268,6 +275,12 @@ class TestL2PopulationRpcTestCase(test_plugin.Ml2PluginV2TestCase):
self._bind_router(router['id'], router['tenant_id'])
return router
def _create_dvr_router(self):
self._setup_l3()
router = self._create_router(distributed=True)
self._bind_router(router['id'], router['tenant_id'])
return router
def _verify_remove_fdb(self, expected, agent_id, device, host=None):
self.mock_fanout.reset_mock()
self.callbacks.update_device_down(self.adminContext, agent_id=host,
@ -339,6 +352,36 @@ class TestL2PopulationRpcTestCase(test_plugin.Ml2PluginV2TestCase):
self.mock_fanout.assert_called_with(
mock.ANY, 'remove_fdb_entries', expected)
def test_ha_agents_with_dvr_rtr_does_not_get_other_fdb(self):
router = self._create_dvr_router()
directory.add_plugin(plugin_constants.L3, self.plugin)
with self.subnet(network=self._network, enable_dhcp=False) as snet:
host_arg = {portbindings.HOST_ID: HOST_4, 'admin_state_up': True}
with self.port(subnet=snet,
device_owner=DEVICE_OWNER_COMPUTE,
arg_list=(portbindings.HOST_ID,),
**host_arg) as port1:
p1 = port1['port']
device1 = 'tap' + p1['id']
self.callbacks.update_device_up(
self.adminContext, agent_id=HOST_4, device=device1)
subnet = snet['subnet']
port = self._add_router_interface(subnet, router, HOST)
self.mock_cast.assert_not_called()
self.mock_fanout.assert_not_called()
self.mock_cast.reset_mock()
self.mock_fanout.reset_mock()
self.callbacks.update_device_up(
self.adminContext, agent_id=HOST_2,
device=port['id'], host=HOST_2)
self.mock_cast.assert_not_called()
self.mock_fanout.assert_not_called()
def test_ha_agents_get_other_fdb(self):
# First network port is added on HOST4, then HA router port is
# added on HOST and HOST2.