Handle instance = None in _local_delete_cleanup

Change I4d3193d8401614311010ed0e055fcb3aaeeebaed added some
additional local delete cleanup to prevent leaking of placement
allocations. The change introduced a regression in our "delete while
booting" handling as the _local_delete_cleanup required a valid
instance object to do its work and in two cases, we could have
instance = None from _lookup_instance if we are racing with a create
request and the conductor has deleted the instance record while we
are in the middle of processing the delete request.

This handles those scenarios by doing two things:

  (1) Changing the _local_delete_cleanup and
      _update_queued_for_deletion methods to take an instance UUID
      instead of a full instance object as they really only need the
      UUID to do their work
  (2) Saving a copy of the instance UUID before doing another instance
      lookup which might return None and passing that UUID to the
      _local_delete_cleanup and _update_queued_for_deletion methods

Closes-Bug: #1914777

Change-Id: I03cf285ad83e09d88cdb702a88dfed53c01610f8
This commit is contained in:
melanie witt
2021-02-12 01:50:19 +00:00
parent f7975d640c
commit 123f6262f6
3 changed files with 29 additions and 36 deletions

View File

@@ -17,7 +17,6 @@ from nova import exception
from nova import objects
from nova import test
from nova.tests import fixtures as nova_fixtures
from nova.tests.functional.api import client
from nova.tests.functional import integrated_helpers
from nova.tests.unit import policy_fixture
@@ -79,14 +78,8 @@ class TestDeleteWhileBooting(test.TestCase,
# while booting" in compute/api fails after a different request has
# deleted it.
br_not_found = exception.BuildRequestNotFound(uuid=self.server['id'])
mock_get_br.side_effect = [self.br, br_not_found]
# FIXME(melwitt): Delete request fails due to the AttributeError.
ex = self.assertRaises(
client.OpenStackApiException, self._delete_server, self.server)
self.assertEqual(500, ex.response.status_code)
self.assertIn('AttributeError', str(ex))
# FIXME(melwitt): Uncomment when the bug is fixed.
# self._delete_server(self.server)
mock_get_br.side_effect = [self.br, br_not_found, br_not_found]
self._delete_server(self.server)
@mock.patch('nova.objects.build_request.BuildRequest.get_by_instance_uuid')
@mock.patch('nova.objects.InstanceMapping.get_by_instance_uuid')
@@ -119,7 +112,7 @@ class TestDeleteWhileBooting(test.TestCase,
context=self.ctxt, instance_uuid=self.server['id'],
cell_mapping=self.cell_mappings['cell1'])
mock_get_im.side_effect = [
no_cell_im, has_cell_im, has_cell_im, has_cell_im]
no_cell_im, has_cell_im, has_cell_im, has_cell_im, has_cell_im]
# Simulate that the instance object has been created by the conductor
# in the create path while the delete request is being processed.
# First lookups are before the instance has been deleted and the last
@@ -127,7 +120,7 @@ class TestDeleteWhileBooting(test.TestCase,
# request to make an instance object for testing.
i = self.br.get_new_instance(self.ctxt)
i_not_found = exception.InstanceNotFound(instance_id=self.server['id'])
mock_get_i.side_effect = [i, i, i, i_not_found]
mock_get_i.side_effect = [i, i, i, i_not_found, i_not_found]
# Simulate that the conductor is running instance_destroy at the same
# time as we are.
@@ -142,10 +135,4 @@ class TestDeleteWhileBooting(test.TestCase,
self.stub_out(
'nova.objects.instance.Instance.destroy', fake_instance_destroy)
# FIXME(melwitt): Delete request fails due to the AttributeError.
ex = self.assertRaises(
client.OpenStackApiException, self._delete_server, self.server)
self.assertEqual(500, ex.response.status_code)
self.assertIn('AttributeError', str(ex))
# FIXME(melwitt): Uncomment when the bug is fixed.
# self._delete_server(self.server)
self._delete_server(self.server)