raise exception.VolumeBackendAPIException('Failed to create ig')
+def xms_failed_rename_snapshot_request(object_type='volumes',
+ request_typ='GET', data=None,
+ name=None, idx=None):
+ if request_typ == 'POST':
+ xms_data['volumes'][27] = {}
+ return {
+ "links": [
+ {
+ "href": "https://host/api/json/v2/types/snapshots/27",
+ "rel": "self"}]}
+ elif request_typ == 'PUT':
+ raise exception.VolumeBackendAPIException(msg='Failed to delete')
+ elif request_typ == 'DELETE':
+ del xms_data['volumes'][27]
+
+
class D(dict):
def update(self, *args, **kwargs):
self.__dict__.update(*args, **kwargs)
clean_xms_data()
self.driver.create_volume(self.data.test_volume)
self.driver.create_snapshot(self.data.test_snapshot)
+ self.assertEqual(self.data.test_snapshot['id'],
+ xms_data['volumes'][3]['name'])
self.driver.delete_snapshot(self.data.test_snapshot)
self.driver.delete_volume(self.data.test_volume)
+ def test_failed_rename_snapshot(self, req):
+ req.side_effect = xms_failed_rename_snapshot_request
+ self.driver.create_snapshot(self.data.test_snapshot)
+ self.assertIn(27, xms_data['volumes'])
+ clean_xms_data()
+
def test_volume_from_snapshot(self, req):
req.side_effect = xms_request
clean_xms_data()
def get_cluster(self):
return self.req('clusters', idx=1)['content']
+ def create_snapshot(self, src, dest, ro=False):
+ """Create a snapshot of a volume on the array.
+
+ XtreamIO array snapshots are also volumes.
+
+ :src: name of the source volume to be cloned
+ :dest: name for the new snapshot
+ :ro: new snapshot type ro/regular. only applicable to Client4
+ """
+ raise NotImplementedError()
+
class XtremIOClient3(XtremIOClient):
def __init__(self, configuration, cluster_id):
return self._portals
+ def create_snapshot(self, src, dest, ro=False):
+ data = {'snap-vol-name': dest, 'ancestor-vol-id': src}
+
+ self.req('snapshots', 'POST', data)
+
class XtremIOClient4(XtremIOClient):
def __init__(self, configuration, cluster_id):
return self.req('clusters', name=self.cluster_id)['content']
+ def create_snapshot(self, src, dest, ro=False):
+ data = {'snapshot-set-name': dest, 'snap-suffix': dest,
+ 'volume-list': [src],
+ 'snapshot-type': 'readonly' if ro else 'regular'}
+
+ res = self.req('snapshots', 'POST', data, ver='v2')
+ typ, idx = res['links'][0]['href'].split('/')[-2:]
+
+ # rename the snapshot
+ data = {'name': dest}
+ try:
+ self.req(typ, 'PUT', data, idx=int(idx))
+ except exception.VolumeBackendAPIException:
+ # reverting
+ msg = _LE('Failed to rename the created snapshot, reverting.')
+ LOG.error(msg)
+ self.req(typ, 'DELETE', idx=int(idx))
+ raise
+
class XtremIOVolumeDriver(san.SanDriver):
"""Executes commands relating to Volumes."""
def create_volume_from_snapshot(self, volume, snapshot):
"""Creates a volume from a snapshot."""
- data = {'snap-vol-name': volume['id'],
- 'ancestor-vol-id': snapshot.id}
-
- self.client.req('snapshots', 'POST', data)
+ self.client.create_snapshot(snapshot.id, volume['id'])
def create_cloned_volume(self, volume, src_vref):
"""Creates a clone of the specified volume."""
- data = {'snap-vol-name': volume['id'],
- 'ancestor-vol-id': src_vref['id']}
-
- self.client.req('snapshots', 'POST', data)
+ self.client.create_snapshot(src_vref['id'], volume['id'])
def delete_volume(self, volume):
"""Deletes a volume."""
def create_snapshot(self, snapshot):
"""Creates a snapshot."""
- data = {'snap-vol-name': snapshot.id,
- 'ancestor-vol-id': snapshot.volume_id}
-
- self.client.req('snapshots', 'POST', data)
+ self.client.create_snapshot(snapshot.volume_id, snapshot.id, True)
def delete_snapshot(self, snapshot):
"""Deletes a snapshot."""