From e78c8f1ccf048f2cb6b7ce30abc494dcff4a118a Mon Sep 17 00:00:00 2001
From: David Lehman <dlehman@redhat.com>
Date: Tue, 8 Jan 2013 18:30:39 -0600
Subject: [PATCH 05/11] Remove unused functions and move storage-specific
 utils to storage.

This is the first pass at setting things up to split storage out into
a separate package.

It replaces the guts of iutil.execWithRedirect and iutil.execWithCapture
with a single backend function, _run_program. The main thing I can think
of that might be cause for complaint is that _run_program does not log
each output line as the external program outputs it, so you get the whole
output buffer at once. Storage gets its own copy of _run_program and
all of the calls in storage use the copy from storage.util.

The reason I moved all of the iutil arch functions into storage is that
they are mostly used in storage and I didn't want there to be two copies
of the whole set.

The rest is removing of unused things and moving of things only used by
storage into storage.
---
 anaconda                                |    6 +-
 configure.ac                            |   12 -
 pyanaconda/__init__.py                  |    4 +-
 pyanaconda/anaconda_log.py              |   48 +--
 pyanaconda/image.py                     |   29 +-
 pyanaconda/isys/Makefile.am             |    8 +-
 pyanaconda/isys/__init__.py             |  255 +---------
 pyanaconda/isys/imount.c                |  257 ----------
 pyanaconda/isys/imount.h                |   42 --
 pyanaconda/isys/isys.c                  |  294 +-----------
 pyanaconda/isys/mem.h                   |   11 -
 pyanaconda/iutil.py                     |  819 ++-----------------------------
 pyanaconda/kickstart.py                 |    3 +-
 pyanaconda/network.py                   |    5 +-
 pyanaconda/packaging/__init__.py        |   14 +-
 pyanaconda/packaging/livepayload.py     |    6 +-
 pyanaconda/packaging/yumpayload.py      |   22 +-
 pyanaconda/platform.py                  |   28 +-
 pyanaconda/storage/__init__.py          |   74 ++--
 pyanaconda/storage/arch.py              |  315 ++++++++++++
 pyanaconda/storage/dasd.py              |   24 +-
 pyanaconda/storage/devicelibs/btrfs.py  |   13 +-
 pyanaconda/storage/devicelibs/crypto.py |    1 -
 pyanaconda/storage/devicelibs/dm.py     |   17 +-
 pyanaconda/storage/devicelibs/loop.py   |   12 +-
 pyanaconda/storage/devicelibs/lvm.py    |   18 +-
 pyanaconda/storage/devicelibs/mdraid.py |   20 +-
 pyanaconda/storage/devicelibs/mpath.py  |   16 +-
 pyanaconda/storage/devicelibs/swap.py   |   13 +-
 pyanaconda/storage/devices.py           |   67 +--
 pyanaconda/storage/devicetree.py        |   14 +-
 pyanaconda/storage/fcoe.py              |   32 +-
 pyanaconda/storage/flags.py             |   98 ++++
 pyanaconda/storage/formats/__init__.py  |   12 +-
 pyanaconda/storage/formats/disklabel.py |    9 +-
 pyanaconda/storage/formats/dmraid.py    |    8 +-
 pyanaconda/storage/formats/fs.py        |   90 ++--
 pyanaconda/storage/formats/luks.py      |    2 +-
 pyanaconda/storage/formats/lvmpv.py     |    2 +-
 pyanaconda/storage/formats/mdraid.py    |    7 +-
 pyanaconda/storage/formats/multipath.py |    2 +-
 pyanaconda/storage/formats/swap.py      |    4 +-
 pyanaconda/storage/iscsi.py             |   34 +-
 pyanaconda/storage/partitioning.py      |    3 -
 pyanaconda/storage/storage_log.py       |   46 ++
 pyanaconda/storage/udev.py              |    4 +-
 pyanaconda/storage/util.py              |  272 ++++++++++
 pyanaconda/storage/zfcp.py              |    6 +-
 pyanaconda/timezone.py                  |    3 +-
 tests/pyanaconda_test/network_test.py   |    8 +-
 50 files changed, 1084 insertions(+), 2025 deletions(-)
 delete mode 100644 pyanaconda/isys/imount.c
 delete mode 100644 pyanaconda/isys/imount.h
 create mode 100644 pyanaconda/storage/arch.py
 create mode 100644 pyanaconda/storage/flags.py
 create mode 100644 pyanaconda/storage/storage_log.py
 create mode 100644 pyanaconda/storage/util.py

diff --git a/anaconda b/anaconda
index 032b35d..ca4961d 100755
--- a/anaconda
+++ b/anaconda
@@ -409,13 +409,15 @@ def setupDisplay(anaconda, opts, addon_paths=None):
     from pyanaconda.ui.tui.spokes.askvnc import AskVNCSpoke
     from pykickstart.constants import DISPLAY_MODE_TEXT
     from pyanaconda import network
+    from pyanaconda.storage import arch
+    from pyanaconda.storage import util
 
     graphical_failed = 0
     vncS = vnc.VncServer()          # The vnc Server object.
     vncS.anaconda = anaconda
 
     anaconda.displayMode = opts.display_mode
-    anaconda.isHeadless = opts.isHeadless or iutil.isS390()
+    anaconda.isHeadless = opts.isHeadless or arch.isS390()
 
     if opts.vnc:
         flags.usevnc = 1
@@ -456,7 +458,7 @@ def setupDisplay(anaconda, opts, addon_paths=None):
             vncS.vncconnectport = anaconda.ksdata.vnc.port
 
     # disable VNC over text question when not enough memory is available
-    if iutil.memInstalled() < isys.MIN_GUI_RAM:
+    if util.total_memory() < isys.MIN_GUI_RAM:
         flags.vncquestion = False
 
     # disable VNC question if text mode is requested and this is a ks install
diff --git a/configure.ac b/configure.ac
index e78e00d..f43a012 100644
--- a/configure.ac
+++ b/configure.ac
@@ -49,18 +49,6 @@ AC_CHECK_LIB([audit], [audit_open],
              [AC_SUBST(AUDIT_LIBS, [-laudit])],
              [AC_MSG_FAILURE([*** libaudit not usable.])])
 
-AC_CHECK_LIB([blkid], [blkid_get_cache],
-             [AC_SUBST(BLKID_LIBS, [-lblkid])],
-             [AC_MSG_FAILURE([*** libblkid not usable.])])
-
-AC_CHECK_LIB([ext2fs], [ext2fs_initialize],
-             [AC_SUBST(EXT2FS_LIBS, [-lext2fs])],
-             [AC_MSG_FAILURE([*** libext2fs not usable.])])
-
-AC_CHECK_LIB([iscsi], [libiscsi_get_firmware_network_config],
-             [AC_SUBST(ISCSI_LIBS, [-liscsi])],
-             [AC_MSG_FAILURE([*** libiscsi not usable.])])
-
 AC_CHECK_LIB([z], [zlibVersion],
              [AC_SUBST(ZLIB_LIBS, [-lz])],
              [AC_MSG_FAILURE([*** libz not usable.])])
diff --git a/pyanaconda/__init__.py b/pyanaconda/__init__.py
index 0b88edf..b217547 100644
--- a/pyanaconda/__init__.py
+++ b/pyanaconda/__init__.py
@@ -30,7 +30,7 @@
 
 import os, time, string
 import sys
-import iutil
+from pyanaconda.storage import arch
 import isys
 from constants import ROOT_PATH
 from tempfile import mkstemp
@@ -71,7 +71,7 @@ class Anaconda(object):
         self.rescue = False
         self.rescue_mount = True
         self.rootParts = None
-        self.simpleFilter = not iutil.isS390()
+        self.simpleFilter = not arch.isS390()
         self.stage2 = None
         self._storage = None
         self.updateSrc = None
diff --git a/pyanaconda/anaconda_log.py b/pyanaconda/anaconda_log.py
index 04e4efc..4391927 100644
--- a/pyanaconda/anaconda_log.py
+++ b/pyanaconda/anaconda_log.py
@@ -22,7 +22,6 @@
 #            Michael Fulbright <msf@redhat.com>
 #
 
-import inspect
 import logging
 from logging.handlers import SysLogHandler, SYSLOG_UDP_PORT
 import os
@@ -31,7 +30,7 @@ import sys
 import types
 import warnings
 
-import iutil
+from pyanaconda.storage import arch
 from flags import flags
 
 DEFAULT_TTY_LEVEL = logging.INFO
@@ -48,6 +47,9 @@ STORAGE_LOG_FILE = "/tmp/storage.log"
 PACKAGING_LOG_FILE = "/tmp/packaging.log"
 ANACONDA_SYSLOG_FACILITY = SysLogHandler.LOG_LOCAL1
 
+from threading import Lock
+program_log_lock = Lock()
+
 logLevelMap = {"debug": logging.DEBUG, "info": logging.INFO,
                "warning": logging.WARNING, "error": logging.ERROR,
                "critical": logging.CRITICAL}
@@ -61,46 +63,6 @@ def setHandlersLevel(logger, level):
     map(lambda hdlr: hdlr.setLevel(level),
         filter (lambda hdlr: hasattr(hdlr, "autoSetLevel") and hdlr.autoSetLevel, logger.handlers))
 
