dpolovinkin / rpms / anaconda

Forked from rpms/anaconda 3 years ago
Clone
Blob Blame History Raw
From 74d70fcd113ca0622959e272cb78cedc6509fbef Mon Sep 17 00:00:00 2001
From: Colin Walters <walters@verbum.org>
Date: Tue, 22 Apr 2014 14:39:26 -0400
Subject: [PATCH 04/20] iutil: Introduce getSysroot()/getTargetPhysicalRoot(),
 use instead of ROOT_PATH

For OSTree, the OS lives in a chroot, thus creating a distinction
between the "physical" root and the "deployment" root.  The physical
root as mounted by anaconda remains as /mnt/sysimage of course, but
*nearly* everything needs to reference the deployment, as that's where
the binaries, config files, etc live.

The deployment root is dynamic - we only know it after we do an
initial installation what the path will be.  This dynamic nature means
that the API is best as a function call.

Resolves: rhbz#1113535
Port of rpmostreepayload patches from master
commit 1b260c0c3ca70b53d44b543babe1a5ab06fb5fb5
---
 pyanaconda/__init__.py              |  6 +--
 pyanaconda/bootloader.py            | 96 +++++++++++++++++--------------------
 pyanaconda/constants.py             |  2 +
 pyanaconda/desktop.py               | 10 ++--
 pyanaconda/exception.py             | 10 ++--
 pyanaconda/install.py               |  6 +--
 pyanaconda/installclasses/fedora.py |  8 ++--
 pyanaconda/installclasses/rhel.py   |  3 +-
 pyanaconda/iutil.py                 | 48 ++++++++++++++++++-
 pyanaconda/kickstart.py             | 51 ++++++++++----------
 pyanaconda/packaging/__init__.py    | 40 ++++++++--------
 pyanaconda/packaging/livepayload.py | 25 +++++-----
 pyanaconda/packaging/tarpayload.py  |  2 +-
 pyanaconda/packaging/yumpayload.py  | 12 ++---
 pyanaconda/rescue.py                | 16 +++----
 pyanaconda/users.py                 |  7 ++-
 16 files changed, 187 insertions(+), 155 deletions(-)

diff --git a/pyanaconda/__init__.py b/pyanaconda/__init__.py
index 9b58f92..fad7a90 100644
--- a/pyanaconda/__init__.py
+++ b/pyanaconda/__init__.py
@@ -30,11 +30,11 @@
 
 import os, time, string
 import sys
-from constants import ROOT_PATH
 from tempfile import mkstemp
 
 from pyanaconda.bootloader import get_bootloader
 from pyanaconda import constants
+from pyanaconda import iutil
 from pyanaconda import addons
 from pyanaconda.i18n import _
 
@@ -228,7 +228,7 @@ class Anaconda(object):
         if self.xdriver is None:
             return
         if root is None:
-            root = ROOT_PATH
+            root = iutil.getSysroot()
         if not os.path.isdir("%s/etc/X11" %(root,)):
             os.makedirs("%s/etc/X11" %(root,), mode=0755)
         f = open("%s/etc/X11/xorg.conf" %(root,), 'w')
@@ -241,7 +241,7 @@ class Anaconda(object):
 
         network.write_sysconfig_network()
         network.disableIPV6()
-        network.copyConfigToPath(ROOT_PATH)
+        network.copyConfigToPath(iutil.getSysroot())
         if not self.ksdata:
             self.instClass.setNetworkOnbootDefault()
         self.desktop.write()
diff --git a/pyanaconda/bootloader.py b/pyanaconda/bootloader.py
index 2fc1d49..90aec61 100644
--- a/pyanaconda/bootloader.py
+++ b/pyanaconda/bootloader.py
@@ -34,7 +34,6 @@ from blivet.devicelibs import mdraid
 from pyanaconda.isys import sync
 from pyanaconda.product import productName
 from pyanaconda.flags import flags
-from pyanaconda.constants import *
 from blivet.errors import StorageError
 from blivet.fcoe import fcoe
 import pyanaconda.network
@@ -929,19 +928,19 @@ class BootLoader(object):
 
     def write_config_post(self):
         try:
-            os.chmod(ROOT_PATH + self.config_file, self.config_file_mode)
+            os.chmod(iutil.getSysroot() + self.config_file, self.config_file_mode)
         except OSError as e:
             log.error("failed to set config file permissions: %s" % e)
 
     def add_crash_args(self):
         buf = ""
-        if os.access("%s%s" % (ROOT_PATH, "/usr/sbin/rhcrashkernel-param"), \
+        if os.access("%s%s" % (iutil.getSysroot(), "/usr/sbin/rhcrashkernel-param"), \
                      os.X_OK):
             (pread, pwrite) = os.pipe()
             os.close(pwrite)
             buf = iutil.execWithCapture("/usr/sbin/rhcrashkernel-param", [],
                                         stdin=pread,
-                                        root=ROOT_PATH)
+                                        root=iutil.getSysroot())
             os.close(pread)
         self.boot_args.add(buf.replace('\n', ' '))
 
@@ -952,7 +951,7 @@ class BootLoader(object):
 
         self.add_crash_args()
 
-        config_path = os.path.normpath(ROOT_PATH + self.config_file)
+        config_path = os.path.normpath(iutil.getSysroot() + self.config_file)
         if os.access(config_path, os.R_OK):
             os.rename(config_path, config_path + ".anacbak")
 
@@ -988,7 +987,7 @@ class BootLoader(object):
 
         self.write_config()
         sync()
-        self.stage2_device.format.sync(root=ROOT_PATH)
+        self.stage2_device.format.sync(root=iutil.getTargetPhysicalRoot())
         self.install()
 
     def install(self):
@@ -1180,7 +1179,7 @@ class GRUB(BootLoader):
 
         if iutil.isConsoleOnVirtualTerminal(self.console):
             splash = "splash.xpm.gz"
