← Back to team overview

curtin-dev team mailing list archive

[Merge] ~mwhudson/curtin:fix-multipath-partition-verification into curtin:master

 

Michael Hudson-Doyle has proposed merging ~mwhudson/curtin:fix-multipath-partition-verification into curtin:master.

Commit message:
block: fixes for verifying existing multipath partitions

Verifying a partition on a multipath disk currently fails for two
reasons:

 1. get_blockdev_for_partition does not know how to go from a multipath
    partition to a multipath disk.
 2. sfdisk --json /dev/dm-X prints /dev/mapper paths for the partition
    paths so get_partition_sfdisk_info doesn't work.

2 is easily fixed by resolving symlinks before comparing nodes. 1 can be
fixed with a little sysfs yoga but then some calls to
get_blockdev_for_partition need to be shielded to avoid calling it on
multipath partitions. One call to it turned out to be in a function
(get_multipath_wwids) that is no longer called from anywhere so I just
removed it.


Requested reviews:
  curtin developers (curtin-dev)

For more details, see:
https://code.launchpad.net/~mwhudson/curtin/+git/curtin/+merge/396046
-- 
Your team curtin developers is requested to review the proposed merge of ~mwhudson/curtin:fix-multipath-partition-verification into curtin:master.
diff --git a/curtin/block/__init__.py b/curtin/block/__init__.py
index 0cf0866..f020cdd 100644
--- a/curtin/block/__init__.py
+++ b/curtin/block/__init__.py
@@ -158,9 +158,10 @@ def sys_block_path(devname, add=None, strict=True):
     devname = os.path.normpath(devname)
     if devname.startswith('/dev/') and not os.path.exists(devname):
         LOG.warning('block.sys_block_path: devname %s does not exist', devname)
-    (parent, partnum) = get_blockdev_for_partition(devname, strict=strict)
-    if partnum:
-        toks.append(path_to_kname(parent))
+    if not os.path.realpath(devname).startswith('/dev/dm-'):
+        (parent, partnum) = get_blockdev_for_partition(devname, strict=strict)
+        if partnum:
+            toks.append(path_to_kname(parent))
 
     toks.append(path_to_kname(devname))
 
@@ -309,7 +310,7 @@ def get_partition_sfdisk_info(devpath, sfdisk_info=None):
         sfdisk_info = sfdisk_info(devpath)
 
     entry = [part for part in sfdisk_info['partitions']
-             if part['node'] == devpath]
+             if os.path.realpath(part['node']) == os.path.realpath(devpath)]
     if len(entry) != 1:
         raise RuntimeError('Device %s not present in sfdisk dump:\n%s' %
                            devpath, util.json_dumps(sfdisk_info))
@@ -421,6 +422,14 @@ def get_blockdev_for_partition(devpath, strict=True):
     if strict and not os.path.exists(syspath):
         raise OSError("%s had no syspath (%s)" % (devpath, syspath))
 
+    dm_name_path = os.path.join(syspath, 'dm/name')
+    if os.path.exists(dm_name_path):
+        dm_name = util.load_file(dm_name_path).rstrip()
+        if '-part' in dm_name:
+            parent_name, ptnum = dm_name.rsplit('-part', 1)
+            parent_path = os.path.realpath('/dev/mapper/' + parent_name)
+            return (parent_path, ptnum)
+
     ptpath = os.path.join(syspath, "partition")
     if not os.path.exists(ptpath):
         return (rpath, None)
@@ -692,28 +701,6 @@ def get_scsi_wwid(device, replace_whitespace=False):
         return None
 
 
-def get_multipath_wwids():
-    """
-    Get WWIDs of all multipath devices available in the system.
-    """
-    multipath_devices = set()
-    multipath_wwids = set()
-    devuuids = [(d, i['UUID']) for d, i in blkid().items() if 'UUID' in i]
-    # Looking for two disks which contain filesystems with the same UUID.
-    for (dev1, uuid1), (dev2, uuid2) in itertools.combinations(devuuids, 2):
-        if uuid1 == uuid2:
-            multipath_devices.add(get_blockdev_for_partition(dev1)[0])
-    for device in multipath_devices:
-        wwid = get_scsi_wwid(device)
-        # Function get_scsi_wwid() may return None in case of errors or
-        # WWID field may be empty for some buggy disk. We don't want to
-        # propagate both of these value further to avoid generation of
-        # incorrect /etc/multipath/bindings file.
-        if wwid:
-            multipath_wwids.add(wwid)
-    return multipath_wwids
-
-
 def get_root_device(dev, paths=None):
     """
     Get root partition for specified device, based on presence of any
@@ -987,10 +974,11 @@ def sysfs_partition_data(blockdev=None, sysfs_path=None):
     # /sys/class/block/vda/vda1/queue/* as queue is only on the
     # parent device
     sysfs_prefix = sysfs_path
-    (parent, partnum) = get_blockdev_for_partition(blockdev)
-    if partnum:
-        sysfs_prefix = sys_block_path(parent)
-        partnum = int(partnum)
+    if not os.path.realpath(blockdev).startswith('/dev/dm-'):
+        (parent, partnum) = get_blockdev_for_partition(blockdev)
+         if partnum:
+             sysfs_prefix = sys_block_path(parent)
+             partnum = int(partnum)
 
     block_size = int(util.load_file(os.path.join(
         sysfs_prefix, 'queue/logical_block_size')))

Follow ups