|
|
b45ed7 |
From 13acd1e7439fe6e587b0f01843755a493a83c88e Mon Sep 17 00:00:00 2001
|
|
|
b45ed7 |
From: Colin Walters <walters@verbum.org>
|
|
|
b45ed7 |
Date: Thu, 27 Jul 2017 10:43:24 -0400
|
|
|
b45ed7 |
Subject: [PATCH] rpmostreepayload: Rollup backport of Fedora patches
|
|
|
b45ed7 |
|
|
|
b45ed7 |
This rolls up all of <https://github.com/rhinstaller/anaconda/pull/1129> which
|
|
|
b45ed7 |
is basically mount handling, plus the pull-local optimization for kickstarts.
|
|
|
b45ed7 |
|
|
|
b45ed7 |
We need to change the implementation for the mount setup, since
|
|
|
b45ed7 |
things work differently in RHEL7 vs Fedora since commit
|
|
|
b45ed7 |
664ef7b43f9102aa9332d0db5b7d13f8ece436f0.
|
|
|
b45ed7 |
|
|
|
b45ed7 |
The code that changed in `pyanaconda/install.py` only applied to ostree-based
|
|
|
b45ed7 |
payloads (where we introduced the physical vs sysroot distinction), so should be
|
|
|
b45ed7 |
safe for backporting.
|
|
|
b45ed7 |
|
|
|
b45ed7 |
Resolves: rhbz#1459623
|
|
|
b45ed7 |
---
|
|
|
b45ed7 |
pyanaconda/install.py | 17 +---
|
|
|
b45ed7 |
pyanaconda/packaging/rpmostreepayload.py | 129 ++++++++++++++++++++++++++-----
|
|
|
b45ed7 |
2 files changed, 111 insertions(+), 35 deletions(-)
|
|
|
b45ed7 |
|
|
|
b45ed7 |
diff --git a/pyanaconda/install.py b/pyanaconda/install.py
|
|
|
b45ed7 |
index 26e1b2680..a711813af 100644
|
|
|
b45ed7 |
--- a/pyanaconda/install.py
|
|
|
b45ed7 |
+++ b/pyanaconda/install.py
|
|
|
b45ed7 |
@@ -253,24 +253,9 @@ def doInstall(storage, payload, ksdata, instClass):
|
|
|
b45ed7 |
if iutil.getSysroot() != iutil.getTargetPhysicalRoot():
|
|
|
b45ed7 |
blivet.setSysroot(iutil.getTargetPhysicalRoot(),
|
|
|
b45ed7 |
iutil.getSysroot())
|
|
|
b45ed7 |
-
|
|
|
b45ed7 |
- # Now that we have the FS layout in the target, umount
|
|
|
b45ed7 |
- # things that were in the legacy sysroot, and put them in
|
|
|
b45ed7 |
- # the target root, except for the physical /. First,
|
|
|
b45ed7 |
- # unmount all target filesystems.
|
|
|
b45ed7 |
- storage.umountFilesystems()
|
|
|
b45ed7 |
-
|
|
|
b45ed7 |
- # Explicitly mount the root on the physical sysroot
|
|
|
b45ed7 |
- rootmnt = storage.mountpoints.get('/')
|
|
|
b45ed7 |
- rootmnt.setup()
|
|
|
b45ed7 |
- rootmnt.format.setup(options=rootmnt.format.options, chroot=iutil.getTargetPhysicalRoot())
|
|
|
b45ed7 |
-
|
|
|
b45ed7 |
+ # Note this changed for RHEL 7.5; see comments in rpmostreepayload.py.
|
|
|
b45ed7 |
payload.prepareMountTargets(storage)
|
|
|
b45ed7 |
|
|
|
b45ed7 |
- # Everything else goes in the target root, including /boot
|
|
|
b45ed7 |
- # since the bootloader code will expect to find /boot
|
|
|
b45ed7 |
- # inside the chroot.
|
|
|
b45ed7 |
- storage.mountFilesystems(skipRoot=True)
|
|
|
b45ed7 |
storage.write()
|
|
|
b45ed7 |
|
|
|
b45ed7 |
# Do bootloader.
|
|
|
b45ed7 |
diff --git a/pyanaconda/packaging/rpmostreepayload.py b/pyanaconda/packaging/rpmostreepayload.py
|
|
|
b45ed7 |
index da7650d3b..a472fa0bc 100644
|
|
|
b45ed7 |
--- a/pyanaconda/packaging/rpmostreepayload.py
|
|
|
b45ed7 |
+++ b/pyanaconda/packaging/rpmostreepayload.py
|
|
|
b45ed7 |
@@ -48,7 +48,7 @@ class RPMOSTreePayload(ArchivePayload):
|
|
|
b45ed7 |
super(RPMOSTreePayload, self).__init__(data)
|
|
|
b45ed7 |
|
|
|
b45ed7 |
self._base_remote_args = None
|
|
|
b45ed7 |
- self._binds = []
|
|
|
b45ed7 |
+ self._internal_mounts = []
|
|
|
b45ed7 |
self._sysroot_path = None
|
|
|
b45ed7 |
|
|
|
b45ed7 |
@property
|
|
|
b45ed7 |
@@ -166,8 +166,21 @@ class RPMOSTreePayload(ArchivePayload):
|
|
|
b45ed7 |
progress = OSTree.AsyncProgress.new()
|
|
|
b45ed7 |
progress.connect('changed', self._pullProgressCb)
|
|
|
b45ed7 |
|
|
|
b45ed7 |
+ pull_opts = {'refs': GLib.Variant('as', [ostreesetup.ref])}
|
|
|
b45ed7 |
+ # If we're doing a kickstart, we can at least use the content as a reference:
|
|
|
b45ed7 |
+ # See <https://github.com/rhinstaller/anaconda/issues/1117>
|
|
|
b45ed7 |
+ # The first path here is used by <https://pagure.io/fedora-lorax-templates>
|
|
|
b45ed7 |
+ # and the second by <https://github.com/projectatomic/rpm-ostree-toolbox/>
|
|
|
b45ed7 |
+ if OSTree.check_version(2017, 8):
|
|
|
b45ed7 |
+ for path in ['/ostree/repo', '/install/ostree/repo']:
|
|
|
b45ed7 |
+ if os.path.isdir(path + '/objects'):
|
|
|
b45ed7 |
+ pull_opts['localcache-repos'] = GLib.Variant('as', [path])
|
|
|
b45ed7 |
+ break
|
|
|
b45ed7 |
+
|
|
|
b45ed7 |
try:
|
|
|
b45ed7 |
- repo.pull(ostreesetup.remote, [ostreesetup.ref], 0, progress, cancellable)
|
|
|
b45ed7 |
+ repo.pull_with_options(ostreesetup.remote,
|
|
|
b45ed7 |
+ GLib.Variant('a{sv}', pull_opts),
|
|
|
b45ed7 |
+ progress, cancellable)
|
|
|
b45ed7 |
except GLib.GError as e:
|
|
|
b45ed7 |
exn = PayloadInstallError("Failed to pull from repository: %s" % e)
|
|
|
b45ed7 |
log.error(str(exn))
|
|
|
b45ed7 |
@@ -176,6 +189,7 @@ class RPMOSTreePayload(ArchivePayload):
|
|
|
b45ed7 |
iutil.ipmi_abort(scripts=self.data.scripts)
|
|
|
b45ed7 |
sys.exit(1)
|
|
|
b45ed7 |
|
|
|
b45ed7 |
+ log.info("ostree pull: " + (progress.get_status() or ""))
|
|
|
b45ed7 |
progressQ.send_message(_("Preparing deployment of %s") % (ostreesetup.ref, ))
|
|
|
b45ed7 |
|
|
|
b45ed7 |
self._safeExecWithRedirect("ostree",
|
|
|
b45ed7 |
@@ -213,25 +227,102 @@ class RPMOSTreePayload(ArchivePayload):
|
|
|
b45ed7 |
|
|
|
b45ed7 |
mainctx.pop_thread_default()
|
|
|
b45ed7 |
|
|
|
b45ed7 |
+ def _setupInternalBindmount(self, src, dest=None,
|
|
|
b45ed7 |
+ src_physical=True,
|
|
|
b45ed7 |
+ bind_ro=False,
|
|
|
b45ed7 |
+ recurse=True):
|
|
|
b45ed7 |
+ """Internal API for setting up bind mounts between the physical root and
|
|
|
b45ed7 |
+ sysroot, also ensures we track them in self._internal_mounts so we can
|
|
|
b45ed7 |
+ cleanly unmount them.
|
|
|
b45ed7 |
+
|
|
|
b45ed7 |
+ :param src: Source path, will be prefixed with physical or sysroot
|
|
|
b45ed7 |
+ :param dest: Destination, will be prefixed with sysroot (defaults to same as src)
|
|
|
b45ed7 |
+ :param src_physical: Prefix src with physical root
|
|
|
b45ed7 |
+ :param bind_ro: Make mount read-only
|
|
|
b45ed7 |
+ :param recurse: Use --rbind to recurse, otherwise plain --bind
|
|
|
b45ed7 |
+ """
|
|
|
b45ed7 |
+ # Default to the same basename
|
|
|
b45ed7 |
+ if dest is None:
|
|
|
b45ed7 |
+ dest = src
|
|
|
b45ed7 |
+ # Almost all of our mounts go from physical to sysroot
|
|
|
b45ed7 |
+ if src_physical:
|
|
|
b45ed7 |
+ src = iutil.getTargetPhysicalRoot() + src
|
|
|
b45ed7 |
+ else:
|
|
|
b45ed7 |
+ src = iutil.getSysroot() + src
|
|
|
b45ed7 |
+ # Canonicalize dest to the full path
|
|
|
b45ed7 |
+ dest = iutil.getSysroot() + dest
|
|
|
b45ed7 |
+ if bind_ro:
|
|
|
b45ed7 |
+ self._safeExecWithRedirect("mount",
|
|
|
b45ed7 |
+ ["--bind", src, src])
|
|
|
b45ed7 |
+ self._safeExecWithRedirect("mount",
|
|
|
b45ed7 |
+ ["--bind", "-o", "remount,ro", src, src])
|
|
|
b45ed7 |
+ else:
|
|
|
b45ed7 |
+ # Recurse for non-ro binds so we pick up sub-mounts
|
|
|
b45ed7 |
+ # like /sys/firmware/efi/efivars.
|
|
|
b45ed7 |
+ if recurse:
|
|
|
b45ed7 |
+ bindopt = '--rbind'
|
|
|
b45ed7 |
+ else:
|
|
|
b45ed7 |
+ bindopt = '--bind'
|
|
|
b45ed7 |
+ self._safeExecWithRedirect("mount",
|
|
|
b45ed7 |
+ [bindopt, src, dest])
|
|
|
b45ed7 |
+ self._internal_mounts.append(src if bind_ro else dest)
|
|
|
b45ed7 |
+
|
|
|
b45ed7 |
def prepareMountTargets(self, storage):
|
|
|
b45ed7 |
ostreesetup = self.data.ostreesetup
|
|
|
b45ed7 |
|
|
|
b45ed7 |
- varroot = iutil.getTargetPhysicalRoot() + '/ostree/deploy/' + ostreesetup.osname + '/var'
|
|
|
b45ed7 |
-
|
|
|
b45ed7 |
- # Set up bind mounts as if we've booted the target system, so
|
|
|
b45ed7 |
- # that %post script work inside the target.
|
|
|
b45ed7 |
- self._binds = [(iutil.getTargetPhysicalRoot(), iutil.getSysroot() + '/sysroot'),
|
|
|
b45ed7 |
- (iutil.getSysroot() + '/usr', None)]
|
|
|
b45ed7 |
- # https://github.com/ostreedev/ostree/issues/855
|
|
|
b45ed7 |
+ # NOTE: This is different from Fedora. There, since since
|
|
|
b45ed7 |
+ # 664ef7b43f9102aa9332d0db5b7d13f8ece436f0 blivet now only sets up
|
|
|
b45ed7 |
+ # mounts in the physical root, and we set up bind mounts. But in RHEL7
|
|
|
b45ed7 |
+ # we tear down and set up the mounts in the sysroot, so this code
|
|
|
b45ed7 |
+ # doesn't need to do as much.
|
|
|
b45ed7 |
+
|
|
|
b45ed7 |
+ # Now that we have the FS layout in the target, umount
|
|
|
b45ed7 |
+ # things that were in the physical sysroot, and put them in
|
|
|
b45ed7 |
+ # the target root, *except* for the physical /.
|
|
|
b45ed7 |
+ storage.umountFilesystems()
|
|
|
b45ed7 |
+
|
|
|
b45ed7 |
+ # Explicitly mount the root on the physical sysroot, since that's
|
|
|
b45ed7 |
+ # how ostree works.
|
|
|
b45ed7 |
+ rootmnt = storage.mountpoints.get('/')
|
|
|
b45ed7 |
+ rootmnt.setup()
|
|
|
b45ed7 |
+ rootmnt.format.setup(options=rootmnt.format.options, chroot=iutil.getTargetPhysicalRoot())
|
|
|
b45ed7 |
+
|
|
|
b45ed7 |
+ # Everything else goes in the target root, including /boot
|
|
|
b45ed7 |
+ # since the bootloader code will expect to find /boot
|
|
|
b45ed7 |
+ # inside the chroot.
|
|
|
b45ed7 |
+ storage.mountFilesystems(skipRoot=True)
|
|
|
b45ed7 |
+
|
|
|
b45ed7 |
+ # We're done with blivet mounts; now set up binds as ostree does it at
|
|
|
b45ed7 |
+ # runtime. We start with /usr being read-only.
|
|
|
b45ed7 |
+ self._setupInternalBindmount('/usr', bind_ro=True, src_physical=False)
|
|
|
b45ed7 |
+
|
|
|
b45ed7 |
+ # Handle /var; if the admin didn't specify a mount for /var, we need to
|
|
|
b45ed7 |
+ # do the default ostree one. See also
|
|
|
b45ed7 |
+ # <https://github.com/ostreedev/ostree/issues/855>.
|
|
|
b45ed7 |
+ varroot = '/ostree/deploy/' + ostreesetup.osname + '/var'
|
|
|
b45ed7 |
if storage.mountpoints.get("/var") is None:
|
|
|
b45ed7 |
- self._binds.append((varroot, iutil.getSysroot() + '/var'))
|
|
|
b45ed7 |
-
|
|
|
b45ed7 |
- for (src, dest) in self._binds:
|
|
|
b45ed7 |
- self._safeExecWithRedirect("mount",
|
|
|
b45ed7 |
- ["--bind", src, dest if dest else src])
|
|
|
b45ed7 |
- if dest is None:
|
|
|
b45ed7 |
- self._safeExecWithRedirect("mount",
|
|
|
b45ed7 |
- ["--bind", "-o", "ro", src, src])
|
|
|
b45ed7 |
+ self._setupInternalBindmount(varroot, dest='/var', recurse=False)
|
|
|
b45ed7 |
+
|
|
|
b45ed7 |
+ self._setupInternalBindmount("/", dest="/sysroot", recurse=False)
|
|
|
b45ed7 |
+
|
|
|
b45ed7 |
+ # Now that we have /var, start filling in any directories that may be
|
|
|
b45ed7 |
+ # required later there. We explicitly make /var/lib, since
|
|
|
b45ed7 |
+ # systemd-tmpfiles doesn't have a --prefix-only=/var/lib. We rely on
|
|
|
b45ed7 |
+ # 80-setfilecons.ks to set the label correctly.
|
|
|
b45ed7 |
+ iutil.mkdirChain(iutil.getSysroot() + '/var/lib')
|
|
|
b45ed7 |
+ # Next, run tmpfiles to make subdirectories of /var. We need this for
|
|
|
b45ed7 |
+ # both mounts like /home (really /var/home) and %post scripts might
|
|
|
b45ed7 |
+ # want to write to e.g. `/srv`, `/root`, `/usr/local`, etc. The
|
|
|
b45ed7 |
+ # /var/lib/rpm symlink is also critical for having e.g. `rpm -qa` work
|
|
|
b45ed7 |
+ # in %post. We don't iterate *all* tmpfiles because we don't have the
|
|
|
b45ed7 |
+ # matching NSS configuration inside Anaconda, and we can't "chroot" to
|
|
|
b45ed7 |
+ # get it because that would require mounting the API filesystems in the
|
|
|
b45ed7 |
+ # target.
|
|
|
b45ed7 |
+ for varsubdir in ('home', 'roothome', 'lib/rpm', 'opt', 'srv',
|
|
|
b45ed7 |
+ 'usrlocal', 'mnt', 'media', 'spool', 'spool/mail'):
|
|
|
b45ed7 |
+ self._safeExecWithRedirect("systemd-tmpfiles",
|
|
|
b45ed7 |
+ ["--create", "--boot", "--root=" + iutil.getSysroot(),
|
|
|
b45ed7 |
+ "--prefix=/var/" + varsubdir])
|
|
|
b45ed7 |
|
|
|
b45ed7 |
def recreateInitrds(self, force=False):
|
|
|
b45ed7 |
# For rpmostree payloads, we're replicating an initramfs from
|
|
|
b45ed7 |
@@ -312,6 +403,6 @@ class RPMOSTreePayload(ArchivePayload):
|
|
|
b45ed7 |
# on inside either blivet (or systemd?) that's causing mounts inside
|
|
|
b45ed7 |
# /mnt/sysimage/ostree/deploy/$x/sysroot/ostree/deploy
|
|
|
b45ed7 |
# which is not what we want.
|
|
|
b45ed7 |
- for (src, dest) in reversed(self._binds):
|
|
|
b45ed7 |
+ for path in reversed(self._internal_mounts):
|
|
|
b45ed7 |
# Also intentionally ignore errors here
|
|
|
b45ed7 |
- iutil.execWithRedirect("umount", ['-R', dest if dest else src])
|
|
|
b45ed7 |
+ iutil.execWithRedirect("umount", ['-R', path])
|
|
|
b45ed7 |
--
|
|
|
b45ed7 |
2.13.5
|
|
|
b45ed7 |
|