summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Grover <andy@groveronline.com>2017-02-07 09:09:20 -0800
committerGitHub <noreply@github.com>2017-02-07 09:09:20 -0800
commit2c65d971ab1e77cad6cc637b1cf39148be87dab2 (patch)
tree9dc9f0d7ef17f441f12531f2f43a4ff52ef7f6ae
parent572e9b41bae87023e5e5845786a15409246253aa (diff)
parent13dfb1aadbba3d1e2fa64133e9e2392071d58a5a (diff)
downloadrtslib-fb-2c65d971ab1e77cad6cc637b1cf39148be87dab2.tar.gz
Merge pull request #89 from mikechristie/alua-exception
Fix crash during restore due to ALUA exception
-rw-r--r--rtslib/__init__.py1
-rw-r--r--rtslib/alua.py8
-rw-r--r--rtslib/root.py7
-rw-r--r--rtslib/target.py34
-rw-r--r--rtslib/tcm.py24
-rw-r--r--rtslib/utils.py6
6 files changed, 65 insertions, 15 deletions
diff --git a/rtslib/__init__.py b/rtslib/__init__.py
index 48aab2a..568619e 100644
--- a/rtslib/__init__.py
+++ b/rtslib/__init__.py
@@ -23,6 +23,7 @@ if __name__ == "rtslib":
from .root import RTSRoot
from .utils import RTSLibError, RTSLibBrokenLink, RTSLibNotInCFS
+from .utils import RTSLibALUANotSupported
from .target import LUN, MappedLUN
from .target import NodeACL, NetworkPortal, TPG, Target
diff --git a/rtslib/alua.py b/rtslib/alua.py
index 86a4dd3..390e74a 100644
--- a/rtslib/alua.py
+++ b/rtslib/alua.py
@@ -18,7 +18,7 @@ a copy of the License at
'''
from .node import CFSNode
-from .utils import RTSLibError, fread, fwrite
+from .utils import RTSLibError, RTSLibALUANotSupported, fread, fwrite
alua_rw_params = ['alua_access_state', 'alua_access_status',
'alua_write_metadata', 'alua_access_type', 'preferred',
@@ -46,6 +46,12 @@ class ALUATargetPortGroup(CFSNode):
@param tag: target port group id. If not passed in, try to look
up existing ALUA TPG with the same name
"""
+ # kernel partially sets up default_tg_pt_gp and will let you partially
+ # setup ALUA groups for pscsi and user, but writing to some of the
+ # files will crash the kernel. Just fail to even create groups until
+ # the kernel is fixed.
+ if storage_object.alua_supported is False:
+ raise RTSLibALUANotSupported("Backend does not support ALUA setup")
# default_tg_pt_gp takes tag 1
if tag is not None and (tag > 65535 or tag < 1):
diff --git a/rtslib/root.py b/rtslib/root.py
index 3cc6fbf..6d6b5ee 100644
--- a/rtslib/root.py
+++ b/rtslib/root.py
@@ -26,7 +26,7 @@ from .node import CFSNode
from .target import Target
from .fabric import FabricModule
from .tcm import so_mapping, StorageObject
-from .utils import RTSLibError, modprobe, mount_configfs
+from .utils import RTSLibError, RTSLibALUANotSupported, modprobe, mount_configfs
from .utils import dict_remove, set_attributes
from .alua import ALUATargetPortGroup
@@ -224,7 +224,10 @@ class RTSRoot(CFSNode):
set_attributes(so_obj, so.get('attributes', {}), so_err_func)
for alua_tpg in so.get('alua_tpgs', {}):
- ALUATargetPortGroup.setup(so_obj, alua_tpg, err_func)
+ try:
+ ALUATargetPortGroup.setup(so_obj, alua_tpg, err_func)
+ except RTSLibALUANotSupported:
+ pass
# Don't need to create fabric modules
for index, fm in enumerate(config.get('fabric_modules', [])):
diff --git a/rtslib/target.py b/rtslib/target.py
index 816be74..d3cdab7 100644
--- a/rtslib/target.py
+++ b/rtslib/target.py
@@ -582,31 +582,43 @@ class LUN(CFSNode):
if os.path.realpath("%s/%s" % (mlun.path, mlun.alias)) == self.path:
yield mlun
+
+ # pass through backends will not have setup all the default
+ # ALUA structs in the kernel. If the kernel has been setup,
+ # a user created group or default_tg_pt_gp will be returned.
+ # If the kernel was not properly setup an empty string is
+ # return in alua_tg_pt_gp. Writing to alua_tg_pt_gp will crash
+ # older kernels and will return a -Exyz code in newer ones.
def _get_alua_tg_pt_gp_name(self):
self._check_self()
+ storage_object = self._get_storage_object()
+ if storage_object.alua_supported is False:
+ return None
+
path = "%s/alua_tg_pt_gp" % self.path
- info = fread(path)
- if info:
+ try:
+ info = fread(path)
+ if not info:
+ return None
group_line = info.splitlines()[0]
return group_line.split(':')[1].strip()
- return None
+ except IOError as e:
+ return None
def _set_alua_tg_pt_gp_name(self, group_name):
self._check_self()
- path = "%s/alua_tg_pt_gp" % self.path
-
- info = fread(path)
- if not info:
- # pass through backends will not have setup the default
- # ALUA structs in the kernel.
- raise RTSLibError("This LUN does not support setting the ALUA Target Port Group")
+ if not self._get_alua_tg_pt_gp_name():
+ return -1
+ path = "%s/alua_tg_pt_gp" % self.path
try:
fwrite(path, group_name)
except IOError as e:
- raise RTSLibError("Cannot set ALUA Target Port Group: %s" % e)
+ return -1
+
+ return 0
# LUN public stuff
diff --git a/rtslib/tcm.py b/rtslib/tcm.py
index 5452f92..aa3530a 100644
--- a/rtslib/tcm.py
+++ b/rtslib/tcm.py
@@ -222,7 +222,15 @@ class StorageObject(CFSNode):
'''
self._check_self()
for tpg in os.listdir("%s/alua" % self.path):
- yield ALUATargetPortGroup(self, tpg)
+ if self.alua_supported:
+ yield ALUATargetPortGroup(self, tpg)
+
+ def _get_alua_supported(self):
+ '''
+ Children should override and return false if ALUA setup is not supported.
+ '''
+ self._check_self()
+ return True
# StorageObject public stuff
@@ -279,6 +287,8 @@ class StorageObject(CFSNode):
doc="Get the list of all LUN objects attached.")
alua_tpgs = property(_list_alua_tpgs,
doc="Get list of ALUA Target Port Groups attached.")
+ alua_supported = property(_get_alua_supported,
+ doc="Returns true if ALUA can be setup. False if not supported.")
def dump(self):
d = super(StorageObject, self).dump()
@@ -408,6 +418,10 @@ class PSCSIStorageObject(StorageObject):
self._check_self()
return int(self._parse_info('Host ID'))
+ def _get_alua_supported(self):
+ self._check_self()
+ return False
+
# PSCSIStorageObject public stuff
wwn = property(StorageObject._get_wwn, _set_wwn,
@@ -427,6 +441,8 @@ class PSCSIStorageObject(StorageObject):
doc="Get the SCSI device target id")
lun = property(_get_lun,
doc="Get the SCSI device LUN")
+ alua_supported = property(_get_alua_supported,
+ doc="ALUA cannot be setup with rtslib, so False is returned.");
def dump(self):
d = super(PSCSIStorageObject, self).dump()
@@ -808,10 +824,16 @@ class UserBackedStorageObject(StorageObject):
return None
return val
+ def _get_alua_supported(self):
+ self._check_self()
+ return False
+
size = property(_get_size,
doc="Get the size in bytes.")
config = property(_get_config,
doc="Get the TCMU config.")
+ alua_supported = property(_get_alua_supported,
+ doc="ALUA cannot be setup with rtslib, so False is returned.");
def dump(self):
d = super(UserBackedStorageObject, self).dump()
diff --git a/rtslib/utils.py b/rtslib/utils.py
index 969d2d7..1a5315e 100644
--- a/rtslib/utils.py
+++ b/rtslib/utils.py
@@ -37,6 +37,12 @@ class RTSLibError(Exception):
'''
pass
+class RTSLibALUANotSupported(RTSLibError):
+ '''
+ Backend does not support ALUA.
+ '''
+ pass
+
class RTSLibBrokenLink(RTSLibError):
'''
Broken link in configfs, i.e. missing LUN storage object.