[PATCH python-blivet rhel7-branch] Split ROOT_PATH usage into getTargetPhysicalRoot()/getSysroot()

Radek Vykydal rvykydal at redhat.com
Mon Jul 14 11:36:39 UTC 2014


From: Colin Walters <walters at verbum.org>

This mirrors the change to Anaconda, in order to enable OSTree
support.

For OSTree, the location of the OS checkout (and e.g. /etc/fstab) is
really in /ostree/deploy/$osname/deploy/$revision/etc/fstab.

In order to properly support OSTree, Blivet will need to gain an
understanding of the separation between the physical system / and the
target root.

This patch will be used in Anaconda, which will call setSysroot()
attribute after the root being installed is laid out.

After that, when we call write(), the fstab data will be correctly
written into the target root.

Related: rhbz#1113535
Port of rpmostreepayload patches from master
commit 5b39c90ae582a8fb008c3633954a33b58394802c
---
 blivet/__init__.py        | 102 +++++++++++++++++++++++++++++++++-------------
 blivet/devicelibs/dasd.py |   4 +-
 blivet/fcoe.py            |   8 ++--
 blivet/iscsi.py           |  14 +++----
 blivet/util.py            |   4 +-
 blivet/zfcp.py            |   8 ++--
 6 files changed, 92 insertions(+), 48 deletions(-)

diff --git a/blivet/__init__.py b/blivet/__init__.py
index 85b67da..6b127d7 100644
--- a/blivet/__init__.py
+++ b/blivet/__init__.py
@@ -30,7 +30,10 @@ __version__ = '0.18.34'
 ## enable_installer_mode is called.
 ##
 isys = None
+iutil = None
 ROOT_PATH = '/'
+_storageRoot = ROOT_PATH
+_sysroot = ROOT_PATH
 shortProductName = 'blivet'
 productName = 'blivet'
 bootLoaderError = Exception
@@ -99,7 +102,10 @@ log = logging.getLogger("blivet")
 
 def enable_installer_mode():
     global isys
+    global iutil
     global ROOT_PATH
+    global _storageRoot
+    global _sysroot
     global shortProductName
     global productName
     global get_bootloader
@@ -108,6 +114,7 @@ def enable_installer_mode():
     global ERROR_RAISE
 
     from pyanaconda import isys
+    from pyanaconda import iutil
     from pyanaconda.constants import ROOT_PATH
     from pyanaconda.constants import shortProductName
     from pyanaconda.constants import productName
@@ -116,11 +123,48 @@ def enable_installer_mode():
     from pyanaconda.errors import errorHandler
     from pyanaconda.errors import ERROR_RAISE
 
+    if hasattr(iutil, 'getTargetPhysicalRoot'):
+        # Introduced in newer Anaconda
+        _storageRoot = iutil.getTargetPhysicalRoot()
+        _sysroot = iutil.getSysroot()
+    else:
+        _storageRoot = _sysroot = ROOT_PATH
+
     from pyanaconda.anaconda_log import program_log_lock
     util.program_log_lock = program_log_lock
 
     flags.installer_mode = True
 
+def getSysroot():
+    """Returns the path to the target OS installation.
+
+    For traditional installations, this is the same as the physical
+    storage root.
+    """
+    return _sysroot
+
+def getTargetPhysicalRoot():
+    """Returns the path to the "physical" storage root.
+
+    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.
+    """
+    return _storageRoot
+
+def setSysroot(storageRoot, sysroot=None):
+    """Change the OS root path.
+       :param storageRoot: The root of physical storage
+       :param sysroot: An optional chroot subdirectory of storageRoot
+
+    Change the
+    """
+    global _storageRoot
+    global _sysroot
+    _storageRoot = _sysroot = storageRoot
+    if sysroot is not None:
+        _sysroot = sysroot
+
 def storageInitialize(storage, ksdata, protected):
     """ Perform installer-specific storage initialization. """
     from pyanaconda.flags import flags as anaconda_flags
@@ -202,7 +246,7 @@ def writeEscrowPackets(storage):
     backupPassphrase = generateBackupPassphrase()
 
     try:
-        escrowDir = ROOT_PATH + "/root"
+        escrowDir = _sysroot + "/root"
         log.debug("escrow: writing escrow packets to %s", escrowDir)
         util.makedirs(escrowDir)
         for device in escrowDevices:
@@ -1665,22 +1709,22 @@ class Blivet(object):
         return list(pkgs)
 
     def write(self):
