Fix multipath device discovery when UFN is enabled.
This currently returns an invalid path of `/dev/mapper/${WWID}` when UFN is enabled leading to failures later on when we attempt to use the device. The output of `multipath -l ${path}` or `multipath -l ${wwid}` should always list the correct device identifier to use with this path as the first word on the first line. The same change has been suggested for both Cinder [1] and Nova [2] as they are also susceptible to this issue. [1] https://review.openstack.org/#/c/170157/ [2] https://review.openstack.org/#/c/169873/ Change-Id: I4a2d0e6ba4522ebfa0c50be49f7039f6e4617ae8 Closes-Bug: 1401799
This commit is contained in:
parent
fa22662d2d
commit
7643a16588
os_brick
@ -28,6 +28,7 @@ from os_brick.openstack.common import log as logging
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
MULTIPATH_ERROR_REGEX = re.compile("\w{3} \d+ \d\d:\d\d:\d\d \|.*$")
|
||||
MULTIPATH_WWID_REGEX = re.compile("\((?P<wwid>.+)\)")
|
||||
|
||||
|
||||
class LinuxSCSI(executor.Executor):
|
||||
@ -150,21 +151,26 @@ class LinuxSCSI(executor.Executor):
|
||||
lines = [line for line in lines
|
||||
if not re.match(MULTIPATH_ERROR_REGEX, line)]
|
||||
if lines:
|
||||
line = lines[0]
|
||||
info = line.split(" ")
|
||||
# device line output is different depending
|
||||
# on /etc/multipath.conf settings.
|
||||
if info[1][:2] == "dm":
|
||||
mdev = "/dev/%s" % info[1]
|
||||
mdev_id = info[0]
|
||||
elif info[2][:2] == "dm":
|
||||
mdev = "/dev/%s" % info[2]
|
||||
mdev_id = info[1].replace('(', '')
|
||||
mdev_id = mdev_id.replace(')', '')
|
||||
|
||||
if mdev is None:
|
||||
LOG.warning(_LW("Couldn't find multipath device %(line)s"),
|
||||
{'line': line})
|
||||
# Use the device name, be it the WWID, mpathN or custom alias
|
||||
# of a device to build the device path. This should be the
|
||||
# first item on the first line of output from `multipath -l
|
||||
# ${path}` or `multipath -l ${wwid}`..
|
||||
mdev_name = lines[0].split(" ")[0]
|
||||
mdev = '/dev/mapper/%s' % mdev_name
|
||||
|
||||
# Find the WWID for the LUN if we are using mpathN or aliases.
|
||||
wwid_search = MULTIPATH_WWID_REGEX.search(lines[0])
|
||||
if wwid_search is not None:
|
||||
mdev_id = wwid_search.group('wwid')
|
||||
else:
|
||||
mdev_id = mdev_name
|
||||
|
||||
# Confirm that the device is present.
|
||||
try:
|
||||
os.stat(mdev)
|
||||
except OSError:
|
||||
LOG.warn(_LW("Couldn't find multipath device %s"), mdev)
|
||||
return None
|
||||
|
||||
LOG.debug("Found multipath device = %(mdev)s",
|
||||
@ -188,6 +194,7 @@ class LinuxSCSI(executor.Executor):
|
||||
if mdev is not None:
|
||||
info = {"device": mdev,
|
||||
"id": mdev_id,
|
||||
"name": mdev_name,
|
||||
"devices": devices}
|
||||
return info
|
||||
return None
|
||||
|
@ -12,6 +12,7 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import os
|
||||
import os.path
|
||||
import string
|
||||
|
||||
@ -29,6 +30,7 @@ class LinuxSCSITestCase(base.TestCase):
|
||||
super(LinuxSCSITestCase, self).setUp()
|
||||
self.cmds = []
|
||||
mock.patch.object(os.path, 'realpath', return_value='/dev/sdc').start()
|
||||
mock.patch.object(os, 'stat', returns=os.stat(__file__)).start()
|
||||
self.addCleanup(mock.patch.stopall)
|
||||
self.linuxscsi = linuxscsi.LinuxSCSI(None, execute=self.fake_execute)
|
||||
|
||||
@ -100,7 +102,7 @@ class LinuxSCSITestCase(base.TestCase):
|
||||
('multipath -f 350002ac20398383d'), ]
|
||||
self.assertEqual(expected_commands, self.cmds)
|
||||
|
||||
def test_find_multipath_device_3par(self):
|
||||
def test_find_multipath_device_3par_ufn(self):
|
||||
def fake_execute(*cmd, **kwargs):
|
||||
out = ("mpath6 (350002ac20398383d) dm-3 3PARdata,VV\n"
|
||||
"size=2.0G features='0' hwhandler='0' wp=rw\n"
|
||||
@ -114,7 +116,11 @@ class LinuxSCSITestCase(base.TestCase):
|
||||
|
||||
info = self.linuxscsi.find_multipath_device('/dev/sde')
|
||||
LOG.error("info = %s" % info)
|
||||
self.assertEqual("/dev/dm-3", info["device"])
|
||||
|
||||
self.assertEqual("350002ac20398383d", info["id"])
|
||||
self.assertEqual("mpath6", info["name"])
|
||||
self.assertEqual("/dev/mapper/mpath6", info["device"])
|
||||
|
||||
self.assertEqual("/dev/sde", info['devices'][0]['device'])
|
||||
self.assertEqual("0", info['devices'][0]['host'])
|
||||
self.assertEqual("0", info['devices'][0]['id'])
|
||||
@ -145,7 +151,12 @@ class LinuxSCSITestCase(base.TestCase):
|
||||
|
||||
info = self.linuxscsi.find_multipath_device('/dev/sde')
|
||||
LOG.error("info = %s" % info)
|
||||
self.assertEqual("/dev/dm-2", info["device"])
|
||||
|
||||
self.assertEqual("36005076da00638089c000000000004d5", info["id"])
|
||||
self.assertEqual("36005076da00638089c000000000004d5", info["name"])
|
||||
self.assertEqual("/dev/mapper/36005076da00638089c000000000004d5",
|
||||
info["device"])
|
||||
|
||||
self.assertEqual("/dev/sde", info['devices'][0]['device'])
|
||||
self.assertEqual("6", info['devices'][0]['host'])
|
||||
self.assertEqual("0", info['devices'][0]['channel'])
|
||||
@ -173,7 +184,12 @@ class LinuxSCSITestCase(base.TestCase):
|
||||
|
||||
info = self.linuxscsi.find_multipath_device('/dev/sdd')
|
||||
LOG.error("info = %s" % info)
|
||||
self.assertEqual("/dev/dm-2", info["device"])
|
||||
|
||||
self.assertEqual("36005076303ffc48e0000000000000101", info["id"])
|
||||
self.assertEqual("36005076303ffc48e0000000000000101", info["name"])
|
||||
self.assertEqual("/dev/mapper/36005076303ffc48e0000000000000101",
|
||||
info["device"])
|
||||
|
||||
self.assertEqual("/dev/sdd", info['devices'][0]['device'])
|
||||
self.assertEqual("6", info['devices'][0]['host'])
|
||||
self.assertEqual("0", info['devices'][0]['channel'])
|
||||
@ -202,7 +218,12 @@ class LinuxSCSITestCase(base.TestCase):
|
||||
|
||||
info = self.linuxscsi.find_multipath_device('/dev/sdd')
|
||||
LOG.error("info = %s" % info)
|
||||
self.assertEqual("/dev/dm-2", info["device"])
|
||||
|
||||
self.assertEqual("36005076303ffc48e0000000000000101", info["id"])
|
||||
self.assertEqual("36005076303ffc48e0000000000000101", info["name"])
|
||||
self.assertEqual("/dev/mapper/36005076303ffc48e0000000000000101",
|
||||
info["device"])
|
||||
|
||||
self.assertEqual("/dev/sdd", info['devices'][0]['device'])
|
||||
self.assertEqual("6", info['devices'][0]['host'])
|
||||
self.assertEqual("0", info['devices'][0]['channel'])
|
||||
|
Loading…
x
Reference in New Issue
Block a user