diff options
author | Zuul <zuul@review.opendev.org> | 2022-09-07 02:20:50 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2022-09-07 02:20:50 +0000 |
commit | 5633be211f4c2e656a585b4ff5ce94035a0df767 (patch) | |
tree | f957c4d8754e3bf682ac943bb409f75ea9b4d41d | |
parent | 5e8f34ca380493bc2a57e0ad14eb7b4a431872b6 (diff) | |
parent | fc20dc2ea23d511a0f741901d7f03135bb269165 (diff) | |
download | nova-5633be211f4c2e656a585b4ff5ce94035a0df767.tar.gz |
Merge "Avoid unbound instance_uuid var during delete" into stable/wallaby
-rw-r--r-- | nova/compute/api.py | 10 | ||||
-rw-r--r-- | nova/tests/unit/compute/test_api.py | 28 |
2 files changed, 34 insertions, 4 deletions
diff --git a/nova/compute/api.py b/nova/compute/api.py index d938a910e5..774eb538c0 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -2231,6 +2231,12 @@ class API(base.Base): # Normal delete should be attempted. may_have_ports_or_volumes = compute_utils.may_have_ports_or_volumes( instance) + + # Save a copy of the instance UUID early, in case + # _lookup_instance returns instance = None, to pass to + # _local_delete_cleanup if needed. + instance_uuid = instance.uuid + if not instance.host and not may_have_ports_or_volumes: try: if self._delete_while_booting(context, instance): @@ -2244,10 +2250,6 @@ class API(base.Base): # full Instance or None if not found. If not found then it's # acceptable to skip the rest of the delete processing. - # Save a copy of the instance UUID early, in case - # _lookup_instance returns instance = None, to pass to - # _local_delete_cleanup if needed. - instance_uuid = instance.uuid cell, instance = self._lookup_instance(context, instance.uuid) if cell and instance: try: diff --git a/nova/tests/unit/compute/test_api.py b/nova/tests/unit/compute/test_api.py index 822bfc1a15..809ed3b295 100644 --- a/nova/tests/unit/compute/test_api.py +++ b/nova/tests/unit/compute/test_api.py @@ -1620,6 +1620,34 @@ class _ComputeAPIUnitTestMixIn(object): self.compute_api.notifier, self.context, instance) destroy_mock.assert_called_once_with() + def test_delete_instance_while_booting_host_changes_lookup_fails(self): + """Tests the case where the instance become scheduled while being + destroyed but then the final lookup fails. + """ + instance = self._create_instance_obj({'host': None}) + + with test.nested( + mock.patch.object( + self.compute_api, '_delete_while_booting', + side_effect=exception.ObjectActionError( + action="delete", reason="reason")), + mock.patch.object( + self.compute_api, '_lookup_instance', + return_value=(None, None)), + mock.patch.object(self.compute_api, '_local_delete_cleanup') + ) as ( + _delete_while_booting, _lookup_instance, _local_delete_cleanup + ): + self.compute_api._delete( + self.context, instance, 'delete', mock.NonCallableMock()) + + _delete_while_booting.assert_called_once_with( + self.context, instance) + _lookup_instance.assert_called_once_with( + self.context, instance.uuid) + _local_delete_cleanup.assert_called_once_with( + self.context, instance.uuid) + @mock.patch.object(context, 'target_cell') @mock.patch.object(objects.InstanceMapping, 'get_by_instance_uuid', side_effect=exception.InstanceMappingNotFound( |