Skip to content

Commit

Permalink
CA-165611: DM Multipath mishandles blacklisted devices if some paths …
Browse files Browse the repository at this point in the history
…down

This bug may occur when [1 <= paths < total_num_paths] to a device are offline
and the device is blacklisted. Up until now, we checked only the first path in
the list, which might be offline. If this was the case, we incorrectly
determined that the device was not blacklisted (the lack of the
"wwid blacklisted" string doesn't mean it's whitelisted).

To tackle the issue, we check all paths to the device until we have a definite
answer.

Signed-off-by: Kostas Ladopoulos <konstantinos.ladopoulos@citrix.com>
Reviewed-by: Germano Percossi <germano.percossi@citrix.com>

GitHub: closes #254
  • Loading branch information
kostaslambda authored and germanop committed Sep 25, 2015
1 parent 7a8a158 commit 7b81acf
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 20 deletions.
35 changes: 23 additions & 12 deletions drivers/mpath_dmp.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,19 +181,30 @@ def map_by_scsibus(sid,npaths=0):
if(len(devices)>=npaths or npaths==0):
# Enable this device's sid: it could be blacklisted
# We expect devices to be blacklisted according to their
# wwid only. Checking the first one is sufficient
if wwid_conf.is_blacklisted(devices[0]):
# wwid only. We go through the list of paths until we have
# a definite answer about the device's blacklist status.
# If the path we are checking is down, we cannot tell.
for dev in devices:
try:
wwid_conf.edit_wwid(sid)
except:
util.SMlog("WARNING: exception raised while attempting to"
" modify multipath.conf")
try:
mpath_cli.reconfigure()
except:
util.SMlog("WARNING: exception raised while attempting to"
" reconfigure")
time.sleep(5)
if wwid_conf.is_blacklisted(dev):
try:
wwid_conf.edit_wwid(sid)
except:
util.SMlog("WARNING: exception raised while "
"attempting to modify multipath.conf")
try:
mpath_cli.reconfigure()
except:
util.SMlog("WARNING: exception raised while "
"attempting to reconfigure")
time.sleep(5)

break
except wwid_conf.WWIDException as e:
util.SMlog(e.errstr)
else:
util.SMlog("Device 'SCSI_id: {}' is inaccessible; "
"All paths are down.".format(sid))

__map_explicit(devices)
return
Expand Down
39 changes: 31 additions & 8 deletions drivers/wwid_conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@
CONF_FILE = "/etc/multipath.xenserver/multipath.conf"
BELIST_TAG = "blacklist_exceptions"

class WWIDException(Exception):
def __init__(self, errstr):
self.errstr = errstr


def edit_wwid(wwid, remove=False):
"""Add a wwid to the list of exceptions or remove if
Expand Down Expand Up @@ -75,17 +79,33 @@ def is_blacklisted(dev):
"""This function returns True if the device is blacklisted according
to multipath.conf rules.
There is also the possibility that the path to the device we are
checking is unavailable for some reason. In that case,
is_blacklisted() cannot tell if the device is blacklisted or not
and a WWIDException is raised.
It cannot be used to check the current daemon rules because it
could be running with an old configuration file in memory
dev -- it is any string accepted by "multipath -c". A full path
is sufficient
Input:
dev -- it is any string accepted by "multipath -c". A full path
is expected.
Return:
bool -- True or False, depending on whether the device is
blacklisted or not.
Raise:
WWIDException
"""

(rc,stdout,stderr) = util.doexec(['/sbin/multipath','-v3','-c',dev])

# If the devices is blacklisted according to multipath.conf, the
if "scope is nul" in stdout:
raise WWIDException("WARNING: Could not retrieve device's "
"WWID. Path {} is down".format(dev))

# If the device is blacklisted according to multipath.conf, the
# string "wwid blacklisted" appears in the verbose output.
# This is a very fragile mechanism and keeps changing.
# What we want is a method to tell immediately if a device is
Expand Down Expand Up @@ -146,11 +166,14 @@ def usage():
usage()
sys.exit(1)

if force or xor(remove, is_blacklisted(device)):
try:
edit_wwid(wwid, remove)
except:
sys.exit(1)
try:
if force or xor(remove, is_blacklisted(device)):
try:
edit_wwid(wwid, remove)
except:
sys.exit(1)
except WWIDException as e:
util.SMlog(e.errstr)

sys.exit(0)

0 comments on commit 7b81acf

Please sign in to comment.