diff options
author | Jenkins <jenkins@review.openstack.org> | 2015-04-08 15:08:25 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2015-04-08 15:08:25 +0000 |
commit | b3c2b0cc6d4748f08ae2814f634411f9dde1e06d (patch) | |
tree | 8410726783eed02a8cb10e893fce1474b2478e4e | |
parent | 420931abd5204627840f4117f305a9aec8848f7d (diff) | |
parent | e82b39baa4ef382415d54dc85b99fc2554ac56a7 (diff) | |
download | nova-b3c2b0cc6d4748f08ae2814f634411f9dde1e06d.tar.gz |
Merge "Fix multipath device discovery when UFN is enabled."
-rw-r--r-- | nova/storage/linuxscsi.py | 40 | ||||
-rw-r--r-- | nova/tests/unit/test_linuxscsi.py | 57 |
2 files changed, 75 insertions, 22 deletions
diff --git a/nova/storage/linuxscsi.py b/nova/storage/linuxscsi.py index ed30462ec0..285dda96f6 100644 --- a/nova/storage/linuxscsi.py +++ b/nova/storage/linuxscsi.py @@ -21,8 +21,13 @@ from nova.i18n import _LW from nova.openstack.common import loopingcall from nova import utils +import os +import re + LOG = logging.getLogger(__name__) +MULTIPATH_WWID_REGEX = re.compile("\((?P<wwid>.+)\)") + def echo_scsi_command(path, content): """Used to echo strings to scsi subsystem.""" @@ -106,23 +111,29 @@ def find_multipath_device(device): lines = out.strip() lines = lines.split("\n") 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_id = info[0] - mdev = '/dev/mapper/%s' % mdev_id - elif info[2][:2] == "dm": - mdev_id = info[1].replace('(', '') - mdev_id = mdev_id.replace(')', '') - mdev = '/dev/mapper/%s' % mdev_id - - if mdev is None: - LOG.warning(_LW("Couldn't find multipath device %s"), 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 /dev/${path}`. + 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.warning(_LW("Couldn't find multipath device %s"), mdev) return None LOG.debug("Found multipath device = %s", mdev) + device_lines = lines[3:] for dev_line in device_lines: if dev_line.find("policy") != -1: @@ -147,6 +158,7 @@ def find_multipath_device(device): if mdev is not None: info = {"device": mdev, "id": mdev_id, + "name": mdev_name, "devices": devices} return info return None diff --git a/nova/tests/unit/test_linuxscsi.py b/nova/tests/unit/test_linuxscsi.py index 45d6212a80..279b3c9a6a 100644 --- a/nova/tests/unit/test_linuxscsi.py +++ b/nova/tests/unit/test_linuxscsi.py @@ -20,6 +20,8 @@ from nova.storage import linuxscsi from nova import test from nova import utils +import os + LOG = logging.getLogger(__name__) CONF = cfg.CONF @@ -29,16 +31,21 @@ class StorageLinuxSCSITestCase(test.NoDBTestCase): def setUp(self): super(StorageLinuxSCSITestCase, self).setUp() self.executes = [] + self.fake_stat_result = os.stat(__file__) def fake_execute(*cmd, **kwargs): self.executes.append(cmd) return None, None + def fake_stat(path): + return self.fake_stat_result + self.stubs.Set(utils, 'execute', fake_execute) + self.stubs.Set(os, 'stat', fake_stat) def test_find_multipath_device_3par(self): def fake_execute(*cmd, **kwargs): - out = ("mpath6 (350002ac20398383d) dm-3 3PARdata,VV\n" + out = ("350002ac20398383d dm-3 3PARdata,VV\n" "size=2.0G features='0' hwhandler='0' wp=rw\n" "`-+- policy='round-robin 0' prio=-1 status=active\n" " |- 0:0:0:1 sde 8:64 active undef running\n" @@ -46,12 +53,34 @@ class StorageLinuxSCSITestCase(test.NoDBTestCase): ) return out, None - def fake_execute2(*cmd, **kwargs): - out = ("350002ac20398383d dm-3 3PARdata,VV\n" + self.stubs.Set(utils, 'execute', fake_execute) + + info = linuxscsi.find_multipath_device('/dev/sde') + LOG.error("info = %s" % info) + + self.assertEqual("350002ac20398383d", info["name"]) + self.assertEqual("350002ac20398383d", info["id"]) + self.assertEqual("/dev/mapper/350002ac20398383d", info["device"]) + + self.assertEqual("/dev/sde", info['devices'][0]['device']) + self.assertEqual("0", info['devices'][0]['host']) + self.assertEqual("0", info['devices'][0]['id']) + self.assertEqual("0", info['devices'][0]['channel']) + self.assertEqual("1", info['devices'][0]['lun']) + + self.assertEqual("/dev/sdf", info['devices'][1]['device']) + self.assertEqual("2", info['devices'][1]['host']) + self.assertEqual("0", info['devices'][1]['id']) + self.assertEqual("0", info['devices'][1]['channel']) + self.assertEqual("1", info['devices'][1]['lun']) + + 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" "`-+- policy='round-robin 0' prio=-1 status=active\n" - " |- 0:0:0:1 sde 8:64 active undef running\n" - " `- 2:0:0:1 sdf 8:80 active undef running\n" + " |- 0:0:0:1 sde 8:64 active undef running\n" + " `- 2:0:0:1 sdf 8:80 active undef running\n" ) return out, None @@ -59,7 +88,11 @@ class StorageLinuxSCSITestCase(test.NoDBTestCase): info = linuxscsi.find_multipath_device('/dev/sde') LOG.error("info = %s" % info) - self.assertEqual("/dev/mapper/350002ac20398383d", info["device"]) + + self.assertEqual("mpath6", info["name"]) + self.assertEqual("350002ac20398383d", info["id"]) + 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']) @@ -90,8 +123,12 @@ class StorageLinuxSCSITestCase(test.NoDBTestCase): info = linuxscsi.find_multipath_device('/dev/sde') LOG.error("info = %s" % info) + + self.assertEqual("36005076da00638089c000000000004d5", info["name"]) + self.assertEqual("36005076da00638089c000000000004d5", info["id"]) 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']) @@ -110,8 +147,8 @@ class StorageLinuxSCSITestCase(test.NoDBTestCase): "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" + " |- 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 @@ -119,8 +156,12 @@ class StorageLinuxSCSITestCase(test.NoDBTestCase): info = linuxscsi.find_multipath_device('/dev/sdd') LOG.error("info = %s" % info) + + self.assertEqual("36005076303ffc48e0000000000000101", info["name"]) + self.assertEqual("36005076303ffc48e0000000000000101", info["id"]) 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']) |