-            splash_path = os.path.normpath("%s/boot/%s/%s" % (ROOT_PATH,
+            splash_path = os.path.normpath("%s/boot/%s/%s" % (iutil.getSysroot(),
                                                         self.splash_dir,
                                                         splash))
             if os.access(splash_path, os.R_OK):
@@ -1233,7 +1232,7 @@ class GRUB(BootLoader):
 
     def write_device_map(self):
         """ Write out a device map containing all supported devices. """
-        map_path = os.path.normpath(ROOT_PATH + self.device_map_file)
+        map_path = os.path.normpath(iutil.getSysroot() + self.device_map_file)
         if os.access(map_path, os.R_OK):
             os.rename(map_path, map_path + ".anacbak")
 
@@ -1249,7 +1248,7 @@ class GRUB(BootLoader):
         super(GRUB, self).write_config_post()
 
         # make symlink for menu.lst (grub's default config file name)
-        menu_lst = "%s%s/menu.lst" % (ROOT_PATH, self.config_dir)
+        menu_lst = "%s%s/menu.lst" % (iutil.getSysroot(), self.config_dir)
         if os.access(menu_lst, os.R_OK):
             try:
                 os.rename(menu_lst, menu_lst + '.anacbak')
@@ -1262,7 +1261,7 @@ class GRUB(BootLoader):
             log.error("failed to create grub menu.lst symlink: %s" % e)
 
         # make symlink to grub.conf in /etc since that's where configs belong
-        etc_grub = "%s/etc/%s" % (ROOT_PATH, self._config_file)
+        etc_grub = "%s/etc/%s" % (iutil.getSysroot(), self._config_file)
         if os.access(etc_grub, os.R_OK):
             try:
                 os.unlink(etc_grub)
@@ -1320,9 +1319,8 @@ class GRUB(BootLoader):
 
         return targets
 
-    def install(self):
-        rc = iutil.execWithRedirect("grub-install", ["--just-copy"],
-                                    root=ROOT_PATH)
+    def install(self, args=None):
+        rc = iutil.execInSysroot("grub-install", ["--just-copy"])
         if rc:
             raise BootLoaderError("bootloader install failed")
 
@@ -1342,8 +1340,7 @@ class GRUB(BootLoader):
             os.close(pwrite)
             args = ["--batch", "--no-floppy",
                     "--device-map=%s" % self.device_map_file]
-            rc = iutil.execWithRedirect("grub", args,
-                                        stdin=pread, root=ROOT_PATH)
+            rc = iutil.execInSysroot("grub", args, stdin=pread)
             os.close(pread)
             if rc:
                 raise BootLoaderError("bootloader install failed")
@@ -1452,7 +1449,7 @@ class GRUB2(GRUB):
 
     def write_device_map(self):
         """ Write out a device map containing all supported devices. """
-        map_path = os.path.normpath(ROOT_PATH + self.device_map_file)
+        map_path = os.path.normpath(iutil.getSysroot() + self.device_map_file)
         if os.access(map_path, os.R_OK):
             os.rename(map_path, map_path + ".anacbak")
 
@@ -1477,7 +1474,7 @@ class GRUB2(GRUB):
         dev_map.close()
 
     def write_defaults(self):
-        defaults_file = "%s%s" % (ROOT_PATH, self.defaults_file)
+        defaults_file = "%s%s" % (iutil.getSysroot(), self.defaults_file)
         defaults = open(defaults_file, "w+")
         defaults.write("GRUB_TIMEOUT=%d\n" % self.timeout)
         defaults.write("GRUB_DISTRIBUTOR=\"$(sed 's, release .*$,,g' /etc/system-release)\"\n")
@@ -1511,7 +1508,7 @@ class GRUB2(GRUB):
         os.close(pwrite)
         buf = iutil.execWithCapture("grub2-mkpasswd-pbkdf2", [],
                                     stdin=pread,
-                                    root=ROOT_PATH)
+                                    root=iutil.getSysroot())
         os.close(pread)
         self.encrypted_password = buf.split()[-1].strip()
         if not self.encrypted_password.startswith("grub.pbkdf2."):
@@ -1521,7 +1518,7 @@ class GRUB2(GRUB):
         if not self.password and not self.encrypted_password:
             return
 
-        users_file = ROOT_PATH + "/etc/grub.d/01_users"
+        users_file = iutil.getSysroot() + "/etc/grub.d/01_users"
         header = open(users_file, "w")
         header.write("#!/bin/sh -e\n\n")
         header.write("cat << \"EOF\"\n")
@@ -1555,16 +1552,13 @@ class GRUB2(GRUB):
         # make sure the default entry is the OS we are installing
         entry_title = "%s Linux, with Linux %s" % (productName,
                                                    self.default.version)
-        rc = iutil.execWithRedirect("grub2-set-default",
-                                    [entry_title],
-                                    root=ROOT_PATH)
+        rc = iutil.execInSysroot("grub2-set-default", [entry_title])
         if rc:
             log.error("failed to set default menu entry to %s" % productName)
 
         # now tell grub2 to generate the main configuration file
-        rc = iutil.execWithRedirect("grub2-mkconfig",
-                                    ["-o", self.config_file],
-                                    root=ROOT_PATH)
+        rc = iutil.execInSysroot("grub2-mkconfig",
+                                 ["-o", self.config_file])
         if rc:
             raise BootLoaderError("failed to write bootloader configuration")
 
@@ -1585,7 +1579,7 @@ class GRUB2(GRUB):
                 grub_args.insert(0, '--force')
 
             rc = iutil.execWithRedirect("grub2-install", grub_args,
-                                        root=ROOT_PATH,
+                                        root=iutil.getSysroot(),
                                         env_prune=['MALLOC_PERTURB_'])
             if rc:
                 raise BootLoaderError("bootloader install failed")
@@ -1600,14 +1594,14 @@ class GRUB2(GRUB):
             return
 
         self.write_device_map()
-        self.stage2_device.format.sync(root=ROOT_PATH)
+        self.stage2_device.format.sync(root=iutil.getTargetPhysicalRoot())
         sync()
         self.install()
         sync()
-        self.stage2_device.format.sync(root=ROOT_PATH)
+        self.stage2_device.format.sync(root=iutil.getTargetPhysicalRoot())
         self.write_config()
         sync()
-        self.stage2_device.format.sync(root=ROOT_PATH)
+        self.stage2_device.format.sync(root=iutil.getTargetPhysicalRoot())
 
     def check(self):
         """ When installing to the mbr of a disk grub2 needs enough space
@@ -1676,7 +1670,7 @@ class EFIGRUB(GRUB2):
         else:
             exec_func = iutil.execWithRedirect
         if "root" not in kwargs:
-            kwargs["root"] = ROOT_PATH
+            kwargs["root"] = iutil.getSysroot()
 
         return exec_func("efibootmgr", list(args), **kwargs)
 
@@ -1722,7 +1716,8 @@ class EFIGRUB(GRUB2):
         rc = self.efibootmgr("-c", "-w", "-L", productName,
                              "-d", boot_disk.path, "-p", boot_part_num,
                              "-l",
-                             self.efi_dir_as_efifs_dir + self._efi_binary)
+                             self.efi_dir_as_efifs_dir + self._efi_binary,
+                             root=iutil.getSysroot())
         if rc:
             raise BootLoaderError("failed to set new efi boot target")
 
@@ -1747,7 +1742,7 @@ class EFIGRUB(GRUB2):
             return
 
         sync()
-        self.stage2_device.format.sync(root=ROOT_PATH)
+        self.stage2_device.format.sync(root=iutil.getTargetPhysicalRoot())
         self.install()
         self.write_config()
 
@@ -1765,9 +1760,8 @@ class Aarch64EFIGRUB(EFIGRUB):
 
 class MacEFIGRUB(EFIGRUB):
     def mactel_config(self):
-        if os.path.exists(ROOT_PATH + "/usr/libexec/mactel-boot-setup"):
-            rc = iutil.execWithRedirect("/usr/libexec/mactel-boot-setup", [],
-                                        root=ROOT_PATH)
+        if os.path.exists(iutil.getSysroot() + "/usr/libexec/mactel-boot-setup"):
+            rc = iutil.execInSysroot("/usr/libexec/mactel-boot-setup", [])
             if rc:
                 log.error("failed to configure Mac bootloader")
 
@@ -1881,7 +1875,7 @@ class Yaboot(YabootBase):
         super(Yaboot, self).write_config_post()
 
         # make symlink in /etc to yaboot.conf if config is in /boot/etc
-        etc_yaboot_conf = ROOT_PATH + "/etc/yaboot.conf"
+        etc_yaboot_conf = iutil.getSysroot() + "/etc/yaboot.conf"
         if not os.access(etc_yaboot_conf, os.R_OK):
             try:
                 os.symlink("../boot/etc/yaboot.conf", etc_yaboot_conf)
@@ -1889,8 +1883,8 @@ class Yaboot(YabootBase):
                 log.error("failed to create /etc/yaboot.conf symlink: %s" % e)
 
     def write_config(self):
-        if not os.path.isdir(ROOT_PATH + self.config_dir):
-            os.mkdir(ROOT_PATH + self.config_dir)
+        if not os.path.isdir(iutil.getSysroot() + self.config_dir):
+            os.mkdir(iutil.getSysroot() + self.config_dir)
 
         # this writes the config
         super(Yaboot, self).write_config()
@@ -1901,8 +1895,7 @@ class Yaboot(YabootBase):
 
     def install(self):
         args = ["-f", "-C", self.config_file]
-        rc = iutil.execWithRedirect(self.prog, args,
-                                    root=ROOT_PATH)
+        rc = iutil.execInSysroot(self.prog, args)
         if rc:
             raise BootLoaderError("bootloader installation failed")
 
@@ -2027,7 +2020,7 @@ class IPSeriesGRUB2(GRUB2):
     def write_defaults(self):
         super(IPSeriesGRUB2, self).write_defaults()
 
-        defaults_file = "%s%s" % (ROOT_PATH, self.defaults_file)
+        defaults_file = "%s%s" % (iutil.getSysroot(), self.defaults_file)
         defaults = open(defaults_file, "a+")
         # The terminfo's X and Y size, and output location could change in the future
         defaults.write("GRUB_TERMINFO=\"terminfo -g 80x24 console\"\n")
@@ -2142,10 +2135,8 @@ class ZIPL(BootLoader):
     # installation
     #
 
-    def install(self):
-        buf = iutil.execWithCapture("zipl", [],
-                                    root=ROOT_PATH,
-                                    fatal=True)
+    def install(self, args=None):
+        buf = iutil.execWithCapture("zipl", [], root=iutil.getSysroot(), fatal=True)
         for line in buf.splitlines():
             if line.startswith("Preparing boot device: "):
                 # Output here may look like:
@@ -2192,7 +2183,7 @@ class UBOOT(BootLoader):
     def install(self):
         # a-b-c is a tool that generates a generic boor.scr that works in most situations.
         # not perfect but is better than doing nothing
-        rc = iutil.execWithRedirect("a-b-c", [], root=ROOT_PATH)
+        rc = iutil.execWithRedirect("a-b-c", [], root=iutil.getSysroot())
 
         if rc:
             raise BootLoaderError("bootloader install failed")
@@ -2274,7 +2265,7 @@ class EXTLINUX(BootLoader):
             config.write("menu notabmsg Press [Tab] and enter the password to edit options")
 
     def write_config_post(self):
-        etc_extlinux = os.path.normpath(ROOT_PATH + "/etc/" + self._config_file)
+        etc_extlinux = os.path.normpath(iutil.getSysroot() + "/etc/" + self._config_file)
         if not os.access(etc_extlinux, os.R_OK):
             try:
                 os.symlink("../boot/%s" % self._config_file, etc_extlinux)
@@ -2291,8 +2282,7 @@ class EXTLINUX(BootLoader):
     def install(self):
         backup = "%s/backup.b" % self._config_dir
         args = ["--install", self._config_dir]
-        rc = iutil.execWithRedirect("extlinux", args,
-                                    root=ROOT_PATH)
+        rc = iutil.execInSysroot("extlinux", args)
 
         if rc:
             raise BootLoaderError("bootloader install failed")
@@ -2326,9 +2316,9 @@ def writeSysconfigKernel(storage, version):
     # get the name of the default kernel package based on the version
     kernel_basename = "vmlinuz-" + version
     kernel_file = "/boot/%s" % kernel_basename
-    if not os.path.isfile(ROOT_PATH + kernel_file):
+    if not os.path.isfile(iutil.getSysroot() + kernel_file):
         kernel_file = "/boot/efi/EFI/redhat/%s" % kernel_basename
-        if not os.path.isfile(ROOT_PATH + kernel_file):
+        if not os.path.isfile(iutil.getSysroot() + kernel_file):
             log.error("failed to recreate path to default kernel image")
             return
 
@@ -2338,7 +2328,7 @@ def writeSysconfigKernel(storage, version):
         log.error("failed to import rpm python module")
         return
 
-    ts = rpm.TransactionSet(ROOT_PATH)
+    ts = rpm.TransactionSet(iutil.getSysroot())
     mi = ts.dbMatch('basenames', kernel_file)
     try:
         h = mi.next()
@@ -2348,7 +2338,7 @@ def writeSysconfigKernel(storage, version):
 
     kernel = h.name
 
-    f = open(ROOT_PATH + "/etc/sysconfig/kernel", "w+")
+    f = open(iutil.getSysroot() + "/etc/sysconfig/kernel", "w+")
     f.write("# UPDATEDEFAULT specifies if new-kernel-pkg should make\n"
             "# new kernels the default\n")
     # only update the default if we're setting the default to linux (#156678)
diff --git a/pyanaconda/constants.py b/pyanaconda/constants.py
index e864630..1d523c0 100644
--- a/pyanaconda/constants.py
+++ b/pyanaconda/constants.py
@@ -80,6 +80,8 @@ DD_RPMS = "/tmp/DD-*"
 TRANSLATIONS_UPDATE_DIR="/tmp/updates/po"
 
 ANACONDA_CLEANUP = "anaconda-cleanup"
+# This is a legacy variable; new code should use iutil.getSysroot()
+# or iutil.getTargetPhysicalRoot().
 ROOT_PATH = os.environ.get("ANACONDA_ROOT_PATH", "/mnt/sysimage")
 MOUNT_DIR = "/mnt/install"
 DRACUT_REPODIR = "/run/install/repo"
diff --git a/pyanaconda/desktop.py b/pyanaconda/desktop.py
index fde1dc7..c4edf2f 100644
--- a/pyanaconda/desktop.py
+++ b/pyanaconda/desktop.py
@@ -21,7 +21,8 @@
 
 import os
 from simpleconfig import SimpleConfigFile
-from pyanaconda.constants import ROOT_PATH, RUNLEVELS
+from pyanaconda.constants import RUNLEVELS
+from pyanaconda import iutil
 
 import logging
 log = logging.getLogger("anaconda")
@@ -51,14 +52,15 @@ class Desktop(SimpleConfigFile):
 
     def write(self):
         if self.getDefaultDesktop():
-            f = open(ROOT_PATH + "/etc/sysconfig/desktop", "w")
+            f = open(iutil.getSysroot() + "/etc/sysconfig/desktop", "w")
             f.write(str(self))
             f.close()
 
-        if not os.path.isdir(ROOT_PATH + '/etc/systemd/system'):
+        if not os.path.isdir(iutil.getSysroot() + '/etc/systemd/system'):
             log.warning("there is no /etc/systemd/system directory, cannot update default.target!")
             return
-        default_target = ROOT_PATH + '/etc/systemd/system/default.target'
+
+        default_target = iutil.getSysroot() + '/etc/systemd/system/default.target'
         if os.path.islink(default_target):
             os.unlink(default_target)
         os.symlink('/lib/systemd/system/%s' % RUNLEVELS[self.runlevel],
diff --git a/pyanaconda/exception.py b/pyanaconda/exception.py
index 861425f..fe2bb8d 100644
--- a/pyanaconda/exception.py
+++ b/pyanaconda/exception.py
@@ -34,7 +34,7 @@ import kickstart
 import blivet.errors
 from pyanaconda.errors import CmdlineError
 from pyanaconda.ui.communication import hubQ
-from pyanaconda.constants import ROOT_PATH, THREAD_EXCEPTION_HANDLING_TEST
+from pyanaconda.constants import THREAD_EXCEPTION_HANDLING_TEST
 from pyanaconda.threads import threadMgr
 from pyanaconda.i18n import _
 from pyanaconda import flags
@@ -159,12 +159,12 @@ class AnacondaExceptionHandler(ExceptionHandler):
         anaconda = dump_info.object
 
         # See if there is a /root present in the root path and put exception there as well
-        if os.access(ROOT_PATH + "/root", os.X_OK):
+        if os.access(iutil.getSysroot() + "/root", os.X_OK):
             try:
-                dest = ROOT_PATH + "/root/%s" % os.path.basename(self.exnFile)
+                dest = iutil.getSysroot() + "/root/%s" % os.path.basename(self.exnFile)
                 shutil.copyfile(self.exnFile, dest)
             except:
-                log.error("Failed to copy %s to %s/root" % (self.exnFile, ROOT_PATH))
+                log.error("Failed to copy %s to %s/root" % (self.exnFile, iutil.getSysroot()))
                 pass
 
         # run kickstart traceback scripts (if necessary)
@@ -213,7 +213,7 @@ class AnacondaExceptionHandler(ExceptionHandler):
 def initExceptionHandling(anaconda):
     fileList = [ "/tmp/anaconda.log", "/tmp/packaging.log",
                  "/tmp/program.log", "/tmp/storage.log", "/tmp/ifcfg.log",
-                 "/tmp/yum.log", ROOT_PATH + "/root/install.log",
+                 "/tmp/yum.log", iutil.getSysroot() + "/root/install.log",
                  "/proc/cmdline" ]
     if flags.flags.livecdInstall:
         fileList.extend(["/var/log/messages"])
diff --git a/pyanaconda/install.py b/pyanaconda/install.py
index 5796086..db66e78 100644
--- a/pyanaconda/install.py
+++ b/pyanaconda/install.py
@@ -20,12 +20,12 @@
 # Red Hat Author(s): Chris Lumens <clumens@redhat.com>
 #
 
-from pyanaconda.constants import ROOT_PATH, THREAD_PAYLOAD
 from blivet import turnOnFilesystems
 from pyanaconda.bootloader import writeBootLoader
 from pyanaconda.progress import progress_report, progressQ
 from pyanaconda.users import createLuserConf, getPassAlgo, Users
 from pyanaconda import flags
+from pyanaconda import iutil
 from pyanaconda import timezone
 from pyanaconda.i18n import _
 from pyanaconda.threads import threadMgr
@@ -35,7 +35,7 @@ log = logging.getLogger("anaconda")
 def _writeKS(ksdata):
     import os
 
-    path = ROOT_PATH + "/root/anaconda-ks.cfg"
+    path = iutil.getSysroot() + "/root/anaconda-ks.cfg"
 
     # Clear out certain sensitive information that kickstart doesn't have a
     # way of representing encrypted.
@@ -80,7 +80,7 @@ def doConfiguration(storage, payload, ksdata, instClass):
 
     # Creating users and groups requires some pre-configuration.
     with progress_report(_("Creating users")):
-        createLuserConf(ROOT_PATH, algoname=getPassAlgo(ksdata.authconfig.authconfig))
+        createLuserConf(iutil.getSysroot(), algoname=getPassAlgo(ksdata.authconfig.authconfig))
         u = Users()
         ksdata.rootpw.execute(storage, ksdata, instClass, u)
         ksdata.group.execute(storage, ksdata, instClass, u)
diff --git a/pyanaconda/installclasses/fedora.py b/pyanaconda/installclasses/fedora.py
index 98e922f..3e0a5f2 100644
--- a/pyanaconda/installclasses/fedora.py
+++ b/pyanaconda/installclasses/fedora.py
@@ -18,11 +18,11 @@
 #
 
 from pyanaconda.installclass import BaseInstallClass
-from pyanaconda.constants import *
-from pyanaconda.product import *
+from pyanaconda.product import productName
 from pyanaconda import network
+from pyanaconda import iutil
 from pyanaconda import nm
-from pyanaconda.i18n import _
+from pyanaconda.i18n import _, N_
 
 import os, types
 
@@ -68,7 +68,7 @@ class InstallClass(BaseInstallClass):
             except ValueError as e:
                 continue
             if link_up:
-                ifcfg_path = network.find_ifcfg_file_of_device(devName, root_path=ROOT_PATH)
+                ifcfg_path = network.find_ifcfg_file_of_device(devName, root_path=iutil.getSysroot())
                 if not ifcfg_path:
                     continue
                 ifcfg = network.IfcfgFile(ifcfg_path)
diff --git a/pyanaconda/installclasses/rhel.py b/pyanaconda/installclasses/rhel.py
index f3e5a99..74052fd 100644
--- a/pyanaconda/installclasses/rhel.py
+++ b/pyanaconda/installclasses/rhel.py
@@ -22,6 +22,7 @@ from pyanaconda.constants import *
 from pyanaconda.product import *
 from pyanaconda import network
 from pyanaconda import nm
+from pyanaconda import iutil
 import types
 
 class InstallClass(BaseInstallClass):
@@ -71,7 +72,7 @@ class InstallClass(BaseInstallClass):
             return
         if nm.nm_device_type_is_wifi(devName):
             return
-        ifcfg_path = network.find_ifcfg_file_of_device(devName, root_path=ROOT_PATH)
+        ifcfg_path = network.find_ifcfg_file_of_device(devName, root_path=iutil.getSysroot())
         if not ifcfg_path:
             return
         ifcfg = network.IfcfgFile(ifcfg_path)
diff --git a/pyanaconda/iutil.py b/pyanaconda/iutil.py
index 8d6b31b..46f8079 100644
--- a/pyanaconda/iutil.py
+++ b/pyanaconda/iutil.py
@@ -44,10 +44,44 @@ from anaconda_log import program_log_lock
 def augmentEnv():
     env = os.environ.copy()
     env.update({"LC_ALL": "C",
-                "ANA_INSTALL_PATH": ROOT_PATH
+                "ANA_INSTALL_PATH": getSysroot()
                })
     return env
 
+def getTargetPhysicalRoot():
+    """Returns the path to the "physical" storage root, traditionally /mnt/sysimage.
+
+    This may be distinct from the sysroot, which could be a
+    chroot-type subdirectory of the physical root.  This is used for
+    example by all OSTree-based installations.
+    """
+
+    # We always use the traditional /mnt/sysimage - the physical OS
+    # target is never mounted anywhere else.  This API call just
+    # allows us to have a clean "git grep ROOT_PATH" in other parts of
+    # the code.
+    return ROOT_PATH
+
+_sysroot = ROOT_PATH
+
+def getSysroot():
+    """Returns the path to the target OS installation.
+
+    For ordinary package-based installations, this is the same as the
+    target root.
+    """
+    return _sysroot
+
+def setSysroot(path):
+    """Change the OS root path.
+       :param path: The new OS root path
+
+    This should only be used by Payload subclasses which install operating
+    systems to non-default roots.
+    """
+    global _sysroot
+    _sysroot = path
+
 def _run_program(argv, root='/', stdin=None, stdout=None, env_prune=None, log_output=True, binary_output=False):
     """ Run an external program, log the output and return it to the caller
         @param argv The command to run and argument
@@ -105,6 +139,16 @@ def _run_program(argv, root='/', stdin=None, stdout=None, env_prune=None, log_ou
 
     return (proc.returncode, output_string)
 
+def execInSysroot(command, argv, stdin=None):
+    """ Run an external program in the target root.
+        :param command: The command to run
+        :param argv: The argument list
+        :param stdin: The file object to read stdin from.
+        :return: The return code of the command
+    """
+
+    return execWithRedirect(command, argv, stdin=stdin, root=getSysroot())
+
 def execWithRedirect(command, argv, stdin=None, stdout=None,
                      stderr=None, root='/', env_prune=[], log_output=True, binary_output=False):
     """ Run an external program and redirect the output to a file.
@@ -323,7 +367,7 @@ def reIPL(ipldev):
         log.info("reIPL configuration successful")
 
 def resetRpmDb():
-    for rpmfile in glob.glob("%s/var/lib/rpm/__db.*" % ROOT_PATH):
+    for rpmfile in glob.glob("%s/var/lib/rpm/__db.*" % getSysroot()):
         try:
             os.unlink(rpmfile)
         except OSError as e:
diff --git a/pyanaconda/kickstart.py b/pyanaconda/kickstart.py
index df7b5e6..92a406a 100644
--- a/pyanaconda/kickstart.py
+++ b/pyanaconda/kickstart.py
@@ -40,7 +40,7 @@ import tempfile
 import subprocess
 import flags as flags_module
 from flags import flags
-from constants import *
+from constants import ADDON_PATHS
 import shlex
 import sys
 import urlgrabber
@@ -227,14 +227,14 @@ class Authconfig(commands.authconfig.FC3_Authconfig):
         args = ["--update", "--nostart"] + shlex.split(self.authconfig)
 
         if not flags.automatedInstall and \
-           (os.path.exists(ROOT_PATH + "/lib64/security/pam_fprintd.so") or \
-            os.path.exists(ROOT_PATH + "/lib/security/pam_fprintd.so")):
+           (os.path.exists(iutil.getSysroot() + "/lib64/security/pam_fprintd.so") or \
+            os.path.exists(iutil.getSysroot() + "/lib/security/pam_fprintd.so")):
             args += ["--enablefingerprint"]
 
         try:
-            iutil.execWithRedirect("/usr/sbin/authconfig", args, root=ROOT_PATH)
+            iutil.execInSysroot("/usr/sbin/authconfig", args)
         except OSError as msg:
-            log.error("Error running /usr/sbin/authconfig %s: %s", args, msg)
+            log.error("Error running /usr/sbin/authconfig %s: %s" %  (args, msg))
 
 class AutoPart(commands.autopart.F20_AutoPart):
     def execute(self, storage, ksdata, instClass):
@@ -470,7 +470,7 @@ class Realm(commands.realm.F19_Realm):
             # no explicit password arg using implicit --no-password
             pw_args = ["--no-password"]
 
-        argv = ["realm", "join", "--install", ROOT_PATH, "--verbose"] + \
+        argv = ["realm", "join", "--install", iutil.getSysroot(), "--verbose"] + \
                pw_args + self.join_args
         rc = -1
         try:
@@ -581,11 +581,11 @@ class Firewall(commands.firewall.F20_Firewall):
             args += [ "--service=%s" % (service,) ]
 
         cmd = "/usr/bin/firewall-offline-cmd"
-        if not os.path.exists(ROOT_PATH+cmd):
+        if not os.path.exists(iutil.getSysroot()+cmd):
             msg = _("%s is missing. Cannot setup firewall.") % (cmd,)
             raise KickstartError(msg)
         else:
-            iutil.execWithRedirect(cmd, args, root=ROOT_PATH)
+            iutil.execInSysroot(cmd, args)
 
 class Firstboot(commands.firstboot.FC3_Firstboot):
     def setup(self, *args):
@@ -598,7 +598,7 @@ class Firstboot(commands.firstboot.FC3_Firstboot):
                          "/lib/systemd/system/initial-setup-graphical.service",
                          "/lib/systemd/system/initial-setup-text.service")
 
-        if not any(os.path.exists(ROOT_PATH + path) for path in service_paths):
+        if not any(os.path.exists(iutil.getSysroot() + path) for path in service_paths):
             # none of the first boot utilities installed, nothing to do here
             return
 
@@ -607,13 +607,12 @@ class Firstboot(commands.firstboot.FC3_Firstboot):
         if self.firstboot == FIRSTBOOT_SKIP:
             action = "disable"
         elif self.firstboot == FIRSTBOOT_RECONFIG:
-            f = open(ROOT_PATH + "/etc/reconfigSys", "w+")
+            f = open(iutil.getSysroot() + "/etc/reconfigSys", "w+")
             f.close()
 
-        iutil.execWithRedirect("systemctl", [action, "firstboot-graphical.service",
+        iutil.execInSysroot("systemctl", [action, "firstboot-graphical.service",
                                                      "initial-setup-graphical.service",
-                                                     "initial-setup-text.service"],
-                               root=ROOT_PATH)
+                                                     "initial-setup-text.service"])
 
 class Group(commands.group.F12_Group):
     def execute(self, storage, ksdata, instClass, users):
@@ -621,7 +620,7 @@ class Group(commands.group.F12_Group):
 
         for grp in self.groupList:
             kwargs = grp.__dict__
-            kwargs.update({"root": ROOT_PATH})
+            kwargs.update({"root": iutil.getSysroot()})
             if not users.createGroup(grp.name, **kwargs):
                 log.error("Group %s already exists, not creating." % grp.name)
 
@@ -692,7 +691,7 @@ class IscsiName(commands.iscsiname.FC6_IscsiName):
 
 class Lang(commands.lang.F19_Lang):
     def execute(self, *args, **kwargs):
-        localization.write_language_configuration(self, ROOT_PATH)
+        localization.write_language_configuration(self, iutil.getSysroot())
 
 # no overrides needed here
 Eula = commands.eula.F20_Eula
@@ -902,7 +901,7 @@ class Logging(commands.logging.FC6_Logging):
 
 class Network(commands.network.RHEL7_Network):
     def execute(self, storage, ksdata, instClass):
-        network.write_network_config(storage, ksdata, instClass, ROOT_PATH)
+        network.write_network_config(storage, ksdata, instClass, iutil.getSysroot())
 
 class MultiPath(commands.multipath.FC6_MultiPath):
     def parse(self, args):
@@ -1326,7 +1325,7 @@ class SELinux(commands.selinux.FC3_SELinux):
             return
 
         try:
-            selinux_cfg = SimpleConfigFile(ROOT_PATH+"/etc/selinux/config")
+            selinux_cfg = SimpleConfigFile(iutil.getSysroot()+"/etc/selinux/config")
             selinux_cfg.read()
             selinux_cfg.set(("SELINUX", selinux_states[self.selinux]))
             selinux_cfg.write()
@@ -1339,12 +1338,10 @@ class Services(commands.services.FC6_Services):
         enabled = map(lambda s: s + ".service", self.enabled)
 
         if disabled:
-            iutil.execWithRedirect("systemctl", ["disable"] + disabled,
-                                   root=ROOT_PATH)
+            iutil.execInSysroot("systemctl", ["disable"] + disabled)
 
         if enabled:
-            iutil.execWithRedirect("systemctl", ["enable"] + enabled,
-                                   root=ROOT_PATH)
+            iutil.execInSysroot("systemctl", ["enable"] + enabled)
 
 class Timezone(commands.timezone.F18_Timezone):
     def __init__(self, *args):
@@ -1393,11 +1390,11 @@ class Timezone(commands.timezone.F18_Timezone):
                         "back to default (America/New_York)." % (self.timezone,))
             self.timezone = "America/New_York"
 
-        timezone.write_timezone_config(self, ROOT_PATH)
+        timezone.write_timezone_config(self, iutil.getSysroot())
 
         # write out NTP configuration (if set)
         if not self.nontp and self.ntpservers:
-            chronyd_conf_path = os.path.normpath(ROOT_PATH + ntp.NTP_CONFIG_FILE)
+            chronyd_conf_path = os.path.normpath(iutil.getSysroot() + ntp.NTP_CONFIG_FILE)
             try:
                 ntp.save_servers_to_config(self.ntpservers,
                                            conf_file_path=chronyd_conf_path)
@@ -1410,7 +1407,7 @@ class User(commands.user.F12_User):
 
         for usr in self.userList:
             kwargs = usr.__dict__
-            kwargs.update({"algo": algo, "root": ROOT_PATH})
+            kwargs.update({"algo": algo, "root": iutil.getSysroot()})
 
             # If the user password came from a kickstart and it is blank we
             # need to make sure the account is locked, not created with an
@@ -1515,7 +1512,7 @@ class ZFCP(commands.zfcp.F14_ZFCP):
 
 class Keyboard(commands.keyboard.F18_Keyboard):
     def execute(self, *args):
-        keyboard.write_keyboard_config(self, ROOT_PATH)
+        keyboard.write_keyboard_config(self, iutil.getSysroot())
 
     def dracutSetupArgs(self, *args):
         return keyboard.dracut_setup_args(self)
@@ -1542,7 +1539,7 @@ class SpokeRegistry(dict):
 
     # pylint: disable-msg=C0103
     def execute(self, storage, ksdata, instClass, users):
-        path = os.path.join(ROOT_PATH, "var", "lib", "inital-setup")
+        path = os.path.join(iutil.getSysroot(), "var", "lib", "inital-setup")
         try:
             os.makedirs(path, 0755)
         except OSError:
@@ -1748,7 +1745,7 @@ def runPostScripts(scripts):
             del(os.environ[var])
 
     log.info("Running kickstart %%post script(s)")
-    map (lambda s: s.run(ROOT_PATH), postScripts)
+    map (lambda s: s.run(iutil.getSysroot()), postScripts)
     log.info("All kickstart %%post script(s) have been run")
 
 def runPreScripts(scripts):
diff --git a/pyanaconda/packaging/__init__.py b/pyanaconda/packaging/__init__.py
index 47bb895..9b97149 100644
--- a/pyanaconda/packaging/__init__.py
+++ b/pyanaconda/packaging/__init__.py
@@ -377,8 +377,8 @@ class Payload(object):
             else:
                 cmpfunc = yum.rpmUtils.miscutils.compareVerOnly
 
-            files = glob.glob(ROOT_PATH + "/boot/vmlinuz-*")
-            files.extend(glob.glob(ROOT_PATH + "/boot/efi/EFI/redhat/vmlinuz-*"))
+            files = glob.glob(iutil.getSysroot() + "/boot/vmlinuz-*")
+            files.extend(glob.glob(iutil.getSysroot() + "/boot/efi/EFI/redhat/vmlinuz-*"))
             # strip off everything up to and including vmlinuz- to get versions
             # Ignore rescue kernels
             versions = [f.split("/")[-1][8:] for f in files if os.path.isfile(f) \
@@ -536,7 +536,7 @@ class Payload(object):
     ###
     def preInstall(self, packages=None, groups=None):
         """ Perform pre-installation tasks. """
-        iutil.mkdirChain(ROOT_PATH + "/root")
+        iutil.mkdirChain(iutil.getSysroot() + "/root")
 
         self._writeModuleBlacklist()
 
@@ -552,8 +552,8 @@ class Payload(object):
         if "modprobe.blacklist" not in flags.cmdline:
             return
 
-        iutil.mkdirChain(ROOT_PATH + "/etc/modprobe.d")
-        with open(ROOT_PATH + "/etc/modprobe.d/anaconda-blacklist.conf", "w") as f:
+        iutil.mkdirChain(iutil.getSysroot() + "/etc/modprobe.d")
+        with open(iutil.getSysroot() + "/etc/modprobe.d/anaconda-blacklist.conf", "w") as f:
             f.write("# Module blacklists written by anaconda\n")
             for module in flags.cmdline["modprobe.blacklist"].split():
                 f.write("blacklist %s\n" % module)
@@ -568,7 +568,7 @@ class Payload(object):
         # the firmware files in the common DD firmware directory
         for f in glob.glob(DD_FIRMWARE+"/*"):
             try:
-                shutil.copyfile(f, "%s/lib/firmware/" % ROOT_PATH)
+                shutil.copyfile(f, "%s/lib/firmware/" % iutil.getSysroot())
             except IOError as e:
                 log.error("Could not copy firmware file %s: %s" % (f, e.strerror))
             else:
@@ -576,12 +576,12 @@ class Payload(object):
 
         #copy RPMS
         for d in glob.glob(DD_RPMS):
-            shutil.copytree(d, ROOT_PATH + "/root/" + os.path.basename(d))
+            shutil.copytree(d, iutil.getSysroot() + "/root/" + os.path.basename(d))
 
         #copy modules and firmware into root's home directory
         if os.path.exists(DD_ALL):
             try:
-                shutil.copytree(DD_ALL, ROOT_PATH + "/root/DD")
+                shutil.copytree(DD_ALL, iutil.getSysroot() + "/root/DD")
             except IOError as e:
                 log.error("failed to copy driver disk files: %s" % e.strerror)
                 # XXX TODO: real error handling, as this is probably going to
@@ -603,26 +603,24 @@ class Payload(object):
         for kernel in self.kernelVersionList:
             log.info("recreating initrd for %s" % kernel)
             if not flags.imageInstall:
-                iutil.execWithRedirect("new-kernel-pkg",
-                                       ["--mkinitrd", "--dracut",
-                                        "--depmod", "--update", kernel],
-                                       root=ROOT_PATH)
+                iutil.execInSysroot("new-kernel-pkg",
+                                    ["--mkinitrd", "--dracut",
+                                    "--depmod", "--update", kernel])
             else:
                 # hostonly is not sensible for disk image installations
                 # using /dev/disk/by-uuid/ is necessary due to disk image naming
-                iutil.execWithRedirect("dracut",
-                                       ["-N",
-                                        "--persistent-policy", "by-uuid",
-                                        "-f", "/boot/initramfs-%s.img" % kernel,
-                                        kernel],
-                                        root=ROOT_PATH)
+                iutil.execInSysroot("dracut",
+                                    ["-N",
+                                     "--persistent-policy", "by-uuid",
+                                     "-f", "/boot/initramfs-%s.img" % kernel,
+                                    kernel])
 
         self._createdInitrds = True
 
 
     def _setDefaultBootTarget(self):
         """ Set the default systemd target for the system. """
-        if not os.path.exists(ROOT_PATH + "/etc/systemd/system"):
+        if not os.path.exists(iutil.getSysroot() + "/etc/systemd/system"):
             log.error("systemd is not installed -- can't set default target")
             return
 
@@ -635,7 +633,7 @@ class Payload(object):
         except ImportError:
             log.info("failed to import rpm -- not adjusting default runlevel")
         else:
-            ts = rpm.TransactionSet(ROOT_PATH)
+            ts = rpm.TransactionSet(iutil.getSysroot())
 
             # XXX one day this might need to account for anaconda's display mode
             if ts.dbMatch("provides", 'service(graphical-login)').count() and \
@@ -653,7 +651,7 @@ class Payload(object):
             pass
         else:
             iutil.resetRpmDb()
-            ts = rpm.TransactionSet(ROOT_PATH)
+            ts = rpm.TransactionSet(iutil.getSysroot())
 
             # Only add "rhgb quiet" on non-s390, non-serial installs
             if iutil.isConsoleOnVirtualTerminal() and \
diff --git a/pyanaconda/packaging/livepayload.py b/pyanaconda/packaging/livepayload.py
index 48c154f..09485e1 100644
--- a/pyanaconda/packaging/livepayload.py
+++ b/pyanaconda/packaging/livepayload.py
@@ -42,7 +42,7 @@ import glob
 
 from . import ImagePayload, PayloadSetupError, PayloadInstallError
 
-from pyanaconda.constants import INSTALL_TREE, ROOT_PATH, THREAD_LIVE_PROGRESS
+from pyanaconda.constants import INSTALL_TREE, THREAD_LIVE_PROGRESS
 from pyanaconda.constants import IMAGE_DIR
 
 from pyanaconda import iutil
@@ -61,7 +61,7 @@ class LiveImagePayload(ImagePayload):
     """ A LivePayload copies the source image onto the target system. """
     def __init__(self, *args, **kwargs):
         super(LiveImagePayload, self).__init__(*args, **kwargs)
-        # Used to adjust size of ROOT_PATH when files are already present
+        # Used to adjust size of sysroot when files are already present
         self._adj_size = 0
 
     def setup(self, storage):
@@ -91,7 +91,7 @@ class LiveImagePayload(ImagePayload):
         while self.pct < 100:
             dest_size = 0
             for mnt in mountpoints:
-                mnt_stat = os.statvfs(ROOT_PATH+mnt)
+                mnt_stat = os.statvfs(iutil.getSysroot()+mnt)
                 dest_size += mnt_stat.f_frsize * (mnt_stat.f_blocks - mnt_stat.f_bfree)
             if dest_size >= self._adj_size:
                 dest_size -= self._adj_size
@@ -118,7 +118,7 @@ class LiveImagePayload(ImagePayload):
         # file system boundaries
         args = ["-pogAXtlHrDx", "--exclude", "/dev/", "--exclude", "/proc/",
                 "--exclude", "/sys/", "--exclude", "/run/", "--exclude", "/boot/*rescue*",
-                "--exclude", "/etc/machine-id", INSTALL_TREE+"/", ROOT_PATH]
+                "--exclude", "/etc/machine-id", INSTALL_TREE+"/", iutil.getSysroot()]
         try:
             rc = iutil.execWithRedirect(cmd, args)
         except (OSError, RuntimeError) as e:
@@ -149,14 +149,13 @@ class LiveImagePayload(ImagePayload):
 
         # Live needs to create the rescue image before bootloader is written
         for kernel in self.kernelVersionList:
-            log.info("Generating rescue image for %s", kernel)
-            iutil.execWithRedirect("new-kernel-pkg",
-                                   ["--rpmposttrans", kernel],
-                                   root=ROOT_PATH)
+            log.info("Generating rescue image for %s" % kernel)
+            iutil.execInSysroot("new-kernel-pkg",
+                                ["--rpmposttrans", kernel])
 
         # Make sure the new system has a machine-id, it won't boot without it
-        if not os.path.exists(ROOT_PATH+"/etc/machine-id"):
-            iutil.execWithRedirect("systemd-machine-id-setup", [], root=ROOT_PATH)
+        if not os.path.exists(iutil.getSysroot()+"/etc/machine-id"):
+            iutil.execInSysroot("systemd-machine-id-setup", [])
 
     @property
     def spaceRequired(self):
@@ -216,7 +215,7 @@ class LiveImageKSPayload(LiveImagePayload):
     def __init__(self, *args, **kwargs):
         super(LiveImageKSPayload, self).__init__(*args, **kwargs)
         self._min_size = 0
-        self.image_path = ROOT_PATH+"/disk.img"
+        self.image_path = iutil.getSysroot()+"/disk.img"
 
     def setup(self, storage):
         """ Check the availability and size of the image.
@@ -263,10 +262,10 @@ class LiveImageKSPayload(LiveImagePayload):
         """ Download image and loopback mount it.
 
             This is called after partitioning is setup, we now have space
-            to grab the image. Download it to ROOT_PATH and provide feedback
+            to grab the image. Download it to sysroot and provide feedback
             during the download (using urlgrabber callback).
         """
-        # Setup urlgrabber and call back to download image to ROOT_PATH
+        # Setup urlgrabber and call back to download image to sysroot
         progress = URLGrabberProgress()
         ugopts = {"ssl_verify_peer": not self.data.method.noverifyssl,
                   "ssl_verify_host": not self.data.method.noverifyssl,
diff --git a/pyanaconda/packaging/tarpayload.py b/pyanaconda/packaging/tarpayload.py
index 26922af..fe78478 100644
--- a/pyanaconda/packaging/tarpayload.py
+++ b/pyanaconda/packaging/tarpayload.py
@@ -79,7 +79,7 @@ class TarPayload(ArchivePayload):
 
     def install(self):
         try:
-            self.archive.extractall(path=ROOT_PATH)
+            self.archive.extractall(path=iutil.getSysroot())
         except (tarfile.ExtractError, tarfile.CompressionError) as e:
             log.error("extracting tar archive %s: %s" % (self.image_file, e))
 
diff --git a/pyanaconda/packaging/yumpayload.py b/pyanaconda/packaging/yumpayload.py
index 211e5e9..a81b5bc 100644
--- a/pyanaconda/packaging/yumpayload.py
+++ b/pyanaconda/packaging/yumpayload.py
@@ -288,7 +288,7 @@ reposdir=%s
     def _yumCacheDirHack(self):
         # This is what it takes to get yum to use a cache dir outside the
         # install root. We do this so we don't have to re-gather repo meta-
-        # data after we change the install root to ROOT_PATH, which can only
+        # data after we change the install root to sysroot, which can only
         # happen after we've enabled the new storage configuration.
         with _yum_lock:
             if not self._yum.conf.cachedir.startswith(self._yum.conf.installroot):
@@ -363,7 +363,7 @@ reposdir=%s
         self._writeYumConfig()
         self._writeLangpacksConfig()
         log.debug("setting releasever to previous value of %s" % releasever)
-        self._resetYum(root=ROOT_PATH, keep_cache=True, releasever=releasever)
+        self._resetYum(root=iutil.getSysroot(), keep_cache=True, releasever=releasever)
         self._yumCacheDirHack()
         self.gatherRepoMetadata()
 
@@ -1629,7 +1629,7 @@ reposdir=%s
             "PROGRESS_POST"    : _("Performing post-installation setup tasks")
         }
 
-        ts_file = ROOT_PATH+"/anaconda-yum.yumtx"
+        ts_file = iutil.getSysroot()+"/anaconda-yum.yumtx"
         with _yum_lock:
             # Save the transaction, this will be loaded and executed by the new
             # process.
@@ -1646,7 +1646,7 @@ reposdir=%s
         args = ["--config", "/tmp/anaconda-yum.conf",
                 "--tsfile", ts_file,
                 "--rpmlog", script_log,
-                "--installroot", ROOT_PATH,
+                "--installroot", iutil.getSysroot(),
                 "--release", release,
                 "--arch", blivet.arch.getArch()]
 
@@ -1702,7 +1702,7 @@ reposdir=%s
         #        all yumvars and writing out the expanded pairs to the conf
         yb = yum.YumBase()
         yum_conf_path = "/etc/yum.conf"
-        yb.preconf.fn = ROOT_PATH + yum_conf_path
+        yb.preconf.fn = iutil.getSysroot() + yum_conf_path
         yb.conf.multilib_policy = "all"
 
         # this will appear in yum.conf, which is silly
@@ -1712,7 +1712,7 @@ reposdir=%s
         cachedir = yb.conf.cachedir.replace("/%s/" % yb.arch.basearch,
                                             "/$basearch/")
         yb.conf.cachedir = cachedir
-        yum_conf = ROOT_PATH + yum_conf_path
+        yum_conf = iutil.getSysroot() + yum_conf_path
         if os.path.exists(yum_conf):
             try:
                 os.rename(yum_conf, yum_conf + ".anacbak")
diff --git a/pyanaconda/rescue.py b/pyanaconda/rescue.py
index ff74f6b..e0c4e13 100644
--- a/pyanaconda/rescue.py
+++ b/pyanaconda/rescue.py
@@ -40,7 +40,7 @@ import subprocess
 
 from snack import ButtonChoiceWindow, ListboxChoiceWindow,SnackScreen
 
-from constants import ANACONDA_CLEANUP, ROOT_PATH
+from constants import ANACONDA_CLEANUP
 from constants_text import TEXT_OK_BUTTON, TEXT_NO_BUTTON, TEXT_YES_BUTTON
 from text import WaitWindow, OkCancelWindow, ProgressWindow, PassphraseEntryWindow
 from flags import flags
@@ -308,7 +308,7 @@ def doRescue(intf, rescue_mount, ksdata):
                   "\n\n"
                   "If for some reason this process fails you can choose 'Skip' "
                   "and this step will be skipped and you will go directly to a "
-                  "command shell.\n\n") % (ROOT_PATH,),
+                  "command shell.\n\n") % (iutil.getSysroot(),),
                   [_("Continue"), _("Read-Only"), _("Skip")] )
 
             if rc == _("Skip").lower():
