XtremIO: Add CG capability to generic groups.

Add consistency group capability to generic volume groups.

DocImpact

Change-Id: I0276769b5457961dafbfc4e7f570ac67aa41bbe3
implements: blueprint xtremio-cg-over-generic-groups
This commit is contained in:
Elad Zucker 2016-12-11 15:13:09 +02:00
parent 02389a1d2a
commit ca77a489dc
3 changed files with 267 additions and 7 deletions

View File

@ -820,8 +820,6 @@ class XtremIODriverISCSITestCase(BaseXtremIODriverTestCase):
add_volumes=[d.test_volume,
d.test_volume2])
self.driver.db = mock.Mock()
(self.driver.db.
volume_get_all_by_group.return_value) = [mock.MagicMock()]
self.driver.create_cgsnapshot(d.context, d.cgsnapshot, [snapshot_obj])
self.driver.delete_consistencygroup(d.context, d.group, [])
@ -938,6 +936,169 @@ class XtremIODriverISCSITestCase(BaseXtremIODriverTestCase):
self.driver.create_consistencygroup_from_src,
d.context, d.group, [], None, None, None, None)
# #### Groups ####
def test_group_create(self, req):
"""Test group create."""
req.side_effect = xms_request
d = self.data
self.driver.create_group(d.context, d.group)
self.assertEqual(1, len(xms_data['consistency-groups']))
def test_group_update(self, req):
"""Test group update."""
req.side_effect = xms_request
d = self.data
self.driver.create_consistencygroup(d.context, d.group)
self.driver.update_consistencygroup(d.context, d.group,
add_volumes=[d.test_volume,
d.test_volume2])
self.assertEqual(2, len(xms_data['consistency-group-volumes']))
self.driver.update_group(d.context, d.group,
remove_volumes=[d.test_volume2])
self.assertEqual(1, len(xms_data['consistency-group-volumes']))
def test_create_group_snapshot(self, req):
"""Test create group snapshot."""
req.side_effect = xms_request
d = self.data
snapshot_obj = fake_snapshot.fake_snapshot_obj(d.context)
snapshot_obj.consistencygroup_id = d.group['id']
self.driver.create_group(d.context, d.group)
self.driver.update_group(d.context, d.group,
add_volumes=[d.test_volume,
d.test_volume2])
res = self.driver.create_group_snapshot(d.context, d.cgsnapshot,
[snapshot_obj])
self.assertEqual((None, None), res)
def test_group_delete(self, req):
""""Test delete group."""
req.side_effect = xms_request
d = self.data
snapshot_obj = fake_snapshot.fake_snapshot_obj(d.context)
snapshot_obj.consistencygroup_id = d.group['id']
self.driver.create_group(d.context, d.group)
self.driver.update_group(d.context, d.group,
add_volumes=[d.test_volume,
d.test_volume2])
self.driver.db = mock.Mock()
(self.driver.db.
volume_get_all_by_group.return_value) = [mock.MagicMock()]
self.driver.create_group_snapshot(d.context, d.cgsnapshot,
[snapshot_obj])
self.driver.delete_group(d.context, d.group, [])
def test_group_snapshot(self, req):
"""test group snapshot."""
req.side_effect = xms_request
d = self.data
snapshot_obj = fake_snapshot.fake_snapshot_obj(d.context)
snapshot_obj.consistencygroup_id = d.group['id']
self.driver.create_group(d.context, d.group)
self.driver.update_group(d.context, d.group,
add_volumes=[d.test_volume,
d.test_volume2])
snapset_name = self.driver._get_cgsnap_name(d.cgsnapshot)
self.assertEqual(snapset_name,
'192eb39b6c2f420cbae33cfd117f0345192eb39b6c2f420cbae'
'33cfd117f9876')
snapset1 = {'ancestor-vol-id': ['', d.test_volume['id'], 2],
'consistencygroup_id': d.group['id'],
'name': snapset_name,
'index': 1}
xms_data['snapshot-sets'] = {snapset_name: snapset1, 1: snapset1}
res = self.driver.delete_group_snapshot(d.context, d.cgsnapshot,
[snapshot_obj])
self.assertEqual((None, None), res)
def test_delete_group_snapshot(self, req):
"""test delete group snapshot."""
d = self.data
snapshot_obj = fake_snapshot.fake_snapshot_obj(d.context)
snapshot_obj.consistencygroup_id = d.group['id']
self.driver.delete_group_snapshot(d.context, d.cgsnapshot,
[snapshot_obj])
req.assert_called_once_with('snapshot-sets', 'DELETE', None,
'192eb39b6c2f420cbae33cfd117f0345192eb39'
'b6c2f420cbae33cfd117f9876', None, 'v2')
def test_group_from_src_snapshot(self, req):
"""test group from source snapshot."""
req.side_effect = xms_request
d = self.data
self.driver.create_group(d.context, d.group)
self.driver.create_volume(d.test_volume)
self.driver.create_group_snapshot(d.context, d.cgsnapshot, [])
xms_data['volumes'][2]['ancestor-vol-id'] = (xms_data['volumes'][1]
['vol-id'])
snapset_name = self.driver._get_cgsnap_name(d.cgsnapshot)
snapset1 = {'vol-list': [xms_data['volumes'][2]['vol-id']],
'name': snapset_name,
'index': 1}
xms_data['snapshot-sets'] = {snapset_name: snapset1, 1: snapset1}
cg_obj = fake_cg.fake_consistencyobject_obj(d.context)
new_vol1 = fake_volume_obj(d.context)
snapshot1 = (fake_snapshot
.fake_snapshot_obj
(d.context, volume_id=d.test_volume['id']))
res = self.driver.create_group_from_src(d.context, cg_obj,
[new_vol1],
d.cgsnapshot,
[snapshot1])
self.assertEqual((None, None), res)
def test_group_from_src_group(self, req):
"""test group from source group."""
req.side_effect = xms_request
d = self.data
self.driver.create_group(d.context, d.group)
self.driver.create_volume(d.test_volume)
self.driver.create_group_snapshot(d.context, d.cgsnapshot, [])
xms_data['volumes'][2]['ancestor-vol-id'] = (xms_data['volumes'][1]
['vol-id'])
snapset_name = self.driver._get_cgsnap_name(d.cgsnapshot)
snapset1 = {'vol-list': [xms_data['volumes'][2]['vol-id']],
'name': snapset_name,
'index': 1}
xms_data['snapshot-sets'] = {snapset_name: snapset1, 1: snapset1}
cg_obj = fake_cg.fake_consistencyobject_obj(d.context)
new_vol1 = fake_volume_obj(d.context)
new_cg_obj = fake_cg.fake_consistencyobject_obj(
d.context, id=fake.CONSISTENCY_GROUP2_ID)
snapset2_name = new_cg_obj.id
new_vol1.id = '192eb39b-6c2f-420c-bae3-3cfd117f0001'
new_vol2 = fake_volume_obj(d.context)
snapset2 = {'vol-list': [xms_data['volumes'][2]['vol-id']],
'name': snapset2_name,
'index': 1}
xms_data['snapshot-sets'].update({5: snapset2,
snapset2_name: snapset2})
self.driver.create_group_from_src(d.context, new_cg_obj,
[new_vol2],
None, None,
cg_obj, [new_vol1])
def test_invalid_group_from_src_input(self, req):
"""test invalid group from source."""
req.side_effect = xms_request
d = self.data
self.assertRaises(exception.InvalidInput,
self.driver.create_group_from_src,
d.context, d.group, [], None, None, None, None)
@mock.patch('requests.request')
class XtremIODriverTestCase(BaseXtremIODriverTestCase):

