From 67e45d324af39a66fbd4ad175e410407b2720e68 Mon Sep 17 00:00:00 2001 From: Yalei Wang Date: Thu, 8 Jan 2015 10:46:08 +0800 Subject: [PATCH] Add the rebinding chance in _bind_port_if_needed Make function _bind_port_if_needed to bind at least one time when the port's binding status passed in is already in binding_failed. Change-Id: I823ff5ca66833cdca459f13ab28f5075ae03ded3 Closes-Bug: #1399249 --- neutron/plugins/ml2/plugin.py | 14 ++++--- neutron/tests/unit/ml2/test_ml2_plugin.py | 48 +++++++++++++++++++++++ 2 files changed, 57 insertions(+), 5 deletions(-) diff --git a/neutron/plugins/ml2/plugin.py b/neutron/plugins/ml2/plugin.py index a303fac35..66a43e1b7 100644 --- a/neutron/plugins/ml2/plugin.py +++ b/neutron/plugins/ml2/plugin.py @@ -260,7 +260,8 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2, # First, determine whether it is necessary and possible to # bind the port. binding = context._binding - if (binding.vif_type != portbindings.VIF_TYPE_UNBOUND + if (binding.vif_type not in [portbindings.VIF_TYPE_UNBOUND, + portbindings.VIF_TYPE_BINDING_FAILED] or not binding.host): # We either don't need to bind the port, or can't, so # notify if needed and return. @@ -298,12 +299,15 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2, LOG.debug("Port %s has been deleted concurrently", port_id) return context + + context = new_context + + if (context._binding.vif_type == + portbindings.VIF_TYPE_BINDING_FAILED): + return context # Need to notify if we succeed and our results were # committed. - if did_commit and (new_context._binding.vif_type != - portbindings.VIF_TYPE_BINDING_FAILED): - need_notify = True - context = new_context + need_notify |= did_commit def _bind_port(self, orig_context): # Construct a new PortContext from the one from the previous diff --git a/neutron/tests/unit/ml2/test_ml2_plugin.py b/neutron/tests/unit/ml2/test_ml2_plugin.py index f05893d22..9cc046988 100644 --- a/neutron/tests/unit/ml2/test_ml2_plugin.py +++ b/neutron/tests/unit/ml2/test_ml2_plugin.py @@ -457,6 +457,54 @@ class TestMl2PortBinding(Ml2PluginV2TestCase, # should have returned before calling _make_port_dict self.assertFalse(mpd_mock.mock_calls) + def test_bind_port_if_needed(self): + # create a port and set its vif_type to binding_failed + 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' + + binding['vif_type'] = portbindings.VIF_TYPE_BINDING_FAILED + mech_context = driver_context.PortContext( + plugin, self.context, port['port'], + plugin.get_network(self.context, port['port']['network_id']), + binding) + + # test when _commit_port_binding return binding_failed + self._test_bind_port_if_needed(plugin, mech_context, False) + # test when _commit_port_binding NOT return binding_failed + self._test_bind_port_if_needed(plugin, mech_context, True) + + def _test_bind_port_if_needed(self, plugin, mech_context, commit_fail): + # mock _commit_port_binding + commit_context = mock.MagicMock() + if commit_fail: + commit_context._binding.vif_type = ( + portbindings.VIF_TYPE_BINDING_FAILED) + else: + commit_context._binding.vif_type = portbindings.VIF_TYPE_OVS + + 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._bind_port'), + mock.patch('neutron.plugins.ml2.plugin.' + 'Ml2Plugin._commit_port_binding', + return_value=(commit_context, False)) + ) as (glpab_mock, bd_mock, commit_mock): + bound_context = plugin._bind_port_if_needed(mech_context) + # check _bind_port be called + self.assertTrue(bd_mock.called) + + if commit_fail: + self.assertEqual(portbindings.VIF_TYPE_BINDING_FAILED, + bound_context._binding.vif_type) + else: + self.assertEqual(portbindings.VIF_TYPE_OVS, + bound_context._binding.vif_type) + def test_port_binding_profile_not_changed(self): profile = {'e': 5} profile_arg = {portbindings.PROFILE: profile} -- 2.45.2