3PAR: Delete missing snapshot stuck in error_del

If the snapshot is deleted outside of cinder, attempting
to delete it again results in the snapshot state stuck in
error_deleting.

This is because the current code raises a NotFound exception,
but the base cinder code does not catch this and update its db.

Instead, log a warning, and simply tell the base cinder code that it was
successfully deleted.

Change-Id: I5c5d24bc113e320346ff4f1f4f62fffdf7cddfc4
Closes-Bug: #1283233
This commit is contained in:
Ramy Asselin 2014-02-24 12:29:01 -08:00
parent f2137b37e8
commit e31b9e7837
2 changed files with 28 additions and 7 deletions

View File

@ -547,6 +547,21 @@ class HP3PARBaseDriver(object):
self.driver.delete_snapshot,
self.snapshot)
def test_delete_snapshot_not_found(self):
# setup_mock_client drive with default configuration
# and return the mock HTTP 3PAR client
mock_client = self.setup_driver()
self.driver.create_snapshot(self.snapshot)
try:
ex = hpexceptions.HTTPNotFound("not found")
mock_client.deleteVolume = mock.Mock(side_effect=ex)
self.driver.delete_snapshot(self.snapshot)
except Exception:
self.fail("Deleting a snapshot that is missing should act as if "
"it worked.")
def test_create_volume_from_snapshot(self):
# setup_mock_client drive with default configuration
# and return the mock HTTP 3PAR client

View File

@ -116,10 +116,11 @@ class HP3PARCommon(object):
2.0.0 - Update hp3parclient API uses 3.0.x
2.0.1 - Updated to use qos_specs, added new qos settings and personas
2.0.2 - Add back-end assisted volume migrate
2.0.3 - Allow deleting missing snapshots bug #1283233
"""
VERSION = "2.0.2"
VERSION = "2.0.3"
stats = {}
@ -564,7 +565,7 @@ class HP3PARCommon(object):
# Cleanup the volume set if unable to create the qos rule
# or add the volume to the volume set
self.client.deleteVolumeSet(vvs_name)
raise exception.CinderException(ex.get_description())
raise exception.CinderException(ex)
def get_cpg(self, volume, allowSnap=False):
volume_name = self._get_3par_vol_name(volume['id'])
@ -831,7 +832,9 @@ class HP3PARCommon(object):
except hpexceptions.HTTPNotFound as ex:
# We'll let this act as if it worked
# it helps clean up the cinder entries.
LOG.error(str(ex))
msg = _("Delete volume id not found. Removing from cinder: "
"%(id)s Ex: %(msg)s") % {'id': volume['id'], 'msg': ex}
LOG.warning(msg)
except hpexceptions.HTTPForbidden as ex:
LOG.error(str(ex))
raise exception.NotAuthorized(ex.get_description())
@ -898,7 +901,7 @@ class HP3PARCommon(object):
# Delete the volume if unable to add it to the volume set
self.client.deleteVolume(volume_name)
LOG.error(str(ex))
raise exception.CinderException(ex.get_description())
raise exception.CinderException(ex)
except hpexceptions.HTTPForbidden as ex:
LOG.error(str(ex))
raise exception.NotAuthorized()
@ -907,7 +910,7 @@ class HP3PARCommon(object):
raise exception.NotFound()
except Exception as ex:
LOG.error(str(ex))
raise exception.CinderException(ex.get_description())
raise exception.CinderException(ex)
def create_snapshot(self, snapshot):
LOG.debug("Create Snapshot\n%s" % pprint.pformat(snapshot))
@ -1129,8 +1132,11 @@ class HP3PARCommon(object):
LOG.error(str(ex))
raise exception.NotAuthorized()
except hpexceptions.HTTPNotFound as ex:
LOG.error(str(ex))
raise exception.NotFound()
# We'll let this act as if it worked
# it helps clean up the cinder entries.
msg = _("Delete Snapshot id not found. Removing from cinder: "
"%(id)s Ex: %(msg)s") % {'id': snapshot['id'], 'msg': ex}
LOG.warning(msg)
except hpexceptions.HTTPConflict as ex:
LOG.error(str(ex))
raise exception.SnapshotIsBusy(snapshot_name=snapshot['id'])