[PATCH 2/2] Find and format any unformatted DASD devices (#528386).

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

 



Before the device tree is built in the storage code, run through the
DASD devices on the system and format any with a status of
'unformatted'.  We have to run dasdfmt on these devices before we can
partition them.

Under RHEL-5, this process was serial and the user had to click Yes for
each unformatted DASD found, which could take a really long time if
you had thousands of DASDs.

The idea now is that if the DASD is seen by anaconda, we want to use it
for installation.  The stage 1 device initialization routines as well as
the CMS conf file provided at boot time allow the user to restrict the
range of devices we see during installation.  If any of the devices we
see are unformatted, run dasdfmt before building the devicetree.

This process is implemented in a DASD class that works similar to the
iscsi and zfcp classes.  That is, devices may need to be started or
brought in to a working state before the anaconda storage code can use
them.
---
 storage/__init__.py |    3 +
 storage/dasd.py     |  167 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 170 insertions(+), 0 deletions(-)
 create mode 100644 storage/dasd.py

diff --git a/storage/__init__.py b/storage/__init__.py
index 0a9dad0..e1569c8 100644
--- a/storage/__init__.py
+++ b/storage/__init__.py
@@ -51,6 +51,7 @@ from udev import *
 import iscsi
 import fcoe
 import zfcp
+import dasd
 
 import gettext
 _ = lambda x: gettext.ldgettext("anaconda", x)
@@ -252,6 +253,7 @@ class Storage(object):
         self.iscsi = iscsi.iscsi()
         self.fcoe = fcoe.fcoe()
         self.zfcp = zfcp.ZFCP()
+        self.dasd = dasd.DASD()
 
         self._nextID = 0
         self.defaultFSType = get_default_filesystem_type()
@@ -320,6 +322,7 @@ class Storage(object):
         self.iscsi.startup(self.anaconda.intf)
         self.fcoe.startup(self.anaconda.intf)
         self.zfcp.startup()
+        self.dasd.startup(self.anaconda.intf)
         if self.anaconda.id.getUpgrade():
             clearPartType = CLEARPART_TYPE_NONE
         else:
diff --git a/storage/dasd.py b/storage/dasd.py
new file mode 100644
index 0000000..f4df8ca
--- /dev/null
+++ b/storage/dasd.py
@@ -0,0 +1,167 @@
+#
+# dasd.py - DASD class
+#
+# Copyright (C) 2009  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): David Cantrell <dcantrell@xxxxxxxxxx>
+#
+
+import iutil
+import sys
+import os
+from constants import *
+from flags import flags
+
+import logging
+log = logging.getLogger("anaconda")
+
+import gettext
+_ = lambda x: gettext.ldgettext("anaconda", x)
+P_ = lambda x, y, z: gettext.ldngettext("anaconda", x, y, z)
+
+class DASD:
+    """ Controlling class for DASD interaction before the storage code in
+        anaconda has initialized.
+
+        The DASD class can determine if any DASD devices on the system are
+        unformatted and can perform a dasdfmt on them.
+    """
+
+    def __init__(self):
+        self._dasdlist = []
+        self._totalCylinders = 0
+        self._completedCylinders = 0.0
+        self._maxFormatJobs = 0
+        self._progressBuffer = ''
+        self.started = False
+
+    def startup(self, intf=None):
+        """ Look for any unformatted DASDs in the system and offer the user
+            the option for format them with dasdfmt or exit the installer.
+        """
+        if self.started:
+            return
+
+        self.started = True
+
+        if not iutil.isS390():
+            return
+
+        log.info("Checking for unformatted DASD devices:")
+
+        for device in os.listdir("/sys/block"):
+            if not device.startswith("dasd"):
+                continue
+
+            statusfile = "/sys/block/%s/device/status" % (device,)
+            if not os.path.isfile(statusfile):
+                continue
+
+            f = open(statusfile, "r")
+            status = f.read().strip()
+            f.close()
+
+            if status == "unformatted":
+                log.info("    %s is an unformatted DASD" % (device,))
+                self._dasdlist.append(device)
+
+        if not len(self._dasdlist):
+            log.info("    no unformatted DASD devices found")
+            return
+
+        if intf:
+            c = len(self._dasdlist)
+
+            title = P_("Unformatted DASD Device Found",
+                       "Unformatted DASD Devices Found", c)
+            msg = P_("Format uninitialized DASD device?\n\n"
+                     "There is %d uninitialized DASD device on this "
+                     "system.  To continue installation, the device must "
+                     "be formatted.  Formatting will remove any data on "
+                     "this device.  If you are unsure of your DASD "
+                     "configuration, select No to exit the installer." % c,
+                     "Format uninitialized DASD devices?\n\n"
+                     "There are %d uninitialized DASD devices on this "
+                     "system.  To continue installation, the devices must "
+                     "be formatted.  Formatting will remove any data on "
+                     "these devices.  If you are unsure of your DASD "
+                     "configuration, select No to exit the installer." % c,
+                     c)
+
+            rc = intf.messageWindow(title, msg,
+                                    custom_icon="error", type="yesno")
+            if rc == 0:
+                sys.exit(0)
+
+        self._dasdlist = map(lambda s: "/dev/" + s, self._dasdlist)
+        dasdlist = " ".join(self._dasdlist)
+        log.info("Running dasdfmt on %s" % (dasdlist,))
+        argv = ["-y", "-P", "-d", "cdl", "-b", "4096"]
+
+        if intf:
+            title = P_("Formatting DASD Device", "Formatting DASD Devices", c)
+            msg = P_("Preparing %d DASD device for use with Linux..." % c,
+                     "Preparing %d DASD devices for use with Linux..." % c, c)
+            pw = intf.progressWindow(title, msg, 1.0)
+
+            for dasd in self._dasdlist:
+                iutil.execWithCallback("/sbin/dasdfmt", argv + [dasd],
+                                       stdout="/dev/tty5", stderr="/dev/tty5",
+                                       callback=self._updateProgressWindow,
+                                       callback_data=pw)
+
+            pw.pop()
+        else:
+            for dasd in self._dasdlist:
+                iutil.execWithRedirect("/sbin/dasdfmt", argv + [dasd],
+                                       stdout="/dev/tty5", stderr="/dev/tty5")
+
+    def _updateProgressWindow(self, data, callback_data=None):
+        """ Reads progress output from dasdfmt and collects the number of
+            cylinders completed so the progress window can update.
+        """
+        if not callback_data:
+            return
+
+        if data == '\n':
+            # each newline we see in this output means one more cylinder done
+            self._completedCylinders += 1.0
+            self._progressBuffer = ''
+            callback_data.set(self._completedCylinders / self.totalCylinders)
+        else:
+            self._progressBuffer += data
+
+    @property
+    def totalCylinders(self):
+        """ Total number of cylinders of all unformatted DASD devices. """
+        if self._totalCylinders:
+            return self._totalCylinders
+
+        argv = ["-t", "-v", "-y", "-d", "cdl", "-b", "4096"]
+        for dasd in self._dasdlist:
+            buf = iutil.execWithCapture("/sbin/dasdfmt", argv + [dasd],
+                                        stderr="/dev/tty5")
+            for line in buf.splitlines():
+                if line.startswith("Drive Geometry: "):
+                    # line will look like this:
+                    # Drive Geometry: 3339 Cylinders * 15 Heads =  50085 Tracks
+                    cyls = long(filter(lambda s: s, line.split(' '))[2])
+                    self._totalCylinders += cyls
+                    break
+
+        return self._totalCylinders
+
+# vim:tw=78:ts=4:et:sw=4
-- 
1.6.2.5

_______________________________________________
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