Skip to content

Commit

Permalink
Merge pull request #89 from mikechristie/alua-exception
Browse files Browse the repository at this point in the history
Fix crash during restore due to ALUA exception
  • Loading branch information
agrover committed Feb 7, 2017
2 parents 572e9b4 + 13dfb1a commit 2c65d97
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 15 deletions.
1 change: 1 addition & 0 deletions rtslib/__init__.py
Expand Up @@ -23,6 +23,7 @@

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
Expand Down
8 changes: 7 additions & 1 deletion rtslib/alua.py
Expand Up @@ -18,7 +18,7 @@
'''

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',
Expand Down Expand Up @@ -46,6 +46,12 @@ def __init__(self, storage_object, name, tag=None):
@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):
Expand Down
7 changes: 5 additions & 2 deletions rtslib/root.py
Expand Up @@ -26,7 +26,7 @@
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

Expand Down Expand Up @@ -224,7 +224,10 @@ def so_err_func(x):
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', [])):
Expand Down
34 changes: 23 additions & 11 deletions rtslib/target.py
Expand Up @@ -582,31 +582,43 @@ def _list_mapped_luns(self):
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

Expand Down
24 changes: 23 additions & 1 deletion rtslib/tcm.py
Expand Up @@ -222,7 +222,15 @@ def _list_alua_tpgs(self):
'''
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

Expand Down Expand Up @@ -279,6 +287,8 @@ def is_configured(self):
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()
Expand Down Expand Up @@ -408,6 +418,10 @@ def _get_host_id(self):
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,
Expand All @@ -427,6 +441,8 @@ def _get_host_id(self):
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()
Expand Down Expand Up @@ -808,10 +824,16 @@ def _get_config(self):
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()
Expand Down
6 changes: 6 additions & 0 deletions rtslib/utils.py
Expand Up @@ -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.
Expand Down

0 comments on commit 2c65d97

Please sign in to comment.