-def function_name_and_depth():
-    IGNORED_FUNCS = ["function_name_and_depth",
-                     "log_method_call",
-                     "log_method_return"]
-    stack = inspect.stack()
-
-    for i, frame in enumerate(stack):
-        methodname = frame[3]
-        if methodname not in IGNORED_FUNCS:
-            return (methodname, len(stack) - i)
-
-    return ("unknown function?", 0)
-
-def log_method_call(d, *args, **kwargs):
-    classname = d.__class__.__name__
-    (methodname, depth) = function_name_and_depth()
-    spaces = depth * ' '
-    fmt = "%s%s.%s:"
-    fmt_args = [spaces, classname, methodname]
-
-    for arg in args:
-        fmt += " %s ;"
-        fmt_args.append(arg)
-
-    for k, v in kwargs.items():
-        fmt += " %s: %s ;"
-        if "pass" in k.lower() and v:
-            v = "Skipped"
-        fmt_args.extend([k, v])
-
-    logging.getLogger("storage").debug(fmt % tuple(fmt_args))
-
-def log_method_return(d, retval):
-    classname = d.__class__.__name__
-    (methodname, depth) = function_name_and_depth()
-    spaces = depth * ' '
-    fmt = "%s%s.%s returned %s"
-    fmt_args = (spaces, classname, methodname, retval)
-    logging.getLogger("storage").debug(fmt % fmt_args)
-
 class AnacondaSyslogHandler(SysLogHandler):
     def __init__(self,
                  address=('localhost', SYSLOG_UDP_PORT),
@@ -143,7 +105,7 @@ class AnacondaLog:
             logger.setLevel(logging.DEBUG)
             self.forwardToSyslog(logger)
             # Logging of basic stuff and storage to tty3.
-            if not iutil.isS390() and os.access(MAIN_LOG_TTY, os.W_OK):
+            if not arch.isS390() and os.access(MAIN_LOG_TTY, os.W_OK):
                 self.addFileHandler(MAIN_LOG_TTY, logger,
                                     fmtStr=TTY_FORMAT,
                                     autoLevel=True)
diff --git a/pyanaconda/image.py b/pyanaconda/image.py
index f18057e..6786082 100644
--- a/pyanaconda/image.py
+++ b/pyanaconda/image.py
@@ -17,19 +17,22 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 
-import isys, iutil
+import isys
 import os, os.path, stat, sys
+from pyanaconda.storage import util
 from constants import *
 
 from errors import *
 
+import pyanaconda.storage.arch
+
 import gettext
 _ = lambda x: gettext.ldgettext("anaconda", x)
 
 import logging
 log = logging.getLogger("anaconda")
 
-_arch = iutil.getArch()
+_arch = pyanaconda.storage.arch.getArch()
 
 def findFirstIsoImage(path):
     """
@@ -59,12 +62,12 @@ def findFirstIsoImage(path):
 
         log.debug("mounting %s on /mnt/install/cdimage", what)
         try:
-            isys.mount(what, "/mnt/install/cdimage", fstype="iso9660", readOnly=True)
-        except SystemError:
+            util.mount(what, "/mnt/install/cdimage", fstype="iso9660", options="ro")
+        except OSError:
             continue
 
         if not os.access("/mnt/install/cdimage/.discinfo", os.R_OK):
-            isys.umount("/mnt/install/cdimage", removeDir=False)
+            util.umount("/mnt/install/cdimage")
             continue
 
         log.debug("Reading .discinfo")
@@ -78,14 +81,14 @@ def findFirstIsoImage(path):
         if discArch != arch:
             log.warning("findFirstIsoImage: architectures mismatch: %s, %s" %
                         (discArch, arch))
-            isys.umount("/mnt/install/cdimage", removeDir=False)
+            util.umount("/mnt/install/cdimage")
             continue
 
         # If there's no repodata, there's no point in trying to
         # install from it.
         if not os.access("/mnt/install/cdimage/repodata", os.R_OK):
             log.warning("%s doesn't have repodata, skipping" %(what,))
-            isys.umount("/mnt/install/cdimage", removeDir=False)
+            util.umount("/mnt/install/cdimage")
             continue
 
         # warn user if images appears to be wrong size
@@ -96,7 +99,7 @@ def findFirstIsoImage(path):
                 raise exn
 
         log.info("Found disc at %s" % fn)
-        isys.umount("/mnt/install/cdimage", removeDir=False)
+        util.umount("/mnt/install/cdimage")
         return fn
 
     return None
@@ -149,8 +152,8 @@ def mountImageDirectory(method, storage):
 
         while True:
             try:
-                isys.mount(url, ISO_DIR, options=method.options)
-            except SystemError as e:
+                util.mount(url, ISO_DIR, fstype="nfs", options=method.options)
+            except OSError as e:
                 log.error("couldn't mount ISO source directory: %s" % e)
                 exn = MediaMountError(str(e))
                 if errorHandler.cb(exn) == ERROR_RAISE:
@@ -172,8 +175,8 @@ def mountImage(isodir, tree):
             image = os.path.normpath("%s/%s" % (isodir, image))
 
         try:
-            isys.mount(image, tree, fstype = 'iso9660', readOnly = True)
-        except SystemError:
+            util.mount(image, tree, fstype = 'iso9660', options="ro")
+        except OSError:
             exn = MissingImageError()
             if errorHandler.cb(exn) == ERROR_RAISE:
                 raise exn
@@ -211,7 +214,7 @@ def potentialHdisoSources(devicetree):
 
 def umountImage(tree):
     if os.path.ismount(tree):
-        isys.umount(tree, removeDir=False)
+        util.umount(tree)
 
 def unmountCD(dev):
     if not dev:
diff --git a/pyanaconda/isys/Makefile.am b/pyanaconda/isys/Makefile.am
index 3d521d7..35e9206 100644
--- a/pyanaconda/isys/Makefile.am
+++ b/pyanaconda/isys/Makefile.am
@@ -19,17 +19,17 @@
 
 pkgpyexecdir = $(pyexecdir)/py$(PACKAGE_NAME)
 
-ISYS_SRCS = devices.c imount.c lang.c \
+ISYS_SRCS = devices.c lang.c \
             isofs.c linkdetect.c vio.c ethtool.c eddsupport.c iface.c \
             auditd.c log.c mem.c
 
 dist_noinst_HEADERS = *.h
 
-ISYS_CFLAGS = -DVERSION='"$(PACKAGE_VERSION)"' $(NFS_CFLAGS) \
+ISYS_CFLAGS = -DVERSION='"$(PACKAGE_VERSION)"' \
               $(NETWORKMANAGER_CFLAGS) $(LIBNL_CFLAGS) $(LIBNM_GLIB_CFLAGS) \
               $(SELINUX_CFLAGS)
-ISYS_LIBS   = $(RESOLV_LIBS) $(EXT2FS_LIBS) $(ZLIB_LIBS) \
-              $(DEVMAPPER_LIBS) $(BLKID_LIBS) $(X11_LIBS) $(SELINUX_LIBS) \
+ISYS_LIBS   = $(RESOLV_LIBS) $(ZLIB_LIBS) \
+              $(DEVMAPPER_LIBS) $(X11_LIBS) $(SELINUX_LIBS) \
               $(LIBNL_LIBS) $(LIBNM_GLIB_LIBS)
 
 isysdir     = $(pkgpyexecdir)/isys
diff --git a/pyanaconda/isys/__init__.py b/pyanaconda/isys/__init__.py
index 995ae77..7d73836 100755
--- a/pyanaconda/isys/__init__.py
+++ b/pyanaconda/isys/__init__.py
@@ -37,11 +37,10 @@ import stat
 import posix
 import sys
 from pyanaconda import iutil
-import resource
+from pyanaconda.storage import arch
 import re
 import struct
 import dbus
-import selinux
 
 import logging
 log = logging.getLogger("anaconda")
@@ -72,12 +71,15 @@ NM_DEVICE_TYPE_ETHERNET = 1
 
 DBUS_PROPS_IFACE = "org.freedesktop.DBus.Properties"
 
-mountCount = {}
+if arch.getArch() in ("sparc", "ppc64"):
+    MIN_RAM = 768 * 1024
+    GUI_INSTALL_EXTRA_RAM = 512 * 1024
+else:
+    MIN_RAM = 512 * 1024
+    GUI_INSTALL_EXTRA_RAM = 0
 
-MIN_RAM = _isys.MIN_RAM
-MIN_GUI_RAM = _isys.MIN_GUI_RAM
-GUI_INSTALL_EXTRA_RAM = _isys.GUI_INSTALL_EXTRA_RAM
-EARLY_SWAP_RAM = _isys.EARLY_SWAP_RAM
+MIN_GUI_RAM = MIN_RAM + GUI_INSTALL_EXTRA_RAM
+EARLY_SWAP_RAM = 896 * 1024
 
 ## Get the amount of free space available under a directory path.
 # @param path The directory path to check.
@@ -85,151 +87,9 @@ EARLY_SWAP_RAM = _isys.EARLY_SWAP_RAM
 def pathSpaceAvailable(path):
     return _isys.devSpaceFree(path)
 
-## Mount a filesystem, similar to the mount system call.
-# @param device The device to mount.  If bindMount is True, this should be an
-#               already mounted directory.  Otherwise, it should be a device
-#               name.
-# @param location The path to mount device on.
-# @param fstype The filesystem type on device.  This can be disk filesystems
-#               such as vfat or ext3, or pseudo filesystems such as proc or
-#               selinuxfs.
-# @param readOnly Should this filesystem be mounted readonly?
-# @param bindMount Is this a bind mount?  (see the mount(8) man page)
-# @param remount Are we mounting an already mounted filesystem?
-# @return The return value from the mount system call.
-def mount(device, location, fstype = "ext2", readOnly = False,
-          bindMount = False, remount = False, options = None):
-    flags = None
-    location = os.path.normpath(location)
-    if not options:
-        opts = ["defaults"]
-    else:
-        opts = options.split(",")
-
-    # We don't need to create device nodes for devices that start with '/'
-    # (like '/usbdevfs') and also some special fake devices like 'proc'.
-    # First try to make a device node and if that fails, assume we can
-    # mount without making a device node.  If that still fails, the caller
-    # will have to deal with the exception.
-    # We note whether or not we created a node so we can clean up later.
-
-    if mountCount.has_key(location) and mountCount[location] > 0 and not remount:
-	mountCount[location] = mountCount[location] + 1
-	return
-
-    if readOnly or bindMount or remount:
-        if readOnly:
-            opts.append("ro")
-        if bindMount:
-            opts.append("bind")
-        if remount:
-            opts.append("remount")
-
-    flags = ",".join(opts)
-
-    log.debug("isys.py:mount()- going to mount %s on %s as %s with options %s" %(device, location, fstype, flags))
-    rc = _isys.mount(fstype, device, location, flags)
-
-    if not rc:
-	mountCount[location] = 1
-
-    return rc
-
-## Unmount a filesystem, similar to the umount system call.
-# @param what The directory to be unmounted.  This does not need to be the
-#             absolute path.
-# @param removeDir Should the mount point be removed after being unmounted?
-# @return The return value from the umount system call.
-def umount(what, removeDir = True):
-    what = os.path.normpath(what)
-
-    if not os.path.isdir(what):
-	raise ValueError, "isys.umount() can only umount by mount point"
-
-    if mountCount.has_key(what) and mountCount[what] > 1:
-	mountCount[what] = mountCount[what] - 1
-	return
-
-    log.debug("isys.py:umount()- going to unmount %s, removeDir = %s" % (what, removeDir))
-    rc = _isys.umount(what)
-
-    if removeDir and os.path.isdir(what):
-        try:
-            os.rmdir(what)
-        except:
-            pass
-
-    if not rc and mountCount.has_key(what):
-	del mountCount[what]
-
-    return rc
-
-## Disable swap.
-# @param path The full path of the swap device to disable.
-def swapoff (path):
-    return _isys.swapoff (path)
-
-## Enable swap.
-# @param path The full path of the swap device to enable.
-def swapon (path):
-    return _isys.swapon (path)
-
 def resetResolv():
     return _isys.resetresolv()
 
-def readFSUuid(device):
-    if not os.path.exists(device):
-        device = "/dev/%s" % device
-
-    label = _isys.getblkid(device, "UUID")
-    return label
-
-def readFSLabel(device):
-    if not os.path.exists(device):
-        device = "/dev/%s" % device
-
-    label = _isys.getblkid(device, "LABEL")
-    return label
-
-def readFSType(device):
-    if not os.path.exists(device):
-        device = "/dev/%s" % device
-
-    fstype = _isys.getblkid(device, "TYPE")
-    if fstype is None:
-        # FIXME: libblkid doesn't show physical volumes as having a filesystem
-        # so let's sniff for that.(#409321)
-        try:
-            fd = os.open(device, os.O_RDONLY)
-            buf = os.read(fd, 2048)
-        except:
-            return fstype
-        finally:
-            try:
-                os.close(fd)
-            except:
-                pass
-
-        if buf.startswith("HM"):
-            return "physical volume (LVM)"
-        for sec in range(0, 4):
-            off = (sec * 512) + 24
-            if len(buf) < off:
-                continue
-            if buf[off:].startswith("LVM2"):
-                return "physical volume (LVM)"
-    elif fstype == "lvm2pv":
-        return "physical volume (LVM)"
-    return fstype
-
-def ext2IsDirty(device):
-    label = _isys.e2dirty(device)
-    return label
-
-def ext2HasJournal(device):
-    hasjournal = _isys.e2hasjournal(device)
-    return hasjournal
-
 def modulesWithPaths():
     mods = []
     for modline in open("/proc/modules", "r"):
@@ -240,34 +100,6 @@ def modulesWithPaths():
         mods.extend(modPaths)
     return mods
 
-def driveUsesModule(device, modules):
-    """Returns true if a drive is using a prticular module.  Only works
-       for SCSI devices right now."""
-
-    if not isinstance(modules, ().__class__) and not \
-            isinstance(modules, [].__class__):
-        modules = [modules]
-
-    if device[:2] == "hd":
-        return False
-    rc = False
-    if os.access("/tmp/scsidisks", os.R_OK):
-        sdlist=open("/tmp/scsidisks", "r")
-        sdlines = sdlist.readlines()
-        sdlist.close()
-        for l in sdlines:
-            try:
-                # each line has format of:  <device>  <module>
-                (sddev, sdmod) = string.split(l)
-
-                if sddev == device:
-                    if sdmod in modules:
-                        rc = True
-                        break
-            except:
-                    pass
-    return rc
-
 def isPseudoTTY (fd):
     return _isys.isPseudoTTY (fd)
 
@@ -331,39 +163,6 @@ def getMacAddress(dev):
             raise
     return device_macaddr
 
-# Get a description string for a network device (e.g., eth0)
-def getNetDevDesc(dev):
-    from pyanaconda.baseudev import udev_get_device
-    desc = "Network Interface"
-
-    if dev == '' or dev is None:
-        return desc
-
-    bus = dbus.SystemBus()
-    nm = bus.get_object(NM_SERVICE, NM_MANAGER_PATH)
-    devlist = nm.get_dbus_method("GetDevices")()
-
-    for path in devlist:
-        device = bus.get_object(NM_SERVICE, path)
-        device_iface = dbus.Interface(device, DBUS_PROPS_IFACE)
-        device_props = device_iface.get_dbus_method("GetAll")(NM_DEVICE_IFACE)
-
-        if dev == device_props['Interface']:
-            # This is the sysfs path (for now).
-            udev_path = device_props['Udi']
-            dev = udev_get_device(udev_path[4:])
-
-            if dev is None:
-                log.debug("weird, we have a None dev with path %s" % path)
-            elif dev.has_key("ID_VENDOR_ENC") and dev.has_key("ID_MODEL_ENC"):
-                desc = "%s %s" % (dev["ID_VENDOR_ENC"], dev["ID_MODEL_ENC"])
-            elif dev.has_key("ID_VENDOR_FROM_DATABASE") and dev.has_key("ID_MODEL_FROM_DATABASE"):
-                desc = "%s %s" % (dev["ID_VENDOR_FROM_DATABASE"], dev["ID_MODEL_FROM_DATABASE"])
-
-            return desc
-
-    return desc
-
 # Determine if a network device is a wireless device.
 def isWirelessDevice(dev_name):
     bus = dbus.SystemBus()
@@ -435,40 +234,6 @@ def getIPAddresses(dev, version=4):
 
     return addresses
 
-## Get the correct context for a file from loaded policy.
-# @param fn The filename to query.
-def matchPathContext(fn):
-    con = None
-    try:
-        con = selinux.matchpathcon(os.path.normpath(fn), 0)[1]
-    except OSError as e:
-        log.info("failed to get default SELinux context for %s: %s" % (fn, e))
-    return con
-
-## Set the SELinux file context of a file
-# @param fn The filename to fix.
-# @param con The context to use.
-# @param instroot An optional root filesystem to look under for fn.
-def setFileContext(fn, con, instroot = '/'):
-    full_path = os.path.normpath("%s/%s" % (instroot, fn))
-    rc = False
-    if con is not None and os.access(full_path, os.F_OK):
-        try:
-            rc = (selinux.lsetfilecon(full_path, con) == 0)
-        except OSError as e:
-            log.info("failed to set SELinux context for %s: %s" % (full_path, e))
-    return rc
-
-## Restore the SELinux file context of a file to its default.
-# @param fn The filename to fix.
-# @param instroot An optional root filesystem to look under for fn.
-def resetFileContext(fn, instroot = '/'):
-    con = matchPathContext(fn)
-    if con:
-        if setFileContext(fn, con, instroot):
-            return con
-    return None
-
 def prefix2netmask(prefix):
     return _isys.prefix2netmask(prefix)
 
@@ -490,7 +255,7 @@ def isPaeAvailable():
         return isPAE
 
     isPAE = False
-    if not iutil.isX86():
+    if not arch.isX86():
         return isPAE
 
     f = open("/proc/cpuinfo", "r")
diff --git a/pyanaconda/isys/imount.c b/pyanaconda/isys/imount.c
deleted file mode 100644
index 146a00b..0000000
--- a/pyanaconda/isys/imount.c
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- * imount.c
- *
- * Copyright (C) 2007, 2008, 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/>.
- */
-
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/mount.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-#include <glib.h>
-
-#include "imount.h"
-#include "log.h"
-
-#define _(foo) foo
-
-static int readFD(int fd, char **buf) {
-    char *p;
-    size_t size = 4096;
-    int s, filesize = 0;
-
-    *buf = calloc(4096, sizeof (char));
-    if (*buf == NULL)
-        abort();
-
-    do {
-        p = &(*buf)[filesize];
-        s = read(fd, p, 4096);
-        if (s < 0)
-            break;
-
-        filesize += s;
-        if (s == 0)
-           break;
-
-        size += s;
-        *buf = realloc(*buf, size);
-        if (*buf == NULL)
-            abort();
-    } while (1);
-
-    if (filesize == 0 && s < 0) {
-        free(*buf);
-        *buf = NULL;
-        return -1;
-    }
-
-    return filesize;
-}
-
-static size_t rstrip(char *str) {
-    size_t len = strlen(str);
-    if (len > 0 && str[len-1] == '\n') {
-        str[len-1] = '\0';
-        --len;
-    }
-    return len;
-}
-
-int mountCommandWrapper(int mode, char *dev, char *where, char *fs,
-                        char *options, char **err) {
-    int rc, child, status;
-    int stdout_pipe[2], stderr_pipe[2];
-    char *opts = NULL, *device = NULL, *cmd = NULL;
-
-    switch (mode) {
-    case IMOUNT_MODE_MOUNT:
-    case IMOUNT_MODE_BIND:
-        cmd = "/bin/mount";
-        if (g_mkdir_with_parents(where, 0755))
-            return IMOUNT_ERR_ERRNO;
-        break;
-    case IMOUNT_MODE_UMOUNT:
-        cmd = "/bin/umount";
-        break;
-    default:
-        return IMOUNT_ERR_MODE;
-    }
-
-    if (mode == IMOUNT_MODE_MOUNT) {
-        if (strstr(fs, "nfs")) {
-            if (options && strlen(options)) { // do not append if the options are empty
-                if (asprintf(&opts, "%s,nolock", options) == -1) {
-                    fprintf(stderr, "%s: %d: %s\n", __func__, __LINE__,
-                            strerror(errno));
-                    fflush(stderr);
-                    abort();
-                }
-            } else {
-                opts = strdup("nolock");
-            }
-
-            device = strdup(dev);
-        } else {
-            if ((options && strstr(options, "bind") == NULL) &&
-                strncmp(dev, "LABEL=", 6) && strncmp(dev, "UUID=", 5) &&
-                *dev != '/') {
-               if (asprintf(&device, "/dev/%s", dev) == -1) {
-                   fprintf(stderr, "%s: %d: %s\n", __func__, __LINE__,
-                           strerror(errno));
-                   fflush(stderr);
-                   abort();
-               }
-            } else {
-               device = strdup(dev);
-            }
-
-            if (options)
-                opts = strdup(options);
-        }
-    }
-
-    if (pipe(stdout_pipe))
-        return IMOUNT_ERR_ERRNO;
-    if (pipe(stderr_pipe))
-        return IMOUNT_ERR_ERRNO;
-
-    if (!(child = fork())) {
-        int tty_fd;
-
-        close(stdout_pipe[0]);
-        close(stderr_pipe[0]);
-
-        /* Pull stdin from /dev/tty5 and redirect stdout and stderr to the pipes
-         *  so we can log the output and put error messages into exceptions.
-         *  We'll only use these messages should mount also return an error
-         *  code.
-         */
-        tty_fd = open("/dev/tty5", O_RDONLY);
-        close(STDIN_FILENO);
-        dup2(tty_fd, STDIN_FILENO);
-        close(tty_fd);
-
-        close(STDOUT_FILENO);
-        dup2(stdout_pipe[1], STDOUT_FILENO);
-        close(STDERR_FILENO);
-        dup2(stderr_pipe[1], STDERR_FILENO);
-
-        if (mode == IMOUNT_MODE_MOUNT) {
-            if (opts) {
-                logProgramMessage(INFO, "Running... %s -n -t %s -o %s %s %s",
-                        cmd, fs, opts, device, where);
-                rc = execl(cmd, cmd,
-                           "-n", "-t", fs, "-o", opts, device, where, NULL);
-                exit(1);
-            } else {
-                logProgramMessage(INFO, "Running... %s -n -t %s %s %s",
-                        cmd, fs, device, where);
-                rc = execl(cmd, cmd, "-n", "-t", fs, device, where, NULL);
-                exit(1);
-            }
-        } else if (mode == IMOUNT_MODE_BIND) {
-            logProgramMessage(INFO, "Running... %s --bind %s %s",
-                              cmd, dev, where);
-            rc = execl(cmd, cmd, "--bind", dev, where, NULL);
-            exit(1);
-        } else if (mode == IMOUNT_MODE_UMOUNT) {
-            logProgramMessage(INFO, "Running... %s %s", cmd, where);
-            rc = execl(cmd, cmd, where, NULL);
-            exit(1);
-        } else {
-            logProgramMessage(ERROR, "Running... Unknown imount mode: %d\n", mode);
-            exit(1);
-        }
-    }
-
-    close(stdout_pipe[1]);
-    close(stderr_pipe[1]);
-
-    char *buffer = NULL;
-    /* In case when when the stderr pipe gets enough data to fill the kernel
-     * buffer we might see a deadlock as this will block the mount program on
-     * its next write(). The buffer size is 65kB though so we should be safe.
-     */
-    rc = readFD(stdout_pipe[0], &buffer);
-    if (rc > 0) {
-        rstrip(buffer);
-        logProgramMessage(INFO, buffer);
-        free(buffer);
-        buffer = NULL;
-    }
-    rc = readFD(stderr_pipe[0], &buffer);
-    if (rc > 0) {
-        rstrip(buffer);
-        logProgramMessage(ERROR, buffer);
-        if (err != NULL)
-            *err = buffer;
-        else
-            free(buffer);
-    }
-
-    waitpid(child, &status, 0);
-    close(stdout_pipe[0]);
-    close(stderr_pipe[0]);
-
-    if (opts) {
-        free(opts);
-    }
-
-    if (device) {
-        free(device);
-    }
-
-    if (!WIFEXITED(status))
-        return IMOUNT_ERR_OTHER;
-    else if ( (rc = WEXITSTATUS(status)) )
-        return rc;
-
-    return 0;
-}
-
-int doBindMount(char* path, char *where, char **err) {
-    return mountCommandWrapper(IMOUNT_MODE_BIND,
-                               path, where, NULL, NULL, err);
-}
-
-int doPwMount(char *dev, char *where, char *fs, char *options, char **err) {
-    return mountCommandWrapper(IMOUNT_MODE_MOUNT,
-                               dev, where, fs, options, err);
-}
-
-int doPwUmount(char *where, char **err) {
-    return mountCommandWrapper(IMOUNT_MODE_UMOUNT,
-                               NULL, where, NULL, NULL, err);
-}
-
-/* Returns true iff it is possible that the mount command that have returned
- * 'errno' might succeed at a later time (think e.g. not yet initialized USB
- * device, etc.) */
-int mountMightSucceedLater(int mountRc)
-{
-    /* 32 is the mount exit code for "mount failure" */
-    if (mountRc > 0 && mountRc & 0x20)
-        return 1;
-    else
-        return 0;
-}
diff --git a/pyanaconda/isys/imount.h b/pyanaconda/isys/imount.h
deleted file mode 100644
index 0af238d..0000000
--- a/pyanaconda/isys/imount.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * imount.h
- *
- * Copyright (C) 2007, 2008, 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/>.
- */
-
-#ifndef H_IMOUNT
-#define H_IMOUNT
-
-#define IMOUNT_ERR_ERRNO          -1
-#define IMOUNT_ERR_OTHER          -2
-#define IMOUNT_ERR_MODE           -3
-
-#include <sys/mount.h>		/* for umount() */
-
-#define IMOUNT_RDONLY  1
-#define IMOUNT_BIND    2
-#define IMOUNT_REMOUNT 4
-
-#define IMOUNT_MODE_MOUNT  1
-#define IMOUNT_MODE_UMOUNT 2
-#define IMOUNT_MODE_BIND   3
-
-int doBindMount(char* path, char *where, char **err);
-int doPwMount(char *dev, char *where, char *fs, char *options, char **err);
-int doPwUmount(char *where, char **err);
-int mountMightSucceedLater(int mountRc);
-
-#endif
diff --git a/pyanaconda/isys/isys.c b/pyanaconda/isys/isys.c
index c3f2183..7597f85 100644
--- a/pyanaconda/isys/isys.c
+++ b/pyanaconda/isys/isys.c
@@ -24,7 +24,6 @@
 #include <errno.h>
 #define u32 __u32
 #include <fcntl.h>
-#include <ext2fs/ext2fs.h>
 /* Need to tell loop.h what the actual dev_t type is. */
 #undef dev_t
 #if defined(__alpha) || (defined(__sparc__) && defined(__arch64__))
@@ -47,8 +46,6 @@
 #include <sys/vfs.h>
 #include <unistd.h>
 #include <resolv.h>
-#include <scsi/scsi.h>
-#include <scsi/scsi_ioctl.h>
 #include <sys/vt.h>
 #include <sys/types.h>
 #include <sys/socket.h>
@@ -58,25 +55,19 @@
 #include <libgen.h>
 #include <linux/cdrom.h>
 #include <linux/major.h>
-#include <linux/raid/md_u.h>
-#include <linux/raid/md_p.h>
 #include <signal.h>
 #include <execinfo.h>
 
-#include <blkid/blkid.h>
-
 #include <X11/Xlib.h>
 #include <X11/XKBlib.h>
 #include <X11/keysym.h>
 
 #include "iface.h"
 #include "isys.h"
-#include "imount.h"
 #include "ethtool.h"
 #include "lang.h"
 #include "eddsupport.h"
 #include "auditd.h"
-#include "imount.h"
 #include "log.h"
 #include "mem.h"
 
@@ -84,16 +75,7 @@
 #define CDROMEJECT 0x5309
 #endif
 
-static PyObject * doMount(PyObject * s, PyObject * args);
-static PyObject * doUMount(PyObject * s, PyObject * args);
-static PyObject * doSwapon(PyObject * s, PyObject * args);
-static PyObject * doSwapoff(PyObject * s, PyObject * args);
-static PyObject * doWipeRaidSuperblock(PyObject * s, PyObject * args);
-static PyObject * doGetRaidChunkSize(PyObject * s, PyObject * args);
 static PyObject * doDevSpaceFree(PyObject * s, PyObject * args);
-static PyObject * doExt2Dirty(PyObject * s, PyObject * args);
-static PyObject * doExt2HasJournal(PyObject * s, PyObject * args);
-static PyObject * doEjectCdrom(PyObject * s, PyObject * args);
 static PyObject * doisPseudoTTY(PyObject * s, PyObject * args);
 static PyObject * doisVioConsole(PyObject * s);
 static PyObject * doSync(PyObject * s, PyObject * args);
@@ -103,7 +85,6 @@ static PyObject * py_bind_textdomain_codeset(PyObject * o, PyObject * args);
 static PyObject * doSegvHandler(PyObject *s, PyObject *args);
 static PyObject * doAuditDaemon(PyObject *s);
 static PyObject * doPrefixToNetmask(PyObject *s, PyObject *args);
-static PyObject * doGetBlkidData(PyObject * s, PyObject * args);
 static PyObject * doIsCapsLockEnabled(PyObject * s, PyObject * args);
 static PyObject * doGetLinkStatus(PyObject * s, PyObject * args);
 static PyObject * doGetAnacondaVersion(PyObject * s, PyObject * args);
@@ -111,16 +92,7 @@ static PyObject * doInitLog(PyObject * s);
 static PyObject * doTotalMemory(PyObject * s);
 
 static PyMethodDef isysModuleMethods[] = {
-    { "ejectcdrom", (PyCFunction) doEjectCdrom, METH_VARARGS, NULL },
-    { "e2dirty", (PyCFunction) doExt2Dirty, METH_VARARGS, NULL },
-    { "e2hasjournal", (PyCFunction) doExt2HasJournal, METH_VARARGS, NULL },
     { "devSpaceFree", (PyCFunction) doDevSpaceFree, METH_VARARGS, NULL },
-    { "wiperaidsb", (PyCFunction) doWipeRaidSuperblock, METH_VARARGS, NULL },
-    { "getraidchunk", (PyCFunction) doGetRaidChunkSize, METH_VARARGS, NULL },
-    { "mount", (PyCFunction) doMount, METH_VARARGS, NULL },
-    { "umount", (PyCFunction) doUMount, METH_VARARGS, NULL },
-    { "swapon",  (PyCFunction) doSwapon, METH_VARARGS, NULL },
-    { "swapoff",  (PyCFunction) doSwapoff, METH_VARARGS, NULL },
     { "isPseudoTTY", (PyCFunction) doisPseudoTTY, METH_VARARGS, NULL},
     { "isVioConsole", (PyCFunction) doisVioConsole, METH_NOARGS, NULL},
     { "sync", (PyCFunction) doSync, METH_VARARGS, NULL},
@@ -130,7 +102,6 @@ static PyMethodDef isysModuleMethods[] = {
     { "handleSegv", (PyCFunction) doSegvHandler, METH_VARARGS, NULL },
     { "auditdaemon", (PyCFunction) doAuditDaemon, METH_NOARGS, NULL },
     { "prefix2netmask", (PyCFunction) doPrefixToNetmask, METH_VARARGS, NULL },
-    { "getblkid", (PyCFunction) doGetBlkidData, METH_VARARGS, NULL },
     { "isCapsLockEnabled", (PyCFunction) doIsCapsLockEnabled, METH_VARARGS, NULL },
     { "getLinkStatus", (PyCFunction) doGetLinkStatus, METH_VARARGS, NULL },
     { "getAnacondaVersion", (PyCFunction) doGetAnacondaVersion, METH_VARARGS, NULL },
@@ -139,121 +110,11 @@ static PyMethodDef isysModuleMethods[] = {
     { NULL, NULL, 0, NULL }
 } ;
 
-static PyObject * doUMount(PyObject * s, PyObject * args) {
-    char *err = NULL, *mntpoint = NULL;
-    int rc;
-
-    if (!PyArg_ParseTuple(args, "s", &mntpoint)) {
-        return NULL;
-    }
-
-    Py_BEGIN_ALLOW_THREADS
-    rc = doPwUmount(mntpoint, &err);
-    Py_END_ALLOW_THREADS
-
-    if (rc == IMOUNT_ERR_ERRNO) {
-        PyErr_SetFromErrno(PyExc_SystemError);
-    } else if (rc) {
-        PyObject *tuple = PyTuple_New(2);
-
-        PyTuple_SetItem(tuple, 0, PyInt_FromLong(rc));
-
-        if (err == NULL) {
-            Py_INCREF(Py_None);
-            PyTuple_SetItem(tuple, 1, Py_None);
-        } else {
-            PyTuple_SetItem(tuple, 1, PyString_FromString(err));
-        }
-
-        PyErr_SetObject(PyExc_SystemError, tuple);
-    }
-
-    if (rc) {
-        return NULL;
-    }
-
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-static PyObject * doMount(PyObject * s, PyObject * args) {
-    char *err = NULL, *fs, *device, *mntpoint, *flags = NULL;
-    int rc;
-
-    if (!PyArg_ParseTuple(args, "sss|z", &fs, &device, &mntpoint,
-			  &flags)) return NULL;
-
-    Py_BEGIN_ALLOW_THREADS
-    rc = doPwMount(device, mntpoint, fs, flags, &err);
-    Py_END_ALLOW_THREADS
-
-    if (rc == IMOUNT_ERR_ERRNO)
-	PyErr_SetFromErrno(PyExc_SystemError);
-    else if (rc) {
-        PyObject *tuple = PyTuple_New(2);
-
-        PyTuple_SetItem(tuple, 0, PyInt_FromLong(rc));
-
-        if (err == NULL) {
-            Py_INCREF(Py_None);
-            PyTuple_SetItem(tuple, 1, Py_None);
-        } else {
-            PyTuple_SetItem(tuple, 1, PyString_FromString(err));
-        }
-
-        PyErr_SetObject(PyExc_SystemError, tuple);
-    }
-
-    if (rc) return NULL;
-
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
 #define BOOT_SIGNATURE	0xaa55	/* boot signature */
 #define BOOT_SIG_OFFSET	510	/* boot signature offset */
 
-int swapoff(const char * path);
-int swapon(const char * path, int priorty);
-
-static PyObject * doSwapoff (PyObject * s, PyObject * args) {
-    char * path;
-
-    if (!PyArg_ParseTuple(args, "s", &path)) return NULL;
-
-    if (swapoff (path)) {
-	PyErr_SetFromErrno(PyExc_SystemError);
-	return NULL;
-    }
-    
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-static PyObject * doSwapon (PyObject * s, PyObject * args) {
-    char * path;
-
-    if (!PyArg_ParseTuple(args, "s", &path)) return NULL;
-
-    if (swapon (path, 0)) {
-	PyErr_SetFromErrno(PyExc_SystemError);
-	return NULL;
-    }
-    
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
 void init_isys(void) {
-    PyObject * m, * d;
-
-    m = Py_InitModule("_isys", isysModuleMethods);
-    d = PyModule_GetDict(m);
-
-    PyDict_SetItemString(d, "MIN_RAM", PyInt_FromLong(MIN_RAM));
-    PyDict_SetItemString(d, "MIN_GUI_RAM", PyInt_FromLong(MIN_GUI_RAM));
-    PyDict_SetItemString(d, "GUI_INSTALL_EXTRA_RAM", PyInt_FromLong(GUI_INSTALL_EXTRA_RAM));
-    PyDict_SetItemString(d, "EARLY_SWAP_RAM", PyInt_FromLong(EARLY_SWAP_RAM));
+    Py_InitModule("_isys", isysModuleMethods);
 }
 
 static PyObject * doPrefixToNetmask (PyObject * s, PyObject * args) {
@@ -273,70 +134,6 @@ static PyObject * doPrefixToNetmask (PyObject * s, PyObject * args) {
     return Py_BuildValue("s", dst);
 }
 
-static PyObject * doWipeRaidSuperblock(PyObject * s, PyObject * args) {
-    int fd;
-    unsigned long size;
-    struct mdp_super_t * sb;
-
-    if (!PyArg_ParseTuple(args, "i", &fd)) return NULL;
-
-    if (ioctl(fd, BLKGETSIZE, &size)) {
-	PyErr_SetFromErrno(PyExc_SystemError);
-	return NULL;
-    }
-
-    /* put the size in 1k blocks */
-    size >>= 1;
-
-    if (lseek64(fd, ((off64_t) 512) * (off64_t) MD_NEW_SIZE_SECTORS(size), SEEK_SET) < 0) {
-	PyErr_SetFromErrno(PyExc_SystemError);
-	return NULL;
-    } 
-
-    sb = malloc(sizeof(mdp_super_t));
-    sb = memset(sb, '\0', sizeof(mdp_super_t));
-
-    if (write(fd, sb, sizeof(sb)) != sizeof(sb)) {
-	PyErr_SetFromErrno(PyExc_SystemError);
-	return NULL;
-    }
-
-    return Py_None;
-}
-
-static PyObject * doGetRaidChunkSize(PyObject * s, PyObject * args) {
-    int fd;
-    unsigned long size;
-    mdp_super_t sb;
-
-    if (!PyArg_ParseTuple(args, "i", &fd)) return NULL;
-
-    if (ioctl(fd, BLKGETSIZE, &size)) {
-	PyErr_SetFromErrno(PyExc_SystemError);
-	return NULL;
-    }
-
-    /* put the size in 1k blocks */
-    size >>= 1;
-
-    if (lseek64(fd, ((off64_t) 512) * (off64_t) MD_NEW_SIZE_SECTORS(size), SEEK_SET) < 0) {
-	PyErr_SetFromErrno(PyExc_SystemError);
-	return NULL;
-    } 
-
-    if (read(fd, &sb, sizeof(sb)) != sizeof(sb)) {
-	PyErr_SetFromErrno(PyExc_SystemError);
-	return NULL;
-    }
-
-    if (sb.md_magic != MD_SB_MAGIC) {
-	PyErr_SetString(PyExc_ValueError, "bad md magic on device");
-	return NULL;
-    }
-
-    return Py_BuildValue("i", sb.chunk_size / 1024);
-}
-
 static int get_bits(unsigned long long v) {
     int  b = 0;
     
@@ -371,67 +168,6 @@ static PyObject * doDevSpaceFree(PyObject * s, PyObject * args) {
     return PyLong_FromUnsignedLongLong(size>>20);
 }
 
-static PyObject * doExt2Dirty(PyObject * s, PyObject * args) {
-    char * device;
-    ext2_filsys fsys;
-    int rc;
-    int clean;
-
-    if (!PyArg_ParseTuple(args, "s", &device)) return NULL;
-
-    rc = ext2fs_open(device, EXT2_FLAG_FORCE, 0, 0, unix_io_manager,
-		     &fsys);
-    if (rc) {
-	Py_INCREF(Py_None);
-	return Py_None;
-    }
-
-    clean = fsys->super->s_state & EXT2_VALID_FS;
-
-    ext2fs_close(fsys);
-
-    return Py_BuildValue("i", !clean); 
-}
-static PyObject * doExt2HasJournal(PyObject * s, PyObject * args) {
-    char * device;
-    ext2_filsys fsys;
-    int rc;
-    int hasjournal;
-
-    if (!PyArg_ParseTuple(args, "s", &device)) return NULL;
-    rc = ext2fs_open(device, EXT2_FLAG_FORCE, 0, 0, unix_io_manager,
-		     &fsys);
-    if (rc) {
-	Py_INCREF(Py_None);
-	return Py_None;
-    }
-
-    hasjournal = fsys->super->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL;
-
-    ext2fs_close(fsys);
-
-    return Py_BuildValue("i", hasjournal); 
-}
-
-static PyObject * doEjectCdrom(PyObject * s, PyObject * args) {
-    int fd;
-
-    if (!PyArg_ParseTuple(args, "i", &fd)) return NULL;
-
-    /* Ask it to unlock the door and then eject the disc. There's really
-     * nothing to do if unlocking doesn't work, so just eject without
-     * worrying about it. -- pjones
-     */
-    ioctl(fd, CDROM_LOCKDOOR, 0);
-    if (ioctl(fd, CDROMEJECT, 1)) {
-	PyErr_SetFromErrno(PyExc_SystemError);
-	return NULL;
-    }
-
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
 static PyObject * doisPseudoTTY(PyObject * s, PyObject * args) {
     int fd;
     struct stat sb;
@@ -524,34 +260,6 @@ static PyObject * doAuditDaemon(PyObject *s) {
     return Py_None;
 }
 
-static PyObject * doGetBlkidData(PyObject * s, PyObject * args) {
-    char * dev, * key;
-    blkid_cache cache;
-    blkid_dev bdev = NULL;
-    blkid_tag_iterate titer;
-    const char * type, * data;
-
-    if (!PyArg_ParseTuple(args, "ss", &dev, &key)) return NULL;
-
-    blkid_get_cache(&cache, NULL);
-
-    bdev = blkid_get_dev(cache, dev, BLKID_DEV_NORMAL);
-    if (bdev == NULL)
-        goto out;
-    titer = blkid_tag_iterate_begin(bdev);
-    while (blkid_tag_next(titer, &type, &data) >= 0) {
-        if (!strcmp(type, key)) {
-            blkid_tag_iterate_end(titer);
-            return Py_BuildValue("s", data);
-        }
-    }
-    blkid_tag_iterate_end(titer);
-
- out:
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
 static PyObject * doIsCapsLockEnabled(PyObject * s, PyObject * args) {
     Display *d = NULL;
     XkbStateRec state;
diff --git a/pyanaconda/isys/mem.h b/pyanaconda/isys/mem.h
index 092999e..9a5eaa3 100644
--- a/pyanaconda/isys/mem.h
+++ b/pyanaconda/isys/mem.h
@@ -25,17 +25,6 @@
 
 #include <glib.h>
 
-/* The *_RAM sizes are all in KB */
-#if defined(__powerpc64__) || defined(__sparc__)
-  #define MIN_RAM                 768*1024
-  #define GUI_INSTALL_EXTRA_RAM   512*1024
-#else
-  #define MIN_RAM                 512 * 1024
-  #define GUI_INSTALL_EXTRA_RAM   0 * 1024
-#endif
-#define MIN_GUI_RAM             MIN_RAM + GUI_INSTALL_EXTRA_RAM
-#define EARLY_SWAP_RAM          896 * 1024
-
 #define MEMINFO "/proc/meminfo"
 
 guint64 totalMemory(void);
diff --git a/pyanaconda/iutil.py b/pyanaconda/iutil.py
index 69355ab..66024c5 100644
--- a/pyanaconda/iutil.py
+++ b/pyanaconda/iutil.py
@@ -40,40 +40,7 @@ import logging
 log = logging.getLogger("anaconda")
 program_log = logging.getLogger("program")
 
-class ExecProduct(object):
-    def __init__(self, rc, stdout, stderr):
-        self.rc = rc
-        self.stdout = stdout
-        self.stderr = stderr
-
-#Python reimplementation of the shell tee process, so we can
-#feed the pipe output into two places at the same time
-class tee(threading.Thread):
-    def __init__(self, inputdesc, outputdesc, logmethod, command):
-        threading.Thread.__init__(self)
-        self.inputdesc = os.fdopen(inputdesc, "r")
-        self.outputdesc = outputdesc
-        self.logmethod = logmethod
-        self.running = True
-        self.command = command
-
-    def run(self):
-        while self.running:
-            try:
-                data = self.inputdesc.readline()
-            except IOError:
-                self.logmethod("Can't read from pipe during a call to %s. "
-                               "(program terminated suddenly?)" % self.command)
-                break
-            if data == "":
-                self.running = False
-            else:
-                self.logmethod(data.rstrip('\n'))
-                os.write(self.outputdesc, data)
-
-    def stop(self):
-        self.running = False
-        return self
+from anaconda_log import program_log_lock
 
 def augmentEnv():
     env = os.environ.copy()
@@ -82,6 +49,41 @@ def augmentEnv():
                })
     return env
 
+def _run_program(argv, root='/', stdin=None, env_prune=None):
+    if env_prune is None:
+        env_prune = []
+
+    def chroot():
+        if root and root != '/':
+            os.chroot(root)
+
+    with program_log_lock:
+        program_log.info("Running... %s" % " ".join(argv))
+
+        env = augmentEnv()
+        for var in env_prune:
+            env.pop(var, None)
+
+        try:
+            proc = subprocess.Popen(argv,
+                                    stdin=stdin,
+                                    stdout=subprocess.PIPE,
+                                    stderr=subprocess.STDOUT,
+                                    preexec_fn=chroot, cwd=root, env=env)
+
+            out = proc.communicate()[0]
+            if out:
+                for line in out.splitlines():
+                    program_log.info(line)
+
+        except OSError as e:
+            program_log.error("Error running %s: %s" % (argv[0], e.strerror))
+            raise
+
+        program_log.debug("Return code: %d" % proc.returncode)
+
+    return (proc.returncode, out)
+
 ## Run an external program and redirect the output to a file.
 # @param command The command to run.
 # @param argv A list of arguments.
@@ -97,102 +99,8 @@ def execWithRedirect(command, argv, stdin = None, stdout = None,
                    % (command, " ".join(argv)))
         return 0
 
-    def chroot ():
-        os.chroot(root)
-
-    stdinclose = stdoutclose = stderrclose = lambda : None
-
-    argv = list(argv)
-    if isinstance(stdin, str):
-        if os.access(stdin, os.R_OK):
-            stdin = os.open(stdin, os.O_RDONLY)
-            stdinclose = lambda : os.close(stdin)
-        else:
-            stdin = sys.stdin.fileno()
-    elif isinstance(stdin, int):
-        pass
-    elif stdin is None or not isinstance(stdin, file):
-        stdin = sys.stdin.fileno()
-
-    orig_stdout = stdout
-    if isinstance(stdout, str):
-        stdout = os.open(stdout, os.O_RDWR|os.O_CREAT)
-        stdoutclose = lambda : os.close(stdout)
-    elif isinstance(stdout, int):
-        pass
-    elif stdout is None or not isinstance(stdout, file):
-        stdout = sys.stdout.fileno()
-
-    if isinstance(stderr, str) and isinstance(orig_stdout, str) and stderr == orig_stdout:
-        stderr = stdout
-    elif isinstance(stderr, str):
-        stderr = os.open(stderr, os.O_RDWR|os.O_CREAT)
-        stderrclose = lambda : os.close(stderr)
-    elif isinstance(stderr, int):
-        pass
-    elif stderr is None or not isinstance(stderr, file):
-        stderr = sys.stderr.fileno()
-
-    program_log.info("Running... %s" % (" ".join([command] + argv),))
-
-    #prepare os pipes for feeding tee proceses
-    pstdout, pstdin = os.pipe()
-    perrout, perrin = os.pipe()
-
-    env = augmentEnv()
-
-    for var in env_prune:
-        if env.has_key(var):
-            del env[var]
-
-    try:
-        #prepare tee proceses
-        proc_std = tee(pstdout, stdout, program_log.info, command)
-        proc_err = tee(perrout, stderr, program_log.error, command)
-
-        #start monitoring the outputs
-        proc_std.start()
-        proc_err.start()
-
-        proc = subprocess.Popen([command] + argv, stdin=stdin,
-                                stdout=pstdin,
-                                stderr=perrin,
-                                preexec_fn=chroot, cwd=root,
-                                env=env)
-
-        proc.wait()
-        ret = proc.returncode
-
-        #close the input ends of pipes so we get EOF in the tee processes
-        os.close(pstdin)
-        os.close(perrin)
-
-        #wait for the output to be written and destroy them
-        proc_std.join()
-        del proc_std
-
-        proc_err.join()
-        del proc_err
-
-        stdinclose()
-        stdoutclose()
-        stderrclose()
-    except OSError as e:
-        errstr = "Error running %s: %s" % (command, e.strerror)
-        log.error(errstr)
-        program_log.error(errstr)
-        #close the input ends of pipes so we get EOF in the tee processes
-        os.close(pstdin)
-        os.close(perrin)
-        proc_std.join()
-        proc_err.join()
-
-        stdinclose()
-        stdoutclose()
-        stderrclose()
-        raise RuntimeError, errstr
-
-    return ret
+    argv = [command] + argv
+    return _run_program(argv, stdin=stdin, root=root, env_prune=env_prune)[0]
 
 ## Run an external program and capture standard out.
 # @param command The command to run.
@@ -209,208 +117,8 @@ def execWithCapture(command, argv, stdin = None, stderr = None, root='/',
                     % (command, " ".join(argv)))
         return ""
 
-    def chroot():
-        if root is not None:
-            os.chroot(root)
-
-    def closefds ():
-        stdinclose()
-        stderrclose()
-
-    stdinclose = stderrclose = lambda : None
-    rc = ""
-    argv = list(argv)
-
-    if isinstance(stdin, str):
-        if os.access(stdin, os.R_OK):
-            stdin = os.open(stdin, os.O_RDONLY)
-            stdinclose = lambda : os.close(stdin)
-        else:
-            stdin = sys.stdin.fileno()
-    elif isinstance(stdin, int):
-        pass
-    elif stdin is None or not isinstance(stdin, file):
-        stdin = sys.stdin.fileno()
-
-    if isinstance(stderr, str):
-        stderr = os.open(stderr, os.O_RDWR|os.O_CREAT)
-        stderrclose = lambda : os.close(stderr)
-    elif isinstance(stderr, int):
-        pass
-    elif stderr is None or not isinstance(stderr, file):
-        stderr = sys.stderr.fileno()
-
-    program_log.info("Running... %s" % (" ".join([command] + argv),))
-
-    try:
-        proc = subprocess.Popen([command] + argv, stdin=stdin,
-                                stdout=subprocess.PIPE,
-                                stderr=subprocess.PIPE,
-                                preexec_fn=chroot, cwd=root,
-                                env=augmentEnv())
-
-        while True:
-            (outStr, errStr) = proc.communicate()
-            if outStr:
-                map(program_log.info, outStr.splitlines())
-                rc += outStr
-            if errStr:
-                map(program_log.error, errStr.splitlines())
-                os.write(stderr, errStr)
-
-            if proc.returncode is not None:
-                break
-        # if we have anything other than a clean exit, and we get the fatal
-        # option, raise the OSError.
-        if proc.returncode and fatal:
-            raise RuntimeError('Error running ' + command + ': Non-zero return code: %s' % proc.returncode)
-    except OSError as e:
-        log.error ("Error running " + command + ": " + e.strerror)
-        raise RuntimeError, "Error running " + command + ": " + e.strerror
-    finally:
-        closefds()
-
-    return rc
-
-def execWithCallback(command, argv, stdin = None, stdout = None,
-                     stderr = None, echo = True, callback = None,
-                     callback_data = None, root = '/'):
-    if flags.testing:
-        log.info("not running command because we're testing: %s %s"
-                    % (command, " ".join(argv)))
-        return ExecProduct(0, '', '')
-
-    def chroot():
-        os.chroot(root)
-
-    def closefds ():
-        stdinclose()
-        stdoutclose()
-        stderrclose()
-
-    stdinclose = stdoutclose = stderrclose = lambda : None
-
-    argv = list(argv)
-    if isinstance(stdin, str):
-        if os.access(stdin, os.R_OK):
-            stdin = os.open(stdin, os.O_RDONLY)
-            stdinclose = lambda : os.close(stdin)
-        else:
-            stdin = sys.stdin.fileno()
-    elif isinstance(stdin, int):
-        pass
-    elif stdin is None or not isinstance(stdin, file):
-        stdin = sys.stdin.fileno()
-
-    if isinstance(stdout, str):
-        stdout = os.open(stdout, os.O_RDWR|os.O_CREAT)
-        stdoutclose = lambda : os.close(stdout)
-    elif isinstance(stdout, int):
-        pass
-    elif stdout is None or not isinstance(stdout, file):
-        stdout = sys.stdout.fileno()
-
-    if isinstance(stderr, str):
-        stderr = os.open(stderr, os.O_RDWR|os.O_CREAT)
-        stderrclose = lambda : os.close(stderr)
-    elif isinstance(stderr, int):
-        pass
-    elif stderr is None or not isinstance(stderr, file):
-        stderr = sys.stderr.fileno()
-
-    program_log.info("Running... %s" % (" ".join([command] + argv),))
-
-    p = os.pipe()
-    p_stderr = os.pipe()
-    childpid = os.fork()
-    if not childpid:
-        os.close(p[0])
-        os.close(p_stderr[0])
-        os.dup2(p[1], 1)
-        os.dup2(p_stderr[1], 2)
-        os.dup2(stdin, 0)
-        os.close(stdin)
-        os.close(p[1])
-        os.close(p_stderr[1])
-
-        os.execvp(command, [command] + argv)
-        os._exit(1)
-
-    os.close(p[1])
-    os.close(p_stderr[1])
-
-    log_output = ''
-    while 1:
-        try:
-            s = os.read(p[0], 1)
-        except OSError as e:
-            if e.errno != 4:
-                map(program_log.info, log_output.splitlines())
-                raise IOError, e.args
-
-        if echo:
-            os.write(stdout, s)
-        log_output += s
-
-        if callback:
-            callback(s, callback_data=callback_data)
-
-        # break out early if the sub-process changes status.
-        # no need to flush the stream if the process has exited
-        try:
-            (pid, status) = os.waitpid(childpid,os.WNOHANG)
-            if pid != 0:
-                break
-        except OSError as e:
-            log.critical("exception from waitpid: %s %s" %(e.errno, e.strerror))
-
-        if len(s) < 1:
-            break
-
-    map(program_log.info, log_output.splitlines())
-
-    log_errors = ''
-    while 1:
-        try:
-            err = os.read(p_stderr[0], 128)
-        except OSError as e:
-            if e.errno != 4:
-                map(program_log.error, log_errors.splitlines())
-                raise IOError, e.args
-            break
-        log_errors += err
-        if len(err) < 1:
-            break
-
-    os.write(stderr, log_errors)
-    map(program_log.error, log_errors.splitlines())
-    os.close(p[0])
-    os.close(p_stderr[0])
-
-    try:
-        #if we didn't already get our child's exit status above, do so now.
-        if not pid:
-            (pid, status) = os.waitpid(childpid, 0)
-    except OSError as e:
-        log.critical("exception from waitpid: %s %s" %(e.errno, e.strerror))
-
-    closefds()
-
-    rc = 1
-    if os.WIFEXITED(status):
-        rc = os.WEXITSTATUS(status)
-    return ExecProduct(rc, log_output , log_errors)
-
-def _pulseProgressCallback(data, callback_data=None):
-    if callback_data:
-        callback_data.pulse()
-
-def execWithPulseProgress(command, argv, stdin = None, stdout = None,
-                          stderr = None, echo = True, progress = None,
-                          root = '/'):
-    return execWithCallback(command, argv, stdin=stdin, stdout=stdout,
-                     stderr=stderr, echo=echo, callback=_pulseProgressCallback,
-                     callback_data=progress, root=root)
+    argv = [command] + argv
+    return _run_program(argv, stdin=stdin, root=root)[1]
 
 ## Run a shell.
 def execConsole():
@@ -459,29 +167,6 @@ def getDirSize(dir):
         return dsize
     return getSubdirSize(dir)/1024
 
-## Get the amount of RAM not used by /tmp.
-# @return The amount of available memory in kilobytes.
-def memAvailable():
-    tram = memInstalled()
-
-    ramused = getDirSize("/tmp")
-    return tram - ramused
-
-## Get the amount of RAM installed in the machine.
-# @return The amount of installed memory in kilobytes.
-def memInstalled():
-    f = open("/proc/meminfo", "r")
-    lines = f.readlines()
-    f.close()
-
-    for l in lines:
-        if l.startswith("MemTotal:"):
-            fields = string.split(l)
-            mem = fields[1]
-            break
-
-    return long(mem)
-
 ## Create a directory path.  Don't fail if the directory already exists.
 # @param dir The directory path to create.
 def mkdirChain(dir):
@@ -496,316 +181,6 @@ def mkdirChain(dir):
 
         log.error("could not create directory %s: %s" % (dir, e.strerror))
 
-## Copy a device node.
-# Copies a device node by looking at the device type, major and minor device
-# numbers, and doing a mknod on the new device name.
-#
-# @param src The name of the source device node.
-# @param dest The name of the new device node to create.
-def copyDeviceNode(src, dest):
-    filestat = os.lstat(src)
-    mode = filestat[stat.ST_MODE]
-    if stat.S_ISBLK(mode):
-        type = stat.S_IFBLK
-    elif stat.S_ISCHR(mode):
-        type = stat.S_IFCHR
-    else:
-        # XXX should we just fallback to copying normally?
-        raise RuntimeError, "Tried to copy %s which isn't a device node" % (src,)
-
-    os.mknod(dest, mode | type, filestat.st_rdev)
-
-## Get the SPARC machine variety type.
-# @return The SPARC machine type, or 0 if not SPARC.
-def getSparcMachine():
-    if not isSparc():
-        return 0
-
-    machine = None
-
-
-    f = open('/proc/cpuinfo', 'r')
-    lines = f.readlines()
-    f.close()
-    for line in lines:
-        if line.find('type') != -1:
-            machine = line.split(':')[1].strip()
-            return machine
-
-    return None
-
-## Get the PPC machine variety type.
-# @return The PPC machine type, or 0 if not PPC.
-def getPPCMachine():
-    if not isPPC():
-        return 0
-
-    ppcMachine = None
-    machine = None
-    platform = None
-
-    # ppc machine hash
-    ppcType = { 'Mac'      : 'PMac',
-                'Book'     : 'PMac',
-                'CHRP IBM' : 'pSeries',
-                'Pegasos'  : 'Pegasos',
-                'Efika'    : 'Efika',
-                'iSeries'  : 'iSeries',
-                'pSeries'  : 'pSeries',
-                'PReP'     : 'PReP',
-                'CHRP'     : 'pSeries',
-                'Amiga'    : 'APUS',
-                'Gemini'   : 'Gemini',
-                'Shiner'   : 'ANS',
-                'BRIQ'     : 'BRIQ',
-                'Teron'    : 'Teron',
-                'AmigaOne' : 'Teron',
-                'Maple'    : 'pSeries',
-                'Cell'     : 'pSeries',
-                'Momentum' : 'pSeries',
-                'PS3'      : 'PS3',
-                'PowerNV'  : 'pSeries'
-                }
-
-    f = open('/proc/cpuinfo', 'r')
-    lines = f.readlines()
-    f.close()
-    for line in lines:
-        if line.find('machine') != -1:
-            machine = line.split(':')[1]
-        elif line.find('platform') != -1:
-            platform = line.split(':')[1]
-
-    for part in (machine, platform):
-        if ppcMachine is None and part is not None:
-            for type in ppcType.items():
-                if part.find(type[0]) != -1:
-                    ppcMachine = type[1]
-
-    if ppcMachine is None:
-        log.warning("Unable to find PowerPC machine type")
-    elif ppcMachine == 0:
-        log.warning("Unknown PowerPC machine type: %s" %(ppcMachine,))
-
-    return ppcMachine
-
-## Get the powermac machine ID.
-# @return The powermac machine id, or 0 if not PPC.
-def getPPCMacID():
-    machine = None
-
-    if not isPPC():
-        return 0
-    if getPPCMachine() != "PMac":
-        return 0
-
-    f = open('/proc/cpuinfo', 'r')
-    lines = f.readlines()
-    f.close()
-    for line in lines:
-      if line.find('machine') != -1:
-        machine = line.split(':')[1]
-        machine = machine.strip()
-        return machine
-
-    log.warning("No Power Mac machine id")
-    return 0
-
-## Get the powermac generation.
-# @return The powermac generation, or 0 if not powermac.
-def getPPCMacGen():
-    # XXX: should NuBus be here?
-    pmacGen = ['OldWorld', 'NewWorld', 'NuBus']
-
-    if not isPPC():
-        return 0
-    if getPPCMachine() != "PMac":
-        return 0
-
-    f = open('/proc/cpuinfo', 'r')
-    lines = f.readlines()
-    f.close()
-    gen = None
-    for line in lines:
-      if line.find('pmac-generation') != -1:
-        gen = line.split(':')[1]
-        break
-
-    if gen is None:
-        log.warning("Unable to find pmac-generation")
-
-    for type in pmacGen:
-      if gen.find(type) != -1:
-          return type
-
-    log.warning("Unknown Power Mac generation: %s" %(gen,))
-    return 0
-
-## Determine if the hardware is an iBook or PowerBook
-# @return 1 if so, 0 otherwise.
-def getPPCMacBook():
-    if not isPPC():
-        return 0
-    if getPPCMachine() != "PMac":
-        return 0
-
-    f = open('/proc/cpuinfo', 'r')
-    lines = f.readlines()
-    f.close()
-
-    for line in lines:
-      if not string.find(string.lower(line), 'book') == -1:
-        return 1
-    return 0
-
-## Get the ARM processor variety.
-# @return The ARM processor variety type, or 0 if not ARM.
-def getARMMachine():
-    if not isARM():
-        return 0
-
-    if flags.armPlatform:
-        return flags.armPlatform
-
-    armMachine = os.uname()[2].rpartition('.' )[2]
-
-    if armMachine.startswith('arm'):
-        return None
-    else:
-        return armMachine
-
-
-cell = None
-## Determine if the hardware is the Cell platform.
-# @return True if so, False otherwise.
-def isCell():
-    global cell
-    if cell is not None:
-        return cell
-
-    cell = False
-    if not isPPC():
-        return cell
-
-    f = open('/proc/cpuinfo', 'r')
-    lines = f.readlines()
-    f.close()
-
-    for line in lines:
-      if not string.find(line, 'Cell') == -1:
-          cell = True
-
-    return cell
-
-mactel = None
-## Determine if the hardware is an Intel-based Apple Mac.
-# @return True if so, False otherwise.
-def isMactel():
-    global mactel
-    if mactel is not None:
-        return mactel
-
-    if not isX86():
-        mactel = False
-    elif not os.path.isfile(DMI_CHASSIS_VENDOR):
-        mactel = False
-    else:
-        buf = open(DMI_CHASSIS_VENDOR).read()
-        if buf.lower().find("apple") != -1:
-            mactel = True
-        else:
-            mactel = False
-    return mactel
-
-efi = None
-## Determine if the hardware supports EFI.
-# @return True if so, False otherwise.
-def isEfi():
-    global efi
-    if efi is not None:
-        return efi
-
-    efi = False
-    # XXX need to make sure efivars is loaded...
-    if os.path.exists("/sys/firmware/efi"):
-        efi = True
-
-    return efi
-
-# Architecture checking functions
-
-def isX86(bits=None):
-    arch = os.uname()[4]
-
-    # x86 platforms include:
-    #     i*86
-    #     athlon*
-    #     x86_64
-    #     amd*
-    #     ia32e
-    if bits is None:
-        if (arch.startswith('i') and arch.endswith('86')) or \
-           arch.startswith('athlon') or arch.startswith('amd') or \
-           arch == 'x86_64' or arch == 'ia32e':
-            return True
-    elif bits == 32:
-        if arch.startswith('i') and arch.endswith('86'):
-            return True
-    elif bits == 64:
-        if arch.startswith('athlon') or arch.startswith('amd') or \
-           arch == 'x86_64' or arch == 'ia32e':
-            return True
-
-    return False
-
-def isPPC(bits=None):
-    arch = os.uname()[4]
-
-    if bits is None:
-        if arch == 'ppc' or arch == 'ppc64':
-            return True
-    elif bits == 32:
-        if arch == 'ppc':
-            return True
-    elif bits == 64:
-        if arch == 'ppc64':
-            return True
-
-    return False
-
-def isS390():
-    return os.uname()[4].startswith('s390')
-
-def isIA64():
-    return os.uname()[4] == 'ia64'
-
-def isAlpha():
-    return os.uname()[4].startswith('alpha')
-
-def isSparc():
-    return os.uname()[4].startswith('sparc')
-
-def isARM():
-    return os.uname()[4].startswith('arm')
-
-def getArch():
-    if isX86(bits=32):
-        return 'i386'
-    elif isX86(bits=64):
-        return 'x86_64'
-    elif isPPC(bits=32):
-        return 'ppc'
-    elif isPPC(bits=64):
-        return 'ppc64'
-    elif isAlpha():
-        return 'alpha'
-    elif isSparc():
-        return 'sparc'
-    elif isARM():
-        return 'arm'
-    else:
-        return os.uname()[4]
-
 def isConsoleOnVirtualTerminal():
     # XXX PJFIX is there some way to ask the kernel this instead?
     if isS390():
@@ -828,54 +203,6 @@ def strip_markup(text):
             r += c
     return r.encode("utf-8")
 
-def notify_kernel(path, action="change"):
-    """ Signal the kernel that the specified device has changed.
-
-        Exceptions raised: ValueError, IOError
-    """
-    log.debug("notifying kernel of '%s' event on device %s" % (action, path))
-    path = os.path.join(path, "uevent")
-    if not path.startswith("/sys/") or not os.access(path, os.W_OK):
-        log.debug("sysfs path '%s' invalid" % path)
-        raise ValueError("invalid sysfs path")
-
-    f = open(path, "a")
-    f.write("%s\n" % action)
-    f.close()
-
-def get_sysfs_path_by_name(dev_node, class_name="block"):
-    """ Return sysfs path for a given device.
-
-        For a device node (e.g. /dev/vda2) get the respective sysfs path
-        (e.g. /sys/class/block/vda2). This also has to work for device nodes
-        that are in a subdirectory of /dev like '/dev/cciss/c0d0p1'.
-     """
-    dev_name = os.path.basename(dev_node)
-    if dev_node.startswith("/dev/"):
-        dev_name = dev_node[5:].replace("/", "!")
-    sysfs_class_dir = "/sys/class/%s" % class_name
-    dev_path = os.path.join(sysfs_class_dir, dev_name)
-    if os.path.exists(dev_path):
-        return dev_path
-    else:
-        raise RuntimeError("get_sysfs_path_by_name: Could not find sysfs path "
-                           "for '%s' (it is not at '%s')" % (dev_node, dev_path))
-
-def numeric_type(num):
-    """ Verify that a value is given as a numeric data type.
-
-        Return the number if the type is sensible or raise ValueError
-        if not.
-    """
-    if num is None:
-        num = 0
-    elif not (isinstance(num, int) or \
-              isinstance(num, long) or \
-              isinstance(num, float)):
-        raise ValueError("value (%s) must be either a number or None" % num)
-
-    return num
-
 def reIPL(ipldev):
     try:
         rc = execWithRedirect("chreipl", ["node", "/dev/" + ipldev])
@@ -929,19 +256,6 @@ def parseNfsUrl(nfsurl):
             host = s[0]
     return (options, host, path)
 
-def insert_colons(a_string):
-    """
-    Insert colon between every second character.
-
-    E.g. creates 'al:go:ri:th:ms' from 'algoritms'. Useful for formatting MAC
-    addresses and wwids for output.
-    """
-    suffix = a_string[-2:]
-    if len(a_string) > 2:
-        return insert_colons(a_string[:-2]) + ':' + suffix
-    else:
-        return suffix
-
 def add_po_path(module, dir):
     """ Looks to see what translations are under a given path and tells
     the gettext module to use that path as the base dir """
@@ -961,43 +275,6 @@ def setup_translations(module):
         add_po_path(module, TRANSLATIONS_UPDATE_DIR)
     module.textdomain("anaconda")
 
-def copy_to_sysimage(source):
-    if not os.access(source, os.R_OK):
-        log.info("copy_to_sysimage: source '%s' does not exist." % source)
-        return False
-
-    target = ROOT_PATH + source
-    target_dir = os.path.dirname(target)
-    log.debug("copy_to_sysimage: '%s' -> '%s'." % (source, target))
-    if not os.path.isdir(target_dir):
-        os.makedirs(target_dir)
-    shutil.copy(source, target)
-    return True
-
-def get_sysfs_attr(path, attr):
-    if not attr:
-        log.debug("get_sysfs_attr() called with attr=None")
-        return None
-
-    attribute = "/sys%s/%s" % (path, attr)
-    attribute = os.path.realpath(attribute)
-
-    if not os.path.isfile(attribute) and not os.path.islink(attribute):
-        log.warning("%s is not a valid attribute" % (attr,))
-        return None
-
-    return open(attribute, "r").read().strip()
-
-def find_program_in_path(prog, raise_on_error=False):
-    for d in os.environ["PATH"].split(os.pathsep):
-        full = os.path.join(d, prog)
-        if os.access(full, os.X_OK):
-            return full
-
-    if raise_on_error:
-        raise RuntimeError("Unable to locate a needed executable: '%s'" % prog)
-    return None
-
 def fork_orphan():
     """Forks an orphan.
 
@@ -1013,12 +290,6 @@ def fork_orphan():
     os.waitpid(intermediate, 0)
     return 1
 
-def lsmod():
-    """ Returns list of names of all loaded modules. """
-    with open("/proc/modules") as f:
-        lines = f.readlines()
-    return [l.split()[0] for l in lines]
-
 def _run_systemctl(command, service):
     """
     Runs 'systemctl command service.service'
@@ -1070,16 +341,6 @@ def dracut_eject(device):
     except Exception, e:
         log.error("Error writing dracut shutdown eject hook for %s: %s" % (device, e))
 
-def get_option_value(opt_name, options):
-    """ Return the value of a named option in the specified options string. """
-    for opt in options.split(","):
-        if "=" not in opt:
-            continue
-
-        name, val = opt.split("=")
-        if name == opt_name:
-            return val.strip()
-
 def vtActivate(num):
     """
     Try to switch to tty number $num.
diff --git a/pyanaconda/kickstart.py b/pyanaconda/kickstart.py
index 2919329..a723039 100644
--- a/pyanaconda/kickstart.py
+++ b/pyanaconda/kickstart.py
@@ -44,6 +44,7 @@ import sys
 import urlgrabber
 import pykickstart.commands as commands
 from storage.devices import *
+from pyanaconda.storage import arch
 from pyanaconda import keyboard
 from pyanaconda import ntp
 from pyanaconda import timezone
@@ -849,7 +850,7 @@ class PartitionData(commands.partition.F18_PartData):
             if self.onPart:
                 ksdata.onPart[kwargs["name"]] = self.onPart
         elif self.mountpoint == "/boot/efi":
-            if iutil.isMactel():
+            if arch.isMactel():
                 type = "hfs+"
             else:
                 type = "EFI System Partition"
diff --git a/pyanaconda/network.py b/pyanaconda/network.py
index b0b3fd5..f968fba 100644
--- a/pyanaconda/network.py
+++ b/pyanaconda/network.py
@@ -40,6 +40,7 @@ from flags import flags
 from simpleconfig import IfcfgFile
 import urlgrabber.grabber
 from pyanaconda.storage.devices import FcoeDiskDevice, iScsiDiskDevice
+from pyanaconda.storage import arch
 
 import gettext
 _ = lambda x: gettext.ldgettext("anaconda", x)
@@ -268,7 +269,7 @@ class NetworkDevice(IfcfgFile):
     def __str__(self):
         s = ""
         keys = self.info.keys()
-        if iutil.isS390() and ("HWADDR" in keys):
+        if arch.isS390() and ("HWADDR" in keys):
             keys.remove("HWADDR")
         # make sure we include autoneg in the ethtool line
         if 'ETHTOOL_OPTS' in keys:
@@ -593,7 +594,7 @@ def dracutBootArguments(ifcfg, storage_ipaddr, hostname=None):
 
     nettype = ifcfg.get("NETTYPE")
     subchannels = ifcfg.get("SUBCHANNELS")
-    if iutil.isS390() and nettype and subchannels:
+    if arch.isS390() and nettype and subchannels:
         znet = "rd.znet=%s,%s" % (nettype, subchannels)
         options = ifcfg.get("OPTIONS").strip("'\"")
         if options:
diff --git a/pyanaconda/packaging/__init__.py b/pyanaconda/packaging/__init__.py
index 84d7c33..690c19d 100644
--- a/pyanaconda/packaging/__init__.py
+++ b/pyanaconda/packaging/__init__.py
@@ -53,6 +53,8 @@ log = logging.getLogger("packaging")
 
 from pyanaconda.errors import *
 from pyanaconda.storage.errors import StorageError
+from pyanaconda.storage import util
+from pyanaconda.storage import arch
 #from pyanaconda.progress import progress
 
 from pyanaconda.product import productName, productVersion
@@ -481,7 +483,7 @@ class Payload(object):
                 return
             else:
                 try:
-                    isys.umount(realMountpoint, removeDir=False)
+                    util.umount(realMountpoint)
                 except Exception as e:
                     log.error(str(e))
                     log.info("umount failed -- mounting on top of it")
@@ -507,8 +509,8 @@ class Payload(object):
             else:
                 log.debug("%s already has something mounted on it" % mountpoint)
                 try:
-                    isys.umount(mountpoint, removeDir=False)
-                except Exception as e:
+                    util.umount(mountpoint)
+                except OSError as e:
                     log.error(str(e))
                     log.info("umount failed -- mounting on top of it")
 
@@ -516,8 +518,8 @@ class Payload(object):
         url = "%s:%s" % (server, path)
 
         try:
-            isys.mount(url, mountpoint, fstype="nfs", options=options)
-        except SystemError as e:
+            util.mount(url, mountpoint, fstype="nfs", options=options)
+        except OSError as e:
             raise PayloadSetupError(str(e))
 
     ###
@@ -652,7 +654,7 @@ class PackagePayload(Payload):
             kernels.insert(0, "kernel-PAE")
 
         # most ARM systems use platform-specific kernels
-        if iutil.isARM():
+        if arch.isARM():
             if self.storage.platform.armMachine is not None:
                 kernels = ["kernel-%s" % self.storage.platform.armMachine]
 
diff --git a/pyanaconda/packaging/livepayload.py b/pyanaconda/packaging/livepayload.py
index 03c464e..43f9871 100644
--- a/pyanaconda/packaging/livepayload.py
+++ b/pyanaconda/packaging/livepayload.py
@@ -33,7 +33,6 @@ import os
 import stat
 from time import sleep
 from threading import Lock
-from pyanaconda import isys
 
 from . import *
 
@@ -48,6 +47,7 @@ log = logging.getLogger("anaconda")
 from pyanaconda.errors import *
 from pyanaconda import progress
 from pyanaconda.storage.size import Size
+from pyanaconda.storage import util
 from pyanaconda.threads import threadMgr, AnacondaThread
 
 import gettext
@@ -64,7 +64,7 @@ class LiveImagePayload(ImagePayload):
             exn = PayloadSetupError("%s is not a valid block device" % (self.data.method.partition,))
             if errorHandler.cb(exn) == ERROR_RAISE:
                 raise exn
-        isys.mount(osimg.path, INSTALL_TREE, fstype="auto", readOnly=True)
+        util.mount(osimg.path, INSTALL_TREE, fstype="auto", options="ro")
 
     def preInstall(self, packages=None, groups=None):
         """ Perform pre-installation tasks. """
@@ -130,7 +130,7 @@ class LiveImagePayload(ImagePayload):
     def postInstall(self):
         """ Perform post-installation tasks. """
         progress.send_message(_("Performing post-install setup tasks"))
-        isys.umount(INSTALL_TREE, removeDir=True)
+        util.umount(INSTALL_TREE)
 
         super(LiveImagePayload, self).postInstall()
         self._recreateInitrds()
diff --git a/pyanaconda/packaging/yumpayload.py b/pyanaconda/packaging/yumpayload.py
index 4637210..43feebe 100644
--- a/pyanaconda/packaging/yumpayload.py
+++ b/pyanaconda/packaging/yumpayload.py
@@ -72,9 +72,10 @@ from pyanaconda.flags import flags
 
 from pyanaconda import iutil
 from pyanaconda.iutil import ProxyString, ProxyStringError
-from pyanaconda import isys
 from pyanaconda.network import hasActiveNetDev
 from pyanaconda.storage.size import Size
+from pyanaconda.storage import util
+from pyanaconda.storage import arch
 
 from pyanaconda.image import opticalInstallMedia
 from pyanaconda.image import mountImage
@@ -136,7 +137,7 @@ class YumPayload(PackagePayload):
                get_mount_device(INSTALL_TREE) == self.install_device.path:
                 self.install_device.teardown(recursive=True)
             else:
-                isys.umount(INSTALL_TREE, removeDir=False)
+                util.umount(INSTALL_TREE)
 
         if os.path.ismount(ISO_DIR) and not flags.testing:
             if self.install_device and \
@@ -149,7 +150,7 @@ class YumPayload(PackagePayload):
             # Commenting out the below is a hack for F18.  FIXME
             #else:
             #    # NFS
-            #    isys.umount(ISO_DIR, removeDir=False)
+            #    util.umount(ISO_DIR)
 
         self.install_device = None
 
@@ -647,17 +648,6 @@ reposdir=%s
                                            ["--make-rprivate", "/"])
                     iutil.execWithRedirect("mount",
                                            ["--move", INSTALL_TREE, ISO_DIR])
