Discussion:
[Libstoragemgmt-devel] [PATCH] SMI-S plugin: better way for profile support checking
Gris Ge
2014-05-19 15:21:15 UTC
Permalink
* Convert SMI-S SPEC version into integer for better comparison.
Please check _spec_ver_str_to_num() for detail.
* Let _root_cim_syss() handle the fall back checking. It will return a list
of CIM_ComputerSystem for fallback mode or not.
* Checking for 1.4 'Array' profile support in startup().
As 'Block Services Package' (AKA: BSP) is mandatory for that profile, we
don't do extra check in methods using BSP profile.
* Noting down the method naming scheme for consistency.
* Move SNIA related constants to a standalone class SNIA which shorter the
constant variable name.
* _profile_is_supported() now support raise error if not found.
* Split _cim_sys_of_id() out to raise LsmError ErrorNumber.NOT_FOUND_SYSTEM.
* Add RegisteredOrganization checking in CIM_RegisteredProfile.

Signed-off-by: Gris Ge <***@redhat.com>
---
plugin/smispy/smis.py | 505 ++++++++++++++++++--------------------------------
1 file changed, 182 insertions(+), 323 deletions(-)

diff --git a/plugin/smispy/smis.py b/plugin/smispy/smis.py
index c63d8cd..e0a0d97 100644
--- a/plugin/smispy/smis.py
+++ b/plugin/smispy/smis.py
@@ -37,6 +37,16 @@ from lsm import (IStorageAreaNetwork, Error, uri_parse, LsmError, ErrorNumber,
# pool Object of LSM Pool
# vol Object of LSM Volume

+## Method Naming schme:
+# _cim_xxx()
+# Return CIMInstance without any Associators() call.
+# _cim_xxx_of(cim_yyy)
+# Return CIMInstance associated to cim_yyy
+# _adj_cim_xxx()
+# Retrun CIMInstance with 'adj' only
+# _cim_xxx_of_id(some_id)
+# Return CIMInstance for given ID
+

def handle_cim_errors(method):
def cim_wrapper(*args, **kwargs):
@@ -65,6 +75,35 @@ def handle_cim_errors(method):
traceback.format_exc())
return cim_wrapper

+def _spec_ver_str_to_num(spec_ver_str):
+ """
+ Convert version string stored in CIM_RegisteredProfile to a integer.
+ Example:
+ "1.5.1" -> 1,005,001
+ """
+ tmp_list = [0,0,0]
+ tmp_list = spec_ver_str.split(".")
+ if len(tmp_list) == 2:
+ tmp_list.extend([0])
+ if len(tmp_list) == 3:
+ return (int(tmp_list[0]) * 10 ** 6 +
+ int(tmp_list[1]) * 10 ** 3 +
+ int(tmp_list[2]))
+ return None
+
+class SNIA(object):
+ BLK_ROOT_PROFILE = 'Array'
+ BLK_SRVS_PROFILE = 'Block Services'
+ DISK_LITE_PROFILE = 'Disk Drive Lite'
+ MULTI_SYS_PROFILE = 'Multiple Computer System'
+ SMIS_SPEC_VER_1_4 ='1.4'
+ SMIS_SPEC_VER_1_5 ='1.5'
+ SMIS_SPEC_VER_1_6 ='1.6'
+ _FAKE_SPEC_VER_FALLBACK = '0.1'
+ # This version is indicate we are in fallback mode.
+ # Used by _profile_is_supported()
+ REG_ORG_CODE = pywbem.Uint16(11)
+

class Smis(IStorageAreaNetwork):
"""
@@ -252,13 +291,6 @@ class Smis(IStorageAreaNetwork):
# DSP 1033 Profile Registration
DMTF_INTEROP_NAMESPACES = ['interop', 'root/interop']
SMIS_DEFAULT_NAMESPACE = 'interop'
- SNIA_BLK_ROOT_PROFILE = 'Array'
- SNIA_BLK_SRVS_PROFILE = 'Block Services'
- SNIA_DISK_LITE_PROFILE = 'Disk Drive Lite'
- SNIA_MULTI_SYS_PROFILE = 'Multiple Computer System'
- SNIA_SMIS_SPEC_VER_1_4='1.4'
- SNIA_SMIS_SPEC_VER_1_5='1.5'
- SNIA_SMIS_SPEC_VER_1_6='1.6'

IAAN_WBEM_HTTP_PORT = 5988
IAAN_WBEM_HTTPS_PORT = 5989
@@ -350,7 +382,7 @@ class Smis(IStorageAreaNetwork):
self._c = None
self.tmo = 0
self.system_list = None
- self.cim_reg_profiles = []
+ self.cim_rps = []
self.cim_root_profile_dict = dict()
self.fallback_mode = True # Means we cannot use profile register

@@ -555,31 +587,29 @@ class Smis(IStorageAreaNetwork):

try:
for interop_namespace in Smis.DMTF_INTEROP_NAMESPACES:
- self.cim_reg_profiles = self._c.EnumerateInstances(
+ self.cim_rps = self._c.EnumerateInstances(
'CIM_RegisteredProfile',
namespace=interop_namespace,
- PropertyList=['RegisteredName', 'RegisteredVersion'],
+ PropertyList=['RegisteredName', 'RegisteredVersion',
+ 'RegisteredOrganization'],
LocalOnly=False)
- if len(self.cim_reg_profiles) != 0:
+ if len(self.cim_rps) != 0:
break

- if len(self.cim_reg_profiles) >= 1:
+ if len(self.cim_rps) >= 1:
self.fallback_mode = False
# Support 'Array' profile is step 0 for this whole plugin.
# We find out all 'Array' CIM_RegisteredProfile and stored
# them into self.cim_root_profile_dict
- for cim_reg_profile in self.cim_reg_profiles:
- if 'RegisteredName' not in cim_reg_profile or \
- 'RegisteredVersion' not in cim_reg_profile:
- continue
- if cim_reg_profile['RegisteredName'] == \
- Smis.SNIA_BLK_ROOT_PROFILE:
- ver = cim_reg_profile['RegisteredVersion']
- self.cim_root_profile_dict[ver]= cim_reg_profile
- if len(self.cim_root_profile_dict) == 0:
+ if not self._profile_is_supported(
+ SNIA.BLK_ROOT_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4,
+ strict=False):
raise LsmError(ErrorNumber.NO_SUPPORT,
- "SMI-S provider does not support 'Array'"
- "profile which is prerequisite")
+ "SMI-S provider does not support "
+ "SNIA SMI-S SPEC %s '%s' profile" %
+ (SNIA.SMIS_SPEC_VER_1_4,
+ SNIA.BLK_ROOT_PROFILE))
except CIMError as e:
if e[0] == pywbem.CIM_ERR_NOT_SUPPORTED or \
e[0] == pywbem.CIM_ERR_INVALID_NAMESPACE:
@@ -720,12 +750,8 @@ class Smis(IStorageAreaNetwork):
# Get the cim object that represents the system
cim_sys = None
cim_pcms = None
+ cim_sys = self._cim_sys_of_id(system.id)
if self.fallback_mode:
- cim_sys = self._get_cim_syss_fallback(
- sys_id=system.id,
- property_list=[])[0] # Surely, we will get at least one
- # cim_sys since LSM system already
- # provided.

# Using 'ExposePathsSupported of
# CIM_ProtocolControllerMaskingCapabilities
@@ -752,26 +778,16 @@ class Smis(IStorageAreaNetwork):
cap.set(Capabilities.ACCESS_GROUP_DEL_INITIATOR)
return
else:
- cim_syss = self._get_cim_syss(
- Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- sys_id=system.id,
- property_list=[])
- # we might not get any cim_sys on unsupported system.
- if len(cim_syss) == 1:
- cim_sys = cim_syss[0]
- # Since SNIA SMI-S 1.4rev6:
- # CIM_ControllerConfigurationService is mandatory
- # and it's ExposePaths() and HidePaths() are mandatory
- cap.set(Capabilities.ACCESS_GROUP_LIST)
- cap.set(Capabilities.ACCESS_GROUP_GRANT)
- cap.set(Capabilities.ACCESS_GROUP_REVOKE)
- cap.set(Capabilities.ACCESS_GROUP_ADD_INITIATOR)
- cap.set(Capabilities.ACCESS_GROUP_DEL_INITIATOR)
- cap.set(Capabilities.ACCESS_GROUPS_GRANTED_TO_VOLUME)
- cap.set(Capabilities.VOLUMES_ACCESSIBLE_BY_ACCESS_GROUP)
- else:
- return
+ # Since SNIA SMI-S 1.4rev6:
+ # CIM_ControllerConfigurationService is mandatory
+ # and it's ExposePaths() and HidePaths() are mandatory
+ cap.set(Capabilities.ACCESS_GROUP_LIST)
+ cap.set(Capabilities.ACCESS_GROUP_GRANT)
+ cap.set(Capabilities.ACCESS_GROUP_REVOKE)
+ cap.set(Capabilities.ACCESS_GROUP_ADD_INITIATOR)
+ cap.set(Capabilities.ACCESS_GROUP_DEL_INITIATOR)
+ cap.set(Capabilities.ACCESS_GROUPS_GRANTED_TO_VOLUME)
+ cap.set(Capabilities.VOLUMES_ACCESSIBLE_BY_ACCESS_GROUP)

def _common_capabilities(self, system):
cap = Capabilities()
@@ -1283,19 +1299,15 @@ class Smis(IStorageAreaNetwork):
|
v
CIM_StorageVolume
+ As 'Block Services Package' is mandatory for 'Array' profile, we
+ don't check support status here as startup() already checked 'Array'
+ profile.
"""
rc = []
cim_syss = []
cim_sys_pros = self._property_list_of_id("System")
- if self.fallback_mode:
- cim_syss = self._get_cim_syss_fallback(property_list=cim_sys_pros)
- else:
- cim_syss = self._get_cim_syss(
- Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False,
- property_list=cim_sys_pros,
- raise_error=True)
+
+ cim_syss = self._root_cim_syss(cim_sys_pros)
cim_vol_pros = self._new_vol_cim_vol_pros()
for cim_sys in cim_syss:
sys_id = self._sys_id(cim_sys)
@@ -1405,22 +1417,16 @@ class Smis(IStorageAreaNetwork):
|
v
CIM_StoragePool
+ As 'Block Services Package' is mandatory for 'Array' profile, we
+ don't check support status here as startup() already checked 'Array'
+ profile.
"""
rc = []
cim_pool_pros = self._new_pool_cim_pool_pros(
flags == Pool.RETRIEVE_FULL_INFO)

cim_sys_pros = self._property_list_of_id("System")
- cim_syss = []
- if self.fallback_mode:
- cim_syss = self._get_cim_syss_fallback(property_list=cim_sys_pros)
- else:
- cim_syss = self._get_cim_syss(
- Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False,
- property_list=cim_sys_pros,
- raise_error=True)
+ cim_syss = self._root_cim_syss(cim_sys_pros)

for cim_sys in cim_syss:
system_id = self._sys_id(cim_sys)
@@ -1535,20 +1541,14 @@ class Smis(IStorageAreaNetwork):
def systems(self, flags=0):
"""
Return the storage arrays accessible from this plug-in at this time
+
+ As 'Block Services Package' is mandatory for 'Array' profile, we
+ don't check support status here as startup() already checked 'Array'
+ profile.
"""
cim_sys_pros = self._cim_sys_pros()
- if self.fallback_mode:
- cim_syss = self._get_cim_syss_fallback(property_list=cim_sys_pros)
- else:
- cim_syss = self._get_cim_syss(
- Smis.SNIA_BLK_ROOT_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False,
- property_list=cim_sys_pros,
- raise_error=True)
-
- if cim_syss is None:
- return []
+ cim_syss = self._root_cim_syss(cim_sys_pros)
+
return [Smis._cim_sys_2_lsm_sys(s) for s in cim_syss]

def _new_init(self, cim_st_hwid):
@@ -2246,33 +2246,30 @@ class Smis(IStorageAreaNetwork):
rc = []
cim_syss = []
cim_sys_pros = self._property_list_of_id("System")
- if self.fallback_mode:
- cim_syss = self._get_cim_syss_fallback(property_list=cim_sys_pros)
- else:
- cim_syss = self._get_cim_syss(
- Smis.SNIA_DISK_LITE_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False,
- property_list=cim_sys_pros,
- raise_error=True)
-
+ self._profile_is_supported(SNIA.DISK_LITE_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4,
+ strict=False,
+ raise_error=True)
+
+ # In SNIA SMI-S 1.6rev4 Common Book,
+ # 30.1.5 Associations between ComputerSystems and other Logical
+ # Elements
+ # "If the device may become unavailable while the system as a
+ # whole remains available, the device shall be associated to a
+ # non-top-level system that has availability equivalent to the
+ # device. This system could be a real system or a system in an
+ # intermediate tier (representing some redundancy less than full
+ # redundancy)."
+
+ # Hence DiskDrive might not associated to top level
+ # CIM_ComputerSystem
flag_multi_sys = None
- if not self.fallback_mode:
- flag_multi_sys = self._profile_is_supported(
- Smis.SNIA_MULTI_SYS_PROFILE, Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False)
- # In SNIA SMI-S 1.6rev4 Common Book,
- # 30.1.5 Associations between ComputerSystems and other Logical
- # Elements
- # "If the device may become unavailable while the system as a
- # whole remains available, the device shall be associated to a
- # non-top-level system that has availability equivalent to the
- # device. This system could be a real system or a system in an
- # intermediate tier (representing some redundancy less than full
- # redundancy)."
-
- # Hence DiskDrive might not associated to top level
- # CIM_ComputerSystem
+ if not self.fallback_mode and \
+ self._profile_is_supported(SNIA.MULTI_SYS_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4,
+ strict=False,
+ raise_error=False):
+ flag_multi_sys = True

for cim_sys in cim_syss:
cim_disk_pros = Smis._new_disk_cim_disk_pros(flags)
@@ -3008,15 +3005,15 @@ class Smis(IStorageAreaNetwork):
"""
cim_sys_pros = self._property_list_of_id("System")
if not self.fallback_mode and \
- self._profile_is_supported(Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
+ self._profile_is_supported(SNIA.BLK_SRVS_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4,
strict=False) is None:
raise LsmError(ErrorNumber.NO_SUPPORT,
"SMI-S %s version %s is not supported" %
- (Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4))
+ (SNIA.BLK_SRVS_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4))

- cim_sys = self._get_cim_sys_by_id(pool.system_id)
+ cim_sys = self._cim_sys_of_id(pool.system_id)
cim_pool = self._get_cim_pool_by_id(cim_sys.path, pool.id)
cim_scs = self._get_cim_scs(cim_sys.path)

@@ -3039,15 +3036,15 @@ class Smis(IStorageAreaNetwork):
CreateOrModifyStoragePool()
"""
if not self.fallback_mode and \
- self._profile_is_supported(Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
+ self._profile_is_supported(SNIA.BLK_SRVS_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4,
strict=False) is None:
raise LsmError(ErrorNumber.NO_SUPPORT,
"SMI-S %s version %s is not supported" %
- (Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4))
+ (SNIA.BLK_SRVS_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4))

- cim_sys = self._get_cim_sys_by_id(system.id)
+ cim_sys = self._cim_sys_of_id(system.id)

# we does not support defining thinp_type yet.
# just using whatever provider set.
@@ -3371,238 +3368,106 @@ class Smis(IStorageAreaNetwork):
"CIM_StorageConfigurationService of " +
"CIM_ComputerSystem %s" % cim_sys_path)

- def _profile_is_supported(self, profile_name, spec_ver, strict=False):
+ def _profile_is_supported(self, profile_name, spec_ver, strict=False,
+ raise_error=False):
"""
Usage:
Check whether we support certain profile at certain SNIA
specification version.
- When strict == False(default), profile spec version newer than
- require spec_ver will also be consider as found.
+ When strict == False(default), profile spec version later or equal
+ than require spec_ver will also be consider as found.
When strict == True, only defined spec_version is allowed.
+ Require self.cim_rps containing all CIM_RegisteredProfile
+ Will raise LsmError(ErrorNumber.NO_SUPPORT, 'xxx') if raise_error
+ is True when nothing found.
+ When in fallback mode, we just return
+ _spec_ver_str_to_num(SNIA._FAKE_SPEC_VER_FALLBACK)
Parameter:
- profile_name # Smis.SNIA_REGISTERED_PROFILE_XXX
- spec_ver # Smis.SNIA_SMIS_SPEC_VER_XXX
- property_list # a list of properties should contained in
- # returned CIM_ComputerSystem
- # When property_list == None, we retrieve full
- # data, when property_list == [], we retrieve
- # nothing but a CIMInstanceName.
+ profile_name # SNIA.XXXX_PROFILE
+ spec_ver # SNIA.SMIS_SPEC_VER_XXX
strict # False or True. If True, only defined
# spec_version is consider as supported
# If false, will return the maximum version of
# spec.
+ raise_error # Raise LsmError if not found
Returns:
None # Not supported.
or
- spec_version # the vendor implemented version. like '1.4.1'
- # This is a string, NOT float.
- """
- max_spec_ver = 0
- max_spec_ver_flt = 0
- # assuming spec_ver is well formatted, since we are internal
- # method, we can do that guess.
- req_ver_main = spec_ver.split('.')[0]
- req_ver_sub = spec_ver.split('.')[1]
-
- for cim_reg_profile in self.cim_reg_profiles:
- if 'RegisteredName' not in cim_reg_profile or \
- 'RegisteredVersion' not in cim_reg_profile:
+ spec_int # Integer. Converted by _spec_ver_str_to_num()
+ """
+ if self.fallback_mode:
+ return _spec_ver_str_to_num(SNIA._FAKE_SPEC_VER_FALLBACK)
+ req_ver = _spec_ver_str_to_num(spec_ver)
+
+ max_spec_ver_str = None
+ max_spec_ver = None
+ for cim_rp in self.cim_rps:
+ if 'RegisteredName' not in cim_rp or \
+ 'RegisteredVersion' not in cim_rp:
continue
- if cim_reg_profile['RegisteredName'] == profile_name:
+ if cim_rp['RegisteredName'] == profile_name:
# check spec version
- cur_ver = cim_reg_profile['RegisteredVersion']
- cur_ver_list = cur_ver.split('.')
- if len(cur_ver_list) < 2:
- continue
- cur_ver_flt = float("%s.%s" % tuple(cur_ver_list[0:2]))
- req_ver_flt = float("%s.%s" % (req_ver_main, req_ver_sub))
+ cur_ver = _spec_ver_str_to_num(cim_rp['RegisteredVersion'])

- if strict and cur_ver_flt == req_ver_flt:
+ if strict and cur_ver == req_ver:
return cur_ver
-
- if strict is False and cur_ver_flt >= req_ver_flt:
- if cur_ver_flt > max_spec_ver_flt:
+ elif cur_ver >= req_ver:
+ if max_spec_ver is None or \
+ cur_ver > max_spec_ver:
max_spec_ver = cur_ver
- max_spec_ver_flt = cur_ver_flt
+ max_spec_ver_str = cim_rp['RegisteredVersion']
+ if strict or max_spec_ver is None:
+ raise LsmError(ErrorNumber.NO_SUPPORT,
+ "SNIA SMI-S %s '%s' profile is not supported" %
+ (spec_ver, profile_name))

- if max_spec_ver == 0:
- return None
return max_spec_ver

- def _get_cim_syss(self, profile_name, spec_ver, property_list=None,
- strict=False, sys_id=None, raise_error=False):
+ def _root_cim_syss(self, property_list=None):
"""
- Usage:
- Check whether we support certain profile at certain SNIA
- specification version.
- When strict == False(default), profile spec version newer than
- require spec_ver will also be consider as found.
- When strict == True, only defined spec_version is allowed.
+ For fallback mode, this just enumerate CIM_ComputerSystem.
+ We require vendor to implement profile registration when using
+ "Multiple System Profile".
+ For normal mode, this just find out the root CIM_ComputerSystem
+ via:

- If found, follow this procedure to get CIM_ComputerSystem:
CIM_RegisteredProfile # Root Profile('Array') in interop
|
| CIM_ElementConformsToProfile
v
CIM_ComputerSystem # vendor namespace

- We depend on self.cim_reg_profiles which was updated by startup().
- But this method does not check it, you should check
- self.fallback_mode == True before call this method.
-
- Please use constant spec_ver and profile_name for better
- code management.
- We also apply to system filter in URI which is stored in
- self.system_list
- When returning None, it means current provider does not support
- requested profile or version.
- Parameter:
- profile_name # Smis.SNIA_REGISTERED_PROFILE_XXX
- spec_ver # Smis.SNIA_SMIS_SPEC_VER_XXX
- property_list # a list of properties should contained in
- # returned CIM_ComputerSystem
- # When property_list == None, we retrieve full
- # data, when property_list == [], we retrieve
- # nothing but a CIMInstanceName.
- strict # False or True. If True, only defined
- # spec_version is consider as supported
- sys_id # Only return CIM_ComputerSystem for certain
- # system ID.
- Returns:
- cim_syss # a list of CIMInstanceName of CIM_ComputerSystem
- or
- None # Current SMI-S provider does not support this
- # profile at certain version.
- """
- max_spec_ver = self._profile_is_supported(
- profile_name, spec_ver, strict)
-
- if max_spec_ver is None:
- if raise_error:
- error_msg = ("Current SMI-S provider does not support "
- "SMI-S %s profile, version %s" %
- (profile_name, spec_ver))
- if not strict:
- error_msg = "%s(or later version)" % error_msg
- raise LsmError(ErrorNumber.NO_SUPPORT, error_msg)
- else:
- return None
-
- if max_spec_ver not in self.cim_root_profile_dict.keys():
- raise LsmError(ErrorNumber.INTERNAL_ERROR,
- "Failed to find out CIM_RegisteredProfile " +
- "for profile %s with version %s " %
- (Smis.SNIA_BLK_ROOT_PROFILE, max_spec_ver) +
- "even its subprofile found.")
-
- cim_root_profile = self.cim_root_profile_dict[max_spec_ver]
-
- if property_list is None:
- cim_syss = self._c.Associators(
- cim_root_profile.path,
- ResultClass='CIM_ComputerSystem',
- AssocClass='CIM_ElementConformsToProfile')
- else:
- sys_id_pros = self._property_list_of_id('System')
- for key in sys_id_pros:
- if key not in property_list:
- property_list.extend([key])
- cim_syss = self._c.Associators(
- cim_root_profile.path,
- ResultClass='CIM_ComputerSystem',
- AssocClass='CIM_ElementConformsToProfile',
- PropertyList=property_list)
-
- if self.system_list is None:
- return cim_syss
-
- # Method level filter
- if sys_id is not None:
- return [s for s in cim_syss if self._sys_id(s) == sys_id][0]
-
- # Apply URI system filter
- needed_cim_syss = []
- for cim_sys in cim_syss:
- if self._sys_id(cim_sys) in self.system_list:
- needed_cim_syss.extend([cim_sys])
- return needed_cim_syss
-
- def _get_cim_syss_fallback(self, sys_id=None, property_list=None):
- """
- Usage:
- Find out the root CIM_ComputerSystem using the fallback method:
- CIM_StorageConfigurationService # Enumerate
- |
- | CIM_HostedService
- v
- CIM_ComputerSystem
- If CIM_StorageConfigurationService is not support neither,
- we enumerate CIM_ComputerSystem.
- Parameter:
- property_list # a list of properties should contained in
- # returned CIM_ComputerSystem
- # When property_list == None, we retrieve full
- # data, when property_list == [], we retrieve
- # nothing but a CIMInstanceName.
- Returns:
- cim_syss # A list of CIMInstanceName of CIM_ComputerSystem
- or
- None
+ We also assume no matter which version of root profile can lead to
+ the same CIM_ComputerSystem instance.
+ As CIM_ComputerSystem has no property indicate SNIA SMI-S version,
+ this is assumption should work. Tested on EMC SMI-S provider which
+ provide 1.4, 1.5, 1.6 root profile.
"""
- sys_id_pros = self._property_list_of_id('System')
- flag_full_info = False
+ cim_sys_id_pros = self._property_list_of_id('System')
if property_list is None:
- flag_full_info = True
+ property_list = cim_sys_id_pros
else:
- for key in sys_id_pros:
- if key not in property_list:
- property_list.extend([key])
+ for key_name in cim_sys_id_pros:
+ if key_name not in property_list:
+ property_list.extend([key_name])

- cim_syss = []
- cim_scss_path = []
- try:
- # Note: Please be informed, if PropertyList is an empty list,
- # XIV will return NOTHING, so use EnumerateInstanceNames()
- # when you need nothing but the CIMInstanceName
- cim_scss_path = self._c.EnumerateInstanceNames(
- 'CIM_StorageConfigurationService')
- except CIMError as e:
- # If array does not support CIM_StorageConfigurationService
- # we use CIM_ComputerSystem which is mandatory.
- # We might get some non-storage array listed as system.
- # but we would like to take that risk instead of
- # skipping basic support of old SMIS provider.
- if e[0] == pywbem.CIM_ERR_INVALID_CLASS:
- if flag_full_info:
- cim_syss = self._c.EnumerateInstances(
- 'CIM_ComputerSystem', LocalOnly=False)
- else:
- cim_syss = self._c.EnumerateInstances(
- 'CIM_ComputerSystem',
- PropertyList=property_list,
- LocalOnly=False)
- else:
- raise e
- if not cim_syss:
- for cim_scs_path in cim_scss_path:
- cim_tmp = None
- if flag_full_info:
- cim_tmp = self._c.Associators(
- cim_scs_path,
- AssocClass='CIM_HostedService',
- ResultClass='CIM_ComputerSystem')
- else:
- cim_tmp = self._c.Associators(
- cim_scs_path,
- AssocClass='CIM_HostedService',
+ cim_syss = None
+ if self.fallback_mode:
+ cim_syss = self._c.EnumerateInstances(
+ 'CIM_ComputerSystem',
+ PropertyList=property_list)
+ else:
+ for cim_rp in self.cim_rps:
+ if cim_rp['RegisteredName'] == SNIA.BLK_ROOT_PROFILE and\
+ cim_rp['RegisteredOrganization'] == SNIA.REG_ORG_CODE:
+ cim_syss = self._c.Associators(
+ cim_rp.path,
ResultClass='CIM_ComputerSystem',
- PropertyList=property_list)
- if cim_tmp and cim_tmp[0]:
- cim_syss.extend([cim_tmp[0]])
-
- # Method level filter
- if sys_id is not None:
- return [s for s in cim_syss if self._sys_id(s) == sys_id]
+ AssocClass='CIM_ElementConformsToProfile')
+ if cim_syss is None:
+ raise LsmError(ErrorNumber.NO_SUPPORT,
+ "SMI-S provider is not supporting SNIA SMI-S "
+ "Array profile")

# System URI Filtering
if self.system_list:
@@ -3614,7 +3479,8 @@ class Smis(IStorageAreaNetwork):
else:
return cim_syss

- def _get_cim_sys_by_id(self, system_id, property_list=None):
+
+ def _cim_sys_of_id(self, system_id, property_list=None):
"""
Return a CIMInstance of CIM_ComputerSystem for given system id.
"""
@@ -3626,15 +3492,8 @@ class Smis(IStorageAreaNetwork):
if pro not in property_list:
property_list.extend([pro])

- if self.fallback_mode:
- cim_syss = self._get_cim_syss_fallback(property_list)
- else:
- cim_syss = self._get_cim_syss(
- Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False,
- property_list=property_list,
- raise_error=True)
+ cim_syss = self._root_cim_syss(property_list)
+
for cim_sys in cim_syss:
if self._sys_id(cim_sys) == system_id:
return cim_sys
--
1.8.3.1
Tony Asleson
2014-05-19 23:35:15 UTC
Permalink
With this patch, when I list systems I'm seeing this:

ID | Name | Status | Status Info
-------------------------------------------------------------
NodePairSystem1 | NodePairSystem1 | Unknown,OK |
200002095D | 1303657-2 | Unknown,OK |
20000208A4 | 1303657-3 | Unknown,OK |
2FF70002AC000E49 | 3PAR_ARR_1 | Unknown,OK |

Instead of this:

ID | Name | Status | Status Info
--------------------------------------------------------
2FF70002AC000E49 | 3PAR_ARR_1 | Unknown,OK |


Please take a look, the other objects are not usable as systems.

