From 31577ad32ca9344be399a0d993f23b96c6b80069 Mon Sep 17 00:00:00 2001
From: "Samantha N. Bueno" <sbueno+anaconda@redhat.com>
Date: Thu, 30 Apr 2015 02:59:41 -0400
Subject: [PATCH] Make appropriate changes to adapt for s390 libblockdev
 plugin.

This includes:
 -- removing blivet.devices.dasd
 -- moving some remaining, localized functions into blivet.devicetree
    (make_dasd_list and make_unformatted_dasd_list) or blivet.blivet
    (write_dasd_conf).
-- getting rid of dasd/zfcp input sanitizing functions
-- getting rid of the DASD test file (now in libblockdev)
---
 blivet/blivet.py                   |  15 ++-
 blivet/devicelibs/dasd.py          | 184 -------------------------------------
 blivet/devicelibs/lvm.py           |   2 +-
 blivet/devicetree.py               |  35 ++++++-
 blivet/zfcp.py                     |  65 +------------
 tests/devicelibs_test/dasd_test.py |  32 -------
 6 files changed, 52 insertions(+), 281 deletions(-)
 delete mode 100644 blivet/devicelibs/dasd.py
 delete mode 100644 tests/devicelibs_test/dasd_test.py

diff --git a/blivet/blivet.py b/blivet/blivet.py
index c49a380..3892580 100644
--- a/blivet/blivet.py
+++ b/blivet/blivet.py
@@ -37,7 +37,6 @@ from .devices import MDRaidArrayDevice, PartitionDevice, TmpFSDevice, devicePath
 from .deviceaction import ActionCreateDevice, ActionCreateFormat, ActionDestroyDevice
 from .deviceaction import ActionDestroyFormat, ActionResizeDevice, ActionResizeFormat
 from .devicelibs.edd import get_edd_dict
-from .devicelibs.dasd import make_dasd_list, write_dasd_conf
 from .errors import StorageError
 from .size import Size
 from .devicetree import DeviceTree
@@ -263,7 +262,7 @@ class Blivet(object):
             self.iscsi.startup()
             self.fcoe.startup()
             self.zfcp.startup()
-            self.dasd = make_dasd_list(self.dasd, self.devices)
+            self.dasd = self.devicetree.make_dasd_list(self.dasd, self.devices)
 
         if self.dasd:
             # Reset the internal dasd list (823534)
@@ -1399,6 +1398,18 @@ class Blivet(object):
         self.zfcp.write(getSysroot())
         write_dasd_conf(self.dasd, getSysroot())
 
+    def write_dasd_conf(self, disks, root):
+        """ Write /etc/dasd.conf to target system for all DASD devices
+            configured during installation.
+        """
+        if not (arch.isS390() or disks):
+            return
+
+        with open(os.path.realpath(root + "/etc/dasd.conf"), "w") as f:
+            for dasd in sorted(disks, key=lambda d: d.name):
+                fields = [dasd.busid] + dasd.getOpts()
+                f.write("%s\n" % " ".join(fields),)
+
     def turnOnSwap(self):
         self.fsset.turnOnSwap(rootPath=getSysroot())
 