-        if not os.path.isdir("%s/etc" % ROOT_PATH):
-            os.mkdir("%s/etc" % ROOT_PATH)
+        if not os.path.isdir("%s/etc" % _sysroot):
+            os.mkdir("%s/etc" % _sysroot)
 
         self.fsset.write()
         self.makeMtab()
-        self.iscsi.write(ROOT_PATH, self)
-        self.fcoe.write(ROOT_PATH)
-        self.zfcp.write(ROOT_PATH)
-        write_dasd_conf(self.dasd, ROOT_PATH)
+        self.iscsi.write(_sysroot, self)
+        self.fcoe.write(_sysroot)
+        self.zfcp.write(_sysroot)
+        write_dasd_conf(self.dasd, _sysroot)
 
     def turnOnSwap(self, upgrading=None):
-        self.fsset.turnOnSwap(rootPath=ROOT_PATH,
+        self.fsset.turnOnSwap(rootPath=_sysroot,
                               upgrading=upgrading)
 
     def mountFilesystems(self, raiseErrors=None, readOnly=None, skipRoot=False):
-        self.fsset.mountFilesystems(rootPath=ROOT_PATH,
+        self.fsset.mountFilesystems(rootPath=_sysroot,
                                     raiseErrors=raiseErrors,
                                     readOnly=readOnly, skipRoot=skipRoot)
 
@@ -1797,7 +1841,7 @@ class Blivet(object):
     def makeMtab(self):
         path = "/etc/mtab"
         target = "/proc/self/mounts"
-        path = os.path.normpath("%s/%s" % (ROOT_PATH, path))
+        path = os.path.normpath("%s/%s" % (_sysroot, path))
 
         if os.path.islink(path):
             # return early if the mtab symlink is already how we like it
@@ -2130,7 +2174,7 @@ def mountExistingSystem(fsset, rootDevice,
                         allowDirty=None, dirtyCB=None,
                         readOnly=None):
     """ Mount filesystems specified in rootDevice's /etc/fstab file. """
-    rootPath = ROOT_PATH
+    rootPath = _sysroot
     if dirtyCB is None:
         dirtyCB = lambda l: False
 
@@ -2172,7 +2216,7 @@ def mountExistingSystem(fsset, rootDevice,
     if dirtyDevs and (not allowDirty or dirtyCB(dirtyDevs)):
         raise DirtyFSError("\n".join(dirtyDevs))
 
-    fsset.mountFilesystems(rootPath=ROOT_PATH, readOnly=readOnly, skipRoot=True)
+    fsset.mountFilesystems(rootPath=_sysroot, readOnly=readOnly, skipRoot=True)
 
 
 class BlkidTab(object):
@@ -2529,7 +2573,7 @@ class FSSet(object):
                 loop mounts?
         """
         if not chroot or not os.path.isdir(chroot):
-            chroot = ROOT_PATH
+            chroot = _sysroot
 
         path = "%s/etc/fstab" % chroot
         if not os.access(path, os.R_OK):
@@ -2703,10 +2747,10 @@ class FSSet(object):
         self.active = False
 
     def createSwapFile(self, device, size):
-        """ Create and activate a swap file under ROOT_PATH. """
+        """ Create and activate a swap file under storage root. """
         filename = "/SWAP"
         count = 0
-        basedir = os.path.normpath("%s/%s" % (ROOT_PATH,
+        basedir = os.path.normpath("%s/%s" % (getTargetPhysicalRoot(),
                                               device.format.mountpoint))
         while os.path.exists("%s/%s" % (basedir, filename)) or \
               self.devicetree.getDeviceByName(filename):
@@ -2727,10 +2771,10 @@ class FSSet(object):
 
     def mkDevRoot(self):
         root = self.rootDevice
-        dev = "%s/%s" % (ROOT_PATH, root.path)
-        if not os.path.exists("%s/dev/root" %(ROOT_PATH,)) and os.path.exists(dev):
+        dev = "%s/%s" % (_sysroot, root.path)
+        if not os.path.exists("%s/dev/root" %(_sysroot,)) and os.path.exists(dev):
             rdev = os.stat(dev).st_rdev
-            os.mknod("%s/dev/root" % (ROOT_PATH,), stat.S_IFBLK | 0600, rdev)
+            os.mknod("%s/dev/root" % (_sysroot,), stat.S_IFBLK | 0600, rdev)
 
     @property
     def swapDevices(self):
@@ -2742,7 +2786,7 @@ class FSSet(object):
 
     @property
     def rootDevice(self):
-        for path in ["/", ROOT_PATH]:
+        for path in ["/", getTargetPhysicalRoot()]:
             for device in self.devices:
                 try:
                     mountpoint = device.format.mountpoint
@@ -2755,19 +2799,19 @@ class FSSet(object):
     def write(self):
         """ write out all config files based on the set of filesystems """
         # /etc/fstab
-        fstab_path = os.path.normpath("%s/etc/fstab" % ROOT_PATH)
+        fstab_path = os.path.normpath("%s/etc/fstab" % _sysroot)
         fstab = self.fstab()
         open(fstab_path, "w").write(fstab)
 
         # /etc/crypttab
-        crypttab_path = os.path.normpath("%s/etc/crypttab" % ROOT_PATH)
+        crypttab_path = os.path.normpath("%s/etc/crypttab" % _sysroot)
         crypttab = self.crypttab()
         origmask = os.umask(0077)
         open(crypttab_path, "w").write(crypttab)
         os.umask(origmask)
 
         # /etc/mdadm.conf
-        mdadm_path = os.path.normpath("%s/etc/mdadm.conf" % ROOT_PATH)
+        mdadm_path = os.path.normpath("%s/etc/mdadm.conf" % _sysroot)
         mdadm_conf = self.mdadmConf()
         if mdadm_conf:
             open(mdadm_path, "w").write(mdadm_conf)
@@ -2900,11 +2944,11 @@ def getReleaseString():
     relVer = None
 
     try:
-        relArch = util.capture_output(["arch"], root=ROOT_PATH).strip()
+        relArch = util.capture_output(["arch"], root=_sysroot).strip()
     except:
         relArch = None
 
-    filename = "%s/etc/redhat-release" % ROOT_PATH
+    filename = "%s/etc/redhat-release" % getSysroot()
     if os.access(filename, os.R_OK):
         with open(filename) as f:
             try:
@@ -2923,8 +2967,8 @@ def getReleaseString():
     return (relArch, relName, relVer)
 
 def findExistingInstallations(devicetree):
-    if not os.path.exists(ROOT_PATH):
-        util.makedirs(ROOT_PATH)
+    if not os.path.exists(getTargetPhysicalRoot()):
+        util.makedirs(getTargetPhysicalRoot())
 
     roots = []
     for device in devicetree.leaves:
@@ -2940,7 +2984,7 @@ def findExistingInstallations(devicetree):
 
         options = device.format.options + ",ro"
         try:
-            device.format.mount(options=options, mountpoint=ROOT_PATH)
+            device.format.mount(options=options, mountpoint=getSysroot())
         except Exception as e:
             log.warning("mount of %s as %s failed: %s" % (device.name,
                                                           device.format.type,
@@ -2948,7 +2992,7 @@ def findExistingInstallations(devicetree):
             device.teardown()
             continue
 
-        if not os.access(ROOT_PATH + "/etc/fstab", os.R_OK):
+        if not os.access(getSysroot() + "/etc/fstab", os.R_OK):
             device.teardown(recursive=True)
             continue
 
@@ -3000,7 +3044,7 @@ class Root(object):
 def parseFSTab(devicetree, chroot=None):
     """ parse /etc/fstab and return a tuple of a mount dict and swap list """
     if not chroot or not os.path.isdir(chroot):
-        chroot = ROOT_PATH
+        chroot = _sysroot
 
     mounts = {}
     swaps = []
diff --git a/blivet/devicelibs/dasd.py b/blivet/devicelibs/dasd.py
index 7eb2551..5beb11d 100644
--- a/blivet/devicelibs/dasd.py
+++ b/blivet/devicelibs/dasd.py
@@ -110,14 +110,14 @@ def dasd_needs_format(dasd):
     return False
 
 
-def write_dasd_conf(disks, ROOT_PATH):
+def write_dasd_conf(disks, root):
     """ Write /etc/dasd.conf to target system for all DASD devices
         configured during installation.
     """
     if not (arch.isS390() or disks):
         return
 
-    with open(os.path.realpath(ROOT_PATH + "/etc/dasd.conf"), "w") as f:
+    with open(os.path.realpath(root + "/etc/dasd.conf"), "w") as f:
         for dasd in sorted(disks, key=lambda d: d.name):
             fields = [dasd.busid] + dasd.getOpts()
             f.write("%s\n" % " ".join(fields),)
diff --git a/blivet/fcoe.py b/blivet/fcoe.py
index 42d7550..71ffbcb 100644
--- a/blivet/fcoe.py
+++ b/blivet/fcoe.py
@@ -149,15 +149,15 @@ class fcoe(object):
 
         return error_msg
 
-    def write(self, ROOT_PATH):
+    def write(self, root):
         if not self.nics:
             return
 
-        if not os.path.isdir(ROOT_PATH + "/etc/fcoe"):
-            os.makedirs(ROOT_PATH + "/etc/fcoe", 0755)
+        if not os.path.isdir(root + "/etc/fcoe"):
+            os.makedirs(root + "/etc/fcoe", 0755)
 
         for nic, dcb, auto_vlan in self.nics:
-            fd = os.open(ROOT_PATH + "/etc/fcoe/cfg-" + nic,
+            fd = os.open(root + "/etc/fcoe/cfg-" + nic,
                          os.O_RDWR | os.O_CREAT)
             os.write(fd, '# Created by anaconda\n')
             os.write(fd, '# Enable/Disable FCoE service at the Ethernet port\n')
diff --git a/blivet/iscsi.py b/blivet/iscsi.py
index fceb881..eb640cd 100644
--- a/blivet/iscsi.py
+++ b/blivet/iscsi.py
@@ -360,7 +360,7 @@ class iscsi(object):
 
         self.stabilize()
 
-    def write(self, ROOT_PATH, storage):
+    def write(self, root, storage):
         if not self.initiatorSet:
             return
 
@@ -377,17 +377,17 @@ class iscsi(object):
             if autostart:
                 node.setParameter("node.startup", "automatic")
 
-        if not os.path.isdir(ROOT_PATH + "/etc/iscsi"):
-            os.makedirs(ROOT_PATH + "/etc/iscsi", 0755)
-        fd = os.open(ROOT_PATH + INITIATOR_FILE, os.O_RDWR | os.O_CREAT)
+        if not os.path.isdir(root + "/etc/iscsi"):
+            os.makedirs(root + "/etc/iscsi", 0755)
+        fd = os.open(root + INITIATOR_FILE, os.O_RDWR | os.O_CREAT)
         os.write(fd, "InitiatorName=%s\n" %(self.initiator))
         os.close(fd)
 
         # copy "db" files.  *sigh*
-        if os.path.isdir(ROOT_PATH + "/var/lib/iscsi"):
-            shutil.rmtree(ROOT_PATH + "/var/lib/iscsi")
+        if os.path.isdir(root + "/var/lib/iscsi"):
+            shutil.rmtree(root + "/var/lib/iscsi")
         if os.path.isdir("/var/lib/iscsi"):
-            shutil.copytree("/var/lib/iscsi", ROOT_PATH + "/var/lib/iscsi",
+            shutil.copytree("/var/lib/iscsi", root + "/var/lib/iscsi",
                             symlinks=True)
 
     def getNode(self, name, address, port, iface):
diff --git a/blivet/util.py b/blivet/util.py
index d43b252..505acc6 100644
--- a/blivet/util.py
+++ b/blivet/util.py
@@ -277,13 +277,13 @@ def makedirs(path):
 
 def copy_to_system(source):
     # do the import now because enable_installer_mode() has finally been called.
-    from . import ROOT_PATH
+    from . import getSysroot
 
     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 = getSysroot() + source
     target_dir = os.path.dirname(target)
     log.debug("copy_to_system: '%s' -> '%s'." % (source, target))
     if not os.path.isdir(target_dir):
diff --git a/blivet/zfcp.py b/blivet/zfcp.py
index cf8ec40..565c201 100644
--- a/blivet/zfcp.py
+++ b/blivet/zfcp.py
@@ -409,15 +409,15 @@ class ZFCP:
             except ValueError as e:
                 log.warn(str(e))
 
-    def write(self, ROOT_PATH):
+    def write(self, root):
         if len(self.fcpdevs) == 0:
             return
-        f = open(ROOT_PATH + zfcpconf, "w")
+        f = open(root + zfcpconf, "w")
         for d in self.fcpdevs:
             f.write("%s\n" %(d,))
         f.close()
-        
-        f = open(ROOT_PATH + "/etc/modprobe.conf", "a")
+
+        f = open(root + "/etc/modprobe.conf", "a")
         f.write("alias scsi_hostadapter zfcp\n")
         f.close()
 
-- 
1.9.0



More information about the anaconda-patches mailing list