Coverage for sm/core/mpath_dmp.py : 90%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1#!/usr/bin/python
2#
3# Copyright (C) Citrix Systems Inc.
4#
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU Lesser General Public License as published
7# by the Free Software Foundation; version 2.1 only.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU Lesser General Public License for more details.
13#
14# You should have received a copy of the GNU Lesser General Public License
15# along with this program; if not, write to the Free Software Foundation, Inc.,
16# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18"""Copy of mpath_dmp.py in SM with unneeded code removed"""
20import os
21import errno
23from fairlock import Fairlock
25from . import util
26from . import f_exceptions
28DEVMAPPERPATH = "/dev/mapper"
29DEVBYIDPATH = "/dev/disk/by-id"
30MP_INUSEDIR = "/dev/disk/mpInuse"
32def activate_MPdev(sid, dst):
33 try:
34 os.mkdir(MP_INUSEDIR)
35 except OSError as exc:
36 if exc.errno == errno.EEXIST:
37 pass
38 else:
39 raise
40 path = os.path.join(MP_INUSEDIR, sid)
41 cmd = ['ln', '-sf', dst, path]
42 util.pread2(cmd)
44def deactivate_MPdev(sid):
45 path = os.path.join(MP_INUSEDIR, sid)
46 if os.path.exists(path): 46 ↛ 47line 46 didn't jump to line 47, because the condition on line 46 was never true
47 os.unlink(path)
49def reset(sid):
50 util.SMlog("Resetting LUN %s" % sid)
51 _resetDMP(sid)
53def _resetDMP(sid):
54# If mpath has been turned on since the sr/vdi was attached, we
55# might be trying to unmap it before the daemon has been started
56# This is unnecessary (and will fail) so just return.
57 deactivate_MPdev(sid)
59# If the multipath daemon is running, but we were initially plugged
60# with multipathing set to no, there may be no map for us in the multipath
61# tables. In that case, list_paths will return [], but remove_map might
62# throw an exception. Catch it and ignore it.
63 with Fairlock("devicemapper"):
64 util.retry(lambda: util.pread2(['/usr/sbin/multipath', '-f', sid]), 64 ↛ exitline 64 didn't run the lambda on line 64
65 maxretry = 3, period = 4)
66 util.retry(lambda: util.pread2(['/usr/sbin/multipath', '-W']), maxretry = 3, 66 ↛ exitline 66 didn't run the lambda on line 66
67 period = 4)
69 path = "/dev/mapper/%s" % sid
71 if not util.wait_for_nopath(path, 10): 71 ↛ 72line 71 didn't jump to line 72, because the condition on line 71 was never true
72 util.SMlog("MPATH: WARNING - path did not disappear [%s]" % path)
73 else:
74 util.SMlog("MPATH: path disappeared [%s]" % path)
76def refresh(sid):
77 # Refresh the multipath status
78 util.SMlog("Refreshing LUN %s" % sid)
79 if len(sid):
80 path = DEVBYIDPATH + "/scsi-" + sid
81 if not os.path.exists(path):
82 raise f_exceptions.XenError("mpath_dmp", "{} not found".
83 format(path))
84 _refresh_DMP(sid)
85 else:
86 raise f_exceptions.XenError('mpath_dmp', 'MPath not written yet')
89def _is_valid_multipath_device(sid):
90 by_id_path = "/dev/disk/by-id/scsi-"+sid
91 real_path = util.get_real_path(by_id_path)
92 with Fairlock("devicemapper"):
93 (ret, stdout, stderr) = util.doexec(['/usr/sbin/multipath', '-a', sid])
95 if ret < 0:
96 util.SMlog("Failed to add {}: wwid could be explicitly blacklisted\n"
97 " Continue with multipath disabled for this SR".format(sid))
98 return False
100 with Fairlock("devicemapper"):
101 (ret, stdout, stderr) = util.doexec(['/usr/sbin/multipath', '-c',
102 real_path])
104 if ret == 1:
105 # This is very fragile but it is not a good sign to fail without
106 # any output. At least until multipath 0.4.9, for example, multipath -c
107 # fails without any log if it is able to retrieve the wwid of the
108 # device.
109 # In this case it is better to fail immediately.
110 if not stdout+stderr:
111 # Attempt to cleanup wwids file before raising
112 try:
113 with Fairlock("devicemapper"):
114 (ret, stdout, stderr) = util.doexec(['/usr/sbin/multipath',
115 '-w', sid])
116 except OSError:
117 util.SMlog("Error removing {} from wwids file".format(sid))
118 raise f_exceptions.XenError('MultipathGenericFailure',
119 '"multipath -c" failed without any'
120 ' output on {}'.format(real_path))
121 util.SMlog("When dealing with {} returned with:\n"
122 " {}{} Continue with multipath disabled for this SR"
123 .format(sid, stdout, stderr))
124 return False
125 return True
128def _refresh_DMP(sid):
129 if not _is_valid_multipath_device(sid): 129 ↛ 130line 129 didn't jump to line 130, because the condition on line 129 was never true
130 return
132 with Fairlock("devicemapper"):
133 util.retry(lambda: util.pread2(['/usr/sbin/multipath', '-r', sid]), maxretry = 3,
134 period = 4)
136 path = os.path.join(DEVMAPPERPATH, sid)
137 util.wait_for_path(path, 10)
138 if not os.path.exists(path):
139 raise f_exceptions.XenError('DMP', 'failed to activate mapper path')
140 lvm_path = "/dev/disk/by-scsid/"+sid+"/mapper"
141 util.wait_for_path(lvm_path, 10)
142 activate_MPdev(sid, path)