View File

@ -408,15 +408,25 @@ class XtremIOVolumeDriver(san.SanDriver):
self.client = XtremIOClient4(self.configuration, self.cluster_id)
def create_volume(self, volume):
"Creates a volume"
"""Creates a volume."""
data = {'vol-name': volume['id'],
'vol-size': str(volume['size']) + 'g'
}
self.client.req('volumes', 'POST', data)
if volume.get('consistencygroup_id'):
# Add the volume to a cg in case volume requested a cgid or group_id.
# If both cg_id and group_id exists in a volume. group_id will take
# place.
consistency_group = volume.get('consistencygroup_id')
# if cg_id and group_id are both exists, we gives priority to group_id.
if volume.get('group_id'):
consistency_group = volume.get('group_id')
if consistency_group:
self.client.add_vol_to_cg(volume['id'],
volume['consistencygroup_id'])
consistency_group)
def create_volume_from_snapshot(self, volume, snapshot):
"""Creates a volume from a snapshot."""
@ -679,8 +689,6 @@ class XtremIOVolumeDriver(san.SanDriver):
self.client.req('consistency-groups', 'DELETE', name=group['id'],
ver='v2')
volumes = self.db.volume_get_all_by_group(context, group['id'])
for volume in volumes:
self.delete_volume(volume)
volume.status = 'deleted'
@ -787,6 +795,94 @@ class XtremIOVolumeDriver(san.SanDriver):
return None, None
def create_group(self, context, group):
"""Creates a group.
:param context: the context of the caller.
:param group: the group object.
:returns: model_update
"""
# the driver treats a group as a CG internally.
# We proxy the calls to the CG api.
return self.create_consistencygroup(context, group)
def delete_group(self, context, group, volumes):
"""Deletes a group.
:param context: the context of the caller.
:param group: the group object.
:param volumes: a list of volume objects in the group.
:returns: model_update, volumes_model_update
"""
# the driver treats a group as a CG internally.
# We proxy the calls to the CG api.
return self.delete_consistencygroup(context, group, volumes)
def update_group(self, context, group,
add_volumes=None, remove_volumes=None):
"""Updates a group.
:param context: the context of the caller.
:param group: the group object.
:param add_volumes: a list of volume objects to be added.
:param remove_volumes: a list of volume objects to be removed.
:returns: model_update, add_volumes_update, remove_volumes_update
"""
# the driver treats a group as a CG internally.
# We proxy the calls to the CG api.
return self.update_consistencygroup(context, group, add_volumes,
remove_volumes)
def create_group_from_src(self, context, group, volumes,
group_snapshot=None, snapshots=None,
source_group=None, source_vols=None):
"""Creates a group from source.
:param context: the context of the caller.
:param group: the Group object to be created.
:param volumes: a list of Volume objects in the group.
:param group_snapshot: the GroupSnapshot object as source.
:param snapshots: a list of snapshot objects in group_snapshot.
:param source_group: the Group object as source.
:param source_vols: a list of volume objects in the source_group.
:returns: model_update, volumes_model_update
"""
# the driver treats a group as a CG internally.
# We proxy the calls to the CG api.
return self.create_consistencygroup_from_src(context, group, volumes,
group_snapshot, snapshots,
source_group, source_vols)
def create_group_snapshot(self, context, group_snapshot, snapshots):
"""Creates a group_snapshot.
:param context: the context of the caller.
:param group_snapshot: the GroupSnapshot object to be created.
:param snapshots: a list of Snapshot objects in the group_snapshot.
:returns: model_update, snapshots_model_update
"""
# the driver treats a group as a CG internally.
# We proxy the calls to the CG api.
return self.create_cgsnapshot(context, group_snapshot, snapshots)
def delete_group_snapshot(self, context, group_snapshot, snapshots):
"""Deletes a group_snapshot.
:param context: the context of the caller.
:param group_snapshot: the GroupSnapshot object to be deleted.
:param snapshots: a list of snapshot objects in the group_snapshot.
:returns: model_update, snapshots_model_update
"""
# the driver treats a group as a CG internally.
# We proxy the calls to the CG api.
return self.delete_cgsnapshot(context, group_snapshot, snapshots)
def _get_ig(self, name):
try:
return self.client.req('initiator-groups', 'GET',

View File

@ -0,0 +1,3 @@
---
features:
- Add consistent group capability to generic volume groups in the XtremIO driver.