RBD: support to get manageable snapshots
This patch adds the ability to get manageable snapshots to RBD driver. Partial-Implements: blueprint ceph-list-manageable-volumes-and-snapshots Change-Id: I2f979f445aeb2664c93c6810dcf2e82aed92a8cf
This commit is contained in:
parent
1aa9231cb2
commit
280cc7c5ae
@ -1978,6 +1978,63 @@ class RBDTestCase(test.TestCase):
|
||||
# Make sure the exception was raised
|
||||
self.assertEqual([self.mock_rbd.ImageExists], RAISED_EXCEPTIONS)
|
||||
|
||||
@common_mocks
|
||||
def test_get_manageable_snapshots(self):
|
||||
cinder_snaps = [{'id': '00000000-0000-0000-0000-000000000000',
|
||||
'volume_id': '11111111-1111-1111-1111-111111111111'}]
|
||||
vols = ['volume-11111111-1111-1111-1111-111111111111', 'vol1']
|
||||
self.mock_rbd.RBD.return_value.list.return_value = vols
|
||||
image = self.mock_proxy.return_value.__enter__.return_value
|
||||
image.list_snaps.side_effect = [
|
||||
[{'id': 1, 'name': 'snapshot-00000000-0000-0000-0000-000000000000',
|
||||
'size': 2 * units.Gi},
|
||||
{'id': 2, 'name': 'snap1', 'size': 6 * units.Gi},
|
||||
{'id': 3, 'size': 8 * units.Gi,
|
||||
'name': 'volume-22222222-2222-2222-2222-222222222222.clone_snap'
|
||||
},
|
||||
{'id': 4, 'size': 5 * units.Gi,
|
||||
'name': 'backup.33333333-3333-3333-3333-333333333333.snap.123'}],
|
||||
[{'id': 1, 'name': 'snap2', 'size': 4 * units.Gi}]]
|
||||
res = self.driver.get_manageable_snapshots(
|
||||
cinder_snaps, None, 1000, 0, ['size'], ['desc'])
|
||||
exp = [
|
||||
{'size': 8, 'safe_to_manage': False, 'extra_info': None,
|
||||
'reason_not_safe': 'used for clone snap', 'cinder_id': None,
|
||||
'reference': {
|
||||
'source-name':
|
||||
'volume-22222222-2222-2222-2222-222222222222.clone_snap'},
|
||||
'source_reference': {
|
||||
'source-name': 'volume-11111111-1111-1111-1111-111111111111'}
|
||||
},
|
||||
{'size': 6, 'safe_to_manage': True, 'extra_info': None,
|
||||
'reason_not_safe': None, 'cinder_id': None,
|
||||
'reference': {'source-name': 'snap1'},
|
||||
'source_reference': {
|
||||
'source-name': 'volume-11111111-1111-1111-1111-111111111111'}
|
||||
},
|
||||
{'size': 5, 'safe_to_manage': False, 'extra_info': None,
|
||||
'reason_not_safe': 'used for volume backup', 'cinder_id': None,
|
||||
'reference': {
|
||||
'source-name':
|
||||
'backup.33333333-3333-3333-3333-333333333333.snap.123'},
|
||||
'source_reference': {
|
||||
'source-name': 'volume-11111111-1111-1111-1111-111111111111'}
|
||||
},
|
||||
{'size': 4, 'safe_to_manage': True, 'extra_info': None,
|
||||
'reason_not_safe': None, 'cinder_id': None,
|
||||
'reference': {'source-name': 'snap2'},
|
||||
'source_reference': {'source-name': 'vol1'}
|
||||
},
|
||||
{'size': 2, 'safe_to_manage': False, 'extra_info': None,
|
||||
'reason_not_safe': 'already managed',
|
||||
'cinder_id': '00000000-0000-0000-0000-000000000000',
|
||||
'reference': {'source-name':
|
||||
'snapshot-00000000-0000-0000-0000-000000000000'},
|
||||
'source_reference': {
|
||||
'source-name': 'volume-11111111-1111-1111-1111-111111111111'}
|
||||
}]
|
||||
self.assertEqual(exp, res)
|
||||
|
||||
@common_mocks
|
||||
def test_unmanage_snapshot(self):
|
||||
proxy = self.mock_proxy.return_value
|
||||
|
@ -1764,6 +1764,57 @@ class RBDDriver(driver.CloneableImageVD, driver.MigrateVD,
|
||||
if not volume.is_protected_snap(snapshot.name):
|
||||
volume.protect_snap(snapshot.name)
|
||||
|
||||
def get_manageable_snapshots(self, cinder_snapshots, marker, limit, offset,
|
||||
sort_keys, sort_dirs):
|
||||
"""List manageable snapshots on RBD backend."""
|
||||
manageable_snapshots = []
|
||||
cinder_snapshot_ids = [resource['id'] for resource in cinder_snapshots]
|
||||
|
||||
with RADOSClient(self) as client:
|
||||
for image_name in self.RBDProxy().list(client.ioctx):
|
||||
with RBDVolumeProxy(self, image_name, read_only=True,
|
||||
client=client.cluster,
|
||||
ioctx=client.ioctx) as image:
|
||||
try:
|
||||
for snapshot in image.list_snaps():
|
||||
snapshot_id = (
|
||||
volume_utils.extract_id_from_snapshot_name(
|
||||
snapshot['name']))
|
||||
snapshot_info = {
|
||||
'reference': {'source-name': snapshot['name']},
|
||||
'size': int(math.ceil(
|
||||
float(snapshot['size']) / units.Gi)),
|
||||
'cinder_id': None,
|
||||
'extra_info': None,
|
||||
'safe_to_manage': False,
|
||||
'reason_not_safe': None,
|
||||
'source_reference': {'source-name': image_name}
|
||||
}
|
||||
|
||||
if snapshot_id in cinder_snapshot_ids:
|
||||
# Exclude snapshots already managed.
|
||||
snapshot_info['reason_not_safe'] = (
|
||||
'already managed')
|
||||
snapshot_info['cinder_id'] = snapshot_id
|
||||
elif snapshot['name'].endswith('.clone_snap'):
|
||||
# Exclude clone snapshot.
|
||||
snapshot_info['reason_not_safe'] = (
|
||||
'used for clone snap')
|
||||
elif (snapshot['name'].startswith('backup')
|
||||
and '.snap.' in snapshot['name']):
|
||||
# Exclude intermediate snapshots created by the
|
||||
# Ceph backup driver.
|
||||
snapshot_info['reason_not_safe'] = (
|
||||
'used for volume backup')
|
||||
else:
|
||||
snapshot_info['safe_to_manage'] = True
|
||||
manageable_snapshots.append(snapshot_info)
|
||||
except self.rbd.ImageNotFound:
|
||||
LOG.debug("Image %s is not found.", image_name)
|
||||
|
||||
return volume_utils.paginate_entries_list(
|
||||
manageable_snapshots, marker, limit, offset, sort_keys, sort_dirs)
|
||||
|
||||
def unmanage_snapshot(self, snapshot):
|
||||
"""Removes the specified snapshot from Cinder management."""
|
||||
with RBDVolumeProxy(self, snapshot.volume_name) as volume:
|
||||
|
@ -0,0 +1,3 @@
|
||||
---
|
||||
features:
|
||||
- Allow rbd driver to list manageable snapshots.
|
Loading…
Reference in New Issue
Block a user