# 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.
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
# 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}