summaryrefslogtreecommitdiffstats
path: root/storage
diff options
context:
space:
mode:
authorDavid Cantrell <dcantrell@redhat.com>2010-04-28 12:29:39 -1000
committerDavid Cantrell <dcantrell@redhat.com>2010-04-28 12:29:39 -1000
commit7d77daf5542ee07a6887756214c832cd31077963 (patch)
treee2a99617b84647f1964fc00f7e31f6af8db26908 /storage
parentb0771f5d49a22ea8c154421c73d5f7cf21a0bf26 (diff)
downloadanaconda-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__.py2
-rw-r--r--storage/dasd.py110
-rw-r--r--storage/errors.py3
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