From ded04737acfa55a0f84ee270702b2f011970b1f3 Mon Sep 17 00:00:00 2001 From: Chris Behrens Date: Wed, 26 Sep 2012 10:46:49 +0000 Subject: [PATCH] Fix issues deleting instances in RESIZED state DB API call migration_get_by_instance_and_status requires admin context...and it'll also raise an exception if no migration matches. _delete() in compute/api was not using admin context, and was checking for a false return from the DB call vs checking for an exception. Added a test that covers both problems. Fixes bug 1056601 Change-Id: Ib3c631dccbb2776761cf5acb8bab1d814bf3e282 (cherry picked from commit 8c9c380935b4aac40269754a291134c130bccec9) --- nova/compute/api.py | 8 ++++++-- nova/tests/compute/test_compute.py | 13 +++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/nova/compute/api.py b/nova/compute/api.py index c1b5ac3795e..531aa441488 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -880,8 +880,12 @@ def _delete(self, context, instance): if instance['vm_state'] == vm_states.RESIZED: # If in the middle of a resize, use confirm_resize to # ensure the original instance is cleaned up too - migration_ref = self.db.migration_get_by_instance_and_status( - context, instance['uuid'], 'finished') + get_migration = self.db.migration_get_by_instance_and_status + try: + migration_ref = get_migration(context.elevated(), + instance['uuid'], 'finished') + except exception.MigrationNotFoundByStatus: + migration_ref = None if migration_ref: src_host = migration_ref['source_compute'] # Call since this can race with the terminate_instance. diff --git a/nova/tests/compute/test_compute.py b/nova/tests/compute/test_compute.py index a78bdd65e29..3687c683f7b 100644 --- a/nova/tests/compute/test_compute.py +++ b/nova/tests/compute/test_compute.py @@ -2986,6 +2986,19 @@ def test_delete(self): db.instance_destroy(self.context, instance['uuid']) + def test_delete_in_resized(self): + instance, instance_uuid = self._run_instance(params={ + 'host': FLAGS.host}) + + instance['vm_state'] = vm_states.RESIZED + + self.compute_api.delete(self.context, instance) + + instance = db.instance_get_by_uuid(self.context, instance_uuid) + self.assertEqual(instance['task_state'], task_states.DELETING) + + db.instance_destroy(self.context, instance['uuid']) + def test_repeated_delete_quota(self): in_use = {'instances': 1}