Fix driver exception when cascade deleting volume after transferring
After transferring a volume without snapshots from one user project to another user project, if the receiving user uses cascade deleting, it will cause some exceptions in driver and volume will be error_deleting. APIImpact Change-Id: I9a870118c9c68799a4dab4bfa1f08b1e65a4796a Closes-Bug: #1698310
This commit is contained in:
parent
c1dbabaddb
commit
6e412852f2
|
@ -409,6 +409,10 @@ def volume_qos_allows_retype(new_vol_type):
|
||||||
return IMPL.volume_qos_allows_retype(new_vol_type)
|
return IMPL.volume_qos_allows_retype(new_vol_type)
|
||||||
|
|
||||||
|
|
||||||
|
def volume_has_other_project_snp_filter():
|
||||||
|
return IMPL.volume_has_other_project_snp_filter()
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2618,6 +2618,12 @@ def volume_qos_allows_retype(new_vol_type):
|
||||||
models.QualityOfServiceSpecs.value != 'back-end'))))
|
models.QualityOfServiceSpecs.value != 'back-end'))))
|
||||||
|
|
||||||
|
|
||||||
|
def volume_has_other_project_snp_filter():
|
||||||
|
return sql.exists().where(
|
||||||
|
and_(models.Volume.id == models.Snapshot.volume_id,
|
||||||
|
models.Volume.project_id != models.Snapshot.project_id))
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2479,6 +2479,28 @@ class VolumeTestCase(base.BaseVolumeTestCase):
|
||||||
volume = objects.Volume.get_by_id(self.context, volume.id)
|
volume = objects.Volume.get_by_id(self.context, volume.id)
|
||||||
self.assertEqual('deleting', volume.status)
|
self.assertEqual('deleting', volume.status)
|
||||||
|
|
||||||
|
def test_cascade_delete_volume_with_snapshots_in_other_project(self):
|
||||||
|
"""Test volume deletion with dependent snapshots in other project."""
|
||||||
|
volume = tests_utils.create_volume(self.user_context,
|
||||||
|
**self.volume_params)
|
||||||
|
snapshot = create_snapshot(volume['id'], size=volume['size'],
|
||||||
|
project_id=fake.PROJECT2_ID)
|
||||||
|
self.volume.create_snapshot(self.context, snapshot)
|
||||||
|
self.assertEqual(
|
||||||
|
snapshot.id, objects.Snapshot.get_by_id(self.context,
|
||||||
|
snapshot.id).id)
|
||||||
|
|
||||||
|
volume['status'] = 'available'
|
||||||
|
volume['host'] = 'fakehost'
|
||||||
|
|
||||||
|
volume_api = cinder.volume.api.API()
|
||||||
|
|
||||||
|
self.assertRaises(exception.InvalidVolume,
|
||||||
|
volume_api.delete,
|
||||||
|
self.user_context,
|
||||||
|
volume,
|
||||||
|
cascade=True)
|
||||||
|
|
||||||
@mock.patch.object(driver.BaseVD, 'get_backup_device')
|
@mock.patch.object(driver.BaseVD, 'get_backup_device')
|
||||||
@mock.patch.object(driver.BaseVD, 'secure_file_operations_enabled')
|
@mock.patch.object(driver.BaseVD, 'secure_file_operations_enabled')
|
||||||
def test_get_backup_device(self, mock_secure, mock_get_backup):
|
def test_get_backup_device(self, mock_secure, mock_get_backup):
|
||||||
|
|
|
@ -418,6 +418,10 @@ class API(base.Base):
|
||||||
else:
|
else:
|
||||||
# Allow deletion if all snapshots are in an expected state
|
# Allow deletion if all snapshots are in an expected state
|
||||||
filters = [~db.volume_has_undeletable_snapshots_filter()]
|
filters = [~db.volume_has_undeletable_snapshots_filter()]
|
||||||
|
# Check if the volume has snapshots which are existing in
|
||||||
|
# other project now.
|
||||||
|
if not context.is_admin:
|
||||||
|
filters.append(~db.volume_has_other_project_snp_filter())
|
||||||
else:
|
else:
|
||||||
# Don't allow deletion of volume with snapshots
|
# Don't allow deletion of volume with snapshots
|
||||||
filters = [~db.volume_has_snapshots_filter()]
|
filters = [~db.volume_has_snapshots_filter()]
|
||||||
|
@ -433,7 +437,8 @@ class API(base.Base):
|
||||||
status = utils.build_or_str(expected.get('status'),
|
status = utils.build_or_str(expected.get('status'),
|
||||||
_('status must be %s and'))
|
_('status must be %s and'))
|
||||||
msg = _('Volume %s must not be migrating, attached, belong to a '
|
msg = _('Volume %s must not be migrating, attached, belong to a '
|
||||||
'group or have snapshots.') % status
|
'group, have snapshots or be disassociated from '
|
||||||
|
'snapshots after volume transfer.') % status
|
||||||
LOG.info(msg)
|
LOG.info(msg)
|
||||||
raise exception.InvalidVolume(reason=msg)
|
raise exception.InvalidVolume(reason=msg)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
---
|
||||||
|
fixes:
|
||||||
|
- After transferring a volume without snapshots from one user project
|
||||||
|
to another user project, if the receiving user uses cascade deleting,
|
||||||
|
it will cause some exceptions in driver and volume will be error_deleting.
|
||||||
|
Adding additional check to ensure there are no snapshots left in other
|
||||||
|
project when cascade deleting a tranferred volume.
|
Loading…
Reference in New Issue