diff options
author | David Cantrell <dcantrell@redhat.com> | 2010-04-28 12:29:39 -1000 |
---|---|---|
committer | David Cantrell <dcantrell@redhat.com> | 2010-04-28 12:29:39 -1000 |
commit | 7d77daf5542ee07a6887756214c832cd31077963 (patch) | |
tree | e2a99617b84647f1964fc00f7e31f6af8db26908 /storage | |
parent | b0771f5d49a22ea8c154421c73d5f7cf21a0bf26 (diff) | |
download | anaconda-7d77daf5542ee07a6887756214c832cd31077963.tar.gz anaconda-7d77daf5542ee07a6887756214c832cd31077963.tar.xz anaconda-7d77daf5542ee07a6887756214c832cd31077963.zip |
Offer to format unformatted DASD devices (#560702)
On s390, if you had a single DASD that needed dasdfmt run, you would get
a ZeroDivisionError traceback because the self._totalCylinders value was
zero. The problem was caused by the DASD.totalCylinders property and
how it initialized. It would initialize itself on the first call, but
since we'd already fired off a dasdfmt process for the device, the one
running to capture the cylinder count couldn't get access to the device.
Users with more than one DASD needing a dasdfmt would not see the
traceback, but would have an incorrect total cylinder count, so 100%
would be reached when n-1 devices had been formatted.
Honor the exclusiveDisks list in the storage object and log the
/dev/disk/by-path alias for the device when logging the info message
about what device was found that was unformatted.
[Originally worked up in November 2009, I've updated the patch a bit to
work with our current code. Tested in text mode and gui mode. If you
have any unformatted DASD devices, anaconda prompts you and asks if you
want to format them.]
Diffstat (limited to 'storage')
-rw-r--r-- | storage/__init__.py | 2 | ||||
-rw-r--r-- | storage/dasd.py | 110 | ||||
-rw-r--r-- | storage/errors.py | 3 |
3 files changed, 68 insertions, 47 deletions
diff --git a/storage/__init__.py b/storage/__init__.py index 85ee6cf3d..fc0db0007 100644 --- a/storage/__init__.py +++ b/storage/__init__.py @@ -371,7 +371,7 @@ class Storage(object): self.iscsi.startup(self.anaconda.intf) self.fcoe.startup(self.anaconda.intf) self.zfcp.startup() - self.dasd.startup(intf=self.anaconda.intf, zeroMbr=self.zeroMbr) + self.dasd.startup(self.anaconda.intf, self.exclusiveDisks, self.zeroMbr) if self.anaconda.upgrade: clearPartType = CLEARPART_TYPE_NONE else: diff --git a/storage/dasd.py b/storage/dasd.py index a8ee27adf..d8766d92d 100644 --- a/storage/dasd.py +++ b/storage/dasd.py @@ -1,7 +1,7 @@ # # dasd.py - DASD class # -# Copyright (C) 2009 Red Hat, Inc. All rights reserved. +# Copyright (C) 2009, 2010 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 @@ -22,6 +22,7 @@ import iutil import sys import os +from storage.errors import DasdFormatError from storage.devices import deviceNameToDiskByPath from constants import * from flags import flags @@ -61,15 +62,17 @@ class DASD: def __init__(self): self._dasdlist = [] self._devices = [] # list of DASDDevice objects - self._totalCylinders = 0 + self.totalCylinders = 0 self._completedCylinders = 0.0 self._maxFormatJobs = 0 + self.dasdfmt = "/sbin/dasdfmt" + self.commonArgv = ["-y", "-d", "cdl", "-b", "4096"] self.started = False def __call__(self): return self - def startup(self, *args, **kwargs): + def startup(self, intf, exclusiveDisks, zeroMbr): """ Look for any unformatted DASDs in the system and offer the user the option for format them with dasdfmt or exit the installer. """ @@ -77,13 +80,12 @@ class DASD: return self.started = True + out = "/dev/tty5" + err = "/dev/tty5" if not iutil.isS390(): return - intf = kwargs.get("intf") - zeroMbr = kwargs.get("zeroMbr") - log.info("Checking for unformatted DASD devices:") for device in os.listdir("/sys/block"): @@ -98,8 +100,11 @@ class DASD: status = f.read().strip() f.close() - if status == "unformatted": - log.info(" %s is an unformatted DASD" % (device,)) + if status in ["unformatted"] and device not in exclusiveDisks: + bypath = deviceNameToDiskByPath("/dev/" + device) + log.info(" %s (%s) status is %s, needs dasdfmt" % (device, + bypath, + status,)) self._dasdlist.append(device) if not len(self._dasdlist): @@ -133,27 +138,60 @@ class DASD: log.info(" rescue mode: not running dasdfmt") return - argv = ["-y", "-P", "-d", "cdl", "-b", "4096"] + # gather total cylinder count + argv = ["-t", "-v"] + self.commonArgv + for dasd in self._dasdlist: + buf = iutil.execWithCapture(self.dasdfmt, argv + [dasd], + stderr=err) + 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 + + # format DASDs + argv = ["-P"] + self.commonArgv + update = self._updateProgressWindow + + 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) 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) + if self.totalCylinders: + pw = intf.progressWindow(title, msg, 1.0) + else: + pw = intf.progressWindow(title, msg, 100, pulse=True) - for dasd in self._dasdlist: - log.info("Running dasdfmt on %s" % (dasd,)) - iutil.execWithCallback("/sbin/dasdfmt", argv + [dasd], - stdout="/dev/tty5", stderr="/dev/tty5", - callback=self._updateProgressWindow, - callback_data=pw, echo=False) - - pw.pop() - else: - for dasd in self._dasdlist: - log.info("Running dasdfmt on %s" % (dasd,)) - iutil.execWithRedirect("/sbin/dasdfmt", argv + [dasd], - stdout="/dev/tty5", stderr="/dev/tty5") + for dasd in self._dasdlist: + bypath = deviceNameToDiskByPath("/dev/" + dasd) + log.info("Running dasdfmt on %s" % (bypath,)) + arglist = argv + [dasd] + + try: + if intf and self.totalCylinders: + rc = iutil.execWithCallback(self.dasdfmt, arglist, + stdout=out, stderr=err, + callback=update, + callback_data=pw, + echo=False) + elif intf: + rc = iutil.execWithPulseProgress(self.dasdfmt, arglist, + stdout=out, stderr=err, + progress=pw) + else: + rc = iutil.execWithRedirect(self.dasdfmt, arglist, + stdout=out, stderr=err) + except Exception as e: + raise DasdFormatError(e, bypath) + + if rc: + raise DasdFormatError("dasdfmt failed: %s" % rc, bypath) + + if intf: + pw.pop() def addDASD(self, dasd): """ Adds a DASDDevice to the internal list of DASDs. """ @@ -185,26 +223,6 @@ class DASD: self._completedCylinders += 1.0 callback_data.set(self._completedCylinders / self.totalCylinders) - @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 - # Create DASD singleton DASD = DASD() diff --git a/storage/errors.py b/storage/errors.py index a0f5f602b..c4d43133f 100644 --- a/storage/errors.py +++ b/storage/errors.py @@ -148,3 +148,6 @@ class UdevError(StorageError): class UnrecognizedFSTabEntryError(StorageError): pass +# dasd +class DasdFormatError(StorageError): + pass |