@@ -380,14 +380,14 @@ def doRescue(intf, rescue_mount, ksdata):
                 rootmounted = False
             else:
                 if flags.automatedInstall:
-                    log.info("System has been mounted under: %s" % ROOT_PATH)
+                    log.info("System has been mounted under: %s" % iutil.getSysroot())
                 else:
                     ButtonChoiceWindow(intf.screen, _("Rescue"),
                        _("Your system has been mounted under %(rootPath)s.\n\n"
                          "Press <return> to get a shell. If you would like to "
                          "make your system the root environment, run the command:\n\n"
                          "\tchroot %(rootPath)s\n\n%(msg)s") %
-                                       {'rootPath': ROOT_PATH,
+                                       {'rootPath': iutil.getSysroot(),
                                         'msg': msg},
                                        [_("OK")] )
                 rootmounted = True
@@ -404,7 +404,7 @@ def doRescue(intf, rescue_mount, ksdata):
                     # we have to catch the possible exception
                     # because we support read-only mounting
                     try:
-                        fd = open("%s/.autorelabel" % ROOT_PATH, "w+")
+                        fd = open("%s/.autorelabel" % iutil.getSysroot(), "w+")
                         fd.close()
                     except IOError:
                         log.warning("cannot touch /.autorelabel")
@@ -456,7 +456,7 @@ def doRescue(intf, rescue_mount, ksdata):
                 ButtonChoiceWindow(intf.screen, _("Rescue"),
                     _("An error occurred trying to mount some or all of your "
                       "system. Some of it may be mounted under %s.\n\n"
-                      "Press <return> to get a shell.") % ROOT_PATH + msg,
+                      "Press <return> to get a shell.") % iutil.getSysroot() + msg,
                       [_("OK")] )
     else:
         if flags.automatedInstall and ksdata.reboot.action in [KS_REBOOT, KS_SHUTDOWN]:
