From 4976268a594bb4603d5f16ed967963ede49d5063 Mon Sep 17 00:00:00 2001 From: jbtrystram Date: Thu, 17 Jul 2025 17:19:08 +0200 Subject: [PATCH 1/3] osbuild: use bootc install to deploy the container Instead of deploying the container to the tree then copy all the contents to the disk image, use bootc to directly manage the installation to the target filesystems. Right now this requires to use the image as the buildroot so this requires python (for osbuild). This is tracked in [1]. [1] https://github.com/bootc-dev/bootc/issues/1410 Requires https://github.com/osbuild/osbuild/pull/2149 --- src/cmd-osbuild | 4 + .../coreos.osbuild.x86_64.mpp.yaml | 336 +++--------------- src/runvm-osbuild | 7 +- 3 files changed, 60 insertions(+), 287 deletions(-) diff --git a/src/cmd-osbuild b/src/cmd-osbuild index 993be80b19..eefa0bd1bb 100755 --- a/src/cmd-osbuild +++ b/src/cmd-osbuild @@ -397,6 +397,10 @@ main() { fi outdir=$(mktemp -p "${tmp_builddir}" -d) + # To get a shell in the osbuild supervin VM uncomment this. + # osbuild can be started with `bash tmp/build./cmd.sh` + # See comment about checkpoints in runvm-osbuild + # RUNVM_SHELL=1 \ runvm_with_cache -- /usr/lib/coreos-assembler/runvm-osbuild \ --config "${runvm_osbuild_config_json}" \ --mpp "/usr/lib/coreos-assembler/osbuild-manifests/coreos.osbuild.${basearch}.mpp.yaml" \ diff --git a/src/osbuild-manifests/coreos.osbuild.x86_64.mpp.yaml b/src/osbuild-manifests/coreos.osbuild.x86_64.mpp.yaml index 753fee5a95..ad91e568bb 100644 --- a/src/osbuild-manifests/coreos.osbuild.x86_64.mpp.yaml +++ b/src/osbuild-manifests/coreos.osbuild.x86_64.mpp.yaml @@ -37,11 +37,11 @@ mpp-vars: # matches. Unfortunately for FCOS there is no python so we can't # really use FCOS as the buildroot so we'll use the host as the # buildroot there. - buildroot: - mpp-if: osname in ['rhcos', 'scos'] - then: "name:deployed-tree" - else: - mpp-format-string: '{host_as_buildroot}' + buildroot: "name:deployed-tree" + # mpp-if: osname in ['rhcos', 'scos', 'fc'] + # then: "name:deployed-tree" + # else: + # mpp-format-string: '{host_as_buildroot}' mpp-define-images: - id: image sector_size: @@ -162,86 +162,6 @@ pipelines: origin: org.osbuild.pipeline references: - name:deployed-tree - - type: org.osbuild.ostree.init-fs - - type: org.osbuild.ostree.os-init - options: - osname: - mpp-format-string: '{osname}' - - type: org.osbuild.ostree.config - options: - repo: /ostree/repo - config: - sysroot: - readonly: true - bootloader: none - # https://github.com/coreos/fedora-coreos-tracker/issues/1333 - bls-append-except-default: grub_users="" - # Opt-in to https://github.com/ostreedev/ostree/pull/2705 which will - # add /boot as the prefix on top of BLS config entries. This is OK - # because there is a symlink that is created in the root of the boot - # filesystem by OSTree (boot -> .) that makes it so that /boot paths - # will always work. - bootprefix: true - - type: org.osbuild.mkdir - options: - paths: - - path: /boot/efi - mode: 493 - - type: org.osbuild.ignition - # Deploy via ociarchive or container - - mpp-if: ociarchive != '' - then: - type: org.osbuild.ostree.deploy.container - options: - osname: - mpp-format-string: '{osname}' - target_imgref: - mpp-format-string: '{container_imgref}' - mounts: - - /boot - - /boot/efi - kernel_opts: - - rw - - '$ignition_firstboot' - - mpp-format-string: '{extra_kargs}' - inputs: - images: - type: org.osbuild.containers - origin: org.osbuild.pipeline - references: - name:oci-archive: - name: coreos.ociarchive - else: - type: org.osbuild.ostree.deploy.container - options: - osname: - mpp-format-string: '{osname}' - target_imgref: - mpp-format-string: '{container_imgref}' - mounts: - - /boot - - /boot/efi - kernel_opts: - - rw - - '$ignition_firstboot' - - mpp-format-string: '{extra_kargs}' - inputs: - images: - type: org.osbuild.containers - origin: org.osbuild.source - mpp-resolve-images: - images: - - source: $container_repo - tag: $container_tag - - type: org.osbuild.ostree.aleph - options: - coreos_compat: true - deployment: - default: true - - type: org.osbuild.ostree.selinux - options: - deployment: - default: true - name: raw-image build: mpp-format-string: '{buildroot}' @@ -342,69 +262,25 @@ pipelines: partition: mpp-format-int: '{image.layout[''boot''].partnum}' target: /boot-mount-point - - type: org.osbuild.selinux - options: - file_contexts: input://tree/etc/selinux/targeted/contexts/files/file_contexts - target: mount://root/ - inputs: - tree: - type: org.osbuild.tree - origin: org.osbuild.pipeline - references: - - name:deployed-tree - 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: / - - type: org.osbuild.selinux - options: - file_contexts: input://tree/etc/selinux/targeted/contexts/files/file_contexts - target: mount://root/boot/ - inputs: - tree: - type: org.osbuild.tree + # Use bootc install to-filesystem to install the ostree content from the container image + # inside our disc image + - type: org.osbuild.bootc.install-to-filesystem + inputs: + images: + type: org.osbuild.containers origin: org.osbuild.pipeline references: - - name:deployed-tree - 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 - - type: org.osbuild.copy - inputs: - tree: - type: org.osbuild.tree - origin: org.osbuild.pipeline - references: - - name:tree + name:oci-archive: + name: coreos.ociarchive options: - paths: - - from: input://tree/ - to: mount://root/ + kernel-args: + - '$ignition_firstboot' + - mpp-format-string: '{extra_kargs}' + target-imgref: + mpp-format-string: '{container_imgref}' + stateroot: fedora-coreos + boot-mount-spec: "" + root-mount-spec: "" devices: disk: type: org.osbuild.loopback @@ -430,13 +306,11 @@ pipelines: partition: mpp-format-int: '{image.layout[''EFI-SYSTEM''].partnum}' target: /boot/efi - - type: org.osbuild.bootupd + # set up the `ignition.firstboot` stamp at the end because + # bootc want empty filesystems + - type: org.osbuild.ignition options: - bios: - device: disk - static-configs: true - deployment: - default: true + target: mount://boot/ devices: disk: type: org.osbuild.loopback @@ -456,36 +330,6 @@ pipelines: 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 - - type: org.osbuild.chattr - options: - items: - mount://root/: - immutable: true - 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: ostree.deployment - type: org.osbuild.ostree.deployment - options: - source: mount - deployment: - default: true - name: raw-4k-image build: mpp-format-string: '{buildroot}' @@ -596,41 +440,25 @@ pipelines: partition: mpp-format-int: '{image4k.layout[''boot''].partnum}' target: /boot-mount-point - - type: org.osbuild.selinux - options: - file_contexts: input://tree/etc/selinux/targeted/contexts/files/file_contexts - target: mount://root/ - inputs: - tree: - type: org.osbuild.tree + # Use bootc install to-filesystem to install the ostree content from the container image + # inside our disc image + - type: org.osbuild.bootc.install-to-filesystem + inputs: + images: + type: org.osbuild.containers origin: org.osbuild.pipeline references: - - name:deployed-tree - 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: / - - type: org.osbuild.selinux + name:oci-archive: + name: coreos.ociarchive options: - file_contexts: input://tree/etc/selinux/targeted/contexts/files/file_contexts - target: mount://root/boot/ - inputs: - tree: - type: org.osbuild.tree - origin: org.osbuild.pipeline - references: - - name:deployed-tree + kernel-args: + - '$ignition_firstboot' + - mpp-format-string: '{extra_kargs}' + target-imgref: + mpp-format-string: '{container_imgref}' + stateroot: fedora-coreos + boot-mount-spec: "" + root-mount-spec: "" devices: disk: type: org.osbuild.loopback @@ -644,57 +472,25 @@ pipelines: 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 - - type: org.osbuild.copy - inputs: - tree: - type: org.osbuild.tree - origin: org.osbuild.pipeline - references: - - name:tree - options: - paths: - - from: input://tree/ - to: mount://root/ - 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}' + mpp-format-int: '{image.layout[''root''].partnum}' target: / - name: boot type: org.osbuild.ext4 source: disk partition: - mpp-format-int: '{image4k.layout[''boot''].partnum}' + mpp-format-int: '{image.layout[''boot''].partnum}' target: /boot - name: efi type: org.osbuild.fat source: disk partition: - mpp-format-int: '{image4k.layout[''EFI-SYSTEM''].partnum}' + mpp-format-int: '{image.layout[''EFI-SYSTEM''].partnum}' target: /boot/efi - - type: org.osbuild.bootupd + # set up the `ignition.firstboot` stamp at the end because + # bootc want empty filesystems + - type: org.osbuild.ignition options: - static-configs: true - deployment: - default: true + target: mount://boot/ devices: disk: type: org.osbuild.loopback @@ -708,46 +504,14 @@ pipelines: type: org.osbuild.xfs source: disk partition: - mpp-format-int: '{image4k.layout[''root''].partnum}' + mpp-format-int: '{image.layout[''root''].partnum}' target: / - name: boot type: org.osbuild.ext4 source: disk partition: - mpp-format-int: '{image4k.layout[''boot''].partnum}' + mpp-format-int: '{image.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 - - type: org.osbuild.chattr - options: - items: - mount://root/: - immutable: true - 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: ostree.deployment - type: org.osbuild.ostree.deployment - options: - source: mount - deployment: - default: true - mpp-import-pipelines: path: platform.aliyun.ipp.yaml - mpp-import-pipelines: diff --git a/src/runvm-osbuild b/src/runvm-osbuild index 3b1523f89e..a248ac85dc 100755 --- a/src/runvm-osbuild +++ b/src/runvm-osbuild @@ -114,11 +114,16 @@ set -x; osbuild-mpp \ "${mppyaml}" "${processed_json}" set +x -log_disk_usage +#log_disk_usage # Build the image set -x # shellcheck disable=SC2068 +# To stop osbuild at a given stage to inspect the state of +# things you can add `--break stage_id` to the following. +# eg : `--break org.osbuild.bootc.install-to-filesystem` +# The osbuild environnement is set up under `/run/osbuild` +# Use it in conjuction with `RUNVM_SHELL=1 in `cmd-osbuild` osbuild \ --out "$outdir" \ --store "$storedir" \ From a7209a6b75600f1d79fa74327f0fc3abe29ec0d7 Mon Sep 17 00:00:00 2001 From: jbtrystram Date: Tue, 29 Jul 2025 11:38:17 +0200 Subject: [PATCH 2/3] supermin: add ostree prepare-root config file Bootc is looking for the prepare-root config file in the buildroot environnement because the main assumption is that it's run from the target container. However, in osbuild, it's run from te buildroot, because podman inside bwrap (inside supermin in our case) causes issues. It's fine for RHCOS and SCOS where we use the target container as the buildroot but we cannot do that for FCOS because we require python in the buildroot. For now, insert a prepare-root file in the supermin VM (use as the buildroot for osbuild) until either : - bootc learn to look into the container for it [1] - we ship python in our images and can use them as buildroot. Another approach would be to layer python and the osbuild dependencies on top of our image and use that as the buildroot, but that would create room for packages drift (what was in the repos at build time?). At least using COSA it's easier to keep track of versions. [1] https://github.com/bootc-dev/bootc/issues/1410 --- src/osbuild-manifests/coreos.osbuild.x86_64.mpp.yaml | 10 +++++----- src/supermin-init-prelude.sh | 10 ++++++++++ 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/osbuild-manifests/coreos.osbuild.x86_64.mpp.yaml b/src/osbuild-manifests/coreos.osbuild.x86_64.mpp.yaml index ad91e568bb..182304190c 100644 --- a/src/osbuild-manifests/coreos.osbuild.x86_64.mpp.yaml +++ b/src/osbuild-manifests/coreos.osbuild.x86_64.mpp.yaml @@ -37,11 +37,11 @@ mpp-vars: # matches. Unfortunately for FCOS there is no python so we can't # really use FCOS as the buildroot so we'll use the host as the # buildroot there. - buildroot: "name:deployed-tree" - # mpp-if: osname in ['rhcos', 'scos', 'fc'] - # then: "name:deployed-tree" - # else: - # mpp-format-string: '{host_as_buildroot}' + buildroot: + mpp-if: osname in ['rhcos', 'scos'] + then: "name:deployed-tree" + else: + mpp-format-string: '{host_as_buildroot}' mpp-define-images: - id: image sector_size: diff --git a/src/supermin-init-prelude.sh b/src/supermin-init-prelude.sh index 0bb131d539..65b0de9e7e 100644 --- a/src/supermin-init-prelude.sh +++ b/src/supermin-init-prelude.sh @@ -73,3 +73,13 @@ touch /etc/cosa-supermin # the missing link. Hehe. update-alternatives --install /etc/alternatives/iptables iptables /usr/sbin/iptables-legacy 1 update-alternatives --install /etc/alternatives/ip6tables ip6tables /usr/sbin/ip6tables-legacy 1 + +# To build the disk image using osbuild and bootc install to-filesystem we need to +# have a prepare-root config in the build environnement for bootc to read. +# This workaround can be removed when https://github.com/bootc-dev/bootc/issues/1410 +# is fixed or we have python in all streams which allows us to use the OCI image as the buildroot. +# Note that RHCOS and SCOS use the OCI as buildroot so they should not be affected by this. +cat > /usr/lib/ostree/prepare-root.conf < Date: Wed, 30 Jul 2025 08:48:59 +0200 Subject: [PATCH 3/3] Add required osbuild patches to use bootc install Theses are patch from the following PRs: https://github.com/osbuild/osbuild/pull/2152 https://github.com/osbuild/osbuild/pull/2149 --- build.sh | 5 +- ...gnition-parametrize-the-path-to-boot.patch | 68 ++++++++++++++++ ...tall-to-filesystem-parametrize-state.patch | 65 +++++++++++++++ ...tall-make-boot-and-root-mount-spec-c.patch | 81 +++++++++++++++++++ 4 files changed, 218 insertions(+), 1 deletion(-) create mode 100644 src/0001-stages-ignition-parametrize-the-path-to-boot.patch create mode 100644 src/0005-stages-bootc.install-to-filesystem-parametrize-state.patch create mode 100644 src/0006-stages-bootc.install-make-boot-and-root-mount-spec-c.patch diff --git a/build.sh b/build.sh index e73a1944a0..c112aa7a91 100755 --- a/build.sh +++ b/build.sh @@ -190,12 +190,15 @@ patch_osbuild() { ## Now all the software is under the /usr/lib/osbuild dir and we can patch #cat foo.patch | patch -d /usr/lib/osbuild -p1 patch -d /usr/lib/osbuild -p1 < /usr/lib/coreos-assembler/0001-live-artifacts-read-os-name-from-usr-lib-os-release.patch + patch -d /usr/lib/osbuild -p1 < /usr/lib/coreos-assembler/0001-stages-ignition-parametrize-the-path-to-boot.patch + patch -d /usr/lib/osbuild -p1 < /usr/lib/coreos-assembler/0005-stages-bootc.install-to-filesystem-parametrize-state.patch + patch -d /usr/lib/osbuild -p1 < /usr/lib/coreos-assembler/0006-stages-bootc.install-make-boot-and-root-mount-spec-c.patch ## And then move the files back; supermin appliance creation will need it back ## in the places delivered by the RPM. mv /usr/lib/osbuild/tools/osbuild-mpp /usr/bin/osbuild-mpp mv /usr/lib/osbuild/osbuild /usr/lib/python3.13/site-packages/osbuild - mkdir /usr/lib/osbuild/osbuild + mkdir -p /usr/lib/osbuild/osbuild } if [ $# -ne 0 ]; then diff --git a/src/0001-stages-ignition-parametrize-the-path-to-boot.patch b/src/0001-stages-ignition-parametrize-the-path-to-boot.patch new file mode 100644 index 0000000000..1fe393ee93 --- /dev/null +++ b/src/0001-stages-ignition-parametrize-the-path-to-boot.patch @@ -0,0 +1,68 @@ +From f4698da5bb76e369ccf5478d65a96862562aa2bb Mon Sep 17 00:00:00 2001 +From: jbtrystram +Date: Thu, 17 Jul 2025 15:59:27 +0200 +Subject: [PATCH 1/6] stages/ignition: parametrize the path to boot + +Allow passing a mount to specify where to write the igntion.firstboot +file. +This keeps the default `tree:///` value to not break existing stages. +--- + stages/org.osbuild.ignition | 11 +++++++---- + stages/org.osbuild.ignition.meta.json | 5 +++++ + 2 files changed, 12 insertions(+), 4 deletions(-) + +diff --git a/stages/org.osbuild.ignition b/stages/org.osbuild.ignition +index 23f91c48..3e5b1903 100755 +--- a/stages/org.osbuild.ignition ++++ b/stages/org.osbuild.ignition +@@ -2,9 +2,12 @@ + import sys + + import osbuild.api ++from osbuild.util import parsing + + +-def main(tree, options): ++def main(args, options): ++ target = options.get("target", "tree:///boot") ++ location = parsing.parse_location(target, args) + network = options.get("network", []) + + # grub, when detecting the '/boot/ignition.firstboot' file +@@ -13,7 +16,7 @@ def main(tree, options): + # itself will be sourced this the 'ignition_network_kcmdline' + # that is also in the "ignition_firstboot" variable can be + # overwritten with the contents of `network` +- with open(f"{tree}/boot/ignition.firstboot", "w", encoding="utf8") as f: ++ with open(f"{location}/ignition.firstboot", "w", encoding="utf8") as f: + if network: + netstr = " ".join(network) + f.write(f"set ignition_network_kcmdline='{netstr}'") +@@ -22,6 +25,6 @@ def main(tree, options): + + + if __name__ == '__main__': +- args = osbuild.api.arguments() +- r = main(args["tree"], args.get("options", {})) ++ _args = osbuild.api.arguments() ++ r = main(_args, _args["options"]) + sys.exit(r) +diff --git a/stages/org.osbuild.ignition.meta.json b/stages/org.osbuild.ignition.meta.json +index 612d59c7..dd295c24 100644 +--- a/stages/org.osbuild.ignition.meta.json ++++ b/stages/org.osbuild.ignition.meta.json +@@ -22,6 +22,11 @@ + "items": { + "type": "string" + } ++ }, ++ "target": { ++ "type": "string", ++ "description": "Location to write the 'ignition.firstboot' file.", ++ "default": "tree:///boot" + } + } + } +-- +2.50.1 + diff --git a/src/0005-stages-bootc.install-to-filesystem-parametrize-state.patch b/src/0005-stages-bootc.install-to-filesystem-parametrize-state.patch new file mode 100644 index 0000000000..c317abf256 --- /dev/null +++ b/src/0005-stages-bootc.install-to-filesystem-parametrize-state.patch @@ -0,0 +1,65 @@ +From bb33a9fbd3d60e807aa8038e5e5e965f827cbcc7 Mon Sep 17 00:00:00 2001 +From: jbtrystram +Date: Mon, 21 Jul 2025 20:33:29 +0200 +Subject: [PATCH 5/6] stages/bootc.install-to-filesystem: parametrize stateroot + value + +This adds an extra option to make the stateroot name customizable. + +Fixes https://github.com/osbuild/osbuild/issues/2151 +--- + stages/org.osbuild.bootc.install-to-filesystem | 3 +++ + ...org.osbuild.bootc.install-to-filesystem.meta.json | 12 ++++++------ + 2 files changed, 9 insertions(+), 6 deletions(-) + +diff --git a/stages/org.osbuild.bootc.install-to-filesystem b/stages/org.osbuild.bootc.install-to-filesystem +index 6edcbf8f..3d4c67cc 100755 +--- a/stages/org.osbuild.bootc.install-to-filesystem ++++ b/stages/org.osbuild.bootc.install-to-filesystem +@@ -43,6 +43,9 @@ def main(options, inputs, paths): + target_imgref = options.get("target-imgref") + if target_imgref: + pargs.extend(["--target-imgref", target_imgref]) ++ stateroot = options.get("stateroot") ++ if stateroot: ++ pargs.extend(["--stateroot", stateroot]) + # add target and go + pargs.append(dst) + subprocess.run(pargs, env=env, check=True) +diff --git a/stages/org.osbuild.bootc.install-to-filesystem.meta.json b/stages/org.osbuild.bootc.install-to-filesystem.meta.json +index 02268b27..a5a157c6 100644 +--- a/stages/org.osbuild.bootc.install-to-filesystem.meta.json ++++ b/stages/org.osbuild.bootc.install-to-filesystem.meta.json +@@ -7,16 +7,12 @@ + "mounted in the \"mounts\" path.", + "Buildhost commands used: bootc" + ], +- "capabilities": [ +- "CAP_MAC_ADMIN" +- ], ++ "capabilities": ["CAP_MAC_ADMIN"], + "schema_2": { + "inputs": { + "type": "object", + "additionalProperties": false, +- "required": [ +- "images" +- ], ++ "required": ["images"], + "properties": { + "images": { + "type": "object", +@@ -44,6 +40,10 @@ + "target-imgref": { + "description": "Specify the image to fetch for subsequent updates", + "type": "string" ++ }, ++ "stateroot": { ++ "type": "string", ++ "description": "The stateroot name to use. If not specified, defer to bootc's default" + } + } + }, +-- +2.50.1 + diff --git a/src/0006-stages-bootc.install-make-boot-and-root-mount-spec-c.patch b/src/0006-stages-bootc.install-make-boot-and-root-mount-spec-c.patch new file mode 100644 index 0000000000..c3cbeeb5a9 --- /dev/null +++ b/src/0006-stages-bootc.install-make-boot-and-root-mount-spec-c.patch @@ -0,0 +1,81 @@ +From 8e23f3fd16c96f5122d7572efb98776540683df4 Mon Sep 17 00:00:00 2001 +From: jbtrystram +Date: Mon, 21 Jul 2025 20:49:13 +0200 +Subject: [PATCH 6/6] stages/bootc.install: make boot and root mount spec + customizable + +Allow passing custom mount specs for boot and root. Optional fields. +--- + stages/org.osbuild.bootc.install-to-filesystem | 17 +++++++++++++++++ + ...sbuild.bootc.install-to-filesystem.meta.json | 16 ++++++++++++++-- + 2 files changed, 31 insertions(+), 2 deletions(-) + +diff --git a/stages/org.osbuild.bootc.install-to-filesystem b/stages/org.osbuild.bootc.install-to-filesystem +index 3d4c67cc..634263e2 100755 +--- a/stages/org.osbuild.bootc.install-to-filesystem ++++ b/stages/org.osbuild.bootc.install-to-filesystem +@@ -46,6 +46,23 @@ def main(options, inputs, paths): + stateroot = options.get("stateroot") + if stateroot: + pargs.extend(["--stateroot", stateroot]) ++ # Passing the flag with an empty value is intentional: ++ # it triggers a supported behaviour where mountspec ++ # kernel arguments are ommited. ++ # See https://github.com/bootc-dev/bootc/pull/1451 ++ if "root-mount-spec" in options: ++ root_spec = options["root-mount-spec"] ++ if root_spec == "": ++ pargs.extend(["--root-mount-spec="]) ++ else: ++ pargs.extend(["--root-mount-spec", root_spec]) ++ if "boot-mount-spec" in options: ++ boot_spec = options["boot-mount-spec"] ++ if boot_spec == "": ++ pargs.extend(["--boot-mount-spec="]) ++ else: ++ pargs.extend(["--boot-mount-spec", boot_spec]) ++ + # add target and go + pargs.append(dst) + subprocess.run(pargs, env=env, check=True) +diff --git a/stages/org.osbuild.bootc.install-to-filesystem.meta.json b/stages/org.osbuild.bootc.install-to-filesystem.meta.json +index a5a157c6..53369218 100644 +--- a/stages/org.osbuild.bootc.install-to-filesystem.meta.json ++++ b/stages/org.osbuild.bootc.install-to-filesystem.meta.json +@@ -7,12 +7,16 @@ + "mounted in the \"mounts\" path.", + "Buildhost commands used: bootc" + ], +- "capabilities": ["CAP_MAC_ADMIN"], ++ "capabilities": [ ++ "CAP_MAC_ADMIN" ++ ], + "schema_2": { + "inputs": { + "type": "object", + "additionalProperties": false, +- "required": ["images"], ++ "required": [ ++ "images" ++ ], + "properties": { + "images": { + "type": "object", +@@ -44,6 +48,14 @@ + "stateroot": { + "type": "string", + "description": "The stateroot name to use. If not specified, defer to bootc's default" ++ }, ++ "root-mount-spec": { ++ "type": "string", ++ "description": "Source device specification for the root filesystem. If not provided, the UUID of the target filesystem will be used." ++ }, ++ "boot-mount-spec": { ++ "type": "string", ++ "description": "Mount specification for the /boot filesystem. If `/boot` is detected as a mounted partition, then its UUID will be used." + } + } + }, +-- +2.50.1 +