From 69d73630301a9c2d55781920c47b3c29a2cd0fc4 Mon Sep 17 00:00:00 2001 From: Andreas Scheuring Date: Mon, 29 Aug 2016 13:31:17 +0200 Subject: [PATCH] ml2: Add original port to context on _bind_port During portbinding a new PortContext with the binding information for the new host gets created. This patch adds the original port to the newly created context. This has the following effects - When the port was not bound before, context.original will be set set to None on portbinding. - When the port was bound before (also if binding failed before) context.original is set to this port dict on portbinding. This happens mostly in the following scenarios: - Nova triggers a reschedule of an instance Nova reschedules an instance to another host, after spawning an instance on the first host failed for some reason. In this case, context.original is set to the port with the binding information as it was on the failed host. - Live Migration The port is now available on another host. context.original is set to the port and binding information of the source host. Context.original can now be used in mechanism drivers that need to be migration aware. This is the case for the macvtap mechanism driver. The corresponding functionality will be added with patch [1]. [1] https://review.openstack.org/#/c/361301 Partial-Bug: #1550400 Change-Id: I2b60243366505f6e6e4c716d627255a56a4ba486 --- neutron/plugins/ml2/plugin.py | 3 ++- neutron/tests/unit/plugins/ml2/test_plugin.py | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/neutron/plugins/ml2/plugin.py b/neutron/plugins/ml2/plugin.py index 0547f6e6362..d9b6977268d 100644 --- a/neutron/plugins/ml2/plugin.py +++ b/neutron/plugins/ml2/plugin.py @@ -421,7 +421,8 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2, self._update_port_dict_binding(port, new_binding) new_context = driver_context.PortContext( self, orig_context._plugin_context, port, - orig_context.network.current, new_binding, None) + orig_context.network.current, new_binding, None, + original_port=orig_context.original) # Attempt to bind the port and return the context with the # result. diff --git a/neutron/tests/unit/plugins/ml2/test_plugin.py b/neutron/tests/unit/plugins/ml2/test_plugin.py index 96367af4587..9d73ea9b7d8 100644 --- a/neutron/tests/unit/plugins/ml2/test_plugin.py +++ b/neutron/tests/unit/plugins/ml2/test_plugin.py @@ -1707,6 +1707,20 @@ class TestMl2PortBinding(Ml2PluginV2TestCase, self.context, 'foo_port_id', {'port': port}) self.assertFalse(mock_dist.called) + def test__bind_port_original_port_set(self): + plugin = directory.get_plugin() + plugin.mechanism_manager = mock.Mock() + mock_port = {'id': 'port_id'} + context = mock.Mock() + context.network.current = {'id': 'net_id'} + context.original = mock_port + with mock.patch.object(plugin, '_update_port_dict_binding'), \ + mock.patch.object(segments_db, 'get_network_segments', + return_value=[]): + new_context = plugin._bind_port(context) + self.assertEqual(mock_port, new_context.original) + self.assertFalse(new_context == context) + class TestMl2PortBindingNoSG(TestMl2PortBinding): HAS_PORT_FILTER = False