@@ -480,10 +480,10 @@ def doRescue(intf, rescue_mount, ksdata):
     if rootmounted and not readOnly:
         sto.makeMtab()
         try:
-            makeResolvConf(ROOT_PATH)
+            makeResolvConf(iutil.getSysroot())
         except (OSError, IOError) as e:
             log.error("error making a resolv.conf: %s" %(e,))
-        msgStr = _("Your system is mounted under the %s directory.") % (ROOT_PATH,)
+        msgStr = _("Your system is mounted under the %s directory.") % (iutil.getSysroot(),)
         ButtonChoiceWindow(intf.screen, _("Rescue"), msgStr, [_("OK")] )
 
     # we do not need ncurses anymore, shut them down
diff --git a/pyanaconda/users.py b/pyanaconda/users.py
index 9e09be0..2e40465 100644
--- a/pyanaconda/users.py
+++ b/pyanaconda/users.py
@@ -29,7 +29,6 @@ import os.path
 import iutil
 import pwquality
 import re
-from pyanaconda.constants import ROOT_PATH
 from pyanaconda.iutil import strip_accents
 from pyanaconda.i18n import _
 
@@ -192,7 +191,7 @@ class Users:
         """
 
         childpid = os.fork()
-        root = kwargs.get("root", ROOT_PATH)
+        root = kwargs.get("root", iutil.getSysroot())
 
         if not childpid:
             if not root in ["","/"]:
@@ -258,7 +257,7 @@ class Users:
                         available one is used.
         """
         childpid = os.fork()
-        root = kwargs.get("root", ROOT_PATH)
+        root = kwargs.get("root", iutil.getSysroot())
 
         if not childpid:
             if not root in ["","/"]:
@@ -358,7 +357,7 @@ class Users:
         else:
             return False
 
-    def checkUserExists(self, username, root=ROOT_PATH):
+    def checkUserExists(self, username, root=iutil.getSysroot()):
         childpid = os.fork()
 
         if not childpid:
-- 
1.9.3