Tony Asleson
2014-10-07 19:23:28 UTC
From: Gris Ge <***@redhat.com>
* Remove fallback mode as no array really need them.
All SMI-S provider I have access support DMTF profile register and support
SMI-S 1.4 'Array' profile[1].
* New method: SmisCommon.is_netappe() for NetApp-E vendor code check.
* Simply move eseries.py codes into smis.py using SmisCommon.is_netappe()
check.
* Remove eseries.py file.
* Makefile and RPM spec file updated.
* SmisProxy is not needed any more after eseries.py got removed.
* Vendor specific code will be stored in smis.py or future sub
module/namespace of smis.py.
* Makefile and RPM spec file updated.
Changes in V2:
* Fixed a NetApp-E bug:
Old:
self._vendor_namespace = SmisCommon._PRODUCT_NETAPP_E
def is_netappe(self):
return self._vendor_product == SmisCommon._PRODUCT_MEGARAID
New:
self._vendor_product = SmisCommon._PRODUCT_NETAPP_E
def is_netappe(self):
return self._vendor_product == SmisCommon._PRODUCT_NETAPP_E
[1] LSI/Avago MegaRAID is using 1.2 and using vendor specific code in this
plugin.
Signed-off-by: Gris Ge <***@redhat.com>
---
packaging/libstoragemgmt.spec.in | 2 -
plugin/Makefile.am | 2 -
plugin/smispy/eseries.py | 164 --------------------------
plugin/smispy/smis.py | 246 +++++++++++++++++++--------------------
plugin/smispy/smis_common.py | 8 ++
plugin/smispy/smisproxy.py | 51 --------
plugin/smispy/smispy_lsmplugin | 4 +-
7 files changed, 130 insertions(+), 347 deletions(-)
delete mode 100644 plugin/smispy/eseries.py
delete mode 100644 plugin/smispy/smisproxy.py
diff --git a/packaging/libstoragemgmt.spec.in b/packaging/libstoragemgmt.spec.in
index 798d2f4..c9414df 100644
--- a/packaging/libstoragemgmt.spec.in
+++ b/packaging/libstoragemgmt.spec.in
@@ -312,9 +312,7 @@ fi
%files smis-plugin
%defattr(-,root,root,-)
%{python_sitelib}/lsm/plugin/smispy/__init__.*
-%{python_sitelib}/lsm/plugin/smispy/eseries.*
%{python_sitelib}/lsm/plugin/smispy/smis.*
-%{python_sitelib}/lsm/plugin/smispy/smisproxy.*
%{python_sitelib}/lsm/plugin/smispy/dmtf.*
%{python_sitelib}/lsm/plugin/smispy/utils.*
%{python_sitelib}/lsm/plugin/smispy/smis_common.*
diff --git a/plugin/Makefile.am b/plugin/Makefile.am
index a4605ab..424ad93 100644
--- a/plugin/Makefile.am
+++ b/plugin/Makefile.am
@@ -25,8 +25,6 @@ smispydir = $(plugindir)/smispy
smispy_PYTHON = \
smispy/__init__.py \
smispy/smis.py \
- smispy/smisproxy.py \
- smispy/eseries.py \
smispy/utils.py \
smispy/smis_common.py \
smispy/dmtf.py
diff --git a/plugin/smispy/eseries.py b/plugin/smispy/eseries.py
deleted file mode 100644
index c493a47..0000000
--- a/plugin/smispy/eseries.py
+++ /dev/null
@@ -1,164 +0,0 @@
-# Copyright (C) 2011-2014 Red Hat, Inc.
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2.1 of the License, or any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# 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 smis import Smis
-from string import split
-import pywbem
-import time
-from lsm.plugin.smispy.smis import handle_cim_errors
-from lsm import LsmError, ErrorNumber, uri_parse
-
-
-class ESeries(Smis):
- def plugin_register(self, uri, password, timeout, flags=0):
- """
- The only difference we did here compare to supper method:
- we force to be fallback mode.
- NetApp-E support 'Masking and Mapping' profile but not expose it
- via CIM_RegisteredProfile.
- """
- protocol = 'http'
- port = Smis.IAAN_WBEM_HTTP_PORT
- u = uri_parse(uri, ['scheme', 'netloc', 'host'], None)
-
- if u['scheme'].lower() == 'smispy+ssl':
- protocol = 'https'
- port = Smis.IAAN_WBEM_HTTPS_PORT
-
- if 'port' in u:
- port = u['port']
-
- # smisproxy.py already make sure namespace defined.
- namespace = u['parameters']['namespace']
- self.all_vendor_namespaces = [namespace]
-
- url = "%s://%s:%s" % (protocol, u['host'], port)
- self.system_list = None
- if 'systems' in u['parameters']:
- self.system_list = split(u['parameters']["systems"], ":")
-
- self._c = pywbem.WBEMConnection(url, (u['username'], password),
- namespace)
- if "no_ssl_verify" in u["parameters"] \
- and u["parameters"]["no_ssl_verify"] == 'yes':
- try:
- self._c = pywbem.WBEMConnection(
- url,
- (u['username'], password),
- namespace,
- no_verification=True)
- except TypeError:
- # pywbem is not holding fix from
- # https://bugzilla.redhat.com/show_bug.cgi?id=1039801
- pass
-
- self.tmo = timeout
- self.fallback_mode = True
-
- def _deal_volume_associations(self, vol, lun):
- """
- Check a volume to see if it has any associations with other
- volumes.
- """
- rc = False
- lun_path = lun.path
-
- ss = self._c.References(lun_path,
- ResultClass='CIM_StorageSynchronized')
-
- if len(ss):
- for s in ss:
- if 'SyncedElement' in s:
- item = s['SyncedElement']
-
- if Smis._cim_name_match(item, lun_path):
- self._detach(vol, s)
- rc = True
-
- if 'SystemElement' in s:
- item = s['SystemElement']
-
- if Smis._cim_name_match(item, lun_path):
- self._detach(vol, s)
- rc = True
-
- return rc
-
- def _is_access_group(self, s):
- return True
-
- @handle_cim_errors
- def capabilities(self, system, flags=0):
- cap = self._common_capabilities(system)
-
- #TODO We need to investigate why our interrogation code doesn't work.
- #The array is telling us one thing, but when we try to use it, it
- #doesn't work
- return cap
-
- def _detach(self, vol, sync):
-
- #Get the Configuration service for the system we are interested in.
- scs = self._get_class_instance('CIM_StorageConfigurationService',
- 'SystemName', vol.system_id)
-
- in_params = {'Operation': pywbem.Uint16(2),
- 'Synchronization': sync.path}
-
- job_id = self._pi("_detach", Smis.JOB_RETRIEVE_NONE,
- *(self._c.InvokeMethod(
- 'ModifySynchronization', scs.path,
- **in_params)))[0]
-
- self._poll("ModifySynchronization, detach", job_id)
-
- @handle_cim_errors
- def volume_delete(self, volume, flags=0):
- scs = self._get_class_instance('CIM_StorageConfigurationService',
- 'SystemName', volume.system_id)
- lun = self._get_cim_instance_by_id('Volume', volume.id)
-
- #If we actually have an association to delete, the volume will be
- #deleted with the association, no need to call ReturnToStoragePool
- if not self._deal_volume_associations(volume, lun):
- in_params = {'TheElement': lun.path}
-
- #Delete returns None or Job number
- return self._pi("volume_delete", Smis.JOB_RETRIEVE_NONE,
- *(self._c.InvokeMethod('ReturnToStoragePool',
- scs.path, **in_params)))[0]
-
- #Loop to check to see if volume is actually gone yet!
- try:
- lun = self._get_cim_instance_by_id('Volume', volume.id)
- while lun is not None:
- lun = self._get_cim_instance_by_id('Volume', volume.id)
- time.sleep(0.125)
- except LsmError as e:
- pass
-
- @handle_cim_errors
- def access_group_initiator_delete(self, access_group, init_id, init_type,
- flags=0):
- """
- When using HidePaths to remove initiator, the whole SPC will be
- removed. Before we find a workaround for this, I would like to have
- this method disabled as NO_SUPPORT.
- """
- raise LsmError(ErrorNumber.NO_SUPPORT,
- "SMI-S plugin does not support "
- "access_group_initiator_delete() against NetApp-E")
diff --git a/plugin/smispy/smis.py b/plugin/smispy/smis.py
index 3238b86..7ba694b 100644
--- a/plugin/smispy/smis.py
+++ b/plugin/smispy/smis.py
@@ -384,7 +384,6 @@ class Smis(IStorageAreaNetwork):
self._c = None
self.tmo = 0
self.system_list = None
- self.fallback_mode = True # Means we cannot use profile register
self.debug_path = None
def _get_cim_instance_by_id(self, class_type, requested_id,
@@ -566,20 +565,6 @@ class Smis(IStorageAreaNetwork):
volume_resize()
volume_delete()
"""
- if self.fallback_mode:
- # pools() is mandatory, we will try pools() related methods first
- try:
- self._cim_pools_of(cim_sys_path)
- except CIMError as e:
- if e[0] == pywbem.CIM_ERR_NOT_SUPPORTED or \
- e[0] == pywbem.CIM_ERR_INVALID_CLASS:
- raise LsmError(ErrorNumber.NO_SUPPORT,
- "Target SMI-S provider does not support "
- "CIM_StoragePool querying which is "
- "mandatory for pools() method")
- else:
- raise
-
# CIM_StorageConfigurationService is optional.
cim_scs_path = self._get_cim_service_path(
cim_sys_path, 'CIM_StorageConfigurationService')
@@ -631,22 +616,10 @@ class Smis(IStorageAreaNetwork):
return
def _disk_cap_set(self, cim_sys_path, cap):
- if self.fallback_mode:
- try:
- # Assuming provider support disk drive when systems under it
- # support it.
- self._c.EnumerateInstanceNames('CIM_DiskDrive')
- except CIMError as e:
- if e[0] == pywbem.CIM_ERR_NOT_SUPPORTED or \
- e[0] == pywbem.CIM_ERR_INVALID_CLASS:
- return
- else:
- raise
- else:
- if not self._c.profile_check(SmisCommon.SNIA_DISK_LITE_PROFILE,
- SmisCommon.SMIS_SPEC_VER_1_4,
- raise_error=False):
- return
+ if not self._c.profile_check(SmisCommon.SNIA_DISK_LITE_PROFILE,
+ SmisCommon.SMIS_SPEC_VER_1_4,
+ raise_error=False):
+ return
cap.set(Capabilities.DISKS)
return
@@ -723,21 +696,10 @@ class Smis(IStorageAreaNetwork):
In SNIA SMI-S 1.4rev6 'Masking and Mapping' profile:
CIM_ControllerConfigurationService is mandatory
and it's ExposePaths() and HidePaths() are mandatory
-
- For fallback mode, once we found CIM_ControllerConfigurationService,
- we assume they are supporting 1.4rev6 'Masking and Mapping' profile.
- Fallback mode means target provider does not support interop, but
- they still need to follow at least SNIA SMI-S 1.4rev6
"""
- if self.fallback_mode:
- cim_ccs_path = self._get_cim_service_path(
- cim_sys_path, 'CIM_ControllerConfigurationService')
- if cim_ccs_path is None:
- return
-
- elif not self._c.profile_check(SmisCommon.SNIA_MASK_PROFILE,
- SmisCommon.SMIS_SPEC_VER_1_4,
- raise_error=False):
+ if not self._c.profile_check(SmisCommon.SNIA_MASK_PROFILE,
+ SmisCommon.SMIS_SPEC_VER_1_4,
+ raise_error=False):
return
cap.set(Capabilities.ACCESS_GROUPS)
@@ -771,43 +733,23 @@ class Smis(IStorageAreaNetwork):
if cim_sys_path.classname == 'LSIESG_MegaRAIDHBA':
return
- flag_fc_support = False
- flag_iscsi_support = False
- if self.fallback_mode:
- flag_fc_support = True
- flag_iscsi_support = True
- # CIM_FCPort is the control class of FC Targets profile
- try:
- self._cim_fc_tgt_of(cim_sys_path)
- except CIMError as e:
- if e[0] == pywbem.CIM_ERR_NOT_SUPPORTED or \
- e[0] == pywbem.CIM_ERR_INVALID_CLASS:
- flag_fc_support = False
-
- try:
- self._cim_iscsi_pg_of(cim_sys_path)
- except CIMError as e:
- if e[0] == pywbem.CIM_ERR_NOT_SUPPORTED or \
- e[0] == pywbem.CIM_ERR_INVALID_CLASS:
- flag_iscsi_support = False
- else:
+ flag_fc_support = self._c.profile_check(
+ SmisCommon.SNIA_FC_TGT_PORT_PROFILE,
+ SmisCommon.SMIS_SPEC_VER_1_4,
+ raise_error=False)
+ # One more check for NetApp Typo:
+ # NetApp: 'FC Target Port'
+ # SMI-S: 'FC Target Ports'
+ # Bug reported.
+ if not flag_fc_support:
flag_fc_support = self._c.profile_check(
- SmisCommon.SNIA_FC_TGT_PORT_PROFILE,
- SmisCommon.SMIS_SPEC_VER_1_4,
- raise_error=False)
- # One more check for NetApp Typo:
- # NetApp: 'FC Target Port'
- # SMI-S: 'FC Target Ports'
- # Bug reported.
- if not flag_fc_support:
- flag_fc_support = self._c.profile_check(
- 'FC Target Port',
- SmisCommon.SMIS_SPEC_VER_1_4,
- raise_error=False)
- flag_iscsi_support = self._c.profile_check(
- SmisCommon.SNIA_ISCSI_TGT_PORT_PROFILE,
+ 'FC Target Port',
SmisCommon.SMIS_SPEC_VER_1_4,
raise_error=False)
+ flag_iscsi_support = self._c.profile_check(
+ SmisCommon.SNIA_ISCSI_TGT_PORT_PROFILE,
+ SmisCommon.SMIS_SPEC_VER_1_4,
+ raise_error=False)
if flag_fc_support or flag_iscsi_support:
cap.set(Capabilities.TARGET_PORTS)
@@ -877,6 +819,14 @@ class Smis(IStorageAreaNetwork):
@handle_cim_errors
def capabilities(self, system, flags=0):
+ if self._c.is_netappe():
+ cap = self._common_capabilities(system)
+
+ #TODO We need to investigate why our interrogation code doesn't
+ #work.
+ #The array is telling us one thing, but when we try to use it, it
+ #doesn't work
+ return cap
cim_sys = self._get_cim_instance_by_id(
'System', system.id, raise_error=True)
@@ -1698,7 +1648,25 @@ class Smis(IStorageAreaNetwork):
ErrorNumber.PLUGIN_BUG,
msg + ", job error code= " + str(s))
+ def _detach_netapp_e(self, vol, sync):
+ #Get the Configuration service for the system we are interested in.
+ scs = self._get_class_instance('CIM_StorageConfigurationService',
+ 'SystemName', vol.system_id)
+
+ in_params = {'Operation': pywbem.Uint16(2),
+ 'Synchronization': sync.path}
+
+ job_id = self._pi("_detach", Smis.JOB_RETRIEVE_NONE,
+ *(self._c.InvokeMethod(
+ 'ModifySynchronization', scs.path,
+ **in_params)))[0]
+
+ self._poll("ModifySynchronization, detach", job_id)
+
def _detach(self, vol, sync):
+ if self._c.is_netappe():
+ return self._detach_netapp_e(vol, sync)
+
rs = self._get_class_instance("CIM_ReplicationService", 'SystemName',
vol.system_id, raise_error=False)
@@ -1723,11 +1691,43 @@ class Smis(IStorageAreaNetwork):
else:
return False
+ def _deal_volume_associations_netappe(self, vol, lun):
+ """
+ Check a volume to see if it has any associations with other
+ volumes.
+ """
+ rc = False
+ lun_path = lun.path
+
+ ss = self._c.References(lun_path,
+ ResultClass='CIM_StorageSynchronized')
+
+ if len(ss):
+ for s in ss:
+ if 'SyncedElement' in s:
+ item = s['SyncedElement']
+
+ if Smis._cim_name_match(item, lun_path):
+ self._detach(vol, s)
+ rc = True
+
+ if 'SystemElement' in s:
+ item = s['SystemElement']
+
+ if Smis._cim_name_match(item, lun_path):
+ self._detach(vol, s)
+ rc = True
+
+ return rc
+
def _deal_volume_associations(self, vol, lun):
"""
Check a volume to see if it has any associations with other
volumes and deal with them.
"""
+ if self._c.is_netappe():
+ return self._deal_volume_associations_netappe(vol, lun)
+
lun_path = lun.path
try:
@@ -1771,6 +1771,30 @@ class Smis(IStorageAreaNetwork):
if Smis._cim_name_match(item, lun_path):
self._detach(vol, s)
+ def _volume_delete_netapp_e(self, volume, flags=0):
+ scs = self._get_class_instance('CIM_StorageConfigurationService',
+ 'SystemName', volume.system_id)
+ lun = self._get_cim_instance_by_id('Volume', volume.id)
+
+ #If we actually have an association to delete, the volume will be
+ #deleted with the association, no need to call ReturnToStoragePool
+ if not self._deal_volume_associations(volume, lun):
+ in_params = {'TheElement': lun.path}
+
+ #Delete returns None or Job number
+ return self._pi("volume_delete", Smis.JOB_RETRIEVE_NONE,
+ *(self._c.InvokeMethod('ReturnToStoragePool',
+ scs.path, **in_params)))[0]
+
+ #Loop to check to see if volume is actually gone yet!
+ try:
+ lun = self._get_cim_instance_by_id('Volume', volume.id)
+ while lun is not None:
+ lun = self._get_cim_instance_by_id('Volume', volume.id)
+ time.sleep(0.125)
+ except LsmError as e:
+ pass
+
@handle_cim_errors
def volume_delete(self, volume, flags=0):
"""
@@ -2318,6 +2342,9 @@ class Smis(IStorageAreaNetwork):
return None
def _is_access_group(self, cim_spc):
+ if self._c.is_netappe:
+ return True
+
rc = True
_SMIS_EMC_ADAPTER_ROLE_MASKING = 'MASK_VIEW'
@@ -2441,10 +2468,9 @@ class Smis(IStorageAreaNetwork):
if property_list is None:
property_list = []
- if (not self.fallback_mode and
- self._c.profile_check(SmisCommon.SNIA_MASK_PROFILE,
- SmisCommon.SMIS_SPEC_VER_1_6,
- raise_error=False)):
+ if self._c.profile_check(SmisCommon.SNIA_MASK_PROFILE,
+ SmisCommon.SMIS_SPEC_VER_1_6,
+ raise_error=False):
return self._c.Associators(
cim_spc_path,
AssocClass='CIM_AssociatedPrivilege',
@@ -2616,15 +2642,12 @@ class Smis(IStorageAreaNetwork):
def _mask_type(self, raise_error=False):
"""
Return Smis.MASK_TYPE_NO_SUPPORT, MASK_TYPE_MASK or MASK_TYPE_GROUP
- For fallback_mode, return MASK_TYPE_MASK
if 'Group Masking and Mapping' profile is supported, return
MASK_TYPE_GROUP
If raise_error == False, just return Smis.MASK_TYPE_NO_SUPPORT
or, raise NO_SUPPORT error.
"""
- if self.fallback_mode:
- return Smis.MASK_TYPE_MASK
if self._c.profile_check(SmisCommon.SNIA_GROUP_MASK_PROFILE,
SmisCommon.SMIS_SPEC_VER_1_5,
raise_error=False):
@@ -2867,6 +2890,13 @@ class Smis(IStorageAreaNetwork):
@handle_cim_errors
def access_group_initiator_delete(self, access_group, init_id, init_type,
flags=0):
+ if self._c.is_netappe():
+ # When using HidePaths to remove initiator, the whole SPC will be
+ # removed. Before we find a workaround for this, I would like to
+ # have this method disabled as NO_SUPPORT.
+ raise LsmError(ErrorNumber.NO_SUPPORT,
+ "SMI-S plugin does not support "
+ "access_group_initiator_delete() against NetApp-E")
init_id = _lsm_init_id_to_snia(init_id)
mask_type = self._mask_type(raise_error=True)
@@ -2922,10 +2952,9 @@ class Smis(IStorageAreaNetwork):
by ourselves in case URI contain 'system=xxx'.
"""
rc = []
- if not self.fallback_mode:
- self._c.profile_check(SmisCommon.SNIA_DISK_LITE_PROFILE,
- SmisCommon.SMIS_SPEC_VER_1_4,
- raise_error=True)
+ self._c.profile_check(SmisCommon.SNIA_DISK_LITE_PROFILE,
+ SmisCommon.SMIS_SPEC_VER_1_4,
+ raise_error=True)
cim_disk_pros = Smis._new_disk_cim_disk_pros(flags)
cim_disks = self._c.EnumerateInstances(
'CIM_DiskDrive', PropertyList=cim_disk_pros)
@@ -3192,17 +3221,7 @@ class Smis(IStorageAreaNetwork):
def _fc_tgt_is_supported(self, cim_sys_path):
"""
Return True if FC Target Port 1.4+ profile is supported.
- For fallback_mode, we call self._cim_fc_tgt_of() and do try-except
"""
- if self.fallback_mode:
- try:
- self._cim_fc_tgt_of(cim_sys_path)
- except CIMError as e:
- if e[0] == pywbem.CIM_ERR_NOT_SUPPORTED or \
- e[0] == pywbem.CIM_ERR_INVALID_CLASS:
- return False
- return True
-
flag_fc_support = self._c.profile_check(
SmisCommon.SNIA_FC_TGT_PORT_PROFILE,
SmisCommon.SMIS_SPEC_VER_1_4,
@@ -3224,22 +3243,9 @@ class Smis(IStorageAreaNetwork):
def _iscsi_tgt_is_supported(self, cim_sys_path):
"""
Return True if FC Target Port 1.4+ profile is supported.
- For fallback_mode, we call self._cim_iscsi_pg_of() and do try-except
- For fallback_mode:
- Even CIM_EthernetPort is the control class of iSCSI Target
- Ports profile, but that class is optional. :(
We use CIM_iSCSIProtocolEndpoint as it's a start point we are
using in our code of target_ports().
"""
- if self.fallback_mode:
- try:
- self._cim_iscsi_pg_of(cim_sys_path)
- except CIMError as e:
- if e[0] == pywbem.CIM_ERR_NOT_SUPPORTED or \
- e[0] == pywbem.CIM_ERR_INVALID_CLASS:
- return False
- return True
-
if self._c.profile_check(SmisCommon.SNIA_ISCSI_TGT_PORT_PROFILE,
SmisCommon.SMIS_SPEC_VER_1_4,
raise_error=False):
@@ -3249,11 +3255,8 @@ class Smis(IStorageAreaNetwork):
def _multi_sys_is_supported(self):
"""
Return True if Multiple ComputerSystem 1.4+ profile is supported.
- For fallback_mode, always return True.
Return False else.
"""
- if self.fallback_mode:
- return True
flag_multi_sys_support = self._c.profile_check(
SmisCommon.SNIA_MULTI_SYS_PROFILE,
SmisCommon.SMIS_SPEC_VER_1_4,
@@ -3566,7 +3569,7 @@ class Smis(IStorageAreaNetwork):
"these profiles: '%s %s', '%s %s'"
% (SmisCommon.SMIS_SPEC_VER_1_4,
SmisCommon.SNIA_FC_TGT_PORT_PROFILE,
- SmisCommon.SMIS_SPEC_VER_1_4,
+ SmisCommon.SMIS_SPEC_VER_1_4,
SmisCommon.SNIA_ISCSI_TGT_PORT_PROFILE))
if flag_fc_support:
@@ -3764,10 +3767,6 @@ class Smis(IStorageAreaNetwork):
"""
org_init_id = init_id
init_id = _lsm_init_id_to_snia(init_id)
- if self.fallback_mode:
- raise LsmError(ErrorNumber.NO_SUPPORT,
- "access_group_create() is not supported in "
- "fallback mode")
self._c.profile_check(SmisCommon.SNIA_GROUP_MASK_PROFILE,
SmisCommon.SMIS_SPEC_VER_1_5,
@@ -3868,11 +3867,6 @@ class Smis(IStorageAreaNetwork):
return self._cim_init_mg_to_lsm(cim_init_mg, system.id)
def access_group_delete(self, access_group, flags=0):
- if self.fallback_mode:
- raise LsmError(ErrorNumber.NO_SUPPORT,
- "access_group_create() is not supported in "
- "fallback mode")
-
self._c.profile_check(
SmisCommon.SNIA_GROUP_MASK_PROFILE, SmisCommon.SMIS_SPEC_VER_1_5,
raise_error=True)
diff --git a/plugin/smispy/smis_common.py b/plugin/smispy/smis_common.py
index 27aa227..cf01b8f 100644
--- a/plugin/smispy/smis_common.py
+++ b/plugin/smispy/smis_common.py
@@ -153,7 +153,9 @@ class SmisCommon(object):
SMIS_SPEC_VER_1_6 = '1.6'
SNIA_REG_ORG_CODE = Uint16(11)
_MEGARAID_NAMESPACE = 'root/LsiMr13'
+ _NETAPP_E_NAMESPACE = 'root/LsiArray13'
_PRODUCT_MEGARAID = 'LSI MegaRAID'
+ _PRODUCT_NETAPP_E = 'NetApp-E'
def __init__(self, url, username, password,
namespace=DMTF.DEFAULT_NAMESPACE,
@@ -197,6 +199,9 @@ class SmisCommon(object):
(self._profile_dict, self.root_blk_cim_rp) = \
_profile_register_load(self._wbem_conn)
+ if namespace.lower() == SmisCommon._NETAPP_E_NAMESPACE.lower():
+ self._vendor_product = SmisCommon._PRODUCT_NETAPP_E
+
# Check 'Array' 1.4 support status.
_profile_check(
self._profile_dict, SmisCommon.SNIA_BLK_ROOT_PROFILE,
@@ -284,3 +289,6 @@ class SmisCommon(object):
def is_megaraid(self):
return self._vendor_product == SmisCommon._PRODUCT_MEGARAID
+
+ def is_netappe(self):
+ return self._vendor_product == SmisCommon._PRODUCT_NETAPP_E
diff --git a/plugin/smispy/smisproxy.py b/plugin/smispy/smisproxy.py
deleted file mode 100644
index 19a32ce..0000000
--- a/plugin/smispy/smisproxy.py
+++ /dev/null
@@ -1,51 +0,0 @@
-# Copyright (C) 2012 Red Hat, Inc.
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2.1 of the License, or any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# 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 smis import Smis
-from lsm import Proxy, VERSION
-import eseries
-
-#The unfortunate truth is that each of the vendors implements functionality
-#slightly differently so we will need to have some special code for these
-#instances.
-
-
-class SmisProxy(Proxy):
- """
- Layer to allow us to swap out different implementations of smi-s clients
- based on provider.
- """
- def plugin_info(self, flags=0):
- return "Generic SMI-S support", VERSION
-
- def plugin_register(self, uri, password, timeout, flags=0):
- """
- We will provide a concrete implementation of this to get the process
- started. All other method will be delegated to implementation.
- """
-
- #TODO Add code to interrogate the provider and then based on the type
- #we will instantiate the most appropriate implementation. At the
- #moment we will drop back to our current mixed implementation.
-
- #TODO We need to do a better job at check for this.
- if 'root/lsiarray13' in uri.lower():
- self.proxied_obj = eseries.ESeries()
- else:
- self.proxied_obj = Smis()
-
- self.proxied_obj.plugin_register(uri, password, timeout, flags)
diff --git a/plugin/smispy/smispy_lsmplugin b/plugin/smispy/smispy_lsmplugin
index de87c7d..b0ea003 100755
--- a/plugin/smispy/smispy_lsmplugin
+++ b/plugin/smispy/smispy_lsmplugin
@@ -23,10 +23,10 @@ import traceback
try:
from lsm import PluginRunner
- from lsm.plugin.smispy.smisproxy import SmisProxy
+ from lsm.plugin.smispy.smis import Smis
if __name__ == '__main__':
- PluginRunner(SmisProxy, sys.argv).run()
+ PluginRunner(Smis, sys.argv).run()
except Exception:
#This should be quite rare, but when it does happen this is pretty
#key in understanding what happened, especially when it happens when
* Remove fallback mode as no array really need them.
All SMI-S provider I have access support DMTF profile register and support
SMI-S 1.4 'Array' profile[1].
* New method: SmisCommon.is_netappe() for NetApp-E vendor code check.
* Simply move eseries.py codes into smis.py using SmisCommon.is_netappe()
check.
* Remove eseries.py file.
* Makefile and RPM spec file updated.
* SmisProxy is not needed any more after eseries.py got removed.
* Vendor specific code will be stored in smis.py or future sub
module/namespace of smis.py.
* Makefile and RPM spec file updated.
Changes in V2:
* Fixed a NetApp-E bug:
Old:
self._vendor_namespace = SmisCommon._PRODUCT_NETAPP_E
def is_netappe(self):
return self._vendor_product == SmisCommon._PRODUCT_MEGARAID
New:
self._vendor_product = SmisCommon._PRODUCT_NETAPP_E
def is_netappe(self):
return self._vendor_product == SmisCommon._PRODUCT_NETAPP_E
[1] LSI/Avago MegaRAID is using 1.2 and using vendor specific code in this
plugin.
Signed-off-by: Gris Ge <***@redhat.com>
---
packaging/libstoragemgmt.spec.in | 2 -
plugin/Makefile.am | 2 -
plugin/smispy/eseries.py | 164 --------------------------
plugin/smispy/smis.py | 246 +++++++++++++++++++--------------------
plugin/smispy/smis_common.py | 8 ++
plugin/smispy/smisproxy.py | 51 --------
plugin/smispy/smispy_lsmplugin | 4 +-
7 files changed, 130 insertions(+), 347 deletions(-)
delete mode 100644 plugin/smispy/eseries.py
delete mode 100644 plugin/smispy/smisproxy.py
diff --git a/packaging/libstoragemgmt.spec.in b/packaging/libstoragemgmt.spec.in
index 798d2f4..c9414df 100644
--- a/packaging/libstoragemgmt.spec.in
+++ b/packaging/libstoragemgmt.spec.in
@@ -312,9 +312,7 @@ fi
%files smis-plugin
%defattr(-,root,root,-)
%{python_sitelib}/lsm/plugin/smispy/__init__.*
-%{python_sitelib}/lsm/plugin/smispy/eseries.*
%{python_sitelib}/lsm/plugin/smispy/smis.*
-%{python_sitelib}/lsm/plugin/smispy/smisproxy.*
%{python_sitelib}/lsm/plugin/smispy/dmtf.*
%{python_sitelib}/lsm/plugin/smispy/utils.*
%{python_sitelib}/lsm/plugin/smispy/smis_common.*
diff --git a/plugin/Makefile.am b/plugin/Makefile.am
index a4605ab..424ad93 100644
--- a/plugin/Makefile.am
+++ b/plugin/Makefile.am
@@ -25,8 +25,6 @@ smispydir = $(plugindir)/smispy
smispy_PYTHON = \
smispy/__init__.py \
smispy/smis.py \
- smispy/smisproxy.py \
- smispy/eseries.py \
smispy/utils.py \
smispy/smis_common.py \
smispy/dmtf.py
diff --git a/plugin/smispy/eseries.py b/plugin/smispy/eseries.py
deleted file mode 100644
index c493a47..0000000
--- a/plugin/smispy/eseries.py
+++ /dev/null
@@ -1,164 +0,0 @@
-# Copyright (C) 2011-2014 Red Hat, Inc.
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2.1 of the License, or any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# 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 smis import Smis
-from string import split
-import pywbem
-import time
-from lsm.plugin.smispy.smis import handle_cim_errors
-from lsm import LsmError, ErrorNumber, uri_parse
-
-
-class ESeries(Smis):
- def plugin_register(self, uri, password, timeout, flags=0):
- """
- The only difference we did here compare to supper method:
- we force to be fallback mode.
- NetApp-E support 'Masking and Mapping' profile but not expose it
- via CIM_RegisteredProfile.
- """
- protocol = 'http'
- port = Smis.IAAN_WBEM_HTTP_PORT
- u = uri_parse(uri, ['scheme', 'netloc', 'host'], None)
-
- if u['scheme'].lower() == 'smispy+ssl':
- protocol = 'https'
- port = Smis.IAAN_WBEM_HTTPS_PORT
-
- if 'port' in u:
- port = u['port']
-
- # smisproxy.py already make sure namespace defined.
- namespace = u['parameters']['namespace']
- self.all_vendor_namespaces = [namespace]
-
- url = "%s://%s:%s" % (protocol, u['host'], port)
- self.system_list = None
- if 'systems' in u['parameters']:
- self.system_list = split(u['parameters']["systems"], ":")
-
- self._c = pywbem.WBEMConnection(url, (u['username'], password),
- namespace)
- if "no_ssl_verify" in u["parameters"] \
- and u["parameters"]["no_ssl_verify"] == 'yes':
- try:
- self._c = pywbem.WBEMConnection(
- url,
- (u['username'], password),
- namespace,
- no_verification=True)
- except TypeError:
- # pywbem is not holding fix from
- # https://bugzilla.redhat.com/show_bug.cgi?id=1039801
- pass
-
- self.tmo = timeout
- self.fallback_mode = True
-
- def _deal_volume_associations(self, vol, lun):
- """
- Check a volume to see if it has any associations with other
- volumes.
- """
- rc = False
- lun_path = lun.path
-
- ss = self._c.References(lun_path,
- ResultClass='CIM_StorageSynchronized')
-
- if len(ss):
- for s in ss:
- if 'SyncedElement' in s:
- item = s['SyncedElement']
-
- if Smis._cim_name_match(item, lun_path):
- self._detach(vol, s)
- rc = True
-
- if 'SystemElement' in s:
- item = s['SystemElement']
-
- if Smis._cim_name_match(item, lun_path):
- self._detach(vol, s)
- rc = True
-
- return rc
-
- def _is_access_group(self, s):
- return True
-
- @handle_cim_errors
- def capabilities(self, system, flags=0):
- cap = self._common_capabilities(system)
-
- #TODO We need to investigate why our interrogation code doesn't work.
- #The array is telling us one thing, but when we try to use it, it
- #doesn't work
- return cap
-
- def _detach(self, vol, sync):
-
- #Get the Configuration service for the system we are interested in.
- scs = self._get_class_instance('CIM_StorageConfigurationService',
- 'SystemName', vol.system_id)
-
- in_params = {'Operation': pywbem.Uint16(2),
- 'Synchronization': sync.path}
-
- job_id = self._pi("_detach", Smis.JOB_RETRIEVE_NONE,
- *(self._c.InvokeMethod(
- 'ModifySynchronization', scs.path,
- **in_params)))[0]
-
- self._poll("ModifySynchronization, detach", job_id)
-
- @handle_cim_errors
- def volume_delete(self, volume, flags=0):
- scs = self._get_class_instance('CIM_StorageConfigurationService',
- 'SystemName', volume.system_id)
- lun = self._get_cim_instance_by_id('Volume', volume.id)
-
- #If we actually have an association to delete, the volume will be
- #deleted with the association, no need to call ReturnToStoragePool
- if not self._deal_volume_associations(volume, lun):
- in_params = {'TheElement': lun.path}
-
- #Delete returns None or Job number
- return self._pi("volume_delete", Smis.JOB_RETRIEVE_NONE,
- *(self._c.InvokeMethod('ReturnToStoragePool',
- scs.path, **in_params)))[0]
-
- #Loop to check to see if volume is actually gone yet!
- try:
- lun = self._get_cim_instance_by_id('Volume', volume.id)
- while lun is not None:
- lun = self._get_cim_instance_by_id('Volume', volume.id)
- time.sleep(0.125)
- except LsmError as e:
- pass
-
- @handle_cim_errors
- def access_group_initiator_delete(self, access_group, init_id, init_type,
- flags=0):
- """
- When using HidePaths to remove initiator, the whole SPC will be
- removed. Before we find a workaround for this, I would like to have
- this method disabled as NO_SUPPORT.
- """
- raise LsmError(ErrorNumber.NO_SUPPORT,
- "SMI-S plugin does not support "
- "access_group_initiator_delete() against NetApp-E")
diff --git a/plugin/smispy/smis.py b/plugin/smispy/smis.py
index 3238b86..7ba694b 100644
--- a/plugin/smispy/smis.py
+++ b/plugin/smispy/smis.py
@@ -384,7 +384,6 @@ class Smis(IStorageAreaNetwork):
self._c = None
self.tmo = 0
self.system_list = None
- self.fallback_mode = True # Means we cannot use profile register
self.debug_path = None
def _get_cim_instance_by_id(self, class_type, requested_id,
@@ -566,20 +565,6 @@ class Smis(IStorageAreaNetwork):
volume_resize()
volume_delete()
"""
- if self.fallback_mode:
- # pools() is mandatory, we will try pools() related methods first
- try:
- self._cim_pools_of(cim_sys_path)
- except CIMError as e:
- if e[0] == pywbem.CIM_ERR_NOT_SUPPORTED or \
- e[0] == pywbem.CIM_ERR_INVALID_CLASS:
- raise LsmError(ErrorNumber.NO_SUPPORT,
- "Target SMI-S provider does not support "
- "CIM_StoragePool querying which is "
- "mandatory for pools() method")
- else:
- raise
-
# CIM_StorageConfigurationService is optional.
cim_scs_path = self._get_cim_service_path(
cim_sys_path, 'CIM_StorageConfigurationService')
@@ -631,22 +616,10 @@ class Smis(IStorageAreaNetwork):
return
def _disk_cap_set(self, cim_sys_path, cap):
- if self.fallback_mode:
- try:
- # Assuming provider support disk drive when systems under it
- # support it.
- self._c.EnumerateInstanceNames('CIM_DiskDrive')
- except CIMError as e:
- if e[0] == pywbem.CIM_ERR_NOT_SUPPORTED or \
- e[0] == pywbem.CIM_ERR_INVALID_CLASS:
- return
- else:
- raise
- else:
- if not self._c.profile_check(SmisCommon.SNIA_DISK_LITE_PROFILE,
- SmisCommon.SMIS_SPEC_VER_1_4,
- raise_error=False):
- return
+ if not self._c.profile_check(SmisCommon.SNIA_DISK_LITE_PROFILE,
+ SmisCommon.SMIS_SPEC_VER_1_4,
+ raise_error=False):
+ return
cap.set(Capabilities.DISKS)
return
@@ -723,21 +696,10 @@ class Smis(IStorageAreaNetwork):
In SNIA SMI-S 1.4rev6 'Masking and Mapping' profile:
CIM_ControllerConfigurationService is mandatory
and it's ExposePaths() and HidePaths() are mandatory
-
- For fallback mode, once we found CIM_ControllerConfigurationService,
- we assume they are supporting 1.4rev6 'Masking and Mapping' profile.
- Fallback mode means target provider does not support interop, but
- they still need to follow at least SNIA SMI-S 1.4rev6
"""
- if self.fallback_mode:
- cim_ccs_path = self._get_cim_service_path(
- cim_sys_path, 'CIM_ControllerConfigurationService')
- if cim_ccs_path is None:
- return
-
- elif not self._c.profile_check(SmisCommon.SNIA_MASK_PROFILE,
- SmisCommon.SMIS_SPEC_VER_1_4,
- raise_error=False):
+ if not self._c.profile_check(SmisCommon.SNIA_MASK_PROFILE,
+ SmisCommon.SMIS_SPEC_VER_1_4,
+ raise_error=False):
return
cap.set(Capabilities.ACCESS_GROUPS)
@@ -771,43 +733,23 @@ class Smis(IStorageAreaNetwork):
if cim_sys_path.classname == 'LSIESG_MegaRAIDHBA':
return
- flag_fc_support = False
- flag_iscsi_support = False
- if self.fallback_mode:
- flag_fc_support = True
- flag_iscsi_support = True
- # CIM_FCPort is the control class of FC Targets profile
- try:
- self._cim_fc_tgt_of(cim_sys_path)
- except CIMError as e:
- if e[0] == pywbem.CIM_ERR_NOT_SUPPORTED or \
- e[0] == pywbem.CIM_ERR_INVALID_CLASS:
- flag_fc_support = False
-
- try:
- self._cim_iscsi_pg_of(cim_sys_path)
- except CIMError as e:
- if e[0] == pywbem.CIM_ERR_NOT_SUPPORTED or \
- e[0] == pywbem.CIM_ERR_INVALID_CLASS:
- flag_iscsi_support = False
- else:
+ flag_fc_support = self._c.profile_check(
+ SmisCommon.SNIA_FC_TGT_PORT_PROFILE,
+ SmisCommon.SMIS_SPEC_VER_1_4,
+ raise_error=False)
+ # One more check for NetApp Typo:
+ # NetApp: 'FC Target Port'
+ # SMI-S: 'FC Target Ports'
+ # Bug reported.
+ if not flag_fc_support:
flag_fc_support = self._c.profile_check(
- SmisCommon.SNIA_FC_TGT_PORT_PROFILE,
- SmisCommon.SMIS_SPEC_VER_1_4,
- raise_error=False)
- # One more check for NetApp Typo:
- # NetApp: 'FC Target Port'
- # SMI-S: 'FC Target Ports'
- # Bug reported.
- if not flag_fc_support:
- flag_fc_support = self._c.profile_check(
- 'FC Target Port',
- SmisCommon.SMIS_SPEC_VER_1_4,
- raise_error=False)
- flag_iscsi_support = self._c.profile_check(
- SmisCommon.SNIA_ISCSI_TGT_PORT_PROFILE,
+ 'FC Target Port',
SmisCommon.SMIS_SPEC_VER_1_4,
raise_error=False)
+ flag_iscsi_support = self._c.profile_check(
+ SmisCommon.SNIA_ISCSI_TGT_PORT_PROFILE,
+ SmisCommon.SMIS_SPEC_VER_1_4,
+ raise_error=False)
if flag_fc_support or flag_iscsi_support:
cap.set(Capabilities.TARGET_PORTS)
@@ -877,6 +819,14 @@ class Smis(IStorageAreaNetwork):
@handle_cim_errors
def capabilities(self, system, flags=0):
+ if self._c.is_netappe():
+ cap = self._common_capabilities(system)
+
+ #TODO We need to investigate why our interrogation code doesn't
+ #work.
+ #The array is telling us one thing, but when we try to use it, it
+ #doesn't work
+ return cap
cim_sys = self._get_cim_instance_by_id(
'System', system.id, raise_error=True)
@@ -1698,7 +1648,25 @@ class Smis(IStorageAreaNetwork):
ErrorNumber.PLUGIN_BUG,
msg + ", job error code= " + str(s))
+ def _detach_netapp_e(self, vol, sync):
+ #Get the Configuration service for the system we are interested in.
+ scs = self._get_class_instance('CIM_StorageConfigurationService',
+ 'SystemName', vol.system_id)
+
+ in_params = {'Operation': pywbem.Uint16(2),
+ 'Synchronization': sync.path}
+
+ job_id = self._pi("_detach", Smis.JOB_RETRIEVE_NONE,
+ *(self._c.InvokeMethod(
+ 'ModifySynchronization', scs.path,
+ **in_params)))[0]
+
+ self._poll("ModifySynchronization, detach", job_id)
+
def _detach(self, vol, sync):
+ if self._c.is_netappe():
+ return self._detach_netapp_e(vol, sync)
+
rs = self._get_class_instance("CIM_ReplicationService", 'SystemName',
vol.system_id, raise_error=False)
@@ -1723,11 +1691,43 @@ class Smis(IStorageAreaNetwork):
else:
return False
+ def _deal_volume_associations_netappe(self, vol, lun):
+ """
+ Check a volume to see if it has any associations with other
+ volumes.
+ """
+ rc = False
+ lun_path = lun.path
+
+ ss = self._c.References(lun_path,
+ ResultClass='CIM_StorageSynchronized')
+
+ if len(ss):
+ for s in ss:
+ if 'SyncedElement' in s:
+ item = s['SyncedElement']
+
+ if Smis._cim_name_match(item, lun_path):
+ self._detach(vol, s)
+ rc = True
+
+ if 'SystemElement' in s:
+ item = s['SystemElement']
+
+ if Smis._cim_name_match(item, lun_path):
+ self._detach(vol, s)
+ rc = True
+
+ return rc
+
def _deal_volume_associations(self, vol, lun):
"""
Check a volume to see if it has any associations with other
volumes and deal with them.
"""
+ if self._c.is_netappe():
+ return self._deal_volume_associations_netappe(vol, lun)
+
lun_path = lun.path
try:
@@ -1771,6 +1771,30 @@ class Smis(IStorageAreaNetwork):
if Smis._cim_name_match(item, lun_path):
self._detach(vol, s)
+ def _volume_delete_netapp_e(self, volume, flags=0):
+ scs = self._get_class_instance('CIM_StorageConfigurationService',
+ 'SystemName', volume.system_id)
+ lun = self._get_cim_instance_by_id('Volume', volume.id)
+
+ #If we actually have an association to delete, the volume will be
+ #deleted with the association, no need to call ReturnToStoragePool
+ if not self._deal_volume_associations(volume, lun):
+ in_params = {'TheElement': lun.path}
+
+ #Delete returns None or Job number
+ return self._pi("volume_delete", Smis.JOB_RETRIEVE_NONE,
+ *(self._c.InvokeMethod('ReturnToStoragePool',
+ scs.path, **in_params)))[0]
+
+ #Loop to check to see if volume is actually gone yet!
+ try:
+ lun = self._get_cim_instance_by_id('Volume', volume.id)
+ while lun is not None:
+ lun = self._get_cim_instance_by_id('Volume', volume.id)
+ time.sleep(0.125)
+ except LsmError as e:
+ pass
+
@handle_cim_errors
def volume_delete(self, volume, flags=0):
"""
@@ -2318,6 +2342,9 @@ class Smis(IStorageAreaNetwork):
return None
def _is_access_group(self, cim_spc):
+ if self._c.is_netappe:
+ return True
+
rc = True
_SMIS_EMC_ADAPTER_ROLE_MASKING = 'MASK_VIEW'
@@ -2441,10 +2468,9 @@ class Smis(IStorageAreaNetwork):
if property_list is None:
property_list = []
- if (not self.fallback_mode and
- self._c.profile_check(SmisCommon.SNIA_MASK_PROFILE,
- SmisCommon.SMIS_SPEC_VER_1_6,
- raise_error=False)):
+ if self._c.profile_check(SmisCommon.SNIA_MASK_PROFILE,
+ SmisCommon.SMIS_SPEC_VER_1_6,
+ raise_error=False):
return self._c.Associators(
cim_spc_path,
AssocClass='CIM_AssociatedPrivilege',
@@ -2616,15 +2642,12 @@ class Smis(IStorageAreaNetwork):
def _mask_type(self, raise_error=False):
"""
Return Smis.MASK_TYPE_NO_SUPPORT, MASK_TYPE_MASK or MASK_TYPE_GROUP
- For fallback_mode, return MASK_TYPE_MASK
if 'Group Masking and Mapping' profile is supported, return
MASK_TYPE_GROUP
If raise_error == False, just return Smis.MASK_TYPE_NO_SUPPORT
or, raise NO_SUPPORT error.
"""
- if self.fallback_mode:
- return Smis.MASK_TYPE_MASK
if self._c.profile_check(SmisCommon.SNIA_GROUP_MASK_PROFILE,
SmisCommon.SMIS_SPEC_VER_1_5,
raise_error=False):
@@ -2867,6 +2890,13 @@ class Smis(IStorageAreaNetwork):
@handle_cim_errors
def access_group_initiator_delete(self, access_group, init_id, init_type,
flags=0):
+ if self._c.is_netappe():
+ # When using HidePaths to remove initiator, the whole SPC will be
+ # removed. Before we find a workaround for this, I would like to
+ # have this method disabled as NO_SUPPORT.
+ raise LsmError(ErrorNumber.NO_SUPPORT,
+ "SMI-S plugin does not support "
+ "access_group_initiator_delete() against NetApp-E")
init_id = _lsm_init_id_to_snia(init_id)
mask_type = self._mask_type(raise_error=True)
@@ -2922,10 +2952,9 @@ class Smis(IStorageAreaNetwork):
by ourselves in case URI contain 'system=xxx'.
"""
rc = []
- if not self.fallback_mode:
- self._c.profile_check(SmisCommon.SNIA_DISK_LITE_PROFILE,
- SmisCommon.SMIS_SPEC_VER_1_4,
- raise_error=True)
+ self._c.profile_check(SmisCommon.SNIA_DISK_LITE_PROFILE,
+ SmisCommon.SMIS_SPEC_VER_1_4,
+ raise_error=True)
cim_disk_pros = Smis._new_disk_cim_disk_pros(flags)
cim_disks = self._c.EnumerateInstances(
'CIM_DiskDrive', PropertyList=cim_disk_pros)
@@ -3192,17 +3221,7 @@ class Smis(IStorageAreaNetwork):
def _fc_tgt_is_supported(self, cim_sys_path):
"""
Return True if FC Target Port 1.4+ profile is supported.
- For fallback_mode, we call self._cim_fc_tgt_of() and do try-except
"""
- if self.fallback_mode:
- try:
- self._cim_fc_tgt_of(cim_sys_path)
- except CIMError as e:
- if e[0] == pywbem.CIM_ERR_NOT_SUPPORTED or \
- e[0] == pywbem.CIM_ERR_INVALID_CLASS:
- return False
- return True
-
flag_fc_support = self._c.profile_check(
SmisCommon.SNIA_FC_TGT_PORT_PROFILE,
SmisCommon.SMIS_SPEC_VER_1_4,
@@ -3224,22 +3243,9 @@ class Smis(IStorageAreaNetwork):
def _iscsi_tgt_is_supported(self, cim_sys_path):
"""
Return True if FC Target Port 1.4+ profile is supported.
- For fallback_mode, we call self._cim_iscsi_pg_of() and do try-except
- For fallback_mode:
- Even CIM_EthernetPort is the control class of iSCSI Target
- Ports profile, but that class is optional. :(
We use CIM_iSCSIProtocolEndpoint as it's a start point we are
using in our code of target_ports().
"""
- if self.fallback_mode:
- try:
- self._cim_iscsi_pg_of(cim_sys_path)
- except CIMError as e:
- if e[0] == pywbem.CIM_ERR_NOT_SUPPORTED or \
- e[0] == pywbem.CIM_ERR_INVALID_CLASS:
- return False
- return True
-
if self._c.profile_check(SmisCommon.SNIA_ISCSI_TGT_PORT_PROFILE,
SmisCommon.SMIS_SPEC_VER_1_4,
raise_error=False):
@@ -3249,11 +3255,8 @@ class Smis(IStorageAreaNetwork):
def _multi_sys_is_supported(self):
"""
Return True if Multiple ComputerSystem 1.4+ profile is supported.
- For fallback_mode, always return True.
Return False else.
"""
- if self.fallback_mode:
- return True
flag_multi_sys_support = self._c.profile_check(
SmisCommon.SNIA_MULTI_SYS_PROFILE,
SmisCommon.SMIS_SPEC_VER_1_4,
@@ -3566,7 +3569,7 @@ class Smis(IStorageAreaNetwork):
"these profiles: '%s %s', '%s %s'"
% (SmisCommon.SMIS_SPEC_VER_1_4,
SmisCommon.SNIA_FC_TGT_PORT_PROFILE,
- SmisCommon.SMIS_SPEC_VER_1_4,
+ SmisCommon.SMIS_SPEC_VER_1_4,
SmisCommon.SNIA_ISCSI_TGT_PORT_PROFILE))
if flag_fc_support:
@@ -3764,10 +3767,6 @@ class Smis(IStorageAreaNetwork):
"""
org_init_id = init_id
init_id = _lsm_init_id_to_snia(init_id)
- if self.fallback_mode:
- raise LsmError(ErrorNumber.NO_SUPPORT,
- "access_group_create() is not supported in "
- "fallback mode")
self._c.profile_check(SmisCommon.SNIA_GROUP_MASK_PROFILE,
SmisCommon.SMIS_SPEC_VER_1_5,
@@ -3868,11 +3867,6 @@ class Smis(IStorageAreaNetwork):
return self._cim_init_mg_to_lsm(cim_init_mg, system.id)
def access_group_delete(self, access_group, flags=0):
- if self.fallback_mode:
- raise LsmError(ErrorNumber.NO_SUPPORT,
- "access_group_create() is not supported in "
- "fallback mode")
-
self._c.profile_check(
SmisCommon.SNIA_GROUP_MASK_PROFILE, SmisCommon.SMIS_SPEC_VER_1_5,
raise_error=True)
diff --git a/plugin/smispy/smis_common.py b/plugin/smispy/smis_common.py
index 27aa227..cf01b8f 100644
--- a/plugin/smispy/smis_common.py
+++ b/plugin/smispy/smis_common.py
@@ -153,7 +153,9 @@ class SmisCommon(object):
SMIS_SPEC_VER_1_6 = '1.6'
SNIA_REG_ORG_CODE = Uint16(11)
_MEGARAID_NAMESPACE = 'root/LsiMr13'
+ _NETAPP_E_NAMESPACE = 'root/LsiArray13'
_PRODUCT_MEGARAID = 'LSI MegaRAID'
+ _PRODUCT_NETAPP_E = 'NetApp-E'
def __init__(self, url, username, password,
namespace=DMTF.DEFAULT_NAMESPACE,
@@ -197,6 +199,9 @@ class SmisCommon(object):
(self._profile_dict, self.root_blk_cim_rp) = \
_profile_register_load(self._wbem_conn)
+ if namespace.lower() == SmisCommon._NETAPP_E_NAMESPACE.lower():
+ self._vendor_product = SmisCommon._PRODUCT_NETAPP_E
+
# Check 'Array' 1.4 support status.
_profile_check(
self._profile_dict, SmisCommon.SNIA_BLK_ROOT_PROFILE,
@@ -284,3 +289,6 @@ class SmisCommon(object):
def is_megaraid(self):
return self._vendor_product == SmisCommon._PRODUCT_MEGARAID
+
+ def is_netappe(self):
+ return self._vendor_product == SmisCommon._PRODUCT_NETAPP_E
diff --git a/plugin/smispy/smisproxy.py b/plugin/smispy/smisproxy.py
deleted file mode 100644
index 19a32ce..0000000
--- a/plugin/smispy/smisproxy.py
+++ /dev/null
@@ -1,51 +0,0 @@
-# Copyright (C) 2012 Red Hat, Inc.
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2.1 of the License, or any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# 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 smis import Smis
-from lsm import Proxy, VERSION
-import eseries
-
-#The unfortunate truth is that each of the vendors implements functionality
-#slightly differently so we will need to have some special code for these
-#instances.
-
-
-class SmisProxy(Proxy):
- """
- Layer to allow us to swap out different implementations of smi-s clients
- based on provider.
- """
- def plugin_info(self, flags=0):
- return "Generic SMI-S support", VERSION
-
- def plugin_register(self, uri, password, timeout, flags=0):
- """
- We will provide a concrete implementation of this to get the process
- started. All other method will be delegated to implementation.
- """
-
- #TODO Add code to interrogate the provider and then based on the type
- #we will instantiate the most appropriate implementation. At the
- #moment we will drop back to our current mixed implementation.
-
- #TODO We need to do a better job at check for this.
- if 'root/lsiarray13' in uri.lower():
- self.proxied_obj = eseries.ESeries()
- else:
- self.proxied_obj = Smis()
-
- self.proxied_obj.plugin_register(uri, password, timeout, flags)
diff --git a/plugin/smispy/smispy_lsmplugin b/plugin/smispy/smispy_lsmplugin
index de87c7d..b0ea003 100755
--- a/plugin/smispy/smispy_lsmplugin
+++ b/plugin/smispy/smispy_lsmplugin
@@ -23,10 +23,10 @@ import traceback
try:
from lsm import PluginRunner
- from lsm.plugin.smispy.smisproxy import SmisProxy
+ from lsm.plugin.smispy.smis import Smis
if __name__ == '__main__':
- PluginRunner(SmisProxy, sys.argv).run()
+ PluginRunner(Smis, sys.argv).run()
except Exception:
#This should be quite rare, but when it does happen this is pretty
#key in understanding what happened, especially when it happens when
--
1.8.2.1
1.8.2.1