Merge "PowerMax driver - changing from 8.4 to 9.0 REST endpoints"

This commit is contained in:
Zuul 2019-02-06 22:35:20 +00:00 committed by Gerrit Code Review
commit 3449568666
6 changed files with 70 additions and 56 deletions

View File

@ -92,7 +92,7 @@ class PowerMaxCommonData(object):
device_id4 = '00004' device_id4 = '00004'
rdf_group_name = '23_24_007' rdf_group_name = '23_24_007'
rdf_group_no = '70' rdf_group_no = '70'
u4v_version = '84' u4v_version = '90'
storagegroup_name_source = 'Grp_source_sg' storagegroup_name_source = 'Grp_source_sg'
storagegroup_name_target = 'Grp_target_sg' storagegroup_name_target = 'Grp_target_sg'
group_snapshot_name = 'Grp_snapshot' group_snapshot_name = 'Grp_snapshot'
@ -533,13 +533,13 @@ class PowerMaxCommonData(object):
sg_list_rep = [storagegroup_name_with_id] sg_list_rep = [storagegroup_name_with_id]
srp_details = {"srpSloDemandId": ["Bronze", "Diamond", "Gold", srp_details = {"srp_capacity": {u'subscribed_total_tb': 93.52,
"None", "Optimized", "Silver"], 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, "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} "reserved_cap_percent": 10}
array_info_wl = {'RestServerIp': '1.1.1.1', 'RestServerPort': 3448, array_info_wl = {'RestServerIp': '1.1.1.1', 'RestServerPort': 3448,
@ -633,7 +633,7 @@ class PowerMaxCommonData(object):
# replication # replication
volume_snap_vx = {"snapshotLnks": [], volume_snap_vx = {"snapshotLnks": [],
"snapshotSrcs": [ "snapshotSrc": [
{"generation": 0, {"generation": 0,
"linkedDevices": [ "linkedDevices": [
{"targetDevice": device_id2, {"targetDevice": device_id2,
@ -1101,8 +1101,6 @@ class FakeRequestsSession(object):
return_object = self._sloprovisioning_mv(url) return_object = self._sloprovisioning_mv(url)
elif 'portgroup' in url: elif 'portgroup' in url:
return_object = self._sloprovisioning_pg(url) return_object = self._sloprovisioning_pg(url)
elif 'director' in url:
return_object = self._sloprovisioning_port(url)
elif 'host' in url: elif 'host' in url:
return_object = self._sloprovisioning_ig(url) return_object = self._sloprovisioning_ig(url)
elif 'initiator' in url: elif 'initiator' in url:
@ -1122,7 +1120,10 @@ class FakeRequestsSession(object):
return_object = self._replication(url) return_object = self._replication(url)
elif 'system' in 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: elif 'headroom' in url:
return_object = self.data.headroom return_object = self.data.headroom
@ -1168,7 +1169,7 @@ class FakeRequestsSession(object):
break break
return return_object return return_object
def _sloprovisioning_port(self, url): def _system_port(self, url):
return_object = None return_object = None
for port in self.data.port_list: for port in self.data.port_list:
if port['symmetrixPort']['symmetrixPortKey']['directorId'] in url: if port['symmetrixPort']['symmetrixPortKey']['directorId'] in url:
@ -2250,15 +2251,16 @@ class PowerMaxRestTest(test.TestCase):
def test_add_child_sg_to_parent_sg(self): def test_add_child_sg_to_parent_sg(self):
payload = {"editStorageGroupActionParam": { payload = {"editStorageGroupActionParam": {
"addExistingStorageGroupParam": { "expandStorageGroupParam": {
"storageGroupId": [self.data.storagegroup_name_f]}}} "addExistingStorageGroupParam": {
"storageGroupId": [self.data.storagegroup_name_f]}}}}
with mock.patch.object(self.rest, 'modify_storage_group', with mock.patch.object(self.rest, 'modify_storage_group',
return_value=(202, self.data.job_list[0])): return_value=(202, self.data.job_list[0])):
self.rest.add_child_sg_to_parent_sg( self.rest.add_child_sg_to_parent_sg(
self.data.array, self.data.storagegroup_name_f, self.data.array, self.data.storagegroup_name_f,
self.data.parent_sg_f, self.data.extra_specs) self.data.parent_sg_f, self.data.extra_specs)
self.rest.modify_storage_group.assert_called_once_with( 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): def test_remove_child_sg_from_parent_sg(self):
payload = {"editStorageGroupActionParam": { payload = {"editStorageGroupActionParam": {
@ -2771,7 +2773,7 @@ class PowerMaxRestTest(test.TestCase):
def test_create_volume_snap(self): def test_create_volume_snap(self):
snap_name = (self.data.volume_snap_vx snap_name = (self.data.volume_snap_vx
['snapshotSrcs'][0]['snapshotName']) ['snapshotSrc'][0]['snapshotName'])
device_id = self.data.device_id device_id = self.data.device_id
extra_specs = self.data.extra_specs extra_specs = self.data.extra_specs
payload = {"deviceNameListSource": [{"name": device_id}], payload = {"deviceNameListSource": [{"name": device_id}],
@ -2802,9 +2804,9 @@ class PowerMaxRestTest(test.TestCase):
array = self.data.array array = self.data.array
source_id = self.data.device_id source_id = self.data.device_id
target_id = (self.data.volume_snap_vx target_id = (self.data.volume_snap_vx
['snapshotSrcs'][0]['linkedDevices'][0]['targetDevice']) ['snapshotSrc'][0]['linkedDevices'][0]['targetDevice'])
snap_name = (self.data.volume_snap_vx snap_name = (self.data.volume_snap_vx
['snapshotSrcs'][0]['snapshotName']) ['snapshotSrc'][0]['snapshotName'])
extra_specs = self.data.extra_specs extra_specs = self.data.extra_specs
payload = {"deviceNameListSource": [{"name": source_id}], payload = {"deviceNameListSource": [{"name": source_id}],
"deviceNameListTarget": [ "deviceNameListTarget": [
@ -2866,7 +2868,7 @@ class PowerMaxRestTest(test.TestCase):
def test_delete_volume_snap(self): def test_delete_volume_snap(self):
array = self.data.array array = self.data.array
snap_name = (self.data.volume_snap_vx snap_name = (self.data.volume_snap_vx
['snapshotSrcs'][0]['snapshotName']) ['snapshotSrc'][0]['snapshotName'])
source_device_id = self.data.device_id source_device_id = self.data.device_id
payload = {"deviceNameListSource": [{"name": source_device_id}], payload = {"deviceNameListSource": [{"name": source_device_id}],
"generation": 0} "generation": 0}
@ -2881,7 +2883,7 @@ class PowerMaxRestTest(test.TestCase):
def test_delete_volume_snap_restore(self): def test_delete_volume_snap_restore(self):
array = self.data.array array = self.data.array
snap_name = (self.data.volume_snap_vx snap_name = (self.data.volume_snap_vx
['snapshotSrcs'][0]['snapshotName']) ['snapshotSrc'][0]['snapshotName'])
source_device_id = self.data.device_id source_device_id = self.data.device_id
payload = {"deviceNameListSource": [{"name": source_device_id}], payload = {"deviceNameListSource": [{"name": source_device_id}],
"restore": True, "generation": 0} "restore": True, "generation": 0}
@ -2902,23 +2904,23 @@ class PowerMaxRestTest(test.TestCase):
def test_get_volume_snap(self): def test_get_volume_snap(self):
array = self.data.array array = self.data.array
snap_name = (self.data.volume_snap_vx snap_name = (self.data.volume_snap_vx
['snapshotSrcs'][0]['snapshotName']) ['snapshotSrc'][0]['snapshotName'])
device_id = self.data.device_id 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) snap = self.rest.get_volume_snap(array, device_id, snap_name)
self.assertEqual(ref_snap, snap) self.assertEqual(ref_snap, snap)
def test_get_volume_snap_none(self): def test_get_volume_snap_none(self):
array = self.data.array array = self.data.array
snap_name = (self.data.volume_snap_vx snap_name = (self.data.volume_snap_vx
['snapshotSrcs'][0]['snapshotName']) ['snapshotSrc'][0]['snapshotName'])
device_id = self.data.device_id device_id = self.data.device_id
with mock.patch.object(self.rest, 'get_volume_snap_info', with mock.patch.object(self.rest, 'get_volume_snap_info',
return_value=None): return_value=None):
snap = self.rest.get_volume_snap(array, device_id, snap_name) snap = self.rest.get_volume_snap(array, device_id, snap_name)
self.assertIsNone(snap) self.assertIsNone(snap)
with mock.patch.object(self.rest, 'get_volume_snap_info', 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) snap = self.rest.get_volume_snap(array, device_id, snap_name)
self.assertIsNone(snap) self.assertIsNone(snap)
@ -2942,11 +2944,11 @@ class PowerMaxRestTest(test.TestCase):
source_id = self.data.device_id source_id = self.data.device_id
generation = 0 generation = 0
target_id = (self.data.volume_snap_vx target_id = (self.data.volume_snap_vx
['snapshotSrcs'][0]['linkedDevices'][0]['targetDevice']) ['snapshotSrc'][0]['linkedDevices'][0]['targetDevice'])
snap_name = (self.data.volume_snap_vx snap_name = (self.data.volume_snap_vx
['snapshotSrcs'][0]['snapshotName']) ['snapshotSrc'][0]['snapshotName'])
ref_sync = (self.data.volume_snap_vx ref_sync = (self.data.volume_snap_vx
['snapshotSrcs'][0]['linkedDevices'][0]) ['snapshotSrc'][0]['linkedDevices'][0])
sync = self.rest.get_sync_session( sync = self.rest.get_sync_session(
array, source_id, snap_name, target_id, generation) array, source_id, snap_name, target_id, generation)
self.assertEqual(ref_sync, sync) self.assertEqual(ref_sync, sync)
@ -3663,10 +3665,11 @@ class PowerMaxProvisionTest(test.TestCase):
def test_get_srp_pool_stats(self): def test_get_srp_pool_stats(self):
array = self.data.array array = self.data.array
array_info = self.common.pool_info['arrays_info'][0] array_info = self.common.pool_info['arrays_info'][0]
ref_stats = (self.data.srp_details['total_usable_cap_gb'], srp_capacity = self.data.srp_details['srp_capacity']
float(self.data.srp_details['total_usable_cap_gb'] ref_stats = ((srp_capacity['usable_total_tb'] * 1024),
- self.data.srp_details['total_used_cap_gb']), float((srp_capacity['usable_total_tb'] * 1024)
self.data.srp_details['total_subscribed_cap_gb'], - (srp_capacity['usable_used_tb'] * 1024)),
(srp_capacity['subscribed_total_tb'] * 1024),
self.data.srp_details['reserved_cap_percent']) self.data.srp_details['reserved_cap_percent'])
stats = self.provision.get_srp_pool_stats(array, array_info) stats = self.provision.get_srp_pool_stats(array, array_info)
self.assertEqual(ref_stats, stats) self.assertEqual(ref_stats, stats)
@ -3679,9 +3682,10 @@ class PowerMaxProvisionTest(test.TestCase):
stats = self.provision.get_srp_pool_stats(array, array_info) stats = self.provision.get_srp_pool_stats(array, array_info)
self.assertEqual(ref_stats, stats) self.assertEqual(ref_stats, stats)
# cannot report on all stats # cannot report on all stats
with mock.patch.object(self.provision.rest, 'get_srp_by_name', with mock.patch.object(
return_value={'total_usable_cap_gb': 33}): self.provision.rest, 'get_srp_by_name',
ref_stats = (33, 0, 0, 0) 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) stats = self.provision.get_srp_pool_stats(array, array_info)
self.assertEqual(ref_stats, stats) self.assertEqual(ref_stats, stats)

View File

@ -104,6 +104,7 @@ class PowerMaxFCDriver(san.SanDriver, driver.FibreChannelDriver):
- Support for failover to secondary Unisphere - Support for failover to secondary Unisphere
(bp/vmax-unisphere-failover) (bp/vmax-unisphere-failover)
- Rebrand from VMAX to PowerMax(bp/vmax-powermax-rebrand) - Rebrand from VMAX to PowerMax(bp/vmax-powermax-rebrand)
- Change from 84 to 90 REST endpoints (bug #1808539)
""" """
VERSION = "4.0.0" VERSION = "4.0.0"

View File

@ -109,6 +109,7 @@ class PowerMaxISCSIDriver(san.SanISCSIDriver):
- Support for failover to secondary Unisphere - Support for failover to secondary Unisphere
(bp/vmax-unisphere-failover) (bp/vmax-unisphere-failover)
- Rebrand from VMAX to PowerMax(bp/vmax-powermax-rebrand) - Rebrand from VMAX to PowerMax(bp/vmax-powermax-rebrand)
- Change from 84 to 90 REST endpoints (bug #1808539)
""" """
VERSION = "4.0.0" VERSION = "4.0.0"

View File

@ -17,6 +17,7 @@ import time
from oslo_log import log as logging from oslo_log import log as logging
from oslo_service import loopingcall from oslo_service import loopingcall
from oslo_utils import units
from cinder import coordination from cinder import coordination
from cinder import exception from cinder import exception
@ -422,14 +423,16 @@ class PowerMaxProvision(object):
{'srpName': srp, 'array': array}) {'srpName': srp, 'array': array})
return 0, 0, 0, 0, False return 0, 0, 0, 0, False
try: 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: try:
used_capacity_gb = srp_details['total_used_cap_gb'] used_capacity_gb = srp_capacity['usable_used_tb'] * units.Ki
remaining_capacity_gb = float( remaining_capacity_gb = float(
total_capacity_gb - used_capacity_gb) total_capacity_gb - used_capacity_gb)
except KeyError: except KeyError:
remaining_capacity_gb = srp_details['fba_free_capacity'] LOG.error("Unable to retrieve remaining_capacity_gb.")
subscribed_capacity_gb = srp_details['total_subscribed_cap_gb'] subscribed_capacity_gb = (
srp_capacity['subscribed_total_tb'] * units.Ki)
array_reserve_percent = srp_details['reserved_cap_percent'] array_reserve_percent = srp_details['reserved_cap_percent']
except KeyError: except KeyError:
pass pass

View File

@ -39,7 +39,7 @@ LOG = logging.getLogger(__name__)
SLOPROVISIONING = 'sloprovisioning' SLOPROVISIONING = 'sloprovisioning'
REPLICATION = 'replication' REPLICATION = 'replication'
SYSTEM = 'system' SYSTEM = 'system'
U4V_VERSION = '84' U4V_VERSION = '90'
UCODE_5978 = '5978' UCODE_5978 = '5978'
retry_exc_tuple = (exception.VolumeBackendAPIException,) retry_exc_tuple = (exception.VolumeBackendAPIException,)
# HTTP constants # HTTP constants
@ -732,10 +732,10 @@ class PowerMaxRest(object):
:param extra_specs: the extra specifications :param extra_specs: the extra specifications
""" """
payload = {"editStorageGroupActionParam": { payload = {"editStorageGroupActionParam": {
"addExistingStorageGroupParam": { "expandStorageGroupParam": {
"storageGroupId": [child_sg]}}} "addExistingStorageGroupParam": {
sc, job = self.modify_storage_group(array, parent_sg, payload, "storageGroupId": [child_sg]}}}}
version="83") sc, job = self.modify_storage_group(array, parent_sg, payload)
self.wait_for_job('Add child sg to parent sg', sc, job, extra_specs) self.wait_for_job('Add child sg to parent sg', sc, job, extra_specs)
def remove_child_sg_from_parent_sg( def remove_child_sg_from_parent_sg(
@ -1409,7 +1409,7 @@ class PowerMaxRest(object):
resource_name = ('%(directorId)s/port/%(port_number)s' resource_name = ('%(directorId)s/port/%(port_number)s'
% {'directorId': dir_id, 'port_number': port_no}) % {'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) resource_name=resource_name)
def get_iscsi_ip_address_and_iqn(self, array, port_id): def get_iscsi_ip_address_and_iqn(self, array, port_id):
@ -1476,9 +1476,8 @@ class PowerMaxRest(object):
:param params: dict of optional params :param params: dict of optional params
:returns: list of initiators :returns: list of initiators
""" """
version = '90' if self.is_next_gen_array(array) else U4V_VERSION
init_dict = self.get_resource(array, SLOPROVISIONING, 'initiator', init_dict = self.get_resource(array, SLOPROVISIONING, 'initiator',
params=params, version=version) params=params)
try: try:
init_list = init_dict['initiatorId'] init_list = init_dict['initiatorId']
except (KeyError, TypeError): except (KeyError, TypeError):
@ -1846,9 +1845,9 @@ class PowerMaxRest(object):
snapshot = None snapshot = None
snap_info = self.get_volume_snap_info(array, device_id) snap_info = self.get_volume_snap_info(array, device_id)
if snap_info: if snap_info:
if (snap_info.get('snapshotSrcs') and if (snap_info.get('snapshotSrc') and
bool(snap_info['snapshotSrcs'])): bool(snap_info['snapshotSrc'])):
for snap in snap_info['snapshotSrcs']: for snap in snap_info['snapshotSrc']:
if snap['snapshotName'] == snap_name: if snap['snapshotName'] == snap_name:
if snap['generation'] == generation: if snap['generation'] == generation:
snapshot = snap snapshot = snap
@ -1865,8 +1864,8 @@ class PowerMaxRest(object):
snapshot_list = [] snapshot_list = []
snap_info = self.get_volume_snap_info(array, source_device_id) snap_info = self.get_volume_snap_info(array, source_device_id)
if snap_info: if snap_info:
if bool(snap_info['snapshotSrcs']): if bool(snap_info['snapshotSrc']):
snapshot_list = snap_info['snapshotSrcs'] snapshot_list = snap_info['snapshotSrc']
return snapshot_list return snapshot_list
def is_vol_in_rep_session(self, array, device_id): def is_vol_in_rep_session(self, array, device_id):
@ -1985,11 +1984,14 @@ class PowerMaxRest(object):
snap_dict_list = [] snap_dict_list = []
snapshots = self.get_volume_snapshot_list(array, source_device_id) snapshots = self.get_volume_snapshot_list(array, source_device_id)
for snapshot in snapshots: for snapshot in snapshots:
if bool(snapshot['linkedDevices']): try:
link_info = {'linked_vols': snapshot['linkedDevices'], if bool(snapshot['linkedDevices']):
'snap_name': snapshot['snapshotName'], link_info = {'linked_vols': snapshot['linkedDevices'],
'generation': snapshot['generation']} 'snap_name': snapshot['snapshotName'],
snap_dict_list.append(link_info) 'generation': snapshot['generation']}
snap_dict_list.append(link_info)
except KeyError:
pass
return snap_dict_list return snap_dict_list
def get_snap_linked_device_list(self, array, source_device_id, def get_snap_linked_device_list(self, array, source_device_id,

View File

@ -0,0 +1,3 @@
other:
- |
PowerMax driver - Changing 8.4 to 9.0 Unisphere for PowerMax REST endpoints.