Add CG capability to generic groups in GPFS driver

This patch adds the consistency group capability to generic group in
GPFS driver. Consistency groups will be used as generic groups.

Change-Id: I31b210a7186e9212b85ce4ec17693c1ae4bed908
Closes-bug: #1682249
This commit is contained in:
Gaurang Tapase 2017-06-01 05:57:21 -04:00
parent 49932bbd34
commit 6252bd8e5a
3 changed files with 387 additions and 74 deletions

View File

@ -1402,9 +1402,11 @@ class GPFSDriverTestCase(test.TestCase):
self.driver.copy_volume_to_image('', volume, '', '')
@mock.patch('cinder.utils.execute')
@mock.patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.'
'_get_volume_path')
@mock.patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.'
'_can_migrate_locally')
def test_migrate_volume_ok(self, mock_local, mock_exec):
def test_migrate_volume_ok(self, mock_local, volume_path, mock_exec):
volume = self._fake_volume()
host = {}
host = {'host': 'foo', 'capabilities': {}}
@ -1439,9 +1441,11 @@ class GPFSDriverTestCase(test.TestCase):
self.driver._migrate_volume(volume, host))
@mock.patch('cinder.utils.execute')
@mock.patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.'
'_get_volume_path')
@mock.patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.'
'_can_migrate_locally')
def test_migrate_volume_fail_mv(self, mock_local, mock_exec):
def test_migrate_volume_fail_mv(self, mock_local, mock_path, mock_exec):
volume = self._fake_volume()
host = {}
host = {'host': 'foo', 'capabilities': {}}
@ -1459,8 +1463,10 @@ class GPFSDriverTestCase(test.TestCase):
@mock.patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._migrate_volume')
@mock.patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.'
'_update_volume_storage_pool')
@mock.patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.local_path')
@mock.patch('cinder.volume.drivers.ibm.gpfs._different')
def test_retype_ok(self, mock_different, mock_strg_pool, mock_migrate_vol):
def test_retype_ok(self, mock_different, local_path,
mock_strg_pool, mock_migrate_vol):
ctxt = self.context
(volume, new_type, diff, host) = self._fake_retype_arguments()
self.driver.db = mock.Mock()
@ -1537,16 +1543,18 @@ class GPFSDriverTestCase(test.TestCase):
diff,
host))
@mock.patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.local_path')
@mock.patch('cinder.utils.execute')
def test_mkfs_ok(self, mock_exec):
def test_mkfs_ok(self, mock_exec, local_path):
volume = self._fake_volume()
self.driver._mkfs(volume, 'swap')
self.driver._mkfs(volume, 'swap', 'test')
self.driver._mkfs(volume, 'ext3', 'test')
self.driver._mkfs(volume, 'vfat', 'test')
@mock.patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.local_path')
@mock.patch('cinder.utils.execute')
def test_mkfs_fail_mk(self, mock_exec):
def test_mkfs_fail_mk(self, mock_exec, local_path):
volume = self._fake_volume()
mock_exec.side_effect = (
processutils.ProcessExecutionError(stdout='test', stderr='test'))
@ -1591,7 +1599,7 @@ class GPFSDriverTestCase(test.TestCase):
def test_create_consistencygroup(self, mock_exec):
ctxt = self.context
group = self._fake_group()
self.driver.create_consistencygroup(ctxt, group)
self.driver._create_consistencygroup(ctxt, group)
fsdev = self.driver._gpfs_device
cgname = "consisgroup-%s" % group['id']
cgpath = os.path.join(self.driver.configuration.gpfs_mount_point_base,
@ -1610,7 +1618,7 @@ class GPFSDriverTestCase(test.TestCase):
mock_exec.side_effect = (
processutils.ProcessExecutionError(stdout='test', stderr='test'))
self.assertRaises(exception.VolumeBackendAPIException,
self.driver.create_consistencygroup, ctxt, group)
self.driver._create_consistencygroup, ctxt, group)
@mock.patch('cinder.utils.execute')
def test_delete_consistencygroup(self, mock_exec):
@ -1625,7 +1633,7 @@ class GPFSDriverTestCase(test.TestCase):
self.driver.db.volume_get_all_by_group = mock.Mock()
self.driver.db.volume_get_all_by_group.return_value = volumes
self.driver.delete_consistencygroup(ctxt, group, [])
self.driver._delete_consistencygroup(ctxt, group, [])
fsdev = self.driver._gpfs_device
cgname = "consisgroup-%s" % group['id']
cmd = ['mmlsfileset', fsdev, cgname]
@ -1650,7 +1658,7 @@ class GPFSDriverTestCase(test.TestCase):
mock_exec.side_effect = (
processutils.ProcessExecutionError(exit_code=2))
self.driver.delete_consistencygroup(ctxt, group, [])
self.driver._delete_consistencygroup(ctxt, group, [])
fsdev = self.driver._gpfs_device
cgname = "consisgroup-%s" % group['id']
cmd = ['mmlsfileset', fsdev, cgname]
@ -1668,19 +1676,20 @@ class GPFSDriverTestCase(test.TestCase):
mock_exec.side_effect = (
processutils.ProcessExecutionError(stdout='test', stderr='test'))
self.assertRaises(exception.VolumeBackendAPIException,
self.driver.delete_consistencygroup, ctxt, group, [])
self.driver._delete_consistencygroup,
ctxt, group, [])
def test_update_consistencygroup(self):
ctxt = self.context
group = self._fake_group()
self.assertRaises(exception.GPFSDriverUnsupportedOperation,
self.driver.update_consistencygroup, ctxt, group)
self.driver._update_consistencygroup, ctxt, group)
def test_create_consisgroup_from_src(self):
ctxt = self.context
group = self._fake_group()
self.assertRaises(exception.GPFSDriverUnsupportedOperation,
self.driver.create_consistencygroup_from_src,
self.driver._create_consistencygroup_from_src,
ctxt, group, [])
@mock.patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.create_snapshot')
@ -1688,8 +1697,8 @@ class GPFSDriverTestCase(test.TestCase):
ctxt = self.context
cgsnap = self._fake_cgsnapshot()
snapshot1 = self._fake_snapshot()
model_update, snapshots = self.driver.create_cgsnapshot(ctxt, cgsnap,
[snapshot1])
model_update, snapshots = self.driver._create_cgsnapshot(ctxt, cgsnap,
[snapshot1])
self.driver.create_snapshot.assert_called_once_with(snapshot1)
self.assertEqual({'status': fields.ConsistencyGroupStatus.AVAILABLE},
model_update)
@ -1701,8 +1710,8 @@ class GPFSDriverTestCase(test.TestCase):
def test_create_cgsnapshot_empty(self, mock_create_snap):
ctxt = self.context
cgsnap = self._fake_cgsnapshot()
model_update, snapshots = self.driver.create_cgsnapshot(ctxt, cgsnap,
[])
model_update, snapshots = self.driver._create_cgsnapshot(ctxt, cgsnap,
[])
self.assertFalse(self.driver.create_snapshot.called)
self.assertEqual({'status': fields.ConsistencyGroupStatus.AVAILABLE},
model_update)
@ -1712,8 +1721,8 @@ class GPFSDriverTestCase(test.TestCase):
ctxt = self.context
cgsnap = self._fake_cgsnapshot()
snapshot1 = self._fake_snapshot()
model_update, snapshots = self.driver.delete_cgsnapshot(ctxt, cgsnap,
[snapshot1])
model_update, snapshots = self.driver._delete_cgsnapshot(ctxt, cgsnap,
[snapshot1])
self.driver.delete_snapshot.assert_called_once_with(snapshot1)
self.assertEqual({'status': fields.ConsistencyGroupStatus.DELETED},
model_update)
@ -1725,8 +1734,8 @@ class GPFSDriverTestCase(test.TestCase):
def test_delete_cgsnapshot_empty(self, mock_delete_snap):
ctxt = self.context
cgsnap = self._fake_cgsnapshot()
model_update, snapshots = self.driver.delete_cgsnapshot(ctxt, cgsnap,
[])
model_update, snapshots = self.driver._delete_cgsnapshot(ctxt, cgsnap,
[])
self.assertFalse(self.driver.delete_snapshot.called)
self.assertEqual({'status': fields.ConsistencyGroupStatus.DELETED},
model_update)
@ -1741,8 +1750,14 @@ class GPFSDriverTestCase(test.TestCase):
ret = self.driver.local_path(volume)
self.assertEqual(volume_path, ret)
def test_local_path_volume_in_cg(self):
@mock.patch('cinder.db.get_by_id')
@mock.patch('cinder.volume.utils.is_group_a_cg_snapshot_type')
def test_local_path_volume_in_cg(self, mock_group_cg_snapshot_type,
mock_group_obj):
mock_group_cg_snapshot_type.return_value = True
volume = self._fake_volume()
group = self._fake_group()
mock_group_obj.return_value = group
cgname = "consisgroup-%s" % volume['group_id']
volume_path = os.path.join(
self.driver.configuration.gpfs_mount_point_base,
@ -1806,7 +1821,11 @@ class GPFSDriverTestCase(test.TestCase):
group = {}
group['name'] = 'test_group'
group['id'] = fake.CONSISTENCY_GROUP_ID
return group
group['user_id'] = fake.USER_ID
group['group_type_id'] = fake.GROUP_TYPE_ID
group['project_id'] = fake.PROJECT_ID
return objects.Group(self.context, **group)
def _fake_cgsnapshot(self):
snapshot = self._fake_snapshot()
@ -1851,6 +1870,150 @@ class GPFSDriverTestCase(test.TestCase):
return (volume, new_type, diff, host)
@mock.patch('cinder.volume.utils.is_group_a_cg_snapshot_type')
def test_create_group(self, mock_cg_snapshot_type):
mock_cg_snapshot_type.return_value = False
ctxt = self.context
group = self._fake_group()
self.assertRaises(
NotImplementedError,
self.driver.create_group,
ctxt, group
)
@mock.patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.'
'_create_consistencygroup')
@mock.patch('cinder.volume.utils.is_group_a_cg_snapshot_type')
def test_create_group_cg(self, mock_cg_snapshot_type,
mock_consisgroup_create):
mock_cg_snapshot_type.return_value = True
ctxt = self.context
group = self._fake_group()
self.driver.create_group(ctxt, group)
mock_consisgroup_create.assert_called_once_with(ctxt, group)
@mock.patch('cinder.volume.utils.is_group_a_cg_snapshot_type')
def test_delete_group(self, mock_cg_snapshot_type):
mock_cg_snapshot_type.return_value = False
ctxt = self.context
group = self._fake_group()
volumes = []
self.assertRaises(
NotImplementedError,
self.driver.delete_group,
ctxt, group, volumes
)
@mock.patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.'
'_delete_consistencygroup')
@mock.patch('cinder.volume.utils.is_group_a_cg_snapshot_type')
def test_delete_group_cg(self, mock_cg_snapshot_type,
mock_consisgroup_delete):
mock_cg_snapshot_type.return_value = True
ctxt = self.context
group = self._fake_group()
volumes = []
self.driver.delete_group(ctxt, group, volumes)
mock_consisgroup_delete.assert_called_once_with(ctxt, group, volumes)
@mock.patch('cinder.volume.utils.is_group_a_cg_snapshot_type')
def test_update_group(self, mock_cg_snapshot_type):
mock_cg_snapshot_type.return_value = False
ctxt = self.context
group = self._fake_group()
self.assertRaises(
NotImplementedError,
self.driver.update_group,
ctxt, group
)
@mock.patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.'
'_update_consistencygroup')
@mock.patch('cinder.volume.utils.is_group_a_cg_snapshot_type')
def test_update_group_cg(self, mock_cg_snapshot_type,
mock_consisgroup_update):
mock_cg_snapshot_type.return_value = True
ctxt = self.context
group = self._fake_group()
self.driver.update_group(ctxt, group)
mock_consisgroup_update.assert_called_once_with(ctxt, group,
None, None)
@mock.patch('cinder.volume.utils.is_group_a_cg_snapshot_type')
def test_create_group_snapshot(self, mock_cg_snapshot_type):
mock_cg_snapshot_type.return_value = False
ctxt = self.context
group_snapshot = mock.MagicMock()
snapshots = [mock.Mock()]
self.assertRaises(
NotImplementedError,
self.driver.create_group_snapshot,
ctxt, group_snapshot, snapshots
)
@mock.patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.'
'_create_cgsnapshot')
@mock.patch('cinder.volume.utils.is_group_a_cg_snapshot_type')
def test_create_group_snapshot_cg(self, mock_cg_snapshot_type,
mock_cgsnapshot_create):
mock_cg_snapshot_type.return_value = True
ctxt = self.context
group_snapshot = mock.MagicMock()
snapshots = [mock.Mock()]
self.driver.create_group_snapshot(ctxt, group_snapshot, snapshots)
mock_cgsnapshot_create.assert_called_once_with(ctxt, group_snapshot,
snapshots)
@mock.patch('cinder.volume.utils.is_group_a_cg_snapshot_type')
def test_delete_group_snapshot(self, mock_cg_snapshot_type):
mock_cg_snapshot_type.return_value = False
ctxt = self.context
group_snapshot = mock.MagicMock()
snapshots = [mock.Mock()]
self.assertRaises(
NotImplementedError,
self.driver.delete_group_snapshot,
ctxt, group_snapshot, snapshots
)
@mock.patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.'
'_delete_cgsnapshot')
@mock.patch('cinder.volume.utils.is_group_a_cg_snapshot_type')
def test_delete_group_snapshot_cg(self, mock_cg_snapshot_type,
mock_cgsnapshot_delete):
mock_cg_snapshot_type.return_value = True
ctxt = self.context
group_snapshot = mock.MagicMock()
snapshots = [mock.Mock()]
self.driver.delete_group_snapshot(ctxt, group_snapshot, snapshots)
mock_cgsnapshot_delete.assert_called_once_with(ctxt, group_snapshot,
snapshots)
@mock.patch('cinder.volume.utils.is_group_a_cg_snapshot_type')
def test_create_group_from_src(self, mock_cg_snapshot_type):
mock_cg_snapshot_type.return_value = False
ctxt = self.context
group = self._fake_group()
volumes = []
self.assertRaises(
NotImplementedError,
self.driver.create_group_from_src,
ctxt, group, volumes
)
@mock.patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.'
'_create_consistencygroup_from_src')
@mock.patch('cinder.volume.utils.is_group_a_cg_snapshot_type')
def test_create_group_from_src_cg(self, mock_cg_snapshot_type,
mock_cg_clone_create):
mock_cg_snapshot_type.return_value = True
ctxt = self.context
group = self._fake_group()
volumes = []
self.driver.create_group_from_src(ctxt, group, volumes)
mock_cg_clone_create.assert_called_once_with(ctxt, group, volumes,
None, None, None, None)
class GPFSRemoteDriverTestCase(test.TestCase):
"""Unit tests for GPFSRemoteDriver class"""
@ -2004,11 +2167,24 @@ class GPFSNFSDriverTestCase(test.TestCase):
def _fake_volume(self):
volume = {}
volume['id'] = '123456'
volume['name'] = 'test'
volume['id'] = fake.VOLUME_ID
volume['display_name'] = 'test'
volume['metadata'] = {'key1': 'val1'}
volume['_name_id'] = None
volume['size'] = 1000
volume['group_id'] = 'cg-1234'
return volume
volume['group_id'] = fake.CONSISTENCY_GROUP_ID
return objects.Volume(self.context, **volume)
def _fake_group(self):
group = {}
group['name'] = 'test_group'
group['id'] = fake.CONSISTENCY_GROUP_ID
group['user_id'] = fake.USER_ID
group['group_type_id'] = fake.GROUP_TYPE_ID
group['project_id'] = fake.PROJECT_ID
return objects.Group(self.context, **group)
def _fake_snapshot(self):
snapshot = {}
@ -2056,26 +2232,50 @@ class GPFSNFSDriverTestCase(test.TestCase):
self.assertEqual('GPFSNFS', stats['volume_backend_name'])
self.assertEqual('file', stats['storage_protocol'])
def test_get_volume_path(self):
@mock.patch('cinder.db.get_by_id')
@mock.patch('cinder.volume.utils.is_group_a_cg_snapshot_type')
def test_get_volume_path(self, mock_group_cg_snapshot_type, mock_group):
mock_group_cg_snapshot_type.return_value = True
self.driver.configuration.gpfs_mount_point_base = (
self.TEST_GPFS_MNT_POINT_BASE)
volume = self._fake_volume()
self.assertEqual('/export/consisgroup-cg-1234/test',
group = self._fake_group()
mock_group.return_value = group
volume_path_in_cg = os.path.join(self.TEST_GPFS_MNT_POINT_BASE,
'consisgroup-' +
fake.CONSISTENCY_GROUP_ID,
'volume-' + fake.VOLUME_ID)
self.assertEqual(volume_path_in_cg,
self.driver._get_volume_path(volume))
volume['group_id'] = None
self.assertEqual('/export/test',
volume.group_id = None
volume_path = os.path.join(self.TEST_GPFS_MNT_POINT_BASE,
'volume-' + fake.VOLUME_ID)
self.assertEqual(volume_path,
self.driver._get_volume_path(volume))
@mock.patch('cinder.db.get_by_id')
@mock.patch('cinder.volume.utils.is_group_a_cg_snapshot_type')
@mock.patch('cinder.volume.drivers.ibm.gpfs.GPFSNFSDriver.'
'_get_mount_point_for_share')
def test_local_path(self, mock_mount_point):
mock_mount_point.return_value = self.TEST_MNT_POINT
def test_local_path(self, mock_mount_point,
mock_group_cg_snapshot_type,
mock_group):
mock_mount_point.return_value = self.TEST_MNT_POINT_BASE
mock_group_cg_snapshot_type.return_value = True
volume = self._fake_volume()
volume['provider_location'] = self.TEST_GPFS_MNT_POINT_BASE
self.assertEqual('/mnt/nfs/consisgroup-cg-1234/test',
group = self._fake_group()
mock_group.return_value = group
volume['provider_location'] = self.TEST_MNT_POINT_BASE
local_volume_path_in_cg = os.path.join(self.TEST_MNT_POINT_BASE,
'consisgroup-' +
fake.CONSISTENCY_GROUP_ID,
'volume-' + fake.VOLUME_ID)
self.assertEqual(local_volume_path_in_cg,
self.driver.local_path(volume))
volume['group_id'] = None
self.assertEqual('/mnt/nfs/test',
volume.group_id = None
local_volume_path = os.path.join(self.TEST_MNT_POINT_BASE,
'volume-' + fake.VOLUME_ID)
self.assertEqual(local_volume_path,
self.driver.local_path(volume))
@mock.patch('cinder.volume.drivers.ibm.gpfs.GPFSNFSDriver.'

View File

@ -39,6 +39,7 @@ from cinder.volume import driver
from cinder.volume.drivers import nfs
from cinder.volume.drivers import remotefs
from cinder.volume.drivers.san import san
from cinder.volume import utils as volume_utils
GPFS_CLONE_MIN_RELEASE = 1200
GPFS_ENC_MIN_RELEASE = 1404
@ -771,18 +772,20 @@ class GPFSDriver(driver.CloneableImageVD,
"""Return the local path for the specified volume."""
# Check if the volume is part of a consistency group and return
# the local_path accordingly.
if volume['group_id'] is not None:
cgname = "consisgroup-%s" % volume['group_id']
volume_path = os.path.join(
self.configuration.gpfs_mount_point_base,
cgname,
volume['name']
)
else:
volume_path = os.path.join(
self.configuration.gpfs_mount_point_base,
volume['name']
)
if volume.group_id is not None:
if volume_utils.is_group_a_cg_snapshot_type(volume.group):
cgname = "consisgroup-%s" % volume.group_id
volume_path = os.path.join(
self.configuration.gpfs_mount_point_base,
cgname,
volume.name
)
return volume_path
volume_path = os.path.join(
self.configuration.gpfs_mount_point_base,
volume.name
)
return volume_path
def _get_gpfs_encryption_status(self):
@ -858,6 +861,7 @@ class GPFSDriver(driver.CloneableImageVD,
'root_path': gpfs_base})
data['consistencygroup_support'] = 'True'
data['consistent_group_snapshot_enabled'] = True
if self._encryption_state.lower() == 'yes':
data['gpfs_encryption_rest'] = 'True'
@ -1120,7 +1124,7 @@ class GPFSDriver(driver.CloneableImageVD,
LOG.error(msg)
raise exception.VolumeBackendAPIException(data=msg)
def create_consistencygroup(self, context, group):
def _create_consistencygroup(self, context, group):
"""Create consistency group of GPFS volumes."""
cgname = "consisgroup-%s" % group['id']
fsdev = self._gpfs_device
@ -1156,10 +1160,10 @@ class GPFSDriver(driver.CloneableImageVD,
LOG.error(msg)
raise exception.VolumeBackendAPIException(data=msg)
model_update = {'status': fields.ConsistencyGroupStatus.AVAILABLE}
model_update = {'status': fields.GroupStatus.AVAILABLE}
return model_update
def delete_consistencygroup(self, context, group, volumes):
def _delete_consistencygroup(self, context, group, volumes):
"""Delete consistency group of GPFS volumes."""
cgname = "consisgroup-%s" % group['id']
fsdev = self._gpfs_device
@ -1208,9 +1212,9 @@ class GPFSDriver(driver.CloneableImageVD,
return None, None
def create_cgsnapshot(self, context, cgsnapshot, snapshots):
def _create_cgsnapshot(self, context, cgsnapshot, snapshots):
"""Create snapshot of a consistency group of GPFS volumes."""
model_update = {'status': fields.ConsistencyGroupStatus.AVAILABLE}
model_update = {'status': fields.GroupStatus.AVAILABLE}
snapshots_model_update = []
try:
@ -1218,7 +1222,7 @@ class GPFSDriver(driver.CloneableImageVD,
self.create_snapshot(snapshot)
except exception.VolumeBackendAPIException as err:
model_update['status'] = (
fields.ConsistencyGroupStatus.ERROR)
fields.GroupStatus.ERROR)
LOG.error("Failed to create the snapshot %(snap)s of "
"CGSnapshot. Exception: %(exception)s.",
{'snap': snapshot.name, 'exception': err})
@ -1230,9 +1234,9 @@ class GPFSDriver(driver.CloneableImageVD,
return model_update, snapshots_model_update
def delete_cgsnapshot(self, context, cgsnapshot, snapshots):
def _delete_cgsnapshot(self, context, cgsnapshot, snapshots):
"""Delete snapshot of a consistency group of GPFS volumes."""
model_update = {'status': fields.ConsistencyGroupStatus.DELETED}
model_update = {'status': fields.GroupStatus.DELETED}
snapshots_model_update = []
try:
@ -1240,7 +1244,7 @@ class GPFSDriver(driver.CloneableImageVD,
self.delete_snapshot(snapshot)
except exception.VolumeBackendAPIException as err:
model_update['status'] = (
fields.ConsistencyGroupStatus.ERROR_DELETING)
fields.GroupStatus.ERROR_DELETING)
LOG.error("Failed to delete the snapshot %(snap)s of "
"CGSnapshot. Exception: %(exception)s.",
{'snap': snapshot.name, 'exception': err})
@ -1252,20 +1256,127 @@ class GPFSDriver(driver.CloneableImageVD,
return model_update, snapshots_model_update
def update_consistencygroup(self, context, group,
add_volumes=None, remove_volumes=None):
def _update_consistencygroup(self, context, group,
add_volumes=None, remove_volumes=None):
msg = _('Updating a consistency group is not supported.')
LOG.error(msg)
raise exception.GPFSDriverUnsupportedOperation(msg=msg)
def create_consistencygroup_from_src(self, context, group, volumes,
cgsnapshot=None, snapshots=None,
source_cg=None, source_vols=None):
def _create_consistencygroup_from_src(self, context, group, volumes,
cgsnapshot=None, snapshots=None,
source_cg=None, source_vols=None):
msg = _('Creating a consistency group from any source consistency '
'group or consistency group snapshot is not supported.')
LOG.error(msg)
raise exception.GPFSDriverUnsupportedOperation(msg=msg)
def create_group(self, ctxt, group):
"""Creates a group.
:param ctxt: the context of the caller.
:param group: the Group object of the group to be created.
:returns: model_update
"""
if volume_utils.is_group_a_cg_snapshot_type(group):
return self._create_consistencygroup(ctxt, group)
# If it wasn't a consistency group request ignore it and we'll rely on
# the generic group implementation.
raise NotImplementedError()
def delete_group(self, ctxt, group, volumes):
"""Deletes a group.
:param ctxt: the context of the caller.
:param group: the Group object of the group to be deleted.
:param volumes: a list of Volume objects in the group.
:returns: model_update, volumes_model_update
"""
if volume_utils.is_group_a_cg_snapshot_type(group):
return self._delete_consistencygroup(ctxt, group, volumes)
# If it wasn't a consistency group request ignore it and we'll rely on
# the generic group implementation.
raise NotImplementedError()
def update_group(self, ctxt, group,
add_volumes=None, remove_volumes=None):
"""Updates a group.
:param ctxt: the context of the caller.
:param group: the Group object of the group to be updated.
: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
"""
if volume_utils.is_group_a_cg_snapshot_type(group):
return self._update_consistencygroup(ctxt,
group,
add_volumes,
remove_volumes)
# If it wasn't a consistency group request ignore it and we'll rely on
# the generic group implementation.
raise NotImplementedError()
def create_group_snapshot(self, ctxt, group_snapshot, snapshots):
"""Creates a group_snapshot.
:param ctxt: 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
"""
if volume_utils.is_group_a_cg_snapshot_type(group_snapshot):
return self._create_cgsnapshot(ctxt, group_snapshot, snapshots)
# If it wasn't a consistency group request ignore it and we'll rely on
# the generic group implementation.
raise NotImplementedError()
def delete_group_snapshot(self, ctxt, group_snapshot, snapshots):
"""Deletes a group_snapshot.
:param ctxt: 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
"""
if volume_utils.is_group_a_cg_snapshot_type(group_snapshot):
return self._delete_cgsnapshot(ctxt, group_snapshot, snapshots)
# If it wasn't a consistency group request ignore it and we'll rely on
# the generic group implementation.
raise NotImplementedError()
def create_group_from_src(self, ctxt, group, volumes,
group_snapshot=None, snapshots=None,
source_group=None, source_vols=None):
"""Creates a group from source.
:param ctxt: 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
"""
if volume_utils.is_group_a_cg_snapshot_type(group):
return self._create_consistencygroup_from_src(ctxt,
group,
volumes,
group_snapshot,
snapshots,
source_group,
source_vols)
# If it wasn't a consistency group request ignore it and we'll rely on
# the generic group implementation.
raise NotImplementedError()
@interface.volumedriver
class GPFSRemoteDriver(GPFSDriver, san.SanDriver):
@ -1467,18 +1578,18 @@ class GPFSNFSDriver(GPFSDriver, nfs.NfsDriver, san.SanDriver):
'root_path': gpfs_base})
data['consistencygroup_support'] = 'True'
data['consistent_group_snapshot_enabled'] = True
self._stats = data
LOG.debug("Exit _update_volume_stats.")
def _get_volume_path(self, volume):
"""Returns remote GPFS path for the given volume."""
export_path = self.configuration.gpfs_mount_point_base
if volume['group_id'] is not None:
cgname = "consisgroup-%s" % volume['group_id']
volume_path = os.path.join(export_path, cgname, volume['name'])
else:
volume_path = os.path.join(export_path, volume['name'])
return volume_path
if volume.group_id is not None:
if volume_utils.is_group_a_cg_snapshot_type(volume.group):
cgname = "consisgroup-%s" % volume.group_id
return os.path.join(export_path, cgname, volume.name)
return os.path.join(export_path, volume.name)
def local_path(self, volume):
"""Returns the local path for the specified volume."""
@ -1487,12 +1598,11 @@ class GPFSNFSDriver(GPFSDriver, nfs.NfsDriver, san.SanDriver):
# Check if the volume is part of a consistency group and return
# the local_path accordingly.
if volume['group_id'] is not None:
cgname = "consisgroup-%s" % volume['group_id']
volume_path = os.path.join(base_local_path, cgname, volume['name'])
else:
volume_path = os.path.join(base_local_path, volume['name'])
return volume_path
if volume.group_id is not None:
if volume_utils.is_group_a_cg_snapshot_type(volume.group):
cgname = "consisgroup-%s" % volume.group_id
return os.path.join(base_local_path, cgname, volume.name)
return os.path.join(base_local_path, volume.name)
def _get_snapshot_path(self, snapshot):
"""Returns remote GPFS path for the given snapshot."""

View File

@ -0,0 +1,3 @@
---
features:
- Added consistent group capability to generic volume groups in GPFS driver.