From bcc12d383a82250bda0f5c4c06203b0655613be1 Mon Sep 17 00:00:00 2001 From: Simon O'Donovan Date: Thu, 18 Apr 2019 16:05:56 +0100 Subject: [PATCH] PowerMax driver - changing from 9.0 to 9.1 REST endpoints Changing unisphere for powermax REST endpoint from 9.0 to 9.1. Change-Id: Ie072e1c4cd2db204664896dc4dc0c131a9341d57 --- .../dell_emc/powermax/powermax_data.py | 12 ++--- .../powermax/powermax_fake_objects.py | 2 +- .../dell_emc/powermax/test_powermax_common.py | 4 +- .../dell_emc/powermax/test_powermax_rest.py | 52 +++++++++---------- cinder/volume/drivers/dell_emc/powermax/fc.py | 3 +- .../volume/drivers/dell_emc/powermax/iscsi.py | 3 +- .../volume/drivers/dell_emc/powermax/rest.py | 45 ++++++++-------- ...x-90-to-91-endpoints-a92c4d158cb63fe4.yaml | 5 ++ 8 files changed, 68 insertions(+), 58 deletions(-) create mode 100644 releasenotes/notes/powermax-90-to-91-endpoints-a92c4d158cb63fe4.yaml diff --git a/cinder/tests/unit/volume/drivers/dell_emc/powermax/powermax_data.py b/cinder/tests/unit/volume/drivers/dell_emc/powermax/powermax_data.py index e1c0ef5c4f7..4a9e5b77a8e 100644 --- a/cinder/tests/unit/volume/drivers/dell_emc/powermax/powermax_data.py +++ b/cinder/tests/unit/volume/drivers/dell_emc/powermax/powermax_data.py @@ -67,7 +67,7 @@ class PowerMaxData(object): device_id4 = '00004' rdf_group_name = '23_24_007' rdf_group_no = '70' - u4v_version = '90' + u4v_version = '91' storagegroup_name_source = 'Grp_source_sg' storagegroup_name_target = 'Grp_target_sg' group_snapshot_name = 'Grp_snapshot' @@ -438,12 +438,12 @@ class PowerMaxData(object): portgroup = [{'portGroupId': port_group_name_f, 'symmetrixPortKey': [ {'directorId': 'FA-1D', - 'portId': 'FA-1D:4'}], + 'portId': '4'}], 'maskingview': [masking_view_name_f]}, {'portGroupId': port_group_name_i, 'symmetrixPortKey': [ {'directorId': 'SE-4E', - 'portId': 'SE-4E:0'}], + 'portId': '0'}], 'maskingview': [masking_view_name_i]}] port_list = [ @@ -663,7 +663,7 @@ class PowerMaxData(object): # replication volume_snap_vx = {'snapshotLnks': [], - 'snapshotSrc': [ + 'snapshotSrcs': [ {'generation': 0, 'linkedDevices': [ {'targetDevice': device_id2, @@ -748,7 +748,7 @@ class PowerMaxData(object): {'symmetrixId': array_herc, 'model': 'PowerMax 2000', 'ucode': '5978.1091.1092'}] - version_details = {'version': 'V9.0.0.1'} + version_details = {'version': 'V9.1.0.1'} headroom = {'headroom': [{'headroomCapacity': 20348.29}]} @@ -995,7 +995,7 @@ class PowerMaxData(object): data_dict = {volume_id: volume_info_dict} platform = 'Linux-4.4.0-104-generic-x86_64-with-Ubuntu-16.04-xenial' - unisphere_version = u'V9.0.0.1' + unisphere_version = u'V9.1.0.1' openstack_release = '12.0.0.0b3.dev401' openstack_version = '12.0.0' python_version = '2.7.12' diff --git a/cinder/tests/unit/volume/drivers/dell_emc/powermax/powermax_fake_objects.py b/cinder/tests/unit/volume/drivers/dell_emc/powermax/powermax_fake_objects.py index c02ddc726d5..bd8a20f513c 100644 --- a/cinder/tests/unit/volume/drivers/dell_emc/powermax/powermax_fake_objects.py +++ b/cinder/tests/unit/volume/drivers/dell_emc/powermax/powermax_fake_objects.py @@ -229,7 +229,7 @@ class FakeRequestsSession(object): if job['jobId'] in url: return_object = job break - elif 'version' in url: + elif 'info' in url: return_object = self.data.version_details else: for symm in self.data.symmetrix: diff --git a/cinder/tests/unit/volume/drivers/dell_emc/powermax/test_powermax_common.py b/cinder/tests/unit/volume/drivers/dell_emc/powermax/test_powermax_common.py index 101ba2467c1..69c0179d8a3 100644 --- a/cinder/tests/unit/volume/drivers/dell_emc/powermax/test_powermax_common.py +++ b/cinder/tests/unit/volume/drivers/dell_emc/powermax/test_powermax_common.py @@ -1072,8 +1072,10 @@ class PowerMaxCommonTest(test.TestCase): def test_get_ip_and_iqn(self): ref_ip_iqn = [{'iqn': self.data.initiator, 'ip': self.data.ip}] + director = self.data.portgroup[1]['symmetrixPortKey'][0]['directorId'] port = self.data.portgroup[1]['symmetrixPortKey'][0]['portId'] - ip_iqn_list = self.common._get_ip_and_iqn(self.data.array, port) + dirport = "%s:%s" % (director, port) + ip_iqn_list = self.common._get_ip_and_iqn(self.data.array, dirport) self.assertEqual(ref_ip_iqn, ip_iqn_list) def test_find_ip_and_iqns(self): diff --git a/cinder/tests/unit/volume/drivers/dell_emc/powermax/test_powermax_rest.py b/cinder/tests/unit/volume/drivers/dell_emc/powermax/test_powermax_rest.py index c1c6708de0c..6e5e1d28c31 100644 --- a/cinder/tests/unit/volume/drivers/dell_emc/powermax/test_powermax_rest.py +++ b/cinder/tests/unit/volume/drivers/dell_emc/powermax/test_powermax_rest.py @@ -228,7 +228,7 @@ class PowerMaxRestTest(test.TestCase): def test_get_uni_version(self): version, major_version = self.rest.get_uni_version() - self.assertEqual('90', major_version) + self.assertEqual('91', major_version) with mock.patch.object(self.rest, '_get_request', return_value=None): version, major_version = self.rest.get_uni_version() self.assertIsNone(major_version) @@ -317,12 +317,12 @@ class PowerMaxRestTest(test.TestCase): 'storageGroupId': self.data.storagegroup_name_f, 'emulation': 'FBA', 'sloBasedStorageGroupParam': [ - {'num_of_vols': 0, - 'sloId': self.data.slo, + {'sloId': self.data.slo, 'workloadSelection': 'NONE', - 'volumeAttribute': { + 'volumeAttributes': [{ 'volume_size': '0', - 'capacityUnit': 'GB'}}]} + 'capacityUnit': 'GB', + 'num_of_vols': 0}]}]} mock_sg.assert_called_once_with(self.data.array, payload) def test_create_storage_group_failed(self): @@ -350,12 +350,12 @@ class PowerMaxRestTest(test.TestCase): 'storageGroupId': self.data.default_sg_compr_disabled, 'emulation': 'FBA', 'sloBasedStorageGroupParam': [ - {'num_of_vols': 0, - 'sloId': self.data.slo, + {'sloId': self.data.slo, 'workloadSelection': self.data.workload, - 'volumeAttribute': { + 'volumeAttributes': [{ 'volume_size': '0', - 'capacityUnit': 'GB'}, + 'capacityUnit': 'GB', + 'num_of_vols': 0}], 'noCompression': 'true'}]} mock_sg.assert_called_once_with(self.data.array, payload) @@ -475,8 +475,9 @@ class PowerMaxRestTest(test.TestCase): def test_add_child_sg_to_parent_sg(self): payload = {'editStorageGroupActionParam': { - 'addExistingStorageGroupParam': { - 'storageGroupId': [self.data.storagegroup_name_f]}}} + 'expandStorageGroupParam': { + 'addExistingStorageGroupParam': { + 'storageGroupId': [self.data.storagegroup_name_f]}}}} with mock.patch.object( self.rest, 'modify_storage_group', return_value=(202, self.data.job_list[0])) as mck_mod_sg: @@ -484,7 +485,7 @@ class PowerMaxRestTest(test.TestCase): self.data.array, self.data.storagegroup_name_f, self.data.parent_sg_f, self.data.extra_specs) mck_mod_sg.assert_called_once_with( - self.data.array, self.data.parent_sg_f, payload, version='83') + self.data.array, self.data.parent_sg_f, payload) def test_remove_child_sg_from_parent_sg(self): payload = {'editStorageGroupActionParam': { @@ -1001,7 +1002,7 @@ class PowerMaxRestTest(test.TestCase): def test_create_volume_snap(self): snap_name = self.data.volume_snap_vx[ - 'snapshotSrc'][0]['snapshotName'] + 'snapshotSrcs'][0]['snapshotName'] device_id = self.data.device_id extra_specs = self.data.extra_specs payload = {'deviceNameListSource': [{'name': device_id}], @@ -1034,8 +1035,8 @@ class PowerMaxRestTest(test.TestCase): array = self.data.array source_id = self.data.device_id target_id = self.data.volume_snap_vx[ - 'snapshotSrc'][0]['linkedDevices'][0]['targetDevice'] - snap_name = self.data.volume_snap_vx['snapshotSrc'][0]['snapshotName'] + 'snapshotSrcs'][0]['linkedDevices'][0]['targetDevice'] + snap_name = self.data.volume_snap_vx['snapshotSrcs'][0]['snapshotName'] extra_specs = self.data.extra_specs payload = {'deviceNameListSource': [{'name': source_id}], 'deviceNameListTarget': [ @@ -1043,8 +1044,7 @@ class PowerMaxRestTest(test.TestCase): 'copy': 'true', 'action': "", 'star': 'false', 'force': 'false', 'exact': 'false', 'remote': 'false', - 'symforce': 'false', 'nocopy': 'false', - 'generation': 0} + 'symforce': 'false', 'generation': 0} payload_restore = {'deviceNameListSource': [{'name': source_id}], 'deviceNameListTarget': [{'name': source_id}], 'action': 'Restore', @@ -1094,7 +1094,7 @@ class PowerMaxRestTest(test.TestCase): def test_delete_volume_snap(self): array = self.data.array - snap_name = self.data.volume_snap_vx['snapshotSrc'][0]['snapshotName'] + snap_name = self.data.volume_snap_vx['snapshotSrcs'][0]['snapshotName'] source_device_id = self.data.device_id payload = {'deviceNameListSource': [{'name': source_device_id}], 'generation': 0} @@ -1108,7 +1108,7 @@ class PowerMaxRestTest(test.TestCase): def test_delete_volume_snap_restore(self): array = self.data.array - snap_name = self.data.volume_snap_vx['snapshotSrc'][0]['snapshotName'] + snap_name = self.data.volume_snap_vx['snapshotSrcs'][0]['snapshotName'] source_device_id = self.data.device_id payload = {'deviceNameListSource': [{'name': source_device_id}], 'restore': True, 'generation': 0} @@ -1128,22 +1128,22 @@ class PowerMaxRestTest(test.TestCase): def test_get_volume_snap(self): array = self.data.array - snap_name = self.data.volume_snap_vx['snapshotSrc'][0]['snapshotName'] + snap_name = self.data.volume_snap_vx['snapshotSrcs'][0]['snapshotName'] device_id = self.data.device_id - ref_snap = self.data.volume_snap_vx['snapshotSrc'][0] + ref_snap = self.data.volume_snap_vx['snapshotSrcs'][0] snap = self.rest.get_volume_snap(array, device_id, snap_name) self.assertEqual(ref_snap, snap) def test_get_volume_snap_none(self): array = self.data.array - snap_name = self.data.volume_snap_vx['snapshotSrc'][0]['snapshotName'] + snap_name = self.data.volume_snap_vx['snapshotSrcs'][0]['snapshotName'] device_id = self.data.device_id with mock.patch.object(self.rest, 'get_volume_snap_info', return_value=None): snap = self.rest.get_volume_snap(array, device_id, snap_name) self.assertIsNone(snap) with mock.patch.object(self.rest, 'get_volume_snap_info', - return_value={'snapshotSrc': []}): + return_value={'snapshotSrcs': []}): snap = self.rest.get_volume_snap(array, device_id, snap_name) self.assertIsNone(snap) @@ -1167,10 +1167,10 @@ class PowerMaxRestTest(test.TestCase): source_id = self.data.device_id generation = 0 target_id = self.data.volume_snap_vx[ - 'snapshotSrc'][0]['linkedDevices'][0]['targetDevice'] - snap_name = self.data.volume_snap_vx['snapshotSrc'][0]['snapshotName'] + 'snapshotSrcs'][0]['linkedDevices'][0]['targetDevice'] + snap_name = self.data.volume_snap_vx['snapshotSrcs'][0]['snapshotName'] ref_sync = self.data.volume_snap_vx[ - 'snapshotSrc'][0]['linkedDevices'][0] + 'snapshotSrcs'][0]['linkedDevices'][0] sync = self.rest.get_sync_session( array, source_id, snap_name, target_id, generation) self.assertEqual(ref_sync, sync) diff --git a/cinder/volume/drivers/dell_emc/powermax/fc.py b/cinder/volume/drivers/dell_emc/powermax/fc.py index 11723852c3c..577e8e1ef53 100644 --- a/cinder/volume/drivers/dell_emc/powermax/fc.py +++ b/cinder/volume/drivers/dell_emc/powermax/fc.py @@ -108,9 +108,10 @@ class PowerMaxFCDriver(san.SanDriver, driver.FibreChannelDriver): - Fix for PowerMax OS replication settings (bug #1812685) - Support for storage-assisted in-use retype (bp/powermax-storage-assisted-inuse-retype) + 4.1.0 - Changing from 90 to 91 rest endpoints """ - VERSION = "4.0.0" + VERSION = "4.1.0" # ThirdPartySystems wiki CI_WIKI_NAME = "EMC_VMAX_CI" diff --git a/cinder/volume/drivers/dell_emc/powermax/iscsi.py b/cinder/volume/drivers/dell_emc/powermax/iscsi.py index bb7a548e16d..45be71f095e 100644 --- a/cinder/volume/drivers/dell_emc/powermax/iscsi.py +++ b/cinder/volume/drivers/dell_emc/powermax/iscsi.py @@ -113,9 +113,10 @@ class PowerMaxISCSIDriver(san.SanISCSIDriver): - Fix for PowerMax OS replication settings (bug #1812685) - Support for storage-assisted in-use retype (bp/powermax-storage-assisted-inuse-retype) + 4.1.0 - Changing from 90 to 91 rest endpoints """ - VERSION = "4.0.0" + VERSION = "4.1.0" # ThirdPartySystems wiki CI_WIKI_NAME = "EMC_VMAX_CI" diff --git a/cinder/volume/drivers/dell_emc/powermax/rest.py b/cinder/volume/drivers/dell_emc/powermax/rest.py index 7161181c490..1ae12a4a977 100644 --- a/cinder/volume/drivers/dell_emc/powermax/rest.py +++ b/cinder/volume/drivers/dell_emc/powermax/rest.py @@ -38,7 +38,7 @@ LOG = logging.getLogger(__name__) SLOPROVISIONING = 'sloprovisioning' REPLICATION = 'replication' SYSTEM = 'system' -U4V_VERSION = '90' +U4V_VERSION = '91' UCODE_5978 = '5978' retry_exc_tuple = (exception.VolumeBackendAPIException,) # HTTP constants @@ -584,8 +584,8 @@ class PowerMaxRest(object): :returns: version dict """ - version_url = "/%s/system/version" % U4V_VERSION - version_dict = self._get_request(version_url, 'version') + version_url = "/%s/system/info" % U4V_VERSION + version_dict = self._get_request(version_url, 'info') if not version_dict: LOG.error("Unisphere version info not found.") return version_dict @@ -678,7 +678,8 @@ class PowerMaxRest(object): :returns: bool """ is_compression_capable = False - target_uri = "/84/sloprovisioning/symmetrix?compressionCapable=true" + target_uri = ("/%s/sloprovisioning/symmetrix?compressionCapable=true" + % U4V_VERSION) status_code, message = self.request(target_uri, GET) self.check_status_code_success( "Check if compression enabled", status_code, message) @@ -750,10 +751,11 @@ class PowerMaxRest(object): :param extra_specs: the extra specifications """ payload = {"editStorageGroupActionParam": { - "addExistingStorageGroupParam": { - "storageGroupId": [child_sg]}}} - sc, job = self.modify_storage_group(array, parent_sg, payload, - version="83") + "expandStorageGroupParam": { + "addExistingStorageGroupParam": { + "storageGroupId": [child_sg]}}}} + + sc, job = self.modify_storage_group(array, parent_sg, payload) self.wait_for_job('Add child sg to parent sg', sc, job, extra_specs) def remove_child_sg_from_parent_sg( @@ -806,12 +808,12 @@ class PowerMaxRest(object): if slo: if self.is_next_gen_array(array): workload = 'NONE' - slo_param = {"num_of_vols": 0, - "sloId": slo, + slo_param = {"sloId": slo, "workloadSelection": workload, - "volumeAttribute": { + "volumeAttributes": [{ "volume_size": "0", - "capacityUnit": "GB"}} + "capacityUnit": "GB", + "num_of_vols": 0}]} if do_disable_compression: slo_param.update({"noCompression": "true"}) elif self.is_compression_capable(array): @@ -854,7 +856,7 @@ class PowerMaxRest(object): {"executionOption": "ASYNCHRONOUS", "editStorageGroupActionParam": { "expandStorageGroupParam": { - "addVolumeParam": { + "addVolumeParam": [{ "num_of_vols": 1, "emulation": "FBA", "create_new_volumes": "False", @@ -863,7 +865,7 @@ class PowerMaxRest(object): "volumeIdentifierChoice": "identifier_name"}, "volumeAttribute": { "volume_size": volume_size, - "capacityUnit": "GB"}}}}}) + "capacityUnit": "GB"}}]}}}) status_code, job = self.modify_storage_group( array, storagegroup_name, payload) @@ -1413,7 +1415,7 @@ class PowerMaxRest(object): if portgroup_info: port_key = portgroup_info["symmetrixPortKey"] for key in port_key: - port = key['portId'] + port = "%s:%s" % (key['directorId'], key['portId']) portlist.append(port) return portlist @@ -1804,8 +1806,7 @@ class PowerMaxRest(object): "copy": 'true', "action": action, "star": 'false', "force": 'false', "exact": 'false', "remote": 'false', - "symforce": 'false', "nocopy": 'false', - "generation": generation} + "symforce": 'false', "generation": generation} elif action == "Rename": operation = 'Rename snapVx snapshot' @@ -1868,9 +1869,9 @@ class PowerMaxRest(object): snapshot = None snap_info = self.get_volume_snap_info(array, device_id) if snap_info: - if (snap_info.get('snapshotSrc') and - bool(snap_info['snapshotSrc'])): - for snap in snap_info['snapshotSrc']: + if (snap_info.get('snapshotSrcs') and + bool(snap_info['snapshotSrcs'])): + for snap in snap_info['snapshotSrcs']: if snap['snapshotName'] == snap_name: if snap['generation'] == generation: snapshot = snap @@ -1887,8 +1888,8 @@ class PowerMaxRest(object): snapshot_list = [] snap_info = self.get_volume_snap_info(array, source_device_id) if snap_info: - if bool(snap_info['snapshotSrc']): - snapshot_list = snap_info['snapshotSrc'] + if bool(snap_info['snapshotSrcs']): + snapshot_list = snap_info['snapshotSrcs'] return snapshot_list def is_vol_in_rep_session(self, array, device_id): diff --git a/releasenotes/notes/powermax-90-to-91-endpoints-a92c4d158cb63fe4.yaml b/releasenotes/notes/powermax-90-to-91-endpoints-a92c4d158cb63fe4.yaml new file mode 100644 index 00000000000..510d94320d8 --- /dev/null +++ b/releasenotes/notes/powermax-90-to-91-endpoints-a92c4d158cb63fe4.yaml @@ -0,0 +1,5 @@ +--- +other: + - | + PowerMax driver - the minimum version of Unisphere for PowerMax required + for Train is 9.1, so all the latest 91 REST endpoints will be used.