-                    # Mounts are kept track of in isys it seems
-                    # Remove the count for the source
-                    if isys.mountCount.has_key(INSTALL_TREE):
-                        if isys.mountCount[INSTALL_TREE] > 1:
-                            isys.mountCount[INSTALL_TREE] -= 1
-                        else:
-                            del(isys.mountCount[INSTALL_TREE])
-                    # Add a count for the new location
-                    if not isys.mountCount.has_key(ISO_DIR):
-                        isys.mountCount[ISO_DIR] = 0
-                    isys.mountCount[ISO_DIR] += 1
                     # mount the ISO on a loop
                     image = os.path.normpath("%s/%s" % (ISO_DIR, image))
                     mountImage(image, INSTALL_TREE)
@@ -845,7 +835,7 @@ reposdir=%s
 
         if mountpoint and os.path.ismount(mountpoint):
             try:
-                isys.umount(mountpoint, removeDir=False)
+                util.umount(mountpoint, removeDir=False)
             except SystemError as e:
                 log.error("failed to unmount nfs repo %s: %s" % (mountpoint, e))
 
@@ -1512,7 +1502,7 @@ class RPMCallback(object):
 
         self.total_actions = 0
         self.completed_actions = None   # will be set to 0 when starting tx
-        self.base_arch = iutil.getArch()
+        self.base_arch = arch.getArch()
 
     def _get_txmbr(self, key):
         """ Return a (name, TransactionMember) tuple from cb key. """
