diff --git a/cinder/tests/unit/volume/drivers/dell_emc/powermax/test_powermax.py b/cinder/tests/unit/volume/drivers/dell_emc/powermax/test_powermax.py index 0bf80124fbd..84f1913627f 100644 --- a/cinder/tests/unit/volume/drivers/dell_emc/powermax/test_powermax.py +++ b/cinder/tests/unit/volume/drivers/dell_emc/powermax/test_powermax.py @@ -92,7 +92,7 @@ class PowerMaxCommonData(object): device_id4 = '00004' rdf_group_name = '23_24_007' rdf_group_no = '70' - u4v_version = '84' + u4v_version = '90' storagegroup_name_source = 'Grp_source_sg' storagegroup_name_target = 'Grp_target_sg' group_snapshot_name = 'Grp_snapshot' @@ -533,13 +533,13 @@ class PowerMaxCommonData(object): sg_list_rep = [storagegroup_name_with_id] - srp_details = {"srpSloDemandId": ["Bronze", "Diamond", "Gold", - "None", "Optimized", "Silver"], + srp_details = {"srp_capacity": {u'subscribed_total_tb': 93.52, + u'usable_used_tb': 8.62, + u'usable_total_tb': 24.45, + u'snapshot_modified_tb': 0.0, + u'subscribed_allocated_tb': 18.77, + u'snapshot_total_tb': 1.58}, "srpId": srp, - "total_used_cap_gb": 5244.7, - "total_usable_cap_gb": 20514.4, - "total_subscribed_cap_gb": 84970.1, - "fba_used_capacity": 5244.7, "reserved_cap_percent": 10} array_info_wl = {'RestServerIp': '1.1.1.1', 'RestServerPort': 3448, @@ -633,7 +633,7 @@ class PowerMaxCommonData(object): # replication volume_snap_vx = {"snapshotLnks": [], - "snapshotSrcs": [ + "snapshotSrc": [ {"generation": 0, "linkedDevices": [ {"targetDevice": device_id2, @@ -1101,8 +1101,6 @@ class FakeRequestsSession(object): return_object = self._sloprovisioning_mv(url) elif 'portgroup' in url: return_object = self._sloprovisioning_pg(url) - elif 'director' in url: - return_object = self._sloprovisioning_port(url) elif 'host' in url: return_object = self._sloprovisioning_ig(url) elif 'initiator' in url: @@ -1122,7 +1120,10 @@ class FakeRequestsSession(object): return_object = self._replication(url) elif 'system' in url: - return_object = self._system(url) + if 'director' in url: + return_object = self._system_port(url) + else: + return_object = self._system(url) elif 'headroom' in url: return_object = self.data.headroom @@ -1168,7 +1169,7 @@ class FakeRequestsSession(object): break return return_object - def _sloprovisioning_port(self, url): + def _system_port(self, url): return_object = None for port in self.data.port_list: if port['symmetrixPort']['symmetrixPortKey']['directorId'] in url: @@ -2250,15 +2251,16 @@ 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])): self.rest.add_child_sg_to_parent_sg( self.data.array, self.data.storagegroup_name_f, self.data.parent_sg_f, self.data.extra_specs) self.rest.modify_storage_group.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": { @@ -2771,7 +2773,7 @@ class PowerMaxRestTest(test.TestCase): def test_create_volume_snap(self): snap_name = (self.data.volume_snap_vx - ['snapshotSrcs'][0]['snapshotName']) + ['snapshotSrc'][0]['snapshotName']) device_id = self.data.device_id extra_specs = self.data.extra_specs payload = {"deviceNameListSource": [{"name": device_id}], @@ -2802,9 +2804,9 @@ class PowerMaxRestTest(test.TestCase): array = self.data.array source_id = self.data.device_id target_id = (self.data.volume_snap_vx - ['snapshotSrcs'][0]['linkedDevices'][0]['targetDevice']) + ['snapshotSrc'][0]['linkedDevices'][0]['targetDevice']) snap_name = (self.data.volume_snap_vx - ['snapshotSrcs'][0]['snapshotName']) + ['snapshotSrc'][0]['snapshotName']) extra_specs = self.data.extra_specs payload = {"deviceNameListSource": [{"name": source_id}], "deviceNameListTarget": [ @@ -2866,7 +2868,7 @@ class PowerMaxRestTest(test.TestCase): def test_delete_volume_snap(self): array = self.data.array snap_name = (self.data.volume_snap_vx - ['snapshotSrcs'][0]['snapshotName']) + ['snapshotSrc'][0]['snapshotName']) source_device_id = self.data.device_id payload = {"deviceNameListSource": [{"name": source_device_id}], "generation": 0} @@ -2881,7 +2883,7 @@ class PowerMaxRestTest(test.TestCase): def test_delete_volume_snap_restore(self): array = self.data.array snap_name = (self.data.volume_snap_vx - ['snapshotSrcs'][0]['snapshotName']) + ['snapshotSrc'][0]['snapshotName']) source_device_id = self.data.device_id payload = {"deviceNameListSource": [{"name": source_device_id}], "restore": True, "generation": 0} @@ -2902,23 +2904,23 @@ class PowerMaxRestTest(test.TestCase): def test_get_volume_snap(self): array = self.data.array snap_name = (self.data.volume_snap_vx - ['snapshotSrcs'][0]['snapshotName']) + ['snapshotSrc'][0]['snapshotName']) device_id = self.data.device_id - ref_snap = self.data.volume_snap_vx['snapshotSrcs'][0] + ref_snap = self.data.volume_snap_vx['snapshotSrc'][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 - ['snapshotSrcs'][0]['snapshotName']) + ['snapshotSrc'][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={'snapshotSrcs': []}): + return_value={'snapshotSrc': []}): snap = self.rest.get_volume_snap(array, device_id, snap_name) self.assertIsNone(snap) @@ -2942,11 +2944,11 @@ class PowerMaxRestTest(test.TestCase): source_id = self.data.device_id generation = 0 target_id = (self.data.volume_snap_vx - ['snapshotSrcs'][0]['linkedDevices'][0]['targetDevice']) + ['snapshotSrc'][0]['linkedDevices'][0]['targetDevice']) snap_name = (self.data.volume_snap_vx - ['snapshotSrcs'][0]['snapshotName']) + ['snapshotSrc'][0]['snapshotName']) ref_sync = (self.data.volume_snap_vx - ['snapshotSrcs'][0]['linkedDevices'][0]) + ['snapshotSrc'][0]['linkedDevices'][0]) sync = self.rest.get_sync_session( array, source_id, snap_name, target_id, generation) self.assertEqual(ref_sync, sync) @@ -3663,10 +3665,11 @@ class PowerMaxProvisionTest(test.TestCase): def test_get_srp_pool_stats(self): array = self.data.array array_info = self.common.pool_info['arrays_info'][0] - ref_stats = (self.data.srp_details['total_usable_cap_gb'], - float(self.data.srp_details['total_usable_cap_gb'] - - self.data.srp_details['total_used_cap_gb']), - self.data.srp_details['total_subscribed_cap_gb'], + srp_capacity = self.data.srp_details['srp_capacity'] + ref_stats = ((srp_capacity['usable_total_tb'] * 1024), + float((srp_capacity['usable_total_tb'] * 1024) + - (srp_capacity['usable_used_tb'] * 1024)), + (srp_capacity['subscribed_total_tb'] * 1024), self.data.srp_details['reserved_cap_percent']) stats = self.provision.get_srp_pool_stats(array, array_info) self.assertEqual(ref_stats, stats) @@ -3679,9 +3682,10 @@ class PowerMaxProvisionTest(test.TestCase): stats = self.provision.get_srp_pool_stats(array, array_info) self.assertEqual(ref_stats, stats) # cannot report on all stats - with mock.patch.object(self.provision.rest, 'get_srp_by_name', - return_value={'total_usable_cap_gb': 33}): - ref_stats = (33, 0, 0, 0) + with mock.patch.object( + self.provision.rest, 'get_srp_by_name', + return_value={'srp_capacity': {'usable_total_tb': 33}}): + ref_stats = (33 * 1024, 0, 0, 0) stats = self.provision.get_srp_pool_stats(array, array_info) self.assertEqual(ref_stats, stats) diff --git a/cinder/volume/drivers/dell_emc/powermax/fc.py b/cinder/volume/drivers/dell_emc/powermax/fc.py index 76f791e1ed0..d997863f018 100644 --- a/cinder/volume/drivers/dell_emc/powermax/fc.py +++ b/cinder/volume/drivers/dell_emc/powermax/fc.py @@ -104,6 +104,7 @@ class PowerMaxFCDriver(san.SanDriver, driver.FibreChannelDriver): - Support for failover to secondary Unisphere (bp/vmax-unisphere-failover) - Rebrand from VMAX to PowerMax(bp/vmax-powermax-rebrand) + - Change from 84 to 90 REST endpoints (bug #1808539) """ VERSION = "4.0.0" diff --git a/cinder/volume/drivers/dell_emc/powermax/iscsi.py b/cinder/volume/drivers/dell_emc/powermax/iscsi.py index 24b85e565c8..bcb9b9e8f05 100644 --- a/cinder/volume/drivers/dell_emc/powermax/iscsi.py +++ b/cinder/volume/drivers/dell_emc/powermax/iscsi.py @@ -109,6 +109,7 @@ class PowerMaxISCSIDriver(san.SanISCSIDriver): - Support for failover to secondary Unisphere (bp/vmax-unisphere-failover) - Rebrand from VMAX to PowerMax(bp/vmax-powermax-rebrand) + - Change from 84 to 90 REST endpoints (bug #1808539) """ VERSION = "4.0.0" diff --git a/cinder/volume/drivers/dell_emc/powermax/provision.py b/cinder/volume/drivers/dell_emc/powermax/provision.py index d6b368b5691..12c8ef66410 100644 --- a/cinder/volume/drivers/dell_emc/powermax/provision.py +++ b/cinder/volume/drivers/dell_emc/powermax/provision.py @@ -17,6 +17,7 @@ import time from oslo_log import log as logging from oslo_service import loopingcall +from oslo_utils import units from cinder import coordination from cinder import exception @@ -422,14 +423,16 @@ class PowerMaxProvision(object): {'srpName': srp, 'array': array}) return 0, 0, 0, 0, False try: - total_capacity_gb = srp_details['total_usable_cap_gb'] + srp_capacity = srp_details['srp_capacity'] + total_capacity_gb = srp_capacity['usable_total_tb'] * units.Ki try: - used_capacity_gb = srp_details['total_used_cap_gb'] + used_capacity_gb = srp_capacity['usable_used_tb'] * units.Ki remaining_capacity_gb = float( total_capacity_gb - used_capacity_gb) except KeyError: - remaining_capacity_gb = srp_details['fba_free_capacity'] - subscribed_capacity_gb = srp_details['total_subscribed_cap_gb'] + LOG.error("Unable to retrieve remaining_capacity_gb.") + subscribed_capacity_gb = ( + srp_capacity['subscribed_total_tb'] * units.Ki) array_reserve_percent = srp_details['reserved_cap_percent'] except KeyError: pass diff --git a/cinder/volume/drivers/dell_emc/powermax/rest.py b/cinder/volume/drivers/dell_emc/powermax/rest.py index 6aac825ec34..bea6249038a 100644 --- a/cinder/volume/drivers/dell_emc/powermax/rest.py +++ b/cinder/volume/drivers/dell_emc/powermax/rest.py @@ -39,7 +39,7 @@ LOG = logging.getLogger(__name__) SLOPROVISIONING = 'sloprovisioning' REPLICATION = 'replication' SYSTEM = 'system' -U4V_VERSION = '84' +U4V_VERSION = '90' UCODE_5978 = '5978' retry_exc_tuple = (exception.VolumeBackendAPIException,) # HTTP constants @@ -732,10 +732,10 @@ 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( @@ -1409,7 +1409,7 @@ class PowerMaxRest(object): resource_name = ('%(directorId)s/port/%(port_number)s' % {'directorId': dir_id, 'port_number': port_no}) - return self.get_resource(array, SLOPROVISIONING, 'director', + return self.get_resource(array, SYSTEM, 'director', resource_name=resource_name) def get_iscsi_ip_address_and_iqn(self, array, port_id): @@ -1476,9 +1476,8 @@ class PowerMaxRest(object): :param params: dict of optional params :returns: list of initiators """ - version = '90' if self.is_next_gen_array(array) else U4V_VERSION init_dict = self.get_resource(array, SLOPROVISIONING, 'initiator', - params=params, version=version) + params=params) try: init_list = init_dict['initiatorId'] except (KeyError, TypeError): @@ -1846,9 +1845,9 @@ class PowerMaxRest(object): snapshot = None snap_info = self.get_volume_snap_info(array, device_id) if snap_info: - if (snap_info.get('snapshotSrcs') and - bool(snap_info['snapshotSrcs'])): - for snap in snap_info['snapshotSrcs']: + if (snap_info.get('snapshotSrc') and + bool(snap_info['snapshotSrc'])): + for snap in snap_info['snapshotSrc']: if snap['snapshotName'] == snap_name: if snap['generation'] == generation: snapshot = snap @@ -1865,8 +1864,8 @@ class PowerMaxRest(object): snapshot_list = [] snap_info = self.get_volume_snap_info(array, source_device_id) if snap_info: - if bool(snap_info['snapshotSrcs']): - snapshot_list = snap_info['snapshotSrcs'] + if bool(snap_info['snapshotSrc']): + snapshot_list = snap_info['snapshotSrc'] return snapshot_list def is_vol_in_rep_session(self, array, device_id): @@ -1985,11 +1984,14 @@ class PowerMaxRest(object): snap_dict_list = [] snapshots = self.get_volume_snapshot_list(array, source_device_id) for snapshot in snapshots: - if bool(snapshot['linkedDevices']): - link_info = {'linked_vols': snapshot['linkedDevices'], - 'snap_name': snapshot['snapshotName'], - 'generation': snapshot['generation']} - snap_dict_list.append(link_info) + try: + if bool(snapshot['linkedDevices']): + link_info = {'linked_vols': snapshot['linkedDevices'], + 'snap_name': snapshot['snapshotName'], + 'generation': snapshot['generation']} + snap_dict_list.append(link_info) + except KeyError: + pass return snap_dict_list def get_snap_linked_device_list(self, array, source_device_id, diff --git a/releasenotes/notes/84-to-90-endpoints-831c28423d32cac5.yaml b/releasenotes/notes/84-to-90-endpoints-831c28423d32cac5.yaml new file mode 100644 index 00000000000..1ba39dd907f --- /dev/null +++ b/releasenotes/notes/84-to-90-endpoints-831c28423d32cac5.yaml @@ -0,0 +1,3 @@ +other: + - | + PowerMax driver - Changing 8.4 to 9.0 Unisphere for PowerMax REST endpoints.