From 0b84027204d94e7b314bce505e59aa0c336af43c Mon Sep 17 00:00:00 2001 From: Patrick East Date: Tue, 14 Oct 2014 15:45:38 -0700 Subject: [PATCH] Multipath commands with error messages in stdout fail to parse MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit This change fixes an issue in find_multipath_device() where the command output of ‘multipath -l ’ would sometimes fail to be parsed if there were error messages in the stdout string in addition to the expected output. We will now strip out the error messages before we attempt to parse the lines. Change-Id: I3d48debc7d64f6a891ac37d4c2c5ebddfb5b00b0 Closes-Bug: #1380742 --- cinder/brick/initiator/linuxscsi.py | 5 ++++ cinder/tests/brick/test_brick_linuxscsi.py | 29 ++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/cinder/brick/initiator/linuxscsi.py b/cinder/brick/initiator/linuxscsi.py index a374ce61f..1b3b87390 100644 --- a/cinder/brick/initiator/linuxscsi.py +++ b/cinder/brick/initiator/linuxscsi.py @@ -17,6 +17,7 @@ Note, this is not iSCSI. """ import os +import re from cinder.brick import executor from cinder.i18n import _ @@ -25,6 +26,8 @@ from cinder.openstack.common import processutils as putils LOG = logging.getLogger(__name__) +MULTIPATH_ERROR_REGEX = re.compile("\w{3} \d+ \d\d:\d\d:\d\d \|.*$") + class LinuxSCSI(executor.Executor): def __init__(self, root_helper, execute=putils.execute, @@ -143,6 +146,8 @@ class LinuxSCSI(executor.Executor): if out: lines = out.strip() lines = lines.split("\n") + lines = [line for line in lines + if not re.match(MULTIPATH_ERROR_REGEX, line)] if lines: line = lines[0] info = line.split(" ") diff --git a/cinder/tests/brick/test_brick_linuxscsi.py b/cinder/tests/brick/test_brick_linuxscsi.py index 5dc46130e..fcea805a2 100644 --- a/cinder/tests/brick/test_brick_linuxscsi.py +++ b/cinder/tests/brick/test_brick_linuxscsi.py @@ -181,3 +181,32 @@ class LinuxSCSITestCase(test.TestCase): self.assertEqual("1", info['devices'][1]['channel']) self.assertEqual("0", info['devices'][1]['id']) self.assertEqual("3", info['devices'][1]['lun']) + + def test_find_multipath_device_with_error(self): + def fake_execute(*cmd, **kwargs): + out = ("Oct 13 10:24:01 | /lib/udev/scsi_id exitted with 1\n" + "36005076303ffc48e0000000000000101 dm-2 IBM,2107900\n" + "size=1.0G features='1 queue_if_no_path' hwhandler='0'" + " wp=rw\n" + "`-+- policy='round-robin 0' prio=-1 status=active\n" + " |- 6:0:2:0 sdd 8:64 active undef running\n" + " `- 6:1:0:3 sdc 8:32 active undef running\n" + ) + return out, None + + self.stubs.Set(self.linuxscsi, '_execute', fake_execute) + + info = self.linuxscsi.find_multipath_device('/dev/sdd') + LOG.error("info = %s" % info) + self.assertEqual("/dev/dm-2", info["device"]) + self.assertEqual("/dev/sdd", info['devices'][0]['device']) + self.assertEqual("6", info['devices'][0]['host']) + self.assertEqual("0", info['devices'][0]['channel']) + self.assertEqual("2", info['devices'][0]['id']) + self.assertEqual("0", info['devices'][0]['lun']) + + self.assertEqual("/dev/sdc", info['devices'][1]['device']) + self.assertEqual("6", info['devices'][1]['host']) + self.assertEqual("1", info['devices'][1]['channel']) + self.assertEqual("0", info['devices'][1]['id']) + self.assertEqual("3", info['devices'][1]['lun']) -- 2.45.2