From: Michael Tremer Date: Mon, 10 May 2021 14:15:44 +0000 (+0000) Subject: Add installation of bootloaders X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=0a760ee00b46a5f89eb215049ce6ee736d9ca4f4;p=people%2Fms%2Fbricklayer.git Add installation of bootloaders Currently only GRUB (in legacy and EFI mode) are supported Signed-off-by: Michael Tremer --- diff --git a/Makefile.am b/Makefile.am index e7db931..0f93d6b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -45,6 +45,7 @@ dist_bin_SCRIPTS = \ dist_pkgpython_PYTHON = \ src/python/__init__.py \ + src/python/bootloaders.py \ src/python/disk.py \ src/python/errors.py \ src/python/i18n.py \ diff --git a/src/python/__init__.py b/src/python/__init__.py index f2ebbde..d6c1846 100644 --- a/src/python/__init__.py +++ b/src/python/__init__.py @@ -26,6 +26,7 @@ import traceback import pakfire +from . import bootloaders from . import disk from . import i18n from . import logger @@ -71,6 +72,9 @@ class Bricklayer(object): # Read OS information self.os = self._read_os_release() + # Select a bootloaders + self.bootloaders = self._select_bootloaders() + # Hardware self.disks = disk.Disks(self) for path in disks: @@ -99,6 +103,7 @@ class Bricklayer(object): disk.CreateFilesystems, disk.MountFilesystems, packages.InstallPackages, + bootloaders.InstallBootloader, # Done! disk.UmountFilesystems, @@ -219,3 +224,15 @@ class Bricklayer(object): """ return pakfire.Pakfire(self.root, arch=self.arch, conf="/etc/pakfire/distros/ipfire3.conf") + + def _select_bootloaders(self): + """ + Select all bootloaders for this installation process + """ + _bootloaders = ( + bootloaders.Grub(self), + bootloaders.GrubEFI(self), + ) + + # Return all supported bootloaders + return [bl for bl in _bootloaders if bl.supported] diff --git a/src/python/bootloaders.py b/src/python/bootloaders.py new file mode 100644 index 0000000..9e9f46b --- /dev/null +++ b/src/python/bootloaders.py @@ -0,0 +1,138 @@ +############################################################################### +# # +# Bricklayer - An Installer for IPFire # +# Copyright (C) 2021 IPFire Development Team # +# # +# This program is free software; you can redistribute it and/or # +# modify it under the terms of the GNU General Public License # +# as published by the Free Software Foundation; either version 2 # +# of the License, or (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see . # +# # +############################################################################### + +import itertools +import logging + +from . import step +from .i18n import _, N_ + +# Setup logging +log = logging.getLogger("bricklayer.bootloaders") + +class Bootloader(object): + """ + A generic class for bootloaders + """ + + # Set the name of the bootloader + name = None + + # Which architectures are supported? + arches = [] + + # Packages that need to be installed + packages = [] + + def __init__(self, bricklayer): + self.bricklayer = bricklayer + + @property + def supported(self): + """ + Returns True if this booloader is supported + """ + # If arches is empty, this bootloader is supported + if not self.arches: + return True + + return self.bricklayer.arch in self.arches + + def install(self): + """ + Called to install the bootloader + """ + pass + + +class Grub(Bootloader): + name = N_("GRUB") + + arches = [ + "x86_64", + ] + + packages = [ + "grub", + ] + + 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) + + @property + def grub_arch(self): + return "i386-pc" + + @property + def grub_args(self): + return [ + "--target=%s" % self.grub_arch, + ] + + def install_on_disk(self, disk, pakfire): + log.info("Installing GRUB on %s" % disk.path) + + pakfire.execute(["grub-install"] + self.grub_args + [disk.path]) + + +class GrubEFI(Grub): + name = N_("GRUB EFI") + + @property + def grub_arch(self): + if self.bricklayer.arch == "aarch64": + return "arm64-efi" + + elif self.bricklayer.arch == "x86_64": + return "x86_64-efi" + + @property + def grub_args(self): + return [ + "--target=%s" % self.grub_arch, + "--efi-directory=/boot/efi", + ] + + +class InstallBootloader(step.Step): + """ + Installs the bootloader + """ + def run(self, tui): + # Find all packages that need to be installed + packages = [] + for bootloader in self.bricklayer.bootloaders: + packages += bootloader.packages + + # Install them + #self.install_packages(tui, packages) + + # Install all bootloaders + for bootloader in self.bricklayer.bootloaders: + with tui.progress( + _("Installing Bootloader"), + _("Installing bootloader \"%s\"...") % _(bootloader.name), + ): + bootloader.install() diff --git a/src/python/packages.py b/src/python/packages.py index 166274b..b0f6beb 100644 --- a/src/python/packages.py +++ b/src/python/packages.py @@ -18,67 +18,11 @@ # # ############################################################################### -import logging -import pakfire.errors - from . import step -from .i18n import _ - -# Set up logging -log = logging.getLogger("bricklayer.packages") class InstallPackages(step.Step): def run(self, tui): - # Set up Pakfire - with tui.progress( - _("Setting Up Pakfire"), - _("Pakfire is being set up..."), - ): - p = self.bricklayer.setup_pakfire() - # Get list of all packages to be installed packages = self.bricklayer.settings.get("packages", []) - with p as p: - # Resolve package dependencies - with tui.progress( - _("Resolving Dependencies"), - _("Resolving package dependencies..."), - ): - try: - transaction = p.install(packages) - - # Abort on any dependencies problems - except pakfire.errors.DependencyError as e: - problems = e.args[0] - - # Format problem descriptions - text = [] - for problem in problems: - lines = [ - "* %s" % problem - ] - for solution in problem.solutions: - lines.append(" --> %s" % solution) - - text.append("\n".join(lines)) - - tui.error( - _("Dependency Problem"), - _( - "A problem has occured during resolving package dependencies:\n\n%s", - "Problems have occured during resolving package dependencies:\n\n%s", - len(problems), - ) % "\n\n".join(text), - width=78, - ) - - # Log the transaction - log.info("%s" % transaction.dump()) - - # Run the transaction - with tui.progress( - _("Installing Packages"), - _("Installing packages..."), - ): - transaction.run() + self.install_packages(tui, packages) diff --git a/src/python/step.py b/src/python/step.py index 3626e9f..91d0a43 100644 --- a/src/python/step.py +++ b/src/python/step.py @@ -21,6 +21,7 @@ import logging import os import time +import pakfire.errors import snack @@ -58,6 +59,62 @@ class Step(object): """ pass + def install_packages(self, tui, packages): + # Nothing to do if there are no packages + if not packages: + return + + # Set up Pakfire + with tui.progress( + _("Setting Up Pakfire"), + _("Pakfire is being set up..."), + ): + p = self.bricklayer.setup_pakfire() + + with p as p: + # Resolve package dependencies + with tui.progress( + _("Resolving Dependencies"), + _("Resolving package dependencies..."), + ): + try: + transaction = p.install(packages) + + # Abort on any dependencies problems + except pakfire.errors.DependencyError as e: + problems = e.args[0] + + # Format problem descriptions + text = [] + for problem in problems: + lines = [ + "* %s" % problem + ] + for solution in problem.solutions: + lines.append(" --> %s" % solution) + + text.append("\n".join(lines)) + + tui.error( + _("Dependency Problem"), + _( + "A problem has occured during resolving package dependencies:\n\n%s", + "Problems have occured during resolving package dependencies:\n\n%s", + len(problems), + ) % "\n\n".join(text), + width=78, + ) + + # Log the transaction + log.info("%s" % transaction.dump()) + + # Run the transaction + with tui.progress( + _("Installing Packages"), + _("Installing packages..."), + ): + transaction.run() + class InteractiveStep(Step): """