diff --git a/blivet/devicelibs/dasd.py b/blivet/devicelibs/dasd.py
deleted file mode 100644
index e8ffdd5..0000000
--- a/blivet/devicelibs/dasd.py
+++ /dev/null
@@ -1,184 +0,0 @@
-#
-# dasd.py - DASD functions
-#
-# Copyright (C) 2013 Red Hat, Inc.  All rights reserved.
-#
-# 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/>.
-#
-# Red Hat Author(s): Samantha N. Bueno
-#
-
-import os
-from blivet.errors import DasdFormatError
-from blivet.devices import deviceNameToDiskByPath
-from blivet import util
-from blivet import arch
-
-import logging
-log = logging.getLogger("blivet")
-
-from blivet.i18n import _
-
-def get_dasd_ports():
-    """ Return comma delimited string of valid DASD ports. """
-    ports = []
-
-    with open("/proc/dasd/devices", "r") as f:
-        lines = (line.strip() for line in f.readlines())
-
-    for line in lines:
-        if "unknown" in line:
-            continue
-
-        if "(FBA )" in line or "(ECKD)" in line:
-            ports.append(line.split('(')[0])
-
-    return ','.join(ports)
-
-def format_dasd(dasd):
-    """ Run dasdfmt on a DASD. Aside from one type of device noted below, this
-        function _does not_ check if a DASD needs to be formatted, but rather,
-        assumes the list passed needs formatting.
-
-        We don't need to show or update any progress bars, since disk actions
-        will be taking place all in the progress hub, which is just one big
-        progress bar.
-    """
-    try:
-        rc = util.run_program(["/sbin/dasdfmt", "-y", "-d", "cdl", "-b", "4096", "/dev/" + dasd])
-    except Exception as err:
-        raise DasdFormatError(err)
-
-    if rc:
-        raise DasdFormatError("dasdfmt failed: %s" % rc)
-
-def make_dasd_list(dasds, disks):
-    """ Create a list of DASDs recognized by the system. """
-    if not arch.isS390():
-        return
-
-    log.info("Generating DASD list...")
-    for dev in (d for d in disks if d.type == "dasd"):
-        if dev not in dasds:
-            dasds.append(dev)
-
-    return dasds
-
-def make_unformatted_dasd_list(dasds):
-    """ Return a list of DASDS which are not formatted. """
-    unformatted = []
-
-    for dasd in dasds:
-        if dasd_needs_format(dasd):
-            unformatted.append(dasd)
-
-    return unformatted
-
-def dasd_needs_format(dasd):
-    """ Check if a DASD needs to have dasdfmt run against it or not.
-        Return True if we do need dasdfmt, False if not.
-    """
-    statusfile = "/sys/block/%s/device/status" % (dasd,)
-    if not os.path.isfile(statusfile):
-        return False
-
-    with open(statusfile, "r") as f:
-        status = f.read().strip()
-
-    if status in ["unformatted"]:
-        bypath = deviceNameToDiskByPath(dasd)
-        if not bypath:
-            bypath = "/dev/" + dasd
-
-        log.info("  %s (%s) status is %s, needs dasdfmt", dasd, bypath, status)
-        return True
-
-    return False
-
-def sanitize_dasd_dev_input(dev):
-    """ Synthesizes a complete DASD number from a possibly partial one.
-
-        :param str dev: a possibly partial DASD device number
-        :returns: a synthesized DASD device number
-        :rtype: str
-
-        :raises: ValueError if dev is None or empty
-
-        *) Assumes that the rightmost '.' if any, separates the bus number
-           from the device number.
-        *) Pads the device number on the left with 0s to a length of four
-           characters.
-        *) If no bus number extracted from dev, uses bus number default 0.0.
-
-        A DASD number has the format n.n.hhhh, where n is any decimal
-        digit and h any hexadecimal digit, e.g., 0.0.abcd, 0.0.002A.
-
-        A properly formatted number can be synthesized from a partial number
-        if the partial number is missing hexadecimal digits, e.g., 0.0.b, or
-        missing a bus number, e.g., 0012. The minimal partial number
-        contains a single digit. For example a will be extended to 0.0.000a.
-        Wildly improper partial numbers, e.g., qu.er.ty will yield a wildly
-        improper result.
-    """
-    if dev is None or dev == "":
-        raise ValueError(_("You have not specified a device number or the number is invalid"))
-    dev = dev.lower()
-    (bus, _sep, dev) = dev.rpartition('.')
-
-    padding = "0" * (4 - len(dev))
-    bus = bus or '0.0'
-    return bus + '.' + padding + dev
-
-def online_dasd(dev):
-    """ Given a device number, switch the device to be online.
-
-        :param str dev: a DASD device number
-
-        Raises a ValueError if a device with that number does not exist,
-        is already online, or can not be put online.
-    """
-    online = "/sys/bus/ccw/drivers/dasd-eckd/%s/online" % (dev)
-
-    if not os.path.exists(online):
-        log.info("Freeing DASD device %s", dev)
-        util.run_program(["dasd_cio_free", "-d", dev])
-
-    if not os.path.exists(online):
-        raise ValueError(_("DASD device %s not found, not even in device ignore list.")
-            % dev)
-
-    try:
-        with open(online, "r") as f:
-            devonline = f.readline().strip()
-        if devonline == "1":
-            raise ValueError(_("Device %s is already online.") % dev)
-        else:
-            with open(online, "w") as f:
-                log.debug("echo %s > %s", "1", online)
-                f.write("%s\n" % ("1"))
-    except IOError as e:
-        raise ValueError(_("Could not set DASD device %(dev)s online (%(e)s).") \
-                        % {'dev': dev, 'e': e})
-
-def write_dasd_conf(disks, root):
-    """ Write /etc/dasd.conf to target system for all DASD devices
-        configured during installation.
-    """
-    if not (arch.isS390() or disks):
-        return
-
-    with open(os.path.realpath(root + "/etc/dasd.conf"), "w") as f:
-        for dasd in sorted(disks, key=lambda d: d.name):
-            fields = [dasd.busid] + dasd.getOpts()
-            f.write("%s\n" % " ".join(fields),)
diff --git a/blivet/devicelibs/lvm.py b/blivet/devicelibs/lvm.py
index 6366703..f48743c 100644
--- a/blivet/devicelibs/lvm.py
+++ b/blivet/devicelibs/lvm.py
@@ -79,7 +79,7 @@ def _set_global_config():
     if not flags.lvm_metadata_backup:
         config_string += "backup {backup=0 archive=0} "
 
