From ddc8d7a4233aee139f9c91aeee885d7f2e45f8ac Mon Sep 17 00:00:00 2001 From: Jordan Tardif Date: Mon, 15 Sep 2014 17:59:06 -0400 Subject: [PATCH] Catch ImageNotFound exception when deleting rbd volume When deleting a rbd volume it is possible for remove() to throw a ImageNotFound exception. In this case we should catch the exception, so the volume delete can continue. Closes-Bug: 1403172 Change-Id: I32cf9d3774c129cda4449996ceeb4b43b7e42904 --- cinder/tests/test_rbd.py | 32 ++++++++++++++++++++++++++++++++ cinder/volume/drivers/rbd.py | 5 +++++ 2 files changed, 37 insertions(+) diff --git a/cinder/tests/test_rbd.py b/cinder/tests/test_rbd.py index f40409b46..7b6496160 100644 --- a/cinder/tests/test_rbd.py +++ b/cinder/tests/test_rbd.py @@ -348,6 +348,38 @@ class RBDTestCase(test.TestCase): self.assertEqual(RAISED_EXCEPTIONS, [self.mock_rbd.ImageBusy]) + @common_mocks + def test_delete_volume_not_found(self): + self.mock_rbd.Image.return_value.list_snaps.return_value = [] + + self.mock_rbd.RBD.return_value.remove.side_effect = ( + self.mock_rbd.ImageNotFound) + + with mock.patch.object(self.driver, '_get_clone_info') as \ + mock_get_clone_info: + mock_get_clone_info.return_value = (None, None, None) + with mock.patch.object(self.driver, '_delete_backup_snaps') as \ + mock_delete_backup_snaps: + with mock.patch.object(driver, 'RADOSClient') as \ + mock_rados_client: + self.assertIsNone(self.driver.delete_volume(self.volume)) + mock_get_clone_info.assert_called_once_with( + self.mock_rbd.Image.return_value, + self.volume_name, + None) + (self.mock_rbd.Image.return_value.list_snaps + .assert_called_once_with()) + mock_rados_client.assert_called_once_with(self.driver) + mock_delete_backup_snaps.assert_called_once_with( + self.mock_rbd.Image.return_value) + self.assertFalse( + self.mock_rbd.Image.return_value.unprotect_snap.called) + self.assertEqual( + 1, self.mock_rbd.RBD.return_value.remove.call_count) + # Make sure the exception was raised + self.assertEqual(RAISED_EXCEPTIONS, + [self.mock_rbd.ImageNotFound]) + @common_mocks def test_create_snapshot(self): proxy = self.mock_proxy.return_value diff --git a/cinder/volume/drivers/rbd.py b/cinder/volume/drivers/rbd.py index 703d14ff3..0c1a0749d 100644 --- a/cinder/volume/drivers/rbd.py +++ b/cinder/volume/drivers/rbd.py @@ -658,6 +658,11 @@ class RBDDriver(driver.VolumeDriver): # Now raise this so that volume stays available so that we # delete can be retried. raise exception.VolumeIsBusy(msg, volume_name=volume_name) + except self.rbd.ImageNotFound: + msg = (_LI("RBD volume %s not found, allowing delete " + "operation to proceed.") % volume_name) + LOG.info(msg) + return # If it is a clone, walk back up the parent chain deleting # references. -- 2.45.2