diff --git a/pyanaconda/platform.py b/pyanaconda/platform.py
index b1c849b..2012cdb 100644
--- a/pyanaconda/platform.py
+++ b/pyanaconda/platform.py
@@ -26,10 +26,8 @@ log = logging.getLogger("anaconda")
 import parted
 
 from pyanaconda import bootloader
-from pyanaconda.storage.devicelibs import mdraid
-from pyanaconda.constants import DMI_CHASSIS_VENDOR
+from pyanaconda.storage import arch
 
-import iutil
 from flags import flags
 
 import gettext
@@ -233,7 +231,7 @@ class MacEFI(EFI):
         return ret
 
 class PPC(Platform):
-    _ppcMachine = iutil.getPPCMachine()
+    _ppcMachine = arch.getPPCMachine()
     bootloaderClass = bootloader.GRUB2
     _boot_stage1_device_types = ["partition"]
 
@@ -347,7 +345,7 @@ class ARM(Platform):
     @property
     def armMachine(self):
         if not self._armMachine:
-            self._armMachine = iutil.getARMMachine()
+            self._armMachine = arch.getARMMachine()
         return self._armMachine
 
     def weight(self, fstype=None, mountpoint=None):
@@ -393,10 +391,10 @@ def getPlatform():
     """Check the architecture of the system and return an instance of a
        Platform subclass to match.  If the architecture could not be determined,
        raise an exception."""