-    blockdev.lvm.set_global_config(config_string)
+    blockdev.lvm_set_global_config(config_string)
 
 def needs_config_refresh(fn):
     def fn_with_refresh(*args, **kwargs):
diff --git a/blivet/devicetree.py b/blivet/devicetree.py
index 4c3f40a..ce66b59 100644
--- a/blivet/devicetree.py
+++ b/blivet/devicetree.py
@@ -41,7 +41,7 @@ from .devices import MultipathDevice, NoDevice, OpticalDevice
 from .devices import PartitionDevice, ZFCPDiskDevice, iScsiDiskDevice
 from .devices import devicePathToName
 from .deviceaction import ActionCreateDevice, ActionDestroyDevice, action_type_from_string, action_object_from_string
-from . import formats
+from . import formats, arch
 from .formats import getFormat
 from .formats.fs import nodev_filesystems
 from .devicelibs import lvm
@@ -2270,6 +2270,39 @@ class DeviceTree(object):
             devices = (d for d in devices if getattr(d, "complete", True))
         return devices
 
+    def make_dasd_list(self, dasds, disks):
+        """ Create a list of DASDs recognized by the system
+
+            :param list dasds: a list of DASD devices
+            :param list disks: a list of disks on the system
+            :returns: a list of DASD devices identified on the system
+            :rtype: list of :class: 
+        """
+        if not arch.isS390():
+            return
+
+        log.info("Generating DASD list....")
+        for dev in (disk for disk in disks if disk.type == "dasd"):
+            if dev not in dasds:
+                dasds.append(dev)
+
+        return dasds
+
+    def make_unformatted_dasd_list(self, dasds):
+        """ Create a list of DASDs which are detected to require dasdfmt.
+
+            :param list dasds: a list of DASD devices
+            :returns: a list of DASDs which need dasdfmt in order to be used
+            :rtype: list of :class:
+        """
+        unformatted = []
+
+        for dasd in dasds:
+            if blockdev.s390.dasd_needs_format(dasd.busid):
+                unformatted.append(dasd)
+
+        return unformatted
+
     def getDeviceBySysfsPath(self, path, incomplete=False, hidden=False):
         """ Return a list of devices with a matching sysfs path.
 
diff --git a/blivet/zfcp.py b/blivet/zfcp.py
index 0b93e6f..aba8e93 100644
--- a/blivet/zfcp.py
+++ b/blivet/zfcp.py
@@ -25,6 +25,7 @@ from . import udev
 from . import util
 from .i18n import _
 from .util import stringize, unicodeize
+from gi.repository import BlockDev as bd
 
 import logging
 log = logging.getLogger("blivet")
@@ -41,9 +42,9 @@ zfcpconf = "/etc/zfcp.conf"
 
 class ZFCPDevice:
     def __init__(self, devnum, wwpn, fcplun):
-        self.devnum = self.sanitizeDeviceInput(devnum)
-        self.wwpn = self.sanitizeWWPNInput(wwpn)
-        self.fcplun = self.sanitizeFCPLInput(fcplun)
+        self.devnum = bd.s390.sanitize_dev_input(devnum)
+        self.wwpn = bd.s390.zfcp_sanitize_wwpn_input(wwpn)
+        self.fcplun = bd.s390.zfcp_sanitize_lun_input(fcplun)
 
         if not self.checkValidDevice(self.devnum):
             raise ValueError(_("You have not specified a device number or the number is invalid"))
@@ -62,64 +63,6 @@ class ZFCPDevice:
     def __unicode__(self):
         return unicodeize(self._toString())
 
-    def sanitizeDeviceInput(self, dev):
-        if dev is None or dev == "":
-            return None
-        dev = dev.lower()
-        bus = dev[:string.rfind(dev, ".") + 1]
-        dev = dev[string.rfind(dev, ".") + 1:]
-        dev = "0" * (4 - len(dev)) + dev
-        if not len(bus):
-            return "0.0." + dev
-        else:
-            return bus + dev
-
-    def sanitizeWWPNInput(self, wwpn):
-        if wwpn is None or wwpn == "":
-            return None
-        wwpn = wwpn.lower()
-        if wwpn[:2] != "0x":
-            return "0x" + wwpn
-        return wwpn
-
-    # ZFCP LUNs are usually entered as 16 bit, sysfs accepts only 64 bit
-    # (#125632), expand with zeroes if necessary
-    def sanitizeFCPLInput(self, lun):
-        if lun is None or lun == "":
-            return None
-        lun = lun.lower()
-        if lun[:2] == "0x":
-            lun = lun[2:]
-        lun = "0x" + "0" * (4 - len(lun)) + lun
-        lun = lun + "0" * (16 - len(lun) + 2)
-        return lun
-
-    def _hextest(self, hexnum):
-        try:
-            int(hexnum, 16)
-            return True
-        except TypeError:
-            return False
-
-    def checkValidDevice(self, devnum):
-        if devnum is None or devnum == "":
-            return False
-        if len(devnum) != 8:             # p.e. 0.0.0600
-            return False
-        if devnum[0] not in string.digits or devnum[2] not in string.digits:
-            return False
-        if devnum[1] != "." or devnum[3] != ".":
-            return False
-        return self._hextest(devnum[4:])
-
-    def checkValid64BitHex(self, hexnum):
-        if hexnum is None or hexnum == "":
-            return False
-        if len(hexnum) != 18:
-            return False
-        return self._hextest(hexnum)
-    checkValidWWPN = checkValidFCPLun = checkValid64BitHex
-
     def onlineDevice(self):
         online = "%s/%s/online" %(zfcpsysfs, self.devnum)
         portadd = "%s/%s/port_add" %(zfcpsysfs, self.devnum)
diff --git a/tests/devicelibs_test/dasd_test.py b/tests/devicelibs_test/dasd_test.py
deleted file mode 100644
index 98f2cd1..0000000
--- a/tests/devicelibs_test/dasd_test.py
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/usr/bin/python
-import unittest
-
-import blivet.devicelibs.dasd as dasd
-
-class SanitizeTest(unittest.TestCase):
-
-    def testSanitize(self):
-        with self.assertRaises(ValueError):
-            dasd.sanitize_dasd_dev_input("")
-
-        # without a ., the whole value is assumed to be the device number
-        # and a bus number is prepended
-        dev = "1234abc"
-        self.assertEqual(dasd.sanitize_dasd_dev_input(dev), '0.0.' + dev)
-
-        # whatever is on the left side of the rightmost period is assumed to
-        # be the bus number
-        dev = "zed.1234abq"
-        self.assertEqual(dasd.sanitize_dasd_dev_input(dev), dev)
-
-        # the device number is padded on the left with 0s up to 4 digits
-        dev = "zed.abc"
-        self.assertEqual(dasd.sanitize_dasd_dev_input(dev), "zed.0abc")
-        dev = "abc"
-        self.assertEqual(dasd.sanitize_dasd_dev_input(dev), "0.0.0abc")
-        dev = ".abc"
-        self.assertEqual(dasd.sanitize_dasd_dev_input(dev), "0.0.0abc")
-
-        # a complete number is unchanged
-        dev = "0.0.abcd"
-        self.assertEqual(dasd.sanitize_dasd_dev_input(dev), dev)
-- 
1.9.3

