]> git.ipfire.org Git - people/ms/bricklayer.git/commitdiff
Add installation of bootloaders
authorMichael Tremer <michael.tremer@ipfire.org>
Mon, 10 May 2021 14:15:44 +0000 (14:15 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Mon, 10 May 2021 14:15:44 +0000 (14:15 +0000)
Currently only GRUB (in legacy and EFI mode) are supported

Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
Makefile.am
src/python/__init__.py
src/python/bootloaders.py [new file with mode: 0644]
src/python/packages.py
src/python/step.py

index e7db9314243fe6a71c64f1481492cc298841542f..0f93d6b9d28c6d0b7cd8a2dcf6902780084e2a90 100644 (file)
@@ -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 \
index f2ebbdeb95757628e7ce6f9488077e80697fde8f..d6c1846117af35798c1f1164eb2bf1958aeac50b 100644 (file)
@@ -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 (file)
index 0000000..9e9f46b
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.       #
+#                                                                             #
+###############################################################################
+
+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()
index 166274b70dfbaa21e4b6476a12dc9c8519822b26..b0f6beb64f90dea109a35b3149a782ea6ca2ac98 100644 (file)
 #                                                                             #
 ###############################################################################
 
-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)
index 3626e9fd4352a98f20ce0ea6c04e26ff7baf110f..91d0a4373c1ec711204f324441708069fd701dfc 100644 (file)
@@ -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):
        """