From 273559fae459326ff6fccfe5cc026020daf151f6 Mon Sep 17 00:00:00 2001
From: Colin Walters <walters@verbum.org>
Date: Fri, 17 Oct 2014 00:01:25 -0400
Subject: [PATCH 2/5] rpmostreepayload: Copy all subdirectories of
 /usr/lib/ostree-boot

Previously we were special casing extlinux/ and grub2/, but this
misses out on efi/.  To support rpmostreepayload + GRUB2 + EFI, we
need special handling here.  Any bootloaders installing files in /boot
instead of a subdirectory will then need to be special cased (or
"fixed").

Now in a perfect world, I'd have a time machine and we could go back
and have every bootloader install in a subdirectory /boot/data or
something.  But we basically can't change existing systems, which kind
of traps us into the current RPM-level layout forever, with rpm-ostree
postprocessing it.

(One could argue it's rpm-ostree's job to postprocess this so Anaconda
 wouldn't have to care.  Open to that.)
---
 pyanaconda/packaging/rpmostreepayload.py | 60 +++++++++++++++++++++++---------
 1 file changed, 44 insertions(+), 16 deletions(-)

diff --git a/pyanaconda/packaging/rpmostreepayload.py b/pyanaconda/packaging/rpmostreepayload.py
index dfb0466..bf8d7e1 100644
--- a/pyanaconda/packaging/rpmostreepayload.py
+++ b/pyanaconda/packaging/rpmostreepayload.py
@@ -89,6 +89,41 @@ class RPMOSTreePayload(ArchivePayload):
         else:
             progressQ.send_message("Writing objects")
 
+    def _copyBootloaderData(self):
+        # Copy bootloader data files from the deployment
+        # checkout to the target root.  See
+        # https://bugzilla.gnome.org/show_bug.cgi?id=726757 This
+        # happens once, at installation time.
+        # extlinux ships its modules directly in the RPM in /boot.
+        # For GRUB2, Anaconda installs device.map there.  We may need
+        # to add other bootloaders here though (if they can't easily
+        # be fixed to *copy* data into /boot at install time, instead
+        # of shipping it in the RPM).
+        physboot = iutil.getTargetPhysicalRoot() + '/boot'
+        ostree_boot_source = iutil.getSysroot() + '/usr/lib/ostree-boot'
+        if not os.path.isdir(ostree_boot_source):
+            ostree_boot_source = iutil.getSysroot() + '/boot'
+        for fname in os.listdir(ostree_boot_source):
+            srcpath = os.path.join(ostree_boot_source, fname)
+            destpath = os.path.join(physboot, fname)
+
+            # We're only copying directories
+            if not os.path.isdir(srcpath):
+                continue
+
+            # Special handling for EFI, as it's a mount point that's
+            # expected to already exist (so if we used copytree, we'd
+            # traceback).  If it doesn't, we're not on a UEFI system,
+            # so we don't want to copy the data.
+            if fname == 'efi' and os.path.isdir(destpath):
+                for subname in os.listdir(srcpath):
+                    sub_srcpath = os.path.join(srcpath, subname)
+                    sub_destpath = os.path.join(destpath, subname)
+                    self._safeExecWithRedirect('cp', ['-r', '-p', sub_srcpath, sub_destpath])
+            else:
+                log.info("Copying bootloader data: " + fname)
+                shutil.copytree(srcpath, destpath)
+
     def install(self):
         mainctx = GLib.MainContext.new()
         mainctx.push_thread_default()
@@ -161,22 +196,15 @@ class RPMOSTreePayload(ArchivePayload):
         deployment_path = sysroot.get_deployment_directory(deployment)
         iutil.setSysroot(deployment_path.get_path())
 
-        # Copy specific bootloader data files from the deployment
-        # checkout to the target root.  See
-        # https://bugzilla.gnome.org/show_bug.cgi?id=726757 This
-        # happens once, at installation time.
-        # extlinux ships its modules directly in the RPM in /boot.
-        # For GRUB2, Anaconda installs device.map there.  We may need
-        # to add other bootloaders here though (if they can't easily
-        # be fixed to *copy* data into /boot at install time, instead
-        # of shipping it in the RPM).
-        physboot = iutil.getTargetPhysicalRoot() + '/boot'
-        sysboot = iutil.getSysroot() + '/boot'
-        for fname in ['extlinux', 'grub2']:
-            srcpath = os.path.join(sysboot, fname)
-            if os.path.isdir(srcpath):
-                log.info("Copying bootloader data: " + fname)
-                shutil.copytree(srcpath, os.path.join(physboot, fname))
+        try:
+            self._copyBootloaderData()
+        except (OSError, RuntimeError) as e:
+            exn = PayloadInstallError("Failed to copy bootloader data: %s" % e)
+            log.error(str(exn))
+            if errors.errorHandler.cb(exn) == errors.ERROR_RAISE:
+                progressQ.send_quit(1)
+                iutil.ipmi_report(constants.IPMI_ABORTED)
+                sys.exit(1)
 
         mainctx.pop_thread_default()
 
-- 
1.8.3.1