summaryrefslogtreecommitdiffstats
path: root/pyanaconda/storage/devicelibs/mpath.py
diff options
context:
space:
mode:
Diffstat (limited to 'pyanaconda/storage/devicelibs/mpath.py')
-rw-r--r--pyanaconda/storage/devicelibs/mpath.py285
1 files changed, 0 insertions, 285 deletions
diff --git a/pyanaconda/storage/devicelibs/mpath.py b/pyanaconda/storage/devicelibs/mpath.py
deleted file mode 100644
index d49ab07be..000000000
--- a/pyanaconda/storage/devicelibs/mpath.py
+++ /dev/null
@@ -1,285 +0,0 @@
-
-import re
-
-from ..udev import udev_device_is_disk
-from .. import util
-from ..flags import flags
-from ..storage_log import log_method_call
-
-import logging
-log = logging.getLogger("storage")
-
-def parseMultipathOutput(output):
- """
- Parse output from "multipath -d" or "multipath -ll" and form a topology.
-
- Returns a dictionary:
- {'mpatha':['sdb','sdc'], 'mpathb': ['sdd', 'sde'], ... }
-
- The 'multipath -d' output looks like:
- create: mpathc (1ATA ST3120026AS 5M) undef ATA,ST3120026AS
- size=112G features='0' hwhandler='0' wp=undef
- `-+- policy='round-robin 0' prio=1 status=undef
- `- 2:0:0:0 sda 8:0 undef ready running
- create: mpathb (36006016092d21800703762872c60db11) undef DGC,RAID 5
- size=10G features='1 queue_if_no_path' hwhandler='1 emc' wp=undef
- `-+- policy='round-robin 0' prio=2 status=undef
- |- 6:0:0:0 sdb 8:16 undef ready running
- `- 7:0:0:0 sdc 8:32 undef ready running
- create: mpatha (36001438005deb4710000500000270000) dm-0 HP,HSV400
- size=20G features='0' hwhandler='0' wp=rw
- |-+- policy='round-robin 0' prio=-1 status=active
- | |- 7:0:0:1 sda 8:0 active undef running
- | `- 7:0:1:1 sdb 8:16 active undef running
- `-+- policy='round-robin 0' prio=-1 status=enabled
- |- 7:0:2:1 sdc 8:32 active undef running
- `- 7:0:3:1 sdd 8:48 active undef running
-
- (In anaconda, the first one there won't be included because we blacklist
- "ATA" as a vendor.)
-
- The 'multipath -ll' output looks like (notice the missing 'create' before
- 'mpatha'):
-
- mpatha (3600a0b800067fcc9000001694b557dd1) dm-0 IBM,1726-4xx FAStT
- size=360G features='0' hwhandler='1 rdac' wp=rw
- `-+- policy='round-robin 0' prio=3 status=active
- |- 2:0:0:0 sda 8:0 active ready running
- `- 3:0:0:0 sdb 8:16 active ready running
-
- """
- mpaths = {}
- if output is None:
- return mpaths
-
- name = None
- devices = []
-
- policy = re.compile('^[|+` -]+policy')
- device = re.compile('^[|+` -]+[0-9]+:[0-9]+:[0-9]+:[0-9]+ ([a-zA-Z0-9!/]+)')
- create = re.compile('^(create: )?(mpath\w+|[a-f0-9]+)')
-
- lines = output.split('\n')
- for line in lines:
- pmatch = policy.match(line)
- dmatch = device.match(line)
- cmatch = create.match(line)
- lexemes = line.split()
- if not lexemes:
- break
- if cmatch and cmatch.group(2):
- if name and devices:
- mpaths[name] = devices
- name = None
- devices = []
- name = cmatch.group(2)
- elif lexemes[0].startswith('size='):
- pass
- elif pmatch:
- pass
- elif dmatch:
- devices.append(dmatch.groups()[0].replace('!','/'))
-
- if name and devices:
- mpaths[name] = devices
-
- return mpaths
-
-class MultipathTopology(object):
- def __init__(self, devices_list):
- self._devices = devices_list
- self._nondisks = []
- self._singlepaths = []
- self._multipaths = [] # mpath members
- self._devmap = {}
-
- self._build_topology()
-
- def _build_devmap(self):
- self._devmap = {}
- for dev in self._devices:
- self._devmap[dev['name']] = dev
-
- def _build_mpath_topology(self):
- with open("/etc/multipath.conf") as conf:
- log.debug("/etc/multipath.conf contents:")
- map(lambda line: log.debug(line.rstrip()), conf)
- log.debug("(end of /etc/multipath.conf)")
- self._mpath_topology = parseMultipathOutput(
- util.capture_output(["multipath", "-d"]))
- self._mpath_topology.update(parseMultipathOutput(
- util.capture_output(["multipath", "-ll"])))
-
- delete_keys = []
- for (mp, disks) in self._mpath_topology.items():
- # single device mpath is not really an mpath, eliminate them:
- if len(disks) < 2:
- log.info("MultipathTopology: not a multipath: %s" % disks)
- delete_keys.append(mp)
- continue
- # 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). find those mpaths and eliminate them:
- only_non_usbs = [d for d in disks if
- self._devmap[d].get("ID_USB_DRIVER") != "usb-storage"]
- if len(only_non_usbs) == 0:
- log.info("DeviceToppology: found multi lun usb "
- "mass storage device: %s" % disks)
- delete_keys.append(mp)
- map(lambda key: self._mpath_topology.pop(key), delete_keys)
-
- def _build_topology(self):
- log_method_call(self)
- self._build_devmap()
- self._build_mpath_topology()
-
- for dev in self._devices:
- name = dev['name']
- if not udev_device_is_disk(dev):
- self._nondisks.append(name)
- log.info("MultipathTopology: found non-disk device: %s" % name)
- continue
- mpath_name = self.multipath_name(name)
- if mpath_name:
- dev["ID_FS_TYPE"] = "multipath_member"
- dev["ID_MPATH_NAME"] = mpath_name
- log.info("MultipathTopology: found a multipath member of %s: %s " %
- (mpath_name, name))
- continue
- # it's a disk and not a multipath member (can be a coalesced
- # multipath)
- self._singlepaths.append(name)
- log.info("MultipathTopology: found singlepath device: %s" % name)
-
- def devices_iter(self):
- """ Generator. Yields all disk devices, mpaths members, coalesced mpath
- devices and partitions.
-
- This property guarantees the order of the returned devices is the
- same as in the device list passed to the object's constructor.
- """
- for device in self._devices:
- yield device
-
- def singlepaths_iter(self):
- """ Generator. Yields only the singlepath disks.
- """
- for name in self._singlepaths:
- yield self._devmap[name]
-
- def multipath_name(self, mpath_member_name):
- """ If the mpath_member_name is a member of a multipath device return
- the name of the device (e.g. mpathc).
-
- Else return None.
- """
- for (name, members) in self._mpath_topology.items():
- if mpath_member_name in members:
- return name
- return None
-
- def multipaths_iter(self):
- """Generator. Yields all the multipath members, in a topology.
-
- Every iteration returns a list of mpath member devices forming a
- multipath.
- """
- for disks in self._mpath_topology.values():
- yield [self._devmap[d] for d in disks]
-
-
-class MultipathConfigWriter:
- def __init__(self):
- self.blacklist_devices = []
- self.mpaths = []
-
- def addBlacklistDevice(self, device):
- self.blacklist_devices.append(device)
-
- def addMultipathDevice(self, mpath):
- self.mpaths.append(mpath)
-
- def write(self, friendly_names):
- # if you add anything here, be sure and also add it to anaconda's
- # multipath.conf
- ret = ''
- ret += """\
-# multipath.conf written by anaconda
-
-defaults {
- user_friendly_names %(friendly_names)s
-}
-blacklist {
- devnode "^(ram|raw|loop|fd|md|dm-|sr|scd|st)[0-9]*"
- devnode "^hd[a-z]"
- devnode "^dcssblk[0-9]*"
- device {
- vendor "DGC"
- product "LUNZ"
- }
- device {
- vendor "IBM"
- product "S/390.*"
- }
- # don't count normal SATA devices as multipaths
- device {
- vendor "ATA"
- }
- # don't count 3ware devices as multipaths
- device {
- vendor "3ware"
- }
- device {
- vendor "AMCC"
- }
- # nor highpoint devices
- device {
- vendor "HPT"
- }
-""" % {'friendly_names' : "yes" if friendly_names else "no"}
- for device in self.blacklist_devices:
- if device.serial:
- ret += '\twwid "%s"\n' % device.serial
- elif device.vendor and device.model:
- ret += '\tdevice {\n'
- ret += '\t\tvendor %s\n' % device.vendor
- ret += '\t\tproduct %s\n' % device.model
- ret += '\t}\n'
- if self.mpaths:
- ret += '\twwid "*"\n'
- ret += '}\n'
- ret += 'blacklist_exceptions {\n'
- for mpath in self.mpaths:
- for k,v in mpath.config.items():
- if k == 'wwid':
- ret += '\twwid "%s"\n' % v
- ret += '}\n'
- ret += 'multipaths {\n'
- for mpath in self.mpaths:
- ret += '\tmultipath {\n'
- for k,v in mpath.config.items():
- if k == 'wwid':
- ret += '\t\twwid "%s"\n' % v
- else:
- ret += '\t\t%s %s\n' % (k, v)
- ret += '\t}\n'
- ret += '}\n'
-
- return ret
-
- def writeConfig(self, friendly_names=True):
- if not flags.multipath:
- # not writing out a multipath.conf will effectively blacklist all
- # mpath which will prevent any of them from being activated during
- # install
- return
-
- cfg = self.write(friendly_names)
- with open("/etc/multipath.conf", "w+") as mpath_cfg:
- mpath_cfg.write(cfg)
-
-def flush_mpaths():
- util.run_program(["multipath", "-F"])
- check_output = util.capture_output(["multipath", "-ll"]).strip()
- if check_output:
- log.error("multipath: some devices could not be flushed")