-    if iutil.isPPC():
-        ppcMachine = iutil.getPPCMachine()
+    if arch.isPPC():
+        ppcMachine = arch.getPPCMachine()
 
-        if (ppcMachine == "PMac" and iutil.getPPCMacGen() == "NewWorld"):
+        if (ppcMachine == "PMac" and arch.getPPCMacGen() == "NewWorld"):
             return NewWorldPPC()
         elif ppcMachine in ["iSeries", "pSeries"]:
             return IPSeriesPPC()
@@ -404,19 +402,19 @@ def getPlatform():
             return PS3()
         else:
             raise SystemError, "Unsupported PPC machine type: %s" % ppcMachine
-    elif iutil.isS390():
+    elif arch.isS390():
         return S390()
-    elif iutil.isSparc():
+    elif arch.isSparc():
         return Sparc()
-    elif iutil.isEfi():
-        if iutil.isMactel():
+    elif arch.isEfi():
+        if arch.isMactel():
             return MacEFI()
         else:
             return EFI()
-    elif iutil.isX86():
+    elif arch.isX86():
         return X86()
-    elif iutil.isARM():
-        armMachine = iutil.getARMMachine()
+    elif arch.isARM():
+        armMachine = arch.getARMMachine()
         if armMachine == "omap":
             return omapARM()
         else:
diff --git a/pyanaconda/storage/__init__.py b/pyanaconda/storage/__init__.py
index 9d3af87..94f6263 100644
--- a/pyanaconda/storage/__init__.py
+++ b/pyanaconda/storage/__init__.py
@@ -31,16 +31,13 @@ import copy
 import nss.nss
 import parted
 
-from pyanaconda import isys
-from pyanaconda import iutil
 from pyanaconda.constants import *
 from pykickstart.constants import *
-from pyanaconda.flags import flags
 from pyanaconda import tsort
 from pyanaconda.errors import *
 from pyanaconda.bootloader import BootLoaderError
-from pyanaconda.anaconda_log import log_method_call
 
+from storage_log import log_method_call
 from errors import *
 from devices import *
 from devicetree import DeviceTree
@@ -63,6 +60,14 @@ import iscsi
 import fcoe
 import zfcp
 import dasd
+import util
+import arch
+import flags
+
+if flags.installer_mode:
+    from pyanaconda import isys
+else:
+    isys = None
 
 import shelve
 import contextlib
@@ -123,7 +128,7 @@ def storageInitialize(storage, ksdata, protected):
 
     # XXX I don't understand why I have to do this, but this is needed to
     #     populate the udev db
-    iutil.execWithRedirect("udevadm", ["control", "--property=ANACONDA=1"])
+    util.run_program(["udevadm", "control", "--property=ANACONDA=1"])
     udev_trigger(subsystem="block", action="change")
 
     # Before we set up the storage system, we need to know which disks to
@@ -137,30 +142,24 @@ def storageInitialize(storage, ksdata, protected):
         storage.config.protectedDevSpecs.extend(protected)
         storage.reset()
 
-        if not flags.livecdInstall and not storage.protectedDevices:
-            if anaconda.upgrade:
-                return
-            else:
-                raise UnknownSourceDeviceError(protected)
+        if not flags.live_install and not storage.protectedDevices:
+            raise UnknownSourceDeviceError(protected)
     else:
         storage.reset()
 
     # kickstart uses all the disks
-    if flags.automatedInstall:
+    if flags.automated_install:
         if not ksdata.ignoredisk.onlyuse:
             ksdata.ignoredisk.onlyuse = [d.name for d in storage.disks \
                                          if d.name not in ksdata.ignoredisk.ignoredisk]
             log.debug("onlyuse is now: %s" % (",".join(ksdata.ignoredisk.onlyuse)))
 
 def turnOnFilesystems(storage):
-    upgrade = "preupgrade" in flags.cmdline
-
-    if not upgrade:
-        if (flags.livecdInstall and not flags.imageInstall and not storage.fsset.active):
-            # turn off any swaps that we didn't turn on
-            # needed for live installs
-            iutil.execWithRedirect("swapoff", ["-a"])
-        storage.devicetree.teardownAll()
+    if (flags.live_install and not flags.image_install and not storage.fsset.active):
+        # turn off any swaps that we didn't turn on
+        # needed for live installs
+        util.run_program(["swapoff", "-a"])
+    storage.devicetree.teardownAll()
 
     try:
         storage.doIt()
@@ -394,7 +393,7 @@ class Storage(object):
         if self.data:
             self.config.update(self.data)
 
-        if not flags.imageInstall:
+        if not flags.image_install:
             self.iscsi.startup()
             self.fcoe.startup()
             self.zfcp.startup()
@@ -402,9 +401,6 @@ class Storage(object):
                               self.config.exclusiveDisks,
                               self.config.initializeDisks)
         clearPartType = self.config.clearPartType # save this before overriding it
-        if self.data and self.data.upgrade.upgrade:
-            self.config.clearPartType = CLEARPART_TYPE_NONE
-
         if self.dasd:
             # Reset the internal dasd list (823534)
             self.dasd.clear_device_list()
@@ -1300,7 +1296,7 @@ class Storage(object):
         else:
             template = prefix
 
-        if flags.imageInstall:
+        if flags.image_install:
             template = "%s_image" % template
 
         names = self.names
@@ -1429,11 +1425,14 @@ class Storage(object):
             a really small /, etc).  Returns (errors, warnings) where
             each is a list of strings.
         """
-        checkSizes = [('/usr', 250), ('/tmp', 50), ('/var', 384),
-                      ('/home', 100), ('/boot', 75)]
         warnings = []
         errors = []
 
+        if not flags.installer_mode:
+            return (errors, warnings)
+
+        checkSizes = [('/usr', 250), ('/tmp', 50), ('/var', 384),
+                      ('/home', 100), ('/boot', 75)]
         mustbeonlinuxfs = ['/', '/var', '/tmp', '/usr', '/home', '/usr/share', '/usr/lib']
         mustbeonroot = ['/bin','/dev','/sbin','/etc','/lib','/root', '/mnt', 'lost+found', '/proc']
 
@@ -1462,7 +1461,7 @@ class Storage(object):
         # restricted to a single PV.  The backend support is there, but there are
         # no UI hook-ups to drive that functionality, but I do not personally
         # care.  --dcantrell
-        if iutil.isS390() and \
+        if arch.isS390() and \
            not self.mountpoints.has_key('/boot') and \
            root.type == 'lvmlv' and not root.singlePV:
             errors.append(_("This platform requires /boot on a dedicated "
@@ -1494,9 +1493,11 @@ class Storage(object):
                               % {"mount":mount, "format": device.format.name,
                                  "minSize": device.minSize, "maxSize": device.maxSize})
 
+        # FIXME: this does not work, but probably should
+        """
         usb_disks = []
         firewire_disks = []
-        for disk in self.disks:
+        #for disk in self.disks:
             if isys.driveUsesModule(disk.name, ["usb-storage", "ub"]):
                 usb_disks.append(disk)
             elif isys.driveUsesModule(disk.name, ["sbp2", "firewire-sbp2"]):
@@ -1521,6 +1522,7 @@ class Storage(object):
         if uses_firewire:
             warnings.append(_("Installing on a FireWire device.  This may "
                               "or may not produce a working system."))
