From: Michael Tremer Date: Tue, 29 Nov 2022 14:36:54 +0000 (+0000) Subject: bootloader: Don't use Pakfire jail to run GRUB commands X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a57e98a4f1246e7ae31a776253b6746c8d74d245;p=people%2Fms%2Fbricklayer.git bootloader: Don't use Pakfire jail to run GRUB commands GRUB seems to be very pissy when it does not have full access to the system - understandably :) We now create a very simple chroot environment for GRUB to install itself. Signed-off-by: root --- diff --git a/src/python/__init__.py b/src/python/__init__.py index 860fcc9..60a3300 100644 --- a/src/python/__init__.py +++ b/src/python/__init__.py @@ -19,6 +19,7 @@ ############################################################################### import logging +import os import subprocess import sys import tempfile @@ -215,12 +216,16 @@ class Bricklayer(object): with open("/etc/os-release") as f: return util.config_read(f) - def command(self, command, error_ok=False, interactive=False): + def command(self, command, error_ok=False, interactive=False, chroot=False, bind=None): """ Runs a command in a shell environment """ log.debug("Running command: %s" % " ".join(command)) + # Run this command in the installed environment if requested + if chroot: + command = ["chroot", self.root] + command + args = {} if not interactive: @@ -229,8 +234,19 @@ class Bricklayer(object): "stderr" : subprocess.STDOUT, }) - # Execute the command - p = subprocess.run(command, **args) + try: + # Bind-mount things + if bind: + self._bind(bind) + + # Execute the command + p = subprocess.run(command, **args) + + finally: + # If the command is successful or not, we will always need to unbind + # anything that has been mounted before. + if bind: + self._unbind(bind) # Check the return code (raises CalledProcessError on non-zero) if not error_ok: @@ -249,6 +265,38 @@ class Bricklayer(object): return output + def _bind(self, mountpoints): + """ + Bind-mounts the given mountpoints + """ + for source in mountpoints: + if not source.startswith("/"): + raise ValueError("Mountpoints must be absolute paths") + + target = os.path.join(self.root, source[1:]) + + # Make sure we mount into our root + assert(target.startswith(self.root)) + + # Perform mount + self.command(["mount", "--bind", source, target]) + + def _unbind(self, mountpoints): + """ + Umounts any bind-mounted mountpoints + """ + for source in reversed(mountpoints): + if not source.startswith("/"): + continue + + target = os.path.join(self.root, source[1:]) + + # Make sure we mount into our root + assert(target.startswith(self.root)) + + # Perform umount + self.command(["umount", target], error_ok=True) + def setup_pakfire(self, **kwargs): """ Calls Pakfire and has it load its configuration diff --git a/src/python/bootloaders.py b/src/python/bootloaders.py index d1cb69f..d8cb906 100644 --- a/src/python/bootloaders.py +++ b/src/python/bootloaders.py @@ -82,15 +82,12 @@ class Grub(Bootloader): requires_bootldr_partition = True def install(self): - # Initialize Pakfire - pakfire = self.bricklayer.setup_pakfire() - # Install GRUB2 on all disks that have been selected for disk in self.bricklayer.disks.selected: - self.install_on_disk(disk, pakfire) + self.install_on_disk(disk) # Install configuration - self.install_configuration(pakfire) + self.install_configuration() @property def grub_arch(self): @@ -102,23 +99,21 @@ class Grub(Bootloader): "--target=%s" % self.grub_arch, ] - def install_on_disk(self, disk, pakfire): + def install_on_disk(self, disk): log.info("Installing GRUB on %s" % disk.path) - # Make /dev available in the jail - # XXX this should be limited to the device nodes we need only - bind = ["/dev"] - - pakfire.execute(["grub-install"] + self.grub_args + [disk.path], bind=bind) + self.bricklayer.command([ + "grub-install", "--verbose", "--force", "--recheck", + *self.grub_args, disk.path, + ], chroot=True, bind=["/dev", "/proc", "/sys"]) - def install_configuration(self, pakfire): + def install_configuration(self): """ Generates a GRUB configuration file """ - # XXX see above - bind = ["/dev"] - - pakfire.execute(["grub-mkconfig", "-o", "/boot/grub/grub.cfg"], bind=bind) + self.bricklayer.command([ + "grub-mkconfig", "-o", "/boot/grub/grub.cfg", + ], chroot=True, bind=["/dev", "/proc", "/sys"]) class GrubEFI(Grub):