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:
parent
49932bbd34
commit
6252bd8e5a
@ -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.'
|
||||
|
@ -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."""
|
||||
|
@ -0,0 +1,3 @@
|
||||
---
|
||||
features:
|
||||
- Added consistent group capability to generic volume groups in GPFS driver.
|
Loading…
Reference in New Issue
Block a user