From 3d18b30329183c6d89f287c5dd23248cbcc24607 Mon Sep 17 00:00:00 2001 From: Dermot Tynan Date: Thu, 25 Apr 2013 10:46:34 +0100 Subject: [PATCH] Clear volumes stuck in 'downloading' If the CinderVolume service is restarted while an image-copy is happening, the volume gets left in a 'downloading' state and cannot be used or deleted. This fix adds code to init_host to look for volumes (on this host) in such a state, and move them to an error state. It also calls clear_download in the driver in case the driver needs to perform an action, such as detaching the volume. Fixes Bug #1172645 Change-Id: Ia5dab9ebf997f573c0b4e57d983f5996af81ede5 --- cinder/tests/test_volume.py | 13 +++++++++++-- cinder/volume/driver.py | 4 ++++ cinder/volume/manager.py | 5 +++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/cinder/tests/test_volume.py b/cinder/tests/test_volume.py index a22224ace..523ebcf66 100644 --- a/cinder/tests/test_volume.py +++ b/cinder/tests/test_volume.py @@ -77,7 +77,7 @@ class VolumeTestCase(test.TestCase): @staticmethod def _create_volume(size=0, snapshot_id=None, image_id=None, - metadata=None): + metadata=None, status="creating"): """Create a volume object.""" vol = {} vol['size'] = size @@ -86,13 +86,22 @@ class VolumeTestCase(test.TestCase): vol['user_id'] = 'fake' vol['project_id'] = 'fake' vol['availability_zone'] = FLAGS.storage_availability_zone - vol['status'] = "creating" + vol['status'] = status vol['attach_status'] = "detached" vol['host'] = FLAGS.host if metadata is not None: vol['metadata'] = metadata return db.volume_create(context.get_admin_context(), vol) + def test_init_host_clears_downloads(self): + """Test that init_host will unwedge a volume stuck in downloading.""" + volume = self._create_volume(status='downloading') + volume_id = volume['id'] + self.volume.init_host() + volume = db.volume_get(context.get_admin_context(), volume_id) + self.assertEquals(volume['status'], "error") + self.volume.delete_volume(self.context, volume_id) + def test_create_delete_volume(self): """Test volume can be created and deleted.""" # Need to stub out reserve, commit, and rollback diff --git a/cinder/volume/driver.py b/cinder/volume/driver.py index 7615932e1..03f18a2b7 100644 --- a/cinder/volume/driver.py +++ b/cinder/volume/driver.py @@ -191,6 +191,10 @@ class VolumeDriver(object): """Restore an existing backup to a new or existing volume.""" raise NotImplementedError() + def clear_download(self, context, volume): + """Clean up after an interrupted image copy.""" + pass + class ISCSIDriver(VolumeDriver): """Executes commands relating to ISCSI volumes. diff --git a/cinder/volume/manager.py b/cinder/volume/manager.py index 5e2ee28dd..5ae2b28f1 100644 --- a/cinder/volume/manager.py +++ b/cinder/volume/manager.py @@ -147,6 +147,11 @@ class VolumeManager(manager.SchedulerDependentManager): for volume in volumes: if volume['status'] in ['available', 'in-use']: self.driver.ensure_export(ctxt, volume) + elif volume['status'] == 'downloading': + LOG.info(_("volume %s stuck in a downloading state"), + volume['id']) + self.driver.clear_download(ctxt, volume) + self.db.volume_update(ctxt, volume['id'], {'status': 'error'}) else: LOG.info(_("volume %s: skipping export"), volume['name']) -- 2.45.2