+        """
 
         if self.bootloader and not self.bootloader.skip_bootloader:
             stage1 = self.bootloader.stage1_device
@@ -1564,7 +1566,7 @@ class Storage(object):
         if not swaps:
             from pyanaconda.storage.size import Size
 
-            installed = Size(spec="%s kb" % iutil.memInstalled())
+            installed = Size(spec="%s kb" % util.total_memory())
             required = Size(spec="%s kb" % isys.EARLY_SWAP_RAM)
 
             if installed < required:
@@ -1820,7 +1822,7 @@ class Storage(object):
         elif mountpoint == "/boot":
             fstype = self.defaultBootFSType
         elif mountpoint == "/boot/efi":
-            if iutil.isMactel():
+            if arch.isMactel():
                 fstype = "hfs+"
             else:
                 fstype = "efi"
@@ -2354,10 +2356,10 @@ def mountExistingSystem(fsset, rootDevice,
         readOnly = ""
 
     if rootDevice.protected and os.path.ismount("/mnt/install/isodir"):
-        isys.mount("/mnt/install/isodir",
+        util.mount("/mnt/install/isodir",
                    rootPath,
                    fstype=rootDevice.format.type,
-                   bindMount=True)
+                   options="bind")
     else:
         rootDevice.setup()
         rootDevice.format.mount(chroot=rootPath,
@@ -2979,9 +2981,9 @@ class FSSet(object):
             f.close()
         else:
             log.info("not writing out mpath configuration")
-        iutil.copy_to_sysimage("/etc/multipath/wwids")
+        util.copy_to_system("/etc/multipath/wwids")
         if self.devicetree.mpathFriendlyNames:
-            iutil.copy_to_sysimage("/etc/multipath/bindings")
+            util.copy_to_system("/etc/multipath/bindings")
 
     def crypttab(self):
         # if we are upgrading, do we want to update crypttab?
@@ -3125,7 +3127,7 @@ def getReleaseString():
     relVer = None
 
     try:
-        relArch = iutil.execWithCapture("arch", [], root=ROOT_PATH).strip()
+        relArch = util.capture_output(["arch"], root=ROOT_PATH).strip()
     except:
         relArch = None
 
@@ -3149,7 +3151,7 @@ def getReleaseString():
 
 def findExistingInstallations(devicetree):
     if not os.path.exists(ROOT_PATH):
-        iutil.mkdirChain(ROOT_PATH)
+        util.makedirs(ROOT_PATH)
 
     roots = []
     for device in devicetree.leaves:
diff --git a/pyanaconda/storage/arch.py b/pyanaconda/storage/arch.py
new file mode 100644
index 0000000..7fc39e7
--- /dev/null
+++ b/pyanaconda/storage/arch.py
@@ -0,0 +1,315 @@
+#
+# arch.py
+#
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 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/>.
+#
+# Author(s): Jeremy Katz <katzj@redhat.com>
+#            Paul Nasrat <pnasrat@redhat.com>
+#            Peter Jones <pjones@redhat.com>
+#            Chris Lumens <clumens@redhat.com>
+#            Will Woods <wwoods@redhat.com>
+#            Dennis Gilmore <dgilmore@ausil.us>
+#            David Marlin <dmarlin@redhat.com>
+#
+
+import os
+
+from .flags import flags
+
+## Get the SPARC machine variety type.
+# @return The SPARC machine type, or 0 if not SPARC.
+def getSparcMachine():
+    if not isSparc():
+        return 0
+
+    machine = None
+
+
+    f = open('/proc/cpuinfo', 'r')
+    lines = f.readlines()
+    f.close()
+    for line in lines:
+        if line.find('type') != -1:
+            machine = line.split(':')[1].strip()
+            return machine
+
+    return None
+
+## Get the PPC machine variety type.
+# @return The PPC machine type, or 0 if not PPC.
+def getPPCMachine():
+    if not isPPC():
+        return 0
+
+    ppcMachine = None
+    machine = None
+    platform = None
+
+    # ppc machine hash
+    ppcType = { 'Mac'      : 'PMac',
+                'Book'     : 'PMac',
+                'CHRP IBM' : 'pSeries',
+                'Pegasos'  : 'Pegasos',
+                'Efika'    : 'Efika',
+                'iSeries'  : 'iSeries',
+                'pSeries'  : 'pSeries',
+                'PReP'     : 'PReP',
+                'CHRP'     : 'pSeries',
+                'Amiga'    : 'APUS',
+                'Gemini'   : 'Gemini',
+                'Shiner'   : 'ANS',
+                'BRIQ'     : 'BRIQ',
+                'Teron'    : 'Teron',
+                'AmigaOne' : 'Teron',
+                'Maple'    : 'pSeries',
+                'Cell'     : 'pSeries',
+                'Momentum' : 'pSeries',
+                'PS3'      : 'PS3',
+                'PowerNV'  : 'pSeries'
+                }
+
+    f = open('/proc/cpuinfo', 'r')
+    lines = f.readlines()
+    f.close()
+    for line in lines:
+        if line.find('machine') != -1:
+            machine = line.split(':')[1]
+        elif line.find('platform') != -1:
+            platform = line.split(':')[1]
+
+    for part in (machine, platform):
+        if ppcMachine is None and part is not None:
+            for type in ppcType.items():
+                if part.find(type[0]) != -1:
+                    ppcMachine = type[1]
+
+    if ppcMachine is None:
+        log.warning("Unable to find PowerPC machine type")
+    elif ppcMachine == 0:
+        log.warning("Unknown PowerPC machine type: %s" %(ppcMachine,))
+
+    return ppcMachine
+
+## Get the powermac machine ID.
+# @return The powermac machine id, or 0 if not PPC.
+def getPPCMacID():
+    machine = None
+
+    if not isPPC():
+        return 0
+    if getPPCMachine() != "PMac":
+        return 0
+
+    f = open('/proc/cpuinfo', 'r')
+    lines = f.readlines()
+    f.close()
+    for line in lines:
+      if line.find('machine') != -1:
+        machine = line.split(':')[1]
+        machine = machine.strip()
+        return machine
+
+    log.warning("No Power Mac machine id")
+    return 0
+
+## Get the powermac generation.
+# @return The powermac generation, or 0 if not powermac.
+def getPPCMacGen():
+    # XXX: should NuBus be here?
+    pmacGen = ['OldWorld', 'NewWorld', 'NuBus']
+
+    if not isPPC():
+        return 0
+    if getPPCMachine() != "PMac":
+        return 0
+
+    f = open('/proc/cpuinfo', 'r')
+    lines = f.readlines()
+    f.close()
+    gen = None
+    for line in lines:
+      if line.find('pmac-generation') != -1:
+        gen = line.split(':')[1]
+        break
+
+    if gen is None:
+        log.warning("Unable to find pmac-generation")
+
+    for _type in pmacGen:
+      if _type in gen:
+          return type
+
+    log.warning("Unknown Power Mac generation: %s" %(gen,))
+    return 0
+
+## Determine if the hardware is an iBook or PowerBook
+# @return 1 if so, 0 otherwise.
+def getPPCMacBook():
+    if not isPPC():
+        return 0
+    if getPPCMachine() != "PMac":
+        return 0
+
+    f = open('/proc/cpuinfo', 'r')
+    buf = f.read()
+    f.close()
+    return 'book' in buf.lower()
+
+## Get the ARM processor variety.
+# @return The ARM processor variety type, or 0 if not ARM.
+def getARMMachine():
+    if not isARM():
+        return 0
+
+    if flags.arm_platform:
+        return flags.arm_platform
+
+    armMachine = os.uname()[2].rpartition('.' )[2]
+
+    if armMachine.startswith('arm'):
+        return None
+    else:
+        return armMachine
+
+
+cell = None
+## Determine if the hardware is the Cell platform.
+# @return True if so, False otherwise.
+def isCell():
+    global cell
+    if cell is not None:
+        return cell
+
+    cell = False
+    if not isPPC():
+        return cell
+
+    f = open('/proc/cpuinfo', 'r')
+    lines = f.readlines()
+    f.close()
+
+    for line in lines:
+      if 'Cell' in line:
+          cell = True
+
+    return cell
+
+mactel = None
+## Determine if the hardware is an Intel-based Apple Mac.
+# @return True if so, False otherwise.
+def isMactel():
+    global mactel
+    if mactel is not None:
+        return mactel
+
+    if not isX86():
+        mactel = False
+    elif not os.path.isfile(DMI_CHASSIS_VENDOR):
+        mactel = False
+    else:
+        buf = open(DMI_CHASSIS_VENDOR).read()
+        mactel = ("apple" in buf.lower())
+    return mactel
+
+efi = None
+## Determine if the hardware supports EFI.
+# @return True if so, False otherwise.
+def isEfi():
+    global efi
+    if efi is not None:
+        return efi
+
+    efi = False
+    # XXX need to make sure efivars is loaded...
+    if os.path.exists("/sys/firmware/efi"):
+        efi = True
+
+    return efi
+
+# Architecture checking functions
+
+def isX86(bits=None):
+    arch = os.uname()[4]
+
+    # x86 platforms include:
+    #     i*86
+    #     athlon*
+    #     x86_64
+    #     amd*
+    #     ia32e
+    if bits is None:
+        if (arch.startswith('i') and arch.endswith('86')) or \
+           arch.startswith('athlon') or arch.startswith('amd') or \
+           arch == 'x86_64' or arch == 'ia32e':
+            return True
+    elif bits == 32:
+        if arch.startswith('i') and arch.endswith('86'):
+            return True
+    elif bits == 64:
+        if arch.startswith('athlon') or arch.startswith('amd') or \
+           arch == 'x86_64' or arch == 'ia32e':
+            return True
+
+    return False
+
+def isPPC(bits=None):
+    arch = os.uname()[4]
+
+    if bits is None:
+        if arch == 'ppc' or arch == 'ppc64':
+            return True
+    elif bits == 32:
+        if arch == 'ppc':
+            return True
+    elif bits == 64:
+        if arch == 'ppc64':
+            return True
+
+    return False
+
+def isS390():
+    return os.uname()[4].startswith('s390')
+
+def isIA64():
+    return os.uname()[4] == 'ia64'
+
+def isAlpha():
+    return os.uname()[4].startswith('alpha')
+
+def isSparc():
+    return os.uname()[4].startswith('sparc')
+
+def isARM():
+    return os.uname()[4].startswith('arm')
+
+def getArch():
+    if isX86(bits=32):
+        return 'i386'
+    elif isX86(bits=64):
+        return 'x86_64'
+    elif isPPC(bits=32):
+        return 'ppc'
+    elif isPPC(bits=64):
+        return 'ppc64'
+    elif isAlpha():
+        return 'alpha'
+    elif isSparc():
+        return 'sparc'
+    elif isARM():
+        return 'arm'
+    else:
+        return os.uname()[4]
diff --git a/pyanaconda/storage/dasd.py b/pyanaconda/storage/dasd.py
index 6c583cb..752ca05 100644
--- a/pyanaconda/storage/dasd.py
+++ b/pyanaconda/storage/dasd.py
@@ -19,17 +19,17 @@
 # Red Hat Author(s): David Cantrell <dcantrell@redhat.com>
 #
 
-from pyanaconda import iutil
 import sys
 import os
 from pyanaconda.storage.errors import DasdFormatError
 from pyanaconda.storage.devices import deviceNameToDiskByPath
+from pyanaconda.storage import util
+from pyanaconda.storage import arch
 from pyanaconda.constants import *
-from pyanaconda.flags import flags
 from pyanaconda.baseudev import udev_trigger
 
 import logging
-log = logging.getLogger("anaconda")
+log = logging.getLogger("storage")
 
 import gettext
 _ = lambda x: gettext.ldgettext("anaconda", x)
@@ -82,7 +82,7 @@ class DASD:
 
         self.started = True
 
-        if not iutil.isS390():
+        if not arch.isS390():
             return
 
         # Trigger udev data about the dasd devices on the system
@@ -140,8 +140,7 @@ class DASD:
         # gather total cylinder count
         argv = ["-t", "-v"] + self.commonArgv
         for dasd, bypath in self._dasdlist:
-            buf = iutil.execWithCapture(self.dasdfmt, argv + ["/dev/" + dasd],
-                                        stderr=err)
+            buf = util.capture_output([self.dasdfmt, argv, "/dev/" + dasd])
             for line in buf.splitlines():
                 if line.startswith("Drive Geometry: "):
                     # line will look like this:
@@ -169,18 +168,7 @@ class DASD:
             arglist = argv + ["/dev/" + dasd]
 
             try:
-                if intf and self.totalCylinders:
-                    ret = iutil.execWithCallback(self.dasdfmt, arglist,
-                                                 callback=update,
-                                                 callback_data=pw,
-                                                 echo=False)
-                    rc = ret.rc
-                elif intf:
-                    ret = iutil.execWithPulseProgress(self.dasdfmt, arglist,
-                                                      progress=pw)
-                    rc = ret.rc
-                else:
-                    rc = iutil.execWithRedirect(self.dasdfmt, arglist)
+                rc = util.run_program([self.dasdfmt] + arglist)
             except Exception as e:
                 raise DasdFormatError(e, bypath)
 
diff --git a/pyanaconda/storage/devicelibs/btrfs.py b/pyanaconda/storage/devicelibs/btrfs.py
index b6d0e54..a6b69e3 100644
--- a/pyanaconda/storage/devicelibs/btrfs.py
+++ b/pyanaconda/storage/devicelibs/btrfs.py
@@ -23,7 +23,7 @@
 import os
 import re
 
-from pyanaconda import iutil
+from .. import util
 from ..errors import *
 
 import gettext
@@ -33,13 +33,14 @@ import logging
 log = logging.getLogger("storage")
 
 def btrfs(args, capture=False):
-    kwargs = {}
     if capture:
-        exec_func = iutil.execWithCapture
+        exec_func = util.capture_output
     else:
-        exec_func = iutil.execWithRedirect
+        exec_func = util.run_program
 
-    ret = exec_func("btrfs", args, **kwargs)
+    argv = ["btrfs"] + args
+
+    ret = exec_func(argv)
     if ret and not capture:
         raise BTRFSError(ret)
     return ret
@@ -63,7 +64,7 @@ def create_volume(devices, label=None, data=None, metadata=None):
 
     args.extend(devices)
 
-    ret = iutil.execWithRedirect("mkfs.btrfs", args)
+    ret = util.run_program(["mkfs.btrfs"] + args)
     if ret:
         raise BTRFSError(ret)
 
diff --git a/pyanaconda/storage/devicelibs/crypto.py b/pyanaconda/storage/devicelibs/crypto.py
index 92a22a8..2a41cdd 100644
--- a/pyanaconda/storage/devicelibs/crypto.py
+++ b/pyanaconda/storage/devicelibs/crypto.py
@@ -22,7 +22,6 @@
 
 import os
 from pycryptsetup import CryptSetup
-from pyanaconda import iutil
 
 from ..errors import *
 
diff --git a/pyanaconda/storage/devicelibs/dm.py b/pyanaconda/storage/devicelibs/dm.py
index b451890..e7adfec 100644
--- a/pyanaconda/storage/devicelibs/dm.py
+++ b/pyanaconda/storage/devicelibs/dm.py
@@ -23,7 +23,7 @@
 import os
 
 import block
-from pyanaconda import iutil
+from .. import util
 from ..errors import *
 
 import gettext
@@ -33,25 +33,18 @@ import logging
 log = logging.getLogger("storage")
 
 def dm_setup(args):
-    ret = iutil.execWithRedirect("dmsetup", args)
+    ret = util.run_program(["dmsetup"] + args)
     if ret:
-        raise DMError(ret.stderr)
+        raise DMError("Failed to run dmsetup %s" % " ".join(args))
 
 def dm_create_linear(map_name, device, length, uuid):
     table = "0 %d linear %s 0" % (length, device)
     args = ["create", map_name, "--uuid", uuid, "--table", "%s" % table]
-    try:
-        dm_setup(args)
-    except DMError as msg:
-        raise DMError("dm_create_linear (%s, %d, %s) failed: %s"
-                                % (map_name, length, device, msg))
+    dm_setup(args)
 
 def dm_remove(map_name):
     args = ["remove", map_name]
-    try:
-        dm_setup(args)
-    except DMError as msg:
-        raise DMError("dm_remove (%s) failed: %s" % (map_name, msg))
+    dm_setup(args)
 
 def name_from_dm_node(dm_node):
     # first, try sysfs
diff --git a/pyanaconda/storage/devicelibs/loop.py b/pyanaconda/storage/devicelibs/loop.py
index 92b3444..8a4750c 100644
--- a/pyanaconda/storage/devicelibs/loop.py
+++ b/pyanaconda/storage/devicelibs/loop.py
@@ -22,7 +22,7 @@
 
 import os
 
-from pyanaconda import iutil
+from .. import util
 from ..errors import *
 
 import gettext
@@ -34,15 +34,15 @@ log = logging.getLogger("storage")
 
 def losetup(args, capture=False):
     if capture:
-        exec_func = iutil.execWithCapture
+        exec_func = util.capture_output
     else:
-        exec_func = iutil.execWithRedirect
+        exec_func = util.run_program
 
     try:
         # ask losetup what this loop device's backing device is
-        ret = exec_func("losetup", args)
-    except RuntimeError as e:
-        raise LoopError(str(e))
+        ret = exec_func(["losetup"] + args)
+    except OSError as e:
+        raise LoopError(e.strerror)
 
     return ret
 
diff --git a/pyanaconda/storage/devicelibs/lvm.py b/pyanaconda/storage/devicelibs/lvm.py
index 2638ec7..7691993 100644
--- a/pyanaconda/storage/devicelibs/lvm.py
+++ b/pyanaconda/storage/devicelibs/lvm.py
@@ -24,12 +24,12 @@ import os
 import math
 import re
 
-from pyanaconda import iutil
 import logging
 log = logging.getLogger("storage")
 
+from .. import util
+from .. import arch
 from ..errors import *
-from pyanaconda.constants import *
 
 import gettext
 _ = lambda x: gettext.ldgettext("anaconda", x)
@@ -41,7 +41,7 @@ LVM_PE_START = 1.0      # MB
 LVM_PE_SIZE = 4.0       # MB
 
 def has_lvm():
-    if iutil.find_program_in_path("lvm"):
+    if util.find_program_in_path("lvm"):
         for line in open("/proc/devices").readlines():
             if "device-mapper" in line.split():
                 return True
@@ -134,7 +134,7 @@ def getPossiblePhysicalExtents(floor=0):
 
 def getMaxLVSize():
     """ Return the maximum size (in MB) of a logical volume. """
-    if iutil.getArch() in ("x86_64", "ppc64", "alpha", "ia64", "s390", "sparc"): #64bit architectures
+    if arch.getArch() in ("x86_64", "ppc64", "alpha", "ia64", "s390", "sparc"): #64bit architectures
         return (8*1024*1024*1024*1024) #Max is 8EiB (very large number..)
     else:
         return (16*1024*1024) #Max is 16TiB
@@ -158,7 +158,7 @@ def get_pv_space(size, disks, pesize=LVM_PE_SIZE,
     return space
 
 def lvm(args):
-    ret = iutil.execWithRedirect("lvm", args)
+    ret = util.run_program(["lvm"] + args)
     if ret:
         raise LVMError("running lvm " + " ".join(args) + " failed")
 
@@ -212,7 +212,7 @@ def pvinfo(device):
             config_args + \
             [device]
 
-    rc = iutil.execWithCapture("lvm", args)
+    rc = util.capture_output(["lvm"] + args)
     vals = rc.split()
     if not vals:
         raise LVMError("pvinfo failed for %s" % device)
@@ -299,7 +299,7 @@ def vginfo(vg_name):
             config_args + \
             [vg_name]
 
-    buf = iutil.execWithCapture("lvm", args)
+    buf = util.capture_output(["lvm"] + args)
     info = buf.split()
     if len(info) != 7:
         raise LVMError(_("vginfo failed for %s" % vg_name))
@@ -316,7 +316,7 @@ def lvs(vg_name):
             config_args + \
             [vg_name]
 
-    buf = iutil.execWithCapture("lvm", args)
+    buf = util.capture_output(["lvm"] + args)
 
     lvs = {}
     for line in buf.splitlines():
@@ -338,7 +338,7 @@ def lvorigin(vg_name, lv_name):
             config_args + \
             ["%s/%s" % (vg_name, lv_name)]
 
-    buf = iutil.execWithCapture("lvm", args)
+    buf = util.capture_output(["lvm"] + args)
 
     try:
         origin = buf.splitlines()[0].strip()
diff --git a/pyanaconda/storage/devicelibs/mdraid.py b/pyanaconda/storage/devicelibs/mdraid.py
index f8e93d5..ab18641 100644
--- a/pyanaconda/storage/devicelibs/mdraid.py
+++ b/pyanaconda/storage/devicelibs/mdraid.py
@@ -22,7 +22,7 @@
 
 import os
 
-from pyanaconda import iutil
+from .. import util
 from ..errors import *
 
 import gettext
@@ -169,7 +169,7 @@ def get_member_space(size, disks, level=None):
     return space * disks
 
 def mdadm(args):
-    ret = iutil.execWithRedirect("mdadm", args)
+    ret = util.run_program(["mdadm"] + args)
     if ret:
         raise MDRaidError("running mdadm " + " ".join(args) + " failed")
 
@@ -233,17 +233,17 @@ def mddeactivate(device):
         raise MDRaidError("mddeactivate failed for %s: %s" % (device, msg))
 
 def mdexamine(device):
-    vars = iutil.execWithCapture("mdadm",
-                                 ["--examine", "--brief", device]).split()
+    _vars = util.capture_output(["mdadm",
+                                 "--examine", "--brief", device]).split()
 
     info = {}
-    if len(vars) > 1 and vars[1].startswith("/dev/md"):
-        info["device"] = vars[1]
-        vars = vars[2:]
-    elif len(vars) > 1:
-        vars = vars[1:]
+    if len(_vars) > 1 and _vars[1].startswith("/dev/md"):
+        info["device"] = _vars[1]
+        _vars = _vars[2:]
+    elif len(_vars) > 1:
+        _vars = _vars[1:]
 
-    for var in vars:
+    for var in _vars:
         (name, equals, value) = var.partition("=")
         if not equals:
             continue
diff --git a/pyanaconda/storage/devicelibs/mpath.py b/pyanaconda/storage/devicelibs/mpath.py
index 2e5efd1..d49ab07 100644
--- a/pyanaconda/storage/devicelibs/mpath.py
+++ b/pyanaconda/storage/devicelibs/mpath.py
@@ -2,9 +2,9 @@
 import re
 
 from ..udev import udev_device_is_disk
-from pyanaconda import iutil
-from pyanaconda.flags import flags
-from pyanaconda.anaconda_log import log_method_call
+from .. import util
+from ..flags import flags
+from ..storage_log import log_method_call
 
 import logging
 log = logging.getLogger("storage")
@@ -106,9 +106,9 @@ class MultipathTopology(object):
             map(lambda line: log.debug(line.rstrip()), conf)
             log.debug("(end of /etc/multipath.conf)")
         self._mpath_topology = parseMultipathOutput(
-            iutil.execWithCapture("multipath", ["-d",]))
+            util.capture_output(["multipath", "-d"]))
         self._mpath_topology.update(parseMultipathOutput(
-                iutil.execWithCapture("multipath", ["-ll",])))
+            util.capture_output(["multipath", "-ll"])))
 
         delete_keys = []
         for (mp, disks) in self._mpath_topology.items():
@@ -268,7 +268,7 @@ blacklist {
         return ret
 
     def writeConfig(self, friendly_names=True):
-        if not flags.mpath:
+        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
@@ -279,7 +279,7 @@ blacklist {
             mpath_cfg.write(cfg)
 
 def flush_mpaths():
-    iutil.execWithRedirect("multipath", ["-F"])
-    check_output = iutil.execWithCapture("multipath", ["-ll"]).strip()
+    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")
diff --git a/pyanaconda/storage/devicelibs/swap.py b/pyanaconda/storage/devicelibs/swap.py
index b96aefe..4c9490a 100644
--- a/pyanaconda/storage/devicelibs/swap.py
+++ b/pyanaconda/storage/devicelibs/swap.py
@@ -21,18 +21,17 @@
 #
 
 import resource
-
-from pyanaconda import iutil
 import os
 
 from ..errors import *
+from .. import util
 from . import dm
 
 import gettext
 _ = lambda x: gettext.ldgettext("anaconda", x)
 
 import logging
-log = logging.getLogger("anaconda")
+log = logging.getLogger("storage")
 
 def mkswap(device, label=''):
     # We use -f to force since mkswap tends to refuse creation on lvs with
@@ -42,7 +41,7 @@ def mkswap(device, label=''):
         argv.extend(["-L", label])
     argv.append(device)
 
-    ret = iutil.execWithRedirect("mkswap", argv)
+    ret = util.run_program(["mkswap"] + argv)
 
     if ret:
         raise SwapError("mkswap failed for '%s'" % device)
@@ -83,13 +82,13 @@ def swapon(device, priority=None):
         argv.extend(["-p", "%d" % priority])
     argv.append(device)
         
-    rc = iutil.execWithRedirect("swapon", argv)
+    rc = util.run_program(["swapon"] + argv)
 
     if rc:
         raise SwapError("swapon failed for '%s'" % device)
 
 def swapoff(device):
-    rc = iutil.execWithRedirect("swapoff", [device])
+    rc = util.run_program(["swapoff", device])
 
     if rc:
         raise SwapError("swapoff failed for '%s'" % device)
@@ -127,7 +126,7 @@ def swapSuggestion(quiet=False, hibernation=False):
 
     """
 
-    mem = iutil.memInstalled()/1024
+    mem = util.total_memory()/1024
     mem = ((mem/16)+1)*16
     if not quiet:
         log.info("Detected %sM of memory", mem)
diff --git a/pyanaconda/storage/devices.py b/pyanaconda/storage/devices.py
index d3897d0..56f871a 100644
--- a/pyanaconda/storage/devices.py
+++ b/pyanaconda/storage/devices.py
@@ -111,9 +111,10 @@ import _ped
 import block
 
 from errors import *
-from pyanaconda.iutil import notify_kernel, numeric_type
-from pyanaconda.flags import flags
-from pyanaconda.anaconda_log import log_method_call
+import util
+import arch
+from flags import flags
+from storage_log import log_method_call
 from udev import *
 from formats import get_device_format_class, getFormat, DeviceFormat
 
@@ -474,9 +475,9 @@ class StorageDevice(Device):
 
         self.uuid = uuid
         self._format = None
-        self._size = numeric_type(size)
-        self.major = numeric_type(major)
-        self.minor = numeric_type(minor)
+        self._size = util.numeric_type(size)
+        self.major = util.numeric_type(major)
+        self.minor = util.numeric_type(minor)
         self.sysfsPath = sysfsPath
         self._serial = serial
         self._vendor = vendor
@@ -665,7 +666,7 @@ class StorageDevice(Device):
 
         path = os.path.normpath("/sys/%s" % self.sysfsPath)
         try:
-            notify_kernel(path, action="change")
+            util.notify_kernel(path, action="change")
         except (ValueError, IOError) as e:
             log.warning("failed to notify kernel of change: %s" % e)
 
@@ -1169,7 +1170,7 @@ class PartitionDevice(StorageDevice):
             self.req_name = name
             self.req_partType = partType
             self.req_primary = primary
-            self.req_max_size = numeric_type(maxsize)
+            self.req_max_size = util.numeric_type(maxsize)
             self.req_grow = grow
             self.req_bootable = bootable
 
@@ -1376,7 +1377,7 @@ class PartitionDevice(StorageDevice):
     def _setBootable(self, bootable):
         """ Set the bootable flag for this partition. """
         if self.partedPartition:
-            if iutil.isS390():
+            if arch.isS390():
                 return
             if self.flagAvailable(parted.PARTITION_BOOT):
                 if bootable:
@@ -1765,16 +1766,14 @@ class DMDevice(StorageDevice):
 
     def setupPartitions(self):
         log_method_call(self, name=self.name, kids=self.kids)
-        rc = iutil.execWithRedirect("kpartx",
-                                ["-a", "-s", self.path])
+        rc = util.run_program(["kpartx", "-a", "-s", self.path])
         if rc:
             raise DMError("partition activation failed for '%s'" % self.name)
         udev_settle()
 
     def teardownPartitions(self):
         log_method_call(self, name=self.name, kids=self.kids)
-        rc = iutil.execWithRedirect("kpartx",
-                                ["-d", "-s", self.path])
+        rc = util.run_program(["kpartx", "-d", "-s", self.path])
         if rc:
             raise DMError("partition deactivation failed for '%s'" % self.name)
         udev_settle()
@@ -1985,11 +1984,11 @@ class LVMVolumeGroupDevice(DMDevice):
                           exists=exists, sysfsPath=sysfsPath)
 
         self.uuid = uuid
-        self.free = numeric_type(free)
-        self.peSize = numeric_type(peSize)
-        self.peCount = numeric_type(peCount)
-        self.peFree = numeric_type(peFree)
-        self.pvCount = numeric_type(pvCount)
+        self.free = util.numeric_type(free)
+        self.peSize = util.numeric_type(peSize)
+        self.peCount = util.numeric_type(peCount)
+        self.peFree = util.numeric_type(peFree)
+        self.pvCount = util.numeric_type(pvCount)
         self.lv_names = []
         self.lv_uuids = []
         self.lv_sizes = []
@@ -2321,7 +2320,7 @@ class LVMVolumeGroupDevice(DMDevice):
 
     def align(self, size, roundup=None):
         """ Align a size to a multiple of physical extent size. """
-        size = numeric_type(size)
+        size = util.numeric_type(size)
 
         if roundup:
             round = math.ceil
@@ -2425,10 +2424,10 @@ class LVMLogicalVolumeDevice(DMDevice):
 
         if not self.exists:
             self.req_grow = grow
-            self.req_max_size = numeric_type(maxsize)
+            self.req_max_size = util.numeric_type(maxsize)
             # XXX should we enforce that req_size be pe-aligned?
             self.req_size = self._size
-            self.req_percent = numeric_type(percent)
+            self.req_percent = util.numeric_type(percent)
 
         if self.singlePV:
             # make sure there is at least one PV that can hold this LV
@@ -2471,7 +2470,7 @@ class LVMLogicalVolumeDevice(DMDevice):
         return self.stripes > 1
 
     def _setSize(self, size):
-        size = self.vg.align(numeric_type(size))
+        size = self.vg.align(util.numeric_type(size))
         log.debug("trying to set lv %s size to %dMB" % (self.name, size))
         if size <= self.vg.freeSpace + self.vgSpaceUsed:
             self._size = size
@@ -2671,8 +2670,8 @@ class MDRaidArrayDevice(StorageDevice):
                                  {"raidLevel": self.level, "minMembers": mdraid.get_raid_min_members(self.level)}
 
         self.uuid = uuid
-        self._totalDevices = numeric_type(totalDevices)
-        self._memberDevices = numeric_type(memberDevices)
+        self._totalDevices = util.numeric_type(totalDevices)
+        self._memberDevices = util.numeric_type(memberDevices)
 
         self.chunkSize = 512.0 / 1024.0         # chunk size in MB
 
