From d6c527bb6b0ee63fc07b91855fcf4e15f7a03821 Mon Sep 17 00:00:00 2001 From: Eoghan Glynn Date: Tue, 22 Jan 2013 15:44:21 +0000 Subject: Avoid stuck task_state on snapshot image failure Fixes bug LP 1101136 Previously if the glance interaction failed prior to an instance being snapshot'd or backed up, the task state remained stuck at image_snapshot/backup. The normal task state reversion logic did not kick in, as this is limited to the compute layer, whereas the intial glance interaction occurs within the API layer. Now, we avoid this problem by delaying setting the task state until the initial initial image creation/retrieval has completed. Change-Id: Id498ae6b3674306743013e4fe99837da8e2031b5 --- nova/tests/compute/test_compute.py | 54 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/compute/test_compute.py b/nova/tests/compute/test_compute.py index 092fd940a..865288f95 100644 --- a/nova/tests/compute/test_compute.py +++ b/nova/tests/compute/test_compute.py @@ -4688,6 +4688,60 @@ class ComputeAPITestCase(BaseTestCase): self.assertEqual(properties['d'], 'd') self.assertFalse('spam' in properties) + def _do_test_snapshot_image_service_fails(self, method, image_id): + # Ensure task_state remains at None if image service fails. + def fake_fails(*args, **kwargs): + raise test.TestingException() + + restore = getattr(fake_image._FakeImageService, method) + self.stubs.Set(fake_image._FakeImageService, method, fake_fails) + + instance = self._create_fake_instance() + self.assertRaises(test.TestingException, + self.compute_api.snapshot, + self.context, + instance, + 'no_image_snapshot', + image_id=image_id) + + self.stubs.Set(fake_image._FakeImageService, method, restore) + db_instance = db.instance_get_all(self.context)[0] + self.assertIsNone(db_instance['task_state']) + + def test_snapshot_image_creation_fails(self): + self._do_test_snapshot_image_service_fails('create', None) + + def test_snapshot_image_show_fails(self): + self._do_test_snapshot_image_service_fails('show', 'image') + + def _do_test_backup_image_service_fails(self, method, image_id): + # Ensure task_state remains at None if image service fails. + def fake_fails(*args, **kwargs): + raise test.TestingException() + + restore = getattr(fake_image._FakeImageService, method) + self.stubs.Set(fake_image._FakeImageService, method, fake_fails) + + instance = self._create_fake_instance() + self.assertRaises(test.TestingException, + self.compute_api.backup, + self.context, + instance, + 'no_image_backup', + 'DAILY', + 0, + image_id=image_id) + + self.stubs.Set(fake_image._FakeImageService, method, restore) + db_instance = db.instance_get_all(self.context)[0] + self.assertIsNone(db_instance['task_state']) + + def test_backup_image_creation_fails(self): + self._do_test_backup_image_service_fails('create', None) + + def test_backup_image_show_fails(self): + self._do_test_backup_image_service_fails('show', 'image') + def test_backup(self): # Can't backup an instance which is already being backed up. instance = self._create_fake_instance() -- cgit