diff options
-rw-r--r-- | .zuul.yaml | 10 | ||||
-rw-r--r-- | cinder/tests/unit/volume/drivers/test_gpfs.py | 40 | ||||
-rw-r--r-- | cinder/tests/unit/volume/drivers/test_pure.py | 6 | ||||
-rw-r--r-- | cinder/volume/api.py | 3 | ||||
-rw-r--r-- | cinder/volume/drivers/ibm/gpfs.py | 30 | ||||
-rw-r--r-- | cinder/volume/drivers/pure.py | 19 | ||||
-rw-r--r-- | releasenotes/notes/bug-gpfs-fix-nfs-cow.yaml | 10 | ||||
-rw-r--r-- | releasenotes/notes/bug_1945824-7f8f238e274ddebd.yaml | 5 | ||||
-rw-r--r-- | releasenotes/notes/fix-transfer-accept-policy-7594806372b14284.yaml | 8 |
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. |