Re: [PATCH 5/5] Recognize mpath devices when we see them.

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

 



On Thu, 2009-08-06 at 11:04 -0400, Peter Jones wrote:
> This identifies that a device is part of a multipath, and builds an
> mpath device for partitioning.

Comments inline...

> ---
>  70-anaconda.rules            |    2 +-
>  storage/devicelibs/dm.py     |   18 +++++
>  storage/devices.py           |  108 +++++++++++++++++++++++---
>  storage/devicetree.py        |  173 ++++++++++++++++++++++++++++++++++++------
>  storage/errors.py            |    3 +
>  storage/formats/multipath.py |   88 +++++++++++++++++++++
>  storage/udev.py              |   46 +++++++++++
>  7 files changed, 401 insertions(+), 37 deletions(-)
>  create mode 100644 storage/formats/multipath.py
> 

> diff --git a/storage/devicelibs/dm.py b/storage/devicelibs/dm.py
> index 29df126..a4a4ca9 100644
> --- a/storage/devicelibs/dm.py
> +++ b/storage/devicelibs/dm.py
> @@ -105,3 +113,13 @@ def get_backing_devs_from_name(map_name):
>      slave_devs = os.listdir("/sys/block/virtual/%s" % dm_node)
>      return slave_devs
>  
> +def dm_is_multipath_disk(map_name):
> +    return False
> +
> +def dm_get_mutlipath_partition_disk(map_name):
> +    return None
> +
> +def dm_is_multipath_partition(map_name):
> +    return False
> +
> +

Why add the above three functions if they don't do anything?

> diff --git a/storage/devices.py b/storage/devices.py
> index 3ca05aa..a866f14 100644
> --- a/storage/devices.py
> +++ b/storage/devices.py
> @@ -96,6 +96,7 @@
>  import os
>  import math
>  import copy
> +import string

If we can avoid this by using the string instances' methods we should do
so.

