[PATCH 5/6] Make multipath support use device-mapper-multipath to setup mpaths.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Use device-mapper-multipath's "multipath" tool to find and set up
multipath devices.
---
 storage/devicelibs/mpath.py |   91 +++++++++++++++++++++++++++++--------------
 storage/devices.py          |   74 +++++++++++++++++++++++++++++------
 2 files changed, 122 insertions(+), 43 deletions(-)

diff --git a/storage/devicelibs/mpath.py b/storage/devicelibs/mpath.py
index b59f00e..06fd8b2 100644
--- a/storage/devicelibs/mpath.py
+++ b/storage/devicelibs/mpath.py
@@ -1,4 +1,5 @@
 from ..udev import *
+import iutil
 
 def parseMultipathOutput(output):
     # this function parses output from "multipath -d", so we can use its
@@ -20,6 +21,8 @@ def parseMultipathOutput(output):
     # It returns a structure like:
     # [ {'mpatha':['sdb','sdc']}, ... ]
     mpaths = {}
+    if output is None:
+        return mpaths
 
     name = None
     devices = []
@@ -52,63 +55,91 @@ def identifyMultipaths(devices):
     # 1) identifies multipath disks
     # 2) sets their ID_FS_TYPE to multipath_member
     # 3) removes the individual members of an mpath's partitions
-    # sample input with multipath pairs [sda,sdc] and [sdb,sdd]
-    # [sr0, sda, sda1, sdb, sda2, sdc, sdd, sdc1, sdc2, sde, sde1]
+    # sample input with multipath pair [sdb,sdc]
+    # [sr0, sda, sda1, sdb, sdb1, sdb2, sdc, sdc1, sdd, sdd1, sdd2]
     # sample output:
-    # [sr0, sda, sdb, sdc, sdd, sde, sde1]
-
+    # [sda, sdd], [[sdb, sdc]], [sr0, sda1, sdd1, sdd2]]
     log.info("devices to scan for multipath: %s" % [d['name'] for d in devices])
-    serials = {}
+
+    topology = parseMultipathOutput(iutil.execWithCapture("multipath", ["-d",]))
+    # find the devices that aren't in topology, and add them into it...
+    topodevs = reduce(lambda x,y: x.union(y), topology.values(), set())
+    for name in set([d['name'] for d in devices]).difference(topodevs):
+        topology[name] = [name]
+    
+    devmap = {}
     non_disk_devices = {}
     for d in devices:
-        serial = udev_device_get_serial(d)
-        if (not udev_device_is_disk(d)) or \
-                (not d.has_key('ID_SERIAL_SHORT')):
-            non_disk_devices.setdefault(serial, [])
-            non_disk_devices[serial].append(d)
+        if not udev_device_is_disk(d):
+            non_disk_devices[d['name']] = d
             log.info("adding %s to non_disk_device list" % (d['name'],))
             continue
-
-        serials.setdefault(serial, [])
-        serials[serial].append(d)
+        devmap[d['name']] = d
 
     singlepath_disks = []
     multipaths = []
-    for serial, disks in serials.items():
+
+    for name, disks in topology.items():
         if len(disks) == 1:
-            log.info("adding %s to singlepath_disks" % (disks[0]['name'],))
-            singlepath_disks.append(disks[0])
+            if not non_disk_devices.has_key(disks[0]):
+                log.info("adding %s to singlepath_disks" % (disks[0],))
+                singlepath_disks.append(devmap[disks[0]])
         else:
             # some usb cardreaders use multiple lun's (for different slots)
             # and report a fake disk serial which is the same for all the
             # lun's (#517603)
             all_usb = True
-            for d in disks:
+            # see if we've got any non-disk devices on our mpath list.
+            # If so, they're probably false-positives.
+            non_disks = False
+            for disk in disks:
+                d = devmap[disk]
                 if d.get("ID_USB_DRIVER") != "usb-storage":
                     all_usb = False
-                    break
+                if (not devmap.has_key(disk)) and non_disk_devices.has_key(disk):
+                    non_disks = True
+
             if all_usb:
                 log.info("adding multi lun usb mass storage device to singlepath_disks: %s" %
-                         [disk['name'] for disk in disks])
-                singlepath_disks.extend(disks)
+                         (disks,))
+                singlepath_disks.extend([devmap[d] for d in disks])
+                continue
+
+            if non_disks:
+                log.warning("non-disk device %s is part of an mpath")
+                for disk in disks:
+                    if devmap.has_key(disk):
+                        del devmap[disk]
+                    if topology.has_key(disk):
+                        del topology[disk]
                 continue
 
-            for d in disks:
-                log.info("adding %s to multipath_disks" % (d['name'],))
+            log.info("found multipath set: %s" % (disks,))
+            for disk in disks:
+                d = devmap[disk]
+                log.info("adding %s to multipath_disks" % (disk,))
                 d["ID_FS_TYPE"] = "multipath_member"
+                d["ID_MPATH_NAME"] = name
+            
+            multipaths.append([devmap[d] for d in disks])
 
