summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.zuul.yaml10
-rw-r--r--cinder/tests/unit/volume/drivers/test_gpfs.py40
-rw-r--r--cinder/tests/unit/volume/drivers/test_pure.py6
-rw-r--r--cinder/volume/api.py3
-rw-r--r--cinder/volume/drivers/ibm/gpfs.py30
-rw-r--r--cinder/volume/drivers/pure.py19
-rw-r--r--releasenotes/notes/bug-gpfs-fix-nfs-cow.yaml10
-rw-r--r--releasenotes/notes/bug_1945824-7f8f238e274ddebd.yaml5
-rw-r--r--releasenotes/notes/fix-transfer-accept-policy-7594806372b14284.yaml8
9 files changed, 100 insertions, 31 deletions
diff --git a/.zuul.yaml b/.zuul.yaml
index 182194959..a79713ee6 100644
--- a/.zuul.yaml
+++ b/.zuul.yaml
@@ -69,6 +69,11 @@
irrelevant-files: *gate-irrelevant-files
- tempest-ipv6-only:
irrelevant-files: *gate-irrelevant-files
+ - openstacksdk-functional-devstack:
+ required-projects:
+ - name: opendev.org/openstack/openstacksdk
+ override-branch: stable/wallaby
+ irrelevant-files: *gate-irrelevant-files
gate:
jobs:
- cinder-grenade-mn-sub-volbak:
@@ -81,6 +86,11 @@
irrelevant-files: *gate-irrelevant-files
- tempest-ipv6-only:
irrelevant-files: *gate-irrelevant-files
+ - openstacksdk-functional-devstack:
+ required-projects:
+ - name: opendev.org/openstack/openstacksdk
+ override-branch: stable/wallaby
+ irrelevant-files: *gate-irrelevant-files
experimental:
jobs:
- tempest-cinder-v2-api:
diff --git a/cinder/tests/unit/volume/drivers/test_gpfs.py b/cinder/tests/unit/volume/drivers/test_gpfs.py
index 6ffea6116..67666c6ec 100644
--- a/cinder/tests/unit/volume/drivers/test_gpfs.py
+++ b/cinder/tests/unit/volume/drivers/test_gpfs.py
@@ -154,6 +154,25 @@ class GPFSDriverTestCase(test.TestCase):
self.driver._check_gpfs_state)
@mock.patch('cinder.utils.execute')
+ def test_same_filesystem_ok(self, mock_exec):
+ # returns filesystem id in hex
+ mock_exec.return_value = ('ef0009600000002\nef0009600000002\n', '')
+ self.assertTrue(self.driver._same_filesystem('/path1', '/path2'))
+
+ @mock.patch('cinder.utils.execute')
+ def test_same_filesystem_not_ok(self, mock_exec):
+ # returns filesystem id in hex
+ mock_exec.return_value = ('ef0009600000002\n000000000000007\n', '')
+ self.assertFalse(self.driver._same_filesystem('/path1', '/path2'))
+
+ @mock.patch('cinder.utils.execute')
+ def test_same_filesystem_failed(self, mock_exec):
+ mock_exec.side_effect = processutils.ProcessExecutionError(
+ stdout='test', stderr='test')
+ self.assertRaises(exception.VolumeBackendAPIException,
+ self.driver._same_filesystem, '', '')
+
+ @mock.patch('cinder.utils.execute')
def test_get_fs_from_path_ok(self, mock_exec):
mock_exec.return_value = ('Filesystem 1K-blocks '
'Used Available Use%% Mounted on\n'
@@ -559,12 +578,12 @@ class GPFSDriverTestCase(test.TestCase):
conf.SHARED_CONF_GROUP)
# fail configuration.gpfs_images_share_mode == 'copy_on_write' and not
- # _same_filesystem(configuration.gpfs_mount_point_base,
+ # self._same_filesystem(configuration.gpfs_mount_point_base,
# configuration.gpfs_images_dir)
self.override_config('gpfs_images_share_mode', 'copy_on_write',
conf.SHARED_CONF_GROUP)
- with mock.patch('cinder.volume.drivers.ibm.gpfs._same_filesystem',
- return_value=False):
+ with mock.patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.'
+ '_same_filesystem', return_value=False):
self.assertRaises(exception.VolumeBackendAPIException,
self.driver.check_for_setup_error)
@@ -1281,21 +1300,22 @@ class GPFSDriverTestCase(test.TestCase):
@mock.patch('cinder.image.image_utils.qemu_img_info')
@mock.patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.'
'_is_gpfs_parent_file')
- @mock.patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.local_path')
+ @mock.patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.'
+ '_get_volume_path')
@mock.patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._is_cloneable')
@mock.patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.'
'_verify_gpfs_path_state')
def test_clone_image_format_raw_copy(self,
mock_verify_gpfs_path_state,
mock_is_cloneable,
- mock_local_path,
+ mock_get_volume_path,
mock_is_gpfs_parent_file,
mock_qemu_img_info,
mock_copyfile,
mock_set_rw_permission,
mock_resize_volume_file):
mock_is_cloneable.return_value = (True, 'test', self.images_dir)
- mock_local_path.return_value = self.volumes_path
+ mock_get_volume_path.return_value = self.volumes_path
mock_qemu_img_info.return_value = self._fake_qemu_raw_image_info('')
volume = self._fake_volume()
org_value = self.driver.configuration.gpfs_images_share_mode
@@ -2255,7 +2275,11 @@ class GPFSNFSDriverTestCase(test.TestCase):
@mock.patch('cinder.volume.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.patch('cinder.volume.drivers.ibm.gpfs.GPFSNFSDriver.'
+ '_find_share')
+ def test_local_path(self,
+ mock_find_share,
+ mock_mount_point,
mock_group_cg_snapshot_type,
mock_group):
mock_mount_point.return_value = self.TEST_MNT_POINT_BASE
@@ -2263,7 +2287,7 @@ class GPFSNFSDriverTestCase(test.TestCase):
volume = self._fake_volume()
group = self._fake_group()
mock_group.return_value = group
- volume['provider_location'] = self.TEST_MNT_POINT_BASE
+ mock_find_share.return_value = self.TEST_VOLUME_PATH
local_volume_path_in_cg = os.path.join(self.TEST_MNT_POINT_BASE,
'consisgroup-' +
fake.CONSISTENCY_GROUP_ID,
diff --git a/cinder/tests/unit/volume/drivers/test_pure.py b/cinder/tests/unit/volume/drivers/test_pure.py
index dc5fd8984..e55821f33 100644
--- a/cinder/tests/unit/volume/drivers/test_pure.py
+++ b/cinder/tests/unit/volume/drivers/test_pure.py
@@ -1639,7 +1639,7 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
mock_cgsnapshot = mock.Mock()
mock_snapshots = [mock.Mock() for i in range(5)]
mock_volumes = [mock.Mock() for i in range(5)]
- result = self.driver.create_consistencygroup_from_src(
+ self.driver.create_consistencygroup_from_src(
mock_context,
mock_group,
mock_volumes,
@@ -1648,7 +1648,6 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
source_cg=None,
source_vols=None
)
- self.assertEqual((None, None), result)
mock_create_cg.assert_called_with(mock_context, mock_group)
expected_calls = [mock.call(vol, snap)
for vol, snap in zip(mock_volumes, mock_snapshots)]
@@ -1675,14 +1674,13 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
mock_source_cg = mock.MagicMock()
mock_volumes = [mock.MagicMock() for i in range(num_volumes)]
mock_source_vols = [mock.MagicMock() for i in range(num_volumes)]
- result = self.driver.create_consistencygroup_from_src(
+ self.driver.create_consistencygroup_from_src(
mock_context,
mock_group,
mock_volumes,
source_cg=mock_source_cg,
source_vols=mock_source_vols
)
- self.assertEqual((None, None), result)
mock_create_cg.assert_called_with(mock_context, mock_group)
self.assertTrue(self.array.create_pgroup_snapshot.called)
self.assertTrue(self.array.destroy_pgroup.called)
diff --git a/cinder/volume/api.py b/cinder/volume/api.py
index ae1bee553..cfd1925d4 100644
--- a/cinder/volume/api.py
+++ b/cinder/volume/api.py
@@ -51,7 +51,6 @@ from cinder.policies import snapshot_metadata as s_meta_policy
from cinder.policies import snapshots as snapshot_policy
from cinder.policies import volume_actions as vol_action_policy
from cinder.policies import volume_metadata as vol_meta_policy
-from cinder.policies import volume_transfer as vol_transfer_policy
from cinder.policies import volumes as vol_policy
from cinder import quota
from cinder import quota_utils
@@ -828,8 +827,6 @@ class API(base.Base):
def accept_transfer(self, context, volume, new_user, new_project,
no_snapshots=False):
- context.authorize(vol_transfer_policy.ACCEPT_POLICY,
- target_obj=volume)
if volume['status'] == 'maintenance':
LOG.info('Unable to accept transfer for volume, '
'because it is in maintenance.', resource=volume)
diff --git a/cinder/volume/drivers/ibm/gpfs.py b/cinder/volume/drivers/ibm/gpfs.py
index 55c4eb222..aa9ea89eb 100644
--- a/cinder/volume/drivers/ibm/gpfs.py
+++ b/cinder/volume/drivers/ibm/gpfs.py
@@ -134,11 +134,6 @@ def _different(difference_tuple):
return False
-def _same_filesystem(path1, path2):
- """Return true if the two paths are in the same GPFS file system."""
- return os.lstat(path1).st_dev == os.lstat(path2).st_dev
-
-
def _sizestr(size_in_g):
"""Convert the specified size into a string value."""
return '%sG' % size_in_g
@@ -204,6 +199,19 @@ class GPFSDriver(driver.CloneableImageVD,
raise exception.VolumeBackendAPIException(
data=_('GPFS is not running, state: %s.') % gpfs_state)
+ def _same_filesystem(self, path1, path2):
+ """Return true if the two paths are in the same GPFS file system."""
+ try:
+ (out, err) = self.gpfs_execute('stat', '-f', '-c', '"%i"',
+ path1, path2)
+ lines = out.splitlines()
+ return lines[0] == lines[1]
+ except processutils.ProcessExecutionError as exc:
+ LOG.error('Failed to issue stat command on path '
+ '%(path1)s and path %(path2)s, error: %(error)s',
+ {'path1': path1, 'path2': path2, 'error': exc.stderr})
+ raise exception.VolumeBackendAPIException(data=exc.stderr)
+
def _get_filesystem_from_path(self, path):
"""Return filesystem for specified path."""
try:
@@ -435,8 +443,8 @@ class GPFSDriver(driver.CloneableImageVD,
raise exception.VolumeBackendAPIException(data=msg)
if(self.configuration.gpfs_images_share_mode == 'copy_on_write' and
- not _same_filesystem(self.configuration.gpfs_mount_point_base,
- self.configuration.gpfs_images_dir)):
+ not self._same_filesystem(self.configuration.gpfs_mount_point_base,
+ self.configuration.gpfs_images_dir)):
msg = (_('gpfs_images_share_mode is set to copy_on_write, but '
'%(vol)s and %(img)s belong to different file '
'systems.') %
@@ -907,13 +915,13 @@ class GPFSDriver(driver.CloneableImageVD,
{'img': image_id, 'reas': reason})
return (None, False)
- vol_path = self.local_path(volume)
-
data = image_utils.qemu_img_info(image_path)
# if image format is already raw either clone it or
# copy it depending on config file settings
+ # GPFS command (mmclone) needs to run on GPFS node on GPFS path
if data.file_format == 'raw':
+ vol_path = self._get_volume_path(volume)
if (self.configuration.gpfs_images_share_mode ==
'copy_on_write'):
LOG.debug('Clone image to vol %s using mmclone.',
@@ -929,7 +937,9 @@ class GPFSDriver(driver.CloneableImageVD,
shutil.copyfile(image_path, vol_path)
# if image is not raw convert it to raw into vol_path destination
+ # Image conversion can be run locally on GPFS mount path
else:
+ vol_path = self.local_path(volume)
LOG.debug('Clone image to vol %s using qemu convert.',
volume['id'])
image_utils.convert_image(image_path, vol_path, 'raw')
@@ -1587,7 +1597,7 @@ class GPFSNFSDriver(GPFSDriver, nfs.NfsDriver, san.SanDriver):
def local_path(self, volume):
"""Returns the local path for the specified volume."""
- remotefs_share = volume['provider_location']
+ remotefs_share = self._find_share(volume)
base_local_path = self._get_mount_point_for_share(remotefs_share)
# Check if the volume is part of a consistency group and return
diff --git a/cinder/volume/drivers/pure.py b/cinder/volume/drivers/pure.py
index 332176778..7487232e6 100644
--- a/cinder/volume/drivers/pure.py
+++ b/cinder/volume/drivers/pure.py
@@ -544,6 +544,7 @@ class PureBaseVolumeDriver(san.SanDriver):
repl_status = fields.ReplicationStatus.ENABLED
model_update = {
+ 'id': volume.id,
'provider_id': purity_vol_name,
'replication_status': repl_status,
}
@@ -970,8 +971,11 @@ class PureBaseVolumeDriver(san.SanDriver):
The new volumes will be consistent with the snapshot.
"""
+ vol_models = []
for volume, snapshot in zip(volumes, snapshots):
- self.create_volume_from_snapshot(volume, snapshot)
+ vol_models.append(self.create_volume_from_snapshot(volume,
+ snapshot))
+ return vol_models
def _create_cg_from_cg(self, group, source_group, volumes, source_vols):
"""Creates a new consistency group from an existing cg.
@@ -979,6 +983,7 @@ class PureBaseVolumeDriver(san.SanDriver):
The new volumes will be in a consistent state, but this requires
taking a new temporary group snapshot and cloning from that.
"""
+ vol_models = []
pgroup_name = self._get_pgroup_name(source_group)
tmp_suffix = '%s-tmp' % uuid.uuid4()
tmp_pgsnap_name = '%(pgroup_name)s.%(pgsnap_suffix)s' % {
@@ -1007,19 +1012,21 @@ class PureBaseVolumeDriver(san.SanDriver):
)
finally:
self._delete_pgsnapshot(tmp_pgsnap_name)
+ return vol_models
@pure_driver_debug_trace
def create_consistencygroup_from_src(self, context, group, volumes,
cgsnapshot=None, snapshots=None,
source_cg=None, source_vols=None):
- self.create_consistencygroup(context, group)
+ model_update = self.create_consistencygroup(context, group)
if cgsnapshot and snapshots:
- self._create_cg_from_cgsnap(volumes,
- snapshots)
+ vol_models = self._create_cg_from_cgsnap(volumes,
+ snapshots)
elif source_cg:
- self._create_cg_from_cg(group, source_cg, volumes, source_vols)
+ vol_models = self._create_cg_from_cg(group, source_cg,
+ volumes, source_vols)
- return None, None
+ return model_update, vol_models
@pure_driver_debug_trace
def delete_consistencygroup(self, context, group, volumes):
diff --git a/releasenotes/notes/bug-gpfs-fix-nfs-cow.yaml b/releasenotes/notes/bug-gpfs-fix-nfs-cow.yaml
new file mode 100644
index 000000000..866cb820f
--- /dev/null
+++ b/releasenotes/notes/bug-gpfs-fix-nfs-cow.yaml
@@ -0,0 +1,10 @@
+---
+fixes:
+ - |
+ `Bug #1947134 <https://bugs.launchpad.net/cinder/+bug/1947134>`_: Fixed
+ the initialization of GPFS NFS driver when gpfs_images_share_mode
+ is set to copy_on_write by correcting _same_filesystem functionality.
+ - |
+ `Bug #1947123 <https://bugs.launchpad.net/cinder/+bug/1947123>`_: Fixed
+ the volume creation issue in GPFS NFS driver when gpfs_images_share_mode
+ is set to copy_on_write.
diff --git a/releasenotes/notes/bug_1945824-7f8f238e274ddebd.yaml b/releasenotes/notes/bug_1945824-7f8f238e274ddebd.yaml
new file mode 100644
index 000000000..1d1ed0c7f
--- /dev/null
+++ b/releasenotes/notes/bug_1945824-7f8f238e274ddebd.yaml
@@ -0,0 +1,5 @@
+---
+fixes:
+ - |
+ Pure Storage driver `Bug #1945824 <https://bugs.launchpad.net/cinder/+bug/1945824>`_:
+ Fixed missing DB values when creating new consistency group from CG snapshot.
diff --git a/releasenotes/notes/fix-transfer-accept-policy-7594806372b14284.yaml b/releasenotes/notes/fix-transfer-accept-policy-7594806372b14284.yaml
new file mode 100644
index 000000000..24de5752a
--- /dev/null
+++ b/releasenotes/notes/fix-transfer-accept-policy-7594806372b14284.yaml
@@ -0,0 +1,8 @@
+---
+fixes:
+ - |
+ `Bug #1950474 <https://bugs.launchpad.net/cinder/+bug/1950474>`_: Fixed
+ policy authorization for transfer accept API. Previously, if an operator
+ had overridden the default transfer accept policy to something project
+ specific in policy.yaml file, it would break the transfer accept API
+ which is fixed in this release.