@@ -3372,8 +3371,7 @@ class MultipathDevice(DMDevice):
         """
         if self.exists and os.path.exists(self.path):
             #self.teardownPartitions()
-            #rc = iutil.execWithRedirect("multipath",
-            #                    ['-f', self.name])
+            #rc = util.run_program(["multipath", '-f', self.name])
             #if rc:
             #    raise MPathError("multipath deactivation failed for '%s'" %
             #                    self.name)
@@ -3392,8 +3390,7 @@ class MultipathDevice(DMDevice):
         log_method_call(self, self.name, orig=orig, status=self.status,
                         controllable=self.controllable)
         udev_settle()
-        rc = iutil.execWithRedirect("multipath",
-                            [self.name])
+        rc = util.run_program(["multipath", self.name])
         if rc:
             raise MPathError("multipath activation failed for '%s'" %
                             self.name, hardware_fault=True)
@@ -3555,7 +3552,7 @@ class DirectoryDevice(FileDevice):
     def _create(self):
         """ Create the device. """
         log_method_call(self, self.name, status=self.status)
-        iutil.mkdirChain(self.path)
+        util.makedirs(self.path)
 
 
 class LoopDevice(StorageDevice):
@@ -3775,8 +3772,6 @@ class OpticalDevice(StorageDevice):
 
     def eject(self):
         """ Eject the drawer. """
-        from pyanaconda import _isys
-
         log_method_call(self, self.name, status=self.status)
         if not self.exists:
             raise DeviceError("device has not been created", self.name)
@@ -3788,17 +3783,11 @@ class OpticalDevice(StorageDevice):
             log.info("noeject in effect, not ejecting cdrom")
             return
 
-        # Make a best effort attempt to do the eject.  If it fails, it's not
-        # critical.
-        fd = os.open(self.path, os.O_RDONLY | os.O_NONBLOCK)
-
         try:
-            _isys.ejectcdrom(fd)
-        except SystemError as e:
+            util.run_program(["eject", self.name]) 
+        except OSError as e:
             log.warning("error ejecting cdrom %s: %s" % (self.name, e))
 
-        os.close(fd)
-
 
 class ZFCPDiskDevice(DiskDevice):
     """ A mainframe ZFCP disk. """
diff --git a/pyanaconda/storage/devicetree.py b/pyanaconda/storage/devicetree.py
index 578671f..0a5e7cd 100644
--- a/pyanaconda/storage/devicetree.py
+++ b/pyanaconda/storage/devicetree.py
@@ -40,11 +40,11 @@ import devicelibs.mpath
 import devicelibs.loop
 import devicelibs.edd
 from udev import *
-from pyanaconda import iutil
+import util
 from pyanaconda import platform
 from pyanaconda import tsort
-from pyanaconda.flags import flags
-from pyanaconda.anaconda_log import log_method_call, log_method_return
+from flags import flags
+from storage_log import log_method_call, log_method_return
 import parted
 import _ped
 
@@ -534,7 +534,7 @@ class DeviceTree(object):
              udev_device_is_dm_crypt(info) or
              (udev_device_is_md(info) and not
               udev_device_get_md_container(info)))):
-            if iutil.get_sysfs_attr(info["sysfs_path"], 'ro') == '1':
+            if util.get_sysfs_attr(info["sysfs_path"], 'ro') == '1':
                 log.debug("Ignoring read only device %s" % name)
                 self.addIgnoredDisk(name)
                 return True
@@ -1599,7 +1599,7 @@ class DeviceTree(object):
     def updateDeviceFormat(self, device):
         log.info("updating format of device: %s" % device)
         try:
-            iutil.notify_kernel("/sys%s" % device.sysfsPath)
+            util.notify_kernel("/sys%s" % device.sysfsPath)
         except (ValueError, IOError) as e:
             log.warning("failed to notify kernel of change: %s" % e)
 
@@ -2189,10 +2189,10 @@ class DeviceTree(object):
             attr = None
             if "subvol=" in options:
                 attr = "name"
-                val = iutil.get_option_value("subvol", options)
+                val = util.get_option_value("subvol", options)
             elif "subvolid=" in options:
                 attr = "vol_id"
-                val = iutil.get_option_value("subvolid", options)
+                val = util.get_option_value("subvolid", options)
 
             if attr and val:
                 for subvol in device.subvolumes:
diff --git a/pyanaconda/storage/fcoe.py b/pyanaconda/storage/fcoe.py
index e839f10..3a4d147 100644
--- a/pyanaconda/storage/fcoe.py
+++ b/pyanaconda/storage/fcoe.py
@@ -18,13 +18,13 @@
 #
 
 import os
-from pyanaconda import iutil
+from . import util
+from pyanaconda.baseudev import udev_settle
 from pyanaconda import isys
 from pyanaconda.constants import ROOT_PATH
 import logging
 import time
-from pyanaconda.flags import flags
-log = logging.getLogger("anaconda")
+log = logging.getLogger("storage")
 
 import gettext
 _ = lambda x: gettext.ldgettext("anaconda", x)
@@ -34,11 +34,11 @@ _fcoe_module_loaded = False
 def has_fcoe():
     global _fcoe_module_loaded
     if not _fcoe_module_loaded:
-        iutil.execWithRedirect("modprobe", [ "fcoe" ])
+        util.run_program(["modprobe", "fcoe"])
         _fcoe_module_loaded = True
-        if "bnx2x" in iutil.lsmod():
+        if "bnx2x" in util.lsmod():
             log.info("fcoe: loading bnx2fc")
-            iutil.execWithRedirect("modprobe", [ "bnx2fc" ])
+            util.run_program(["modprobe", "bnx2fc"])
 
     return os.access("/sys/module/fcoe", os.X_OK)
 
@@ -67,10 +67,10 @@ class fcoe(object):
     def _stabilize(self):
         # I have no clue how long we need to wait, this ought to do the trick
         time.sleep(10)
-        iutil.execWithRedirect("udevadm", [ "settle" ])
+        udev_settle()
 
     def _startEDD(self):
-        rc = iutil.execWithCapture("/usr/libexec/fcoe/fcoe_edd.sh", [ "-i" ])
+        rc = util.capture_output(["/usr/libexec/fcoe/fcoe_edd.sh", "-i"])
         if not rc.startswith("NIC="):
             log.info("No FCoE EDD info found: %s" % rc.rstrip())
             return
@@ -97,7 +97,7 @@ class fcoe(object):
         if self.lldpadStarted:
             return
 
-        iutil.execWithRedirect("lldpad", [ "-d" ])
+        util.run_program(["lldpad", "-d"])
         self.lldpadStarted = True
 
     def addSan(self, nic, dcb=False, auto_vlan=True):
@@ -107,20 +107,20 @@ class fcoe(object):
         log.info("Activating FCoE SAN attached to %s, dcb: %s autovlan: %s" %
                  (nic, dcb, auto_vlan))
 
-        iutil.execWithRedirect("ip", [ "link", "set", nic, "up" ])
+        util.run_program(["ip", "link", "set", nic, "up"])
 
         if dcb:
             self._startLldpad()
-            iutil.execWithRedirect("dcbtool", [ "sc", nic, "dcb", "on" ])
-            iutil.execWithRedirect("dcbtool", [ "sc", nic, "app:fcoe",
-                                                "e:1", "a:1", "w:1" ])
-            iutil.execWithRedirect("fipvlan", [ "-c", "-s", "-f",
+            util.run_program(["dcbtool", "sc", nic, "dcb", "on"])
+            util.run_program(["dcbtool", "sc", nic, "app:fcoe",
+                                                "e:1", "a:1", "w:1"])
+            util.run_program(["fipvlan", "-c", "-s", "-f",
                                                "'-fcoe'", nic])
         else:
             if auto_vlan:
                 # certain network configrations require the VLAN layer module:
-                iutil.execWithRedirect("modprobe", ["8021q"])
-                iutil.execWithRedirect("fipvlan", ['-c', '-s', '-f',
+                util.run_program(["modprobe", "8021q"])
+                util.run_program(["fipvlan", '-c', '-s', '-f',
                                                    "'-fcoe'",  nic])
             else:
                 f = open("/sys/module/libfcoe/parameters/create", "w")
diff --git a/pyanaconda/storage/flags.py b/pyanaconda/storage/flags.py
new file mode 100644
index 0000000..ed0e5dc
--- /dev/null
+++ b/pyanaconda/storage/flags.py
@@ -0,0 +1,98 @@
+# flags.py
+#
+# Copyright (C) 2013  Red Hat, Inc.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions of
+# the GNU General Public License v.2, or (at your option) any later version.
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY expressed or implied, including the implied warranties 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, write to the
+# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.  Any Red Hat trademarks that are incorporated in the
+# source code or documentation are not subject to the GNU General Public
+# License and may only be used or replicated with the express permission of
+# Red Hat, Inc.
+#
+# Red Hat Author(s): David Lehman <dlehman@redhat.com>
+#
+
+import shlex
+import selinux
+
+class Flags(object):
+    def __init__(self):
+        #
+        # mode of operation
+        #
+        self.testing = False
+        self.installer_mode = False
+
+        #
+        # minor modes (installer-specific)
+        #
+        self.automated_install = False
+        self.live_install = False
+        self.image_install = False
+
+        #
+        # enable/disable functionality
+        #
+        self.selinux = selinux.is_selinux_enabled()
+        self.multipath = True
+        self.dmraid = True
+        self.ibft = False
+        self.noiswmd = False
+
+        self.gfs2 = True
+        self.jfs = True
+        self.reiserfs = True
+
+        self.arm_platform = None
+
+        self.gpt = False
+
+        self.boot_cmdline = {}
+
+        self.update_from_boot_cmdline()
+
+    def get_boot_cmdline(self):
+        buf = open("/proc/cmdline").read().strip()
+        args = shlex.split(buf)
+        for arg in args:
+            (opt, equals, val) = arg.partition("=")
+            self.boot_cmdline[opt] = val
+
+    def update_from_boot_cmdline(self):
+        self.get_boot_cmdline()
+        if "nompath" in self.boot_cmdline:
+            self.multipath = False
+
+        if "nodmraid" in self.boot_cmdline:
+            self.dmraid = False
+
+        if "ibft" in self.boot_cmdline:
+            self.ibft = True
+
+        if "noiswmd" in self.boot_cmdline:
+            self.noiswmd = True
+
+    def update_from_anaconda_flags(self, anaconda_flags):
+        self.installer_mode = True
+        self.testing = anaconda_flags.testing
+        self.automated_install = anaconda_flags.automatedInstall
+        self.live_install = anaconda_flags.livecdInstall
+
+        self.selinux = anaconda_flags.selinux
+
+        self.gfs2 = "gfs2" in self.boot_cmdline
+        self.jfs = "jfs" in self.boot_cmdline
+        self.reiserfs = "reiserfs" in self.boot_cmdline
+
+        self.arm_platform = anaconda_flags.armPlatform
+        self.gpt = anaconda_flags.gpt
+
+
+flags = Flags()
diff --git a/pyanaconda/storage/formats/__init__.py b/pyanaconda/storage/formats/__init__.py
index 532855a..62bfb31 100644
--- a/pyanaconda/storage/formats/__init__.py
+++ b/pyanaconda/storage/formats/__init__.py
@@ -24,10 +24,10 @@ import os
 
 from pyanaconda.product import productName
 from pyanaconda.baseudev import udev_get_device
-from pyanaconda.iutil import notify_kernel
-from pyanaconda.iutil import get_sysfs_path_by_name
-from pyanaconda.iutil import execWithRedirect
-from pyanaconda.anaconda_log import log_method_call
+from ..util import notify_kernel
+from ..util import get_sysfs_path_by_name
+from ..util import run_program
+from ..storage_log import log_method_call
 from ..errors import *
 from ..devicelibs.dm import dm_node_from_name
 from ..devicelibs.mdraid import md_node_from_name
@@ -309,8 +309,8 @@ class DeviceFormat(object):
         log_method_call(self, device=self.device,
                         type=self.type, status=self.status)
         try:
-            rc = execWithRedirect("wipefs", ["-a", self.device])
-        except Exception as e:
+            rc = run_program(["wipefs", "-a", self.device])
+        except OSError as e:
             err = str(e)
         else:
             err = ""
diff --git a/pyanaconda/storage/formats/disklabel.py b/pyanaconda/storage/formats/disklabel.py
index 7a8c18b..018adf4 100644
--- a/pyanaconda/storage/formats/disklabel.py
+++ b/pyanaconda/storage/formats/disklabel.py
@@ -23,13 +23,12 @@
 import os
 import copy
 
-from pyanaconda.flags import flags
-
-from pyanaconda.anaconda_log import log_method_call
-from pyanaconda import iutil
+from ..storage_log import log_method_call
 import parted
 import _ped
 from ..errors import *
+from .. import arch
+from ..flags import flags
 from ..udev import udev_settle
 from . import DeviceFormat, register_device_format
 
@@ -172,7 +171,7 @@ class DiskLabel(DeviceFormat):
             # Set the boot flag on the GPT PMBR, this helps some BIOS systems boot
             if self._partedDisk.isFlagAvailable(parted.DISK_GPT_PMBR_BOOT):
                 # MAC can boot as EFI or as BIOS, neither should have PMBR boot set
-                if iutil.isEfi() or iutil.isMactel():
+                if arch.isEfi() or arch.isMactel():
                     self._partedDisk.unsetFlag(parted.DISK_GPT_PMBR_BOOT)
                     log.debug("Clear pmbr_boot on %s" % (self._partedDisk,))
                 else:
diff --git a/pyanaconda/storage/formats/dmraid.py b/pyanaconda/storage/formats/dmraid.py
index 37624af..f37b2d3 100644
--- a/pyanaconda/storage/formats/dmraid.py
+++ b/pyanaconda/storage/formats/dmraid.py
@@ -20,8 +20,8 @@
 # Red Hat Author(s): Dave Lehman <dlehman@redhat.com>
 #
 
-from pyanaconda.anaconda_log import log_method_call
-from pyanaconda.flags import flags
+from ..storage_log import log_method_call
+from ..flags import flags
 from ..errors import *
 from . import DeviceFormat, register_device_format
 
@@ -102,12 +102,12 @@ class DMRaidMember(DeviceFormat):
         raise DMRaidMemberError("destruction of dmraid members is non-sense")
 
 
-if not flags.cmdline.has_key("noiswmd"):
+if not flags.noiswmd:
     DMRaidMember._udevTypes.remove("isw_raid_member")
 
 # The anaconda cmdline has not been parsed yet when we're first imported,
 # so we can not use flags.dmraid here
-if flags.cmdline.has_key("nodmraid"):
+if not flags.dmraid:
     DMRaidMember._udevTypes = []
 
 register_device_format(DMRaidMember)
diff --git a/pyanaconda/storage/formats/fs.py b/pyanaconda/storage/formats/fs.py
index 80c3e09..1d355c3 100644
--- a/pyanaconda/storage/formats/fs.py
+++ b/pyanaconda/storage/formats/fs.py
@@ -31,14 +31,13 @@ import os
 import sys
 import tempfile
 import selinux
-from pyanaconda import isys
 
 from ..errors import *
 from . import DeviceFormat, register_device_format
-from pyanaconda import iutil
-from pyanaconda.flags import flags
+from .. import util
+from ..flags import flags
 from parted import fileSystemType
-from pyanaconda.anaconda_log import log_method_call
+from ..storage_log import log_method_call
 
 import logging
 log = logging.getLogger("storage")
@@ -255,12 +254,12 @@ class FS(DeviceFormat):
         size = self._size
 
         if self.infofsProg and self.exists and not size and \
-           iutil.find_program_in_path(self.infofsProg):
+           util.find_program_in_path(self.infofsProg):
             try:
                 values = []
                 argv = self._defaultInfoOptions + [ self.device ]
 
-                buf = iutil.execWithCapture(self.infofsProg, argv)
+                buf = util.capture_output([self.infofsProg] + argv)
 
                 for line in buf.splitlines():
                     found = False
@@ -363,8 +362,8 @@ class FS(DeviceFormat):
         argv = self._getFormatOptions(options=options)
 
         try:
-            ret = iutil.execWithRedirect(self.mkfsProg, argv)
-        except Exception as e:
+            ret = util.run_program([self.mkfsProg] + argv)
+        except OSError as e:
             raise FormatCreateError(e, self.device)
 
         if ret:
@@ -416,9 +415,8 @@ class FS(DeviceFormat):
             log.info("Minimum size changed, setting targetSize on %s to %s" \
                      % (self.device, self.targetSize))
         try:
-            ret = iutil.execWithRedirect(self.resizefsProg,
-                                         self.resizeArgs)
-        except Exception as e:
+            ret = util.run_program([self.resizefsProg] + self.resizeArgs)
+        except OSError as e:
             raise FSResizeError(e, self.device)
 
         if ret:
@@ -453,9 +451,8 @@ class FS(DeviceFormat):
             raise FSError("device does not exist")
 
         try:
-            ret = iutil.execWithRedirect(self.fsckProg,
-                                         self._getCheckArgs())
-        except Exception as e:
+            ret = util.run_program([self.fsckProg] + self._getCheckArgs())
+        except OSError as e:
             raise FSError("filesystem check failed: %s" % e)
 
         if self._fsckFailed(ret):
@@ -474,8 +471,8 @@ class FS(DeviceFormat):
 
         for module in self._modules:
             try:
-                rc = iutil.execWithRedirect("modprobe", [module])
-            except Exception as e:
+                rc = util.run_program(["modprobe", module])
+            except OSError as e:
                 log.error("Could not load kernel module %s: %s" % (module, e))
                 self._supported = False
                 return
@@ -551,9 +548,9 @@ class FS(DeviceFormat):
         #
         #mountpoint = os.path.join(chroot, mountpoint)
         chrootedMountpoint = os.path.normpath("%s/%s" % (chroot, mountpoint))
-        iutil.mkdirChain(chrootedMountpoint)
+        util.makedirs(chrootedMountpoint)
         if flags.selinux:
-            ret = isys.resetFileContext(mountpoint, chroot)
+            ret = util.reset_file_context(mountpoint, chroot)
             log.info("set SELinux context for mountpoint %s to %s" \
                      % (mountpoint, ret))
 
@@ -561,11 +558,13 @@ class FS(DeviceFormat):
         if not options or not isinstance(options, str):
             options = self.options
 
+        if isinstance(self, BindFS):
+            options = "bind," + options
+
         try: 
-            rc = isys.mount(self.device, chrootedMountpoint, 
+            rc = util.mount(self.device, chrootedMountpoint,
                             fstype=self.mountType,
-                            options=options,
-                            bindMount=isinstance(self, BindFS))
+                            options=options)
         except Exception as e:
             raise FSError("mount failed: %s" % e)
 
@@ -573,11 +572,11 @@ class FS(DeviceFormat):
             raise FSError("mount failed: %s" % rc)
 
         if flags.selinux and "ro" not in options.split(","):
-            ret = isys.resetFileContext(mountpoint, chroot)
+            ret = util.reset_file_context(mountpoint, chroot)
             log.info("set SELinux context for newly mounted filesystem "
                      "root at %s to %s" %(mountpoint, ret))
-            isys.setFileContext("%s/lost+found" % mountpoint,
-                                lost_and_found_context, chroot)
+            util.set_file_context("%s/lost+found" % mountpoint,
+                               lost_and_found_context, chroot)
 
         self._mountpoint = chrootedMountpoint
 
@@ -593,7 +592,7 @@ class FS(DeviceFormat):
         if not os.path.exists(self._mountpoint):
             raise FSError("mountpoint does not exist")
 
-        rc = isys.umount(self._mountpoint, removeDir = False)
+        rc = util.umount(self._mountpoint)
         if rc:
             raise FSError("umount failed")
 
@@ -617,7 +616,7 @@ class FS(DeviceFormat):
             raise FSError("device does not exist")
 
         argv = self._getLabelArgs(label)
-        rc = iutil.execWithRedirect(self.labelfsProg, argv)
+        rc = util.run_program([self.labelfsProg] + argv)
         if rc:
             raise FSError("label failed")
 
@@ -625,7 +624,7 @@ class FS(DeviceFormat):
         self.notifyKernel()
 
     def _getRandomUUID(self):
-        uuid = iutil.execWithCapture("uuidgen", []).strip()
+        uuid = util.capture_output(["uuidgen"]).strip()
         return uuid
 
     def writeRandomUUID(self):
@@ -668,7 +667,7 @@ class FS(DeviceFormat):
             if not prog:
                 continue
 
-            if not iutil.find_program_in_path(prog):
+            if not util.find_program_in_path(prog):
                 return False
 
         return True
@@ -830,11 +829,8 @@ class Ext2FS(FS):
 
         err = None
         try:
-            rc = iutil.execWithRedirect("tune2fs",
-                                        ["-U",
-                                         "random",
-                                         self.device])
-        except Exception as e:
+            rc = util.run_program(["tune2fs", "-U", "random", self.device])
+        except OSError as e:
             err = str(e)
         else:
             if rc:
@@ -854,8 +850,7 @@ class Ext2FS(FS):
 
             if self.exists and os.path.exists(self.device):
                 # get block size
-                buf = iutil.execWithCapture(self.infofsProg,
-                                            ["-h", self.device])
+                buf = util.capture_output([self.infofsProg, "-h", self.device])
                 for line in buf.splitlines():
                     if line.startswith("Block size:"):
                         blockSize = int(line.split(" ")[-1])
@@ -869,8 +864,8 @@ class Ext2FS(FS):
                                   "on %s" % (self.mountType, self.device))
 
                 # get minimum size according to resize2fs
-                buf = iutil.execWithCapture(self.resizefsProg,
-                                            ["-P", self.device])
+                buf = util.capture_output([self.resizefsProg,
+                                           "-P", self.device])
                 for line in buf.splitlines():
                     if "minimum size of the filesystem:" not in line:
                         continue
@@ -1067,7 +1062,7 @@ class GFS2(FS):
     def supported(self):
         """ Is this filesystem a supported type? """
         supported = self._supported
-        if flags.cmdline.has_key("gfs2"):
+        if flags.gfs2:
             supported = self.utilsAvailable
 
         return supported
@@ -1099,7 +1094,7 @@ class JFS(FS):
     def supported(self):
         """ Is this filesystem a supported type? """
         supported = self._supported
-        if flags.cmdline.has_key("jfs"):
+        if flags.jfs:
             supported = self.utilsAvailable
 
         return supported
@@ -1133,7 +1128,7 @@ class ReiserFS(FS):
     def supported(self):
         """ Is this filesystem a supported type? """
         supported = self._supported
-        if flags.cmdline.has_key("reiserfs"):
+        if flags.reiserfs:
             supported = self.utilsAvailable
 
         return supported
@@ -1184,15 +1179,13 @@ class XFS(FS):
             return
 
         try:
-            iutil.execWithRedirect("xfs_freeze", ["-f", self.mountpoint],
-                                   root=root)
-        except (RuntimeError, OSError) as e:
+            util.run_program(["xfs_freeze", "-f", self.mountpoint], root=root)
+        except OSError as e:
             log.error("failed to run xfs_freeze: %s" % e)
 
         try:
-            iutil.execWithRedirect("xfs_freeze", ["-u", self.mountpoint],
-                                   root=root)
-        except (RuntimeError, OSError) as e:
+            util.run_program(["xfs_freeze", "-u", self.mountpoint], root=root)
+        except OSError as e:
             log.error("failed to run xfs_freeze: %s" % e)
 
 register_device_format(XFS)
@@ -1273,10 +1266,9 @@ class NTFS(FS):
             # we try one time to determine the minimum size.
             size = self._minSize
             if self.exists and os.path.exists(self.device) and \
-               iutil.find_program_in_path(self.resizefsProg):
+               util.find_program_in_path(self.resizefsProg):
                 minSize = None
-                buf = iutil.execWithCapture(self.resizefsProg,
-                                            ["-m", self.device])
+                buf = util.run_program([self.resizefsProg, "-m", self.device])
                 for l in buf.split("\n"):
                     if not l.startswith("Minsize"):
                         continue
diff --git a/pyanaconda/storage/formats/luks.py b/pyanaconda/storage/formats/luks.py
index 6bb8b64..4b37cb4 100644
--- a/pyanaconda/storage/formats/luks.py
+++ b/pyanaconda/storage/formats/luks.py
@@ -29,7 +29,7 @@ try:
 except ImportError:
     volume_key = None
 
-from pyanaconda.anaconda_log import log_method_call
+from ..storage_log import log_method_call
 from ..errors import *
 from ..devicelibs import crypto
 from . import DeviceFormat, register_device_format
diff --git a/pyanaconda/storage/formats/lvmpv.py b/pyanaconda/storage/formats/lvmpv.py
index 018d186..d804711 100644
--- a/pyanaconda/storage/formats/lvmpv.py
+++ b/pyanaconda/storage/formats/lvmpv.py
@@ -22,7 +22,7 @@
 
 import os
 
-from pyanaconda.anaconda_log import log_method_call
+from ..storage_log import log_method_call
 from parted import PARTITION_LVM
 from ..errors import *
 from ..devicelibs import lvm
diff --git a/pyanaconda/storage/formats/mdraid.py b/pyanaconda/storage/formats/mdraid.py
index c543434..9d1e26e 100644
--- a/pyanaconda/storage/formats/mdraid.py
+++ b/pyanaconda/storage/formats/mdraid.py
@@ -22,12 +22,12 @@
 
 import os
 
-from pyanaconda.anaconda_log import log_method_call
-from pyanaconda.flags import flags
+from ..storage_log import log_method_call
 from parted import PARTITION_RAID
 from ..errors import *
 from ..devicelibs import mdraid
 from . import DeviceFormat, register_device_format
+from ..flags import flags
 
 import gettext
 _ = lambda x: gettext.ldgettext("anaconda", x)
@@ -113,8 +113,7 @@ class MDRaidMember(DeviceFormat):
 # nodmraid -> Wether to use BIOS RAID or not
 # Note the anaconda cmdline has not been parsed yet when we're first imported,
 # so we can not use flags.dmraid here
-if not flags.cmdline.has_key("noiswmd") and \
-   not flags.cmdline.has_key("nodmraid"):
+if not flags.noiswmd and flags.dmraid:
     MDRaidMember._udevTypes.append("isw_raid_member")
 
 register_device_format(MDRaidMember)
diff --git a/pyanaconda/storage/formats/multipath.py b/pyanaconda/storage/formats/multipath.py
index b77de20..01d69ee 100644
--- a/pyanaconda/storage/formats/multipath.py
+++ b/pyanaconda/storage/formats/multipath.py
@@ -24,7 +24,7 @@
 # Red Hat Author(s): Peter Jones <pjones@redhat.com>
 #
 
-from pyanaconda.anaconda_log import log_method_call
+from ..storage_log import log_method_call
 from ..errors import *
 from . import DeviceFormat, register_device_format
 
diff --git a/pyanaconda/storage/formats/swap.py b/pyanaconda/storage/formats/swap.py
index 2267d68..903fe6e 100644
--- a/pyanaconda/storage/formats/swap.py
+++ b/pyanaconda/storage/formats/swap.py
@@ -20,10 +20,10 @@
 # Red Hat Author(s): Dave Lehman <dlehman@redhat.com>
 #
 
-from pyanaconda.iutil import numeric_type
 from parted import PARTITION_SWAP, fileSystemType
-from pyanaconda.anaconda_log import log_method_call
+from ..storage_log import log_method_call
 from ..errors import *
+from ..util import numeric_type
 from ..devicelibs import swap
 from . import DeviceFormat, register_device_format
 
diff --git a/pyanaconda/storage/iscsi.py b/pyanaconda/storage/iscsi.py
index 78ce1a6..4e64335 100644
--- a/pyanaconda/storage/iscsi.py
+++ b/pyanaconda/storage/iscsi.py
@@ -19,17 +19,17 @@
 #
 
 from pyanaconda.constants import *
-from udev import *
+from udev import udev_settle
+from . import util
+from .flags import flags
 import os
-from pyanaconda import iutil
-from pyanaconda.flags import flags
 import logging
 import shutil
 import time
 import hashlib
 import random
 import itertools
-log = logging.getLogger("anaconda")
+log = logging.getLogger("storage")
 
 import gettext
 _ = lambda x: gettext.ldgettext("anaconda", x)
@@ -53,7 +53,7 @@ def has_iscsi():
         return False
 
     if not ISCSID:
-        location = iutil.find_program_in_path("iscsid")
+        location = util.find_program_in_path("iscsid")
         if not location:
             return False
         ISCSID = location
@@ -197,13 +197,12 @@ class iscsi(object):
         for iface in ifaces:
             iscsi_iface_name = "iface%d" % len(self.ifaces)
             #iscsiadm -m iface -I iface0 --op=new
-            iutil.execWithRedirect("iscsiadm",
-                                   ["-m", "iface", "-I", iscsi_iface_name, "--op=new"])
+            util.run_program(["iscsiadm", "-m", "iface",
+                              "-I", iscsi_iface_name, "--op=new"])
             #iscsiadm -m iface -I iface0 --op=update -n iface.net_ifacename -v eth0
-            iutil.execWithRedirect("iscsiadm",
-                                   ["-m", "iface", "-I", iscsi_iface_name,
-                                    "--op=update", "-n",
-                                    "iface.net_ifacename", "-v", iface])
+            util.run_program(["iscsiadm", "-m", "iface",
+                              "-I", iscsi_iface_name, "--op=update",
+                              "-n", "iface.net_ifacename", "-v", iface])
 
             self.ifaces[iscsi_iface_name] = iface
             log.debug("created_interface %s:%s" % (iscsi_iface_name, iface))
@@ -213,9 +212,8 @@ class iscsi(object):
             return None
         for iscsi_iface_name in self.ifaces:
             #iscsiadm -m iface -I iface0 --op=delete
-            iutil.execWithRedirect("iscsiadm",
-                                   ["-m", "iface", "-I", iscsi_iface_name,
-                                    "--op=delete"])
+            util.run_program(["iscsiadm", "-m", "iface",
+                              "-I", iscsi_iface_name, "--op=delete"])
         self.ifaces = {}
 
     def startup(self):
@@ -246,19 +244,19 @@ class iscsi(object):
                 os.makedirs(fulldir, 0755)
 
         log.info("iSCSI startup")
-        iutil.execWithRedirect('modprobe', ['-a'] + ISCSI_MODULES)
+        util.run_program(['modprobe', '-a'] + ISCSI_MODULES)
         # iscsiuio is needed by Broadcom offload cards (bnx2i). Currently
         # not present in iscsi-initiator-utils for Fedora.
         try:
-            iscsiuio = iutil.find_program_in_path('iscsiuio',
+            iscsiuio = util.find_program_in_path('iscsiuio',
                                                    raise_on_error=True)
         except RuntimeError:
             log.info("iscsi: iscsiuio not found.")
         else:
             log.debug("iscsi: iscsiuio is at %s" % iscsiuio)
-            iutil.execWithRedirect(iscsiuio, [])
+            util.run_program([iscsiuio])
         # run the daemon
-        iutil.execWithRedirect(ISCSID, [])
+        util.run_program([ISCSID])
         time.sleep(1)
 
         self._startIBFT()
diff --git a/pyanaconda/storage/partitioning.py b/pyanaconda/storage/partitioning.py
index 87372fa..64aa250 100644
--- a/pyanaconda/storage/partitioning.py
+++ b/pyanaconda/storage/partitioning.py
@@ -27,9 +27,6 @@ from operator import add, sub, gt, lt
 import parted
 from pykickstart.constants import *
 
-from pyanaconda.constants import *
-from pyanaconda.errors import *
-
 from errors import *
 from deviceaction import *
 from devices import PartitionDevice, LUKSDevice, devicePathToName
diff --git a/pyanaconda/storage/storage_log.py b/pyanaconda/storage/storage_log.py
new file mode 100644
index 0000000..62ad86f
--- /dev/null
+++ b/pyanaconda/storage/storage_log.py
@@ -0,0 +1,46 @@
+import inspect
+import logging
+
+log = logging.getLogger("storage")
+log.addHandler(logging.NullHandler())
+
+def function_name_and_depth():
+    IGNORED_FUNCS = ["function_name_and_depth",
+                     "log_method_call",
+                     "log_method_return"]
+    stack = inspect.stack()
+
+    for i, frame in enumerate(stack):
+        methodname = frame[3]
+        if methodname not in IGNORED_FUNCS:
+            return (methodname, len(stack) - i)
+
+    return ("unknown function?", 0)
+
+def log_method_call(d, *args, **kwargs):
+    classname = d.__class__.__name__
+    (methodname, depth) = function_name_and_depth()
+    spaces = depth * ' '
+    fmt = "%s%s.%s:"
+    fmt_args = [spaces, classname, methodname]
+
+    for arg in args:
+        fmt += " %s ;"
+        fmt_args.append(arg)
+
+    for k, v in kwargs.items():
+        fmt += " %s: %s ;"
+        if "pass" in k.lower() and v:
+            v = "Skipped"
+        fmt_args.extend([k, v])
+
+    logging.getLogger("storage").debug(fmt % tuple(fmt_args))
+
+def log_method_return(d, retval):
+    classname = d.__class__.__name__
+    (methodname, depth) = function_name_and_depth()
+    spaces = depth * ' '
+    fmt = "%s%s.%s returned %s"
+    fmt_args = (spaces, classname, methodname, retval)
+    logging.getLogger("storage").debug(fmt % fmt_args)
+
diff --git a/pyanaconda/storage/udev.py b/pyanaconda/storage/udev.py
index 0510184..cb9601b 100644
--- a/pyanaconda/storage/udev.py
+++ b/pyanaconda/storage/udev.py
@@ -23,7 +23,7 @@
 import os
 import re
 
-from pyanaconda import iutil
+import util
 from errors import *
 from pyanaconda.baseudev import *
 
@@ -270,7 +270,7 @@ def udev_device_get_wwid(udev_info):
     """ The WWID of a device is typically just its serial number, but with
         colons in the name to make it more readable. """
     serial = udev_device_get_serial(udev_info)
-    return iutil.insert_colons(serial) if serial else ""
+    return util.insert_colons(serial) if serial else ""
 
 def udev_device_get_vendor(udev_info):
     """ Get the vendor of the device as reported by udev. """
diff --git a/pyanaconda/storage/util.py b/pyanaconda/storage/util.py
new file mode 100644
index 0000000..c80841b
--- /dev/null
+++ b/pyanaconda/storage/util.py
@@ -0,0 +1,272 @@
+import os
+import selinux
+import subprocess
+
+from size import Size
+
+import logging
+log = logging.getLogger("storage")
+program_log = logging.getLogger("program")
+
+def _run_program(argv, root='/', stdin=None, env_prune=None):
+    if env_prune is None:
+        env_prune = []
+
+    def chroot():
+        if root and root != '/':
+            os.chroot(root)
+
+    program_log.info("Running... %s" % argv)
+
+    env = os.environ.copy()
+    env.update({"LC_ALL": "C",
+                "INSTALL_PATH": root})
+    for var in env_prune:
+        env.pop(var, None)
+
+    try:
+        proc = subprocess.Popen(argv,
+                                stdin=stdin,
+                                stdout=subprocess.PIPE,
+                                stderr=subprocess.STDOUT,
+                                preexec_fn=chroot, cwd=root, env=env)
+
+        while True:
+            out = proc.communicate()[0]
+            if out:
+                for line in out.splitlines():
+                    program_log.info(line)
+
+            if proc.returncode is not None:
+                break
+    except OSError as e:
+        program_log.error("Error running %s: %s" % (argv[0], e.strerror))
+        raise
+
+    program_log.debug("Return code: %d" % proc.returncode)
+    return (proc.returncode, out)
+
+def run_program(*args, **kwargs):
+    return _run_program(*args, **kwargs)[0]
+
+def capture_output(*args, **kwargs):
+    return _run_program(*args, **kwargs)[1]
+
+def mount(device, mountpoint, fstype, options=None):
+    if options is None:
+        options = "defaults"
+
+    mountpoint = os.path.normpath(mountpoint)
+    if not os.path.exists(mountpoint):
+        makedirs(mountpoint)
+
+    argv = ["mount", "-t", fstype, "-o", options, device, mountpoint]
+    try:
+        rc = run_program(argv)
+    except OSError as e:
+        raise
+
+    return rc
+
+def umount(mountpoint):
+    try:
+        rc = run_program(["umount", mountpoint])
+    except OSError as e:
+        raise
+
+    return rc
+
+def total_memory():
+    """ Return the amount of system RAM in kilobytes. """
+    lines = open("/proc/meminfo").readlines()
+    for line in lines:
+        if line.startswith("MemTotal:"):
+            mem = long(line.split()[1])
+
+    return mem
+
+##
+## sysfs functions
+##
+def notify_kernel(path, action="change"):
+    """ Signal the kernel that the specified device has changed.
+
+        Exceptions raised: ValueError, IOError
+    """
+    log.debug("notifying kernel of '%s' event on device %s" % (action, path))
+    path = os.path.join(path, "uevent")
+    if not path.startswith("/sys/") or not os.access(path, os.W_OK):
+        log.debug("sysfs path '%s' invalid" % path)
+        raise ValueError("invalid sysfs path")
+
+    f = open(path, "a")
+    f.write("%s\n" % action)
+    f.close()
+
+def get_sysfs_attr(path, attr):
+    if not attr:
+        log.debug("get_sysfs_attr() called with attr=None")
+        return None
+
+    attribute = "/sys%s/%s" % (path, attr)
+    attribute = os.path.realpath(attribute)
+
+    if not os.path.isfile(attribute) and not os.path.islink(attribute):
+        log.warning("%s is not a valid attribute" % (attr,))
+        return None
+
+    return open(attribute, "r").read().strip()
+
+def get_sysfs_path_by_name(dev_node, class_name="block"):
+    """ Return sysfs path for a given device.
+
+        For a device node (e.g. /dev/vda2) get the respective sysfs path
+        (e.g. /sys/class/block/vda2). This also has to work for device nodes
+        that are in a subdirectory of /dev like '/dev/cciss/c0d0p1'.
+     """
+    dev_name = os.path.basename(dev_node)
+    if dev_node.startswith("/dev/"):
+        dev_name = dev_node[5:].replace("/", "!")
+    sysfs_class_dir = "/sys/class/%s" % class_name
+    dev_path = os.path.join(sysfs_class_dir, dev_name)
+    if os.path.exists(dev_path):
+        return dev_path
+    else:
+        raise RuntimeError("get_sysfs_path_by_name: Could not find sysfs path "
+                           "for '%s' (it is not at '%s')" % (dev_node, dev_path))
+
+##
+## SELinux functions
+##
+def match_path_context(path):
+    """ Return the default SELinux context for the given path. """
+    context = None
+    try:
+        context = selinux.matchpathcon(os.path.normpath(path), 0)[1]
+    except OSError as e:
+        log.info("failed to get default SELinux context for %s: %s" % (path, e))
+
+    return context
+
+def set_file_context(path, context, root=None):
+    """ Set the SELinux file context of a file.
+
+        Arguments:
+
+            path        filename string
+            context     context string
+
+        Keyword Arguments:
+
+            root        an optional chroot string
+
+        Return Value:
+
+            True if successful, False if not.
+    """
+    if root is None:
+        root = '/'
+
+    full_path = os.path.normpath("%s/%s" % (root, path))
+    if context is None or not os.access(full_path, os.F_OK):
+        return False
+
+    try:
+        rc = (selinux.lsetfilecon(full_path, context) == 0)
+    except OSError as e:
+        log.info("failed to set SELinux context for %s: %s" % (full_path, e))
+        rc = False
+
+    return rc
+
+def reset_file_context(path, root=None):
+    """ Restore the SELinux context of a file to its default value.
+
+        Arguments:
+
+            path        filename string
+
+        Keyword Arguments:
+
+            root        an optional chroot string
+
+        Return Value:
+
+            If successful, returns the file's new/default context.
+    """
+    context = match_path_context(path)
+    if context:
+        if set_file_context(path, context, root=root):
+            return context
+
+##
+## Miscellaneous
+##
+def find_program_in_path(prog, raise_on_error=False):
+    for d in os.environ["PATH"].split(os.pathsep):
+        full = os.path.join(d, prog)
+        if os.access(full, os.X_OK):
+            return full
+
+    if raise_on_error:
+        raise RuntimeError("Unable to locate a needed executable: '%s'" % prog)
+
+def makedirs(path):
+    if not os.path.isdir(path):
+        os.makedirs(path, 0755)
+
+def copy_to_system(source):
+    if not os.access(source, os.R_OK):
+        log.info("copy_to_system: source '%s' does not exist." % source)
+        return False
+
+    target = ROOT_PATH + source
+    target_dir = os.path.dirname(target)
+    log.debug("copy_to_system: '%s' -> '%s'." % (source, target))
+    if not os.path.isdir(target_dir):
+        os.makedirs(target_dir)
+    shutil.copy(source, target)
+    return True
+
+def lsmod():
+    """ Returns list of names of all loaded modules. """
+    with open("/proc/modules") as f:
+        lines = f.readlines()
+    return [l.split()[0] for l in lines]
+
+def get_option_value(opt_name, options):
+    """ Return the value of a named option in the specified options string. """
+    for opt in options.split(","):
+        if "=" not in opt:
+            continue
+
+        name, val = opt.split("=")
+        if name == opt_name:
+            return val.strip()
+
+def numeric_type(num):
+    """ Verify that a value is given as a numeric data type.
+
+        Return the number if the type is sensible or raise ValueError
+        if not.
+    """
+    if num is None:
+        num = 0
+    elif not (isinstance(num, int) or \
+              isinstance(num, long) or \
+              isinstance(num, float)):
+        raise ValueError("value (%s) must be either a number or None" % num)
+
+    return num
+
+def insert_colons(a_string):
+    """ Insert colon between every second character.
+
+        E.g. creates 'al:go:ri:th:ms' from 'algoritms'. Useful for formatting
+        MAC addresses and wwids for output.
+    """
+    suffix = a_string[-2:]
+    if len(a_string) > 2:
+        return insert_colons(a_string[:-2]) + ':' + suffix
+    else:
+        return suffix
diff --git a/pyanaconda/storage/zfcp.py b/pyanaconda/storage/zfcp.py
index 28b2317..27dd107 100644
--- a/pyanaconda/storage/zfcp.py
+++ b/pyanaconda/storage/zfcp.py
@@ -23,13 +23,13 @@ import string
 import os
 from pyanaconda.constants import *
 from udev import udev_settle
+from . import util
 
 import gettext
 _ = lambda x: gettext.ldgettext("anaconda", x)
 
-from pyanaconda import iutil
 import logging
-log = logging.getLogger("anaconda")
+log = logging.getLogger("storage")
 
 def loggedWriteLineToFile(fn, value):
     f = open(fn, "w")
@@ -125,7 +125,7 @@ class ZFCPDevice:
 
         if not os.path.exists(online):
             log.info("Freeing zFCP device %s" % (self.devnum,))
-            iutil.execWithRedirect("zfcp_cio_free", ["-d", self.devnum])
+            util.run_program(["zfcp_cio_free", "-d", self.devnum])
 
         if not os.path.exists(online):
             raise ValueError, _(
diff --git a/pyanaconda/timezone.py b/pyanaconda/timezone.py
index 6e8709b..01edeb3 100644
--- a/pyanaconda/timezone.py
+++ b/pyanaconda/timezone.py
@@ -30,6 +30,7 @@ from collections import OrderedDict
 
 from pyanaconda import localization
 from pyanaconda import iutil
+from pyanaconda.storage import arch
 
 import logging
 log = logging.getLogger("anaconda")
@@ -105,7 +106,7 @@ def save_hw_clock(timezone):
 
     """
 