Thanks,
Tony
Post by Gris Ge
* Convert SMI-S SPEC version into integer for better comparison.
Please check _spec_ver_str_to_num() for detail.
* Let _root_cim_syss() handle the fall back checking. It will return a list
of CIM_ComputerSystem for fallback mode or not.
* Checking for 1.4 'Array' profile support in startup().
As 'Block Services Package' (AKA: BSP) is mandatory for that profile, we
don't do extra check in methods using BSP profile.
* Noting down the method naming scheme for consistency.
* Move SNIA related constants to a standalone class SNIA which shorter the
constant variable name.
* _profile_is_supported() now support raise error if not found.
* Split _cim_sys_of_id() out to raise LsmError ErrorNumber.NOT_FOUND_SYSTEM.
* Add RegisteredOrganization checking in CIM_RegisteredProfile.
---
plugin/smispy/smis.py | 505 ++++++++++++++++++--------------------------------
1 file changed, 182 insertions(+), 323 deletions(-)
diff --git a/plugin/smispy/smis.py b/plugin/smispy/smis.py
index c63d8cd..e0a0d97 100644
--- a/plugin/smispy/smis.py
+++ b/plugin/smispy/smis.py
@@ -37,6 +37,16 @@ from lsm import (IStorageAreaNetwork, Error, uri_parse, LsmError, ErrorNumber,
# pool Object of LSM Pool
# vol Object of LSM Volume
+# _cim_xxx()
+# Return CIMInstance without any Associators() call.
+# _cim_xxx_of(cim_yyy)
+# Return CIMInstance associated to cim_yyy
+# _adj_cim_xxx()
+# Retrun CIMInstance with 'adj' only
+# _cim_xxx_of_id(some_id)
+# Return CIMInstance for given ID
+
traceback.format_exc())
return cim_wrapper
+ """
+ Convert version string stored in CIM_RegisteredProfile to a integer.
+ "1.5.1" -> 1,005,001
+ """
+ tmp_list = [0,0,0]
+ tmp_list = spec_ver_str.split(".")
+ tmp_list.extend([0])
+ return (int(tmp_list[0]) * 10 ** 6 +
+ int(tmp_list[1]) * 10 ** 3 +
+ int(tmp_list[2]))
+ return None
+
+ BLK_ROOT_PROFILE = 'Array'
+ BLK_SRVS_PROFILE = 'Block Services'
+ DISK_LITE_PROFILE = 'Disk Drive Lite'
+ MULTI_SYS_PROFILE = 'Multiple Computer System'
+ SMIS_SPEC_VER_1_4 ='1.4'
+ SMIS_SPEC_VER_1_5 ='1.5'
+ SMIS_SPEC_VER_1_6 ='1.6'
+ _FAKE_SPEC_VER_FALLBACK = '0.1'
+ # This version is indicate we are in fallback mode.
+ # Used by _profile_is_supported()
+ REG_ORG_CODE = pywbem.Uint16(11)
+
"""
# DSP 1033 Profile Registration
DMTF_INTEROP_NAMESPACES = ['interop', 'root/interop']
SMIS_DEFAULT_NAMESPACE = 'interop'
- SNIA_BLK_ROOT_PROFILE = 'Array'
- SNIA_BLK_SRVS_PROFILE = 'Block Services'
- SNIA_DISK_LITE_PROFILE = 'Disk Drive Lite'
- SNIA_MULTI_SYS_PROFILE = 'Multiple Computer System'
- SNIA_SMIS_SPEC_VER_1_4='1.4'
- SNIA_SMIS_SPEC_VER_1_5='1.5'
- SNIA_SMIS_SPEC_VER_1_6='1.6'
IAAN_WBEM_HTTP_PORT = 5988
IAAN_WBEM_HTTPS_PORT = 5989
self._c = None
self.tmo = 0
self.system_list = None
- self.cim_reg_profiles = []
+ self.cim_rps = []
self.cim_root_profile_dict = dict()
self.fallback_mode = True # Means we cannot use profile register
- self.cim_reg_profiles = self._c.EnumerateInstances(
+ self.cim_rps = self._c.EnumerateInstances(
'CIM_RegisteredProfile',
namespace=interop_namespace,
- PropertyList=['RegisteredName', 'RegisteredVersion'],
+ PropertyList=['RegisteredName', 'RegisteredVersion',
+ 'RegisteredOrganization'],
LocalOnly=False)
break
self.fallback_mode = False
# Support 'Array' profile is step 0 for this whole plugin.
# We find out all 'Array' CIM_RegisteredProfile and stored
# them into self.cim_root_profile_dict
- if 'RegisteredName' not in cim_reg_profile or \
- continue
- if cim_reg_profile['RegisteredName'] == \
- ver = cim_reg_profile['RegisteredVersion']
- self.cim_root_profile_dict[ver]= cim_reg_profile
+ if not self._profile_is_supported(
+ SNIA.BLK_ROOT_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4,
raise LsmError(ErrorNumber.NO_SUPPORT,
- "SMI-S provider does not support 'Array'"
- "profile which is prerequisite")
+ "SMI-S provider does not support "
+ "SNIA SMI-S SPEC %s '%s' profile" %
+ (SNIA.SMIS_SPEC_VER_1_4,
+ SNIA.BLK_ROOT_PROFILE))
if e[0] == pywbem.CIM_ERR_NOT_SUPPORTED or \
# Get the cim object that represents the system
cim_sys = None
cim_pcms = None
+ cim_sys = self._cim_sys_of_id(system.id)
- cim_sys = self._get_cim_syss_fallback(
- sys_id=system.id,
- property_list=[])[0] # Surely, we will get at least one
- # cim_sys since LSM system already
- # provided.
# Using 'ExposePathsSupported of
# CIM_ProtocolControllerMaskingCapabilities
cap.set(Capabilities.ACCESS_GROUP_DEL_INITIATOR)
return
- cim_syss = self._get_cim_syss(
- Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- sys_id=system.id,
- property_list=[])
- # we might not get any cim_sys on unsupported system.
- cim_sys = cim_syss[0]
- # CIM_ControllerConfigurationService is mandatory
- # and it's ExposePaths() and HidePaths() are mandatory
- cap.set(Capabilities.ACCESS_GROUP_LIST)
- cap.set(Capabilities.ACCESS_GROUP_GRANT)
- cap.set(Capabilities.ACCESS_GROUP_REVOKE)
- cap.set(Capabilities.ACCESS_GROUP_ADD_INITIATOR)
- cap.set(Capabilities.ACCESS_GROUP_DEL_INITIATOR)
- cap.set(Capabilities.ACCESS_GROUPS_GRANTED_TO_VOLUME)
- cap.set(Capabilities.VOLUMES_ACCESSIBLE_BY_ACCESS_GROUP)
- return
+ # CIM_ControllerConfigurationService is mandatory
+ # and it's ExposePaths() and HidePaths() are mandatory
+ cap.set(Capabilities.ACCESS_GROUP_LIST)
+ cap.set(Capabilities.ACCESS_GROUP_GRANT)
+ cap.set(Capabilities.ACCESS_GROUP_REVOKE)
+ cap.set(Capabilities.ACCESS_GROUP_ADD_INITIATOR)
+ cap.set(Capabilities.ACCESS_GROUP_DEL_INITIATOR)
+ cap.set(Capabilities.ACCESS_GROUPS_GRANTED_TO_VOLUME)
+ cap.set(Capabilities.VOLUMES_ACCESSIBLE_BY_ACCESS_GROUP)
cap = Capabilities()
|
v
CIM_StorageVolume
+ As 'Block Services Package' is mandatory for 'Array' profile, we
+ don't check support status here as startup() already checked 'Array'
+ profile.
"""
rc = []
cim_syss = []
cim_sys_pros = self._property_list_of_id("System")
- cim_syss = self._get_cim_syss_fallback(property_list=cim_sys_pros)
- cim_syss = self._get_cim_syss(
- Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False,
- property_list=cim_sys_pros,
- raise_error=True)
+
+ cim_syss = self._root_cim_syss(cim_sys_pros)
cim_vol_pros = self._new_vol_cim_vol_pros()
sys_id = self._sys_id(cim_sys)
|
v
CIM_StoragePool
+ As 'Block Services Package' is mandatory for 'Array' profile, we
+ don't check support status here as startup() already checked 'Array'
+ profile.
"""
rc = []
cim_pool_pros = self._new_pool_cim_pool_pros(
flags == Pool.RETRIEVE_FULL_INFO)
cim_sys_pros = self._property_list_of_id("System")
- cim_syss = []
- cim_syss = self._get_cim_syss_fallback(property_list=cim_sys_pros)
- cim_syss = self._get_cim_syss(
- Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False,
- property_list=cim_sys_pros,
- raise_error=True)
+ cim_syss = self._root_cim_syss(cim_sys_pros)
system_id = self._sys_id(cim_sys)
"""
Return the storage arrays accessible from this plug-in at this time
+
+ As 'Block Services Package' is mandatory for 'Array' profile, we
+ don't check support status here as startup() already checked 'Array'
+ profile.
"""
cim_sys_pros = self._cim_sys_pros()
- cim_syss = self._get_cim_syss_fallback(property_list=cim_sys_pros)
- cim_syss = self._get_cim_syss(
- Smis.SNIA_BLK_ROOT_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False,
- property_list=cim_sys_pros,
- raise_error=True)
-
- return []
+ cim_syss = self._root_cim_syss(cim_sys_pros)
+
return [Smis._cim_sys_2_lsm_sys(s) for s in cim_syss]
rc = []
cim_syss = []
cim_sys_pros = self._property_list_of_id("System")
- cim_syss = self._get_cim_syss_fallback(property_list=cim_sys_pros)
- cim_syss = self._get_cim_syss(
- Smis.SNIA_DISK_LITE_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False,
- property_list=cim_sys_pros,
- raise_error=True)
-
+ self._profile_is_supported(SNIA.DISK_LITE_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4,
+ strict=False,
+ raise_error=True)
+
+ # In SNIA SMI-S 1.6rev4 Common Book,
+ # 30.1.5 Associations between ComputerSystems and other Logical
+ # Elements
+ # "If the device may become unavailable while the system as a
+ # whole remains available, the device shall be associated to a
+ # non-top-level system that has availability equivalent to the
+ # device. This system could be a real system or a system in an
+ # intermediate tier (representing some redundancy less than full
+ # redundancy)."
+
+ # Hence DiskDrive might not associated to top level
+ # CIM_ComputerSystem
flag_multi_sys = None
- flag_multi_sys = self._profile_is_supported(
- Smis.SNIA_MULTI_SYS_PROFILE, Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False)
- # In SNIA SMI-S 1.6rev4 Common Book,
- # 30.1.5 Associations between ComputerSystems and other Logical
- # Elements
- # "If the device may become unavailable while the system as a
- # whole remains available, the device shall be associated to a
- # non-top-level system that has availability equivalent to the
- # device. This system could be a real system or a system in an
- # intermediate tier (representing some redundancy less than full
- # redundancy)."
-
- # Hence DiskDrive might not associated to top level
- # CIM_ComputerSystem
+ if not self.fallback_mode and \
+ self._profile_is_supported(SNIA.MULTI_SYS_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4,
+ strict=False,
+ flag_multi_sys = True
cim_disk_pros = Smis._new_disk_cim_disk_pros(flags)
"""
cim_sys_pros = self._property_list_of_id("System")
if not self.fallback_mode and \
- self._profile_is_supported(Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
+ self._profile_is_supported(SNIA.BLK_SRVS_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4,
raise LsmError(ErrorNumber.NO_SUPPORT,
"SMI-S %s version %s is not supported" %
- (Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4))
+ (SNIA.BLK_SRVS_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4))
- cim_sys = self._get_cim_sys_by_id(pool.system_id)
+ cim_sys = self._cim_sys_of_id(pool.system_id)
cim_pool = self._get_cim_pool_by_id(cim_sys.path, pool.id)
cim_scs = self._get_cim_scs(cim_sys.path)
CreateOrModifyStoragePool()
"""
if not self.fallback_mode and \
- self._profile_is_supported(Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
+ self._profile_is_supported(SNIA.BLK_SRVS_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4,
raise LsmError(ErrorNumber.NO_SUPPORT,
"SMI-S %s version %s is not supported" %
- (Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4))
+ (SNIA.BLK_SRVS_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4))
- cim_sys = self._get_cim_sys_by_id(system.id)
+ cim_sys = self._cim_sys_of_id(system.id)
# we does not support defining thinp_type yet.
# just using whatever provider set.
"CIM_StorageConfigurationService of " +
"CIM_ComputerSystem %s" % cim_sys_path)
+ def _profile_is_supported(self, profile_name, spec_ver, strict=False,
"""
Check whether we support certain profile at certain SNIA
specification version.
- When strict == False(default), profile spec version newer than
- require spec_ver will also be consider as found.
+ When strict == False(default), profile spec version later or equal
+ than require spec_ver will also be consider as found.
When strict == True, only defined spec_version is allowed.
+ Require self.cim_rps containing all CIM_RegisteredProfile
+ Will raise LsmError(ErrorNumber.NO_SUPPORT, 'xxx') if raise_error
+ is True when nothing found.
+ When in fallback mode, we just return
+ _spec_ver_str_to_num(SNIA._FAKE_SPEC_VER_FALLBACK)
- profile_name # Smis.SNIA_REGISTERED_PROFILE_XXX
- spec_ver # Smis.SNIA_SMIS_SPEC_VER_XXX
- property_list # a list of properties should contained in
- # returned CIM_ComputerSystem
- # When property_list == None, we retrieve full
- # data, when property_list == [], we retrieve
- # nothing but a CIMInstanceName.
+ profile_name # SNIA.XXXX_PROFILE
+ spec_ver # SNIA.SMIS_SPEC_VER_XXX
strict # False or True. If True, only defined
# spec_version is consider as supported
# If false, will return the maximum version of
# spec.
+ raise_error # Raise LsmError if not found
None # Not supported.
or
- spec_version # the vendor implemented version. like '1.4.1'
- # This is a string, NOT float.
- """
- max_spec_ver = 0
- max_spec_ver_flt = 0
- # assuming spec_ver is well formatted, since we are internal
- # method, we can do that guess.
- req_ver_main = spec_ver.split('.')[0]
- req_ver_sub = spec_ver.split('.')[1]
-
- if 'RegisteredName' not in cim_reg_profile or \
+ spec_int # Integer. Converted by _spec_ver_str_to_num()
+ """
+ return _spec_ver_str_to_num(SNIA._FAKE_SPEC_VER_FALLBACK)
+ req_ver = _spec_ver_str_to_num(spec_ver)
+
+ max_spec_ver_str = None
+ max_spec_ver = None
+ if 'RegisteredName' not in cim_rp or \
continue
# check spec version
- cur_ver = cim_reg_profile['RegisteredVersion']
- cur_ver_list = cur_ver.split('.')
- continue
- cur_ver_flt = float("%s.%s" % tuple(cur_ver_list[0:2]))
- req_ver_flt = float("%s.%s" % (req_ver_main, req_ver_sub))
+ cur_ver = _spec_ver_str_to_num(cim_rp['RegisteredVersion'])
return cur_ver
-
+ if max_spec_ver is None or \
max_spec_ver = cur_ver
- max_spec_ver_flt = cur_ver_flt
+ max_spec_ver_str = cim_rp['RegisteredVersion']
+ raise LsmError(ErrorNumber.NO_SUPPORT,
+ "SNIA SMI-S %s '%s' profile is not supported" %
+ (spec_ver, profile_name))
- return None
return max_spec_ver
- def _get_cim_syss(self, profile_name, spec_ver, property_list=None,
"""
- Check whether we support certain profile at certain SNIA
- specification version.
- When strict == False(default), profile spec version newer than
- require spec_ver will also be consider as found.
- When strict == True, only defined spec_version is allowed.
+ For fallback mode, this just enumerate CIM_ComputerSystem.
+ We require vendor to implement profile registration when using
+ "Multiple System Profile".
+ For normal mode, this just find out the root CIM_ComputerSystem
CIM_RegisteredProfile # Root Profile('Array') in interop
|
| CIM_ElementConformsToProfile
v
CIM_ComputerSystem # vendor namespace
- We depend on self.cim_reg_profiles which was updated by startup().
- But this method does not check it, you should check
- self.fallback_mode == True before call this method.
-
- Please use constant spec_ver and profile_name for better
- code management.
- We also apply to system filter in URI which is stored in
- self.system_list
- When returning None, it means current provider does not support
- requested profile or version.
- profile_name # Smis.SNIA_REGISTERED_PROFILE_XXX
- spec_ver # Smis.SNIA_SMIS_SPEC_VER_XXX
- property_list # a list of properties should contained in
- # returned CIM_ComputerSystem
- # When property_list == None, we retrieve full
- # data, when property_list == [], we retrieve
- # nothing but a CIMInstanceName.
- strict # False or True. If True, only defined
- # spec_version is consider as supported
- sys_id # Only return CIM_ComputerSystem for certain
- # system ID.
- cim_syss # a list of CIMInstanceName of CIM_ComputerSystem
- or
- None # Current SMI-S provider does not support this
- # profile at certain version.
- """
- max_spec_ver = self._profile_is_supported(
- profile_name, spec_ver, strict)
-
- error_msg = ("Current SMI-S provider does not support "
- "SMI-S %s profile, version %s" %
- (profile_name, spec_ver))
- error_msg = "%s(or later version)" % error_msg
- raise LsmError(ErrorNumber.NO_SUPPORT, error_msg)
- return None
-
- raise LsmError(ErrorNumber.INTERNAL_ERROR,
- "Failed to find out CIM_RegisteredProfile " +
- "for profile %s with version %s " %
- (Smis.SNIA_BLK_ROOT_PROFILE, max_spec_ver) +
- "even its subprofile found.")
-
- cim_root_profile = self.cim_root_profile_dict[max_spec_ver]
-
- cim_syss = self._c.Associators(
- cim_root_profile.path,
- ResultClass='CIM_ComputerSystem',
- AssocClass='CIM_ElementConformsToProfile')
- sys_id_pros = self._property_list_of_id('System')
- property_list.extend([key])
- cim_syss = self._c.Associators(
- cim_root_profile.path,
- ResultClass='CIM_ComputerSystem',
- AssocClass='CIM_ElementConformsToProfile',
- PropertyList=property_list)
-
- return cim_syss
-
- # Method level filter
- return [s for s in cim_syss if self._sys_id(s) == sys_id][0]
-
- # Apply URI system filter
- needed_cim_syss = []
- needed_cim_syss.extend([cim_sys])
- return needed_cim_syss
-
- """
- CIM_StorageConfigurationService # Enumerate
- |
- | CIM_HostedService
- v
- CIM_ComputerSystem
- If CIM_StorageConfigurationService is not support neither,
- we enumerate CIM_ComputerSystem.
- property_list # a list of properties should contained in
- # returned CIM_ComputerSystem
- # When property_list == None, we retrieve full
- # data, when property_list == [], we retrieve
- # nothing but a CIMInstanceName.
- cim_syss # A list of CIMInstanceName of CIM_ComputerSystem
- or
- None
+ We also assume no matter which version of root profile can lead to
+ the same CIM_ComputerSystem instance.
+ As CIM_ComputerSystem has no property indicate SNIA SMI-S version,
+ this is assumption should work. Tested on EMC SMI-S provider which
+ provide 1.4, 1.5, 1.6 root profile.
"""
- sys_id_pros = self._property_list_of_id('System')
- flag_full_info = False
+ cim_sys_id_pros = self._property_list_of_id('System')
- flag_full_info = True
+ property_list = cim_sys_id_pros
- property_list.extend([key])
+ property_list.extend([key_name])
- cim_syss = []
- cim_scss_path = []
- # Note: Please be informed, if PropertyList is an empty list,
- # XIV will return NOTHING, so use EnumerateInstanceNames()
- # when you need nothing but the CIMInstanceName
- cim_scss_path = self._c.EnumerateInstanceNames(
- 'CIM_StorageConfigurationService')
- # If array does not support CIM_StorageConfigurationService
- # we use CIM_ComputerSystem which is mandatory.
- # We might get some non-storage array listed as system.
- # but we would like to take that risk instead of
- # skipping basic support of old SMIS provider.
- cim_syss = self._c.EnumerateInstances(
- 'CIM_ComputerSystem', LocalOnly=False)
- cim_syss = self._c.EnumerateInstances(
- 'CIM_ComputerSystem',
- PropertyList=property_list,
- LocalOnly=False)
- raise e
- cim_tmp = None
- cim_tmp = self._c.Associators(
- cim_scs_path,
- AssocClass='CIM_HostedService',
- ResultClass='CIM_ComputerSystem')
- cim_tmp = self._c.Associators(
- cim_scs_path,
- AssocClass='CIM_HostedService',
+ cim_syss = None
+ cim_syss = self._c.EnumerateInstances(
+ 'CIM_ComputerSystem',
+ PropertyList=property_list)
+ if cim_rp['RegisteredName'] == SNIA.BLK_ROOT_PROFILE and\
+ cim_syss = self._c.Associators(
+ cim_rp.path,
ResultClass='CIM_ComputerSystem',
- PropertyList=property_list)
- cim_syss.extend([cim_tmp[0]])
-
- # Method level filter
- return [s for s in cim_syss if self._sys_id(s) == sys_id]
+ AssocClass='CIM_ElementConformsToProfile')
+ raise LsmError(ErrorNumber.NO_SUPPORT,
+ "SMI-S provider is not supporting SNIA SMI-S "
+ "Array profile")
# System URI Filtering
return cim_syss
+
"""
Return a CIMInstance of CIM_ComputerSystem for given system id.
"""
property_list.extend([pro])
- cim_syss = self._get_cim_syss_fallback(property_list)
- cim_syss = self._get_cim_syss(
- Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False,
- property_list=property_list,
- raise_error=True)
+ cim_syss = self._root_cim_syss(property_list)
+
return cim_sys
Gris Ge
2014-05-20 01:32:25 UTC
Permalink
Post by Tony Asleson
ID | Name | Status | Status Info
-------------------------------------------------------------
NodePairSystem1 | NodePairSystem1 | Unknown,OK |
200002095D | 1303657-2 | Unknown,OK |
20000208A4 | 1303657-3 | Unknown,OK |
2FF70002AC000E49 | 3PAR_ARR_1 | Unknown,OK |
ID | Name | Status | Status Info
--------------------------------------------------------
2FF70002AC000E49 | 3PAR_ARR_1 | Unknown,OK |
Please take a look, the other objects are not usable as systems.
Thanks,
Tony
Hi Tony,

I changed the fallback mode work flow by assuming fallback array does
not support 'Multiple System' profile.
I will change that code back to old way:
Enumerata CIM_ControllerConfigurationService
|
v
CIM_ComputerSystem

This is not a standard way, but a hack(that's why fallback mode for).

Can you email me the URI privately?

I will investigate through and send a V2 patch.

Best regards.
--
Gris Ge
Gris Ge
2014-05-21 01:17:09 UTC
Permalink
* Convert SMI-S SPEC version into integer for better comparison.
Please check _spec_ver_str_to_num() for detail.
* Let _root_cim_syss() handle the fall back checking. It will return a list
of CIM_ComputerSystem for fallback mode or not.
* Checking for 1.4 'Array' profile support in startup().
As 'Block Services Package' (AKA: BSP) is mandatory for that profile, we
don't do extra check in methods using BSP profile.
* Noting down the method naming scheme for consistency.
* Move SNIA related constants to a standalone class SNIA which shorter the
constant variable name.
* _profile_is_supported() now support raise error if not found.
* Split _cim_sys_of_id() out to raise LsmError ErrorNumber.NOT_FOUND_SYSTEM.
* Add RegisteredOrganization checking in CIM_RegisteredProfile.

Changes since V2:
* In case fallmode facing 'multiple system' profile supported array,
the _root_cim_syss() will use the old way to get top ComputerSystem:
CIM_StorageConfigurationService -> ComputerSystem
* Add author names.

Signed-off-by: Gris Ge <***@redhat.com>
---
plugin/smispy/smis.py | 531 ++++++++++++++++++++------------------------------
1 file changed, 214 insertions(+), 317 deletions(-)

diff --git a/plugin/smispy/smis.py b/plugin/smispy/smis.py
index c63d8cd..efaffd6 100644
--- a/plugin/smispy/smis.py
+++ b/plugin/smispy/smis.py
@@ -13,6 +13,9 @@
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
# USA
+#
+# Author: tasleson
+# Gris Ge <***@redhat.com>

from string import split
import time
@@ -32,11 +35,22 @@ from lsm import (IStorageAreaNetwork, Error, uri_parse, LsmError, ErrorNumber,
# cim_pool CIM_StoragePool
# cim_scs CIM_StorageConfigurationService
# cim_vol CIM_StorageVolume
+# cim_rp CIM_RegisteredProfile
#
# sys Object of LSM System
# pool Object of LSM Pool
# vol Object of LSM Volume

+## Method Naming schme:
+# _cim_xxx()
+# Return CIMInstance without any Associators() call.
+# _cim_xxx_of(cim_yyy)
+# Return CIMInstance associated to cim_yyy
+# _adj_cim_xxx()
+# Retrun CIMInstance with 'adj' only
+# _cim_xxx_of_id(some_id)
+# Return CIMInstance for given ID
+

def handle_cim_errors(method):
def cim_wrapper(*args, **kwargs):
@@ -65,6 +79,32 @@ def handle_cim_errors(method):
traceback.format_exc())
return cim_wrapper

+def _spec_ver_str_to_num(spec_ver_str):
+ """
+ Convert version string stored in CIM_RegisteredProfile to a integer.
+ Example:
+ "1.5.1" -> 1,005,001
+ """
+ tmp_list = [0,0,0]
+ tmp_list = spec_ver_str.split(".")
+ if len(tmp_list) == 2:
+ tmp_list.extend([0])
+ if len(tmp_list) == 3:
+ return (int(tmp_list[0]) * 10 ** 6 +
+ int(tmp_list[1]) * 10 ** 3 +
+ int(tmp_list[2]))
+ return None
+
+class SNIA(object):
+ BLK_ROOT_PROFILE = 'Array'
+ BLK_SRVS_PROFILE = 'Block Services'
+ DISK_LITE_PROFILE = 'Disk Drive Lite'
+ MULTI_SYS_PROFILE = 'Multiple Computer System'
+ SMIS_SPEC_VER_1_4 ='1.4'
+ SMIS_SPEC_VER_1_5 ='1.5'
+ SMIS_SPEC_VER_1_6 ='1.6'
+ REG_ORG_CODE = pywbem.Uint16(11)
+

class Smis(IStorageAreaNetwork):
"""
@@ -252,13 +292,6 @@ class Smis(IStorageAreaNetwork):
# DSP 1033 Profile Registration
DMTF_INTEROP_NAMESPACES = ['interop', 'root/interop']
SMIS_DEFAULT_NAMESPACE = 'interop'
- SNIA_BLK_ROOT_PROFILE = 'Array'
- SNIA_BLK_SRVS_PROFILE = 'Block Services'
- SNIA_DISK_LITE_PROFILE = 'Disk Drive Lite'
- SNIA_MULTI_SYS_PROFILE = 'Multiple Computer System'
- SNIA_SMIS_SPEC_VER_1_4='1.4'
- SNIA_SMIS_SPEC_VER_1_5='1.5'
- SNIA_SMIS_SPEC_VER_1_6='1.6'

IAAN_WBEM_HTTP_PORT = 5988
IAAN_WBEM_HTTPS_PORT = 5989
@@ -350,7 +383,7 @@ class Smis(IStorageAreaNetwork):
self._c = None
self.tmo = 0
self.system_list = None
- self.cim_reg_profiles = []
+ self.cim_rps = []
self.cim_root_profile_dict = dict()
self.fallback_mode = True # Means we cannot use profile register

@@ -555,31 +588,29 @@ class Smis(IStorageAreaNetwork):

try:
for interop_namespace in Smis.DMTF_INTEROP_NAMESPACES:
- self.cim_reg_profiles = self._c.EnumerateInstances(
+ self.cim_rps = self._c.EnumerateInstances(
'CIM_RegisteredProfile',
namespace=interop_namespace,
- PropertyList=['RegisteredName', 'RegisteredVersion'],
+ PropertyList=['RegisteredName', 'RegisteredVersion',
+ 'RegisteredOrganization'],
LocalOnly=False)
- if len(self.cim_reg_profiles) != 0:
+ if len(self.cim_rps) != 0:
break

- if len(self.cim_reg_profiles) >= 1:
+ if len(self.cim_rps) >= 1:
self.fallback_mode = False
# Support 'Array' profile is step 0 for this whole plugin.
# We find out all 'Array' CIM_RegisteredProfile and stored
# them into self.cim_root_profile_dict
- for cim_reg_profile in self.cim_reg_profiles:
- if 'RegisteredName' not in cim_reg_profile or \
- 'RegisteredVersion' not in cim_reg_profile:
- continue
- if cim_reg_profile['RegisteredName'] == \
- Smis.SNIA_BLK_ROOT_PROFILE:
- ver = cim_reg_profile['RegisteredVersion']
- self.cim_root_profile_dict[ver]= cim_reg_profile
- if len(self.cim_root_profile_dict) == 0:
+ if not self._profile_is_supported(
+ SNIA.BLK_ROOT_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4,
+ strict=False):
raise LsmError(ErrorNumber.NO_SUPPORT,
- "SMI-S provider does not support 'Array'"
- "profile which is prerequisite")
+ "SMI-S provider does not support "
+ "SNIA SMI-S SPEC %s '%s' profile" %
+ (SNIA.SMIS_SPEC_VER_1_4,
+ SNIA.BLK_ROOT_PROFILE))
except CIMError as e:
if e[0] == pywbem.CIM_ERR_NOT_SUPPORTED or \
e[0] == pywbem.CIM_ERR_INVALID_NAMESPACE:
@@ -720,12 +751,8 @@ class Smis(IStorageAreaNetwork):
# Get the cim object that represents the system
cim_sys = None
cim_pcms = None
+ cim_sys = self._cim_sys_of_id(system.id)
if self.fallback_mode:
- cim_sys = self._get_cim_syss_fallback(
- sys_id=system.id,
- property_list=[])[0] # Surely, we will get at least one
- # cim_sys since LSM system already
- # provided.

# Using 'ExposePathsSupported of
# CIM_ProtocolControllerMaskingCapabilities
@@ -752,26 +779,16 @@ class Smis(IStorageAreaNetwork):
cap.set(Capabilities.ACCESS_GROUP_DEL_INITIATOR)
return
else:
- cim_syss = self._get_cim_syss(
- Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- sys_id=system.id,
- property_list=[])
- # we might not get any cim_sys on unsupported system.
- if len(cim_syss) == 1:
- cim_sys = cim_syss[0]
- # Since SNIA SMI-S 1.4rev6:
- # CIM_ControllerConfigurationService is mandatory
- # and it's ExposePaths() and HidePaths() are mandatory
- cap.set(Capabilities.ACCESS_GROUP_LIST)
- cap.set(Capabilities.ACCESS_GROUP_GRANT)
- cap.set(Capabilities.ACCESS_GROUP_REVOKE)
- cap.set(Capabilities.ACCESS_GROUP_ADD_INITIATOR)
- cap.set(Capabilities.ACCESS_GROUP_DEL_INITIATOR)
- cap.set(Capabilities.ACCESS_GROUPS_GRANTED_TO_VOLUME)
- cap.set(Capabilities.VOLUMES_ACCESSIBLE_BY_ACCESS_GROUP)
- else:
- return
+ # Since SNIA SMI-S 1.4rev6:
+ # CIM_ControllerConfigurationService is mandatory
+ # and it's ExposePaths() and HidePaths() are mandatory
+ cap.set(Capabilities.ACCESS_GROUP_LIST)
+ cap.set(Capabilities.ACCESS_GROUP_GRANT)
+ cap.set(Capabilities.ACCESS_GROUP_REVOKE)
+ cap.set(Capabilities.ACCESS_GROUP_ADD_INITIATOR)
+ cap.set(Capabilities.ACCESS_GROUP_DEL_INITIATOR)
+ cap.set(Capabilities.ACCESS_GROUPS_GRANTED_TO_VOLUME)
+ cap.set(Capabilities.VOLUMES_ACCESSIBLE_BY_ACCESS_GROUP)

def _common_capabilities(self, system):
cap = Capabilities()
@@ -1283,19 +1300,15 @@ class Smis(IStorageAreaNetwork):
|
v
CIM_StorageVolume
+ As 'Block Services Package' is mandatory for 'Array' profile, we
+ don't check support status here as startup() already checked 'Array'
+ profile.
"""
rc = []
cim_syss = []
cim_sys_pros = self._property_list_of_id("System")
- if self.fallback_mode:
- cim_syss = self._get_cim_syss_fallback(property_list=cim_sys_pros)
- else:
- cim_syss = self._get_cim_syss(
- Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False,
- property_list=cim_sys_pros,
- raise_error=True)
+
+ cim_syss = self._root_cim_syss(cim_sys_pros)
cim_vol_pros = self._new_vol_cim_vol_pros()
for cim_sys in cim_syss:
sys_id = self._sys_id(cim_sys)
@@ -1405,22 +1418,16 @@ class Smis(IStorageAreaNetwork):
|
v
CIM_StoragePool
+ As 'Block Services Package' is mandatory for 'Array' profile, we
+ don't check support status here as startup() already checked 'Array'
+ profile.
"""
rc = []
cim_pool_pros = self._new_pool_cim_pool_pros(
flags == Pool.RETRIEVE_FULL_INFO)

cim_sys_pros = self._property_list_of_id("System")
- cim_syss = []
- if self.fallback_mode:
- cim_syss = self._get_cim_syss_fallback(property_list=cim_sys_pros)
- else:
- cim_syss = self._get_cim_syss(
- Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False,
- property_list=cim_sys_pros,
- raise_error=True)
+ cim_syss = self._root_cim_syss(cim_sys_pros)

for cim_sys in cim_syss:
system_id = self._sys_id(cim_sys)
@@ -1535,20 +1542,14 @@ class Smis(IStorageAreaNetwork):
def systems(self, flags=0):
"""
Return the storage arrays accessible from this plug-in at this time
+
+ As 'Block Services Package' is mandatory for 'Array' profile, we
+ don't check support status here as startup() already checked 'Array'
+ profile.
"""
cim_sys_pros = self._cim_sys_pros()
- if self.fallback_mode:
- cim_syss = self._get_cim_syss_fallback(property_list=cim_sys_pros)
- else:
- cim_syss = self._get_cim_syss(
- Smis.SNIA_BLK_ROOT_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False,
- property_list=cim_sys_pros,
- raise_error=True)
-
- if cim_syss is None:
- return []
+ cim_syss = self._root_cim_syss(cim_sys_pros)
+
return [Smis._cim_sys_2_lsm_sys(s) for s in cim_syss]

def _new_init(self, cim_st_hwid):
@@ -2246,33 +2247,31 @@ class Smis(IStorageAreaNetwork):
rc = []
cim_syss = []
cim_sys_pros = self._property_list_of_id("System")
- if self.fallback_mode:
- cim_syss = self._get_cim_syss_fallback(property_list=cim_sys_pros)
- else:
- cim_syss = self._get_cim_syss(
- Smis.SNIA_DISK_LITE_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False,
- property_list=cim_sys_pros,
- raise_error=True)
-
+ if not fallback_mode:
+ self._profile_is_supported(SNIA.DISK_LITE_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4,
+ strict=False,
+ raise_error=True)
+
+ # In SNIA SMI-S 1.6rev4 Common Book,
+ # 30.1.5 Associations between ComputerSystems and other Logical
+ # Elements
+ # "If the device may become unavailable while the system as a
+ # whole remains available, the device shall be associated to a
+ # non-top-level system that has availability equivalent to the
+ # device. This system could be a real system or a system in an
+ # intermediate tier (representing some redundancy less than full
+ # redundancy)."
+
+ # Hence DiskDrive might not associated to top level
+ # CIM_ComputerSystem
flag_multi_sys = None
- if not self.fallback_mode:
- flag_multi_sys = self._profile_is_supported(
- Smis.SNIA_MULTI_SYS_PROFILE, Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False)
- # In SNIA SMI-S 1.6rev4 Common Book,
- # 30.1.5 Associations between ComputerSystems and other Logical
- # Elements
- # "If the device may become unavailable while the system as a
- # whole remains available, the device shall be associated to a
- # non-top-level system that has availability equivalent to the
- # device. This system could be a real system or a system in an
- # intermediate tier (representing some redundancy less than full
- # redundancy)."
-
- # Hence DiskDrive might not associated to top level
- # CIM_ComputerSystem
+ if not self.fallback_mode and \
+ self._profile_is_supported(SNIA.MULTI_SYS_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4,
+ strict=False,
+ raise_error=False):
+ flag_multi_sys = True

for cim_sys in cim_syss:
cim_disk_pros = Smis._new_disk_cim_disk_pros(flags)
@@ -3008,15 +3007,15 @@ class Smis(IStorageAreaNetwork):
"""
cim_sys_pros = self._property_list_of_id("System")
if not self.fallback_mode and \
- self._profile_is_supported(Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
+ self._profile_is_supported(SNIA.BLK_SRVS_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4,
strict=False) is None:
raise LsmError(ErrorNumber.NO_SUPPORT,
"SMI-S %s version %s is not supported" %
- (Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4))
+ (SNIA.BLK_SRVS_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4))

- cim_sys = self._get_cim_sys_by_id(pool.system_id)
+ cim_sys = self._cim_sys_of_id(pool.system_id)
cim_pool = self._get_cim_pool_by_id(cim_sys.path, pool.id)
cim_scs = self._get_cim_scs(cim_sys.path)

@@ -3039,15 +3038,15 @@ class Smis(IStorageAreaNetwork):
CreateOrModifyStoragePool()
"""
if not self.fallback_mode and \
- self._profile_is_supported(Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
+ self._profile_is_supported(SNIA.BLK_SRVS_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4,
strict=False) is None:
raise LsmError(ErrorNumber.NO_SUPPORT,
"SMI-S %s version %s is not supported" %
- (Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4))
+ (SNIA.BLK_SRVS_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4))

- cim_sys = self._get_cim_sys_by_id(system.id)
+ cim_sys = self._cim_sys_of_id(system.id)

# we does not support defining thinp_type yet.
# just using whatever provider set.
@@ -3371,238 +3370,142 @@ class Smis(IStorageAreaNetwork):
"CIM_StorageConfigurationService of " +
"CIM_ComputerSystem %s" % cim_sys_path)

- def _profile_is_supported(self, profile_name, spec_ver, strict=False):
+ def _profile_is_supported(self, profile_name, spec_ver, strict=False,
+ raise_error=False):
"""
Usage:
Check whether we support certain profile at certain SNIA
specification version.
- When strict == False(default), profile spec version newer than
- require spec_ver will also be consider as found.
+ When strict == False(default), profile spec version later or equal
+ than require spec_ver will also be consider as found.
When strict == True, only defined spec_version is allowed.
+ Require self.cim_rps containing all CIM_RegisteredProfile
+ Will raise LsmError(ErrorNumber.NO_SUPPORT, 'xxx') if raise_error
+ is True when nothing found.
Parameter:
- profile_name # Smis.SNIA_REGISTERED_PROFILE_XXX
- spec_ver # Smis.SNIA_SMIS_SPEC_VER_XXX
- property_list # a list of properties should contained in
- # returned CIM_ComputerSystem
- # When property_list == None, we retrieve full
- # data, when property_list == [], we retrieve
- # nothing but a CIMInstanceName.
+ profile_name # SNIA.XXXX_PROFILE
+ spec_ver # SNIA.SMIS_SPEC_VER_XXX
strict # False or True. If True, only defined
# spec_version is consider as supported
# If false, will return the maximum version of
# spec.
+ raise_error # Raise LsmError if not found
Returns:
None # Not supported.
or
- spec_version # the vendor implemented version. like '1.4.1'
- # This is a string, NOT float.
- """
- max_spec_ver = 0
- max_spec_ver_flt = 0
- # assuming spec_ver is well formatted, since we are internal
- # method, we can do that guess.
- req_ver_main = spec_ver.split('.')[0]
- req_ver_sub = spec_ver.split('.')[1]
-
- for cim_reg_profile in self.cim_reg_profiles:
- if 'RegisteredName' not in cim_reg_profile or \
- 'RegisteredVersion' not in cim_reg_profile:
+ spec_int # Integer. Converted by _spec_ver_str_to_num()
+ """
+ req_ver = _spec_ver_str_to_num(spec_ver)
+
+ max_spec_ver_str = None
+ max_spec_ver = None
+ for cim_rp in self.cim_rps:
+ if 'RegisteredName' not in cim_rp or \
+ 'RegisteredVersion' not in cim_rp:
continue
- if cim_reg_profile['RegisteredName'] == profile_name:
+ if cim_rp['RegisteredName'] == profile_name:
# check spec version
- cur_ver = cim_reg_profile['RegisteredVersion']
- cur_ver_list = cur_ver.split('.')
- if len(cur_ver_list) < 2:
- continue
- cur_ver_flt = float("%s.%s" % tuple(cur_ver_list[0:2]))
- req_ver_flt = float("%s.%s" % (req_ver_main, req_ver_sub))
+ cur_ver = _spec_ver_str_to_num(cim_rp['RegisteredVersion'])

- if strict and cur_ver_flt == req_ver_flt:
+ if strict and cur_ver == req_ver:
return cur_ver
-
- if strict is False and cur_ver_flt >= req_ver_flt:
- if cur_ver_flt > max_spec_ver_flt:
+ elif cur_ver >= req_ver:
+ if max_spec_ver is None or \
+ cur_ver > max_spec_ver:
max_spec_ver = cur_ver
- max_spec_ver_flt = cur_ver_flt
+ max_spec_ver_str = cim_rp['RegisteredVersion']
+ if strict or max_spec_ver is None:
+ raise LsmError(ErrorNumber.NO_SUPPORT,
+ "SNIA SMI-S %s '%s' profile is not supported" %
+ (spec_ver, profile_name))

- if max_spec_ver == 0:
- return None
return max_spec_ver

- def _get_cim_syss(self, profile_name, spec_ver, property_list=None,
- strict=False, sys_id=None, raise_error=False):
+ def _root_cim_syss(self, property_list=None):
"""
- Usage:
- Check whether we support certain profile at certain SNIA
- specification version.
- When strict == False(default), profile spec version newer than
- require spec_ver will also be consider as found.
- When strict == True, only defined spec_version is allowed.
+ For fallback mode, this just enumerate CIM_ComputerSystem.
+ We require vendor to implement profile registration when using
+ "Multiple System Profile".
+ For normal mode, this just find out the root CIM_ComputerSystem
+ via:

- If found, follow this procedure to get CIM_ComputerSystem:
CIM_RegisteredProfile # Root Profile('Array') in interop
|
| CIM_ElementConformsToProfile
v
CIM_ComputerSystem # vendor namespace

- We depend on self.cim_reg_profiles which was updated by startup().
- But this method does not check it, you should check
- self.fallback_mode == True before call this method.
-
- Please use constant spec_ver and profile_name for better
- code management.
- We also apply to system filter in URI which is stored in
- self.system_list
- When returning None, it means current provider does not support
- requested profile or version.
- Parameter:
- profile_name # Smis.SNIA_REGISTERED_PROFILE_XXX
- spec_ver # Smis.SNIA_SMIS_SPEC_VER_XXX
- property_list # a list of properties should contained in
- # returned CIM_ComputerSystem
- # When property_list == None, we retrieve full
- # data, when property_list == [], we retrieve
- # nothing but a CIMInstanceName.
- strict # False or True. If True, only defined
- # spec_version is consider as supported
- sys_id # Only return CIM_ComputerSystem for certain
- # system ID.
- Returns:
- cim_syss # a list of CIMInstanceName of CIM_ComputerSystem
- or
- None # Current SMI-S provider does not support this
- # profile at certain version.
- """
- max_spec_ver = self._profile_is_supported(
- profile_name, spec_ver, strict)
-
- if max_spec_ver is None:
- if raise_error:
- error_msg = ("Current SMI-S provider does not support "
- "SMI-S %s profile, version %s" %
- (profile_name, spec_ver))
- if not strict:
- error_msg = "%s(or later version)" % error_msg
- raise LsmError(ErrorNumber.NO_SUPPORT, error_msg)
- else:
- return None
-
- if max_spec_ver not in self.cim_root_profile_dict.keys():
- raise LsmError(ErrorNumber.INTERNAL_ERROR,
- "Failed to find out CIM_RegisteredProfile " +
- "for profile %s with version %s " %
- (Smis.SNIA_BLK_ROOT_PROFILE, max_spec_ver) +
- "even its subprofile found.")
-
- cim_root_profile = self.cim_root_profile_dict[max_spec_ver]
-
- if property_list is None:
- cim_syss = self._c.Associators(
- cim_root_profile.path,
- ResultClass='CIM_ComputerSystem',
- AssocClass='CIM_ElementConformsToProfile')
- else:
- sys_id_pros = self._property_list_of_id('System')
- for key in sys_id_pros:
- if key not in property_list:
- property_list.extend([key])
- cim_syss = self._c.Associators(
- cim_root_profile.path,
- ResultClass='CIM_ComputerSystem',
- AssocClass='CIM_ElementConformsToProfile',
- PropertyList=property_list)
-
- if self.system_list is None:
- return cim_syss
-
- # Method level filter
- if sys_id is not None:
- return [s for s in cim_syss if self._sys_id(s) == sys_id][0]
-
- # Apply URI system filter
- needed_cim_syss = []
- for cim_sys in cim_syss:
- if self._sys_id(cim_sys) in self.system_list:
- needed_cim_syss.extend([cim_sys])
- return needed_cim_syss
-
- def _get_cim_syss_fallback(self, sys_id=None, property_list=None):
+ We also assume no matter which version of root profile can lead to
+ the same CIM_ComputerSystem instance.
+ As CIM_ComputerSystem has no property indicate SNIA SMI-S version,
+ this is assumption should work. Tested on EMC SMI-S provider which
+ provide 1.4, 1.5, 1.6 root profile.
"""
- Usage:
- Find out the root CIM_ComputerSystem using the fallback method:
- CIM_StorageConfigurationService # Enumerate
- |
- | CIM_HostedService
- v
- CIM_ComputerSystem
- If CIM_StorageConfigurationService is not support neither,
- we enumerate CIM_ComputerSystem.
- Parameter:
- property_list # a list of properties should contained in
- # returned CIM_ComputerSystem
- # When property_list == None, we retrieve full
- # data, when property_list == [], we retrieve
- # nothing but a CIMInstanceName.
- Returns:
- cim_syss # A list of CIMInstanceName of CIM_ComputerSystem
- or
- None
- """
- sys_id_pros = self._property_list_of_id('System')
- flag_full_info = False
+ cim_sys_id_pros = self._property_list_of_id('System')
if property_list is None:
- flag_full_info = True
+ property_list = cim_sys_id_pros
else:
- for key in sys_id_pros:
- if key not in property_list:
- property_list.extend([key])
+ for key_name in cim_sys_id_pros:
+ if key_name not in property_list:
+ property_list.extend([key_name])

cim_syss = []
- cim_scss_path = []
- try:
- # Note: Please be informed, if PropertyList is an empty list,
- # XIV will return NOTHING, so use EnumerateInstanceNames()
- # when you need nothing but the CIMInstanceName
- cim_scss_path = self._c.EnumerateInstanceNames(
- 'CIM_StorageConfigurationService')
- except CIMError as e:
- # If array does not support CIM_StorageConfigurationService
- # we use CIM_ComputerSystem which is mandatory.
- # We might get some non-storage array listed as system.
- # but we would like to take that risk instead of
- # skipping basic support of old SMIS provider.
- if e[0] == pywbem.CIM_ERR_INVALID_CLASS:
- if flag_full_info:
- cim_syss = self._c.EnumerateInstances(
- 'CIM_ComputerSystem', LocalOnly=False)
- else:
- cim_syss = self._c.EnumerateInstances(
- 'CIM_ComputerSystem',
- PropertyList=property_list,
- LocalOnly=False)
- else:
- raise e
- if not cim_syss:
- for cim_scs_path in cim_scss_path:
- cim_tmp = None
- if flag_full_info:
- cim_tmp = self._c.Associators(
- cim_scs_path,
- AssocClass='CIM_HostedService',
- ResultClass='CIM_ComputerSystem')
+ if self.fallback_mode:
+ # Fallback mode:
+ # Find out the root CIM_ComputerSystem using the fallback method:
+ # CIM_StorageConfigurationService # Enumerate
+ # |
+ # | CIM_HostedService
+ # v
+ # CIM_ComputerSystem
+ # If CIM_StorageConfigurationService is not support neither,
+ # we enumerate CIM_ComputerSystem.
+ try:
+ cim_scss_path = self._c.EnumerateInstanceNames(
+ 'CIM_StorageConfigurationService')
+ except CIMError as e:
+ # If array does not support CIM_StorageConfigurationService
+ # we use CIM_ComputerSystem which is mandatory.
+ # We might get some non-storage array listed as system.
+ # but we would like to take that risk instead of
+ # skipping basic support of old SMIS provider.
+ if e[0] == pywbem.CIM_ERR_INVALID_CLASS:
+ cim_syss = self._c.EnumerateInstances(
+ 'CIM_ComputerSystem',
+ PropertyList=property_list,
+ LocalOnly=False)
else:
+ raise e
+
+ if not cim_syss:
+ for cim_scs_path in cim_scss_path:
+ cim_tmp = None
+ # CIM_ComputerSystem is one-one map to
+ # CIM_StorageConfigurationService
cim_tmp = self._c.Associators(
cim_scs_path,
AssocClass='CIM_HostedService',
ResultClass='CIM_ComputerSystem',
PropertyList=property_list)
- if cim_tmp and cim_tmp[0]:
- cim_syss.extend([cim_tmp[0]])
-
- # Method level filter
- if sys_id is not None:
- return [s for s in cim_syss if self._sys_id(s) == sys_id]
+ if cim_tmp and cim_tmp[0]:
+ cim_syss.extend([cim_tmp[0]])
+ else:
+ for cim_rp in self.cim_rps:
+ if cim_rp['RegisteredName'] == SNIA.BLK_ROOT_PROFILE and\
+ cim_rp['RegisteredOrganization'] == SNIA.REG_ORG_CODE:
+ cim_syss = self._c.Associators(
+ cim_rp.path,
+ ResultClass='CIM_ComputerSystem',
+ AssocClass='CIM_ElementConformsToProfile',
+ PropertyList=property_list)
+ # Any version of 'Array' profile can get us to root
+ # CIM_ComputerSystem. startup() already has checked the
+ # 1.4 version
+ break
+ if cim_syss is None:
+ raise LsmError(ErrorNumber.NO_SUPPORT,
+ "SMI-S provider is not supporting SNIA SMI-S "
+ "Array profile")

# System URI Filtering
if self.system_list:
@@ -3614,7 +3517,8 @@ class Smis(IStorageAreaNetwork):
else:
return cim_syss

- def _get_cim_sys_by_id(self, system_id, property_list=None):
+
+ def _cim_sys_of_id(self, system_id, property_list=None):
"""
Return a CIMInstance of CIM_ComputerSystem for given system id.
"""
@@ -3626,15 +3530,8 @@ class Smis(IStorageAreaNetwork):
if pro not in property_list:
property_list.extend([pro])

- if self.fallback_mode:
- cim_syss = self._get_cim_syss_fallback(property_list)
- else:
- cim_syss = self._get_cim_syss(
- Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False,
- property_list=property_list,
- raise_error=True)
+ cim_syss = self._root_cim_syss(property_list)
+
for cim_sys in cim_syss:
if self._sys_id(cim_sys) == system_id:
return cim_sys
--
1.8.3.1
Gris Ge
2014-05-21 07:40:11 UTC
Permalink
* Convert SMI-S SPEC version into integer for better comparison.
Please check _spec_ver_str_to_num() for detail.
* Let _root_cim_syss() handle the fall back checking. It will return a list
of CIM_ComputerSystem for fallback mode or not.
* Checking for 1.4 'Array' profile support in startup().
As 'Block Services Package' (AKA: BSP) is mandatory for that profile, we
don't do extra check in methods using BSP profile.
* Noting down the method naming scheme for consistency.
* Move SNIA related constants to a standalone class SNIA which shorter the
constant variable name.
* _profile_is_supported() now support raise error if not found.
* Split _cim_sys_of_id() out to raise LsmError ErrorNumber.NOT_FOUND_SYSTEM.
* Add RegisteredOrganization checking in CIM_RegisteredProfile.

Changes since V2:
* In case fallmode facing 'multiple system' profile supported array,
the _root_cim_syss() will use the old way to get top ComputerSystem:
CIM_StorageConfigurationService -> ComputerSystem
* Add author names.

Changes since V3:
* Removed un-needed check. The startup() already checked the support of
'Array' profile.

Signed-off-by: Gris Ge <***@redhat.com>
---
plugin/smispy/smis.py | 527 ++++++++++++++++++++------------------------------
1 file changed, 210 insertions(+), 317 deletions(-)

diff --git a/plugin/smispy/smis.py b/plugin/smispy/smis.py
index c63d8cd..952eeb6 100644
--- a/plugin/smispy/smis.py
+++ b/plugin/smispy/smis.py
@@ -13,6 +13,9 @@
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
# USA
+#
+# Author: tasleson
+# Gris Ge <***@redhat.com>

from string import split
import time
@@ -32,11 +35,22 @@ from lsm import (IStorageAreaNetwork, Error, uri_parse, LsmError, ErrorNumber,
# cim_pool CIM_StoragePool
# cim_scs CIM_StorageConfigurationService
# cim_vol CIM_StorageVolume
+# cim_rp CIM_RegisteredProfile
#
# sys Object of LSM System
# pool Object of LSM Pool
# vol Object of LSM Volume

+## Method Naming schme:
+# _cim_xxx()
+# Return CIMInstance without any Associators() call.
+# _cim_xxx_of(cim_yyy)
+# Return CIMInstance associated to cim_yyy
+# _adj_cim_xxx()
+# Retrun CIMInstance with 'adj' only
+# _cim_xxx_of_id(some_id)
+# Return CIMInstance for given ID
+

def handle_cim_errors(method):
def cim_wrapper(*args, **kwargs):
@@ -65,6 +79,32 @@ def handle_cim_errors(method):
traceback.format_exc())
return cim_wrapper

+def _spec_ver_str_to_num(spec_ver_str):
+ """
+ Convert version string stored in CIM_RegisteredProfile to a integer.
+ Example:
+ "1.5.1" -> 1,005,001
+ """
+ tmp_list = [0,0,0]
+ tmp_list = spec_ver_str.split(".")
+ if len(tmp_list) == 2:
+ tmp_list.extend([0])
+ if len(tmp_list) == 3:
+ return (int(tmp_list[0]) * 10 ** 6 +
+ int(tmp_list[1]) * 10 ** 3 +
+ int(tmp_list[2]))
+ return None
+
+class SNIA(object):
+ BLK_ROOT_PROFILE = 'Array'
+ BLK_SRVS_PROFILE = 'Block Services'
+ DISK_LITE_PROFILE = 'Disk Drive Lite'
+ MULTI_SYS_PROFILE = 'Multiple Computer System'
+ SMIS_SPEC_VER_1_4 ='1.4'
+ SMIS_SPEC_VER_1_5 ='1.5'
+ SMIS_SPEC_VER_1_6 ='1.6'
+ REG_ORG_CODE = pywbem.Uint16(11)
+

class Smis(IStorageAreaNetwork):
"""
@@ -252,13 +292,6 @@ class Smis(IStorageAreaNetwork):
# DSP 1033 Profile Registration
DMTF_INTEROP_NAMESPACES = ['interop', 'root/interop']
SMIS_DEFAULT_NAMESPACE = 'interop'
- SNIA_BLK_ROOT_PROFILE = 'Array'
- SNIA_BLK_SRVS_PROFILE = 'Block Services'
- SNIA_DISK_LITE_PROFILE = 'Disk Drive Lite'
- SNIA_MULTI_SYS_PROFILE = 'Multiple Computer System'
- SNIA_SMIS_SPEC_VER_1_4='1.4'
- SNIA_SMIS_SPEC_VER_1_5='1.5'
- SNIA_SMIS_SPEC_VER_1_6='1.6'

IAAN_WBEM_HTTP_PORT = 5988
IAAN_WBEM_HTTPS_PORT = 5989
@@ -350,7 +383,7 @@ class Smis(IStorageAreaNetwork):
self._c = None
self.tmo = 0
self.system_list = None
- self.cim_reg_profiles = []
+ self.cim_rps = []
self.cim_root_profile_dict = dict()
self.fallback_mode = True # Means we cannot use profile register

@@ -555,31 +588,29 @@ class Smis(IStorageAreaNetwork):

try:
for interop_namespace in Smis.DMTF_INTEROP_NAMESPACES:
- self.cim_reg_profiles = self._c.EnumerateInstances(
+ self.cim_rps = self._c.EnumerateInstances(
'CIM_RegisteredProfile',
namespace=interop_namespace,
- PropertyList=['RegisteredName', 'RegisteredVersion'],
+ PropertyList=['RegisteredName', 'RegisteredVersion',
+ 'RegisteredOrganization'],
LocalOnly=False)
- if len(self.cim_reg_profiles) != 0:
+ if len(self.cim_rps) != 0:
break

- if len(self.cim_reg_profiles) >= 1:
+ if len(self.cim_rps) >= 1:
self.fallback_mode = False
# Support 'Array' profile is step 0 for this whole plugin.
# We find out all 'Array' CIM_RegisteredProfile and stored
# them into self.cim_root_profile_dict
- for cim_reg_profile in self.cim_reg_profiles:
- if 'RegisteredName' not in cim_reg_profile or \
- 'RegisteredVersion' not in cim_reg_profile:
- continue
- if cim_reg_profile['RegisteredName'] == \
- Smis.SNIA_BLK_ROOT_PROFILE:
- ver = cim_reg_profile['RegisteredVersion']
- self.cim_root_profile_dict[ver]= cim_reg_profile
- if len(self.cim_root_profile_dict) == 0:
+ if not self._profile_is_supported(
+ SNIA.BLK_ROOT_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4,
+ strict=False):
raise LsmError(ErrorNumber.NO_SUPPORT,
- "SMI-S provider does not support 'Array'"
- "profile which is prerequisite")
+ "SMI-S provider does not support "
+ "SNIA SMI-S SPEC %s '%s' profile" %
+ (SNIA.SMIS_SPEC_VER_1_4,
+ SNIA.BLK_ROOT_PROFILE))
except CIMError as e:
if e[0] == pywbem.CIM_ERR_NOT_SUPPORTED or \
e[0] == pywbem.CIM_ERR_INVALID_NAMESPACE:
@@ -720,12 +751,8 @@ class Smis(IStorageAreaNetwork):
# Get the cim object that represents the system
cim_sys = None
cim_pcms = None
+ cim_sys = self._cim_sys_of_id(system.id)
if self.fallback_mode:
- cim_sys = self._get_cim_syss_fallback(
- sys_id=system.id,
- property_list=[])[0] # Surely, we will get at least one
- # cim_sys since LSM system already
- # provided.

# Using 'ExposePathsSupported of
# CIM_ProtocolControllerMaskingCapabilities
@@ -752,26 +779,16 @@ class Smis(IStorageAreaNetwork):
cap.set(Capabilities.ACCESS_GROUP_DEL_INITIATOR)
return
else:
- cim_syss = self._get_cim_syss(
- Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- sys_id=system.id,
- property_list=[])
- # we might not get any cim_sys on unsupported system.
- if len(cim_syss) == 1:
- cim_sys = cim_syss[0]
- # Since SNIA SMI-S 1.4rev6:
- # CIM_ControllerConfigurationService is mandatory
- # and it's ExposePaths() and HidePaths() are mandatory
- cap.set(Capabilities.ACCESS_GROUP_LIST)
- cap.set(Capabilities.ACCESS_GROUP_GRANT)
- cap.set(Capabilities.ACCESS_GROUP_REVOKE)
- cap.set(Capabilities.ACCESS_GROUP_ADD_INITIATOR)
- cap.set(Capabilities.ACCESS_GROUP_DEL_INITIATOR)
- cap.set(Capabilities.ACCESS_GROUPS_GRANTED_TO_VOLUME)
- cap.set(Capabilities.VOLUMES_ACCESSIBLE_BY_ACCESS_GROUP)
- else:
- return
+ # Since SNIA SMI-S 1.4rev6:
+ # CIM_ControllerConfigurationService is mandatory
+ # and it's ExposePaths() and HidePaths() are mandatory
+ cap.set(Capabilities.ACCESS_GROUP_LIST)
+ cap.set(Capabilities.ACCESS_GROUP_GRANT)
+ cap.set(Capabilities.ACCESS_GROUP_REVOKE)
+ cap.set(Capabilities.ACCESS_GROUP_ADD_INITIATOR)
+ cap.set(Capabilities.ACCESS_GROUP_DEL_INITIATOR)
+ cap.set(Capabilities.ACCESS_GROUPS_GRANTED_TO_VOLUME)
+ cap.set(Capabilities.VOLUMES_ACCESSIBLE_BY_ACCESS_GROUP)

def _common_capabilities(self, system):
cap = Capabilities()
@@ -1283,19 +1300,15 @@ class Smis(IStorageAreaNetwork):
|
v
CIM_StorageVolume
+ As 'Block Services Package' is mandatory for 'Array' profile, we
+ don't check support status here as startup() already checked 'Array'
+ profile.
"""
rc = []
cim_syss = []
cim_sys_pros = self._property_list_of_id("System")
- if self.fallback_mode:
- cim_syss = self._get_cim_syss_fallback(property_list=cim_sys_pros)
- else:
- cim_syss = self._get_cim_syss(
- Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False,
- property_list=cim_sys_pros,
- raise_error=True)
+
+ cim_syss = self._root_cim_syss(cim_sys_pros)
cim_vol_pros = self._new_vol_cim_vol_pros()
for cim_sys in cim_syss:
sys_id = self._sys_id(cim_sys)
@@ -1405,22 +1418,16 @@ class Smis(IStorageAreaNetwork):
|
v
CIM_StoragePool
+ As 'Block Services Package' is mandatory for 'Array' profile, we
+ don't check support status here as startup() already checked 'Array'
+ profile.
"""
rc = []
cim_pool_pros = self._new_pool_cim_pool_pros(
flags == Pool.RETRIEVE_FULL_INFO)

cim_sys_pros = self._property_list_of_id("System")
- cim_syss = []
- if self.fallback_mode:
- cim_syss = self._get_cim_syss_fallback(property_list=cim_sys_pros)
- else:
- cim_syss = self._get_cim_syss(
- Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False,
- property_list=cim_sys_pros,
- raise_error=True)
+ cim_syss = self._root_cim_syss(cim_sys_pros)

for cim_sys in cim_syss:
system_id = self._sys_id(cim_sys)
@@ -1535,20 +1542,14 @@ class Smis(IStorageAreaNetwork):
def systems(self, flags=0):
"""
Return the storage arrays accessible from this plug-in at this time
+
+ As 'Block Services Package' is mandatory for 'Array' profile, we
+ don't check support status here as startup() already checked 'Array'
+ profile.
"""
cim_sys_pros = self._cim_sys_pros()
- if self.fallback_mode:
- cim_syss = self._get_cim_syss_fallback(property_list=cim_sys_pros)
- else:
- cim_syss = self._get_cim_syss(
- Smis.SNIA_BLK_ROOT_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False,
- property_list=cim_sys_pros,
- raise_error=True)
-
- if cim_syss is None:
- return []
+ cim_syss = self._root_cim_syss(cim_sys_pros)
+
return [Smis._cim_sys_2_lsm_sys(s) for s in cim_syss]

def _new_init(self, cim_st_hwid):
@@ -2246,33 +2247,31 @@ class Smis(IStorageAreaNetwork):
rc = []
cim_syss = []
cim_sys_pros = self._property_list_of_id("System")
- if self.fallback_mode:
- cim_syss = self._get_cim_syss_fallback(property_list=cim_sys_pros)
- else:
- cim_syss = self._get_cim_syss(
- Smis.SNIA_DISK_LITE_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False,
- property_list=cim_sys_pros,
- raise_error=True)
-
+ if not fallback_mode:
+ self._profile_is_supported(SNIA.DISK_LITE_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4,
+ strict=False,
+ raise_error=True)
+
+ # In SNIA SMI-S 1.6rev4 Common Book,
+ # 30.1.5 Associations between ComputerSystems and other Logical
+ # Elements
+ # "If the device may become unavailable while the system as a
+ # whole remains available, the device shall be associated to a
+ # non-top-level system that has availability equivalent to the
+ # device. This system could be a real system or a system in an
+ # intermediate tier (representing some redundancy less than full
+ # redundancy)."
+
+ # Hence DiskDrive might not associated to top level
+ # CIM_ComputerSystem
flag_multi_sys = None
- if not self.fallback_mode:
- flag_multi_sys = self._profile_is_supported(
- Smis.SNIA_MULTI_SYS_PROFILE, Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False)
- # In SNIA SMI-S 1.6rev4 Common Book,
- # 30.1.5 Associations between ComputerSystems and other Logical
- # Elements
- # "If the device may become unavailable while the system as a
- # whole remains available, the device shall be associated to a
- # non-top-level system that has availability equivalent to the
- # device. This system could be a real system or a system in an
- # intermediate tier (representing some redundancy less than full
- # redundancy)."
-
- # Hence DiskDrive might not associated to top level
- # CIM_ComputerSystem
+ if not self.fallback_mode and \
+ self._profile_is_supported(SNIA.MULTI_SYS_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4,
+ strict=False,
+ raise_error=False):
+ flag_multi_sys = True

for cim_sys in cim_syss:
cim_disk_pros = Smis._new_disk_cim_disk_pros(flags)
@@ -3008,15 +3007,15 @@ class Smis(IStorageAreaNetwork):
"""
cim_sys_pros = self._property_list_of_id("System")
if not self.fallback_mode and \
- self._profile_is_supported(Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
+ self._profile_is_supported(SNIA.BLK_SRVS_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4,
strict=False) is None:
raise LsmError(ErrorNumber.NO_SUPPORT,
"SMI-S %s version %s is not supported" %
- (Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4))
+ (SNIA.BLK_SRVS_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4))

- cim_sys = self._get_cim_sys_by_id(pool.system_id)
+ cim_sys = self._cim_sys_of_id(pool.system_id)
cim_pool = self._get_cim_pool_by_id(cim_sys.path, pool.id)
cim_scs = self._get_cim_scs(cim_sys.path)

@@ -3039,15 +3038,15 @@ class Smis(IStorageAreaNetwork):
CreateOrModifyStoragePool()
"""
if not self.fallback_mode and \
- self._profile_is_supported(Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
+ self._profile_is_supported(SNIA.BLK_SRVS_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4,
strict=False) is None:
raise LsmError(ErrorNumber.NO_SUPPORT,
"SMI-S %s version %s is not supported" %
- (Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4))
+ (SNIA.BLK_SRVS_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4))

- cim_sys = self._get_cim_sys_by_id(system.id)
+ cim_sys = self._cim_sys_of_id(system.id)

# we does not support defining thinp_type yet.
# just using whatever provider set.
@@ -3371,238 +3370,138 @@ class Smis(IStorageAreaNetwork):
"CIM_StorageConfigurationService of " +
"CIM_ComputerSystem %s" % cim_sys_path)

- def _profile_is_supported(self, profile_name, spec_ver, strict=False):
+ def _profile_is_supported(self, profile_name, spec_ver, strict=False,
+ raise_error=False):
"""
Usage:
Check whether we support certain profile at certain SNIA
specification version.
- When strict == False(default), profile spec version newer than
- require spec_ver will also be consider as found.
+ When strict == False(default), profile spec version later or equal
+ than require spec_ver will also be consider as found.
When strict == True, only defined spec_version is allowed.
+ Require self.cim_rps containing all CIM_RegisteredProfile
+ Will raise LsmError(ErrorNumber.NO_SUPPORT, 'xxx') if raise_error
+ is True when nothing found.
Parameter:
- profile_name # Smis.SNIA_REGISTERED_PROFILE_XXX
- spec_ver # Smis.SNIA_SMIS_SPEC_VER_XXX
- property_list # a list of properties should contained in
- # returned CIM_ComputerSystem
- # When property_list == None, we retrieve full
- # data, when property_list == [], we retrieve
- # nothing but a CIMInstanceName.
+ profile_name # SNIA.XXXX_PROFILE
+ spec_ver # SNIA.SMIS_SPEC_VER_XXX
strict # False or True. If True, only defined
# spec_version is consider as supported
# If false, will return the maximum version of
# spec.
+ raise_error # Raise LsmError if not found
Returns:
None # Not supported.
or
- spec_version # the vendor implemented version. like '1.4.1'
- # This is a string, NOT float.
- """
- max_spec_ver = 0
- max_spec_ver_flt = 0
- # assuming spec_ver is well formatted, since we are internal
- # method, we can do that guess.
- req_ver_main = spec_ver.split('.')[0]
- req_ver_sub = spec_ver.split('.')[1]
-
- for cim_reg_profile in self.cim_reg_profiles:
- if 'RegisteredName' not in cim_reg_profile or \
- 'RegisteredVersion' not in cim_reg_profile:
+ spec_int # Integer. Converted by _spec_ver_str_to_num()
+ """
+ req_ver = _spec_ver_str_to_num(spec_ver)
+
+ max_spec_ver_str = None
+ max_spec_ver = None
+ for cim_rp in self.cim_rps:
+ if 'RegisteredName' not in cim_rp or \
+ 'RegisteredVersion' not in cim_rp:
continue
- if cim_reg_profile['RegisteredName'] == profile_name:
+ if cim_rp['RegisteredName'] == profile_name:
# check spec version
- cur_ver = cim_reg_profile['RegisteredVersion']
- cur_ver_list = cur_ver.split('.')
- if len(cur_ver_list) < 2:
- continue
- cur_ver_flt = float("%s.%s" % tuple(cur_ver_list[0:2]))
- req_ver_flt = float("%s.%s" % (req_ver_main, req_ver_sub))
+ cur_ver = _spec_ver_str_to_num(cim_rp['RegisteredVersion'])

- if strict and cur_ver_flt == req_ver_flt:
+ if strict and cur_ver == req_ver:
return cur_ver
-
- if strict is False and cur_ver_flt >= req_ver_flt:
- if cur_ver_flt > max_spec_ver_flt:
+ elif cur_ver >= req_ver:
+ if max_spec_ver is None or \
+ cur_ver > max_spec_ver:
max_spec_ver = cur_ver
- max_spec_ver_flt = cur_ver_flt
+ max_spec_ver_str = cim_rp['RegisteredVersion']
+ if strict or max_spec_ver is None:
+ raise LsmError(ErrorNumber.NO_SUPPORT,
+ "SNIA SMI-S %s '%s' profile is not supported" %
+ (spec_ver, profile_name))

- if max_spec_ver == 0:
- return None
return max_spec_ver

- def _get_cim_syss(self, profile_name, spec_ver, property_list=None,
- strict=False, sys_id=None, raise_error=False):
+ def _root_cim_syss(self, property_list=None):
"""
- Usage:
- Check whether we support certain profile at certain SNIA
- specification version.
- When strict == False(default), profile spec version newer than
- require spec_ver will also be consider as found.
- When strict == True, only defined spec_version is allowed.
+ For fallback mode, this just enumerate CIM_ComputerSystem.
+ We require vendor to implement profile registration when using
+ "Multiple System Profile".
+ For normal mode, this just find out the root CIM_ComputerSystem
+ via:

- If found, follow this procedure to get CIM_ComputerSystem:
CIM_RegisteredProfile # Root Profile('Array') in interop
|
| CIM_ElementConformsToProfile
v
CIM_ComputerSystem # vendor namespace

- We depend on self.cim_reg_profiles which was updated by startup().
- But this method does not check it, you should check
- self.fallback_mode == True before call this method.
-
- Please use constant spec_ver and profile_name for better
- code management.
- We also apply to system filter in URI which is stored in
- self.system_list
- When returning None, it means current provider does not support
- requested profile or version.
- Parameter:
- profile_name # Smis.SNIA_REGISTERED_PROFILE_XXX
- spec_ver # Smis.SNIA_SMIS_SPEC_VER_XXX
- property_list # a list of properties should contained in
- # returned CIM_ComputerSystem
- # When property_list == None, we retrieve full
- # data, when property_list == [], we retrieve
- # nothing but a CIMInstanceName.
- strict # False or True. If True, only defined
- # spec_version is consider as supported
- sys_id # Only return CIM_ComputerSystem for certain
- # system ID.
- Returns:
- cim_syss # a list of CIMInstanceName of CIM_ComputerSystem
- or
- None # Current SMI-S provider does not support this
- # profile at certain version.
- """
- max_spec_ver = self._profile_is_supported(
- profile_name, spec_ver, strict)
-
- if max_spec_ver is None:
- if raise_error:
- error_msg = ("Current SMI-S provider does not support "
- "SMI-S %s profile, version %s" %
- (profile_name, spec_ver))
- if not strict:
- error_msg = "%s(or later version)" % error_msg
- raise LsmError(ErrorNumber.NO_SUPPORT, error_msg)
- else:
- return None
-
- if max_spec_ver not in self.cim_root_profile_dict.keys():
- raise LsmError(ErrorNumber.INTERNAL_ERROR,
- "Failed to find out CIM_RegisteredProfile " +
- "for profile %s with version %s " %
- (Smis.SNIA_BLK_ROOT_PROFILE, max_spec_ver) +
- "even its subprofile found.")
-
- cim_root_profile = self.cim_root_profile_dict[max_spec_ver]
-
- if property_list is None:
- cim_syss = self._c.Associators(
- cim_root_profile.path,
- ResultClass='CIM_ComputerSystem',
- AssocClass='CIM_ElementConformsToProfile')
- else:
- sys_id_pros = self._property_list_of_id('System')
- for key in sys_id_pros:
- if key not in property_list:
- property_list.extend([key])
- cim_syss = self._c.Associators(
- cim_root_profile.path,
- ResultClass='CIM_ComputerSystem',
- AssocClass='CIM_ElementConformsToProfile',
- PropertyList=property_list)
-
- if self.system_list is None:
- return cim_syss
-
- # Method level filter
- if sys_id is not None:
- return [s for s in cim_syss if self._sys_id(s) == sys_id][0]
-
- # Apply URI system filter
- needed_cim_syss = []
- for cim_sys in cim_syss:
- if self._sys_id(cim_sys) in self.system_list:
- needed_cim_syss.extend([cim_sys])
- return needed_cim_syss
-
- def _get_cim_syss_fallback(self, sys_id=None, property_list=None):
- """
- Usage:
- Find out the root CIM_ComputerSystem using the fallback method:
- CIM_StorageConfigurationService # Enumerate
- |
- | CIM_HostedService
- v
- CIM_ComputerSystem
- If CIM_StorageConfigurationService is not support neither,
- we enumerate CIM_ComputerSystem.
- Parameter:
- property_list # a list of properties should contained in
- # returned CIM_ComputerSystem
- # When property_list == None, we retrieve full
- # data, when property_list == [], we retrieve
- # nothing but a CIMInstanceName.
- Returns:
- cim_syss # A list of CIMInstanceName of CIM_ComputerSystem
- or
- None
+ We also assume no matter which version of root profile can lead to
+ the same CIM_ComputerSystem instance.
+ As CIM_ComputerSystem has no property indicate SNIA SMI-S version,
+ this is assumption should work. Tested on EMC SMI-S provider which
+ provide 1.4, 1.5, 1.6 root profile.
"""
- sys_id_pros = self._property_list_of_id('System')
- flag_full_info = False
+ cim_sys_id_pros = self._property_list_of_id('System')
if property_list is None:
- flag_full_info = True
+ property_list = cim_sys_id_pros
else:
- for key in sys_id_pros:
- if key not in property_list:
- property_list.extend([key])
+ for key_name in cim_sys_id_pros:
+ if key_name not in property_list:
+ property_list.extend([key_name])

cim_syss = []
- cim_scss_path = []
- try:
- # Note: Please be informed, if PropertyList is an empty list,
- # XIV will return NOTHING, so use EnumerateInstanceNames()
- # when you need nothing but the CIMInstanceName
- cim_scss_path = self._c.EnumerateInstanceNames(
- 'CIM_StorageConfigurationService')
- except CIMError as e:
- # If array does not support CIM_StorageConfigurationService
- # we use CIM_ComputerSystem which is mandatory.
- # We might get some non-storage array listed as system.
- # but we would like to take that risk instead of
- # skipping basic support of old SMIS provider.
- if e[0] == pywbem.CIM_ERR_INVALID_CLASS:
- if flag_full_info:
- cim_syss = self._c.EnumerateInstances(
- 'CIM_ComputerSystem', LocalOnly=False)
- else:
- cim_syss = self._c.EnumerateInstances(
- 'CIM_ComputerSystem',
- PropertyList=property_list,
- LocalOnly=False)
- else:
- raise e
- if not cim_syss:
- for cim_scs_path in cim_scss_path:
- cim_tmp = None
- if flag_full_info:
- cim_tmp = self._c.Associators(
- cim_scs_path,
- AssocClass='CIM_HostedService',
- ResultClass='CIM_ComputerSystem')
+ if self.fallback_mode:
+ # Fallback mode:
+ # Find out the root CIM_ComputerSystem using the fallback method:
+ # CIM_StorageConfigurationService # Enumerate
+ # |
+ # | CIM_HostedService
+ # v
+ # CIM_ComputerSystem
+ # If CIM_StorageConfigurationService is not support neither,
+ # we enumerate CIM_ComputerSystem.
+ try:
+ cim_scss_path = self._c.EnumerateInstanceNames(
+ 'CIM_StorageConfigurationService')
+ except CIMError as e:
+ # If array does not support CIM_StorageConfigurationService
+ # we use CIM_ComputerSystem which is mandatory.
+ # We might get some non-storage array listed as system.
+ # but we would like to take that risk instead of
+ # skipping basic support of old SMIS provider.
+ if e[0] == pywbem.CIM_ERR_INVALID_CLASS:
+ cim_syss = self._c.EnumerateInstances(
+ 'CIM_ComputerSystem',
+ PropertyList=property_list,
+ LocalOnly=False)
else:
+ raise e
+
+ if not cim_syss:
+ for cim_scs_path in cim_scss_path:
+ cim_tmp = None
+ # CIM_ComputerSystem is one-one map to
+ # CIM_StorageConfigurationService
cim_tmp = self._c.Associators(
cim_scs_path,
AssocClass='CIM_HostedService',
ResultClass='CIM_ComputerSystem',
PropertyList=property_list)
- if cim_tmp and cim_tmp[0]:
- cim_syss.extend([cim_tmp[0]])
-
- # Method level filter
- if sys_id is not None:
- return [s for s in cim_syss if self._sys_id(s) == sys_id]
+ if cim_tmp and cim_tmp[0]:
+ cim_syss.extend([cim_tmp[0]])
+ else:
+ for cim_rp in self.cim_rps:
+ if cim_rp['RegisteredName'] == SNIA.BLK_ROOT_PROFILE and\
+ cim_rp['RegisteredOrganization'] == SNIA.REG_ORG_CODE:
+ cim_syss = self._c.Associators(
+ cim_rp.path,
+ ResultClass='CIM_ComputerSystem',
+ AssocClass='CIM_ElementConformsToProfile',
+ PropertyList=property_list)
+ # Any version of 'Array' profile can get us to root
+ # CIM_ComputerSystem. startup() already has checked the
+ # 1.4 version
+ break

# System URI Filtering
if self.system_list:
@@ -3614,7 +3513,8 @@ class Smis(IStorageAreaNetwork):
else:
return cim_syss

- def _get_cim_sys_by_id(self, system_id, property_list=None):
+
+ def _cim_sys_of_id(self, system_id, property_list=None):
"""
Return a CIMInstance of CIM_ComputerSystem for given system id.
"""
@@ -3626,15 +3526,8 @@ class Smis(IStorageAreaNetwork):
if pro not in property_list:
property_list.extend([pro])

- if self.fallback_mode:
- cim_syss = self._get_cim_syss_fallback(property_list)
- else:
- cim_syss = self._get_cim_syss(
- Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False,
- property_list=property_list,
- raise_error=True)
+ cim_syss = self._root_cim_syss(property_list)
+
for cim_sys in cim_syss:
if self._sys_id(cim_sys) == system_id:
return cim_sys
--
1.8.3.1
Tony Asleson
2014-05-21 14:12:37 UTC
Permalink
Getting this exception in the unit test:

ERROR: test_disks_list (__main__.TestPlugin)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/testing/automated/81/libstoragemgmt-code/test/plugin_test.py",
line 289, in test_disks_list
disks = self.c.disks()
File "/testing/automated/81/libstoragemgmt-code/test/plugin_test.py",
line 183, in present
raise e
LsmError: PLUGIN_ERROR(303): global name 'fallback_mode' is not defined
Data: Traceback (most recent call last):
File
"/testing/automated/81/libstoragemgmt-code/python_binding/lsm/plugin/smispy/smis.py",
line 58, in cim_wrapper
return method(*args, **kwargs)
File
"/testing/automated/81/libstoragemgmt-code/python_binding/lsm/plugin/smispy/smis.py",
line 2250, in disks
if not fallback_mode:
NameError: global name 'fallback_mode' is not defined

Thanks,
Tony
Post by Gris Ge
* Convert SMI-S SPEC version into integer for better comparison.
Please check _spec_ver_str_to_num() for detail.
* Let _root_cim_syss() handle the fall back checking. It will return a list
of CIM_ComputerSystem for fallback mode or not.
* Checking for 1.4 'Array' profile support in startup().
As 'Block Services Package' (AKA: BSP) is mandatory for that profile, we
don't do extra check in methods using BSP profile.
* Noting down the method naming scheme for consistency.
* Move SNIA related constants to a standalone class SNIA which shorter the
constant variable name.
* _profile_is_supported() now support raise error if not found.
* Split _cim_sys_of_id() out to raise LsmError ErrorNumber.NOT_FOUND_SYSTEM.
* Add RegisteredOrganization checking in CIM_RegisteredProfile.
* In case fallmode facing 'multiple system' profile supported array,
CIM_StorageConfigurationService -> ComputerSystem
* Add author names.
* Removed un-needed check. The startup() already checked the support of
'Array' profile.
---
plugin/smispy/smis.py | 527 ++++++++++++++++++++------------------------------
1 file changed, 210 insertions(+), 317 deletions(-)
diff --git a/plugin/smispy/smis.py b/plugin/smispy/smis.py
index c63d8cd..952eeb6 100644
--- a/plugin/smispy/smis.py
+++ b/plugin/smispy/smis.py
@@ -13,6 +13,9 @@
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
# USA
+#
+# Author: tasleson
from string import split
import time
@@ -32,11 +35,22 @@ from lsm import (IStorageAreaNetwork, Error, uri_parse, LsmError, ErrorNumber,
# cim_pool CIM_StoragePool
# cim_scs CIM_StorageConfigurationService
# cim_vol CIM_StorageVolume
+# cim_rp CIM_RegisteredProfile
#
# sys Object of LSM System
# pool Object of LSM Pool
# vol Object of LSM Volume
+# _cim_xxx()
+# Return CIMInstance without any Associators() call.
+# _cim_xxx_of(cim_yyy)
+# Return CIMInstance associated to cim_yyy
+# _adj_cim_xxx()
+# Retrun CIMInstance with 'adj' only
+# _cim_xxx_of_id(some_id)
+# Return CIMInstance for given ID
+
traceback.format_exc())
return cim_wrapper
+ """
+ Convert version string stored in CIM_RegisteredProfile to a integer.
+ "1.5.1" -> 1,005,001
+ """
+ tmp_list = [0,0,0]
+ tmp_list = spec_ver_str.split(".")
+ tmp_list.extend([0])
+ return (int(tmp_list[0]) * 10 ** 6 +
+ int(tmp_list[1]) * 10 ** 3 +
+ int(tmp_list[2]))
+ return None
+
+ BLK_ROOT_PROFILE = 'Array'
+ BLK_SRVS_PROFILE = 'Block Services'
+ DISK_LITE_PROFILE = 'Disk Drive Lite'
+ MULTI_SYS_PROFILE = 'Multiple Computer System'
+ SMIS_SPEC_VER_1_4 ='1.4'
+ SMIS_SPEC_VER_1_5 ='1.5'
+ SMIS_SPEC_VER_1_6 ='1.6'
+ REG_ORG_CODE = pywbem.Uint16(11)
+
"""
# DSP 1033 Profile Registration
DMTF_INTEROP_NAMESPACES = ['interop', 'root/interop']
SMIS_DEFAULT_NAMESPACE = 'interop'
- SNIA_BLK_ROOT_PROFILE = 'Array'
- SNIA_BLK_SRVS_PROFILE = 'Block Services'
- SNIA_DISK_LITE_PROFILE = 'Disk Drive Lite'
- SNIA_MULTI_SYS_PROFILE = 'Multiple Computer System'
- SNIA_SMIS_SPEC_VER_1_4='1.4'
- SNIA_SMIS_SPEC_VER_1_5='1.5'
- SNIA_SMIS_SPEC_VER_1_6='1.6'
IAAN_WBEM_HTTP_PORT = 5988
IAAN_WBEM_HTTPS_PORT = 5989
self._c = None
self.tmo = 0
self.system_list = None
- self.cim_reg_profiles = []
+ self.cim_rps = []
self.cim_root_profile_dict = dict()
self.fallback_mode = True # Means we cannot use profile register
- self.cim_reg_profiles = self._c.EnumerateInstances(
+ self.cim_rps = self._c.EnumerateInstances(
'CIM_RegisteredProfile',
namespace=interop_namespace,
- PropertyList=['RegisteredName', 'RegisteredVersion'],
+ PropertyList=['RegisteredName', 'RegisteredVersion',
+ 'RegisteredOrganization'],
LocalOnly=False)
break
self.fallback_mode = False
# Support 'Array' profile is step 0 for this whole plugin.
# We find out all 'Array' CIM_RegisteredProfile and stored
# them into self.cim_root_profile_dict
- if 'RegisteredName' not in cim_reg_profile or \
- continue
- if cim_reg_profile['RegisteredName'] == \
- ver = cim_reg_profile['RegisteredVersion']
- self.cim_root_profile_dict[ver]= cim_reg_profile
+ if not self._profile_is_supported(
+ SNIA.BLK_ROOT_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4,
raise LsmError(ErrorNumber.NO_SUPPORT,
- "SMI-S provider does not support 'Array'"
- "profile which is prerequisite")
+ "SMI-S provider does not support "
+ "SNIA SMI-S SPEC %s '%s' profile" %
+ (SNIA.SMIS_SPEC_VER_1_4,
+ SNIA.BLK_ROOT_PROFILE))
if e[0] == pywbem.CIM_ERR_NOT_SUPPORTED or \
# Get the cim object that represents the system
cim_sys = None
cim_pcms = None
+ cim_sys = self._cim_sys_of_id(system.id)
- cim_sys = self._get_cim_syss_fallback(
- sys_id=system.id,
- property_list=[])[0] # Surely, we will get at least one
- # cim_sys since LSM system already
- # provided.
# Using 'ExposePathsSupported of
# CIM_ProtocolControllerMaskingCapabilities
cap.set(Capabilities.ACCESS_GROUP_DEL_INITIATOR)
return
- cim_syss = self._get_cim_syss(
- Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- sys_id=system.id,
- property_list=[])
- # we might not get any cim_sys on unsupported system.
- cim_sys = cim_syss[0]
- # CIM_ControllerConfigurationService is mandatory
- # and it's ExposePaths() and HidePaths() are mandatory
- cap.set(Capabilities.ACCESS_GROUP_LIST)
- cap.set(Capabilities.ACCESS_GROUP_GRANT)
- cap.set(Capabilities.ACCESS_GROUP_REVOKE)
- cap.set(Capabilities.ACCESS_GROUP_ADD_INITIATOR)
- cap.set(Capabilities.ACCESS_GROUP_DEL_INITIATOR)
- cap.set(Capabilities.ACCESS_GROUPS_GRANTED_TO_VOLUME)
- cap.set(Capabilities.VOLUMES_ACCESSIBLE_BY_ACCESS_GROUP)
- return
+ # CIM_ControllerConfigurationService is mandatory
+ # and it's ExposePaths() and HidePaths() are mandatory
+ cap.set(Capabilities.ACCESS_GROUP_LIST)
+ cap.set(Capabilities.ACCESS_GROUP_GRANT)
+ cap.set(Capabilities.ACCESS_GROUP_REVOKE)
+ cap.set(Capabilities.ACCESS_GROUP_ADD_INITIATOR)
+ cap.set(Capabilities.ACCESS_GROUP_DEL_INITIATOR)
+ cap.set(Capabilities.ACCESS_GROUPS_GRANTED_TO_VOLUME)
+ cap.set(Capabilities.VOLUMES_ACCESSIBLE_BY_ACCESS_GROUP)
cap = Capabilities()
|
v
CIM_StorageVolume
+ As 'Block Services Package' is mandatory for 'Array' profile, we
+ don't check support status here as startup() already checked 'Array'
+ profile.
"""
rc = []
cim_syss = []
cim_sys_pros = self._property_list_of_id("System")
- cim_syss = self._get_cim_syss_fallback(property_list=cim_sys_pros)
- cim_syss = self._get_cim_syss(
- Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False,
- property_list=cim_sys_pros,
- raise_error=True)
+
+ cim_syss = self._root_cim_syss(cim_sys_pros)
cim_vol_pros = self._new_vol_cim_vol_pros()
sys_id = self._sys_id(cim_sys)
|
v
CIM_StoragePool
+ As 'Block Services Package' is mandatory for 'Array' profile, we
+ don't check support status here as startup() already checked 'Array'
+ profile.
"""
rc = []
cim_pool_pros = self._new_pool_cim_pool_pros(
flags == Pool.RETRIEVE_FULL_INFO)
cim_sys_pros = self._property_list_of_id("System")
- cim_syss = []
- cim_syss = self._get_cim_syss_fallback(property_list=cim_sys_pros)
- cim_syss = self._get_cim_syss(
- Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False,
- property_list=cim_sys_pros,
- raise_error=True)
+ cim_syss = self._root_cim_syss(cim_sys_pros)
system_id = self._sys_id(cim_sys)
"""
Return the storage arrays accessible from this plug-in at this time
+
+ As 'Block Services Package' is mandatory for 'Array' profile, we
+ don't check support status here as startup() already checked 'Array'
+ profile.
"""
cim_sys_pros = self._cim_sys_pros()
- cim_syss = self._get_cim_syss_fallback(property_list=cim_sys_pros)
- cim_syss = self._get_cim_syss(
- Smis.SNIA_BLK_ROOT_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False,
- property_list=cim_sys_pros,
- raise_error=True)
-
- return []
+ cim_syss = self._root_cim_syss(cim_sys_pros)
+
return [Smis._cim_sys_2_lsm_sys(s) for s in cim_syss]
rc = []
cim_syss = []
cim_sys_pros = self._property_list_of_id("System")
- cim_syss = self._get_cim_syss_fallback(property_list=cim_sys_pros)
- cim_syss = self._get_cim_syss(
- Smis.SNIA_DISK_LITE_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False,
- property_list=cim_sys_pros,
- raise_error=True)
-
+ self._profile_is_supported(SNIA.DISK_LITE_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4,
+ strict=False,
+ raise_error=True)
+
+ # In SNIA SMI-S 1.6rev4 Common Book,
+ # 30.1.5 Associations between ComputerSystems and other Logical
+ # Elements
+ # "If the device may become unavailable while the system as a
+ # whole remains available, the device shall be associated to a
+ # non-top-level system that has availability equivalent to the
+ # device. This system could be a real system or a system in an
+ # intermediate tier (representing some redundancy less than full
+ # redundancy)."
+
+ # Hence DiskDrive might not associated to top level
+ # CIM_ComputerSystem
flag_multi_sys = None
- flag_multi_sys = self._profile_is_supported(
- Smis.SNIA_MULTI_SYS_PROFILE, Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False)
- # In SNIA SMI-S 1.6rev4 Common Book,
- # 30.1.5 Associations between ComputerSystems and other Logical
- # Elements
- # "If the device may become unavailable while the system as a
- # whole remains available, the device shall be associated to a
- # non-top-level system that has availability equivalent to the
- # device. This system could be a real system or a system in an
- # intermediate tier (representing some redundancy less than full
- # redundancy)."
-
- # Hence DiskDrive might not associated to top level
- # CIM_ComputerSystem
+ if not self.fallback_mode and \
+ self._profile_is_supported(SNIA.MULTI_SYS_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4,
+ strict=False,
+ flag_multi_sys = True
cim_disk_pros = Smis._new_disk_cim_disk_pros(flags)
"""
cim_sys_pros = self._property_list_of_id("System")
if not self.fallback_mode and \
- self._profile_is_supported(Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
+ self._profile_is_supported(SNIA.BLK_SRVS_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4,
raise LsmError(ErrorNumber.NO_SUPPORT,
"SMI-S %s version %s is not supported" %
- (Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4))
+ (SNIA.BLK_SRVS_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4))
- cim_sys = self._get_cim_sys_by_id(pool.system_id)
+ cim_sys = self._cim_sys_of_id(pool.system_id)
cim_pool = self._get_cim_pool_by_id(cim_sys.path, pool.id)
cim_scs = self._get_cim_scs(cim_sys.path)
CreateOrModifyStoragePool()
"""
if not self.fallback_mode and \
- self._profile_is_supported(Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
+ self._profile_is_supported(SNIA.BLK_SRVS_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4,
raise LsmError(ErrorNumber.NO_SUPPORT,
"SMI-S %s version %s is not supported" %
- (Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4))
+ (SNIA.BLK_SRVS_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4))
- cim_sys = self._get_cim_sys_by_id(system.id)
+ cim_sys = self._cim_sys_of_id(system.id)
# we does not support defining thinp_type yet.
# just using whatever provider set.
"CIM_StorageConfigurationService of " +
"CIM_ComputerSystem %s" % cim_sys_path)
+ def _profile_is_supported(self, profile_name, spec_ver, strict=False,
"""
Check whether we support certain profile at certain SNIA
specification version.
- When strict == False(default), profile spec version newer than
- require spec_ver will also be consider as found.
+ When strict == False(default), profile spec version later or equal
+ than require spec_ver will also be consider as found.
When strict == True, only defined spec_version is allowed.
+ Require self.cim_rps containing all CIM_RegisteredProfile
+ Will raise LsmError(ErrorNumber.NO_SUPPORT, 'xxx') if raise_error
+ is True when nothing found.
- profile_name # Smis.SNIA_REGISTERED_PROFILE_XXX
- spec_ver # Smis.SNIA_SMIS_SPEC_VER_XXX
- property_list # a list of properties should contained in
- # returned CIM_ComputerSystem
- # When property_list == None, we retrieve full
- # data, when property_list == [], we retrieve
- # nothing but a CIMInstanceName.
+ profile_name # SNIA.XXXX_PROFILE
+ spec_ver # SNIA.SMIS_SPEC_VER_XXX
strict # False or True. If True, only defined
# spec_version is consider as supported
# If false, will return the maximum version of
# spec.
+ raise_error # Raise LsmError if not found
None # Not supported.
or
- spec_version # the vendor implemented version. like '1.4.1'
- # This is a string, NOT float.
- """
- max_spec_ver = 0
- max_spec_ver_flt = 0
- # assuming spec_ver is well formatted, since we are internal
- # method, we can do that guess.
- req_ver_main = spec_ver.split('.')[0]
- req_ver_sub = spec_ver.split('.')[1]
-
- if 'RegisteredName' not in cim_reg_profile or \
+ spec_int # Integer. Converted by _spec_ver_str_to_num()
+ """
+ req_ver = _spec_ver_str_to_num(spec_ver)
+
+ max_spec_ver_str = None
+ max_spec_ver = None
+ if 'RegisteredName' not in cim_rp or \
continue
# check spec version
- cur_ver = cim_reg_profile['RegisteredVersion']
- cur_ver_list = cur_ver.split('.')
- continue
- cur_ver_flt = float("%s.%s" % tuple(cur_ver_list[0:2]))
- req_ver_flt = float("%s.%s" % (req_ver_main, req_ver_sub))
+ cur_ver = _spec_ver_str_to_num(cim_rp['RegisteredVersion'])
return cur_ver
-
+ if max_spec_ver is None or \
max_spec_ver = cur_ver
- max_spec_ver_flt = cur_ver_flt
+ max_spec_ver_str = cim_rp['RegisteredVersion']
+ raise LsmError(ErrorNumber.NO_SUPPORT,
+ "SNIA SMI-S %s '%s' profile is not supported" %
+ (spec_ver, profile_name))
- return None
return max_spec_ver
- def _get_cim_syss(self, profile_name, spec_ver, property_list=None,
"""
- Check whether we support certain profile at certain SNIA
- specification version.
- When strict == False(default), profile spec version newer than
- require spec_ver will also be consider as found.
- When strict == True, only defined spec_version is allowed.
+ For fallback mode, this just enumerate CIM_ComputerSystem.
+ We require vendor to implement profile registration when using
+ "Multiple System Profile".
+ For normal mode, this just find out the root CIM_ComputerSystem
CIM_RegisteredProfile # Root Profile('Array') in interop
|
| CIM_ElementConformsToProfile
v
CIM_ComputerSystem # vendor namespace
- We depend on self.cim_reg_profiles which was updated by startup().
- But this method does not check it, you should check
- self.fallback_mode == True before call this method.
-
- Please use constant spec_ver and profile_name for better
- code management.
- We also apply to system filter in URI which is stored in
- self.system_list
- When returning None, it means current provider does not support
- requested profile or version.
- profile_name # Smis.SNIA_REGISTERED_PROFILE_XXX
- spec_ver # Smis.SNIA_SMIS_SPEC_VER_XXX
- property_list # a list of properties should contained in
- # returned CIM_ComputerSystem
- # When property_list == None, we retrieve full
- # data, when property_list == [], we retrieve
- # nothing but a CIMInstanceName.
- strict # False or True. If True, only defined
- # spec_version is consider as supported
- sys_id # Only return CIM_ComputerSystem for certain
- # system ID.
- cim_syss # a list of CIMInstanceName of CIM_ComputerSystem
- or
- None # Current SMI-S provider does not support this
- # profile at certain version.
- """
- max_spec_ver = self._profile_is_supported(
- profile_name, spec_ver, strict)
-
- error_msg = ("Current SMI-S provider does not support "
- "SMI-S %s profile, version %s" %
- (profile_name, spec_ver))
- error_msg = "%s(or later version)" % error_msg
- raise LsmError(ErrorNumber.NO_SUPPORT, error_msg)
- return None
-
- raise LsmError(ErrorNumber.INTERNAL_ERROR,
- "Failed to find out CIM_RegisteredProfile " +
- "for profile %s with version %s " %
- (Smis.SNIA_BLK_ROOT_PROFILE, max_spec_ver) +
- "even its subprofile found.")
-
- cim_root_profile = self.cim_root_profile_dict[max_spec_ver]
-
- cim_syss = self._c.Associators(
- cim_root_profile.path,
- ResultClass='CIM_ComputerSystem',
- AssocClass='CIM_ElementConformsToProfile')
- sys_id_pros = self._property_list_of_id('System')
- property_list.extend([key])
- cim_syss = self._c.Associators(
- cim_root_profile.path,
- ResultClass='CIM_ComputerSystem',
- AssocClass='CIM_ElementConformsToProfile',
- PropertyList=property_list)
-
- return cim_syss
-
- # Method level filter
- return [s for s in cim_syss if self._sys_id(s) == sys_id][0]
-
- # Apply URI system filter
- needed_cim_syss = []
- needed_cim_syss.extend([cim_sys])
- return needed_cim_syss
-
- """
- CIM_StorageConfigurationService # Enumerate
- |
- | CIM_HostedService
- v
- CIM_ComputerSystem
- If CIM_StorageConfigurationService is not support neither,
- we enumerate CIM_ComputerSystem.
- property_list # a list of properties should contained in
- # returned CIM_ComputerSystem
- # When property_list == None, we retrieve full
- # data, when property_list == [], we retrieve
- # nothing but a CIMInstanceName.
- cim_syss # A list of CIMInstanceName of CIM_ComputerSystem
- or
- None
+ We also assume no matter which version of root profile can lead to
+ the same CIM_ComputerSystem instance.
+ As CIM_ComputerSystem has no property indicate SNIA SMI-S version,
+ this is assumption should work. Tested on EMC SMI-S provider which
+ provide 1.4, 1.5, 1.6 root profile.
"""
- sys_id_pros = self._property_list_of_id('System')
- flag_full_info = False
+ cim_sys_id_pros = self._property_list_of_id('System')
- flag_full_info = True
+ property_list = cim_sys_id_pros
- property_list.extend([key])
+ property_list.extend([key_name])
cim_syss = []
- cim_scss_path = []
- # Note: Please be informed, if PropertyList is an empty list,
- # XIV will return NOTHING, so use EnumerateInstanceNames()
- # when you need nothing but the CIMInstanceName
- cim_scss_path = self._c.EnumerateInstanceNames(
- 'CIM_StorageConfigurationService')
- # If array does not support CIM_StorageConfigurationService
- # we use CIM_ComputerSystem which is mandatory.
- # We might get some non-storage array listed as system.
- # but we would like to take that risk instead of
- # skipping basic support of old SMIS provider.
- cim_syss = self._c.EnumerateInstances(
- 'CIM_ComputerSystem', LocalOnly=False)
- cim_syss = self._c.EnumerateInstances(
- 'CIM_ComputerSystem',
- PropertyList=property_list,
- LocalOnly=False)
- raise e
- cim_tmp = None
- cim_tmp = self._c.Associators(
- cim_scs_path,
- AssocClass='CIM_HostedService',
- ResultClass='CIM_ComputerSystem')
+ # CIM_StorageConfigurationService # Enumerate
+ # |
+ # | CIM_HostedService
+ # v
+ # CIM_ComputerSystem
+ # If CIM_StorageConfigurationService is not support neither,
+ # we enumerate CIM_ComputerSystem.
+ cim_scss_path = self._c.EnumerateInstanceNames(
+ 'CIM_StorageConfigurationService')
+ # If array does not support CIM_StorageConfigurationService
+ # we use CIM_ComputerSystem which is mandatory.
+ # We might get some non-storage array listed as system.
+ # but we would like to take that risk instead of
+ # skipping basic support of old SMIS provider.
+ cim_syss = self._c.EnumerateInstances(
+ 'CIM_ComputerSystem',
+ PropertyList=property_list,
+ LocalOnly=False)
+ raise e
+
+ cim_tmp = None
+ # CIM_ComputerSystem is one-one map to
+ # CIM_StorageConfigurationService
cim_tmp = self._c.Associators(
cim_scs_path,
AssocClass='CIM_HostedService',
ResultClass='CIM_ComputerSystem',
PropertyList=property_list)
- cim_syss.extend([cim_tmp[0]])
-
- # Method level filter
- return [s for s in cim_syss if self._sys_id(s) == sys_id]
+ cim_syss.extend([cim_tmp[0]])
+ if cim_rp['RegisteredName'] == SNIA.BLK_ROOT_PROFILE and\
+ cim_syss = self._c.Associators(
+ cim_rp.path,
+ ResultClass='CIM_ComputerSystem',
+ AssocClass='CIM_ElementConformsToProfile',
+ PropertyList=property_list)
+ # Any version of 'Array' profile can get us to root
+ # CIM_ComputerSystem. startup() already has checked the
+ # 1.4 version
+ break
# System URI Filtering
return cim_syss
+
"""
Return a CIMInstance of CIM_ComputerSystem for given system id.
"""
property_list.extend([pro])
- cim_syss = self._get_cim_syss_fallback(property_list)
- cim_syss = self._get_cim_syss(
- Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False,
- property_list=property_list,
- raise_error=True)
+ cim_syss = self._root_cim_syss(property_list)
+
return cim_sys
Gris Ge
2014-05-21 15:03:59 UTC
Permalink
* Convert SMI-S SPEC version into integer for better comparison.
Please check _spec_ver_str_to_num() for detail.
* Let _root_cim_syss() handle the fall back checking. It will return a list
of CIM_ComputerSystem for fallback mode or not.
* Checking for 1.4 'Array' profile support in startup().
As 'Block Services Package' (AKA: BSP) is mandatory for that profile, we
don't do extra check in methods using BSP profile.
* Noting down the method naming scheme for consistency.
* Move SNIA related constants to a standalone class SNIA which shorter the
constant variable name.
* _profile_is_supported() now support raise error if not found.
* Split _cim_sys_of_id() out to raise LsmError ErrorNumber.NOT_FOUND_SYSTEM.
* Add RegisteredOrganization checking in CIM_RegisteredProfile.

Changes in V2:
* In case fallmode facing 'multiple system' profile supported array,
the _root_cim_syss() will use the old way to get top ComputerSystem:
CIM_StorageConfigurationService -> ComputerSystem
* Add author names.

Changes in V3:
* Removed un-needed check. The startup() already checked the support of
'Array' profile.

Changes in V4:
* Fix the incorrect fallback_mode variable used in disks()

Signed-off-by: Gris Ge <***@redhat.com>
---
plugin/smispy/smis.py | 527 ++++++++++++++++++++------------------------------
1 file changed, 210 insertions(+), 317 deletions(-)

diff --git a/plugin/smispy/smis.py b/plugin/smispy/smis.py
index c63d8cd..d60dbd2 100644
--- a/plugin/smispy/smis.py
+++ b/plugin/smispy/smis.py
@@ -13,6 +13,9 @@
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
# USA
+#
+# Author: tasleson
+# Gris Ge <***@redhat.com>

from string import split
import time
@@ -32,11 +35,22 @@ from lsm import (IStorageAreaNetwork, Error, uri_parse, LsmError, ErrorNumber,
# cim_pool CIM_StoragePool
# cim_scs CIM_StorageConfigurationService
# cim_vol CIM_StorageVolume
+# cim_rp CIM_RegisteredProfile
#
# sys Object of LSM System
# pool Object of LSM Pool
# vol Object of LSM Volume

+## Method Naming schme:
+# _cim_xxx()
+# Return CIMInstance without any Associators() call.
+# _cim_xxx_of(cim_yyy)
+# Return CIMInstance associated to cim_yyy
+# _adj_cim_xxx()
+# Retrun CIMInstance with 'adj' only
+# _cim_xxx_of_id(some_id)
+# Return CIMInstance for given ID
+

def handle_cim_errors(method):
def cim_wrapper(*args, **kwargs):
@@ -65,6 +79,32 @@ def handle_cim_errors(method):
traceback.format_exc())
return cim_wrapper

+def _spec_ver_str_to_num(spec_ver_str):
+ """
+ Convert version string stored in CIM_RegisteredProfile to a integer.
+ Example:
+ "1.5.1" -> 1,005,001
+ """
+ tmp_list = [0,0,0]
+ tmp_list = spec_ver_str.split(".")
+ if len(tmp_list) == 2:
+ tmp_list.extend([0])
+ if len(tmp_list) == 3:
+ return (int(tmp_list[0]) * 10 ** 6 +
+ int(tmp_list[1]) * 10 ** 3 +
+ int(tmp_list[2]))
+ return None
+
+class SNIA(object):
+ BLK_ROOT_PROFILE = 'Array'
+ BLK_SRVS_PROFILE = 'Block Services'
+ DISK_LITE_PROFILE = 'Disk Drive Lite'
+ MULTI_SYS_PROFILE = 'Multiple Computer System'
+ SMIS_SPEC_VER_1_4 ='1.4'
+ SMIS_SPEC_VER_1_5 ='1.5'
+ SMIS_SPEC_VER_1_6 ='1.6'
+ REG_ORG_CODE = pywbem.Uint16(11)
+

class Smis(IStorageAreaNetwork):
"""
@@ -252,13 +292,6 @@ class Smis(IStorageAreaNetwork):
# DSP 1033 Profile Registration
DMTF_INTEROP_NAMESPACES = ['interop', 'root/interop']
SMIS_DEFAULT_NAMESPACE = 'interop'
- SNIA_BLK_ROOT_PROFILE = 'Array'
- SNIA_BLK_SRVS_PROFILE = 'Block Services'
- SNIA_DISK_LITE_PROFILE = 'Disk Drive Lite'
- SNIA_MULTI_SYS_PROFILE = 'Multiple Computer System'
- SNIA_SMIS_SPEC_VER_1_4='1.4'
- SNIA_SMIS_SPEC_VER_1_5='1.5'
- SNIA_SMIS_SPEC_VER_1_6='1.6'

IAAN_WBEM_HTTP_PORT = 5988
IAAN_WBEM_HTTPS_PORT = 5989
@@ -350,7 +383,7 @@ class Smis(IStorageAreaNetwork):
self._c = None
self.tmo = 0
self.system_list = None
- self.cim_reg_profiles = []
+ self.cim_rps = []
self.cim_root_profile_dict = dict()
self.fallback_mode = True # Means we cannot use profile register

@@ -555,31 +588,29 @@ class Smis(IStorageAreaNetwork):

try:
for interop_namespace in Smis.DMTF_INTEROP_NAMESPACES:
- self.cim_reg_profiles = self._c.EnumerateInstances(
+ self.cim_rps = self._c.EnumerateInstances(
'CIM_RegisteredProfile',
namespace=interop_namespace,
- PropertyList=['RegisteredName', 'RegisteredVersion'],
+ PropertyList=['RegisteredName', 'RegisteredVersion',
+ 'RegisteredOrganization'],
LocalOnly=False)
- if len(self.cim_reg_profiles) != 0:
+ if len(self.cim_rps) != 0:
break

- if len(self.cim_reg_profiles) >= 1:
+ if len(self.cim_rps) >= 1:
self.fallback_mode = False
# Support 'Array' profile is step 0 for this whole plugin.
# We find out all 'Array' CIM_RegisteredProfile and stored
# them into self.cim_root_profile_dict
- for cim_reg_profile in self.cim_reg_profiles:
- if 'RegisteredName' not in cim_reg_profile or \
- 'RegisteredVersion' not in cim_reg_profile:
- continue
- if cim_reg_profile['RegisteredName'] == \
- Smis.SNIA_BLK_ROOT_PROFILE:
- ver = cim_reg_profile['RegisteredVersion']
- self.cim_root_profile_dict[ver]= cim_reg_profile
- if len(self.cim_root_profile_dict) == 0:
+ if not self._profile_is_supported(
+ SNIA.BLK_ROOT_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4,
+ strict=False):
raise LsmError(ErrorNumber.NO_SUPPORT,
- "SMI-S provider does not support 'Array'"
- "profile which is prerequisite")
+ "SMI-S provider does not support "
+ "SNIA SMI-S SPEC %s '%s' profile" %
+ (SNIA.SMIS_SPEC_VER_1_4,
+ SNIA.BLK_ROOT_PROFILE))
except CIMError as e:
if e[0] == pywbem.CIM_ERR_NOT_SUPPORTED or \
e[0] == pywbem.CIM_ERR_INVALID_NAMESPACE:
@@ -720,12 +751,8 @@ class Smis(IStorageAreaNetwork):
# Get the cim object that represents the system
cim_sys = None
cim_pcms = None
+ cim_sys = self._cim_sys_of_id(system.id)
if self.fallback_mode:
- cim_sys = self._get_cim_syss_fallback(
- sys_id=system.id,
- property_list=[])[0] # Surely, we will get at least one
- # cim_sys since LSM system already
- # provided.

# Using 'ExposePathsSupported of
# CIM_ProtocolControllerMaskingCapabilities
@@ -752,26 +779,16 @@ class Smis(IStorageAreaNetwork):
cap.set(Capabilities.ACCESS_GROUP_DEL_INITIATOR)
return
else:
- cim_syss = self._get_cim_syss(
- Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- sys_id=system.id,
- property_list=[])
- # we might not get any cim_sys on unsupported system.
- if len(cim_syss) == 1:
- cim_sys = cim_syss[0]
- # Since SNIA SMI-S 1.4rev6:
- # CIM_ControllerConfigurationService is mandatory
- # and it's ExposePaths() and HidePaths() are mandatory
- cap.set(Capabilities.ACCESS_GROUP_LIST)
- cap.set(Capabilities.ACCESS_GROUP_GRANT)
- cap.set(Capabilities.ACCESS_GROUP_REVOKE)
- cap.set(Capabilities.ACCESS_GROUP_ADD_INITIATOR)
- cap.set(Capabilities.ACCESS_GROUP_DEL_INITIATOR)
- cap.set(Capabilities.ACCESS_GROUPS_GRANTED_TO_VOLUME)
- cap.set(Capabilities.VOLUMES_ACCESSIBLE_BY_ACCESS_GROUP)
- else:
- return
+ # Since SNIA SMI-S 1.4rev6:
+ # CIM_ControllerConfigurationService is mandatory
+ # and it's ExposePaths() and HidePaths() are mandatory
+ cap.set(Capabilities.ACCESS_GROUP_LIST)
+ cap.set(Capabilities.ACCESS_GROUP_GRANT)
+ cap.set(Capabilities.ACCESS_GROUP_REVOKE)
+ cap.set(Capabilities.ACCESS_GROUP_ADD_INITIATOR)
+ cap.set(Capabilities.ACCESS_GROUP_DEL_INITIATOR)
+ cap.set(Capabilities.ACCESS_GROUPS_GRANTED_TO_VOLUME)
+ cap.set(Capabilities.VOLUMES_ACCESSIBLE_BY_ACCESS_GROUP)

def _common_capabilities(self, system):
cap = Capabilities()
@@ -1283,19 +1300,15 @@ class Smis(IStorageAreaNetwork):
|
v
CIM_StorageVolume
+ As 'Block Services Package' is mandatory for 'Array' profile, we
+ don't check support status here as startup() already checked 'Array'
+ profile.
"""
rc = []
cim_syss = []
cim_sys_pros = self._property_list_of_id("System")
- if self.fallback_mode:
- cim_syss = self._get_cim_syss_fallback(property_list=cim_sys_pros)
- else:
- cim_syss = self._get_cim_syss(
- Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False,
- property_list=cim_sys_pros,
- raise_error=True)
+
+ cim_syss = self._root_cim_syss(cim_sys_pros)
cim_vol_pros = self._new_vol_cim_vol_pros()
for cim_sys in cim_syss:
sys_id = self._sys_id(cim_sys)
@@ -1405,22 +1418,16 @@ class Smis(IStorageAreaNetwork):
|
v
CIM_StoragePool
+ As 'Block Services Package' is mandatory for 'Array' profile, we
+ don't check support status here as startup() already checked 'Array'
+ profile.
"""
rc = []
cim_pool_pros = self._new_pool_cim_pool_pros(
flags == Pool.RETRIEVE_FULL_INFO)

cim_sys_pros = self._property_list_of_id("System")
- cim_syss = []
- if self.fallback_mode:
- cim_syss = self._get_cim_syss_fallback(property_list=cim_sys_pros)
- else:
- cim_syss = self._get_cim_syss(
- Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False,
- property_list=cim_sys_pros,
- raise_error=True)
+ cim_syss = self._root_cim_syss(cim_sys_pros)

for cim_sys in cim_syss:
system_id = self._sys_id(cim_sys)
@@ -1535,20 +1542,14 @@ class Smis(IStorageAreaNetwork):
def systems(self, flags=0):
"""
Return the storage arrays accessible from this plug-in at this time
+
+ As 'Block Services Package' is mandatory for 'Array' profile, we
+ don't check support status here as startup() already checked 'Array'
+ profile.
"""
cim_sys_pros = self._cim_sys_pros()
- if self.fallback_mode:
- cim_syss = self._get_cim_syss_fallback(property_list=cim_sys_pros)
- else:
- cim_syss = self._get_cim_syss(
- Smis.SNIA_BLK_ROOT_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False,
- property_list=cim_sys_pros,
- raise_error=True)
-
- if cim_syss is None:
- return []
+ cim_syss = self._root_cim_syss(cim_sys_pros)
+
return [Smis._cim_sys_2_lsm_sys(s) for s in cim_syss]

def _new_init(self, cim_st_hwid):
@@ -2246,33 +2247,31 @@ class Smis(IStorageAreaNetwork):
rc = []
cim_syss = []
cim_sys_pros = self._property_list_of_id("System")
- if self.fallback_mode:
- cim_syss = self._get_cim_syss_fallback(property_list=cim_sys_pros)
- else:
- cim_syss = self._get_cim_syss(
- Smis.SNIA_DISK_LITE_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False,
- property_list=cim_sys_pros,
- raise_error=True)
-
- flag_multi_sys = None
if not self.fallback_mode:
- flag_multi_sys = self._profile_is_supported(
- Smis.SNIA_MULTI_SYS_PROFILE, Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False)
- # In SNIA SMI-S 1.6rev4 Common Book,
- # 30.1.5 Associations between ComputerSystems and other Logical
- # Elements
- # "If the device may become unavailable while the system as a
- # whole remains available, the device shall be associated to a
- # non-top-level system that has availability equivalent to the
- # device. This system could be a real system or a system in an
- # intermediate tier (representing some redundancy less than full
- # redundancy)."
-
- # Hence DiskDrive might not associated to top level
- # CIM_ComputerSystem
+ self._profile_is_supported(SNIA.DISK_LITE_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4,
+ strict=False,
+ raise_error=True)
+
+ # In SNIA SMI-S 1.6rev4 Common Book,
+ # 30.1.5 Associations between ComputerSystems and other Logical
+ # Elements
+ # "If the device may become unavailable while the system as a
+ # whole remains available, the device shall be associated to a
+ # non-top-level system that has availability equivalent to the
+ # device. This system could be a real system or a system in an
+ # intermediate tier (representing some redundancy less than full
+ # redundancy)."
+
+ # Hence DiskDrive might not associated to top level
+ # CIM_ComputerSystem
+ flag_multi_sys = None
+ if not self.fallback_mode and \
+ self._profile_is_supported(SNIA.MULTI_SYS_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4,
+ strict=False,
+ raise_error=False):
+ flag_multi_sys = True

for cim_sys in cim_syss:
cim_disk_pros = Smis._new_disk_cim_disk_pros(flags)
@@ -3008,15 +3007,15 @@ class Smis(IStorageAreaNetwork):
"""
cim_sys_pros = self._property_list_of_id("System")
if not self.fallback_mode and \
- self._profile_is_supported(Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
+ self._profile_is_supported(SNIA.BLK_SRVS_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4,
strict=False) is None:
raise LsmError(ErrorNumber.NO_SUPPORT,
"SMI-S %s version %s is not supported" %
- (Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4))
+ (SNIA.BLK_SRVS_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4))

- cim_sys = self._get_cim_sys_by_id(pool.system_id)
+ cim_sys = self._cim_sys_of_id(pool.system_id)
cim_pool = self._get_cim_pool_by_id(cim_sys.path, pool.id)
cim_scs = self._get_cim_scs(cim_sys.path)

@@ -3039,15 +3038,15 @@ class Smis(IStorageAreaNetwork):
CreateOrModifyStoragePool()
"""
if not self.fallback_mode and \
- self._profile_is_supported(Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
+ self._profile_is_supported(SNIA.BLK_SRVS_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4,
strict=False) is None:
raise LsmError(ErrorNumber.NO_SUPPORT,
"SMI-S %s version %s is not supported" %
- (Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4))
+ (SNIA.BLK_SRVS_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4))

- cim_sys = self._get_cim_sys_by_id(system.id)
+ cim_sys = self._cim_sys_of_id(system.id)

# we does not support defining thinp_type yet.
# just using whatever provider set.
@@ -3371,238 +3370,138 @@ class Smis(IStorageAreaNetwork):
"CIM_StorageConfigurationService of " +
"CIM_ComputerSystem %s" % cim_sys_path)

- def _profile_is_supported(self, profile_name, spec_ver, strict=False):
+ def _profile_is_supported(self, profile_name, spec_ver, strict=False,
+ raise_error=False):
"""
Usage:
Check whether we support certain profile at certain SNIA
specification version.
- When strict == False(default), profile spec version newer than
- require spec_ver will also be consider as found.
+ When strict == False(default), profile spec version later or equal
+ than require spec_ver will also be consider as found.
When strict == True, only defined spec_version is allowed.
+ Require self.cim_rps containing all CIM_RegisteredProfile
+ Will raise LsmError(ErrorNumber.NO_SUPPORT, 'xxx') if raise_error
+ is True when nothing found.
Parameter:
- profile_name # Smis.SNIA_REGISTERED_PROFILE_XXX
- spec_ver # Smis.SNIA_SMIS_SPEC_VER_XXX
- property_list # a list of properties should contained in
- # returned CIM_ComputerSystem
- # When property_list == None, we retrieve full
- # data, when property_list == [], we retrieve
- # nothing but a CIMInstanceName.
+ profile_name # SNIA.XXXX_PROFILE
+ spec_ver # SNIA.SMIS_SPEC_VER_XXX
strict # False or True. If True, only defined
# spec_version is consider as supported
# If false, will return the maximum version of
# spec.
+ raise_error # Raise LsmError if not found
Returns:
None # Not supported.
or
- spec_version # the vendor implemented version. like '1.4.1'
- # This is a string, NOT float.
- """
- max_spec_ver = 0
- max_spec_ver_flt = 0
- # assuming spec_ver is well formatted, since we are internal
- # method, we can do that guess.
- req_ver_main = spec_ver.split('.')[0]
- req_ver_sub = spec_ver.split('.')[1]
-
- for cim_reg_profile in self.cim_reg_profiles:
- if 'RegisteredName' not in cim_reg_profile or \
- 'RegisteredVersion' not in cim_reg_profile:
+ spec_int # Integer. Converted by _spec_ver_str_to_num()
+ """
+ req_ver = _spec_ver_str_to_num(spec_ver)
+
+ max_spec_ver_str = None
+ max_spec_ver = None
+ for cim_rp in self.cim_rps:
+ if 'RegisteredName' not in cim_rp or \
+ 'RegisteredVersion' not in cim_rp:
continue
- if cim_reg_profile['RegisteredName'] == profile_name:
+ if cim_rp['RegisteredName'] == profile_name:
# check spec version
- cur_ver = cim_reg_profile['RegisteredVersion']
- cur_ver_list = cur_ver.split('.')
- if len(cur_ver_list) < 2:
- continue
- cur_ver_flt = float("%s.%s" % tuple(cur_ver_list[0:2]))
- req_ver_flt = float("%s.%s" % (req_ver_main, req_ver_sub))
+ cur_ver = _spec_ver_str_to_num(cim_rp['RegisteredVersion'])

- if strict and cur_ver_flt == req_ver_flt:
+ if strict and cur_ver == req_ver:
return cur_ver
-
- if strict is False and cur_ver_flt >= req_ver_flt:
- if cur_ver_flt > max_spec_ver_flt:
+ elif cur_ver >= req_ver:
+ if max_spec_ver is None or \
+ cur_ver > max_spec_ver:
max_spec_ver = cur_ver
- max_spec_ver_flt = cur_ver_flt
+ max_spec_ver_str = cim_rp['RegisteredVersion']
+ if strict or max_spec_ver is None:
+ raise LsmError(ErrorNumber.NO_SUPPORT,
+ "SNIA SMI-S %s '%s' profile is not supported" %
+ (spec_ver, profile_name))

- if max_spec_ver == 0:
- return None
return max_spec_ver

- def _get_cim_syss(self, profile_name, spec_ver, property_list=None,
- strict=False, sys_id=None, raise_error=False):
+ def _root_cim_syss(self, property_list=None):
"""
- Usage:
- Check whether we support certain profile at certain SNIA
- specification version.
- When strict == False(default), profile spec version newer than
- require spec_ver will also be consider as found.
- When strict == True, only defined spec_version is allowed.
+ For fallback mode, this just enumerate CIM_ComputerSystem.
+ We require vendor to implement profile registration when using
+ "Multiple System Profile".
+ For normal mode, this just find out the root CIM_ComputerSystem
+ via:

- If found, follow this procedure to get CIM_ComputerSystem:
CIM_RegisteredProfile # Root Profile('Array') in interop
|
| CIM_ElementConformsToProfile
v
CIM_ComputerSystem # vendor namespace

- We depend on self.cim_reg_profiles which was updated by startup().
- But this method does not check it, you should check
- self.fallback_mode == True before call this method.
-
- Please use constant spec_ver and profile_name for better
- code management.
- We also apply to system filter in URI which is stored in
- self.system_list
- When returning None, it means current provider does not support
- requested profile or version.
- Parameter:
- profile_name # Smis.SNIA_REGISTERED_PROFILE_XXX
- spec_ver # Smis.SNIA_SMIS_SPEC_VER_XXX
- property_list # a list of properties should contained in
- # returned CIM_ComputerSystem
- # When property_list == None, we retrieve full
- # data, when property_list == [], we retrieve
- # nothing but a CIMInstanceName.
- strict # False or True. If True, only defined
- # spec_version is consider as supported
- sys_id # Only return CIM_ComputerSystem for certain
- # system ID.
- Returns:
- cim_syss # a list of CIMInstanceName of CIM_ComputerSystem
- or
- None # Current SMI-S provider does not support this
- # profile at certain version.
- """
- max_spec_ver = self._profile_is_supported(
- profile_name, spec_ver, strict)
-
- if max_spec_ver is None:
- if raise_error:
- error_msg = ("Current SMI-S provider does not support "
- "SMI-S %s profile, version %s" %
- (profile_name, spec_ver))
- if not strict:
- error_msg = "%s(or later version)" % error_msg
- raise LsmError(ErrorNumber.NO_SUPPORT, error_msg)
- else:
- return None
-
- if max_spec_ver not in self.cim_root_profile_dict.keys():
- raise LsmError(ErrorNumber.INTERNAL_ERROR,
- "Failed to find out CIM_RegisteredProfile " +
- "for profile %s with version %s " %
- (Smis.SNIA_BLK_ROOT_PROFILE, max_spec_ver) +
- "even its subprofile found.")
-
- cim_root_profile = self.cim_root_profile_dict[max_spec_ver]
-
- if property_list is None:
- cim_syss = self._c.Associators(
- cim_root_profile.path,
- ResultClass='CIM_ComputerSystem',
- AssocClass='CIM_ElementConformsToProfile')
- else:
- sys_id_pros = self._property_list_of_id('System')
- for key in sys_id_pros:
- if key not in property_list:
- property_list.extend([key])
- cim_syss = self._c.Associators(
- cim_root_profile.path,
- ResultClass='CIM_ComputerSystem',
- AssocClass='CIM_ElementConformsToProfile',
- PropertyList=property_list)
-
- if self.system_list is None:
- return cim_syss
-
- # Method level filter
- if sys_id is not None:
- return [s for s in cim_syss if self._sys_id(s) == sys_id][0]
-
- # Apply URI system filter
- needed_cim_syss = []
- for cim_sys in cim_syss:
- if self._sys_id(cim_sys) in self.system_list:
- needed_cim_syss.extend([cim_sys])
- return needed_cim_syss
-
- def _get_cim_syss_fallback(self, sys_id=None, property_list=None):
- """
- Usage:
- Find out the root CIM_ComputerSystem using the fallback method:
- CIM_StorageConfigurationService # Enumerate
- |
- | CIM_HostedService
- v
- CIM_ComputerSystem
- If CIM_StorageConfigurationService is not support neither,
- we enumerate CIM_ComputerSystem.
- Parameter:
- property_list # a list of properties should contained in
- # returned CIM_ComputerSystem
- # When property_list == None, we retrieve full
- # data, when property_list == [], we retrieve
- # nothing but a CIMInstanceName.
- Returns:
- cim_syss # A list of CIMInstanceName of CIM_ComputerSystem
- or
- None
+ We also assume no matter which version of root profile can lead to
+ the same CIM_ComputerSystem instance.
+ As CIM_ComputerSystem has no property indicate SNIA SMI-S version,
+ this is assumption should work. Tested on EMC SMI-S provider which
+ provide 1.4, 1.5, 1.6 root profile.
"""
- sys_id_pros = self._property_list_of_id('System')
- flag_full_info = False
+ cim_sys_id_pros = self._property_list_of_id('System')
if property_list is None:
- flag_full_info = True
+ property_list = cim_sys_id_pros
else:
- for key in sys_id_pros:
- if key not in property_list:
- property_list.extend([key])
+ for key_name in cim_sys_id_pros:
+ if key_name not in property_list:
+ property_list.extend([key_name])

cim_syss = []
- cim_scss_path = []
- try:
- # Note: Please be informed, if PropertyList is an empty list,
- # XIV will return NOTHING, so use EnumerateInstanceNames()
- # when you need nothing but the CIMInstanceName
- cim_scss_path = self._c.EnumerateInstanceNames(
- 'CIM_StorageConfigurationService')
- except CIMError as e:
- # If array does not support CIM_StorageConfigurationService
- # we use CIM_ComputerSystem which is mandatory.
- # We might get some non-storage array listed as system.
- # but we would like to take that risk instead of
- # skipping basic support of old SMIS provider.
- if e[0] == pywbem.CIM_ERR_INVALID_CLASS:
- if flag_full_info:
- cim_syss = self._c.EnumerateInstances(
- 'CIM_ComputerSystem', LocalOnly=False)
- else:
- cim_syss = self._c.EnumerateInstances(
- 'CIM_ComputerSystem',
- PropertyList=property_list,
- LocalOnly=False)
- else:
- raise e
- if not cim_syss:
- for cim_scs_path in cim_scss_path:
- cim_tmp = None
- if flag_full_info:
- cim_tmp = self._c.Associators(
- cim_scs_path,
- AssocClass='CIM_HostedService',
- ResultClass='CIM_ComputerSystem')
+ if self.fallback_mode:
+ # Fallback mode:
+ # Find out the root CIM_ComputerSystem using the fallback method:
+ # CIM_StorageConfigurationService # Enumerate
+ # |
+ # | CIM_HostedService
+ # v
+ # CIM_ComputerSystem
+ # If CIM_StorageConfigurationService is not support neither,
+ # we enumerate CIM_ComputerSystem.
+ try:
+ cim_scss_path = self._c.EnumerateInstanceNames(
+ 'CIM_StorageConfigurationService')
+ except CIMError as e:
+ # If array does not support CIM_StorageConfigurationService
+ # we use CIM_ComputerSystem which is mandatory.
+ # We might get some non-storage array listed as system.
+ # but we would like to take that risk instead of
+ # skipping basic support of old SMIS provider.
+ if e[0] == pywbem.CIM_ERR_INVALID_CLASS:
+ cim_syss = self._c.EnumerateInstances(
+ 'CIM_ComputerSystem',
+ PropertyList=property_list,
+ LocalOnly=False)
else:
+ raise e
+
+ if not cim_syss:
+ for cim_scs_path in cim_scss_path:
+ cim_tmp = None
+ # CIM_ComputerSystem is one-one map to
+ # CIM_StorageConfigurationService
cim_tmp = self._c.Associators(
cim_scs_path,
AssocClass='CIM_HostedService',
ResultClass='CIM_ComputerSystem',
PropertyList=property_list)
- if cim_tmp and cim_tmp[0]:
- cim_syss.extend([cim_tmp[0]])
-
- # Method level filter
- if sys_id is not None:
- return [s for s in cim_syss if self._sys_id(s) == sys_id]
+ if cim_tmp and cim_tmp[0]:
+ cim_syss.extend([cim_tmp[0]])
+ else:
+ for cim_rp in self.cim_rps:
+ if cim_rp['RegisteredName'] == SNIA.BLK_ROOT_PROFILE and\
+ cim_rp['RegisteredOrganization'] == SNIA.REG_ORG_CODE:
+ cim_syss = self._c.Associators(
+ cim_rp.path,
+ ResultClass='CIM_ComputerSystem',
+ AssocClass='CIM_ElementConformsToProfile',
+ PropertyList=property_list)
+ # Any version of 'Array' profile can get us to root
+ # CIM_ComputerSystem. startup() already has checked the
+ # 1.4 version
+ break

# System URI Filtering
if self.system_list:
@@ -3614,7 +3513,8 @@ class Smis(IStorageAreaNetwork):
else:
return cim_syss

- def _get_cim_sys_by_id(self, system_id, property_list=None):
+
+ def _cim_sys_of_id(self, system_id, property_list=None):
"""
Return a CIMInstance of CIM_ComputerSystem for given system id.
"""
@@ -3626,15 +3526,8 @@ class Smis(IStorageAreaNetwork):
if pro not in property_list:
property_list.extend([pro])

- if self.fallback_mode:
- cim_syss = self._get_cim_syss_fallback(property_list)
- else:
- cim_syss = self._get_cim_syss(
- Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False,
- property_list=property_list,
- raise_error=True)
+ cim_syss = self._root_cim_syss(property_list)
+
for cim_sys in cim_syss:
if self._sys_id(cim_sys) == system_id:
return cim_sys
--
1.8.3.1
Tony Asleson
2014-05-21 18:50:33 UTC
Permalink
Gris,

When running this against providers I don't get any errors, however with
this patch we no long return any disks for arrays that we previously did.

Thanks,
Tony
Post by Gris Ge
* Convert SMI-S SPEC version into integer for better comparison.
Please check _spec_ver_str_to_num() for detail.
* Let _root_cim_syss() handle the fall back checking. It will return a list
of CIM_ComputerSystem for fallback mode or not.
* Checking for 1.4 'Array' profile support in startup().
As 'Block Services Package' (AKA: BSP) is mandatory for that profile, we
don't do extra check in methods using BSP profile.
* Noting down the method naming scheme for consistency.
* Move SNIA related constants to a standalone class SNIA which shorter the
constant variable name.
* _profile_is_supported() now support raise error if not found.
* Split _cim_sys_of_id() out to raise LsmError ErrorNumber.NOT_FOUND_SYSTEM.
* Add RegisteredOrganization checking in CIM_RegisteredProfile.
* In case fallmode facing 'multiple system' profile supported array,
CIM_StorageConfigurationService -> ComputerSystem
* Add author names.
* Removed un-needed check. The startup() already checked the support of
'Array' profile.
* Fix the incorrect fallback_mode variable used in disks()
---
plugin/smispy/smis.py | 527 ++++++++++++++++++++------------------------------
1 file changed, 210 insertions(+), 317 deletions(-)
diff --git a/plugin/smispy/smis.py b/plugin/smispy/smis.py
index c63d8cd..d60dbd2 100644
--- a/plugin/smispy/smis.py
+++ b/plugin/smispy/smis.py
@@ -13,6 +13,9 @@
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
# USA
+#
+# Author: tasleson
from string import split
import time
@@ -32,11 +35,22 @@ from lsm import (IStorageAreaNetwork, Error, uri_parse, LsmError, ErrorNumber,
# cim_pool CIM_StoragePool
# cim_scs CIM_StorageConfigurationService
# cim_vol CIM_StorageVolume
+# cim_rp CIM_RegisteredProfile
#
# sys Object of LSM System
# pool Object of LSM Pool
# vol Object of LSM Volume
+# _cim_xxx()
+# Return CIMInstance without any Associators() call.
+# _cim_xxx_of(cim_yyy)
+# Return CIMInstance associated to cim_yyy
+# _adj_cim_xxx()
+# Retrun CIMInstance with 'adj' only
+# _cim_xxx_of_id(some_id)
+# Return CIMInstance for given ID
+
traceback.format_exc())
return cim_wrapper
+ """
+ Convert version string stored in CIM_RegisteredProfile to a integer.
+ "1.5.1" -> 1,005,001
+ """
+ tmp_list = [0,0,0]
+ tmp_list = spec_ver_str.split(".")
+ tmp_list.extend([0])
+ return (int(tmp_list[0]) * 10 ** 6 +
+ int(tmp_list[1]) * 10 ** 3 +
+ int(tmp_list[2]))
+ return None
+
+ BLK_ROOT_PROFILE = 'Array'
+ BLK_SRVS_PROFILE = 'Block Services'
+ DISK_LITE_PROFILE = 'Disk Drive Lite'
+ MULTI_SYS_PROFILE = 'Multiple Computer System'
+ SMIS_SPEC_VER_1_4 ='1.4'
+ SMIS_SPEC_VER_1_5 ='1.5'
+ SMIS_SPEC_VER_1_6 ='1.6'
+ REG_ORG_CODE = pywbem.Uint16(11)
+
"""
# DSP 1033 Profile Registration
DMTF_INTEROP_NAMESPACES = ['interop', 'root/interop']
SMIS_DEFAULT_NAMESPACE = 'interop'
- SNIA_BLK_ROOT_PROFILE = 'Array'
- SNIA_BLK_SRVS_PROFILE = 'Block Services'
- SNIA_DISK_LITE_PROFILE = 'Disk Drive Lite'
- SNIA_MULTI_SYS_PROFILE = 'Multiple Computer System'
- SNIA_SMIS_SPEC_VER_1_4='1.4'
- SNIA_SMIS_SPEC_VER_1_5='1.5'
- SNIA_SMIS_SPEC_VER_1_6='1.6'
IAAN_WBEM_HTTP_PORT = 5988
IAAN_WBEM_HTTPS_PORT = 5989
self._c = None
self.tmo = 0
self.system_list = None
- self.cim_reg_profiles = []
+ self.cim_rps = []
self.cim_root_profile_dict = dict()
self.fallback_mode = True # Means we cannot use profile register
- self.cim_reg_profiles = self._c.EnumerateInstances(
+ self.cim_rps = self._c.EnumerateInstances(
'CIM_RegisteredProfile',
namespace=interop_namespace,
- PropertyList=['RegisteredName', 'RegisteredVersion'],
+ PropertyList=['RegisteredName', 'RegisteredVersion',
+ 'RegisteredOrganization'],
LocalOnly=False)
break
self.fallback_mode = False
# Support 'Array' profile is step 0 for this whole plugin.
# We find out all 'Array' CIM_RegisteredProfile and stored
# them into self.cim_root_profile_dict
- if 'RegisteredName' not in cim_reg_profile or \
- continue
- if cim_reg_profile['RegisteredName'] == \
- ver = cim_reg_profile['RegisteredVersion']
- self.cim_root_profile_dict[ver]= cim_reg_profile
+ if not self._profile_is_supported(
+ SNIA.BLK_ROOT_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4,
raise LsmError(ErrorNumber.NO_SUPPORT,
- "SMI-S provider does not support 'Array'"
- "profile which is prerequisite")
+ "SMI-S provider does not support "
+ "SNIA SMI-S SPEC %s '%s' profile" %
+ (SNIA.SMIS_SPEC_VER_1_4,
+ SNIA.BLK_ROOT_PROFILE))
if e[0] == pywbem.CIM_ERR_NOT_SUPPORTED or \
# Get the cim object that represents the system
cim_sys = None
cim_pcms = None
+ cim_sys = self._cim_sys_of_id(system.id)
- cim_sys = self._get_cim_syss_fallback(
- sys_id=system.id,
- property_list=[])[0] # Surely, we will get at least one
- # cim_sys since LSM system already
- # provided.
# Using 'ExposePathsSupported of
# CIM_ProtocolControllerMaskingCapabilities
cap.set(Capabilities.ACCESS_GROUP_DEL_INITIATOR)
return
- cim_syss = self._get_cim_syss(
- Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- sys_id=system.id,
- property_list=[])
- # we might not get any cim_sys on unsupported system.
- cim_sys = cim_syss[0]
- # CIM_ControllerConfigurationService is mandatory
- # and it's ExposePaths() and HidePaths() are mandatory
- cap.set(Capabilities.ACCESS_GROUP_LIST)
- cap.set(Capabilities.ACCESS_GROUP_GRANT)
- cap.set(Capabilities.ACCESS_GROUP_REVOKE)
- cap.set(Capabilities.ACCESS_GROUP_ADD_INITIATOR)
- cap.set(Capabilities.ACCESS_GROUP_DEL_INITIATOR)
- cap.set(Capabilities.ACCESS_GROUPS_GRANTED_TO_VOLUME)
- cap.set(Capabilities.VOLUMES_ACCESSIBLE_BY_ACCESS_GROUP)
- return
+ # CIM_ControllerConfigurationService is mandatory
+ # and it's ExposePaths() and HidePaths() are mandatory
+ cap.set(Capabilities.ACCESS_GROUP_LIST)
+ cap.set(Capabilities.ACCESS_GROUP_GRANT)
+ cap.set(Capabilities.ACCESS_GROUP_REVOKE)
+ cap.set(Capabilities.ACCESS_GROUP_ADD_INITIATOR)
+ cap.set(Capabilities.ACCESS_GROUP_DEL_INITIATOR)
+ cap.set(Capabilities.ACCESS_GROUPS_GRANTED_TO_VOLUME)
+ cap.set(Capabilities.VOLUMES_ACCESSIBLE_BY_ACCESS_GROUP)
cap = Capabilities()
|
v
CIM_StorageVolume
+ As 'Block Services Package' is mandatory for 'Array' profile, we
+ don't check support status here as startup() already checked 'Array'
+ profile.
"""
rc = []
cim_syss = []
cim_sys_pros = self._property_list_of_id("System")
- cim_syss = self._get_cim_syss_fallback(property_list=cim_sys_pros)
- cim_syss = self._get_cim_syss(
- Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False,
- property_list=cim_sys_pros,
- raise_error=True)
+
+ cim_syss = self._root_cim_syss(cim_sys_pros)
cim_vol_pros = self._new_vol_cim_vol_pros()
sys_id = self._sys_id(cim_sys)
|
v
CIM_StoragePool
+ As 'Block Services Package' is mandatory for 'Array' profile, we
+ don't check support status here as startup() already checked 'Array'
+ profile.
"""
rc = []
cim_pool_pros = self._new_pool_cim_pool_pros(
flags == Pool.RETRIEVE_FULL_INFO)
cim_sys_pros = self._property_list_of_id("System")
- cim_syss = []
- cim_syss = self._get_cim_syss_fallback(property_list=cim_sys_pros)
- cim_syss = self._get_cim_syss(
- Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False,
- property_list=cim_sys_pros,
- raise_error=True)
+ cim_syss = self._root_cim_syss(cim_sys_pros)
system_id = self._sys_id(cim_sys)
"""
Return the storage arrays accessible from this plug-in at this time
+
+ As 'Block Services Package' is mandatory for 'Array' profile, we
+ don't check support status here as startup() already checked 'Array'
+ profile.
"""
cim_sys_pros = self._cim_sys_pros()
- cim_syss = self._get_cim_syss_fallback(property_list=cim_sys_pros)
- cim_syss = self._get_cim_syss(
- Smis.SNIA_BLK_ROOT_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False,
- property_list=cim_sys_pros,
- raise_error=True)
-
- return []
+ cim_syss = self._root_cim_syss(cim_sys_pros)
+
return [Smis._cim_sys_2_lsm_sys(s) for s in cim_syss]
rc = []
cim_syss = []
cim_sys_pros = self._property_list_of_id("System")
- cim_syss = self._get_cim_syss_fallback(property_list=cim_sys_pros)
- cim_syss = self._get_cim_syss(
- Smis.SNIA_DISK_LITE_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False,
- property_list=cim_sys_pros,
- raise_error=True)
-
- flag_multi_sys = None
- flag_multi_sys = self._profile_is_supported(
- Smis.SNIA_MULTI_SYS_PROFILE, Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False)
- # In SNIA SMI-S 1.6rev4 Common Book,
- # 30.1.5 Associations between ComputerSystems and other Logical
- # Elements
- # "If the device may become unavailable while the system as a
- # whole remains available, the device shall be associated to a
- # non-top-level system that has availability equivalent to the
- # device. This system could be a real system or a system in an
- # intermediate tier (representing some redundancy less than full
- # redundancy)."
-
- # Hence DiskDrive might not associated to top level
- # CIM_ComputerSystem
+ self._profile_is_supported(SNIA.DISK_LITE_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4,
+ strict=False,
+ raise_error=True)
+
+ # In SNIA SMI-S 1.6rev4 Common Book,
+ # 30.1.5 Associations between ComputerSystems and other Logical
+ # Elements
+ # "If the device may become unavailable while the system as a
+ # whole remains available, the device shall be associated to a
+ # non-top-level system that has availability equivalent to the
+ # device. This system could be a real system or a system in an
+ # intermediate tier (representing some redundancy less than full
+ # redundancy)."
+
+ # Hence DiskDrive might not associated to top level
+ # CIM_ComputerSystem
+ flag_multi_sys = None
+ if not self.fallback_mode and \
+ self._profile_is_supported(SNIA.MULTI_SYS_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4,
+ strict=False,
+ flag_multi_sys = True
cim_disk_pros = Smis._new_disk_cim_disk_pros(flags)
"""
cim_sys_pros = self._property_list_of_id("System")
if not self.fallback_mode and \
- self._profile_is_supported(Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
+ self._profile_is_supported(SNIA.BLK_SRVS_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4,
raise LsmError(ErrorNumber.NO_SUPPORT,
"SMI-S %s version %s is not supported" %
- (Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4))
+ (SNIA.BLK_SRVS_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4))
- cim_sys = self._get_cim_sys_by_id(pool.system_id)
+ cim_sys = self._cim_sys_of_id(pool.system_id)
cim_pool = self._get_cim_pool_by_id(cim_sys.path, pool.id)
cim_scs = self._get_cim_scs(cim_sys.path)
CreateOrModifyStoragePool()
"""
if not self.fallback_mode and \
- self._profile_is_supported(Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
+ self._profile_is_supported(SNIA.BLK_SRVS_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4,
raise LsmError(ErrorNumber.NO_SUPPORT,
"SMI-S %s version %s is not supported" %
- (Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4))
+ (SNIA.BLK_SRVS_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4))
- cim_sys = self._get_cim_sys_by_id(system.id)
+ cim_sys = self._cim_sys_of_id(system.id)
# we does not support defining thinp_type yet.
# just using whatever provider set.
"CIM_StorageConfigurationService of " +
"CIM_ComputerSystem %s" % cim_sys_path)
+ def _profile_is_supported(self, profile_name, spec_ver, strict=False,
"""
Check whether we support certain profile at certain SNIA
specification version.
- When strict == False(default), profile spec version newer than
- require spec_ver will also be consider as found.
+ When strict == False(default), profile spec version later or equal
+ than require spec_ver will also be consider as found.
When strict == True, only defined spec_version is allowed.
+ Require self.cim_rps containing all CIM_RegisteredProfile
+ Will raise LsmError(ErrorNumber.NO_SUPPORT, 'xxx') if raise_error
+ is True when nothing found.
- profile_name # Smis.SNIA_REGISTERED_PROFILE_XXX
- spec_ver # Smis.SNIA_SMIS_SPEC_VER_XXX
- property_list # a list of properties should contained in
- # returned CIM_ComputerSystem
- # When property_list == None, we retrieve full
- # data, when property_list == [], we retrieve
- # nothing but a CIMInstanceName.
+ profile_name # SNIA.XXXX_PROFILE
+ spec_ver # SNIA.SMIS_SPEC_VER_XXX
strict # False or True. If True, only defined
# spec_version is consider as supported
# If false, will return the maximum version of
# spec.
+ raise_error # Raise LsmError if not found
None # Not supported.
or
- spec_version # the vendor implemented version. like '1.4.1'
- # This is a string, NOT float.
- """
- max_spec_ver = 0
- max_spec_ver_flt = 0
- # assuming spec_ver is well formatted, since we are internal
- # method, we can do that guess.
- req_ver_main = spec_ver.split('.')[0]
- req_ver_sub = spec_ver.split('.')[1]
-
- if 'RegisteredName' not in cim_reg_profile or \
+ spec_int # Integer. Converted by _spec_ver_str_to_num()
+ """
+ req_ver = _spec_ver_str_to_num(spec_ver)
+
+ max_spec_ver_str = None
+ max_spec_ver = None
+ if 'RegisteredName' not in cim_rp or \
continue
# check spec version
- cur_ver = cim_reg_profile['RegisteredVersion']
- cur_ver_list = cur_ver.split('.')
- continue
- cur_ver_flt = float("%s.%s" % tuple(cur_ver_list[0:2]))
- req_ver_flt = float("%s.%s" % (req_ver_main, req_ver_sub))
+ cur_ver = _spec_ver_str_to_num(cim_rp['RegisteredVersion'])
return cur_ver
-
+ if max_spec_ver is None or \
max_spec_ver = cur_ver
- max_spec_ver_flt = cur_ver_flt
+ max_spec_ver_str = cim_rp['RegisteredVersion']
+ raise LsmError(ErrorNumber.NO_SUPPORT,
+ "SNIA SMI-S %s '%s' profile is not supported" %
+ (spec_ver, profile_name))
- return None
return max_spec_ver
- def _get_cim_syss(self, profile_name, spec_ver, property_list=None,
"""
- Check whether we support certain profile at certain SNIA
- specification version.
- When strict == False(default), profile spec version newer than
- require spec_ver will also be consider as found.
- When strict == True, only defined spec_version is allowed.
+ For fallback mode, this just enumerate CIM_ComputerSystem.
+ We require vendor to implement profile registration when using
+ "Multiple System Profile".
+ For normal mode, this just find out the root CIM_ComputerSystem
CIM_RegisteredProfile # Root Profile('Array') in interop
|
| CIM_ElementConformsToProfile
v
CIM_ComputerSystem # vendor namespace
- We depend on self.cim_reg_profiles which was updated by startup().
- But this method does not check it, you should check
- self.fallback_mode == True before call this method.
-
- Please use constant spec_ver and profile_name for better
- code management.
- We also apply to system filter in URI which is stored in
- self.system_list
- When returning None, it means current provider does not support
- requested profile or version.
- profile_name # Smis.SNIA_REGISTERED_PROFILE_XXX
- spec_ver # Smis.SNIA_SMIS_SPEC_VER_XXX
- property_list # a list of properties should contained in
- # returned CIM_ComputerSystem
- # When property_list == None, we retrieve full
- # data, when property_list == [], we retrieve
- # nothing but a CIMInstanceName.
- strict # False or True. If True, only defined
- # spec_version is consider as supported
- sys_id # Only return CIM_ComputerSystem for certain
- # system ID.
- cim_syss # a list of CIMInstanceName of CIM_ComputerSystem
- or
- None # Current SMI-S provider does not support this
- # profile at certain version.
- """
- max_spec_ver = self._profile_is_supported(
- profile_name, spec_ver, strict)
-
- error_msg = ("Current SMI-S provider does not support "
- "SMI-S %s profile, version %s" %
- (profile_name, spec_ver))
- error_msg = "%s(or later version)" % error_msg
- raise LsmError(ErrorNumber.NO_SUPPORT, error_msg)
- return None
-
- raise LsmError(ErrorNumber.INTERNAL_ERROR,
- "Failed to find out CIM_RegisteredProfile " +
- "for profile %s with version %s " %
- (Smis.SNIA_BLK_ROOT_PROFILE, max_spec_ver) +
- "even its subprofile found.")
-
- cim_root_profile = self.cim_root_profile_dict[max_spec_ver]
-
- cim_syss = self._c.Associators(
- cim_root_profile.path,
- ResultClass='CIM_ComputerSystem',
- AssocClass='CIM_ElementConformsToProfile')
- sys_id_pros = self._property_list_of_id('System')
- property_list.extend([key])
- cim_syss = self._c.Associators(
- cim_root_profile.path,
- ResultClass='CIM_ComputerSystem',
- AssocClass='CIM_ElementConformsToProfile',
- PropertyList=property_list)
-
- return cim_syss
-
- # Method level filter
- return [s for s in cim_syss if self._sys_id(s) == sys_id][0]
-
- # Apply URI system filter
- needed_cim_syss = []
- needed_cim_syss.extend([cim_sys])
- return needed_cim_syss
-
- """
- CIM_StorageConfigurationService # Enumerate
- |
- | CIM_HostedService
- v
- CIM_ComputerSystem
- If CIM_StorageConfigurationService is not support neither,
- we enumerate CIM_ComputerSystem.
- property_list # a list of properties should contained in
- # returned CIM_ComputerSystem
- # When property_list == None, we retrieve full
- # data, when property_list == [], we retrieve
- # nothing but a CIMInstanceName.
- cim_syss # A list of CIMInstanceName of CIM_ComputerSystem
- or
- None
+ We also assume no matter which version of root profile can lead to
+ the same CIM_ComputerSystem instance.
+ As CIM_ComputerSystem has no property indicate SNIA SMI-S version,
+ this is assumption should work. Tested on EMC SMI-S provider which
+ provide 1.4, 1.5, 1.6 root profile.
"""
- sys_id_pros = self._property_list_of_id('System')
- flag_full_info = False
+ cim_sys_id_pros = self._property_list_of_id('System')
- flag_full_info = True
+ property_list = cim_sys_id_pros
- property_list.extend([key])
+ property_list.extend([key_name])
cim_syss = []
- cim_scss_path = []
- # Note: Please be informed, if PropertyList is an empty list,
- # XIV will return NOTHING, so use EnumerateInstanceNames()
- # when you need nothing but the CIMInstanceName
- cim_scss_path = self._c.EnumerateInstanceNames(
- 'CIM_StorageConfigurationService')
- # If array does not support CIM_StorageConfigurationService
- # we use CIM_ComputerSystem which is mandatory.
- # We might get some non-storage array listed as system.
- # but we would like to take that risk instead of
- # skipping basic support of old SMIS provider.
- cim_syss = self._c.EnumerateInstances(
- 'CIM_ComputerSystem', LocalOnly=False)
- cim_syss = self._c.EnumerateInstances(
- 'CIM_ComputerSystem',
- PropertyList=property_list,
- LocalOnly=False)
- raise e
- cim_tmp = None
- cim_tmp = self._c.Associators(
- cim_scs_path,
- AssocClass='CIM_HostedService',
- ResultClass='CIM_ComputerSystem')
+ # CIM_StorageConfigurationService # Enumerate
+ # |
+ # | CIM_HostedService
+ # v
+ # CIM_ComputerSystem
+ # If CIM_StorageConfigurationService is not support neither,
+ # we enumerate CIM_ComputerSystem.
+ cim_scss_path = self._c.EnumerateInstanceNames(
+ 'CIM_StorageConfigurationService')
+ # If array does not support CIM_StorageConfigurationService
+ # we use CIM_ComputerSystem which is mandatory.
+ # We might get some non-storage array listed as system.
+ # but we would like to take that risk instead of
+ # skipping basic support of old SMIS provider.
+ cim_syss = self._c.EnumerateInstances(
+ 'CIM_ComputerSystem',
+ PropertyList=property_list,
+ LocalOnly=False)
+ raise e
+
+ cim_tmp = None
+ # CIM_ComputerSystem is one-one map to
+ # CIM_StorageConfigurationService
cim_tmp = self._c.Associators(
cim_scs_path,
AssocClass='CIM_HostedService',
ResultClass='CIM_ComputerSystem',
PropertyList=property_list)
- cim_syss.extend([cim_tmp[0]])
-
- # Method level filter
- return [s for s in cim_syss if self._sys_id(s) == sys_id]
+ cim_syss.extend([cim_tmp[0]])
+ if cim_rp['RegisteredName'] == SNIA.BLK_ROOT_PROFILE and\
+ cim_syss = self._c.Associators(
+ cim_rp.path,
+ ResultClass='CIM_ComputerSystem',
+ AssocClass='CIM_ElementConformsToProfile',
+ PropertyList=property_list)
+ # Any version of 'Array' profile can get us to root
+ # CIM_ComputerSystem. startup() already has checked the
+ # 1.4 version
+ break
# System URI Filtering
return cim_syss
+
"""
Return a CIMInstance of CIM_ComputerSystem for given system id.
"""
property_list.extend([pro])
- cim_syss = self._get_cim_syss_fallback(property_list)
- cim_syss = self._get_cim_syss(
- Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False,
- property_list=property_list,
- raise_error=True)
+ cim_syss = self._root_cim_syss(property_list)
+
return cim_sys
Gris Ge
2014-05-22 14:29:40 UTC
Permalink
Post by Tony Asleson
Gris,
When running this against providers I don't get any errors, however with
this patch we no long return any disks for arrays that we previously did.
Thanks,
Tony
Sorry, I missed to set cim_syss before calling out.

Please kindly try V5 patch again. It comes with better disk query way.

Thanks for test.
Best regards.
--
Gris Ge
Gris Ge
2014-05-22 14:27:53 UTC
Permalink
* Convert SMI-S SPEC version into integer for better comparison.
Please check _spec_ver_str_to_num() for detail.
* Let _root_cim_syss() handle the fall back checking. It will return a list
of CIM_ComputerSystem for fallback mode or not.
* Checking for 1.4 'Array' profile support in startup().
As 'Block Services Package' (AKA: BSP) is mandatory for that profile, we
don't do extra check in methods using BSP profile.
* Noting down the method naming scheme for consistency.
* Move SNIA related constants to a standalone class SNIA which shorter the
constant variable name.
* _profile_is_supported() now support raise error if not found.
* Split _cim_sys_of_id() out to raise LsmError ErrorNumber.NOT_FOUND_SYSTEM.
* Add RegisteredOrganization checking in CIM_RegisteredProfile.

Changes in V2:
* In case fallmode facing 'multiple system' profile supported array,
the _root_cim_syss() will use the old way to get top ComputerSystem:
CIM_StorageConfigurationService -> ComputerSystem
* Add author names.

Changes in V3:
* Removed un-needed check. The startup() already checked the support of
'Array' profile.

Changes in V4:
* Fix the incorrect fallback_mode variable used in disks()

Changes in V5:
* Use new way(Enumerate) for disk query. Better performance[1].
* Removed the unneeded methods _traverse_computer_sys().

[1] EMC VMAX with 64 disks, old way will take 4 minutes, new way only take 1.5
minutes. We might get better if we use DiskDriveView. Will check on that
later.

Signed-off-by: Gris Ge <***@redhat.com>
---
plugin/smispy/smis.py | 663 ++++++++++++++++++--------------------------------
1 file changed, 234 insertions(+), 429 deletions(-)

diff --git a/plugin/smispy/smis.py b/plugin/smispy/smis.py
index c63d8cd..23cc8ed 100644
--- a/plugin/smispy/smis.py
+++ b/plugin/smispy/smis.py
@@ -13,6 +13,9 @@
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
# USA
+#
+# Author: tasleson
+# Gris Ge <***@redhat.com>

from string import split
import time
@@ -32,11 +35,22 @@ from lsm import (IStorageAreaNetwork, Error, uri_parse, LsmError, ErrorNumber,
# cim_pool CIM_StoragePool
# cim_scs CIM_StorageConfigurationService
# cim_vol CIM_StorageVolume
+# cim_rp CIM_RegisteredProfile
#
# sys Object of LSM System
# pool Object of LSM Pool
# vol Object of LSM Volume

+## Method Naming schme:
+# _cim_xxx()
+# Return CIMInstance without any Associators() call.
+# _cim_xxx_of(cim_yyy)
+# Return CIMInstance associated to cim_yyy
+# _adj_cim_xxx()
+# Retrun CIMInstance with 'adj' only
+# _cim_xxx_of_id(some_id)
+# Return CIMInstance for given ID
+

def handle_cim_errors(method):
def cim_wrapper(*args, **kwargs):
@@ -65,6 +79,32 @@ def handle_cim_errors(method):
traceback.format_exc())
return cim_wrapper

+def _spec_ver_str_to_num(spec_ver_str):
+ """
+ Convert version string stored in CIM_RegisteredProfile to a integer.
+ Example:
+ "1.5.1" -> 1,005,001
+ """
+ tmp_list = [0,0,0]
+ tmp_list = spec_ver_str.split(".")
+ if len(tmp_list) == 2:
+ tmp_list.extend([0])
+ if len(tmp_list) == 3:
+ return (int(tmp_list[0]) * 10 ** 6 +
+ int(tmp_list[1]) * 10 ** 3 +
+ int(tmp_list[2]))
+ return None
+
+class SNIA(object):
+ BLK_ROOT_PROFILE = 'Array'
+ BLK_SRVS_PROFILE = 'Block Services'
+ DISK_LITE_PROFILE = 'Disk Drive Lite'
+ MULTI_SYS_PROFILE = 'Multiple Computer System'
+ SMIS_SPEC_VER_1_4 ='1.4'
+ SMIS_SPEC_VER_1_5 ='1.5'
+ SMIS_SPEC_VER_1_6 ='1.6'
+ REG_ORG_CODE = pywbem.Uint16(11)
+

class Smis(IStorageAreaNetwork):
"""
@@ -252,13 +292,6 @@ class Smis(IStorageAreaNetwork):
# DSP 1033 Profile Registration
DMTF_INTEROP_NAMESPACES = ['interop', 'root/interop']
SMIS_DEFAULT_NAMESPACE = 'interop'
- SNIA_BLK_ROOT_PROFILE = 'Array'
- SNIA_BLK_SRVS_PROFILE = 'Block Services'
- SNIA_DISK_LITE_PROFILE = 'Disk Drive Lite'
- SNIA_MULTI_SYS_PROFILE = 'Multiple Computer System'
- SNIA_SMIS_SPEC_VER_1_4='1.4'
- SNIA_SMIS_SPEC_VER_1_5='1.5'
- SNIA_SMIS_SPEC_VER_1_6='1.6'

IAAN_WBEM_HTTP_PORT = 5988
IAAN_WBEM_HTTPS_PORT = 5989
@@ -350,7 +383,7 @@ class Smis(IStorageAreaNetwork):
self._c = None
self.tmo = 0
self.system_list = None
- self.cim_reg_profiles = []
+ self.cim_rps = []
self.cim_root_profile_dict = dict()
self.fallback_mode = True # Means we cannot use profile register

@@ -553,39 +586,37 @@ class Smis(IStorageAreaNetwork):
u['parameters']['namespace'] not in namespace_check_list:
namespace_check_list.extend([u['parameters']['namespace']])

- try:
- for interop_namespace in Smis.DMTF_INTEROP_NAMESPACES:
- self.cim_reg_profiles = self._c.EnumerateInstances(
+ for interop_namespace in Smis.DMTF_INTEROP_NAMESPACES:
+ try:
+ self.cim_rps = self._c.EnumerateInstances(
'CIM_RegisteredProfile',
namespace=interop_namespace,
- PropertyList=['RegisteredName', 'RegisteredVersion'],
+ PropertyList=['RegisteredName', 'RegisteredVersion',
+ 'RegisteredOrganization'],
LocalOnly=False)
- if len(self.cim_reg_profiles) != 0:
- break
+ except CIMError as e:
+ if e[0] == pywbem.CIM_ERR_NOT_SUPPORTED or \
+ e[0] == pywbem.CIM_ERR_INVALID_NAMESPACE:
+ pass
+ else:
+ raise e
+ if len(self.cim_rps) != 0:
+ break

- if len(self.cim_reg_profiles) >= 1:
- self.fallback_mode = False
- # Support 'Array' profile is step 0 for this whole plugin.
- # We find out all 'Array' CIM_RegisteredProfile and stored
- # them into self.cim_root_profile_dict
- for cim_reg_profile in self.cim_reg_profiles:
- if 'RegisteredName' not in cim_reg_profile or \
- 'RegisteredVersion' not in cim_reg_profile:
- continue
- if cim_reg_profile['RegisteredName'] == \
- Smis.SNIA_BLK_ROOT_PROFILE:
- ver = cim_reg_profile['RegisteredVersion']
- self.cim_root_profile_dict[ver]= cim_reg_profile
- if len(self.cim_root_profile_dict) == 0:
- raise LsmError(ErrorNumber.NO_SUPPORT,
- "SMI-S provider does not support 'Array'"
- "profile which is prerequisite")
- except CIMError as e:
- if e[0] == pywbem.CIM_ERR_NOT_SUPPORTED or \
- e[0] == pywbem.CIM_ERR_INVALID_NAMESPACE:
- pass # AFAIK, only LSI does not support RegisteredProfile
- else:
- raise e
+ if len(self.cim_rps) >= 1:
+ self.fallback_mode = False
+ # Support 'Array' profile is step 0 for this whole plugin.
+ # We find out all 'Array' CIM_RegisteredProfile and stored
+ # them into self.cim_root_profile_dict
+ if not self._profile_is_supported(
+ SNIA.BLK_ROOT_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4,
+ strict=False):
+ raise LsmError(ErrorNumber.NO_SUPPORT,
+ "SMI-S provider does not support "
+ "SNIA SMI-S SPEC %s '%s' profile" %
+ (SNIA.SMIS_SPEC_VER_1_4,
+ SNIA.BLK_ROOT_PROFILE))

def time_out_set(self, ms, flags=0):
self.tmo = ms
@@ -720,12 +751,8 @@ class Smis(IStorageAreaNetwork):
# Get the cim object that represents the system
cim_sys = None
cim_pcms = None
+ cim_sys = self._cim_sys_of_id(system.id)
if self.fallback_mode:
- cim_sys = self._get_cim_syss_fallback(
- sys_id=system.id,
- property_list=[])[0] # Surely, we will get at least one
- # cim_sys since LSM system already
- # provided.

# Using 'ExposePathsSupported of
# CIM_ProtocolControllerMaskingCapabilities
@@ -752,26 +779,16 @@ class Smis(IStorageAreaNetwork):
cap.set(Capabilities.ACCESS_GROUP_DEL_INITIATOR)
return
else:
- cim_syss = self._get_cim_syss(
- Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- sys_id=system.id,
- property_list=[])
- # we might not get any cim_sys on unsupported system.
- if len(cim_syss) == 1:
- cim_sys = cim_syss[0]
- # Since SNIA SMI-S 1.4rev6:
- # CIM_ControllerConfigurationService is mandatory
- # and it's ExposePaths() and HidePaths() are mandatory
- cap.set(Capabilities.ACCESS_GROUP_LIST)
- cap.set(Capabilities.ACCESS_GROUP_GRANT)
- cap.set(Capabilities.ACCESS_GROUP_REVOKE)
- cap.set(Capabilities.ACCESS_GROUP_ADD_INITIATOR)
- cap.set(Capabilities.ACCESS_GROUP_DEL_INITIATOR)
- cap.set(Capabilities.ACCESS_GROUPS_GRANTED_TO_VOLUME)
- cap.set(Capabilities.VOLUMES_ACCESSIBLE_BY_ACCESS_GROUP)
- else:
- return
+ # Since SNIA SMI-S 1.4rev6:
+ # CIM_ControllerConfigurationService is mandatory
+ # and it's ExposePaths() and HidePaths() are mandatory
+ cap.set(Capabilities.ACCESS_GROUP_LIST)
+ cap.set(Capabilities.ACCESS_GROUP_GRANT)
+ cap.set(Capabilities.ACCESS_GROUP_REVOKE)
+ cap.set(Capabilities.ACCESS_GROUP_ADD_INITIATOR)
+ cap.set(Capabilities.ACCESS_GROUP_DEL_INITIATOR)
+ cap.set(Capabilities.ACCESS_GROUPS_GRANTED_TO_VOLUME)
+ cap.set(Capabilities.VOLUMES_ACCESSIBLE_BY_ACCESS_GROUP)

def _common_capabilities(self, system):
cap = Capabilities()
@@ -1283,19 +1300,13 @@ class Smis(IStorageAreaNetwork):
|
v
CIM_StorageVolume
+ As 'Block Services Package' is mandatory for 'Array' profile, we
+ don't check support status here as startup() already checked 'Array'
+ profile.
"""
rc = []
- cim_syss = []
cim_sys_pros = self._property_list_of_id("System")
- if self.fallback_mode:
- cim_syss = self._get_cim_syss_fallback(property_list=cim_sys_pros)
- else:
- cim_syss = self._get_cim_syss(
- Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False,
- property_list=cim_sys_pros,
- raise_error=True)
+ cim_syss = self._root_cim_syss(cim_sys_pros)
cim_vol_pros = self._new_vol_cim_vol_pros()
for cim_sys in cim_syss:
sys_id = self._sys_id(cim_sys)
@@ -1405,22 +1416,16 @@ class Smis(IStorageAreaNetwork):
|
v
CIM_StoragePool
+ As 'Block Services Package' is mandatory for 'Array' profile, we
+ don't check support status here as startup() already checked 'Array'
+ profile.
"""
rc = []
cim_pool_pros = self._new_pool_cim_pool_pros(
flags == Pool.RETRIEVE_FULL_INFO)

cim_sys_pros = self._property_list_of_id("System")
- cim_syss = []
- if self.fallback_mode:
- cim_syss = self._get_cim_syss_fallback(property_list=cim_sys_pros)
- else:
- cim_syss = self._get_cim_syss(
- Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False,
- property_list=cim_sys_pros,
- raise_error=True)
+ cim_syss = self._root_cim_syss(cim_sys_pros)

for cim_sys in cim_syss:
system_id = self._sys_id(cim_sys)
@@ -1535,20 +1540,14 @@ class Smis(IStorageAreaNetwork):
def systems(self, flags=0):
"""
Return the storage arrays accessible from this plug-in at this time
+
+ As 'Block Services Package' is mandatory for 'Array' profile, we
+ don't check support status here as startup() already checked 'Array'
+ profile.
"""
cim_sys_pros = self._cim_sys_pros()
- if self.fallback_mode:
- cim_syss = self._get_cim_syss_fallback(property_list=cim_sys_pros)
- else:
- cim_syss = self._get_cim_syss(
- Smis.SNIA_BLK_ROOT_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False,
- property_list=cim_sys_pros,
- raise_error=True)
-
- if cim_syss is None:
- return []
+ cim_syss = self._root_cim_syss(cim_sys_pros)
+
return [Smis._cim_sys_2_lsm_sys(s) for s in cim_syss]

def _new_init(self, cim_st_hwid):
@@ -2211,139 +2210,44 @@ class Smis(IStorageAreaNetwork):
CIM_PhysicalPackage
CIM_DiskDrive
CIM_StorageExtent (Primordial)
- Association Procedure:
-
- CIM_ComputerSystem
- |
- | (CIM_SystemDevice)
- |
- v
- CIM_DiskDrive
-
- If 'Multiple Computer System Subprofile' is supported,
- we run above association on every CIM_ComputerSystem.
- Leaf CIM_ComputerSystem was found via:
-
- CIM_ComputerSystem # Root
- |
- | CIM_ConcreteIdentity
- |
- v
- CIM_RedundancySet <-----------------+
- | |
- | CIM_MemberOfCollection |
- | | CIM_ConcreteIdentity
- v |
- CIM_ComputerSystem # Leaf |
- | |
- +---------------------------+
-
- Will try these steps to find out disk infomation:
- 1. Find out all associated disks: 'CIM_DiskDrive'.
- 2. Find out all association storage extension: 'CIM_StorageExtent'.
- 3. We will use vendor specific way for all workarounds.
+ Due to 'Multiple Computer System' profile, disks might assocated to
+ sub ComputerSystem. To improve profromance of listing disks, we will
+ use EnumerateInstances(). Which means we have to filter the results
+ by ourself in case URI contain 'system=xxx'.
"""
rc = []
- cim_syss = []
cim_sys_pros = self._property_list_of_id("System")
- if self.fallback_mode:
- cim_syss = self._get_cim_syss_fallback(property_list=cim_sys_pros)
- else:
- cim_syss = self._get_cim_syss(
- Smis.SNIA_DISK_LITE_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False,
- property_list=cim_sys_pros,
- raise_error=True)
-
- flag_multi_sys = None
if not self.fallback_mode:
- flag_multi_sys = self._profile_is_supported(
- Smis.SNIA_MULTI_SYS_PROFILE, Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False)
- # In SNIA SMI-S 1.6rev4 Common Book,
- # 30.1.5 Associations between ComputerSystems and other Logical
- # Elements
- # "If the device may become unavailable while the system as a
- # whole remains available, the device shall be associated to a
- # non-top-level system that has availability equivalent to the
- # device. This system could be a real system or a system in an
- # intermediate tier (representing some redundancy less than full
- # redundancy)."
-
- # Hence DiskDrive might not associated to top level
- # CIM_ComputerSystem
+ self._profile_is_supported(SNIA.DISK_LITE_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4,
+ strict=False,
+ raise_error=True)
+ cim_syss = self._root_cim_syss(cim_sys_pros)

- for cim_sys in cim_syss:
- cim_disk_pros = Smis._new_disk_cim_disk_pros(flags)
- cim_disks = self._c.Associators(cim_sys.path,
- AssocClass='CIM_SystemDevice',
- ResultClass='CIM_DiskDrive',
- PropertyList=cim_disk_pros)
- if flag_multi_sys is not None:
- # Checking Disks of sub level ComputerSystems.
- cim_sub_syss_path = self._traverse_computer_sys(cim_sys.path)
- for cim_sub_sys_path in cim_sub_syss_path:
- cim_sub_disks = self._c.Associators(
- cim_sub_sys_path,
- AssocClass='CIM_SystemDevice',
- ResultClass='CIM_DiskDrive',
- PropertyList=cim_disk_pros)
- if cim_sub_disks:
- cim_disks.extend(cim_sub_disks)
- # Clean up the duplicate as SNIA said DiskDrive can be
- # one to many in SNIA SMIS 1.6rev4 CommonProfile Book,
- # 30.1.5 Associations between ComputerSystems and other
- # Logical Elements, PDF Page 311.
- clean_up_dict = {}
- for cim_disk in cim_disks:
- clean_up_dict[self._disk_id(cim_disk)] = cim_disk
- cim_disks = clean_up_dict.values()
+ if len(cim_syss) < 1:
+ return []

- sys_id = self._sys_id(cim_sys)
+ all_vendor_namespaces = []
+ for cim_sys in cim_syss:
+ if cim_sys.path.namespace not in all_vendor_namespaces:
+ all_vendor_namespaces.extend([cim_sys.path.namespace])
+
+ cim_disk_pros = Smis._new_disk_cim_disk_pros(flags)
+ for vendor_namespace in all_vendor_namespaces:
+ cim_disks = self._c.EnumerateInstances(
+ 'CIM_DiskDrive',
+ namespace=vendor_namespace,
+ PropertyList=cim_disk_pros)
for cim_disk in cim_disks:
+ if self.system_list:
+ if self._sys_id_child(cim_disk) not in self.system_list:
+ continue
cim_ext_pros = Smis._new_disk_cim_ext_pros(flags)
cim_ext = self._pri_cim_ext_of_cim_disk(cim_disk.path,
cim_ext_pros)
- rc.extend(
- [self._new_disk(cim_disk, cim_ext, sys_id, flags)])
- return rc

- def _traverse_computer_sys(self, cim_sys_path):
- """
- Walk through the CIM_ComputerSystem based on SNIA SMI-S 1.6rev4
- CommonProfile Book, Multiple Computer System Subprofile
- Will return a array of CIM_InstanceName -- CIM_ComputerSystem
- Including the inter level CIM_ComputerSystem and botton leaf
- CIM_ComputerSystem, but not including the CIM_ComputerSystem provided.
- """
- cim_syss_path = []
- cim_re_sets_path = []
- try:
- cim_re_sets_path = self._c.AssociatorNames(
- cim_sys_path,
- AssocClass='CIM_ConcreteIdentity',
- ResultClass='CIM_RedundancySet')
- except CIMError as e:
- if e[0] == pywbem.CIM_ERR_INVALID_CLASS:
- return []
-
- if cim_re_sets_path:
- for cim_re_set_path in cim_re_sets_path:
- cim_cur_syss_path = self._c.AssociatorNames(
- cim_re_set_path,
- AssocClass='CIM_MemberOfCollection',
- ResultClass='CIM_ComputerSystem')
- if cim_cur_syss_path:
- cim_syss_path.extend(cim_cur_syss_path)
- # every CIM_RedundancySet should associated to a
- # CIM_ComputerSystem, so no else.
- for cim_sys_path in cim_cur_syss_path:
- cim_next_syss_path = self._traverse_computer_sys(
- cim_sys_path)
- if cim_next_syss_path:
- cim_syss_path.extend(cim_next_syss_path)
- return cim_syss_path
+ rc.extend([self._new_disk(cim_disk, cim_ext, flags)])
+ return rc

@staticmethod
def _new_disk_cim_disk_pros(flag=0):
@@ -2401,7 +2305,7 @@ class Smis(IStorageAreaNetwork):
Smis._DMTF_STAUTS_TO_DISK_STATUS_INFO[dmtf_status])
return (status, status_info)

- def _new_disk(self, cim_disk, cim_ext, sys_id, flag_full_info=0):
+ def _new_disk(self, cim_disk, cim_ext, flag_full_info=0):
"""
Takes a CIM_DiskDrive and CIM_StorageExtent, returns a lsm Disk
Assuming cim_disk and cim_ext already contained the correct
@@ -2413,6 +2317,7 @@ class Smis(IStorageAreaNetwork):
num_of_block = Disk.BLOCK_COUNT_NOT_FOUND
disk_type = Disk.DISK_TYPE_UNKNOWN
status_info = ''
+ sys_id = self._sys_id_child(cim_disk)

# These are mandatory
# we do not check whether they follow the SNIA standard.
@@ -3008,15 +2913,15 @@ class Smis(IStorageAreaNetwork):
"""
cim_sys_pros = self._property_list_of_id("System")
if not self.fallback_mode and \
- self._profile_is_supported(Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
+ self._profile_is_supported(SNIA.BLK_SRVS_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4,
strict=False) is None:
raise LsmError(ErrorNumber.NO_SUPPORT,
"SMI-S %s version %s is not supported" %
- (Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4))
+ (SNIA.BLK_SRVS_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4))

- cim_sys = self._get_cim_sys_by_id(pool.system_id)
+ cim_sys = self._cim_sys_of_id(pool.system_id)
cim_pool = self._get_cim_pool_by_id(cim_sys.path, pool.id)
cim_scs = self._get_cim_scs(cim_sys.path)

@@ -3039,15 +2944,15 @@ class Smis(IStorageAreaNetwork):
CreateOrModifyStoragePool()
"""
if not self.fallback_mode and \
- self._profile_is_supported(Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
+ self._profile_is_supported(SNIA.BLK_SRVS_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4,
strict=False) is None:
raise LsmError(ErrorNumber.NO_SUPPORT,
"SMI-S %s version %s is not supported" %
- (Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4))
+ (SNIA.BLK_SRVS_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4))

- cim_sys = self._get_cim_sys_by_id(system.id)
+ cim_sys = self._cim_sys_of_id(system.id)

# we does not support defining thinp_type yet.
# just using whatever provider set.
@@ -3371,238 +3276,144 @@ class Smis(IStorageAreaNetwork):
"CIM_StorageConfigurationService of " +
"CIM_ComputerSystem %s" % cim_sys_path)

- def _profile_is_supported(self, profile_name, spec_ver, strict=False):
+ def _profile_is_supported(self, profile_name, spec_ver, strict=False,
+ raise_error=False):
"""
Usage:
Check whether we support certain profile at certain SNIA
specification version.
- When strict == False(default), profile spec version newer than
- require spec_ver will also be consider as found.
+ When strict == False(default), profile spec version later or equal
+ than require spec_ver will also be consider as found.
When strict == True, only defined spec_version is allowed.
+ Require self.cim_rps containing all CIM_RegisteredProfile
+ Will raise LsmError(ErrorNumber.NO_SUPPORT, 'xxx') if raise_error
+ is True when nothing found.
Parameter:
- profile_name # Smis.SNIA_REGISTERED_PROFILE_XXX
- spec_ver # Smis.SNIA_SMIS_SPEC_VER_XXX
- property_list # a list of properties should contained in
- # returned CIM_ComputerSystem
- # When property_list == None, we retrieve full
- # data, when property_list == [], we retrieve
- # nothing but a CIMInstanceName.
+ profile_name # SNIA.XXXX_PROFILE
+ spec_ver # SNIA.SMIS_SPEC_VER_XXX
strict # False or True. If True, only defined
# spec_version is consider as supported
# If false, will return the maximum version of
# spec.
+ raise_error # Raise LsmError if not found
Returns:
None # Not supported.
or
- spec_version # the vendor implemented version. like '1.4.1'
- # This is a string, NOT float.
- """
- max_spec_ver = 0
- max_spec_ver_flt = 0
- # assuming spec_ver is well formatted, since we are internal
- # method, we can do that guess.
- req_ver_main = spec_ver.split('.')[0]
- req_ver_sub = spec_ver.split('.')[1]
-
- for cim_reg_profile in self.cim_reg_profiles:
- if 'RegisteredName' not in cim_reg_profile or \
- 'RegisteredVersion' not in cim_reg_profile:
+ spec_int # Integer. Converted by _spec_ver_str_to_num()
+ """
+ req_ver = _spec_ver_str_to_num(spec_ver)
+
+ max_spec_ver_str = None
+ max_spec_ver = None
+ for cim_rp in self.cim_rps:
+ if 'RegisteredName' not in cim_rp or \
+ 'RegisteredVersion' not in cim_rp:
continue
- if cim_reg_profile['RegisteredName'] == profile_name:
+ if cim_rp['RegisteredName'] == profile_name:
# check spec version
- cur_ver = cim_reg_profile['RegisteredVersion']
- cur_ver_list = cur_ver.split('.')
- if len(cur_ver_list) < 2:
- continue
- cur_ver_flt = float("%s.%s" % tuple(cur_ver_list[0:2]))
- req_ver_flt = float("%s.%s" % (req_ver_main, req_ver_sub))
+ cur_ver = _spec_ver_str_to_num(cim_rp['RegisteredVersion'])

- if strict and cur_ver_flt == req_ver_flt:
+ if strict and cur_ver == req_ver:
return cur_ver
-
- if strict is False and cur_ver_flt >= req_ver_flt:
- if cur_ver_flt > max_spec_ver_flt:
+ elif cur_ver >= req_ver:
+ if max_spec_ver is None or \
+ cur_ver > max_spec_ver:
max_spec_ver = cur_ver
- max_spec_ver_flt = cur_ver_flt
+ max_spec_ver_str = cim_rp['RegisteredVersion']
+ if (strict or max_spec_ver is None) and raise_error:
+ raise LsmError(ErrorNumber.NO_SUPPORT,
+ "SNIA SMI-S %s '%s' profile is not supported" %
+ (spec_ver, profile_name))

- if max_spec_ver == 0:
- return None
return max_spec_ver

- def _get_cim_syss(self, profile_name, spec_ver, property_list=None,
- strict=False, sys_id=None, raise_error=False):
+ def _root_cim_syss(self, property_list=None):
"""
- Usage:
- Check whether we support certain profile at certain SNIA
- specification version.
- When strict == False(default), profile spec version newer than
- require spec_ver will also be consider as found.
- When strict == True, only defined spec_version is allowed.
+ For fallback mode, this just enumerate CIM_ComputerSystem.
+ We require vendor to implement profile registration when using
+ "Multiple System Profile".
+ For normal mode, this just find out the root CIM_ComputerSystem
+ via:

- If found, follow this procedure to get CIM_ComputerSystem:
CIM_RegisteredProfile # Root Profile('Array') in interop
|
| CIM_ElementConformsToProfile
v
CIM_ComputerSystem # vendor namespace

- We depend on self.cim_reg_profiles which was updated by startup().
- But this method does not check it, you should check
- self.fallback_mode == True before call this method.
-
- Please use constant spec_ver and profile_name for better
- code management.
- We also apply to system filter in URI which is stored in
- self.system_list
- When returning None, it means current provider does not support
- requested profile or version.
- Parameter:
- profile_name # Smis.SNIA_REGISTERED_PROFILE_XXX
- spec_ver # Smis.SNIA_SMIS_SPEC_VER_XXX
- property_list # a list of properties should contained in
- # returned CIM_ComputerSystem
- # When property_list == None, we retrieve full
- # data, when property_list == [], we retrieve
- # nothing but a CIMInstanceName.
- strict # False or True. If True, only defined
- # spec_version is consider as supported
- sys_id # Only return CIM_ComputerSystem for certain
- # system ID.
- Returns:
- cim_syss # a list of CIMInstanceName of CIM_ComputerSystem
- or
- None # Current SMI-S provider does not support this
- # profile at certain version.
- """
- max_spec_ver = self._profile_is_supported(
- profile_name, spec_ver, strict)
-
- if max_spec_ver is None:
- if raise_error:
- error_msg = ("Current SMI-S provider does not support "
- "SMI-S %s profile, version %s" %
- (profile_name, spec_ver))
- if not strict:
- error_msg = "%s(or later version)" % error_msg
- raise LsmError(ErrorNumber.NO_SUPPORT, error_msg)
- else:
- return None
-
- if max_spec_ver not in self.cim_root_profile_dict.keys():
- raise LsmError(ErrorNumber.INTERNAL_ERROR,
- "Failed to find out CIM_RegisteredProfile " +
- "for profile %s with version %s " %
- (Smis.SNIA_BLK_ROOT_PROFILE, max_spec_ver) +
- "even its subprofile found.")
-
- cim_root_profile = self.cim_root_profile_dict[max_spec_ver]
-
- if property_list is None:
- cim_syss = self._c.Associators(
- cim_root_profile.path,
- ResultClass='CIM_ComputerSystem',
- AssocClass='CIM_ElementConformsToProfile')
- else:
- sys_id_pros = self._property_list_of_id('System')
- for key in sys_id_pros:
- if key not in property_list:
- property_list.extend([key])
- cim_syss = self._c.Associators(
- cim_root_profile.path,
- ResultClass='CIM_ComputerSystem',
- AssocClass='CIM_ElementConformsToProfile',
- PropertyList=property_list)
-
- if self.system_list is None:
- return cim_syss
-
- # Method level filter
- if sys_id is not None:
- return [s for s in cim_syss if self._sys_id(s) == sys_id][0]
-
- # Apply URI system filter
- needed_cim_syss = []
- for cim_sys in cim_syss:
- if self._sys_id(cim_sys) in self.system_list:
- needed_cim_syss.extend([cim_sys])
- return needed_cim_syss
-
- def _get_cim_syss_fallback(self, sys_id=None, property_list=None):
- """
- Usage:
- Find out the root CIM_ComputerSystem using the fallback method:
- CIM_StorageConfigurationService # Enumerate
- |
- | CIM_HostedService
- v
- CIM_ComputerSystem
- If CIM_StorageConfigurationService is not support neither,
- we enumerate CIM_ComputerSystem.
- Parameter:
- property_list # a list of properties should contained in
- # returned CIM_ComputerSystem
- # When property_list == None, we retrieve full
- # data, when property_list == [], we retrieve
- # nothing but a CIMInstanceName.
- Returns:
- cim_syss # A list of CIMInstanceName of CIM_ComputerSystem
- or
- None
+ We also assume no matter which version of root profile can lead to
+ the same CIM_ComputerSystem instance.
+ As CIM_ComputerSystem has no property indicate SNIA SMI-S version,
+ this is assumption should work. Tested on EMC SMI-S provider which
+ provide 1.4, 1.5, 1.6 root profile.
"""
- sys_id_pros = self._property_list_of_id('System')
- flag_full_info = False
+ cim_sys_id_pros = self._property_list_of_id('System')
if property_list is None:
- flag_full_info = True
+ property_list = cim_sys_id_pros
else:
- for key in sys_id_pros:
- if key not in property_list:
- property_list.extend([key])
+ for key_name in cim_sys_id_pros:
+ if key_name not in property_list:
+ property_list.extend([key_name])

cim_syss = []
- cim_scss_path = []
- try:
- # Note: Please be informed, if PropertyList is an empty list,
- # XIV will return NOTHING, so use EnumerateInstanceNames()
- # when you need nothing but the CIMInstanceName
- cim_scss_path = self._c.EnumerateInstanceNames(
- 'CIM_StorageConfigurationService')
- except CIMError as e:
- # If array does not support CIM_StorageConfigurationService
- # we use CIM_ComputerSystem which is mandatory.
- # We might get some non-storage array listed as system.
- # but we would like to take that risk instead of
- # skipping basic support of old SMIS provider.
- if e[0] == pywbem.CIM_ERR_INVALID_CLASS:
- if flag_full_info:
- cim_syss = self._c.EnumerateInstances(
- 'CIM_ComputerSystem', LocalOnly=False)
- else:
- cim_syss = self._c.EnumerateInstances(
- 'CIM_ComputerSystem',
- PropertyList=property_list,
- LocalOnly=False)
- else:
- raise e
- if not cim_syss:
- for cim_scs_path in cim_scss_path:
- cim_tmp = None
- if flag_full_info:
- cim_tmp = self._c.Associators(
- cim_scs_path,
- AssocClass='CIM_HostedService',
- ResultClass='CIM_ComputerSystem')
+ if self.fallback_mode:
+ # Fallback mode:
+ # Find out the root CIM_ComputerSystem using the fallback method:
+ # CIM_StorageConfigurationService # Enumerate
+ # |
+ # | CIM_HostedService
+ # v
+ # CIM_ComputerSystem
+ # If CIM_StorageConfigurationService is not support neither,
+ # we enumerate CIM_ComputerSystem.
+ try:
+ cim_scss_path = self._c.EnumerateInstanceNames(
+ 'CIM_StorageConfigurationService')
+ except CIMError as e:
+ # If array does not support CIM_StorageConfigurationService
+ # we use CIM_ComputerSystem which is mandatory.
+ # We might get some non-storage array listed as system.
+ # but we would like to take that risk instead of
+ # skipping basic support of old SMIS provider.
+ if e[0] == pywbem.CIM_ERR_INVALID_CLASS:
+ cim_syss = self._c.EnumerateInstances(
+ 'CIM_ComputerSystem',
+ PropertyList=property_list,
+ LocalOnly=False)
else:
+ raise e
+
+ if not cim_syss:
+ for cim_scs_path in cim_scss_path:
+ cim_tmp = None
+ # CIM_ComputerSystem is one-one map to
+ # CIM_StorageConfigurationService
cim_tmp = self._c.Associators(
cim_scs_path,
AssocClass='CIM_HostedService',
ResultClass='CIM_ComputerSystem',
PropertyList=property_list)
- if cim_tmp and cim_tmp[0]:
- cim_syss.extend([cim_tmp[0]])
-
- # Method level filter
- if sys_id is not None:
- return [s for s in cim_syss if self._sys_id(s) == sys_id]
+ if cim_tmp and cim_tmp[0]:
+ cim_syss.extend([cim_tmp[0]])
+ else:
+ for cim_rp in self.cim_rps:
+ if cim_rp['RegisteredName'] == SNIA.BLK_ROOT_PROFILE and\
+ cim_rp['RegisteredOrganization'] == SNIA.REG_ORG_CODE:
+ cim_syss = self._c.Associators(
+ cim_rp.path,
+ ResultClass='CIM_ComputerSystem',
+ AssocClass='CIM_ElementConformsToProfile',
+ PropertyList=property_list)
+ # Any version of 'Array' profile can get us to root
+ # CIM_ComputerSystem. startup() already has checked the
+ # 1.4 version
+ break
+ if len(cim_syss) == 0:
+ raise LsmError(ErrorNumber.NO_SUPPORT,
+ "Current SMI-S provider does not provide "
+ "the root CIM_ComputerSystem associated "
+ "to 'Array' CIM_RegisteredProfile. Try "
+ "add 'force_fallback_mode=yes' into URI")

# System URI Filtering
if self.system_list:
@@ -3614,7 +3425,8 @@ class Smis(IStorageAreaNetwork):
else:
return cim_syss

- def _get_cim_sys_by_id(self, system_id, property_list=None):
+
+ def _cim_sys_of_id(self, system_id, property_list=None):
"""
Return a CIMInstance of CIM_ComputerSystem for given system id.
"""
@@ -3626,15 +3438,8 @@ class Smis(IStorageAreaNetwork):
if pro not in property_list:
property_list.extend([pro])

- if self.fallback_mode:
- cim_syss = self._get_cim_syss_fallback(property_list)
- else:
- cim_syss = self._get_cim_syss(
- Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False,
- property_list=property_list,
- raise_error=True)
+ cim_syss = self._root_cim_syss(property_list)
+
for cim_sys in cim_syss:
if self._sys_id(cim_sys) == system_id:
return cim_sys
--
1.8.3.1
Tony Asleson
2014-05-22 17:59:54 UTC
Permalink
Patch passed tests, committed.

Thanks,
Tony
Post by Gris Ge
* Convert SMI-S SPEC version into integer for better comparison.
Please check _spec_ver_str_to_num() for detail.
* Let _root_cim_syss() handle the fall back checking. It will return a list
of CIM_ComputerSystem for fallback mode or not.
* Checking for 1.4 'Array' profile support in startup().
As 'Block Services Package' (AKA: BSP) is mandatory for that profile, we
don't do extra check in methods using BSP profile.
* Noting down the method naming scheme for consistency.
* Move SNIA related constants to a standalone class SNIA which shorter the
constant variable name.
* _profile_is_supported() now support raise error if not found.
* Split _cim_sys_of_id() out to raise LsmError ErrorNumber.NOT_FOUND_SYSTEM.
* Add RegisteredOrganization checking in CIM_RegisteredProfile.
* In case fallmode facing 'multiple system' profile supported array,
CIM_StorageConfigurationService -> ComputerSystem
* Add author names.
* Removed un-needed check. The startup() already checked the support of
'Array' profile.
* Fix the incorrect fallback_mode variable used in disks()
* Use new way(Enumerate) for disk query. Better performance[1].
* Removed the unneeded methods _traverse_computer_sys().
[1] EMC VMAX with 64 disks, old way will take 4 minutes, new way only take 1.5
minutes. We might get better if we use DiskDriveView. Will check on that
later.
---
plugin/smispy/smis.py | 663 ++++++++++++++++++--------------------------------
1 file changed, 234 insertions(+), 429 deletions(-)
diff --git a/plugin/smispy/smis.py b/plugin/smispy/smis.py
index c63d8cd..23cc8ed 100644
--- a/plugin/smispy/smis.py
+++ b/plugin/smispy/smis.py
@@ -13,6 +13,9 @@
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
# USA
+#
+# Author: tasleson
from string import split
import time
@@ -32,11 +35,22 @@ from lsm import (IStorageAreaNetwork, Error, uri_parse, LsmError, ErrorNumber,
# cim_pool CIM_StoragePool
# cim_scs CIM_StorageConfigurationService
# cim_vol CIM_StorageVolume
+# cim_rp CIM_RegisteredProfile
#
# sys Object of LSM System
# pool Object of LSM Pool
# vol Object of LSM Volume
+# _cim_xxx()
+# Return CIMInstance without any Associators() call.
+# _cim_xxx_of(cim_yyy)
+# Return CIMInstance associated to cim_yyy
+# _adj_cim_xxx()
+# Retrun CIMInstance with 'adj' only
+# _cim_xxx_of_id(some_id)
+# Return CIMInstance for given ID
+
traceback.format_exc())
return cim_wrapper
+ """
+ Convert version string stored in CIM_RegisteredProfile to a integer.
+ "1.5.1" -> 1,005,001
+ """
+ tmp_list = [0,0,0]
+ tmp_list = spec_ver_str.split(".")
+ tmp_list.extend([0])
+ return (int(tmp_list[0]) * 10 ** 6 +
+ int(tmp_list[1]) * 10 ** 3 +
+ int(tmp_list[2]))
+ return None
+
+ BLK_ROOT_PROFILE = 'Array'
+ BLK_SRVS_PROFILE = 'Block Services'
+ DISK_LITE_PROFILE = 'Disk Drive Lite'
+ MULTI_SYS_PROFILE = 'Multiple Computer System'
+ SMIS_SPEC_VER_1_4 ='1.4'
+ SMIS_SPEC_VER_1_5 ='1.5'
+ SMIS_SPEC_VER_1_6 ='1.6'
+ REG_ORG_CODE = pywbem.Uint16(11)
+
"""
# DSP 1033 Profile Registration
DMTF_INTEROP_NAMESPACES = ['interop', 'root/interop']
SMIS_DEFAULT_NAMESPACE = 'interop'
- SNIA_BLK_ROOT_PROFILE = 'Array'
- SNIA_BLK_SRVS_PROFILE = 'Block Services'
- SNIA_DISK_LITE_PROFILE = 'Disk Drive Lite'
- SNIA_MULTI_SYS_PROFILE = 'Multiple Computer System'
- SNIA_SMIS_SPEC_VER_1_4='1.4'
- SNIA_SMIS_SPEC_VER_1_5='1.5'
- SNIA_SMIS_SPEC_VER_1_6='1.6'
IAAN_WBEM_HTTP_PORT = 5988
IAAN_WBEM_HTTPS_PORT = 5989
self._c = None
self.tmo = 0
self.system_list = None
- self.cim_reg_profiles = []
+ self.cim_rps = []
self.cim_root_profile_dict = dict()
self.fallback_mode = True # Means we cannot use profile register
namespace_check_list.extend([u['parameters']['namespace']])
- self.cim_reg_profiles = self._c.EnumerateInstances(
+ self.cim_rps = self._c.EnumerateInstances(
'CIM_RegisteredProfile',
namespace=interop_namespace,
- PropertyList=['RegisteredName', 'RegisteredVersion'],
+ PropertyList=['RegisteredName', 'RegisteredVersion',
+ 'RegisteredOrganization'],
LocalOnly=False)
- break
+ if e[0] == pywbem.CIM_ERR_NOT_SUPPORTED or \
+ pass
+ raise e
+ break
- self.fallback_mode = False
- # Support 'Array' profile is step 0 for this whole plugin.
- # We find out all 'Array' CIM_RegisteredProfile and stored
- # them into self.cim_root_profile_dict
- if 'RegisteredName' not in cim_reg_profile or \
- continue
- if cim_reg_profile['RegisteredName'] == \
- ver = cim_reg_profile['RegisteredVersion']
- self.cim_root_profile_dict[ver]= cim_reg_profile
- raise LsmError(ErrorNumber.NO_SUPPORT,
- "SMI-S provider does not support 'Array'"
- "profile which is prerequisite")
- if e[0] == pywbem.CIM_ERR_NOT_SUPPORTED or \
- pass # AFAIK, only LSI does not support RegisteredProfile
- raise e
+ self.fallback_mode = False
+ # Support 'Array' profile is step 0 for this whole plugin.
+ # We find out all 'Array' CIM_RegisteredProfile and stored
+ # them into self.cim_root_profile_dict
+ if not self._profile_is_supported(
+ SNIA.BLK_ROOT_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4,
+ raise LsmError(ErrorNumber.NO_SUPPORT,
+ "SMI-S provider does not support "
+ "SNIA SMI-S SPEC %s '%s' profile" %
+ (SNIA.SMIS_SPEC_VER_1_4,
+ SNIA.BLK_ROOT_PROFILE))
self.tmo = ms
# Get the cim object that represents the system
cim_sys = None
cim_pcms = None
+ cim_sys = self._cim_sys_of_id(system.id)
- cim_sys = self._get_cim_syss_fallback(
- sys_id=system.id,
- property_list=[])[0] # Surely, we will get at least one
- # cim_sys since LSM system already
- # provided.
# Using 'ExposePathsSupported of
# CIM_ProtocolControllerMaskingCapabilities
cap.set(Capabilities.ACCESS_GROUP_DEL_INITIATOR)
return
- cim_syss = self._get_cim_syss(
- Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- sys_id=system.id,
- property_list=[])
- # we might not get any cim_sys on unsupported system.
- cim_sys = cim_syss[0]
- # CIM_ControllerConfigurationService is mandatory
- # and it's ExposePaths() and HidePaths() are mandatory
- cap.set(Capabilities.ACCESS_GROUP_LIST)
- cap.set(Capabilities.ACCESS_GROUP_GRANT)
- cap.set(Capabilities.ACCESS_GROUP_REVOKE)
- cap.set(Capabilities.ACCESS_GROUP_ADD_INITIATOR)
- cap.set(Capabilities.ACCESS_GROUP_DEL_INITIATOR)
- cap.set(Capabilities.ACCESS_GROUPS_GRANTED_TO_VOLUME)
- cap.set(Capabilities.VOLUMES_ACCESSIBLE_BY_ACCESS_GROUP)
- return
+ # CIM_ControllerConfigurationService is mandatory
+ # and it's ExposePaths() and HidePaths() are mandatory
+ cap.set(Capabilities.ACCESS_GROUP_LIST)
+ cap.set(Capabilities.ACCESS_GROUP_GRANT)
+ cap.set(Capabilities.ACCESS_GROUP_REVOKE)
+ cap.set(Capabilities.ACCESS_GROUP_ADD_INITIATOR)
+ cap.set(Capabilities.ACCESS_GROUP_DEL_INITIATOR)
+ cap.set(Capabilities.ACCESS_GROUPS_GRANTED_TO_VOLUME)
+ cap.set(Capabilities.VOLUMES_ACCESSIBLE_BY_ACCESS_GROUP)
cap = Capabilities()
|
v
CIM_StorageVolume
+ As 'Block Services Package' is mandatory for 'Array' profile, we
+ don't check support status here as startup() already checked 'Array'
+ profile.
"""
rc = []
- cim_syss = []
cim_sys_pros = self._property_list_of_id("System")
- cim_syss = self._get_cim_syss_fallback(property_list=cim_sys_pros)
- cim_syss = self._get_cim_syss(
- Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False,
- property_list=cim_sys_pros,
- raise_error=True)
+ cim_syss = self._root_cim_syss(cim_sys_pros)
cim_vol_pros = self._new_vol_cim_vol_pros()
sys_id = self._sys_id(cim_sys)
|
v
CIM_StoragePool
+ As 'Block Services Package' is mandatory for 'Array' profile, we
+ don't check support status here as startup() already checked 'Array'
+ profile.
"""
rc = []
cim_pool_pros = self._new_pool_cim_pool_pros(
flags == Pool.RETRIEVE_FULL_INFO)
cim_sys_pros = self._property_list_of_id("System")
- cim_syss = []
- cim_syss = self._get_cim_syss_fallback(property_list=cim_sys_pros)
- cim_syss = self._get_cim_syss(
- Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False,
- property_list=cim_sys_pros,
- raise_error=True)
+ cim_syss = self._root_cim_syss(cim_sys_pros)
system_id = self._sys_id(cim_sys)
"""
Return the storage arrays accessible from this plug-in at this time
+
+ As 'Block Services Package' is mandatory for 'Array' profile, we
+ don't check support status here as startup() already checked 'Array'
+ profile.
"""
cim_sys_pros = self._cim_sys_pros()
- cim_syss = self._get_cim_syss_fallback(property_list=cim_sys_pros)
- cim_syss = self._get_cim_syss(
- Smis.SNIA_BLK_ROOT_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False,
- property_list=cim_sys_pros,
- raise_error=True)
-
- return []
+ cim_syss = self._root_cim_syss(cim_sys_pros)
+
return [Smis._cim_sys_2_lsm_sys(s) for s in cim_syss]
CIM_PhysicalPackage
CIM_DiskDrive
CIM_StorageExtent (Primordial)
-
- CIM_ComputerSystem
- |
- | (CIM_SystemDevice)
- |
- v
- CIM_DiskDrive
-
- If 'Multiple Computer System Subprofile' is supported,
- we run above association on every CIM_ComputerSystem.
-
- CIM_ComputerSystem # Root
- |
- | CIM_ConcreteIdentity
- |
- v
- CIM_RedundancySet <-----------------+
- | |
- | CIM_MemberOfCollection |
- | | CIM_ConcreteIdentity
- v |
- CIM_ComputerSystem # Leaf |
- | |
- +---------------------------+
-
- 1. Find out all associated disks: 'CIM_DiskDrive'.
- 2. Find out all association storage extension: 'CIM_StorageExtent'.
- 3. We will use vendor specific way for all workarounds.
+ Due to 'Multiple Computer System' profile, disks might assocated to
+ sub ComputerSystem. To improve profromance of listing disks, we will
+ use EnumerateInstances(). Which means we have to filter the results
+ by ourself in case URI contain 'system=xxx'.
"""
rc = []
- cim_syss = []
cim_sys_pros = self._property_list_of_id("System")
- cim_syss = self._get_cim_syss_fallback(property_list=cim_sys_pros)
- cim_syss = self._get_cim_syss(
- Smis.SNIA_DISK_LITE_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False,
- property_list=cim_sys_pros,
- raise_error=True)
-
- flag_multi_sys = None
- flag_multi_sys = self._profile_is_supported(
- Smis.SNIA_MULTI_SYS_PROFILE, Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False)
- # In SNIA SMI-S 1.6rev4 Common Book,
- # 30.1.5 Associations between ComputerSystems and other Logical
- # Elements
- # "If the device may become unavailable while the system as a
- # whole remains available, the device shall be associated to a
- # non-top-level system that has availability equivalent to the
- # device. This system could be a real system or a system in an
- # intermediate tier (representing some redundancy less than full
- # redundancy)."
-
- # Hence DiskDrive might not associated to top level
- # CIM_ComputerSystem
+ self._profile_is_supported(SNIA.DISK_LITE_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4,
+ strict=False,
+ raise_error=True)
+ cim_syss = self._root_cim_syss(cim_sys_pros)
- cim_disk_pros = Smis._new_disk_cim_disk_pros(flags)
- cim_disks = self._c.Associators(cim_sys.path,
- AssocClass='CIM_SystemDevice',
- ResultClass='CIM_DiskDrive',
- PropertyList=cim_disk_pros)
- # Checking Disks of sub level ComputerSystems.
- cim_sub_syss_path = self._traverse_computer_sys(cim_sys.path)
- cim_sub_disks = self._c.Associators(
- cim_sub_sys_path,
- AssocClass='CIM_SystemDevice',
- ResultClass='CIM_DiskDrive',
- PropertyList=cim_disk_pros)
- cim_disks.extend(cim_sub_disks)
- # Clean up the duplicate as SNIA said DiskDrive can be
- # one to many in SNIA SMIS 1.6rev4 CommonProfile Book,
- # 30.1.5 Associations between ComputerSystems and other
- # Logical Elements, PDF Page 311.
- clean_up_dict = {}
- clean_up_dict[self._disk_id(cim_disk)] = cim_disk
- cim_disks = clean_up_dict.values()
+ return []
- sys_id = self._sys_id(cim_sys)
+ all_vendor_namespaces = []
+ all_vendor_namespaces.extend([cim_sys.path.namespace])
+
+ cim_disk_pros = Smis._new_disk_cim_disk_pros(flags)
+ cim_disks = self._c.EnumerateInstances(
+ 'CIM_DiskDrive',
+ namespace=vendor_namespace,
+ PropertyList=cim_disk_pros)
+ continue
cim_ext_pros = Smis._new_disk_cim_ext_pros(flags)
cim_ext = self._pri_cim_ext_of_cim_disk(cim_disk.path,
cim_ext_pros)
- rc.extend(
- [self._new_disk(cim_disk, cim_ext, sys_id, flags)])
- return rc
- """
- Walk through the CIM_ComputerSystem based on SNIA SMI-S 1.6rev4
- CommonProfile Book, Multiple Computer System Subprofile
- Will return a array of CIM_InstanceName -- CIM_ComputerSystem
- Including the inter level CIM_ComputerSystem and botton leaf
- CIM_ComputerSystem, but not including the CIM_ComputerSystem provided.
- """
- cim_syss_path = []
- cim_re_sets_path = []
- cim_re_sets_path = self._c.AssociatorNames(
- cim_sys_path,
- AssocClass='CIM_ConcreteIdentity',
- ResultClass='CIM_RedundancySet')
- return []
-
- cim_cur_syss_path = self._c.AssociatorNames(
- cim_re_set_path,
- AssocClass='CIM_MemberOfCollection',
- ResultClass='CIM_ComputerSystem')
- cim_syss_path.extend(cim_cur_syss_path)
- # every CIM_RedundancySet should associated to a
- # CIM_ComputerSystem, so no else.
- cim_next_syss_path = self._traverse_computer_sys(
- cim_sys_path)
- cim_syss_path.extend(cim_next_syss_path)
- return cim_syss_path
+ rc.extend([self._new_disk(cim_disk, cim_ext, flags)])
+ return rc
@staticmethod
Smis._DMTF_STAUTS_TO_DISK_STATUS_INFO[dmtf_status])
return (status, status_info)
"""
Takes a CIM_DiskDrive and CIM_StorageExtent, returns a lsm Disk
Assuming cim_disk and cim_ext already contained the correct
num_of_block = Disk.BLOCK_COUNT_NOT_FOUND
disk_type = Disk.DISK_TYPE_UNKNOWN
status_info = ''
+ sys_id = self._sys_id_child(cim_disk)
# These are mandatory
# we do not check whether they follow the SNIA standard.
"""
cim_sys_pros = self._property_list_of_id("System")
if not self.fallback_mode and \
- self._profile_is_supported(Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
+ self._profile_is_supported(SNIA.BLK_SRVS_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4,
raise LsmError(ErrorNumber.NO_SUPPORT,
"SMI-S %s version %s is not supported" %
- (Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4))
+ (SNIA.BLK_SRVS_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4))
- cim_sys = self._get_cim_sys_by_id(pool.system_id)
+ cim_sys = self._cim_sys_of_id(pool.system_id)
cim_pool = self._get_cim_pool_by_id(cim_sys.path, pool.id)
cim_scs = self._get_cim_scs(cim_sys.path)
CreateOrModifyStoragePool()
"""
if not self.fallback_mode and \
- self._profile_is_supported(Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
+ self._profile_is_supported(SNIA.BLK_SRVS_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4,
raise LsmError(ErrorNumber.NO_SUPPORT,
"SMI-S %s version %s is not supported" %
- (Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4))
+ (SNIA.BLK_SRVS_PROFILE,
+ SNIA.SMIS_SPEC_VER_1_4))
- cim_sys = self._get_cim_sys_by_id(system.id)
+ cim_sys = self._cim_sys_of_id(system.id)
# we does not support defining thinp_type yet.
# just using whatever provider set.
"CIM_StorageConfigurationService of " +
"CIM_ComputerSystem %s" % cim_sys_path)
+ def _profile_is_supported(self, profile_name, spec_ver, strict=False,
"""
Check whether we support certain profile at certain SNIA
specification version.
- When strict == False(default), profile spec version newer than
- require spec_ver will also be consider as found.
+ When strict == False(default), profile spec version later or equal
+ than require spec_ver will also be consider as found.
When strict == True, only defined spec_version is allowed.
+ Require self.cim_rps containing all CIM_RegisteredProfile
+ Will raise LsmError(ErrorNumber.NO_SUPPORT, 'xxx') if raise_error
+ is True when nothing found.
- profile_name # Smis.SNIA_REGISTERED_PROFILE_XXX
- spec_ver # Smis.SNIA_SMIS_SPEC_VER_XXX
- property_list # a list of properties should contained in
- # returned CIM_ComputerSystem
- # When property_list == None, we retrieve full
- # data, when property_list == [], we retrieve
- # nothing but a CIMInstanceName.
+ profile_name # SNIA.XXXX_PROFILE
+ spec_ver # SNIA.SMIS_SPEC_VER_XXX
strict # False or True. If True, only defined
# spec_version is consider as supported
# If false, will return the maximum version of
# spec.
+ raise_error # Raise LsmError if not found
None # Not supported.
or
- spec_version # the vendor implemented version. like '1.4.1'
- # This is a string, NOT float.
- """
- max_spec_ver = 0
- max_spec_ver_flt = 0
- # assuming spec_ver is well formatted, since we are internal
- # method, we can do that guess.
- req_ver_main = spec_ver.split('.')[0]
- req_ver_sub = spec_ver.split('.')[1]
-
- if 'RegisteredName' not in cim_reg_profile or \
+ spec_int # Integer. Converted by _spec_ver_str_to_num()
+ """
+ req_ver = _spec_ver_str_to_num(spec_ver)
+
+ max_spec_ver_str = None
+ max_spec_ver = None
+ if 'RegisteredName' not in cim_rp or \
continue
# check spec version
- cur_ver = cim_reg_profile['RegisteredVersion']
- cur_ver_list = cur_ver.split('.')
- continue
- cur_ver_flt = float("%s.%s" % tuple(cur_ver_list[0:2]))
- req_ver_flt = float("%s.%s" % (req_ver_main, req_ver_sub))
+ cur_ver = _spec_ver_str_to_num(cim_rp['RegisteredVersion'])
return cur_ver
-
+ if max_spec_ver is None or \
max_spec_ver = cur_ver
- max_spec_ver_flt = cur_ver_flt
+ max_spec_ver_str = cim_rp['RegisteredVersion']
+ raise LsmError(ErrorNumber.NO_SUPPORT,
+ "SNIA SMI-S %s '%s' profile is not supported" %
+ (spec_ver, profile_name))
- return None
return max_spec_ver
- def _get_cim_syss(self, profile_name, spec_ver, property_list=None,
"""
- Check whether we support certain profile at certain SNIA
- specification version.
- When strict == False(default), profile spec version newer than
- require spec_ver will also be consider as found.
- When strict == True, only defined spec_version is allowed.
+ For fallback mode, this just enumerate CIM_ComputerSystem.
+ We require vendor to implement profile registration when using
+ "Multiple System Profile".
+ For normal mode, this just find out the root CIM_ComputerSystem
CIM_RegisteredProfile # Root Profile('Array') in interop
|
| CIM_ElementConformsToProfile
v
CIM_ComputerSystem # vendor namespace
- We depend on self.cim_reg_profiles which was updated by startup().
- But this method does not check it, you should check
- self.fallback_mode == True before call this method.
-
- Please use constant spec_ver and profile_name for better
- code management.
- We also apply to system filter in URI which is stored in
- self.system_list
- When returning None, it means current provider does not support
- requested profile or version.
- profile_name # Smis.SNIA_REGISTERED_PROFILE_XXX
- spec_ver # Smis.SNIA_SMIS_SPEC_VER_XXX
- property_list # a list of properties should contained in
- # returned CIM_ComputerSystem
- # When property_list == None, we retrieve full
- # data, when property_list == [], we retrieve
- # nothing but a CIMInstanceName.
- strict # False or True. If True, only defined
- # spec_version is consider as supported
- sys_id # Only return CIM_ComputerSystem for certain
- # system ID.
- cim_syss # a list of CIMInstanceName of CIM_ComputerSystem
- or
- None # Current SMI-S provider does not support this
- # profile at certain version.
- """
- max_spec_ver = self._profile_is_supported(
- profile_name, spec_ver, strict)
-
- error_msg = ("Current SMI-S provider does not support "
- "SMI-S %s profile, version %s" %
- (profile_name, spec_ver))
- error_msg = "%s(or later version)" % error_msg
- raise LsmError(ErrorNumber.NO_SUPPORT, error_msg)
- return None
-
- raise LsmError(ErrorNumber.INTERNAL_ERROR,
- "Failed to find out CIM_RegisteredProfile " +
- "for profile %s with version %s " %
- (Smis.SNIA_BLK_ROOT_PROFILE, max_spec_ver) +
- "even its subprofile found.")
-
- cim_root_profile = self.cim_root_profile_dict[max_spec_ver]
-
- cim_syss = self._c.Associators(
- cim_root_profile.path,
- ResultClass='CIM_ComputerSystem',
- AssocClass='CIM_ElementConformsToProfile')
- sys_id_pros = self._property_list_of_id('System')
- property_list.extend([key])
- cim_syss = self._c.Associators(
- cim_root_profile.path,
- ResultClass='CIM_ComputerSystem',
- AssocClass='CIM_ElementConformsToProfile',
- PropertyList=property_list)
-
- return cim_syss
-
- # Method level filter
- return [s for s in cim_syss if self._sys_id(s) == sys_id][0]
-
- # Apply URI system filter
- needed_cim_syss = []
- needed_cim_syss.extend([cim_sys])
- return needed_cim_syss
-
- """
- CIM_StorageConfigurationService # Enumerate
- |
- | CIM_HostedService
- v
- CIM_ComputerSystem
- If CIM_StorageConfigurationService is not support neither,
- we enumerate CIM_ComputerSystem.
- property_list # a list of properties should contained in
- # returned CIM_ComputerSystem
- # When property_list == None, we retrieve full
- # data, when property_list == [], we retrieve
- # nothing but a CIMInstanceName.
- cim_syss # A list of CIMInstanceName of CIM_ComputerSystem
- or
- None
+ We also assume no matter which version of root profile can lead to
+ the same CIM_ComputerSystem instance.
+ As CIM_ComputerSystem has no property indicate SNIA SMI-S version,
+ this is assumption should work. Tested on EMC SMI-S provider which
+ provide 1.4, 1.5, 1.6 root profile.
"""
- sys_id_pros = self._property_list_of_id('System')
- flag_full_info = False
+ cim_sys_id_pros = self._property_list_of_id('System')
- flag_full_info = True
+ property_list = cim_sys_id_pros
- property_list.extend([key])
+ property_list.extend([key_name])
cim_syss = []
- cim_scss_path = []
- # Note: Please be informed, if PropertyList is an empty list,
- # XIV will return NOTHING, so use EnumerateInstanceNames()
- # when you need nothing but the CIMInstanceName
- cim_scss_path = self._c.EnumerateInstanceNames(
- 'CIM_StorageConfigurationService')
- # If array does not support CIM_StorageConfigurationService
- # we use CIM_ComputerSystem which is mandatory.
- # We might get some non-storage array listed as system.
- # but we would like to take that risk instead of
- # skipping basic support of old SMIS provider.
- cim_syss = self._c.EnumerateInstances(
- 'CIM_ComputerSystem', LocalOnly=False)
- cim_syss = self._c.EnumerateInstances(
- 'CIM_ComputerSystem',
- PropertyList=property_list,
- LocalOnly=False)
- raise e
- cim_tmp = None
- cim_tmp = self._c.Associators(
- cim_scs_path,
- AssocClass='CIM_HostedService',
- ResultClass='CIM_ComputerSystem')
+ # CIM_StorageConfigurationService # Enumerate
+ # |
+ # | CIM_HostedService
+ # v
+ # CIM_ComputerSystem
+ # If CIM_StorageConfigurationService is not support neither,
+ # we enumerate CIM_ComputerSystem.
+ cim_scss_path = self._c.EnumerateInstanceNames(
+ 'CIM_StorageConfigurationService')
+ # If array does not support CIM_StorageConfigurationService
+ # we use CIM_ComputerSystem which is mandatory.
+ # We might get some non-storage array listed as system.
+ # but we would like to take that risk instead of
+ # skipping basic support of old SMIS provider.
+ cim_syss = self._c.EnumerateInstances(
+ 'CIM_ComputerSystem',
+ PropertyList=property_list,
+ LocalOnly=False)
+ raise e
+
+ cim_tmp = None
+ # CIM_ComputerSystem is one-one map to
+ # CIM_StorageConfigurationService
cim_tmp = self._c.Associators(
cim_scs_path,
AssocClass='CIM_HostedService',
ResultClass='CIM_ComputerSystem',
PropertyList=property_list)
- cim_syss.extend([cim_tmp[0]])
-
- # Method level filter
- return [s for s in cim_syss if self._sys_id(s) == sys_id]
+ cim_syss.extend([cim_tmp[0]])
+ if cim_rp['RegisteredName'] == SNIA.BLK_ROOT_PROFILE and\
+ cim_syss = self._c.Associators(
+ cim_rp.path,
+ ResultClass='CIM_ComputerSystem',
+ AssocClass='CIM_ElementConformsToProfile',
+ PropertyList=property_list)
+ # Any version of 'Array' profile can get us to root
+ # CIM_ComputerSystem. startup() already has checked the
+ # 1.4 version
+ break
+ raise LsmError(ErrorNumber.NO_SUPPORT,
+ "Current SMI-S provider does not provide "
+ "the root CIM_ComputerSystem associated "
+ "to 'Array' CIM_RegisteredProfile. Try "
+ "add 'force_fallback_mode=yes' into URI")
# System URI Filtering
return cim_syss
+
"""
Return a CIMInstance of CIM_ComputerSystem for given system id.
"""
property_list.extend([pro])
- cim_syss = self._get_cim_syss_fallback(property_list)
- cim_syss = self._get_cim_syss(
- Smis.SNIA_BLK_SRVS_PROFILE,
- Smis.SNIA_SMIS_SPEC_VER_1_4,
- strict=False,
- property_list=property_list,
- raise_error=True)
+ cim_syss = self._root_cim_syss(property_list)
+
return cim_sys
Loading...