* Convert LSM form of WWPN to SNIA form:
[0-9A-F]{16}
* Removed these initiator types:
AccessGroup.INIT_TYPE_WWNN
AccessGroup.INIT_TYPE_HOSTNAME
AccessGroup.INIT_TYPE_SAS
* Fix these problems:
1. _cim_init_check_or_create() incorrect return CIMInstanceName when
creation needed.
# Now, method renamed to _cim_init_path_check_or_create().
# will return CIMInstanceName always.
2. The confliction error will be raise as CIMError in InvokeMethod()
command, not in _wait_invoke() method.
# Now, we do confliction check when error happened.
# Not check pre-excute, which can save some time for most legal use.
Signed-off-by: Gris Ge <***@redhat.com>
---
plugin/smispy/smis.py | 175 +++++++++++++++++++++++++++-----------------------
1 file changed, 94 insertions(+), 81 deletions(-)
diff --git a/plugin/smispy/smis.py b/plugin/smispy/smis.py
index 88ae335..4d15b0e 100644
--- a/plugin/smispy/smis.py
+++ b/plugin/smispy/smis.py
@@ -30,7 +30,7 @@ from pywbem import CIMError
from lsm import (IStorageAreaNetwork, error, uri_parse, LsmError, ErrorNumber,
JobStatus, md5, Pool, Volume, AccessGroup, System,
Capabilities, Disk, VERSION, TargetPort,
- search_property)
+ search_property, wwpn_to_lsm_type)
## Variable Naming scheme:
# cim_xxx CIMInstance
@@ -137,15 +137,22 @@ def _hex_string_format(hex_str, length, every):
return ':'.join(hex_str[i:i + every] for i in range(0, length, every))
+def _lsm_init_id_to_snia(lsm_init_id):
+ """
+ If lsm_init_id is a WWPN, convert it to SNIA format:
+ [0-9A-F]{16}
+ If not, return directly.
+ """
+ if wwpn_to_lsm_type(lsm_init_id, raise_error=False):
+ return lsm_init_id.replace(':', '').upper()
+ return lsm_init_id
+
+
class DMTF(object):
# CIM_StorageHardwareID['IDType']
- ID_TYPE_OTHER = pywbem.Uint16(1)
ID_TYPE_WWPN = pywbem.Uint16(2)
- ID_TYPE_WWNN = pywbem.Uint16(3)
- ID_TYPE_HOSTNAME = pywbem.Uint16(4)
ID_TYPE_ISCSI = pywbem.Uint16(5)
- ID_TYPE_SW_WWN = pywbem.Uint16(6)
- ID_TYPE_SAS = pywbem.Uint16(7)
+
TGT_PORT_USAGE_FRONTEND_ONLY = pywbem.Uint16(2)
TGT_PORT_USAGE_UNRESTRICTED = pywbem.Uint16(4)
# CIM_FCPort['PortDiscriminator']
@@ -182,28 +189,19 @@ class DMTF(object):
# CIM_GroupMaskingMappingCapabilities['SupportedInitiatorGroupFeatures']
# Allowing empty DeviceMaskingGroup
GMM_CAP_INIT_MG_ALLOW_EMPTY = pywbem.Uint16(4)
- # Allowing empty DeviceMaskingGroup associated to SPC
- GMM_CAP_INIT_MG_ALLOW_EMPTY_W_SPC = pywbem.Uint16(5)
# CIM_GroupMaskingMappingCapabilities['SupportedAsynchronousActions']
# and 'SupportedSynchronousActions'. They are using the same value map.
GMM_CAP_DELETE_SPC = pywbem.Uint16(24)
GMM_CAP_DELETE_GROUP = pywbem.Uint16(20)
-_INIT_TYPE_CONV = {
- DMTF.ID_TYPE_OTHER: AccessGroup.INIT_TYPE_OTHER,
- DMTF.ID_TYPE_WWPN: AccessGroup.INIT_TYPE_WWPN,
- DMTF.ID_TYPE_WWNN: AccessGroup.INIT_TYPE_WWNN,
- DMTF.ID_TYPE_HOSTNAME: AccessGroup.INIT_TYPE_HOSTNAME,
- DMTF.ID_TYPE_ISCSI: AccessGroup.INIT_TYPE_ISCSI_IQN,
- DMTF.ID_TYPE_SW_WWN: AccessGroup.INIT_TYPE_OTHER,
- DMTF.ID_TYPE_SAS: AccessGroup.INIT_TYPE_SAS,
-}
-
def _dmtf_init_type_to_lsm(cim_init):
- if 'IDType' in cim_init and cim_init['IDType'] in _INIT_TYPE_CONV.keys():
- return _INIT_TYPE_CONV[cim_init['IDType']]
+ if 'IDType' in cim_init:
+ if cim_init['IDType'] == DMTF.ID_TYPE_WWPN:
+ return AccessGroup.INIT_TYPE_WWPN
+ elif cim_init['IDType'] == DMTF.ID_TYPE_ISCSI:
+ return AccessGroup.INIT_TYPE_ISCSI_IQN
return AccessGroup.INIT_TYPE_UNKNOWN
@@ -2616,20 +2614,24 @@ class Smis(IStorageAreaNetwork):
Method A defined in SNIA SMIS 1.6 deprecated the Method B and Method A
saved 1 query which provide better performance.
- Hence we try method A.
- Maybe someday, we will stop trying after knowing array's supported
- SMIS version.
+
+ Only iSCSI and WWPN CIM_StorageHardwareID will be returned:
+ CIM_StorageHardwareID['IDType'] == DMTF.ID_TYPE_WWPN(2)
+ or
+ CIM_StorageHardwareID['IDType'] == DMTF.ID_TYPE_ISCSI(5)
"""
cim_inits = []
if property_list is None:
- property_list = []
+ property_list = ['IDType']
+ else:
+ property_list = _merge_list(property_list, ['IDType'])
if (not self.fallback_mode and
self._profile_is_supported(SNIA.MASK_PROFILE,
SNIA.SMIS_SPEC_VER_1_6,
strict=False,
raise_error=False)):
- return self._c.Associators(
+ cim_inits = self._c.Associators(
cim_spc_path,
AssocClass='CIM_AssociatedPrivilege',
ResultClass='CIM_StorageHardwareID',
@@ -2645,7 +2647,13 @@ class Smis(IStorageAreaNetwork):
AssocClass='CIM_AuthorizedSubject',
ResultClass='CIM_StorageHardwareID',
PropertyList=property_list))
- return cim_inits
+ rc = []
+ for cim_init in cim_inits:
+ if cim_init['IDType'] == DMTF.ID_TYPE_WWPN or \
+ cim_init['IDType'] == DMTF.ID_TYPE_ISCSI:
+ rc.append(cim_init)
+
+ return rc
def _cim_init_of_init_mg(self, cim_init_mg_path, property_list=None):
"""
@@ -2862,23 +2870,15 @@ class Smis(IStorageAreaNetwork):
return search_property(rc, search_key, search_value)
- def _cim_init_check_or_create(self, cim_sys_path, init_id, init_type):
+ def _cim_init_path_check_or_create(self, cim_sys_path, init_id, init_type):
"""
Check whether CIM_StorageHardwareID exists, if not, create new one.
"""
cim_init = self._get_cim_instance_by_id(
'Initiator', init_id, raise_error=False, property_list=['IDType'])
- # In rare chance, cim_init might holding different init_type
- # As ExposePaths is using init_id, hence we raise error instead of
- # creating new one
if cim_init:
- if _dmtf_init_type_to_lsm(cim_init) != init_type:
- raise LsmError(ErrorNumber.EXISTS_INITIATOR,
- "Another initiator exists with the same ID "
- "%s, but different init_type %d:" %
- (init_id, _dmtf_init_type_to_lsm(cim_init)))
- return cim_init
+ return cim_init.path
# Create new one
dmtf_id_type = _lsm_init_type_to_dmtf(init_type)
@@ -2887,14 +2887,13 @@ class Smis(IStorageAreaNetwork):
"SMI-S Plugin does not support init_type %d" %
init_type)
- cim_init = self._cim_init_create(
+ return self._cim_init_path_create(
cim_sys_path, init_id, dmtf_id_type)
- return cim_init
-
- def _cim_init_create(self, cim_sys_path, init_id, dmtf_id_type):
+ def _cim_init_path_create(self, cim_sys_path, init_id, dmtf_id_type):
"""
Create a CIM_StorageHardwareID.
+ Return CIM_InstanceName
Raise error if failed. Return if pass.
"""
cim_hw_srv_path = self._get_cim_service_path(
@@ -2929,11 +2928,10 @@ class Smis(IStorageAreaNetwork):
# Check whether already added.
for exist_cim_init in exist_cim_inits:
- if self._init_id(exist_cim_init) == init_id and \
- _dmtf_init_type_to_lsm(exist_cim_init) == init_type:
- return copy.deepcopy(access_group)
+ if self._init_id(exist_cim_init) == init_id:
+ return copy.deepcopy(access_group)
- cim_init = self._cim_init_check_or_create(
+ cim_init_path = self._cim_init_path_check_or_create(
cim_sys.path, init_id, init_type)
cim_gmm_path = self._get_cim_service_path(
@@ -2941,7 +2939,7 @@ class Smis(IStorageAreaNetwork):
in_params = {
'MaskingGroup': cim_init_mg.path,
- 'Members': [cim_init.path],
+ 'Members': [cim_init_path],
}
(rc, out) = self._c.InvokeMethod('AddMembers',
cim_gmm_path, **in_params)
@@ -2959,6 +2957,7 @@ class Smis(IStorageAreaNetwork):
@handle_cim_errors
def access_group_initiator_add(self, access_group, init_id, init_type,
flags=0):
+ init_id = _lsm_init_id_to_snia(init_id)
mask_type = self._mask_type(raise_error=True)
if mask_type == Smis.MASK_TYPE_GROUP:
@@ -2987,19 +2986,12 @@ class Smis(IStorageAreaNetwork):
for exist_cim_init in exist_cim_inits:
if self._init_id(exist_cim_init) == init_id:
- if _dmtf_init_type_to_lsm(exist_cim_init) != init_type:
- raise LsmError(ErrorNumber.EXISTS_INITIATOR,
- "Another initiator exists with the same ID "
- "%s, but different init_type %d:" %
- (init_id,
- _dmtf_init_type_to_lsm(exist_cim_init)))
-
return copy.deepcopy(access_group)
# Check to see if we have this initiator already, if not we
# create it and then add to the view.
- self._cim_init_check_or_create(cim_sys.path, init_id, init_type)
+ self._cim_init_path_check_or_create(cim_sys.path, init_id, init_type)
cim_ccs_path = self._get_cim_service_path(
cim_sys.path, 'CIM_ControllerConfigurationService')
@@ -3093,6 +3085,7 @@ class Smis(IStorageAreaNetwork):
@handle_cim_errors
def access_group_initiator_delete(self, access_group, init_id, flags=0):
+ init_id = _lsm_init_id_to_snia(init_id)
mask_type = self._mask_type(raise_error=True)
if mask_type == Smis.MASK_TYPE_GROUP:
@@ -4844,6 +4837,8 @@ class Smis(IStorageAreaNetwork):
confliction.
1. Create CIM_InitiatorMaskingGroup
"""
+ old_init_id = init_id
+ init_id = _lsm_init_id_to_snia(init_id)
if self.fallback_mode:
raise LsmError(ErrorNumber.NO_SUPPORT,
"access_group_create() is not supported in "
@@ -4886,44 +4881,62 @@ class Smis(IStorageAreaNetwork):
"iSCSI target port, which not allow creating "
"iSCSI IQN access group")
- cim_init = self._cim_init_check_or_create(
+ cim_init_path = self._cim_init_path_check_or_create(
cim_sys.path, init_id, init_type)
- cim_init_mg_pros = self._cim_init_mg_pros()
- exist_cim_init_mgs = self._c.Associators(
- cim_init.path,
- AssocClass='CIM_MemberOfCollection',
- ResultClass='CIM_InitiatorMaskingGroup',
- PropertyList=cim_init_mg_pros)
-
- if len(exist_cim_init_mgs) != 0:
- for exist_cim_init_mg in exist_cim_init_mgs:
- if exist_cim_init_mg['ElementName'] == name:
- return self._cim_init_mg_to_lsm(
- exist_cim_init_mg, system.id)
-
- # Name does not match.
- raise LsmError(ErrorNumber.EXISTS_INITIATOR,
- "Initiator %s already exist in other access group "
- % init_id +
- "with name %s and ID: %s" %
- (exist_cim_init_mgs[0]['ElementName'],
- md5(exist_cim_init_mgs[0]['DeviceID'])))
-
# Create CIM_InitiatorMaskingGroup
cim_gmm_path = self._get_cim_service_path(
cim_sys.path, 'CIM_GroupMaskingMappingService')
in_params = {'GroupName': name,
- 'Members': [cim_init.path],
+ 'Members': [cim_init_path],
'Type': DMTF.MASK_GROUP_TYPE_INIT}
- (rc, out) = self._c.InvokeMethod(
- 'CreateGroup', cim_gmm_path, **in_params)
+ cim_init_mg_pros = self._cim_init_mg_pros()
- cim_init_mg_path = self._wait_invoke(
- rc, out, out_key='MaskingGroup',
- expect_class='CIM_InitiatorMaskingGroup')
+ try:
+ (rc, out) = self._c.InvokeMethod(
+ 'CreateGroup', cim_gmm_path, **in_params)
+
+ cim_init_mg_path = self._wait_invoke(
+ rc, out, out_key='MaskingGroup',
+ expect_class='CIM_InitiatorMaskingGroup')
+ except (LsmError, CIMError):
+ # Check possible failure
+ # 1. Initiator already exist in other group.
+ # If that group hold the same name as requested.
+ # We consider as a duplicate call, return the exist one.
+ exist_cim_init_mgs = self._c.Associators(
+ cim_init_path,
+ AssocClass='CIM_MemberOfCollection',
+ ResultClass='CIM_InitiatorMaskingGroup',
+ PropertyList=cim_init_mg_pros)
+
+ if len(exist_cim_init_mgs) != 0:
+ for exist_cim_init_mg in exist_cim_init_mgs:
+ if exist_cim_init_mg['ElementName'] == name:
+ return self._cim_init_mg_to_lsm(
+ exist_cim_init_mg, system.id)
+
+ # Name does not match.
+ raise LsmError(ErrorNumber.EXISTS_INITIATOR,
+ "Initiator %s " % old_init_id +
+ "already exist in other access group "
+ "with name %s and ID: %s" %
+ (exist_cim_init_mgs[0]['ElementName'],
+ md5(exist_cim_init_mgs[0]['InstanceID'])))
+ # 2. Requested name used by other group.
+ # Since 1) already checked whether any group containing
+ # requested init_id, now, it's surelly a confliction.
+ exist_cim_init_mgs = self._cim_init_mg_of(
+ cim_sys.path, property_list=['ElementName'])
+ for exist_cim_init_mg in exist_cim_init_mgs:
+ if exist_cim_init_mg['ElementName'] == name:
+ raise LsmError(ErrorNumber.EXISTS_ACCESS_GROUP,
+ "Requested name %s is used by " % name +
+ "another access group, but not containing "
+ "requested initiator %s" % old_init_id)
+ raise
cim_init_mg = self._c.GetInstance(
cim_init_mg_path, PropertyList=cim_init_mg_pros, LocalOnly=False)
--
1.8.3.1