00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 from pywbem import Uint16, CIMError
00025 import pywbem
00026 import traceback
00027 import os
00028 import datetime
00029 import time
00030 import sys
00031
00032 import dmtf
00033 from lsm import LsmError, ErrorNumber, md5
00034 from utils import (merge_list)
00035
00036
00037 def _profile_register_load(wbem_conn):
00038 """
00039 Check CIM_RegisteredProfile in interop namespace.
00040 Return (profile_dict, root_blk_cim_rp)
00041 The 'profile_dict' is a dictionary like this:
00042 {
00043 # profile_name: max_version
00044 'Array': 1.4,
00045 'Block Service Profile': 1.4,
00046 }
00047 The 'root_blk_cim_rp' is the 'Array' profile of CIM_RegisteredProfile
00048 with highest version number.
00049 """
00050 profile_dict = {}
00051 root_blk_cim_rp = None
00052 namespace_check_list = dmtf.INTEROP_NAMESPACES
00053
00054 cim_rps = []
00055 for namespace in namespace_check_list:
00056 try:
00057 cim_rps = wbem_conn.EnumerateInstances(
00058 'CIM_RegisteredProfile',
00059 namespace=namespace,
00060 PropertyList=['RegisteredName', 'RegisteredVersion',
00061 'RegisteredOrganization'],
00062 LocalOnly=False)
00063 except CIMError as e:
00064 if e[0] == pywbem.CIM_ERR_NOT_SUPPORTED or \
00065 e[0] == pywbem.CIM_ERR_INVALID_NAMESPACE or \
00066 e[0] == pywbem.CIM_ERR_INVALID_CLASS:
00067 pass
00068 else:
00069 raise
00070 if len(cim_rps) != 0:
00071 break
00072
00073 if len(cim_rps) >= 1:
00074 for cim_rp in cim_rps:
00075 if cim_rp['RegisteredOrganization'] != \
00076 SmisCommon.SNIA_REG_ORG_CODE:
00077 continue
00078 profile_name = cim_rp['RegisteredName']
00079 profile_ver = cim_rp['RegisteredVersion']
00080 profile_ver_num = _profile_spec_ver_to_num(profile_ver)
00081 if profile_name in profile_dict.keys():
00082 exist_ver_num = _profile_spec_ver_to_num(
00083 profile_dict[profile_name])
00084 if exist_ver_num >= profile_ver_num:
00085 continue
00086 if profile_name == SmisCommon.SNIA_BLK_ROOT_PROFILE:
00087 root_blk_cim_rp = cim_rp
00088 profile_dict[profile_name] = profile_ver
00089 else:
00090 raise LsmError(
00091 ErrorNumber.NO_SUPPORT,
00092 "Target SMI-S provider does not support DMTF DSP1033 profile "
00093 "register which is mandatory for LSM")
00094
00095 return profile_dict, root_blk_cim_rp
00096
00097
00098 def _profile_check(profile_dict, profile_name, spec_ver,
00099 raise_error=False):
00100 """
00101 Check whether we support certain profile at certain SNIA
00102 specification version.
00103 Profile spec version later or equal than require spec_ver will also be
00104 consider as found.
00105 Require profile_dict provided by SmisCommon.profile_register_load()
00106 Will raise LsmError(ErrorNumber.NO_SUPPORT, 'xxx') if raise_error
00107 is True when nothing found.
00108 """
00109 request_ver_num = _profile_spec_ver_to_num(spec_ver)
00110 if profile_name not in profile_dict.keys():
00111 if raise_error:
00112 raise LsmError(
00113 ErrorNumber.NO_SUPPORT,
00114 "SNIA SMI-S %s '%s' profile is not supported by " %
00115 (profile_name, spec_ver) +
00116 "target SMI-S provider")
00117 return False
00118
00119 support_ver_num = _profile_spec_ver_to_num(profile_dict[profile_name])
00120 if support_ver_num < request_ver_num:
00121 if raise_error:
00122 raise LsmError(
00123 ErrorNumber.NO_SUPPORT,
00124 "SNIA SMI-S %s '%s' profile is not supported by " %
00125 (profile_name, spec_ver) +
00126 "target SMI-S provider. Only version %s is supported" %
00127 profile_dict[profile_name])
00128 else:
00129 return False
00130 return True
00131
00132
00133 def _profile_spec_ver_to_num(spec_ver_str):
00134 """
00135 Convert version string stored in CIM_RegisteredProfile to a integer.
00136 Example:
00137 "1.5.1" -> 1,005,001
00138 """
00139 tmp_list = [0, 0, 0]
00140 tmp_list = spec_ver_str.split(".")
00141 if len(tmp_list) == 2:
00142 tmp_list.extend([0])
00143 if len(tmp_list) == 3:
00144 return (int(tmp_list[0]) * 10 ** 6 +
00145 int(tmp_list[1]) * 10 ** 3 +
00146 int(tmp_list[2]))
00147 return None
00148
00149
00150 class SmisCommon(object):
00151
00152
00153
00154
00155
00156 SNIA_INVOKE_OK = 0
00157 SNIA_INVOKE_NOT_SUPPORTED = 1
00158 SNIA_INVOKE_FAILED = 4
00159 SNIA_INVOKE_ASYNC = 4096
00160
00161 SNIA_BLK_ROOT_PROFILE = 'Array'
00162 SNIA_BLK_SRVS_PROFILE = 'Block Services'
00163 SNIA_DISK_LITE_PROFILE = 'Disk Drive Lite'
00164 SNIA_MULTI_SYS_PROFILE = 'Multiple Computer System'
00165 SNIA_MASK_PROFILE = 'Masking and Mapping'
00166 SNIA_GROUP_MASK_PROFILE = 'Group Masking and Mapping'
00167 SNIA_FC_TGT_PORT_PROFILE = 'FC Target Ports'
00168 SNIA_ISCSI_TGT_PORT_PROFILE = 'iSCSI Target Ports'
00169 SNIA_SPARE_DISK_PROFILE = 'Disk Sparing'
00170 SMIS_SPEC_VER_1_1 = '1.1'
00171 SMIS_SPEC_VER_1_4 = '1.4'
00172 SMIS_SPEC_VER_1_5 = '1.5'
00173 SMIS_SPEC_VER_1_6 = '1.6'
00174 SNIA_REG_ORG_CODE = Uint16(11)
00175 _MEGARAID_NAMESPACE = 'root/LsiMr13'
00176 _NETAPP_E_NAMESPACE = 'root/LsiArray13'
00177 _PRODUCT_MEGARAID = 'LSI MegaRAID'
00178 _PRODUCT_NETAPP_E = 'NetApp-E'
00179
00180 JOB_RETRIEVE_NONE = 0
00181 JOB_RETRIEVE_VOLUME = 1
00182 JOB_RETRIEVE_VOLUME_CREATE = 2
00183
00184 IAAN_WBEM_HTTP_PORT = 5988
00185 IAAN_WBEM_HTTPS_PORT = 5989
00186
00187 _INVOKE_MAX_LOOP_COUNT = 60
00188 _INVOKE_CHECK_INTERVAL = 5
00189
00190 def __init__(self, url, username, password,
00191 namespace=dmtf.DEFAULT_NAMESPACE,
00192 no_ssl_verify=False, debug_path=None, system_list=None):
00193 self._wbem_conn = None
00194 self._profile_dict = {}
00195 self.root_blk_cim_rp = None
00196 self._vendor_product = None
00197 self.system_list = system_list
00198 self._debug_path = debug_path
00199
00200 if namespace is None:
00201 namespace = dmtf.DEFAULT_NAMESPACE
00202
00203 self._wbem_conn = pywbem.WBEMConnection(
00204 url, (username, password), namespace)
00205 if no_ssl_verify:
00206 try:
00207 self._wbem_conn = pywbem.WBEMConnection(
00208 url, (username, password), namespace,
00209 no_verification=True)
00210 except TypeError:
00211
00212
00213 pass
00214
00215 if debug_path is not None:
00216 self._wbem_conn.debug = True
00217
00218 if namespace.lower() == SmisCommon._MEGARAID_NAMESPACE.lower():
00219
00220
00221 self._profile_dict = {
00222
00223 SmisCommon.SNIA_BLK_ROOT_PROFILE: SmisCommon.SMIS_SPEC_VER_1_4,
00224 SmisCommon.SNIA_BLK_SRVS_PROFILE: SmisCommon.SMIS_SPEC_VER_1_4,
00225 SmisCommon.SNIA_DISK_LITE_PROFILE:
00226 SmisCommon.SMIS_SPEC_VER_1_4,
00227 }
00228 self._vendor_product = SmisCommon._PRODUCT_MEGARAID
00229 else:
00230 (self._profile_dict, self.root_blk_cim_rp) = \
00231 _profile_register_load(self._wbem_conn)
00232
00233 if namespace.lower() == SmisCommon._NETAPP_E_NAMESPACE.lower():
00234 self._vendor_product = SmisCommon._PRODUCT_NETAPP_E
00235
00236
00237
00238 self._profile_dict[SmisCommon.SNIA_FC_TGT_PORT_PROFILE] = \
00239 SmisCommon.SMIS_SPEC_VER_1_4
00240 self._profile_dict[SmisCommon.SNIA_ISCSI_TGT_PORT_PROFILE] = \
00241 SmisCommon.SMIS_SPEC_VER_1_4
00242
00243
00244 self._profile_dict[SmisCommon.SNIA_MASK_PROFILE] = \
00245 SmisCommon.SMIS_SPEC_VER_1_4
00246
00247
00248 _profile_check(
00249 self._profile_dict, SmisCommon.SNIA_BLK_ROOT_PROFILE,
00250 SmisCommon.SMIS_SPEC_VER_1_4, raise_error=True)
00251
00252 def profile_check(self, profile_name, spec_ver, raise_error=False):
00253 """
00254 Usage:
00255 Check whether we support certain profile at certain SNIA
00256 specification version or later version.
00257 Will raise LsmError(ErrorNumber.NO_SUPPORT, 'xxx') if raise_error
00258 is True when nothing found.
00259 Parameter:
00260 profile_name # SmisCommon.SNIA_XXXX_PROFILE
00261 spec_ver # SmisCommon.SMIS_SPEC_VER_XXX
00262 raise_error # Raise LsmError if not found
00263 Returns:
00264 True
00265 or
00266 False
00267 """
00268 return _profile_check(
00269 self._profile_dict, profile_name, spec_ver, raise_error)
00270
00271 def _vendor_namespace(self):
00272 if self.root_blk_cim_rp:
00273 cim_syss_path = self._wbem_conn.AssociatorNames(
00274 self.root_blk_cim_rp.path,
00275 ResultClass='CIM_ComputerSystem',
00276 AssocClass='CIM_ElementConformsToProfile')
00277 if len(cim_syss_path) == 0:
00278 raise LsmError(
00279 ErrorNumber.NO_SUPPORT,
00280 "Target SMI-S provider does not support any "
00281 "CIM_ComputerSystem for SNIA SMI-S '%s' profile" %
00282 SmisCommon.SNIA_BLK_ROOT_PROFILE)
00283 return cim_syss_path[0].namespace
00284 else:
00285 raise LsmError(
00286 ErrorNumber.PLUGIN_BUG,
00287 "_vendor_namespace(): self.root_blk_cim_rp not set yet")
00288
00289 def EnumerateInstances(self, ClassName, namespace=None, **params):
00290 if self._wbem_conn.default_namespace in dmtf.INTEROP_NAMESPACES:
00291
00292 self._wbem_conn.default_namespace = self._vendor_namespace()
00293 params['LocalOnly'] = False
00294 return self._wbem_conn.EnumerateInstances(
00295 ClassName, namespace, **params)
00296
00297 def EnumerateInstanceNames(self, ClassName, namespace=None, **params):
00298 if self._wbem_conn.default_namespace in dmtf.INTEROP_NAMESPACES:
00299
00300 self._wbem_conn.default_namespace = self._vendor_namespace()
00301 params['LocalOnly'] = False
00302 return self._wbem_conn.EnumerateInstanceNames(
00303 ClassName, namespace, **params)
00304
00305 def Associators(self, ObjectName, **params):
00306 return self._wbem_conn.Associators(ObjectName, **params)
00307
00308 def AssociatorNames(self, ObjectName, **params):
00309 return self._wbem_conn.AssociatorNames(ObjectName, **params)
00310
00311 def GetInstance(self, InstanceName, **params):
00312 params['LocalOnly'] = False
00313 return self._wbem_conn.GetInstance(InstanceName, **params)
00314
00315 def DeleteInstance(self, InstanceName, **params):
00316 return self._wbem_conn.DeleteInstance(InstanceName, **params)
00317
00318 def References(self, ObjectName, **params):
00319 return self._wbem_conn.References(ObjectName, **params)
00320
00321 def is_megaraid(self):
00322 return self._vendor_product == SmisCommon._PRODUCT_MEGARAID
00323
00324 def is_netappe(self):
00325 return self._vendor_product == SmisCommon._PRODUCT_NETAPP_E
00326
00327 @staticmethod
00328 def cim_job_pros():
00329 return ['InstanceID']
00330
00331 def cim_job_of_job_id(self, job_id, property_list=None):
00332 """
00333 Return CIM_ConcreteJob for given job_id.
00334 """
00335 if property_list is None:
00336 property_list = SmisCommon.cim_job_pros()
00337 else:
00338 property_list = merge_list(
00339 property_list, SmisCommon.cim_job_pros())
00340
00341 cim_jobs = self.EnumerateInstances(
00342 'CIM_ConcreteJob',
00343 PropertyList=property_list)
00344 real_job_id = SmisCommon.parse_job_id(job_id)[0]
00345 for cim_job in cim_jobs:
00346 if md5(cim_job['InstanceID']) == real_job_id:
00347 return cim_job
00348
00349 raise LsmError(
00350 ErrorNumber.NOT_FOUND_JOB,
00351 "Job %s not found" % job_id)
00352
00353 @staticmethod
00354 def _job_id_of_cim_job(cim_job, retrieve_data, method_data):
00355 """
00356 Return the MD5 has of CIM_ConcreteJob['InstanceID'] in conjunction
00357 with '@%s' % retrieve_data
00358 retrieve_data should be SmisCommon.JOB_RETRIEVE_NONE or
00359 SmisCommon.JOB_RETRIEVE_VOLUME or etc
00360 method_data is any string a method would like store for error
00361 handling by job_status().
00362 """
00363 return "%s@%d@%s" % (
00364 md5(cim_job['InstanceID']), int(retrieve_data), str(method_data))
00365
00366 @staticmethod
00367 def parse_job_id(job_id):
00368 """
00369 job_id is assembled by a md5 string, retrieve_data and method_data
00370 This method will split it and return
00371 (md5_str, retrieve_data, method_data)
00372 """
00373 tmp_list = job_id.split('@', 3)
00374 md5_str = tmp_list[0]
00375 retrieve_data = SmisCommon.JOB_RETRIEVE_NONE
00376 method_data = None
00377 if len(tmp_list) == 3:
00378 retrieve_data = int(tmp_list[1])
00379 method_data = tmp_list[2]
00380 return (md5_str, retrieve_data, method_data)
00381
00382 def _dump_wbem_xml(self, file_prefix):
00383 """
00384 When debugging issues with providers it's helpful to have
00385 the xml request/reply to give to provider developers.
00386 """
00387 try:
00388 if self._debug_path is not None:
00389 if not os.path.exists(self._debug_path):
00390 os.makedirs(self._debug_path)
00391
00392 if os.path.isdir(self._debug_path):
00393 debug_fn = "%s_%s" % (
00394 file_prefix, datetime.datetime.now().isoformat())
00395 debug_full = os.path.join(
00396 self._debug_path, debug_fn)
00397
00398
00399 with open(debug_full, 'w') as d:
00400 d.write("REQUEST:\n%s\n\nREPLY:\n%s\n" %
00401 (self._wbem_conn.last_request,
00402 self._wbem_conn.last_reply))
00403 except Exception:
00404
00405
00406 pass
00407
00408 def invoke_method(self, cmd, cim_path, in_params, out_handler=None,
00409 error_handler=None, retrieve_data=None,
00410 method_data=None):
00411 """
00412 cmd
00413 A string of command, example:
00414 'CreateOrModifyElementFromStoragePool'
00415 cim_path
00416 the CIMInstanceName, example:
00417 CIM_StorageConfigurationService.path
00418 in_params
00419 A dictionary of input parameter, example:
00420 {'ElementName': volume_name,
00421 'ElementType': dmtf_element_type,
00422 'InPool': cim_pool_path,
00423 'Size': pywbem.Uint64(size_bytes)}
00424 out_handler
00425 A reference to a method to parse output, example:
00426 self._new_vol_from_name
00427 error_handler
00428 A reference to a method to handle all exceptions.
00429 retrieve_data
00430 SmisCommon.JOB_RETRIEVE_XXX, it will be used only
00431 when a ASYNC job has been created.
00432 method_data
00433 A string which will be stored in job_id, it could be used by
00434 job_status() to do error checking.
00435 """
00436 if retrieve_data is None:
00437 retrieve_data = SmisCommon.JOB_RETRIEVE_NONE
00438 try:
00439 (rc, out) = self._wbem_conn.InvokeMethod(
00440 cmd, cim_path, **in_params)
00441
00442
00443 if rc == SmisCommon.SNIA_INVOKE_OK:
00444 if out_handler is None:
00445 return None, None
00446 else:
00447 return None, out_handler(out)
00448
00449 elif rc == SmisCommon.SNIA_INVOKE_ASYNC:
00450
00451 job_id = SmisCommon._job_id_of_cim_job(
00452 out['Job'], retrieve_data, method_data)
00453 return job_id, None
00454 elif rc == SmisCommon.SNIA_INVOKE_NOT_SUPPORTED:
00455 raise LsmError(
00456 ErrorNumber.NO_SUPPORT,
00457 'SMI-S error code indicates operation not supported')
00458 else:
00459 self._dump_wbem_xml(cmd)
00460 raise LsmError(ErrorNumber.PLUGIN_BUG,
00461 "Error: %s rc= %s" % (cmd, str(rc)))
00462
00463 except Exception:
00464 exc_info = sys.exc_info()
00465
00466
00467 self._dump_wbem_xml(cmd)
00468 if error_handler is not None:
00469 error_handler(self, method_data, exc_info)
00470 else:
00471 raise
00472
00473 def invoke_method_wait(self, cmd, cim_path, in_params,
00474 out_key=None, expect_class=None,
00475 flag_out_array=False):
00476 """
00477 InvokeMethod and wait it until done.
00478 Return a CIMInstanceName from out[out_key] or from cim_job:
00479 CIM_ConcreteJob
00480 |
00481 | CIM_AffectedJobElement
00482 v
00483 CIMInstanceName # expect_class
00484 If flag_out_array is True, return the first element of out[out_key].
00485 """
00486 (rc, out) = self._wbem_conn.InvokeMethod(cmd, cim_path, **in_params)
00487
00488 try:
00489 if rc == SmisCommon.SNIA_INVOKE_OK:
00490 if out_key is None:
00491 return None
00492 if out_key in out:
00493 if flag_out_array:
00494 if len(out[out_key]) == 1:
00495 return out[out_key][0]
00496 else:
00497 raise LsmError(
00498 ErrorNumber.PLUGIN_BUG,
00499 "invoke_method_wait(), output contains %d " %
00500 len(out[out_key]) +
00501 "elements: %s" % out[out_key])
00502 return out[out_key]
00503 else:
00504 raise LsmError(ErrorNumber.PLUGIN_BUG,
00505 "invoke_method_wait(), %s not exist "
00506 "in out %s" % (out_key, out.items()))
00507
00508 elif rc == SmisCommon.SNIA_INVOKE_ASYNC:
00509 cim_job_path = out['Job']
00510 loop_counter = 0
00511 job_pros = ['JobState', 'ErrorDescription',
00512 'OperationalStatus']
00513 cim_xxxs_path = []
00514 while(loop_counter <= SmisCommon._INVOKE_MAX_LOOP_COUNT):
00515 cim_job = self.GetInstance(cim_job_path,
00516 PropertyList=job_pros)
00517 job_state = cim_job['JobState']
00518 if job_state in (dmtf.JOB_STATE_NEW,
00519 dmtf.JOB_STATE_STARTING,
00520 dmtf.JOB_STATE_RUNNING):
00521 loop_counter += 1
00522 time.sleep(SmisCommon._INVOKE_CHECK_INTERVAL)
00523 continue
00524 elif job_state == dmtf.JOB_STATE_COMPLETED:
00525 if not SmisCommon.cim_job_completed_ok(cim_job):
00526 raise LsmError(
00527 ErrorNumber.PLUGIN_BUG,
00528 str(cim_job['ErrorDescription']))
00529 if expect_class is None:
00530 return None
00531 cim_xxxs_path = self.AssociatorNames(
00532 cim_job.path,
00533 AssocClass='CIM_AffectedJobElement',
00534 ResultClass=expect_class)
00535 break
00536 else:
00537 raise LsmError(
00538 ErrorNumber.PLUGIN_BUG,
00539 "invoke_method_wait(): Got unknown job state "
00540 "%d: %s" % (job_state, cim_job.items()))
00541
00542 if loop_counter > SmisCommon._INVOKE_MAX_LOOP_COUNT:
00543 raise LsmError(
00544 ErrorNumber.TIMEOUT,
00545 "The job generated by %s() failed to finish in %ds" %
00546 (cmd,
00547 SmisCommon._INVOKE_CHECK_INTERVAL *
00548 SmisCommon._INVOKE_MAX_LOOP_COUNT))
00549
00550 if len(cim_xxxs_path) == 1:
00551 return cim_xxxs_path[0]
00552 else:
00553 raise LsmError(
00554 ErrorNumber.PLUGIN_BUG,
00555 "invoke_method_wait(): got unexpected(not 1) "
00556 "return from CIM_AffectedJobElement: "
00557 "%s, out: %s, job: %s" %
00558 (cim_xxxs_path, out.items(), cim_job.items()))
00559 else:
00560 self._dump_wbem_xml(cmd)
00561 raise LsmError(
00562 ErrorNumber.PLUGIN_BUG,
00563 "invoke_method_wait(): Got unexpected rc code "
00564 "%d, out: %s" % (rc, out.items()))
00565 except Exception:
00566 exc_info = sys.exc_info()
00567
00568
00569 self._dump_wbem_xml(cmd)
00570 raise exc_info[0], exc_info[1], exc_info[2]
00571
00572 def _cim_srv_of_sys_id(self, srv_name, sys_id, raise_error):
00573 property_list = ['SystemName']
00574
00575 try:
00576 cim_srvs = self.EnumerateInstances(
00577 srv_name,
00578 PropertyList=property_list)
00579 for cim_srv in cim_srvs:
00580 if cim_srv['SystemName'] == sys_id:
00581 return cim_srv
00582 except CIMError:
00583 if raise_error:
00584 raise
00585 else:
00586 return None
00587
00588 if raise_error:
00589 raise LsmError(
00590 ErrorNumber.NO_SUPPORT,
00591 "Cannot find any '%s' for requested system ID" % srv_name)
00592 return None
00593
00594 def cim_scs_of_sys_id(self, sys_id, raise_error=True):
00595 """
00596 Return a CIMInstance of CIM_StorageConfigurationService for given
00597 system id.
00598 Using 'SystemName' property as system id of a service which is defined
00599 by DMTF CIM_Service.
00600 """
00601 return self._cim_srv_of_sys_id(
00602 'CIM_StorageConfigurationService', sys_id, raise_error)
00603
00604 def cim_rs_of_sys_id(self, sys_id, raise_error=True):
00605 """
00606 Return a CIMInstance of CIM_ReplicationService for given system id.
00607 Using 'SystemName' property as system id of a service which is defined
00608 by DMTF CIM_Service.
00609 """
00610 return self._cim_srv_of_sys_id(
00611 'CIM_ReplicationService', sys_id, raise_error)
00612
00613 def cim_gmms_of_sys_id(self, sys_id, raise_error=True):
00614 """
00615 Return a CIMInstance of CIM_GroupMaskingMappingService for given system
00616 id.
00617 Using 'SystemName' property as system id of a service which is defined
00618 by DMTF CIM_Service.
00619 """
00620 return self._cim_srv_of_sys_id(
00621 'CIM_GroupMaskingMappingService', sys_id, raise_error)
00622
00623 def cim_ccs_of_sys_id(self, sys_id, raise_error=True):
00624 """
00625 Return a CIMInstance of CIM_ControllerConfigurationService for given
00626 system id.
00627 Using 'SystemName' property as system id of a service which is defined
00628 by DMTF CIM_Service.
00629 """
00630 return self._cim_srv_of_sys_id(
00631 'CIM_ControllerConfigurationService', sys_id, raise_error)
00632
00633 def cim_hwms_of_sys_id(self, sys_id, raise_error=True):
00634 """
00635 Return a CIMInstance of CIM_StorageHardwareIDManagementService for
00636 given system id.
00637 Using 'SystemName' property as system id of a service which is defined
00638 by DMTF CIM_Service.
00639 """
00640 return self._cim_srv_of_sys_id(
00641 'CIM_StorageHardwareIDManagementService', sys_id, raise_error)
00642
00643 @staticmethod
00644 def cim_job_completed_ok(status):
00645 """
00646 Given a concrete job instance, check the operational status. This
00647 is a little convoluted as different SMI-S proxies return the values in
00648 different positions in list :-)
00649 """
00650 rc = False
00651 op = status['OperationalStatus']
00652
00653 if (len(op) > 1 and
00654 ((op[0] == dmtf.OP_STATUS_OK and
00655 op[1] == dmtf.OP_STATUS_COMPLETED) or
00656 (op[0] == dmtf.OP_STATUS_COMPLETED and
00657 op[1] == dmtf.OP_STATUS_OK))):
00658 rc = True
00659
00660 return rc