|
|
fbcaed |
From 2a99e198c40b22fd2f3bf3988902b8d02817ea82 Mon Sep 17 00:00:00 2001
|
|
|
fbcaed |
From: Colin Walters <walters@verbum.org>
|
|
|
fbcaed |
Date: Wed, 30 Apr 2014 19:26:37 -0400
|
|
|
fbcaed |
Subject: [PATCH 10/20] Add RPMOSTreePayload
|
|
|
fbcaed |
|
|
|
fbcaed |
This is a new backend that uses ostree to install. However, it's
|
|
|
fbcaed |
named RPMOSTree because a future iteration will use rpm-ostree which
|
|
|
fbcaed |
will support a hybrid of tree + RPM packages.
|
|
|
fbcaed |
|
|
|
fbcaed |
Resolves: rhbz#1113535
|
|
|
fbcaed |
Port of rpmostreepayload patches from master
|
|
|
fbcaed |
commit 131cbcec9c113dd5f66d14d440297d50b2900e01
|
|
|
fbcaed |
---
|
|
|
fbcaed |
data/post-scripts/80-setfilecons.ks | 3 +
|
|
|
fbcaed |
po/POTFILES.in | 1 +
|
|
|
fbcaed |
pyanaconda/__init__.py | 5 +-
|
|
|
fbcaed |
pyanaconda/bootloader.py | 44 +++---
|
|
|
fbcaed |
pyanaconda/install.py | 16 ++
|
|
|
fbcaed |
pyanaconda/packaging/__init__.py | 6 +
|
|
|
fbcaed |
pyanaconda/packaging/rpmostreepayload.py | 246 +++++++++++++++++++++++++++++++
|
|
|
fbcaed |
7 files changed, 302 insertions(+), 19 deletions(-)
|
|
|
fbcaed |
create mode 100644 pyanaconda/packaging/rpmostreepayload.py
|
|
|
fbcaed |
|
|
|
fbcaed |
diff --git a/data/post-scripts/80-setfilecons.ks b/data/post-scripts/80-setfilecons.ks
|
|
|
fbcaed |
index 93ac962..f0d0414 100644
|
|
|
fbcaed |
--- a/data/post-scripts/80-setfilecons.ks
|
|
|
fbcaed |
+++ b/data/post-scripts/80-setfilecons.ks
|
|
|
fbcaed |
@@ -4,6 +4,9 @@ restorecon -ir /etc/sysconfig/network-scripts /var/lib /etc/lvm \
|
|
|
fbcaed |
/dev /etc/iscsi /var/lib/iscsi /root /var/lock /var/log \
|
|
|
fbcaed |
/etc/modprobe.d /etc/sysconfig /var/cache/yum
|
|
|
fbcaed |
|
|
|
fbcaed |
+# Also relabel the OSTree variants of the normal mounts (if they exist)
|
|
|
fbcaed |
+restorecon -ir /var/roothome /var/home /var/opt /var/srv /var/media /var/mnt
|
|
|
fbcaed |
+
|
|
|
fbcaed |
restorecon -i /etc/rpm/macros /etc/dasd.conf /etc/zfcp.conf /lib64 /usr/lib64 \
|
|
|
fbcaed |
/etc/blkid.tab* /etc/mtab /etc/fstab /etc/resolv.conf \
|
|
|
fbcaed |
/etc/modprobe.conf* /var/log/*tmp /etc/crypttab \
|
|
|
fbcaed |
diff --git a/po/POTFILES.in b/po/POTFILES.in
|
|
|
fbcaed |
index 4b341fc..8df1636 100644
|
|
|
fbcaed |
--- a/po/POTFILES.in
|
|
|
fbcaed |
+++ b/po/POTFILES.in
|
|
|
fbcaed |
@@ -25,6 +25,7 @@ pyanaconda/packaging/__init__.py
|
|
|
fbcaed |
pyanaconda/packaging/livepayload.py
|
|
|
fbcaed |
pyanaconda/packaging/tarpayload.py
|
|
|
fbcaed |
pyanaconda/packaging/yumpayload.py
|
|
|
fbcaed |
+pyanaconda/packaging/rpmostreepayload.py
|
|
|
fbcaed |
|
|
|
fbcaed |
# Interfaces
|
|
|
fbcaed |
pyanaconda/ui/common.py
|
|
|
fbcaed |
diff --git a/pyanaconda/__init__.py b/pyanaconda/__init__.py
|
|
|
fbcaed |
index fad7a90..34d46e0 100644
|
|
|
fbcaed |
--- a/pyanaconda/__init__.py
|
|
|
fbcaed |
+++ b/pyanaconda/__init__.py
|
|
|
fbcaed |
@@ -124,7 +124,10 @@ class Anaconda(object):
|
|
|
fbcaed |
if not klass:
|
|
|
fbcaed |
from flags import flags
|
|
|
fbcaed |
|
|
|
fbcaed |
- if flags.livecdInstall:
|
|
|
fbcaed |
+ if self.ksdata.ostreesetup.seen:
|
|
|
fbcaed |
+ from pyanaconda.packaging.rpmostreepayload import RPMOSTreePayload
|
|
|
fbcaed |
+ klass = RPMOSTreePayload
|
|
|
fbcaed |
+ elif flags.livecdInstall:
|
|
|
fbcaed |
from pyanaconda.packaging.livepayload import LiveImagePayload
|
|
|
fbcaed |
klass = LiveImagePayload
|
|
|
fbcaed |
elif self.ksdata.method.method == "liveimg":
|
|
|
fbcaed |
diff --git a/pyanaconda/bootloader.py b/pyanaconda/bootloader.py
|
|
|
fbcaed |
index 860bde3..b6d5941 100644
|
|
|
fbcaed |
--- a/pyanaconda/bootloader.py
|
|
|
fbcaed |
+++ b/pyanaconda/bootloader.py
|
|
|
fbcaed |
@@ -37,6 +37,7 @@ from pyanaconda.flags import flags
|
|
|
fbcaed |
from blivet.errors import StorageError
|
|
|
fbcaed |
from blivet.fcoe import fcoe
|
|
|
fbcaed |
import pyanaconda.network
|
|
|
fbcaed |
+from pyanaconda.packaging.rpmostreepayload import RPMOSTreePayload
|
|
|
fbcaed |
from pyanaconda.nm import nm_device_hwaddress
|
|
|
fbcaed |
from blivet import platform
|
|
|
fbcaed |
from pyanaconda.i18n import _, N_
|
|
|
fbcaed |
@@ -2355,6 +2356,23 @@ def writeSysconfigKernel(storage, version):
|
|
|
fbcaed |
f.write("HYPERVISOR_ARGS=logging=vga,serial,memory\n")
|
|
|
fbcaed |
f.close()
|
|
|
fbcaed |
|
|
|
fbcaed |
+def writeBootLoaderFinal(storage, payload, instClass, ksdata):
|
|
|
fbcaed |
+ """ Do the final write of the bootloader. """
|
|
|
fbcaed |
+
|
|
|
fbcaed |
+ from pyanaconda.errors import errorHandler, ERROR_RAISE
|
|
|
fbcaed |
+
|
|
|
fbcaed |
+ # set up dracut/fips boot args
|
|
|
fbcaed |
+ # XXX FIXME: do this from elsewhere?
|
|
|
fbcaed |
+ storage.bootloader.set_boot_args(storage=storage,
|
|
|
fbcaed |
+ payload=payload,
|
|
|
fbcaed |
+ keyboard=ksdata.keyboard)
|
|
|
fbcaed |
+ try:
|
|
|
fbcaed |
+ storage.bootloader.write()
|
|
|
fbcaed |
+ except BootLoaderError as e:
|
|
|
fbcaed |
+ log.error("bootloader.write failed: %s" % e)
|
|
|
fbcaed |
+ if errorHandler.cb(e) == ERROR_RAISE:
|
|
|
fbcaed |
+ raise
|
|
|
fbcaed |
+
|
|
|
fbcaed |
def writeBootLoader(storage, payload, instClass, ksdata):
|
|
|
fbcaed |
""" Write bootloader configuration to disk.
|
|
|
fbcaed |
|
|
|
fbcaed |
@@ -2362,14 +2380,19 @@ def writeBootLoader(storage, payload, instClass, ksdata):
|
|
|
fbcaed |
image. We only have to add images for the non-default kernels and
|
|
|
fbcaed |
adjust the default to reflect whatever the default variant is.
|
|
|
fbcaed |
"""
|
|
|
fbcaed |
- from pyanaconda.errors import errorHandler, ERROR_RAISE
|
|
|
fbcaed |
-
|
|
|
fbcaed |
if not storage.bootloader.skip_bootloader:
|
|
|
fbcaed |
stage1_device = storage.bootloader.stage1_device
|
|
|
fbcaed |
log.info("bootloader stage1 target device is %s" % stage1_device.name)
|
|
|
fbcaed |
stage2_device = storage.bootloader.stage2_device
|
|
|
fbcaed |
log.info("bootloader stage2 target device is %s" % stage2_device.name)
|
|
|
fbcaed |
|
|
|
fbcaed |
+ if isinstance(payload, RPMOSTreePayload):
|
|
|
fbcaed |
+ if storage.bootloader.skip_bootloader:
|
|
|
fbcaed |
+ log.info("skipping bootloader install per user request")
|
|
|
fbcaed |
+ return
|
|
|
fbcaed |
+ writeBootLoaderFinal(storage, payload, instClass, ksdata)
|
|
|
fbcaed |
+ return
|
|
|
fbcaed |
+
|
|
|
fbcaed |
# get a list of installed kernel packages
|
|
|
fbcaed |
kernel_versions = payload.kernelVersionList
|
|
|
fbcaed |
if not kernel_versions:
|
|
|
fbcaed |
@@ -2414,19 +2437,4 @@ def writeBootLoader(storage, payload, instClass, ksdata):
|
|
|
fbcaed |
label=label, short=short)
|
|
|
fbcaed |
storage.bootloader.add_image(image)
|
|
|
fbcaed |
|
|
|
fbcaed |
- # set up dracut/fips boot args
|
|
|
fbcaed |
- # XXX FIXME: do this from elsewhere?
|
|
|
fbcaed |
- #storage.bootloader.set_boot_args(keyboard=anaconda.keyboard,
|
|
|
fbcaed |
- # storage=anaconda.storage,
|
|
|
fbcaed |
- # language=anaconda.instLanguage,
|
|
|
fbcaed |
- # network=anaconda.network)
|
|
|
fbcaed |
- storage.bootloader.set_boot_args(storage=storage,
|
|
|
fbcaed |
- payload=payload,
|
|
|
fbcaed |
- keyboard=ksdata.keyboard)
|
|
|
fbcaed |
-
|
|
|
fbcaed |
- try:
|
|
|
fbcaed |
- storage.bootloader.write()
|
|
|
fbcaed |
- except BootLoaderError as e:
|
|
|
fbcaed |
- if errorHandler.cb(e) == ERROR_RAISE:
|
|
|
fbcaed |
- raise
|
|
|
fbcaed |
-
|
|
|
fbcaed |
+ writeBootLoaderFinal(storage, payload, instClass, ksdata)
|
|
|
fbcaed |
diff --git a/pyanaconda/install.py b/pyanaconda/install.py
|
|
|
fbcaed |
index 68551cc..d771f5b 100644
|
|
|
fbcaed |
--- a/pyanaconda/install.py
|
|
|
fbcaed |
+++ b/pyanaconda/install.py
|
|
|
fbcaed |
@@ -107,6 +107,17 @@ def doConfiguration(storage, payload, ksdata, instClass):
|
|
|
fbcaed |
|
|
|
fbcaed |
progressQ.send_complete()
|
|
|
fbcaed |
|
|
|
fbcaed |
+def moveBootMntToPhysical(storage):
|
|
|
fbcaed |
+ """Move the /boot mount to /mnt/sysimage/boot."""
|
|
|
fbcaed |
+ if iutil.getSysroot() == iutil.getTargetPhysicalRoot():
|
|
|
fbcaed |
+ return
|
|
|
fbcaed |
+ bootmnt = storage.mountpoints.get('/boot')
|
|
|
fbcaed |
+ if bootmnt is None:
|
|
|
fbcaed |
+ return
|
|
|
fbcaed |
+ bootmnt.format.teardown()
|
|
|
fbcaed |
+ bootmnt.teardown()
|
|
|
fbcaed |
+ bootmnt.format.setup(bootmnt.format.options, chroot=iutil.getTargetPhysicalRoot())
|
|
|
fbcaed |
+
|
|
|
fbcaed |
def doInstall(storage, payload, ksdata, instClass):
|
|
|
fbcaed |
"""Perform an installation. This method takes the ksdata as prepared by
|
|
|
fbcaed |
the UI (the first hub, in graphical mode) and applies it to the disk.
|
|
|
fbcaed |
@@ -189,6 +200,8 @@ def doInstall(storage, payload, ksdata, instClass):
|
|
|
fbcaed |
rootmnt.setup()
|
|
|
fbcaed |
rootmnt.format.setup(rootmnt.format.options, chroot=iutil.getTargetPhysicalRoot())
|
|
|
fbcaed |
|
|
|
fbcaed |
+ payload.prepareMountTargets(storage)
|
|
|
fbcaed |
+
|
|
|
fbcaed |
# Everything else goes in the target root, including /boot
|
|
|
fbcaed |
# since the bootloader code will expect to find /boot
|
|
|
fbcaed |
# inside the chroot.
|
|
|
fbcaed |
@@ -202,6 +215,9 @@ def doInstall(storage, payload, ksdata, instClass):
|
|
|
fbcaed |
writeBootLoader(storage, payload, instClass, ksdata)
|
|
|
fbcaed |
|
|
|
fbcaed |
with progress_report(_("Performing post-installation setup tasks")):
|
|
|
fbcaed |
+ # Now, let's reset the state here so that the payload has
|
|
|
fbcaed |
+ # /boot in the system root.
|
|
|
fbcaed |
+ moveBootMntToPhysical(storage)
|
|
|
fbcaed |
payload.postInstall()
|
|
|
fbcaed |
|
|
|
fbcaed |
progressQ.send_complete()
|
|
|
fbcaed |
diff --git a/pyanaconda/packaging/__init__.py b/pyanaconda/packaging/__init__.py
|
|
|
fbcaed |
index 9b97149..4a5e793 100644
|
|
|
fbcaed |
--- a/pyanaconda/packaging/__init__.py
|
|
|
fbcaed |
+++ b/pyanaconda/packaging/__init__.py
|
|
|
fbcaed |
@@ -128,6 +128,12 @@ class Payload(object):
|
|
|
fbcaed |
""" Reset the instance, not including ksdata. """
|
|
|
fbcaed |
pass
|
|
|
fbcaed |
|
|
|
fbcaed |
+ def prepareMountTargets(self, storage):
|
|
|
fbcaed |
+ """Run when physical storage is mounted, but other mount points may
|
|
|
fbcaed |
+ not exist. Used by the RPMOSTreePayload subclass.
|
|
|
fbcaed |
+ """
|
|
|
fbcaed |
+ pass
|
|
|
fbcaed |
+
|
|
|
fbcaed |
###
|
|
|
fbcaed |
### METHODS FOR WORKING WITH REPOSITORIES
|
|
|
fbcaed |
###
|
|
|
fbcaed |
diff --git a/pyanaconda/packaging/rpmostreepayload.py b/pyanaconda/packaging/rpmostreepayload.py
|
|
|
fbcaed |
new file mode 100644
|
|
|
fbcaed |
index 0000000..1b24a0f
|
|
|
fbcaed |
--- /dev/null
|
|
|
fbcaed |
+++ b/pyanaconda/packaging/rpmostreepayload.py
|
|
|
fbcaed |
@@ -0,0 +1,246 @@
|
|
|
fbcaed |
+# ostreepayload.py
|
|
|
fbcaed |
+# Deploy OSTree trees to target
|
|
|
fbcaed |
+#
|
|
|
fbcaed |
+# Copyright (C) 2012,2014 Red Hat, Inc.
|
|
|
fbcaed |
+#
|
|
|
fbcaed |
+# This copyrighted material is made available to anyone wishing to use,
|
|
|
fbcaed |
+# modify, copy, or redistribute it subject to the terms and conditions of
|
|
|
fbcaed |
+# the GNU General Public License v.2, or (at your option) any later version.
|
|
|
fbcaed |
+# This program is distributed in the hope that it will be useful, but WITHOUT
|
|
|
fbcaed |
+# ANY WARRANTY expressed or implied, including the implied warranties of
|
|
|
fbcaed |
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
|
|
fbcaed |
+# Public License for more details. You should have received a copy of the
|
|
|
fbcaed |
+# GNU General Public License along with this program; if not, write to the
|
|
|
fbcaed |
+# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
|
fbcaed |
+# 02110-1301, USA. Any Red Hat trademarks that are incorporated in the
|
|
|
fbcaed |
+# source code or documentation are not subject to the GNU General Public
|
|
|
fbcaed |
+# License and may only be used or replicated with the express permission of
|
|
|
fbcaed |
+# Red Hat, Inc.
|
|
|
fbcaed |
+#
|
|
|
fbcaed |
+# Red Hat Author(s): Colin Walters <walters@redhat.com>
|
|
|
fbcaed |
+#
|
|
|
fbcaed |
+
|
|
|
fbcaed |
+import os
|
|
|
fbcaed |
+import shutil
|
|
|
fbcaed |
+
|
|
|
fbcaed |
+from pyanaconda import iutil
|
|
|
fbcaed |
+from pyanaconda.i18n import _
|
|
|
fbcaed |
+from pyanaconda.progress import progressQ
|
|
|
fbcaed |
+from gi.repository import GLib
|
|
|
fbcaed |
+from gi.repository import Gio
|
|
|
fbcaed |
+
|
|
|
fbcaed |
+from blivet.size import Size
|
|
|
fbcaed |
+
|
|
|
fbcaed |
+import logging
|
|
|
fbcaed |
+log = logging.getLogger("anaconda")
|
|
|
fbcaed |
+
|
|
|
fbcaed |
+from pyanaconda.packaging import ArchivePayload, PayloadInstallError
|
|
|
fbcaed |
+import pyanaconda.errors as errors
|
|
|
fbcaed |
+
|
|
|
fbcaed |
+class RPMOSTreePayload(ArchivePayload):
|
|
|
fbcaed |
+ """ A RPMOSTreePayload deploys a tree (possibly with layered packages) onto the target system. """
|
|
|
fbcaed |
+ def __init__(self, data):
|
|
|
fbcaed |
+ super(RPMOSTreePayload, self).__init__(data)
|
|
|
fbcaed |
+
|
|
|
fbcaed |
+ def setup(self, storage):
|
|
|
fbcaed |
+ super(RPMOSTreePayload, self).setup(storage)
|
|
|
fbcaed |
+
|
|
|
fbcaed |
+ @property
|
|
|
fbcaed |
+ def handlesBootloaderConfiguration(self):
|
|
|
fbcaed |
+ return True
|
|
|
fbcaed |
+
|
|
|
fbcaed |
+ @property
|
|
|
fbcaed |
+ def kernelVersionList(self):
|
|
|
fbcaed |
+ # OSTree handles bootloader configuration
|
|
|
fbcaed |
+ return []
|
|
|
fbcaed |
+
|
|
|
fbcaed |
+ @property
|
|
|
fbcaed |
+ def spaceRequired(self):
|
|
|
fbcaed |
+ # We don't have this data with OSTree at the moment
|
|
|
fbcaed |
+ return Size(spec="500 MB")
|
|
|
fbcaed |
+
|
|
|
fbcaed |
+ def _safeExecWithRedirect(self, cmd, argv, **kwargs):
|
|
|
fbcaed |
+ """Like iutil.execWithRedirect, but treat errors as fatal"""
|
|
|
fbcaed |
+ rc = iutil.execWithRedirect(cmd, argv, **kwargs)
|
|
|
fbcaed |
+ if rc != 0:
|
|
|
fbcaed |
+ exn = PayloadInstallError("%s %s exited with code %d" % (cmd, argv, rc))
|
|
|
fbcaed |
+ if errors.errorHandler.cb(exn) == errors.ERROR_RAISE:
|
|
|
fbcaed |
+ raise exn
|
|
|
fbcaed |
+
|
|
|
fbcaed |
+ def _pullProgressCb(self, asyncProgress):
|
|
|
fbcaed |
+ status = asyncProgress.get_status()
|
|
|
fbcaed |
+ outstanding_fetches = asyncProgress.get_uint('outstanding-fetches')
|
|
|
fbcaed |
+ if status:
|
|
|
fbcaed |
+ progressQ.send_message(status)
|
|
|
fbcaed |
+ elif outstanding_fetches > 0:
|
|
|
fbcaed |
+ bytes_transferred = asyncProgress.get_uint64('bytes-transferred')
|
|
|
fbcaed |
+ fetched = asyncProgress.get_uint('fetched')
|
|
|
fbcaed |
+ requested = asyncProgress.get_uint('requested')
|
|
|
fbcaed |
+ formatted_bytes = GLib.format_size_full(bytes_transferred, 0)
|
|
|
fbcaed |
+
|
|
|
fbcaed |
+ if requested == 0:
|
|
|
fbcaed |
+ percent = 0.0
|
|
|
fbcaed |
+ else:
|
|
|
fbcaed |
+ percent = (fetched*1.0 / requested) * 100
|
|
|
fbcaed |
+
|
|
|
fbcaed |
+ progressQ.send_message("Receiving objects: %d%% (%d/%d) %s" % (percent, fetched, requested, formatted_bytes))
|
|
|
fbcaed |
+ else:
|
|
|
fbcaed |
+ progressQ.send_message("Writing objects")
|
|
|
fbcaed |
+
|
|
|
fbcaed |
+ def install(self):
|
|
|
fbcaed |
+ cancellable = None
|
|
|
fbcaed |
+ from gi.repository import OSTree
|
|
|
fbcaed |
+ ostreesetup = self.data.ostreesetup
|
|
|
fbcaed |
+ log.info("executing ostreesetup=%r" % ostreesetup)
|
|
|
fbcaed |
+
|
|
|
fbcaed |
+ # Initialize the filesystem - this will create the repo as well
|
|
|
fbcaed |
+ self._safeExecWithRedirect("ostree",
|
|
|
fbcaed |
+ ["admin", "--sysroot=" + iutil.getTargetPhysicalRoot(),
|
|
|
fbcaed |
+ "init-fs", iutil.getTargetPhysicalRoot()])
|
|
|
fbcaed |
+
|
|
|
fbcaed |
+ repo_arg = "--repo=" + iutil.getTargetPhysicalRoot() + '/ostree/repo'
|
|
|
fbcaed |
+
|
|
|
fbcaed |
+ # Set up the chosen remote
|
|
|
fbcaed |
+ remote_args = [repo_arg, "remote", "add"]
|
|
|
fbcaed |
+ if ((hasattr(ostreesetup, 'noGpg') and ostreesetup.noGpg) or
|
|
|
fbcaed |
+ (hasattr(ostreesetup, 'nogpg') and ostreesetup.nogpg)):
|
|
|
fbcaed |
+ remote_args.append("--set=gpg-verify=false")
|
|
|
fbcaed |
+ remote_args.extend([ostreesetup.remote,
|
|
|
fbcaed |
+ ostreesetup.url])
|
|
|
fbcaed |
+ self._safeExecWithRedirect("ostree", remote_args)
|
|
|
fbcaed |
+
|
|
|
fbcaed |
+ sysroot_path = Gio.File.new_for_path(iutil.getTargetPhysicalRoot())
|
|
|
fbcaed |
+ sysroot = OSTree.Sysroot.new(sysroot_path)
|
|
|
fbcaed |
+ sysroot.load(cancellable)
|
|
|
fbcaed |
+
|
|
|
fbcaed |
+ repo = sysroot.get_repo(None)[1]
|
|
|
fbcaed |
+ repo.set_disable_fsync(True)
|
|
|
fbcaed |
+ progressQ.send_message(_("Starting pull of %s from %s") % \
|
|
|
fbcaed |
+ (ostreesetup.ref, ostreesetup.remote))
|
|
|
fbcaed |
+
|
|
|
fbcaed |
+ progress = OSTree.AsyncProgress.new()
|
|
|
fbcaed |
+ progress.connect('changed', self._pullProgressCb)
|
|
|
fbcaed |
+ repo.pull(ostreesetup.remote, [ostreesetup.ref], 0, progress, cancellable)
|
|
|
fbcaed |
+
|
|
|
fbcaed |
+ progressQ.send_message(_("Preparing deployment of %s") % (ostreesetup.ref, ))
|
|
|
fbcaed |
+
|
|
|
fbcaed |
+ self._safeExecWithRedirect("ostree",
|
|
|
fbcaed |
+ ["admin", "--sysroot=" + iutil.getTargetPhysicalRoot(),
|
|
|
fbcaed |
+ "os-init", ostreesetup.osname])
|
|
|
fbcaed |
+
|
|
|
fbcaed |
+ admin_deploy_args = ["admin", "--sysroot=" + iutil.getTargetPhysicalRoot(),
|
|
|
fbcaed |
+ "deploy", "--os=" + ostreesetup.osname]
|
|
|
fbcaed |
+
|
|
|
fbcaed |
+ admin_deploy_args.append(ostreesetup.remote + ':' + ostreesetup.ref)
|
|
|
fbcaed |
+
|
|
|
fbcaed |
+ log.info("ostree admin deploy starting")
|
|
|
fbcaed |
+ progressQ.send_message(_("Deployment starting: %s") % (ostreesetup.ref, ))
|
|
|
fbcaed |
+ self._safeExecWithRedirect("ostree", admin_deploy_args)
|
|
|
fbcaed |
+ log.info("ostree admin deploy complete")
|
|
|
fbcaed |
+ progressQ.send_message(_("Deployment complete: %s") % (ostreesetup.ref, ))
|
|
|
fbcaed |
+
|
|
|
fbcaed |
+ # Reload now that we've deployed, find the path to the new deployment
|
|
|
fbcaed |
+ sysroot.load(None)
|
|
|
fbcaed |
+ deployments = sysroot.get_deployments()
|
|
|
fbcaed |
+ assert len(deployments) > 0
|
|
|
fbcaed |
+ deployment = deployments[0]
|
|
|
fbcaed |
+ deployment_path = sysroot.get_deployment_directory(deployment)
|
|
|
fbcaed |
+ iutil.setSysroot(deployment_path.get_path())
|
|
|
fbcaed |
+
|
|
|
fbcaed |
+ varroot = iutil.getTargetPhysicalRoot() + '/ostree/deploy/' + ostreesetup.osname + '/var'
|
|
|
fbcaed |
+
|
|
|
fbcaed |
+ # This is a bit of a hack; we precreate the targets of
|
|
|
fbcaed |
+ # possible mounts of legacy paths like /home and /opt so the
|
|
|
fbcaed |
+ # installer/%post scripts can find them. In particular,
|
|
|
fbcaed |
+ # Anaconda itself writes to /root/anaconda-ks.cfg. What we
|
|
|
fbcaed |
+ # really should do is export this data in some way the
|
|
|
fbcaed |
+ # installer can read reliably. Right now it's just encoded in
|
|
|
fbcaed |
+ # systemd-tmpfiles.
|
|
|
fbcaed |
+ for (dname, mode) in [('root', 0700), ('home', 0755),
|
|
|
fbcaed |
+ ('opt', 0755), ('srv', 0755),
|
|
|
fbcaed |
+ ('media', 0755), ('mnt', 0755)]:
|
|
|
fbcaed |
+ linksrc = iutil.getSysroot() + '/' + dname
|
|
|
fbcaed |
+ if os.path.islink(linksrc) and not os.path.isdir(linksrc):
|
|
|
fbcaed |
+ linkdata = os.readlink(linksrc)
|
|
|
fbcaed |
+ if linkdata.startswith('var/'):
|
|
|
fbcaed |
+ linkdest = varroot + '/' + linkdata[4:]
|
|
|
fbcaed |
+ log.info("Creating %s" % linkdest)
|
|
|
fbcaed |
+ os.mkdir(linkdest, mode)
|
|
|
fbcaed |
+
|
|
|
fbcaed |
+ # Copy specific bootloader data files from the deployment
|
|
|
fbcaed |
+ # checkout to the target root. See
|
|
|
fbcaed |
+ # https://bugzilla.gnome.org/show_bug.cgi?id=726757 This
|
|
|
fbcaed |
+ # happens once, at installation time.
|
|
|
fbcaed |
+ # extlinux ships its modules directly in the RPM in /boot.
|
|
|
fbcaed |
+ # For GRUB2, Anaconda installs device.map there. We may need
|
|
|
fbcaed |
+ # to add other bootloaders here though (if they can't easily
|
|
|
fbcaed |
+ # be fixed to *copy* data into /boot at install time, instead
|
|
|
fbcaed |
+ # of shipping it in the RPM).
|
|
|
fbcaed |
+ physboot = iutil.getTargetPhysicalRoot() + '/boot'
|
|
|
fbcaed |
+ sysboot = iutil.getSysroot() + '/boot'
|
|
|
fbcaed |
+ for fname in ['extlinux', 'grub2']:
|
|
|
fbcaed |
+ srcpath = os.path.join(sysboot, fname)
|
|
|
fbcaed |
+ if os.path.isdir(srcpath):
|
|
|
fbcaed |
+ log.info("Copying bootloader data: " + fname)
|
|
|
fbcaed |
+ shutil.copytree(srcpath, os.path.join(physboot, fname))
|
|
|
fbcaed |
+
|
|
|
fbcaed |
+ def prepareMountTargets(self, storage):
|
|
|
fbcaed |
+ ostreesetup = self.data.ostreesetup
|
|
|
fbcaed |
+
|
|
|
fbcaed |
+ varroot = iutil.getTargetPhysicalRoot() + '/ostree/deploy/' + ostreesetup.osname + '/var'
|
|
|
fbcaed |
+
|
|
|
fbcaed |
+ # Set up bind mounts as if we've booted the target system, so
|
|
|
fbcaed |
+ # that %post script work inside the target.
|
|
|
fbcaed |
+ binds = [(iutil.getTargetPhysicalRoot(),
|
|
|
fbcaed |
+ iutil.getSysroot() + '/sysroot'),
|
|
|
fbcaed |
+ (varroot,
|
|
|
fbcaed |
+ iutil.getSysroot() + '/var'),
|
|
|
fbcaed |
+ (iutil.getSysroot() + '/usr', None)]
|
|
|
fbcaed |
+
|
|
|
fbcaed |
+ for (src, dest) in binds:
|
|
|
fbcaed |
+ self._safeExecWithRedirect("mount",
|
|
|
fbcaed |
+ ["--bind", src, dest if dest else src])
|
|
|
fbcaed |
+ if dest is None:
|
|
|
fbcaed |
+ self._safeExecWithRedirect("mount",
|
|
|
fbcaed |
+ ["--bind", "-o", "ro", src, src])
|
|
|
fbcaed |
+
|
|
|
fbcaed |
+ def postInstall(self):
|
|
|
fbcaed |
+ super(RPMOSTreePayload, self).postInstall()
|
|
|
fbcaed |
+
|
|
|
fbcaed |
+ physboot = iutil.getTargetPhysicalRoot() + '/boot'
|
|
|
fbcaed |
+
|
|
|
fbcaed |
+ # If we're using extlinux, rename extlinux.conf to
|
|
|
fbcaed |
+ # syslinux.cfg, since that's what OSTree knows about.
|
|
|
fbcaed |
+ # syslinux upstream supports both, but I'd say that upstream
|
|
|
fbcaed |
+ # using syslinux.cfg is somewhat preferred.
|
|
|
fbcaed |
+ physboot_extlinux = physboot + '/extlinux'
|
|
|
fbcaed |
+ if os.path.isdir(physboot_extlinux):
|
|
|
fbcaed |
+ physboot_syslinux = physboot + '/syslinux'
|
|
|
fbcaed |
+ physboot_loader = physboot + '/loader'
|
|
|
fbcaed |
+ assert os.path.isdir(physboot_loader)
|
|
|
fbcaed |
+ orig_extlinux_conf = physboot_extlinux + '/extlinux.conf'
|
|
|
fbcaed |
+ target_syslinux_cfg = physboot_loader + '/syslinux.cfg'
|
|
|
fbcaed |
+ log.info("Moving %s -> %s" % (orig_extlinux_conf, target_syslinux_cfg))
|
|
|
fbcaed |
+ os.rename(orig_extlinux_conf, target_syslinux_cfg)
|
|
|
fbcaed |
+ # A compatibility bit for OSTree
|
|
|
fbcaed |
+ os.mkdir(physboot_syslinux)
|
|
|
fbcaed |
+ os.symlink('../loader/syslinux.cfg', physboot_syslinux + '/syslinux.cfg')
|
|
|
fbcaed |
+ # And *also* tell syslinux that the config is really in /boot/loader
|
|
|
fbcaed |
+ os.symlink('loader/syslinux.cfg', physboot + '/syslinux.cfg')
|
|
|
fbcaed |
+
|
|
|
fbcaed |
+ # OSTree owns the bootloader configuration, so here we give it
|
|
|
fbcaed |
+ # the argument list we computed from storage, architecture and
|
|
|
fbcaed |
+ # such.
|
|
|
fbcaed |
+ set_kargs_args = ["admin", "--sysroot=" + iutil.getTargetPhysicalRoot(),
|
|
|
fbcaed |
+ "instutil", "set-kargs"]
|
|
|
fbcaed |
+ set_kargs_args.extend(self.storage.bootloader.boot_args)
|
|
|
fbcaed |
+ set_kargs_args.append("root=" + self.storage.rootDevice.fstabSpec)
|
|
|
fbcaed |
+ self._safeExecWithRedirect("ostree", set_kargs_args)
|
|
|
fbcaed |
+
|
|
|
fbcaed |
+ # This command iterates over all files we might have created
|
|
|
fbcaed |
+ # and ensures they're labeled. It's like running
|
|
|
fbcaed |
+ # chroot(iutil.getTargetPhysicalRoot()) + fixfiles, except
|
|
|
fbcaed |
+ # with a better name and semantics.
|
|
|
fbcaed |
+ self._safeExecWithRedirect("ostree",
|
|
|
fbcaed |
+ ["admin", "--sysroot=" + iutil.getTargetPhysicalRoot(),
|
|
|
fbcaed |
+ "instutil", "selinux-ensure-labeled", iutil.getTargetPhysicalRoot(), ""])
|
|
|
fbcaed |
--
|
|
|
fbcaed |
1.9.3
|
|
|
fbcaed |
|