Delete InstanceMapping in conductor if BuildRequest is already deleted

The BuildRequest represents a server in the API until the scheduler
picks a host in a cell and we create the instance record in that cell
and update the instance mapping to point at the cell. If the user
deletes the BuildRequest before the instance record is created in a
cell, the conductor schedule_and_build_instances method cleans up the
resource allocations created by scheduler and then continues to the
next instance (if it's a multi-create request). The point is the instance
does not get created in a cell, the BuildRequest is gone, and the
instance mapping is left pointing at no cell - effectively orphaned.

Furthermore, the archive_deleted_rows command change
I483701a55576c245d091ff086b32081b392f746e to cleanup instance mappings
for archived instances will not catch and cleanup the orphan instance
mapping because there never was an instance record to delete and archive
(the BuildRequest was deleted before the instance record was created, and
the BuildRequest is hard deleted so there is no archive).

This change simply deletes the InstanceMapping record in case the
BuildRequest is already gone by the time we finish scheduling and we
do not create the instance record in any cell.

Change-Id: Ia03577ae41f010b449e47ff5b69b432d74f8467b
Related-Bug: #1784074
Related-Bug: #1773945
This commit is contained in:
Matt Riedemann 2019-06-19 16:26:07 -04:00
parent 4e9d224479
commit 1ff029c1c3
2 changed files with 13 additions and 0 deletions

View File

@ -1357,6 +1357,15 @@ class ComputeTaskManager(base.Base):
'was already deleted.', instance=instance)
# This is a placeholder in case the quota recheck fails.
instances.append(None)
# If the build request was deleted and the instance is not
# going to be created, there is on point in leaving an orphan
# instance mapping so delete it.
try:
im = objects.InstanceMapping.get_by_instance_uuid(
context, instance.uuid)
im.destroy()
except exception.InstanceMappingNotFound:
pass
self.report_client.delete_allocation_for_instance(
context, instance.uuid)
continue

View File

@ -2108,6 +2108,10 @@ class ConductorTaskTestCase(_BaseTaskTestCase, test_compute.BaseTestCase):
self.assertFalse(bury.called)
# we don't don't destroy the build request since it's already gone
self.assertFalse(br_destroy.called)
# Make sure the instance mapping is gone.
self.assertRaises(exc.InstanceMappingNotFound,
objects.InstanceMapping.get_by_instance_uuid,
self.context, inst_uuid)
@mock.patch('nova.compute.rpcapi.ComputeAPI.build_and_run_instance')
@mock.patch('nova.scheduler.rpcapi.SchedulerAPI.select_destinations')