Re: [PATCH] Make multipath support use device-mapper-multipath to setup mpaths.

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

 



On 01/20/2010 04:19 PM, Peter Jones wrote:
> Use device-mapper-multipath's "multipath" tool to find and set up
> multipath devices.
> ---
>  storage/devicelibs/mpath.py |   91 +++++++++++++++++++++++++++++--------------
>  storage/devices.py          |   78 ++++++++++++++++++++++++++++++-------
>  2 files changed, 125 insertions(+), 44 deletions(-)
> 
> diff --git a/storage/devicelibs/mpath.py b/storage/devicelibs/mpath.py
> index 4d1b262..0f3efc2 100644
> --- a/storage/devicelibs/mpath.py
> +++ b/storage/devicelibs/mpath.py
> @@ -1,10 +1,13 @@
>  from ..udev import *
> +import iutil
>  
>  def parseMultipathOutput(output):
>      # this function parses output from "multipath -d", so we can use its
>      # logic for our topology.  It returns a structure like:
>      # [ {'mpathb':['sdb','sdc']}, ... ]
>      mpaths = {}
> +    if output is None:
> +        return mpaths

This, of course, is still wrong.

>  
>      name = None
>      devices = []
> @@ -37,63 +40,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 131db2a..0da4aed 100644
> --- a/storage/devices.py
> +++ b/storage/devices.py
> @@ -2931,11 +2931,8 @@ 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)
>                            parents=parents, sysfsPath=sysfsPath,
>                            exists=True)
>  
> @@ -3008,21 +3005,74 @@ 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 teardownPartitions(self):
> +        log_method_call(self, name=self.name, kids=self.kids)
> +        rc = iutil.execWithRedirect("kpartx",
> +                                ["-d", "-p", "p", "/dev/mapper/%s" % self.name],
> +                                stdout = "/dev/tty5",
> +                                stderr = "/dev/tty5")
> +        if rc:
> +            raise MPathError("multipath partition deactivation failed for '%s'"\
> +                            % self.name)
> +        udev_settle()
> +
> +    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)
> +            udev_settle()
> +
> +        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. """


-- 
        Peter

Computers have already beaten communists at chess.  The next thing you
know, they'll be beating humans.
		-- Dale

_______________________________________________
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