From: Kevin Benton Date: Sun, 6 Jul 2014 07:00:23 +0000 (-0700) Subject: Return a tuple of None's instead of one None X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=a84a8a5d83f545d0c00b7a83ad91b52dc31c1194;p=openstack-build%2Fneutron-build.git Return a tuple of None's instead of one None The expected return value of _commit_port_binding is something that can be unpacked into two values. This changes the condition where a concurrent delete was detected to return a 2-tuple of None's instead of a bare None to prevent an iterable error. Closes-Bug: #1342880 Change-Id: I9d3a51eab33819ffda6a65a00c3b5d1006a3577e --- diff --git a/neutron/plugins/ml2/plugin.py b/neutron/plugins/ml2/plugin.py index 0eb7b809e..e3d070b3d 100644 --- a/neutron/plugins/ml2/plugin.py +++ b/neutron/plugins/ml2/plugin.py @@ -356,7 +356,7 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2, port_id) if not port_db: # The port has been deleted concurrently. - return + return (None, None) oport = self._make_port_dict(port_db) port = self._make_port_dict(port_db) network = self.get_network(plugin_context, port['network_id']) diff --git a/neutron/tests/unit/ml2/test_ml2_plugin.py b/neutron/tests/unit/ml2/test_ml2_plugin.py index 929d5dbd2..dbe93f456 100644 --- a/neutron/tests/unit/ml2/test_ml2_plugin.py +++ b/neutron/tests/unit/ml2/test_ml2_plugin.py @@ -28,7 +28,9 @@ from neutron import manager from neutron.plugins.common import constants as service_constants from neutron.plugins.ml2.common import exceptions as ml2_exc from neutron.plugins.ml2 import config +from neutron.plugins.ml2 import db as ml2_db from neutron.plugins.ml2 import driver_api +from neutron.plugins.ml2 import driver_context from neutron.plugins.ml2 import plugin as ml2_plugin from neutron.tests.unit import _test_extension_portbindings as test_bindings from neutron.tests.unit.ml2.drivers import mechanism_logger as mech_logger @@ -225,6 +227,29 @@ class TestMl2PortBinding(Ml2PluginV2TestCase, port = self._show('ports', port_id)['port'] self._check_port_binding_profile(port) + def test_return_on_concurrent_delete_and_binding(self): + # create a port and delete it so we have an expired mechanism context + with self.port() as port: + plugin = manager.NeutronManager.get_plugin() + binding = ml2_db.get_locked_port_and_binding(self.context.session, + port['port']['id'])[1] + binding['host'] = 'test' + mech_context = driver_context.PortContext( + plugin, self.context, port['port'], + plugin.get_network(self.context, port['port']['network_id']), + binding) + with contextlib.nested( + mock.patch('neutron.plugins.ml2.plugin.' + 'db.get_locked_port_and_binding', + return_value=(None, None)), + mock.patch('neutron.plugins.ml2.plugin.Ml2Plugin._make_port_dict') + ) as (glpab_mock, mpd_mock): + plugin._bind_port_if_needed(mech_context) + # called during deletion to get port + self.assertTrue(glpab_mock.mock_calls) + # should have returned before calling _make_port_dict + self.assertFalse(mpd_mock.mock_calls) + class TestMl2PortBindingNoSG(TestMl2PortBinding): HAS_PORT_FILTER = False