-            multipaths.append(disks)
-            log.info("found multipath set: [%s]" % [d['name'] for d in disks])
+    non_disk_serials = {}
+    for name,device in non_disk_devices.items():
+        serial = udev_device_get_serial(device)
+        non_disk_serials.setdefault(serial, [])
+        non_disk_serials[serial].append(device)
 
     for mpath in multipaths:
-        for serial in [d['ID_SERIAL_SHORT'] for d in mpath]:
-            if non_disk_devices.has_key(serial):
-                log.info("filtering out non disk devices [%s]" % [d['name'] for d in non_disk_devices[serial]])
-                del non_disk_devices[serial]
+        for serial in [d.get('ID_SERIAL_SHORT') for d in mpath]:
+            if non_disk_serials.has_key(serial):
+                log.info("filtering out non disk devices [%s]" % [d['name'] for d in non_disk_serials[serial]])
+                for name in [d['name'] for d in non_disk_serials[serial]]:
+                    if non_disk_devices.has_key(name):
+                        del non_disk_devices[name]
 
     partition_devices = []
-    for devs in non_disk_devices.values():
-        partition_devices += devs
+    for device in non_disk_devices.values():
+        partition_devices.append(device)
 
     # this is the list of devices we want to keep from the original
     # device list, but we want to maintain its original order.
diff --git a/storage/devices.py b/storage/devices.py
index 237fc75..c56106f 100644
--- a/storage/devices.py
+++ b/storage/devices.py
@@ -2950,8 +2950,6 @@ class MultipathDevice(DMDevice):
         """
 
         self._info = info
-        self._isUp = False
-        self._pyBlockMultiPath = None
         self.setupIdentity()
         DMDevice.__init__(self, name, format=format, size=size,
                           parents=parents, sysfsPath=sysfsPath,
@@ -3026,21 +3024,71 @@ class MultipathDevice(DMDevice):
         else:
             self.parents.append(parent)
 
-    def setup(self, intf=None):
-        if self.status:
-            self.teardown()
-        self._isUp = True
-        parents = []
-        for p in self.parents:
-            parents.append(p.path)
-        self._pyBlockMultiPath = block.device.MultiPath(*parents)
+    def setupPartitions(self):
+        log_method_call(self, name=self.name, kids=self.kids)
+        rc = iutil.execWithRedirect("kpartx",
+                                ["-a", "-p", "p", "/dev/mapper/%s" % self.name],
+                                stdout = "/dev/tty5",
+                                stderr = "/dev/tty5")
+        if rc:
+            raise MPathError("multipath partition activation failed for '%s'" %
+                            self.name)
+        udev_settle()
+
+    def makeDMNodes(self):
+        log_method_call(self, name=self.name, kids=self.kids)
+        rc = iutil.execWithRedirect("dmsetup", ["mknodes"],
+                                stdout = "/dev/tty5",
+                                stderr = "/dev/tty5")
 
     def teardown(self, recursive=None):
-        if not self.status:
+        """ Tear down the mpath device. """
+        log_method_call(self, self.name, status=self.status)
+
+        if not self.exists and not recursive:
+            raise DeviceError("device has not been created", self.name)
+
+        if self.exists and os.path.exists(self.path):
+            #self.teardownPartitions()
+            #rc = iutil.execWithRedirect("multipath",
+            #                    ['-f', self.name],
+            #                    stdout = "/dev/tty5",
+            #                    stderr = "/dev/tty5")
+            #if rc:
+            #    raise MPathError("multipath deactivation failed for '%s'" %
+            #                    self.name)
+            bdev = block.getDevice(self.name)
+            devmap = block.getMap(major=bdev[0], minor=bdev[1])
+            if devmap.open_count:
+                return
+            try:
+                block.removeDeviceMap(devmap)
+            except Exception as e:
+                raise MPathError("failed to tear down multipath device %s: %s"
+                                % (self.name, e))
+
+        if recursive:
+            self.teardownParents(recursive=recursive)
+
+    def setup(self, intf=None):
+        """ Open, or set up, a device. """
+        log_method_call(self, self.name, status=self.status)
+
+        if self.status:
             return
-        self._isUp = False
-        self._pyBlockMultiPath = None
 
+        StorageDevice.setup(self, intf=intf)
+        udev_settle()
+        rc = iutil.execWithRedirect("multipath",
+                            [self.name],
+                            stdout = "/dev/tty5",
+                            stderr = "/dev/tty5")
+        if rc:
+            raise MPathError("multipath activation failed for '%s'" %
+                            self.name)
+        udev_settle()
+        self.setupPartitions()
+        udev_settle()
 
 class NoDevice(StorageDevice):
     """ A nodev device for nodev filesystems like tmpfs. """
-- 
1.6.5.2

_______________________________________________
Anaconda-devel-list mailing list
Anaconda-devel-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/anaconda-devel-list

[Index of Archives]     [Kickstart]     [Fedora Users]     [Fedora Legacy List]     [Fedora Maintainers]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [Yosemite Photos]     [KDE Users]     [Fedora Tools]
  Powered by Linux