diff --git a/cinder/tests/unit/volume/drivers/solidfire/test_solidfire.py b/cinder/tests/unit/volume/drivers/solidfire/test_solidfire.py index 2fd85ba8de4..4eacec41e0d 100644 --- a/cinder/tests/unit/volume/drivers/solidfire/test_solidfire.py +++ b/cinder/tests/unit/volume/drivers/solidfire/test_solidfire.py @@ -3728,6 +3728,32 @@ class SolidFireVolumeTestCase(test.TestCase): sfv.migrate_volume, ctx, vol, host) mock_do_intercluster_volume_migration.assert_not_called() + @mock.patch.object(solidfire.SolidFireDriver, + '_do_intercluster_volume_migration') + def test_migrate_volume_retyping_status( + self, mock_do_intercluster_volume_migration): + + ctx = context.get_admin_context() + type_fields = {'id': fakes.get_fake_uuid()} + src_vol_type = fake_volume.fake_volume_type_obj(ctx, **type_fields) + + vol_fields = { + 'id': fakes.get_fake_uuid(), + 'volume_type': src_vol_type, + 'host': 'fakeHost@fakeBackend#fakePool', + 'status': 'retyping' + } + + vol = fake_volume.fake_volume_obj(ctx, **vol_fields) + vol.volume_type = src_vol_type + host = {'host': 'fakeHost@fakeBackend#fakePool'} + + sfv = solidfire.SolidFireDriver(configuration=self.configuration) + result = sfv.migrate_volume(ctx, vol, host) + + mock_do_intercluster_volume_migration.assert_not_called() + self.assertEqual((True, {}), result) + @mock.patch.object(solidfire.SolidFireDriver, '_do_intercluster_volume_migration') def test_migrate_volume_same_host_and_backend( @@ -4192,3 +4218,40 @@ class SolidFireVolumeTestCase(test.TestCase): call('RemoveVolumePair', src_params, '8.0'), call('DeleteVolume', src_params), call('PurgeDeletedVolume', src_params)]) + + @data(True, False) + @mock.patch.object(solidfire.SolidFireDriver, '_create_cluster_reference') + @mock.patch.object(solidfire.SolidFireDriver, '_set_cluster_pairs') + @mock.patch.object(solidfire.SolidFireDriver, '_update_cluster_status') + @mock.patch.object(solidfire.SolidFireDriver, '_issue_api_request') + def test_list_volumes_by_name(self, has_endpoint, mock_issue_api_request, + mock_update_cluster_status, + mock_set_cluster_pairs, + mock_create_cluster_reference): + fake_sf_volume_name = 'fake-vol-name' + vol_fields = { + 'id': fakes.get_fake_uuid(), + 'name': fake_sf_volume_name + } + vol = fake_volume.fake_volume_obj( + context.get_admin_context(), **vol_fields) + + fake_endpoint = None + volumes_list = [vol] + + if has_endpoint: + fake_endpoint = self.fake_primary_cluster["endpoint"] + volumes_list = [] + + mock_issue_api_request.return_value = { + 'result': {'volumes': volumes_list}} + + sfv = solidfire.SolidFireDriver(configuration=self.configuration) + result = ( + sfv._list_volumes_by_name(fake_sf_volume_name, + endpoint=fake_endpoint)) + + mock_issue_api_request.assert_called_once_with( + 'ListVolumes', {'volumeName': fake_sf_volume_name}, + version='8.0', endpoint=fake_endpoint) + self.assertEqual(result, volumes_list) diff --git a/cinder/volume/drivers/solidfire.py b/cinder/volume/drivers/solidfire.py index f9f759751e8..a5e50e9cca6 100644 --- a/cinder/volume/drivers/solidfire.py +++ b/cinder/volume/drivers/solidfire.py @@ -276,9 +276,13 @@ class SolidFireDriver(san.SanISCSIDriver): by adding xNotPrimary to the retryable exception list 2.2.2 - Fix bug #1896112 SolidFire Driver creates duplicate volume when API response is lost + 2.2.3 - Fix bug #1942090 SolidFire retype fails due to volume status + as retyping. + Fix bug #1932964 SolidFire duplicate volume name exception + on migration and replication. """ - VERSION = '2.2.2' + VERSION = '2.2.3' SUPPORTS_ACTIVE_ACTIVE = True @@ -1015,10 +1019,10 @@ class SolidFireDriver(san.SanISCSIDriver): params['attributes'] = attributes return self._issue_api_request('ModifyVolume', params) - def _list_volumes_by_name(self, sf_volume_name): + def _list_volumes_by_name(self, sf_volume_name, endpoint=None): params = {'volumeName': sf_volume_name} - return self._issue_api_request( - 'ListVolumes', params, version='8.0')['result']['volumes'] + return self._issue_api_request('ListVolumes', params, version='8.0', + endpoint=endpoint)['result']['volumes'] def _wait_volume_is_active(self, sf_volume_name): @@ -1046,9 +1050,10 @@ class SolidFireDriver(san.SanISCSIDriver): raise SolidFireAPIException(msg) def _do_volume_create(self, sf_account, params, endpoint=None): - sf_volume_name = params['name'] - volumes_found = self._list_volumes_by_name(sf_volume_name) + volumes_found = self._list_volumes_by_name(sf_volume_name, + endpoint=endpoint) + if volumes_found: raise SolidFireDuplicateVolumeNames(vol_name=sf_volume_name) @@ -2522,9 +2527,10 @@ class SolidFireDriver(san.SanISCSIDriver): LOG.info("Migrate volume %(vol_id)s to %(host)s.", {"vol_id": volume.id, "host": host["host"]}) - if volume.status != fields.VolumeStatus.AVAILABLE: - msg = _("Volume status must be 'available' to execute " - "storage assisted migration.") + if (volume.status != fields.VolumeStatus.AVAILABLE and + volume.status != fields.VolumeStatus.RETYPING): + msg = _("Volume status must be 'available' or 'retyping' to " + "execute storage assisted migration.") LOG.error(msg) raise exception.InvalidVolume(reason=msg) diff --git a/releasenotes/notes/solidfire-fix-retype-and-name-exception-on-migration-2af26f095b7cb345.yaml b/releasenotes/notes/solidfire-fix-retype-and-name-exception-on-migration-2af26f095b7cb345.yaml new file mode 100644 index 00000000000..23382d6d29d --- /dev/null +++ b/releasenotes/notes/solidfire-fix-retype-and-name-exception-on-migration-2af26f095b7cb345.yaml @@ -0,0 +1,10 @@ +--- +fixes: + - | + NetApp SolidFire driver `Bug #1932964 + `_: + Fixed a name exception that occurs on any volume migration. + - | + NetApp SolidFire driver `Bug #1942090 + `_: + Fixed a status exception that occurs on volume retype with migration.