Merge "Implement revert_to_snapshot() for StorPool."
This commit is contained in:
commit
3fe2aeebc7
@ -140,6 +140,16 @@ class MockAPI(object):
|
||||
volumes[new_name]['name'] = new_name
|
||||
del volumes[name]
|
||||
|
||||
def volumeRevert(self, name, data):
|
||||
if name not in volumes:
|
||||
raise MockApiError('No such volume {name}'.format(name=name))
|
||||
|
||||
snapname = data['toSnapshot']
|
||||
if snapname not in snapshots:
|
||||
raise MockApiError('No such snapshot {name}'.format(name=snapname))
|
||||
|
||||
volumes[name] = dict(snapshots[snapname])
|
||||
|
||||
|
||||
class MockAttachDB(object):
|
||||
def __init__(self, log):
|
||||
@ -155,6 +165,10 @@ class MockAttachDB(object):
|
||||
return snapshotName(vtype, vid)
|
||||
|
||||
|
||||
def MockVolumeRevertDesc(toSnapshot):
|
||||
return {'toSnapshot': toSnapshot}
|
||||
|
||||
|
||||
def MockVolumeUpdateDesc(size):
|
||||
return {'size': size}
|
||||
|
||||
@ -170,6 +184,7 @@ def MockSPConfig(section = 's01'):
|
||||
fakeStorPool.spapi.ApiError = MockApiError
|
||||
fakeStorPool.spconfig.SPConfig = MockSPConfig
|
||||
fakeStorPool.spopenstack.AttachDB = MockAttachDB
|
||||
fakeStorPool.sptypes.VolumeRevertDesc = MockVolumeRevertDesc
|
||||
fakeStorPool.sptypes.VolumeUpdateDesc = MockVolumeUpdateDesc
|
||||
|
||||
|
||||
@ -524,3 +539,51 @@ class StorPoolTestCase(test.TestCase):
|
||||
self.driver.get_pool({
|
||||
'volume_type': volume_type
|
||||
}))
|
||||
|
||||
def test_volume_revert(self):
|
||||
vol_id = 'rev1'
|
||||
vol_name = volumeName(vol_id)
|
||||
snap_id = 'rev-s1'
|
||||
snap_name = snapshotName('snap', snap_id)
|
||||
|
||||
self.assertVolumeNames([])
|
||||
self.assertDictEqual({}, volumes)
|
||||
self.assertDictEqual({}, snapshots)
|
||||
|
||||
self.driver.create_volume({'id': vol_id, 'name': 'v1', 'size': 1,
|
||||
'volume_type': None})
|
||||
self.assertVolumeNames((vol_id,))
|
||||
self.assertDictEqual({}, snapshots)
|
||||
|
||||
self.driver.create_snapshot({'id': snap_id, 'volume_id': vol_id})
|
||||
self.assertVolumeNames((vol_id,))
|
||||
self.assertListEqual([snap_name], sorted(snapshots.keys()))
|
||||
self.assertDictEqual(volumes[vol_name], snapshots[snap_name])
|
||||
self.assertIsNot(volumes[vol_name], snapshots[snap_name])
|
||||
|
||||
self.driver.extend_volume({'id': vol_id}, 2)
|
||||
self.assertVolumeNames((vol_id,))
|
||||
self.assertNotEqual(volumes[vol_name], snapshots[snap_name])
|
||||
|
||||
self.driver.revert_to_snapshot(None, {'id': vol_id}, {'id': snap_id})
|
||||
self.assertVolumeNames((vol_id,))
|
||||
self.assertDictEqual(volumes[vol_name], snapshots[snap_name])
|
||||
self.assertIsNot(volumes[vol_name], snapshots[snap_name])
|
||||
|
||||
self.driver.delete_snapshot({'id': snap_id})
|
||||
self.assertVolumeNames((vol_id,))
|
||||
self.assertDictEqual({}, snapshots)
|
||||
|
||||
self.assertRaisesRegex(exception.VolumeBackendAPIException,
|
||||
'No such snapshot',
|
||||
self.driver.revert_to_snapshot, None,
|
||||
{'id': vol_id}, {'id': snap_id})
|
||||
|
||||
self.driver.delete_volume({'id': vol_id})
|
||||
self.assertDictEqual({}, volumes)
|
||||
self.assertDictEqual({}, snapshots)
|
||||
|
||||
self.assertRaisesRegex(exception.VolumeBackendAPIException,
|
||||
'No such volume',
|
||||
self.driver.revert_to_snapshot, None,
|
||||
{'id': vol_id}, {'id': snap_id})
|
||||
|
@ -90,9 +90,10 @@ class StorPoolDriver(driver.VolumeDriver):
|
||||
1.2.2 - Reintroduce the driver into OpenStack Queens,
|
||||
add ignore_errors to the internal _detach_volume() method
|
||||
1.2.3 - Advertise some more driver capabilities.
|
||||
2.0.0 - Implement revert_to_snapshot().
|
||||
"""
|
||||
|
||||
VERSION = '1.2.3'
|
||||
VERSION = '2.0.0'
|
||||
CI_WIKI_NAME = 'StorPool_distributed_storage_CI'
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
@ -423,3 +424,18 @@ class StorPoolDriver(driver.VolumeDriver):
|
||||
'%(err)s',
|
||||
{'tname': temp_name, 'oname': orig_name, 'err': e})
|
||||
return {'_name_id': new_volume['_name_id'] or new_volume['id']}
|
||||
|
||||
def revert_to_snapshot(self, context, volume, snapshot):
|
||||
volname = self._attach.volumeName(volume['id'])
|
||||
snapname = self._attach.snapshotName('snap', snapshot['id'])
|
||||
try:
|
||||
rev = sptypes.VolumeRevertDesc(toSnapshot=snapname)
|
||||
self._attach.api().volumeRevert(volname, rev)
|
||||
except spapi.ApiError as e:
|
||||
LOG.error('StorPool revert_to_snapshot(): could not revert '
|
||||
'the %(vol_id)s volume to the %(snap_id)s snapshot: '
|
||||
'%(err)s',
|
||||
{'vol_id': volume['id'],
|
||||
'snap_id': snapshot['id'],
|
||||
'err': e})
|
||||
raise self._backendException(e)
|
||||
|
@ -953,7 +953,7 @@ driver.rbd=complete
|
||||
driver.rbd_iscsi=complete
|
||||
driver.sandstone=complete
|
||||
driver.seagate=missing
|
||||
driver.storpool=missing
|
||||
driver.storpool=complete
|
||||
driver.synology=missing
|
||||
driver.toyou_netstor=complete
|
||||
driver.toyou_netstor_tyds=missing
|
||||
|
@ -0,0 +1,5 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
StorPool driver: implemented revert to snapshot, which happens
|
||||
immediately i.e. without deleting and recreating the volume.
|
Loading…
Reference in New Issue
Block a user