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 <rravanel@redhat.com>
This commit is contained in:
Renata Ravanelli 2023-11-16 09:41:18 -05:00 committed by Achilleas Koutsou
parent c03e6be52a
commit cdcb4598bb
3 changed files with 275 additions and 62 deletions

127
stages/org.osbuild.bootupd Executable file
View file

@ -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)

View file

@ -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"
}
]
}
]
},

View file

@ -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: