From cdcb4598bb557e46a7c4a6a6eccbdcae2757f837 Mon Sep 17 00:00:00 2001 From: Renata Ravanelli Date: Thu, 16 Nov 2023 09:41:18 -0500 Subject: [PATCH] create org.osbuild.bootupd stage Add the bootupd stage to install GRUB on both BIOS and UEFI systems, ensuring that your bootloader stays up-to-date. Signed-off-by: Renata Ravanelli --- stages/org.osbuild.bootupd | 127 ++++++++++++++++++ .../manifests/fedora-coreos-container.json | 116 +++++++++++----- .../fedora-coreos-container.mpp.yaml | 94 +++++++++---- 3 files changed, 275 insertions(+), 62 deletions(-) create mode 100755 stages/org.osbuild.bootupd diff --git a/stages/org.osbuild.bootupd b/stages/org.osbuild.bootupd new file mode 100755 index 00000000..22da890d --- /dev/null +++ b/stages/org.osbuild.bootupd @@ -0,0 +1,127 @@ +#!/usr/bin/python3 +""" +Install GRUB on both BIOS and UEFI systems, +ensuring that your bootloader stays up-to-date. + +Bootupd supports updating GRUB and shim for +UEFI firmware on x86_64 and aarch64, +and GRUB for BIOS firmware on x86_64. +The project is deployed in Fedora CoreOS and derivatives +""" + +import os +import subprocess +import sys + +import osbuild.api +from osbuild.util import ostree + +SCHEMA_2 = r""" +"devices": { + "type": "object", + "additionalProperties": true +}, +"mounts": { + "type": "array" +}, +"options": { + "additionalProperties": false, + "properties": { + "deployment": { + "type": "object", + "additionalProperties": false, + "required": ["osname", "ref"], + "properties": { + "osname": { + "description": "Name of the stateroot to be used in the deployment", + "type": "string" + }, + "ref": { + "description": "OStree ref to create and use for deployment", + "type": "string" + }, + "serial": { + "description": "The deployment serial (usually '0')", + "type": "number", + "default": 0 + } + } + }, + "static-configs": { + "description": "Install the grub configs defined for Fedora CoreOS", + "type": "boolean" + }, + "bios": { + "additionalProperties": false, + "type": "object", + "required": ["device"], + "properties": { + "device": { + "description": "Name of stage device to install GRUB for BIOS-based systems.", + "type": "string" + } + } + } + } +} +""" + + +def main(args, options): + deployment = options.get("deployment", None) + static_configs = options.get("static-configs", False) + bios = options.get("bios", {}) + device = bios.get("device", "") + + # Get the path where the filesystems are mounted + mounts = args["paths"]["mounts"] + + # Get the deployment root. For non-OSTree this is simply + # the root location of the mount points. For OSTree systems + # we'll call ostree.deployment_path() helper to find it for us. + root = mounts + if deployment: + osname = deployment["osname"] + ref = deployment["ref"] + serial = deployment.get("serial", 0) + root = ostree.deployment_path(mounts, osname, ref, serial) + + bootupd_args = [] + if device: + # The value passed by the user is the name of the device + # as specified in the devices array (also passed in by the + # user). Let's map that name to the actual loopback device + # that now backs it. + target = args["devices"][device]["path"] + bootupd_args.append(f"--device={target}") + if static_configs: + bootupd_args.append("--with-static-configs") + + # We want to run the bootupctl command from the target (i.e. we + # want to make sure the version used matches the target and not + # risk any inconsistencies with the build root). Let's set up + # and chroot to run the bootupctl command from the target. + submounts = ['dev', 'proc', 'sys', 'run', 'var', 'tmp'] + for mnt in submounts: + subprocess.run(['mount', '--rbind', + os.path.join("/", mnt), + os.path.join(root, mnt)], + check=True) + try: + cmd = ['chroot', root, '/usr/bin/bootupctl', 'backend', 'install'] + cmd.extend(bootupd_args) + cmd.append(mounts) + subprocess.run(cmd, check=True) + finally: + for mnt in submounts: + subprocess.run(['umount', '--recursive', + os.path.join(root, mnt)], + check=False) + + return 0 + + +if __name__ == '__main__': + _args = osbuild.api.arguments() + r = main(_args, _args["options"]) + sys.exit(r) diff --git a/test/data/manifests/fedora-coreos-container.json b/test/data/manifests/fedora-coreos-container.json index e253a61e..957f3de2 100644 --- a/test/data/manifests/fedora-coreos-container.json +++ b/test/data/manifests/fedora-coreos-container.json @@ -529,25 +529,6 @@ "ref": "ostree/1/1/0" } } - }, - { - "type": "org.osbuild.grub2", - "options": { - "rootfs": { - "label": "root" - }, - "bootfs": { - "label": "boot" - }, - "uefi": { - "vendor": "fedora", - "install": true - }, - "legacy": "i386-pc", - "write_defaults": false, - "greenboot": false, - "ignition": true - } } ] }, @@ -715,23 +696,49 @@ ] }, { - "type": "org.osbuild.grub2.inst", + "type": "org.osbuild.bootupd", "options": { - "platform": "i386-pc", - "filename": "disk.img", - "location": 2048, - "core": { - "type": "mkimage", - "partlabel": "gpt", - "filesystem": "ext4" + "bios": { + "device": "disk" }, - "prefix": { - "type": "partition", - "partlabel": "gpt", - "number": 2, - "path": "/grub2" + "static-configs": true, + "deployment": { + "osname": "fedora-coreos", + "ref": "ostree/1/1/0" } - } + }, + "devices": { + "disk": { + "type": "org.osbuild.loopback", + "options": { + "filename": "disk.img", + "partscan": true + } + } + }, + "mounts": [ + { + "name": "root", + "type": "org.osbuild.xfs", + "source": "disk", + "partition": 4, + "target": "/" + }, + { + "name": "boot", + "type": "org.osbuild.ext4", + "source": "disk", + "partition": 3, + "target": "/boot" + }, + { + "name": "efi", + "type": "org.osbuild.fat", + "source": "disk", + "partition": 2, + "target": "/boot/efi" + } + ] } ] }, @@ -902,6 +909,49 @@ "target": "/boot/efi" } ] + }, + { + "type": "org.osbuild.bootupd", + "options": { + "static-configs": true, + "deployment": { + "osname": "fedora-coreos", + "ref": "ostree/1/1/0" + } + }, + "devices": { + "disk": { + "type": "org.osbuild.loopback", + "options": { + "filename": "disk.img", + "partscan": true, + "sector-size": 4096 + } + } + }, + "mounts": [ + { + "name": "root", + "type": "org.osbuild.xfs", + "source": "disk", + "partition": 4, + "target": "/" + }, + { + "name": "boot", + "type": "org.osbuild.ext4", + "source": "disk", + "partition": 3, + "target": "/boot" + }, + { + "name": "efi", + "type": "org.osbuild.fat", + "source": "disk", + "partition": 2, + "target": "/boot/efi" + } + ] } ] }, diff --git a/test/data/manifests/fedora-coreos-container.mpp.yaml b/test/data/manifests/fedora-coreos-container.mpp.yaml index aefda0d9..2addbe1f 100644 --- a/test/data/manifests/fedora-coreos-container.mpp.yaml +++ b/test/data/manifests/fedora-coreos-container.mpp.yaml @@ -124,19 +124,6 @@ pipelines: deployment: osname: fedora-coreos ref: ostree/1/1/0 - - type: org.osbuild.grub2 - options: - rootfs: - label: root - bootfs: - label: boot - uefi: - vendor: fedora - install: true - legacy: i386-pc - write_defaults: false - greenboot: false - ignition: true - name: raw-image build: name:build stages: @@ -231,23 +218,39 @@ pipelines: partition: mpp-format-int: '{image.layout[''EFI-SYSTEM''].partnum}' target: /boot/efi - - type: org.osbuild.grub2.inst + - type: org.osbuild.bootupd options: - platform: i386-pc - filename: disk.img - location: - mpp-format-int: '{image.layout[''BIOS-BOOT''].start}' - core: - type: mkimage - partlabel: gpt - filesystem: ext4 - prefix: - type: partition - partlabel: - mpp-format-string: '{image.layout.label}' - number: - mpp-format-int: '{image.layout[''boot''].index}' - path: /grub2 + bios: + device: disk + static-configs: true + deployment: + osname: fedora-coreos + ref: ostree/1/1/0 + devices: + disk: + type: org.osbuild.loopback + options: + filename: disk.img + partscan: true + mounts: + - name: root + type: org.osbuild.xfs + source: disk + partition: + mpp-format-int: '{image.layout[''root''].partnum}' + target: / + - name: boot + type: org.osbuild.ext4 + source: disk + partition: + mpp-format-int: '{image.layout[''boot''].partnum}' + target: /boot + - name: efi + type: org.osbuild.fat + source: disk + partition: + mpp-format-int: '{image.layout[''EFI-SYSTEM''].partnum}' + target: /boot/efi - name: raw-4k-image build: name:build stages: @@ -352,6 +355,39 @@ pipelines: partition: mpp-format-int: '{image4k.layout[''EFI-SYSTEM''].partnum}' target: /boot/efi + - type: org.osbuild.bootupd + options: + static-configs: true + deployment: + osname: fedora-coreos + ref: ostree/1/1/0 + devices: + disk: + type: org.osbuild.loopback + options: + filename: disk.img + partscan: true + sector-size: + mpp-format-int: "{four_k_sector_size}" + mounts: + - name: root + type: org.osbuild.xfs + source: disk + partition: + mpp-format-int: '{image4k.layout[''root''].partnum}' + target: / + - name: boot + type: org.osbuild.ext4 + source: disk + partition: + mpp-format-int: '{image4k.layout[''boot''].partnum}' + target: /boot + - name: efi + type: org.osbuild.fat + source: disk + partition: + mpp-format-int: '{image4k.layout[''EFI-SYSTEM''].partnum}' + target: /boot/efi - name: raw-metal-image build: name:build stages: