diff options
author | Zuul <zuul@review.opendev.org> | 2022-12-20 20:16:47 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2022-12-20 20:16:47 +0000 |
commit | e811ca06beab3cc7544f74b6e4b8749404e6b121 (patch) | |
tree | a0b4e100b0943aaa9431940adaa16f9bd1387fd0 | |
parent | 96f0245ce8b9ddbdd92bfe54206b4187ff79aeb2 (diff) | |
parent | d5506014837097261231b205e9b3acbfa503b354 (diff) | |
download | nova-e811ca06beab3cc7544f74b6e4b8749404e6b121.tar.gz |
Merge "Set instance host and drop migration under lock" into stable/train
-rw-r--r-- | nova/compute/manager.py | 18 | ||||
-rw-r--r-- | nova/compute/resource_tracker.py | 18 | ||||
-rw-r--r-- | nova/tests/functional/regressions/test_bug_1896463.py | 11 | ||||
-rw-r--r-- | nova/tests/unit/compute/test_compute_mgr.py | 30 |
4 files changed, 40 insertions, 37 deletions
diff --git a/nova/compute/manager.py b/nova/compute/manager.py index d29b58534b..5027362c9b 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -3479,19 +3479,11 @@ class ComputeManager(manager.Manager): self._notify_instance_rebuild_error(context, instance, e, bdms) raise else: - instance.apply_migration_context() - # NOTE (ndipanov): This save will now update the host and node - # attributes making sure that next RT pass is consistent since - # it will be based on the instance and not the migration DB - # entry. - instance.host = self.host - instance.node = scheduled_node - instance.save() - instance.drop_migration_context() - - # NOTE (ndipanov): Mark the migration as done only after we - # mark the instance as belonging to this host. - self._set_migration_status(migration, 'done') + # NOTE(gibi): Let the resource tracker set the instance + # host and drop the migration context as we need to hold the + # COMPUTE_RESOURCE_SEMAPHORE to avoid the race with + # _update_available_resources. See bug 1896463. + self.rt.finish_evacuation(instance, scheduled_node, migration) def _do_rebuild_instance_with_claim(self, claim_context, *args, **kwargs): """Helper to avoid deep nesting in the top-level method.""" diff --git a/nova/compute/resource_tracker.py b/nova/compute/resource_tracker.py index b2ba0145cf..c34f705eaa 100644 --- a/nova/compute/resource_tracker.py +++ b/nova/compute/resource_tracker.py @@ -1801,3 +1801,21 @@ class ResourceTracker(object): """ self.pci_tracker.free_instance_claims(context, instance) self.pci_tracker.save(context) + + @utils.synchronized(COMPUTE_RESOURCE_SEMAPHORE) + def finish_evacuation(self, instance, node, migration): + instance.apply_migration_context() + # NOTE (ndipanov): This save will now update the host and node + # attributes making sure that next RT pass is consistent since + # it will be based on the instance and not the migration DB + # entry. + instance.host = self.host + instance.node = node + instance.save() + instance.drop_migration_context() + + # NOTE (ndipanov): Mark the migration as done only after we + # mark the instance as belonging to this host. + if migration: + migration.status = 'done' + migration.save() diff --git a/nova/tests/functional/regressions/test_bug_1896463.py b/nova/tests/functional/regressions/test_bug_1896463.py index af381b69fc..a6d38f4835 100644 --- a/nova/tests/functional/regressions/test_bug_1896463.py +++ b/nova/tests/functional/regressions/test_bug_1896463.py @@ -231,13 +231,4 @@ class TestEvacuateResourceTrackerRace( ) self._assert_pci_device_allocated(server['id'], self.compute1_id) - - # This is bug #1896463 as the PCI allocation was deleted by the racing - # _update_available_resource periodic task. - self._assert_pci_device_allocated( - server['id'], self.compute2_id, num=0) - - # FIXME(gibi): When this bug is fixed (or if you remove the sleeps - # above to avoid the race condition) then we expect that the PCI - # allocation exists on the destination host too. - # self._assert_pci_device_allocated(server['id'], self.compute2_id) + self._assert_pci_device_allocated(server['id'], self.compute2_id) diff --git a/nova/tests/unit/compute/test_compute_mgr.py b/nova/tests/unit/compute/test_compute_mgr.py index 17fcb0e99b..dfa14a4c8d 100644 --- a/nova/tests/unit/compute/test_compute_mgr.py +++ b/nova/tests/unit/compute/test_compute_mgr.py @@ -5161,18 +5161,21 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase, node = uuidutils.generate_uuid() # ironic node uuid instance = fake_instance.fake_instance_obj(self.context, node=node) instance.migration_context = None + migration = objects.Migration(status='accepted') with test.nested( mock.patch.object(self.compute, '_get_compute_info'), mock.patch.object(self.compute, '_do_rebuild_instance_with_claim'), mock.patch.object(objects.Instance, 'save'), - mock.patch.object(self.compute, '_set_migration_status'), - ) as (mock_get, mock_rebuild, mock_save, mock_set): - self.compute.rebuild_instance(self.context, instance, None, None, - None, None, None, None, False, - False, False, None, None, {}, None) + mock.patch.object(migration, 'save'), + ) as (mock_get, mock_rebuild, mock_save, mock_migration_save): + self.compute.rebuild_instance( + self.context, instance, None, None, + None, None, None, None, False, + False, False, migration, None, {}, None) self.assertFalse(mock_get.called) self.assertEqual(node, instance.node) - mock_set.assert_called_once_with(None, 'done') + self.assertEqual('done', migration.status) + mock_migration_save.assert_called_once_with() def test_rebuild_node_updated_if_recreate(self): dead_node = uuidutils.generate_uuid() @@ -5185,16 +5188,15 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase, with test.nested( mock.patch.object(self.compute, '_get_compute_info'), mock.patch.object(self.compute, '_do_rebuild_instance_with_claim'), - mock.patch.object(objects.Instance, 'save'), - mock.patch.object(self.compute, '_set_migration_status'), - ) as (mock_get, mock_rebuild, mock_save, mock_set): + ) as (mock_get, mock_rebuild): mock_get.return_value.hypervisor_hostname = 'new-node' - self.compute.rebuild_instance(self.context, instance, None, None, - None, None, None, None, True, - False, False, None, None, {}, None) + self.compute.rebuild_instance( + self.context, instance, None, None, None, None, None, + None, True, False, False, mock.sentinel.migration, None, {}, + None) mock_get.assert_called_once_with(mock.ANY, self.compute.host) - self.assertEqual('new-node', instance.node) - mock_set.assert_called_once_with(None, 'done') + mock_rt.finish_evacuation.assert_called_once_with( + instance, 'new-node', mock.sentinel.migration) # Make sure the rebuild_claim was called with the proper image_meta # from the instance. mock_rt.rebuild_claim.assert_called_once() |