From 853f082884a06e318e7d07249c708c56fd5cf0e3 Mon Sep 17 00:00:00 2001 From: Fabio Oliveira Date: Mon, 30 Aug 2021 11:52:41 -0300 Subject: [PATCH] NetApp Solidfire: Fix retype and name exception on migration While performing retype or migrate on a volume the name exception occurs due to the check on all backends including the origin. The retype status exception occurs because the only accepted state is available, but retype changes the status to retyping. This change just assures to check the name on the target backend and also adds retyping as a valid status for migrate condition. Change-Id: Ic09d65a0a6ecbb529dc0e4b041650ead449e1273 Closes-Bug: 1942090 Closes-Bug: 1932964 --- .../drivers/solidfire/test_solidfire.py | 63 +++++++++++++++++++ cinder/volume/drivers/solidfire.py | 24 ++++--- ...ception-on-migration-2af26f095b7cb345.yaml | 10 +++ 3 files changed, 88 insertions(+), 9 deletions(-) create mode 100644 releasenotes/notes/solidfire-fix-retype-and-name-exception-on-migration-2af26f095b7cb345.yaml 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.