From 40c07c160a857a6800de0d2fade777a322c82612 Mon Sep 17 00:00:00 2001 From: Patrick Woods Date: Thu, 27 Jun 2013 14:44:54 -0500 Subject: [PATCH] Fixup handle_create backup restore. The handle_create did not retrieve the volume_id correctly and the check_create_complete needs to handle the restoring-backup status. Also modify and add support for restoring-backup status test cases for success and error. The additional FakeVolumeFromBackup will force the inital status to be checked by the method check_create_complete in volume.py. Fix bug 1195403. Change-Id: I60bf4f9f90be1058d0fb400aa3778d0448b1a898 --- heat/engine/resources/volume.py | 4 ++- heat/tests/test_volume.py | 64 +++++++++++++++++++++++++++++++-- 2 files changed, 64 insertions(+), 4 deletions(-) diff --git a/heat/engine/resources/volume.py b/heat/engine/resources/volume.py index dcbdb6a35..9d4612579 100644 --- a/heat/engine/resources/volume.py +++ b/heat/engine/resources/volume.py @@ -55,7 +55,7 @@ class Volume(resource.Resource): if volume_backups is None: raise exception.Error( '%s not supported' % self._restore_property) - vol_id = cinder.restores.restore(backup_id)['volume_id'] + vol_id = cinder.restores.restore(backup_id).volume_id vol = cinder.volumes.get(vol_id) vol.update( @@ -77,6 +77,8 @@ class Volume(resource.Resource): return True elif vol.status == 'creating': return False + elif vol.status == 'restoring-backup': + return False else: raise exception.Error(vol.status) diff --git a/heat/tests/test_volume.py b/heat/tests/test_volume.py index d53f4e0b7..bf99680b8 100644 --- a/heat/tests/test_volume.py +++ b/heat/tests/test_volume.py @@ -464,20 +464,22 @@ class VolumeTest(HeatTestCase): @skipIf(volume_backups is None, 'unable to import volume_backups') def test_create_from_snapshot(self): stack_name = 'test_volume_stack' - fv = FakeVolume('creating', 'available') + fv = FakeVolumeFromBackup('restoring-backup', 'available') + fvbr = FakeBackupRestore('vol-123') # create script clients.OpenStackClients.cinder().MultipleTimes().AndReturn( self.cinder_fc) self.m.StubOutWithMock(self.cinder_fc.restores, 'restore') - self.cinder_fc.restores.restore('backup-123').AndReturn( - {'volume_id': 'vol-123'}) + self.cinder_fc.restores.restore('backup-123').AndReturn(fvbr) self.cinder_fc.volumes.get('vol-123').AndReturn(fv) self.m.StubOutWithMock(fv, 'update') vol_name = utils.PhysName(stack_name, 'DataVolume') fv.update( display_description=vol_name, display_name=vol_name) + # sleep will be called since backup will not complete right away + scheduler.TaskRunner._sleep(mox.IsA(int)).AndReturn(None) self.m.ReplayAll() @@ -490,6 +492,41 @@ class VolumeTest(HeatTestCase): self.m.VerifyAll() + @skipIf(volume_backups is None, 'unable to import volume_backups') + def test_create_from_snapshot_error(self): + stack_name = 'test_volume_stack' + fv = FakeVolumeFromBackup('restoring-backup', 'error') + fvbr = FakeBackupRestore('vol-123') + + # create script + clients.OpenStackClients.cinder().MultipleTimes().AndReturn( + self.cinder_fc) + self.m.StubOutWithMock(self.cinder_fc.restores, 'restore') + self.cinder_fc.restores.restore('backup-123').AndReturn(fvbr) + self.cinder_fc.volumes.get('vol-123').AndReturn(fv) + self.m.StubOutWithMock(fv, 'update') + vol_name = utils.PhysName(stack_name, 'DataVolume') + fv.update( + display_description=vol_name, + display_name=vol_name) + # sleep will be called since backup will not complete right away + scheduler.TaskRunner._sleep(mox.IsA(int)).AndReturn(None) + + self.m.ReplayAll() + + t = template_format.parse(volume_template) + t['Resources']['DataVolume']['Properties']['SnapshotId'] = 'backup-123' + t['Resources']['DataVolume']['Properties']['AvailabilityZone'] = 'nova' + stack = parse_stack(t, stack_name=stack_name) + + rsrc = vol.Volume('DataVolume', + t['Resources']['DataVolume'], + stack) + create = scheduler.TaskRunner(rsrc.create) + self.assertRaises(exception.ResourceFailure, create) + + self.m.VerifyAll() + def test_cinder_create(self): fv = FakeVolume('creating', 'available') stack_name = 'test_volume_stack' @@ -698,3 +735,24 @@ class FakeVolume: class FakeBackup(FakeVolume): status = 'creating' id = 'backup-123' + + +class FakeBackupRestore(object): + volume_id = 'vol-123' + + def __init__(self, volume_id): + self.volume_id = volume_id + + +class FakeVolumeFromBackup(FakeVolume): + status = 'restoring-backup' + get_call_count = 0 + + def get(self): + # Allow get to be called once without changing the status + # This is to allow the check_create_complete method to + # check the inital status. + if self.get_call_count < 1: + self.get_call_count += 1 + else: + self.status = self.final_status