From 8b3b8e5657ffe0f12e1ccfbe6d978e62a2bfdc89 Mon Sep 17 00:00:00 2001 From: Steven Webster Date: Mon, 12 Jun 2017 17:10:03 -0400 Subject: [PATCH] Fix instance evacuation with PCI devices update_port_binding_for_instance() now checks that a valid migration object exists as a parameter before any mapping between old/new PCI devices can occur. A migration should be present in the case of a cold migration, resize, or evacuation. An evacuation (being a special case of a rebuild) however, will not pass a migration to update_port_binding_for_instance, as it is called directly from setup_instance_network(). This calling function does not currently take a migration parameter, even though one will certainly exist for an evacuation. This commit adds an optional migration parameter to setup_instance_network_on_host() and passes any migration object to the port update routine. Closes-Bug: #1703629 Related-Bug: #1677621 Related-Bug: #1630698 Change-Id: I4e394c8d275995eac4b049a7b1329ea90f2394be (cherry picked from commit b930336854bffec1bb81b6d67079a4df59e0af19) (cherry picked from commit b9c1a58dd033fa8feeb1175956d57dc90aa55acd) --- nova/compute/manager.py | 8 +++++--- nova/network/api.py | 3 ++- nova/network/base_api.py | 5 ++++- nova/network/neutronv2/api.py | 6 ++++-- nova/tests/unit/compute/test_compute.py | 2 +- 5 files changed, 16 insertions(+), 8 deletions(-) diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 0b68389b8b50..696f0da010c2 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -2780,7 +2780,8 @@ class ComputeManager(manager.Manager): self._do_rebuild_instance_with_claim( claim_ctxt, context, instance, orig_image_ref, image_ref, injected_files, new_pass, orig_sys_metadata, - bdms, recreate, on_shared_storage, preserve_ephemeral) + bdms, recreate, on_shared_storage, preserve_ephemeral, + migration) except exception.ComputeResourcesUnavailable as e: LOG.debug("Could not rebuild instance on this host, not " "enough resources available.", instance=instance) @@ -2836,7 +2837,8 @@ class ComputeManager(manager.Manager): def _do_rebuild_instance(self, context, instance, orig_image_ref, image_ref, injected_files, new_pass, orig_sys_metadata, bdms, recreate, - on_shared_storage, preserve_ephemeral): + on_shared_storage, preserve_ephemeral, + migration): orig_vm_state = instance.vm_state if recreate: @@ -2901,7 +2903,7 @@ class ComputeManager(manager.Manager): # TODO(cfriesen): this network_api call and the one above # are so similar, we should really try to unify them. self.network_api.setup_instance_network_on_host( - context, instance, self.host) + context, instance, self.host, migration) network_info = compute_utils.get_nw_info_for_instance(instance) if bdms is None: diff --git a/nova/network/api.py b/nova/network/api.py index c7d6827a69ce..614a99d46803 100644 --- a/nova/network/api.py +++ b/nova/network/api.py @@ -525,7 +525,8 @@ class API(base_api.NetworkAPI): self.network_rpcapi.migrate_instance_finish(context, **args) - def setup_instance_network_on_host(self, context, instance, host): + def setup_instance_network_on_host(self, context, instance, host, + migration=None): """Setup network for specified instance on host.""" self.migrate_instance_finish(context, instance, {'source_compute': None, diff --git a/nova/network/base_api.py b/nova/network/base_api.py index b9305f36a04c..3b6251ceaa48 100644 --- a/nova/network/base_api.py +++ b/nova/network/base_api.py @@ -338,12 +338,15 @@ class NetworkAPI(base.Base): """Finish migrating the network of an instance.""" raise NotImplementedError() - def setup_instance_network_on_host(self, context, instance, host): + def setup_instance_network_on_host(self, context, instance, host, + migration=None): """Setup network for specified instance on host. :param context: The request context. :param instance: nova.objects.instance.Instance object. :param host: The host which network should be setup for instance. + :param migration: The migration object if the instance is being + tracked with a migration. """ raise NotImplementedError() diff --git a/nova/network/neutronv2/api.py b/nova/network/neutronv2/api.py index e41415f02b0f..3250c93d70a1 100644 --- a/nova/network/neutronv2/api.py +++ b/nova/network/neutronv2/api.py @@ -2377,9 +2377,11 @@ class API(base_api.NetworkAPI): """Create a private DNS domain with optional nova project.""" raise NotImplementedError() - def setup_instance_network_on_host(self, context, instance, host): + def setup_instance_network_on_host(self, context, instance, host, + migration=None): """Setup network for specified instance on host.""" - self._update_port_binding_for_instance(context, instance, host) + self._update_port_binding_for_instance(context, instance, host, + migration) def cleanup_instance_network_on_host(self, context, instance, host): """Cleanup network for specified instance on host.""" diff --git a/nova/tests/unit/compute/test_compute.py b/nova/tests/unit/compute/test_compute.py index 05f02e02f4cb..fa53f3e5dc70 100644 --- a/nova/tests/unit/compute/test_compute.py +++ b/nova/tests/unit/compute/test_compute.py @@ -11706,7 +11706,7 @@ class EvacuateHostTestCase(BaseTestCase): mock_setup_networks_on_host.assert_called_once_with( ctxt, self.inst, self.inst.host) mock_setup_instance_network_on_host.assert_called_once_with( - ctxt, self.inst, self.inst.host) + ctxt, self.inst, self.inst.host, migration) _test_rebuild()