-    if iutil.isS390():
+    if arch.isS390():
         return
 
     cmd = "hwclock"
diff --git a/tests/pyanaconda_test/network_test.py b/tests/pyanaconda_test/network_test.py
index a5afbe6..756c11d 100644
--- a/tests/pyanaconda_test/network_test.py
+++ b/tests/pyanaconda_test/network_test.py
@@ -211,8 +211,8 @@ class NetworkTest(mock.TestCase):
 
     def networkdevice_str_test(self):
         import pyanaconda.network
-        pyanaconda.network.iutil = mock.Mock()
-        pyanaconda.network.iutil.isS390.return_value = False
+        pyanaconda.network.arch = mock.Mock()
+        pyanaconda.network.arch.isS390.return_value = False
 
         nd = pyanaconda.network.NetworkDevice(self.NETSCRIPTSDIR, self.DEVICE)
         nd.info = {'HWADDR': '00:11:22:50:55:50', 'DEVICE': 'eth0', 'TYPE': 'Ethernet'}
@@ -381,8 +381,8 @@ class NetworkTest(mock.TestCase):
 
     def iface_for_host_ip_test(self):
         import pyanaconda.network
-        pyanaconda.network.iutil = mock.Mock()
-        pyanaconda.network.iutil.execWithCapture.return_value = \
+        pyanaconda.network.arch = mock.Mock()
+        pyanaconda.network.arch.execWithCapture.return_value = \
             "10.0.0.2 dev eth0  src 10.0.0.1"
 
         ret = pyanaconda.network.ifaceForHostIP('10.0.0.2')
-- 
1.7.6.5

