From b025ccff2c7320caecfc005cfcbc3f4dfadfa505 Mon Sep 17 00:00:00 2001 From: armando-migliaccio Date: Wed, 13 Aug 2014 11:39:07 -0700 Subject: [PATCH] Fix PortNotFound error during update_device_up for DVR An agent's request to update the ARP entry for a VM port may come after a deletion request has been processed, resulting in a PortNotFound exception being raised. This patch takes care of this condition. A test has been added, which required a minor refactoring of the test case class, in order to accommodate the use of side effects for the objects being mocked. Closes-bug: #1356120 Change-Id: I40d635bcf47c683663cb4dedf20323902dff2c7f --- neutron/plugins/ml2/rpc.py | 6 +++- neutron/tests/unit/ml2/test_rpcapi.py | 43 +++++++++++++++++---------- 2 files changed, 32 insertions(+), 17 deletions(-) diff --git a/neutron/plugins/ml2/rpc.py b/neutron/plugins/ml2/rpc.py index ae447fa8e..9dcf2c4ea 100644 --- a/neutron/plugins/ml2/rpc.py +++ b/neutron/plugins/ml2/rpc.py @@ -16,6 +16,7 @@ from neutron.agent import securitygroups_rpc as sg_rpc from neutron.api.rpc.handlers import dvr_rpc from neutron.common import constants as q_const +from neutron.common import exceptions from neutron.common import rpc as n_rpc from neutron.common import topics from neutron.common import utils @@ -194,7 +195,10 @@ class RpcCallbacks(n_rpc.RpcCallback, if (l3plugin and utils.is_extension_supported(l3plugin, q_const.L3_DISTRIBUTED_EXT_ALIAS)): - l3plugin.dvr_vmarp_table_update(rpc_context, port_id, "add") + try: + l3plugin.dvr_vmarp_table_update(rpc_context, port_id, "add") + except exceptions.PortNotFound: + LOG.debug('Port %s not found during ARP update', port_id) def get_dvr_mac_address_by_host(self, rpc_context, **kwargs): host = kwargs.get('host') diff --git a/neutron/tests/unit/ml2/test_rpcapi.py b/neutron/tests/unit/ml2/test_rpcapi.py index 357312c16..71d80d040 100644 --- a/neutron/tests/unit/ml2/test_rpcapi.py +++ b/neutron/tests/unit/ml2/test_rpcapi.py @@ -20,6 +20,7 @@ Unit Tests for ml2 rpc import mock from neutron.agent import rpc as agent_rpc +from neutron.common import exceptions from neutron.common import rpc as n_rpc from neutron.common import topics from neutron.openstack.common import context @@ -28,41 +29,51 @@ from neutron.plugins.ml2 import rpc as plugin_rpc from neutron.tests import base -class RpcCallbacks(base.BaseTestCase): +class RpcCallbacksTestCase(base.BaseTestCase): def setUp(self): - super(RpcCallbacks, self).setUp() + super(RpcCallbacksTestCase, self).setUp() self.callbacks = plugin_rpc.RpcCallbacks(mock.Mock(), mock.Mock()) + self.manager = mock.patch.object( + plugin_rpc.manager, 'NeutronManager').start() + self.l3plugin = mock.Mock() + self.manager.get_service_plugins.return_value = { + 'L3_ROUTER_NAT': self.l3plugin + } def _test_update_device_up(self, extensions, kwargs): - with mock.patch.object(plugin_rpc.manager, 'NeutronManager') as mgr: - with mock.patch.object(self.callbacks, '_device_to_port_id'): - mock_l3plugin = mock.Mock() - mgr.get_service_plugins.return_value = { - 'L3_ROUTER_NAT': mock_l3plugin - } - type(mock_l3plugin).supported_extension_aliases = ( - mock.PropertyMock(return_value=extensions)) - self.callbacks.update_device_up(mock.ANY, **kwargs) - return mock_l3plugin + with mock.patch.object(self.callbacks, '_device_to_port_id'): + type(self.l3plugin).supported_extension_aliases = ( + mock.PropertyMock(return_value=extensions)) + self.callbacks.update_device_up(mock.ANY, **kwargs) def test_update_device_up_without_dvr(self): kwargs = { 'agent_id': 'foo_agent', 'device': 'foo_device' } - l3plugin = self._test_update_device_up(['router'], kwargs) - self.assertFalse(l3plugin.dvr_vmarp_table_update.call_count) + self._test_update_device_up(['router'], kwargs) + self.assertFalse(self.l3plugin.dvr_vmarp_table_update.call_count) def test_update_device_up_with_dvr(self): kwargs = { 'agent_id': 'foo_agent', 'device': 'foo_device' } - l3plugin = self._test_update_device_up(['router', 'dvr'], kwargs) - l3plugin.dvr_vmarp_table_update.assert_called_once_with( + self._test_update_device_up(['router', 'dvr'], kwargs) + self.l3plugin.dvr_vmarp_table_update.assert_called_once_with( mock.ANY, mock.ANY, 'add') + def test_update_device_up_with_dvr_when_port_not_found(self): + kwargs = { + 'agent_id': 'foo_agent', + 'device': 'foo_device' + } + self.l3plugin.dvr_vmarp_table_update.side_effect = ( + exceptions.PortNotFound(port_id='foo_port_id')) + self._test_update_device_up(['router', 'dvr'], kwargs) + self.assertTrue(self.l3plugin.dvr_vmarp_table_update.call_count) + class RpcApiTestCase(base.BaseTestCase): -- 2.45.2