>  
>  # device backend modules
>  from devicelibs import mdraid
> @@ -416,7 +417,7 @@ class StorageDevice(Device):
>  
>      def __init__(self, device, format=None,
>                   size=None, major=None, minor=None,
> -                 sysfsPath='', parents=None, exists=None):
> +                 sysfsPath='', parents=None, exists=None, serial=None):
>          """ Create a StorageDevice instance.
>  
>              Arguments:
> @@ -446,6 +447,7 @@ class StorageDevice(Device):
>          self.minor = numeric_type(minor)
>          self.sysfsPath = sysfsPath
>          self.exists = exists
> +        self.serial = serial
>  
>          self.protected = False
>  
> @@ -735,12 +737,11 @@ class DiskDevice(StorageDevice):
>          else:
>              self._origPartedDisk = None
>  
> -
>      @property
>      def partedDisk(self):
>          if self._partedDisk:
>              return self._partedDisk
> -
> +        
>          log.debug("looking up parted Device: %s" % self.path)
>  
>          if self.partedDevice:
> @@ -762,14 +763,15 @@ class DiskDevice(StorageDevice):
>                  # When the device has no partition table but it has a FS, it
>                  # will be created with label type loop.  Treat the same as if
>                  # the device had no label (cause it really doesn't).
> -                if self._partedDisk.type == "loop":
> +                if self.partedDisk.type == "loop":
>                      if self._initcb is not None and self._initcb():
> -                        self._partedDisk = parted.freshDisk( \
> -                                device=self.partedDevice, \
> +                        self._partedDisk = parted.freshDisk(device=self.partedDevice, \
>                                  ty = platform.getPlatform(None).diskType)
>                      else:
>                          raise DeviceUserDeniedFormatError("User prefered to not format.")
>  
> +        return self._partedDisk
> +

It looks like some of the previous patch is being reverted in the above
hunk (self._partedDisk -v- self.partedDisk).

>      def __str__(self):
>          s = StorageDevice.__str__(self)
>          s += ("  removable = %(removable)s  partedDevice = %(partedDevice)r\n"
> @@ -2731,19 +2733,34 @@ class DMRaidArrayDevice(DiskDevice):
>          # information about it
>          self._size = self.currentSize
>  
> +class _MultipathDeviceNameGenerator:
> +    def __init__(self):
> +        self.number = 0
> +    def get(self):
> +        ret = self.number
> +        self.number += 1
> +        return ret
> +_multipathDeviceNameGenerator = _MultipathDeviceNameGenerator()
>  
> -class MultipathDevice(DMDevice):
> +def generateMultipathDeviceName():
> +    number = _multipathDeviceNameGenerator.get()
> +    return "mpath%s" % (number, )
> +
> +class MultipathDevice(DiskDevice):
>      """ A multipath device """
>      _type = "dm-multipath"
>      _packages = ["device-mapper-multipath"]
> +    _devDir = "/dev/mapper"
>  
> -    def __init__(self, name, format=None, size=None,
> -                 exists=None, parents=None, sysfsPath=''):
> +    def __init__(self, name, info, format=None, size=None,
> +                 parents=None, sysfsPath='', initcb=None,
> +                 initlabel=None):
>          """ Create a MultipathDevice instance.
>  
>              Arguments:
>  
>                  name -- the device name (generally a device node's basename)
> +                info -- the udev info for this device
>  
>              Keyword Arguments:
>  
> @@ -2751,12 +2768,79 @@ class MultipathDevice(DMDevice):
>                  size -- the device's size
>                  format -- a DeviceFormat instance
>                  parents -- a list of the backing devices (Device instances)
> -                exists -- indicates whether this is an existing device
> +                initcb -- the call back to be used when initiating disk.
> +                initlabel -- whether to start with a fresh disklabel
>          """
> -        DMDevice.__init__(self, name, format=format, size=size,
> +
> +        self._info = info
> +        self._isUp = False
> +        self._pyBlockMultiPath = None
> +        self.setupIdentity()
> +        DiskDevice.__init__(self, name, format=format, size=size,
>                            parents=parents, sysfsPath=sysfsPath,
> -                          exists=exists)
> +                          initcb=initcb, initlabel=initlabel)
> +
> +    def setupIdentity(self):
> +        """ Adds identifying remarks to MultipathDevice object.
> +        
> +            May be overridden by a sub-class for e.g. RDAC handling.
> +        """
> +        self._serial = self._info['ID_SERIAL_SHORT']
> +
> +    @property
> +    def identity(self):
> +        """ Get identity set with setupIdentityFromInfo()
> +        
> +            May be overridden by a sub-class for e.g. RDAC handling.
> +        """
> +        if not hasattr(self, "_serial"):
> +            raise RuntimeError, "setupIdentityFromInfo() has not been called."
> +        return self._serial
>  
> +    @property
> +    def up(self):
> +        return self._isUp

Is this different from status?

> +
> +    @property
> +    def path(self):
> +        """ Device node representing this device. """
> +        return "/dev/mapper/%s" % (self.name,)

This should not be needed. StorageDevice already does this, except
without hard-coding /dev/mapper.

> +
> +    @property
> +    def wwid(self):
> +        serial = self.identity
> +        ret = []
> +        while serial:
> +            ret.append(serial[:2])
> +            serial = serial[2:]
> +        return string.join(ret, ':')

You could avoid the string import above by instead doing this:

  return ":".join(ret)

Weird looking, I know.

> +
> +    @property
> +    def description(self):
> +        return "WWID %s" % (self.wwid,)
> +
> +    def addParent(self, parent):
> +        if self.up:
> +            self.teardown()
> +            self.parents.append(parent)
> +            self.setup()
> +        else:
> +            self.parents.append(parent)
> +
> +    def setup(self, intf=None):
> +        if self.up:
> +            self.teardown()
> +        self._isUp = True
> +        parents = []
> +        for p in self.parents:
> +            parents.append(p.path)
> +        self._pyBlockMultiPath = block.device.MultiPath(*parents)
> +
> +    def teardown(self, recursive=None):
> +        if not self.up:
> +            return
> +        self._isUp = False
> +        self._pyBlockMultiPath = None
>  
>  class NoDevice(StorageDevice):
>      """ A nodev device for nodev filesystems like tmpfs. """
> diff --git a/storage/devicetree.py b/storage/devicetree.py
> index 4ff4727..6030bd4 100644
> --- a/storage/devicetree.py
> +++ b/storage/devicetree.py
> @@ -31,6 +31,7 @@ from partitioning import shouldClear
>  from pykickstart.constants import *
>  import formats
>  import devicelibs.mdraid
> +import devicelibs.dm
>  from udev import *
>  from iutil import log_method_call
>  
> @@ -230,6 +231,7 @@ class DeviceTree(object):
>  
>          self.__passphrase = passphrase
>          self.__luksDevs = {}
> +        self.__multipaths = {}
>          if luksDict and isinstance(luksDict, dict):
>              self.__luksDevs = luksDict
>          self._ignoredDisks = []
> @@ -982,16 +984,25 @@ class DeviceTree(object):
>              # try to get the device again now that we've got all the slaves
>              device = self.getDeviceByName(name)
>  
> -            if device is None and \
> -                    udev_device_is_dmraid_partition(info, self):
> -                diskname = udev_device_get_dmraid_partition_disk(info)
> -                disk = self.getDeviceByName(diskname)
> -                device = PartitionDevice(name, sysfsPath=sysfs_path,
> -                                         major=udev_device_get_major(info),
> -                                         minor=udev_device_get_minor(info),
> -                                         exists=True, parents=[disk])
> -                # DWL FIXME: call self.addUdevPartitionDevice here instead
> -                self._addDevice(device)
> +            if device is None:
> +                if udev_device_is_multipath_partition(info, self):
> +                    diskname = udev_device_get_multipath_partition_disk(info)
> +                    disk = self.getDeviceByName(diskname)
> +                    device = PartitionDevice(name, sysfsPath=sysfs_path,
> +                                             major=udev_device_get_major(info),
> +                                             minor=udev_device_get_minor(info),
> +                                             exists=True, parents=[disk])
> +                elif udev_device_is_dmraid_partition(info, self):
> +                    diskname = udev_device_get_dmraid_partition_disk(info)
> +                    disk = self.getDeviceByName(diskname)
> +                    device = PartitionDevice(name, sysfsPath=sysfs_path,
> +                                             major=udev_device_get_major(info),
> +                                             minor=udev_device_get_minor(info),
> +                                             exists=True, parents=[disk])
> +                if not device is None:
> +                    # DWL FIXME: call self.addUdevPartitionDevice here instead
> +                    self._addDevice(device)
> +
>  
>              # if we get here, we found all of the slave devices and
>              # something must be wrong -- if all of the slaves are in
> @@ -1104,6 +1115,7 @@ class DeviceTree(object):
>          log_method_call(self, name=name)
>          uuid = udev_device_get_uuid(info)
>          sysfs_path = udev_device_get_sysfs_path(info)
> +        serial = udev_device_get_serial(info)
>          device = None
>  
>          kwargs = {}
> @@ -1193,7 +1205,18 @@ class DeviceTree(object):
>          #
>          # The first step is to either look up or create the device
>          #
> -        if udev_device_is_dm(info):
> +        if udev_device_is_multipath_member(info):
> +            device = StorageDevice(name,
> +                            major=udev_device_get_major(info),
> +                            minor=udev_device_get_minor(info),
> +                            sysfsPath=sysfs_path, exists=True,
> +                            serial=udev_device_get_serial(info))
> +            self._addDevice(device)
> +        elif udev_device_is_dm(info) and \
> +               devicelibs.dm.dm_is_multipath(info["DM_MAJOR"], info["DM_MINOR"]):
> +            log.debug("%s is a multipath device" % name)
> +            self.addUdevDMDevice(info)
> +        elif udev_device_is_dm(info):
>              log.debug("%s is a device-mapper device" % name)
>              # try to look up the device
>              if device is None and uuid:
> @@ -1413,6 +1436,44 @@ class DeviceTree(object):
>              md_array._addDevice(device)
>              self._addDevice(md_array)
>  
> +    def handleMultipathMemberFormat(self, info, device):
> +        log_method_call(self, name=device.name, type=device.format.type)
> +
> +        serial = udev_device_get_serial(info)
> +        found = False
> +        if self.__multipaths.has_key(serial):
> +            mp = self.__multipaths[serial]
> +            mp.addParent(device)
> +        else:
> +            name = generateMultipathDeviceName()
> +            devname = "/dev/mapper/%s" % (name,)
> +
> +            if self.zeroMbr:
> +                cb = lambda: True
> +            else:
> +                desc = []
> +                serialtmp = serial
> +                while serialtmp:
> +                    desc.append(serialtmp[:2])
> +                    serialtmp = serialtmp[2:]
> +                desc = "WWID %s" % (string.join(desc, ':'),)

Again, you can do ":".join(desc) here instead.

> +
> +                cb = lambda: questionInitializeDisk(self.intf, devname, desc)
> +
> +            initlabel = False
> +            if not self.clearPartDisks or \
> +                    rs.name in self.clearPartDisks:
> +                initlabel = self.reinitializeDisks
> +                for protected in self.protectedDevNames:
> +                    disk_name = re.sub(r'p\d+$', '', protected)
> +                    if disk_name != protected and \
> +                            disk_name == name:
> +                        initlabel = False
> +                        break
> +            mp = MultipathDevice(name, info, parents=[device], initcb=cb,
> +                                 initlabel=initlabel)
> +            self.__multipaths[serial] = mp
> +
>      def handleUdevDMRaidMemberFormat(self, info, device):
>          log_method_call(self, name=device.name, type=device.format.type)
>          name = udev_device_get_name(info)
> @@ -1504,6 +1565,7 @@ class DeviceTree(object):
>          uuid = udev_device_get_uuid(info)
>          label = udev_device_get_label(info)
>          format_type = udev_device_get_format(info)
> +        serial = udev_device_get_serial(info)
>  
>          format = None
>          if (not device) or (not format_type) or device.format.type:
> @@ -1517,10 +1579,13 @@ class DeviceTree(object):
>          kwargs = {"uuid": uuid,
>                    "label": label,
>                    "device": device.path,
> +                  "serial": serial,
>                    "exists": True}
>  
>          # set up type-specific arguments for the format constructor
> -        if format_type == "crypto_LUKS":
> +        if format_type == "multipath_member":
> +            kwargs["multipath_members"] = self.getDevicesBySerial(serial)
> +        elif format_type == "crypto_LUKS":
>              # luks/dmcrypt
>              kwargs["name"] = "luks-%s" % uuid
>          elif format_type in formats.mdraid.MDRaidMember._udevTypes:
> @@ -1590,6 +1655,8 @@ class DeviceTree(object):
>              self.handleUdevDMRaidMemberFormat(info, device)
>          elif device.format.type == "lvmpv":
>              self.handleUdevLVMPVFormat(info, device)
> +        elif device.format.type == "multipath_member":
> +            self.handleMultipathMemberFormat(info, device)
>  
>      def _handleInconsistencies(self):
>          def reinitializeVG(vg):
> @@ -1708,6 +1775,49 @@ class DeviceTree(object):
>                          (disk.name, disk.format, format))
>                  disk.format = format
>  
> +    def identifyMultipaths(self, devices):
> +        log.info("devices to scan for multipath: %s" % [d['name'] for d in devices])
> +        serials = {}
> +        non_disk_devices = {}
> +        for d in devices:
> +            serial = udev_device_get_serial(d)
> +            if not udev_device_is_disk(d):
> +                non_disk_devices.setdefault(serial, [])
> +                non_disk_devices[serial].append(d)
> +                log.info("adding %s to non_disk_device list" % (d['name'],))
> +                continue
> +
> +            serials.setdefault(serial, [])
> +            serials[serial].append(d)
> +
> +        singlepath_disks = []
> +        multipath_disks = []
> +        for serial, disks in serials.items():
> +            if len(disks) == 1:
> +                log.info("adding %s to singlepath_disks" % (disks[0]['name'],))
> +                singlepath_disks.append(disks[0])
> +            else:
> +                multipath_members = {}
> +                for d in disks:
> +                    log.info("adding %s to multipath_disks" % (d['name'],))
> +                    d["ID_FS_TYPE"] = "multipath_member"
> +                    multipath_disks.append(d)
> +
> +                    multipath_members[d['name']] = { 'info': d,
> +                                                     'found': False }
> +                    log.info("found multipath set: [%s]" % [d['name'] for d in disks])
> +
> +        for serial in [d['ID_SERIAL_SHORT'] for d in multipath_disks]:
> +            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]
> +
> +        partition_devices = []
> +        for devices in non_disk_devices.values():
> +            partition_devices += devices
> +
> +        return partition_devices + multipath_disks + singlepath_disks
> +
>      def populate(self):
>          """ Locate all storage devices. """
>  
> @@ -1723,27 +1833,32 @@ class DeviceTree(object):
>  
>          # each iteration scans any devices that have appeared since the
>          # previous iteration
> -        old_devices = []
> +        old_devices = {}
>          ignored_devices = []
> +        first_iteration = True
> +        handled_mpaths = False
>          while True:
>              devices = []
>              new_devices = udev_get_block_devices()
>  
>              for new_device in new_devices:
> -                found = False
> -                for old_device in old_devices:
> -                    if old_device['name'] == new_device['name']:
> -                        found = True
> -                        break
> -
> -                if not found:
> +                if not old_devices.has_key(new_device['name']):
> +                    old_devices[new_device['name']] = new_device
>                      devices.append(new_device)
>  
>              if len(devices) == 0:
> -                # nothing is changing -- we are finished building devices
> -                break
> -
> -            old_devices = new_devices
> +                if handled_mpaths:
> +                    # nothing is changing -- we are finished building devices
> +                    break
> +                for mp in self.__multipaths.values():
> +                    log.info("adding mpath device %s" % (mp.name,))
> +                    mp.setup()
> +                    self._addDevice(mp)
> +                handled_mpaths = True
> +
> +            if first_iteration:
> +                devices = self.identifyMultipaths(devices)
> +                first_iteration = False
>              log.info("devices to scan: %s" % [d['name'] for d in devices])
>              for dev in devices:
>                  self.addUdevDevice(dev)
> @@ -1803,6 +1918,16 @@ class DeviceTree(object):
>  
>          return found
>  
> +    def getDevicesBySerial(self, serial):
> +        devices = []
> +        for device in self._devices:
> +            if not hasattr(device, "serial"):
> +                log.warning("device %s has no serial attr" % device.name)
> +                continue
> +            if device.serial == serial:
> +                devices.append(device)
> +        return devices
> +
>      def getDeviceByLabel(self, label):
>          if not label:
>              return None
> diff --git a/storage/errors.py b/storage/errors.py
> index 9dd121c..e0175fc 100644
> --- a/storage/errors.py
> +++ b/storage/errors.py
> @@ -64,6 +64,9 @@ class FormatTeardownError(DeviceFormatError):
>  class DMRaidMemberError(DeviceFormatError):
>      pass
>  
> +class MultipathMemberError(DeviceFormatError):
> +    pass
> +
>  class FSError(DeviceFormatError):
>      pass
>  
> diff --git a/storage/formats/multipath.py b/storage/formats/multipath.py
> new file mode 100644
> index 0000000..cad2552
> --- /dev/null
> +++ b/storage/formats/multipath.py
> @@ -0,0 +1,88 @@
> +# multipath.py
> +# multipath device formats
> +#
> +# Copyright (C) 2009  Red Hat, Inc.
> +#
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 2 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program.  If not, see <http://www.gnu.org/licenses/>.
> +#
> +# Any Red Hat trademarks that are incorporated in the source code or
> +# documentation are not subject to the GNU General Public License and
> +# may only be used or replicated with the express permission of
> +# Red Hat, Inc.
> +#
> +# Red Hat Author(s): Peter Jones <pjones@xxxxxxxxxx>
> +#
> +
> +from iutil import log_method_call
> +from ..errors import *
> +from . import DeviceFormat, register_device_format
> +
> +import gettext
> +_ = lambda x: gettext.ldgettext("anaconda", x)
> +
> +import logging
> +log = logging.getLogger("storage")
> +
> +class MultipathMember(DeviceFormat):
> +    """ A multipath member disk. """
> +    _type = "multipath_member"
> +    _name = "multipath member device"
> +    _udev_types = ["multipath_member"]
> +    _formattable = False                # can be formatted
> +    _supported = True                   # is supported
> +    _linuxNative = False                # for clearpart
> +    _packages = ["device-mapper-multipath"] # required packages
> +    _resizable = False                  # can be resized
> +    _bootable = False                   # can be used as boot
> +    _maxSize = 0                        # maximum size in MB
> +    _minSize = 0                        # minimum size in MB
> +
> +    def __init__(self, *args, **kwargs):
> +        """ Create a DeviceFormat instance.
> +
> +            Keyword Arguments:
> +
> +                device -- path to the underlying device
> +                uuid -- this format's UUID
> +                exists -- indicates whether this is an existing format
> +
> +            On initialization this format is like DeviceFormat
> +
> +        """
> +        log_method_call(self, *args, **kwargs)
> +        DeviceFormat.__init__(self, *args, **kwargs)
> +
> +        # Initialize the attribute that will hold the block object.
> +        self._member = None
> +
> +    @property
> +    def member(self):
> +        return self._member
> +
> +    @member.setter
> +    def member(self, member):
> +        self._member = member
> +
> +    def create(self, *args, **kwargs):
> +        log_method_call(self, device=self.device,
> +                        type=self.type, status=self.status)
> +        raise MultipathMemberError("creation of multipath members is non-sense")
> +
> +    def destroy(self, *args, **kwargs):
> +        log_method_call(self, device=self.device,
> +                        type=self.type, status=self.status)
> +        raise MultipathMemberError("destruction of multipath members is non-sense")
> +
> +register_device_format(MultipathMember)
> +
> diff --git a/storage/udev.py b/storage/udev.py
> index 450b54a..adb69e6 100644
> --- a/storage/udev.py
> +++ b/storage/udev.py
> @@ -22,6 +22,7 @@
>  
>  import os
>  import stat
> +import block
>  
>  import iutil
>  from errors import *
> @@ -134,6 +135,10 @@ def udev_device_get_label(udev_info):
>      """ Get the label from the device's format as reported by udev. """
>      return udev_info.get("ID_FS_LABEL")
>  
> +def udev_device_is_multipath_member(info):
> +    """ Return True if the device is part of a multipath. """
> +    return info.get("ID_FS_TYPE") == "multipath_member"

It kind of sucks that we have this string both in the format class and
here.

> +
>  def udev_device_is_dm(info):
>      """ Return True if the device is a device-mapper device. """
>      return info.has_key("DM_NAME")
> @@ -158,6 +163,10 @@ def udev_device_is_partition(info):
>      has_start = os.path.exists("/sys/%s/start" % info['sysfs_path'])
>      return info.get("DEVTYPE") == "partition" or has_start
>  
> +def udev_device_get_serial(udev_info):
> +    """ Get the serial number/UUID from the device as reported by udev. """
> +    return udev_info.get("ID_SERIAL_SHORT")
> +
>  def udev_device_get_sysfs_path(info):
>      return info['sysfs_path']
>  
> @@ -276,6 +285,43 @@ def udev_device_is_dmraid_partition(info, devicetree):
>  
>      return False
>  
> +def udev_device_is_multipath_partition(info, devicetree):
> +    """ Return True if the device is a partition of a multipath device. """
> +    if not udev_device_is_dm(info):
> +        return False
> +    if not info["DM_NAME"].startswith("mpath"):
> +        return False
> +    diskname = udev_device_get_dmraid_partition_disk(info)
> +    if diskname is None:
> +        return False
> +
> +    # this is sort of a lame check, but basically, if diskname gave us "mpath0"
> +    # and we start with "mpath" but we're not "mpath0", then we must be
> +    # "mpath0" plus some non-numeric crap.
> +    if diskname != info["DM_NAME"]:
> +        return True
> +
> +    return False
> +    
> +    
> +    mpath_devices = devicetree.getDevicesByType("multipath")
> +
> +    for device in mpath_devices:
> +        if diskname == device.name:
> +            return True
> +
> +    return False
> +
> +def udev_device_get_multipath_partition_disk(info):
> +    """ Return True if the device is a partition of a multipath device. """
> +    # XXX PJFIX This whole function is crap.
> +    if not udev_device_is_dm(info):
> +        return False
> +    if not info["DM_NAME"].startswith("mpath"):
> +        return False
> +    diskname = udev_device_get_dmraid_partition_disk(info)
> +    return diskname
> +
>  # iscsi disks have ID_PATH in the form of:
>  # ip-${iscsi_address}:${iscsi_port}-iscsi-${iscsi_tgtname}-lun-${lun}
>  def udev_device_is_iscsi(info):

_______________________________________________
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