diff --git a/build.sh b/build.sh index b46b9c886b..27abeca482 100755 --- a/build.sh +++ b/build.sh @@ -208,7 +208,8 @@ patch_osbuild() { /usr/lib/coreos-assembler/0002-osbuild-util-containers.py-rename-variable.patch \ /usr/lib/coreos-assembler/0003-osbuild-util-containers.py-drop-copy-when-using-cont.patch \ /usr/lib/coreos-assembler/0004-drop-remove_signatures-from-org.osbuild.container-de.patch \ - /usr/lib/coreos-assembler/0005-tools-osbuild-mpp-support-mpp-resolve-for-org.osbuil.patch | + /usr/lib/coreos-assembler/0005-tools-osbuild-mpp-support-mpp-resolve-for-org.osbuil.patch \ + /usr/lib/coreos-assembler/0001-stages-add-new-link-stage.patch | patch -d /usr/lib/osbuild -p1 # And then move the files back; supermin appliance creation will need it back diff --git a/src/0001-stages-add-new-link-stage.patch b/src/0001-stages-add-new-link-stage.patch new file mode 100644 index 0000000000..545155e0b5 --- /dev/null +++ b/src/0001-stages-add-new-link-stage.patch @@ -0,0 +1,132 @@ +From f53b6e1c5a8f0c26ee4f92641274a8cdba4b1d5a Mon Sep 17 00:00:00 2001 +From: jbtrystram +Date: Tue, 21 Oct 2025 13:13:57 +0200 +Subject: [PATCH 1/2] stages: add new link stage + +This introduces a new stage, `org.osbuild.ln`, for creating +links within the filesystem tree. + +This takes a list of paths, each with a `target` and a `link_name` +parameters, inspired by the copy stage. + +The target is a simple string because we want the link to be either +absolute or relative. +--- + stages/org.osbuild.ln | 31 ++++++++++++++++ + stages/org.osbuild.ln.meta.json | 66 +++++++++++++++++++++++++++++++++ + 2 files changed, 97 insertions(+) + create mode 100755 stages/org.osbuild.ln + create mode 100644 stages/org.osbuild.ln.meta.json + +diff --git a/stages/org.osbuild.ln b/stages/org.osbuild.ln +new file mode 100755 +index 00000000..8268685d +--- /dev/null ++++ b/stages/org.osbuild.ln +@@ -0,0 +1,31 @@ ++#!/usr/bin/python3 ++import os ++import sys ++ ++import osbuild.api ++from osbuild.util import parsing ++ ++ ++def main(args, options): ++ items = options["paths"] ++ ++ for path in items: ++ target = path["target"] ++ link_name = parsing.parse_location(path["link_name"], args) ++ symbolic = path.get("symbolic", False) ++ ++ print(f"Linking '{link_name}' -> '{target}'") ++ if symbolic: ++ print(f"Creating symbolic link: '{link_name}' -> '{target}'") ++ os.symlink(target, link_name) ++ else: ++ print(f"Creating hard link: '{link_name}' -> '{target}'") ++ os.link(target, link_name) ++ ++ return 0 ++ ++ ++if __name__ == '__main__': ++ _args = osbuild.api.arguments() ++ r = main(_args, _args["options"]) ++ sys.exit(r) +diff --git a/stages/org.osbuild.ln.meta.json b/stages/org.osbuild.ln.meta.json +new file mode 100644 +index 00000000..81f297be +--- /dev/null ++++ b/stages/org.osbuild.ln.meta.json +@@ -0,0 +1,66 @@ ++{ ++ "summary": "Create links", ++ "description": [ ++ "Creates links within the tree or mounts. The target and link_name are specified as URLs.", ++ "Only allows tree or mounts URLs." ++ ], ++ "schema_2": { ++ "options": { ++ "additionalProperties": false, ++ "required": [ ++ "paths" ++ ], ++ "properties": { ++ "paths": { ++ "description": "Array of links to create.", ++ "type": "array", ++ "minItems": 1, ++ "items": { ++ "type": "object", ++ "additionalProperties": false, ++ "required": [ ++ "target", ++ "link_name" ++ ], ++ "properties": { ++ "target": { ++ "type": "string", ++ "description": "The target for the link, relative or absolute" ++ }, ++ "link_name": { ++ "oneOf": [ ++ { ++ "type": "string", ++ "description": "The link path, if in a mount", ++ "pattern": "^mount://[^/]+/" ++ }, ++ { ++ "type": "string", ++ "description": "The link path, if in a tree", ++ "pattern": "^tree://" ++ } ++ ] ++ }, ++ "symbolic": { ++ "type": "boolean", ++ "description": "Use a symbolic link instead of hard-linking. Defaults to False.", ++ "default": false ++ } ++ } ++ } ++ } ++ } ++ }, ++ "devices": { ++ "type": "object", ++ "additionalProperties": true ++ }, ++ "mounts": { ++ "type": "array" ++ }, ++ "inputs": { ++ "type": "object", ++ "additionalProperties": true ++ } ++ } ++} +-- +2.51.0 + diff --git a/src/cmd-osbuild b/src/cmd-osbuild index 0f263bede4..b2f2d1bebd 100755 --- a/src/cmd-osbuild +++ b/src/cmd-osbuild @@ -408,10 +408,23 @@ main() { else cmd="runvm_with_cache" fi - $cmd -- /usr/lib/coreos-assembler/runvm-osbuild \ - --config "${runvm_osbuild_config_json}" \ - --mpp "/usr/lib/coreos-assembler/osbuild-manifests/coreos.osbuild.${basearch}.mpp.yaml" \ - --outdir "${outdir}" \ + + # Use the bootc install to-filesystem manifest if applicable + bootc_suffix="" + if should_use_bootc_install; then + bootc_suffix=".bootc" + fi + + manifest_path="/usr/lib/coreos-assembler/osbuild-manifests/coreos.osbuild.${basearch}${bootc_suffix}.mpp.yaml" + + # To get a shell in the osbuild supermin VM uncomment this. + # osbuild can then be started with `bash tmp/build./cmd.sh` + # See comment about checkpoints in runvm-osbuild + # RUNVM_SHELL=1 \ + $cmd -- /usr/lib/coreos-assembler/runvm-osbuild \ + --config "${runvm_osbuild_config_json}" \ + --mpp "${manifest_path}" \ + --outdir "${outdir}" \ --platforms "$(IFS=,; echo "${platforms[*]}")" for platform in "${platforms[@]}"; do diff --git a/src/cmdlib.sh b/src/cmdlib.sh index 979e00f5c5..d046d9fb44 100755 --- a/src/cmdlib.sh +++ b/src/cmdlib.sh @@ -148,28 +148,53 @@ yaml2json() { python3 -c 'import sys, json, yaml; json.dump(yaml.safe_load(sys.stdin), sys.stdout, sort_keys=True)' < "$1" > "$2" } -should_build_with_buildah() { - local variant manifest - if [ -n "${COSA_BUILD_WITH_BUILDAH:-}" ]; then - if [ "${COSA_BUILD_WITH_BUILDAH:-}" = 1 ]; then +# Common helper to check for features that can be enabled via an env var or +# in the manifest metadata. +_should_enable_feature() { + local env_var_name=$1 + local metadata_key=$2 + local env_var_value + # Indirect expansion + env_var_value=${!env_var_name:-} + + if [ -n "${env_var_value}" ]; then + if [ "${env_var_value}" = 1 ]; then return 0 else return 1 fi fi + + # Make sure we are in the config directory (e.g. cmd-osbuild set a different working directory). + # When called very early (e.g. cmd-fetch), configdir isn't initialized yet so we assume we are in the top + # cosa initialized dir and use `src/config`. + # We redirect the output to /dev/null to avoid the noisy `dirs` output. + set +u + pushd "${configdir:-src/config}" > /dev/null + set -u # this slightly duplicates some logic in `prepare_build`, but meh... - if [[ -f "src/config.json" ]]; then - variant="$(jq --raw-output '."coreos-assembler.config-variant"' src/config.json)" - manifest="src/config/manifest-${variant}.yaml" + if [[ -f "../config.json" ]]; then + variant="$(jq --raw-output '."coreos-assembler.config-variant"' ../config.json)" + manifest="manifest-${variant}.yaml" else - manifest="src/config/manifest.yaml" + manifest="manifest.yaml" fi - if [ "$(yq .metadata.build_with_buildah "${manifest}")" = true ]; then + if [ "$(yq ".metadata.${metadata_key}" "${manifest}")" = true ]; then + popd > /dev/null return 0 fi + popd > /dev/null return 1 } +should_use_bootc_install() { + _should_enable_feature "COSA_OSBUILD_USE_BOOTC_INSTALL" "use_bootc_install" +} + +should_build_with_buildah() { + _should_enable_feature "COSA_BUILD_WITH_BUILDAH" "build_with_buildah" +} + prepare_build() { preflight preflight_kvm @@ -759,8 +784,8 @@ runvm() { # include COSA in the image find /usr/lib/coreos-assembler/ -type f > "${vmpreparedir}/hostfiles" cat <> "${vmpreparedir}/hostfiles" -/usr/lib/osbuild/stages/org.osbuild.coreos.live-artifacts.mono -/usr/lib/osbuild/stages/org.osbuild.coreos.live-artifacts.mono.meta.json +/usr/lib/osbuild/stages/org.osbuild.ln +/usr/lib/osbuild/stages/org.osbuild.ln.meta.json EOF # and include all GPG keys @@ -787,7 +812,7 @@ rc=0 if [ -z "${RUNVM_SHELL:-}" ]; then (cd ${workdir}; bash ${tmp_builddir}/cmd.sh |& tee /dev/virtio-ports/cosa-cmdout) || rc=\$? else - (cd ${workdir}; bash) + (cd ${workdir}; RUNVM_SHELL=${RUNVM_SHELL:-} bash) fi echo \$rc > ${rc_file} if [ -n "\${cachedev}" ]; then diff --git a/src/osbuild-manifests/coreos.osbuild.x86_64.bootc.mpp.yaml b/src/osbuild-manifests/coreos.osbuild.x86_64.bootc.mpp.yaml new file mode 100644 index 0000000000..9a02052907 --- /dev/null +++ b/src/osbuild-manifests/coreos.osbuild.x86_64.bootc.mpp.yaml @@ -0,0 +1,740 @@ +version: '2' +mpp-vars: + artifact_name_prefix: $artifact_name_prefix + ociarchive: $ociarchive + osname: $osname + container_imgref: $container_imgref + container_repo: $container_repo + container_tag: $container_tag + extra_kargs: $extra_kargs + metal_image_size_mb: $metal_image_size_mb + cloud_image_size_mb: $cloud_image_size_mb + bios_boot_size_mb: 1 + ppc_prep_size_mb: 4 + reserved_part_size_mb: 1 + efi_system_size_mb: 127 + boot_size_mb: 384 + sector_size: 512 + four_k_sector_size: 4096 + # Filesystem UUID and label definitions. These UUIDs + # are looked for on boot and if found replaced with + # a new random UUID to make each install unique. + boot_fs_uuid: 96d15588-3596-4b3c-adca-a2ff7279ea63 + boot_fs_label: boot + root_fs_uuid: 910678ff-f77e-4a7d-8d53-86f2ac47a823 + root_fs_label: root + # For some stages (i.e. the qemu stages) we'll use the host as + # the buildroot (i.e. COSA in most cases but sometimes just + # the actual HOST filesystem like in coreos/custom-coreos-disk-images). + # This is useful/necessary because we definitely don't include + # qemu-img or tools like zip in the actual CoreOS OS. "" here + # means to use the host as buildroot. It is worth noting that + # the host buildroot is the default if nothing is specified. + # We're still defining it here in an attempt to be explicit. + host_as_buildroot: "" + # Set the buildroot string to use for most operations here. We create + # the buildroot from the target OSTree contents so we have version + # 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}' +mpp-define-images: + - id: image + sector_size: + mpp-format-int: "{sector_size}" + size: + mpp-format-string: "{metal_image_size_mb * 1024 * 1024}" + table: + uuid: 00000000-0000-4000-a000-000000000001 + label: gpt + partitions: + - name: BIOS-BOOT + type: 21686148-6449-6E6F-744E-656564454649 + bootable: true + size: + mpp-format-int: "{bios_boot_size_mb * 1024 * 1024 / sector_size}" + - name: EFI-SYSTEM + type: C12A7328-F81F-11D2-BA4B-00A0C93EC93B + size: + mpp-format-int: "{efi_system_size_mb * 1024 * 1024 / sector_size}" + - name: boot + type: 0FC63DAF-8483-4772-8E79-3D69D8477DE4 + size: + mpp-format-int: "{boot_size_mb * 1024 * 1024 / sector_size}" + - name: root + type: 0FC63DAF-8483-4772-8E79-3D69D8477DE4 + - id: image4k + sector_size: + mpp-format-int: "{four_k_sector_size}" + size: + mpp-format-string: "{metal_image_size_mb * 1024 * 1024}" + table: + uuid: 00000000-0000-4000-a000-000000000001 + label: gpt + partitions: + - name: BIOS-BOOT + type: 21686148-6449-6E6F-744E-656564454649 + bootable: true + size: + mpp-format-int: "{bios_boot_size_mb * 1024 * 1024 / four_k_sector_size}" + - name: EFI-SYSTEM + type: C12A7328-F81F-11D2-BA4B-00A0C93EC93B + size: + mpp-format-int: "{efi_system_size_mb * 1024 * 1024 / four_k_sector_size}" + - name: boot + type: 0FC63DAF-8483-4772-8E79-3D69D8477DE4 + size: + mpp-format-int: "{boot_size_mb * 1024 * 1024 / four_k_sector_size}" + - name: root + type: 0FC63DAF-8483-4772-8E79-3D69D8477DE4 +pipelines: + # If installing from container then let's pull the container file into a pipeline + - name: oci-archive + stages: + - mpp-if: ociarchive != '' + then: + type: org.osbuild.copy + inputs: + inlinefile: + type: org.osbuild.files + origin: org.osbuild.source + mpp-embed: + id: coreos.ociarchive + url: + mpp-format-string: 'file://{ociarchive}' + options: + paths: + - from: + mpp-format-string: input://inlinefile/{embedded['coreos.ociarchive']} + to: tree:///coreos.ociarchive + else: + type: org.osbuild.noop + # Construct a tree here that is a representation of the filesystem + # that you would see on a running OSTree system. i.e. instead of just + # /ostree and /sysroot at the toplevel we see /usr/ /var/ /etc/ ... that + # you would see inside an OSTree deployment. Having the plain files accessible + # allows for this pipeline to be used as a buildroot for some stages + # or as inputs for others (i.e. file_context input to the org.osbuild.selinux + # stages). This pipeline isn't actually used for built artifacts but + # to help during build. + # + # NOTE: this is only used as a buildroot on RHCOS (FCOS doesn't ship python). + - name: deployed-tree + stages: + - mpp-if: ociarchive != '' + then: + type: org.osbuild.container-deploy + inputs: + images: + type: org.osbuild.containers + origin: org.osbuild.pipeline + references: + name:oci-archive: + name: coreos.ociarchive + else: + type: org.osbuild.container-deploy + inputs: + images: + type: org.osbuild.containers-storage + origin: org.osbuild.source + mpp-resolve-images: + images: + - source: $container_repo + tag: $container_tag + - name: tree + build: + mpp-format-string: '{buildroot}' + source-epoch: 1659397331 + stages: + # Set the context of the root of the tree so that we avoid unlabeled_t files. + # https://github.com/coreos/fedora-coreos-tracker/issues/1772 + - type: org.osbuild.selinux + options: + file_contexts: input://tree/etc/selinux/targeted/contexts/files/file_contexts + target: tree:/// + inputs: + tree: + type: org.osbuild.tree + origin: org.osbuild.pipeline + references: + - name:deployed-tree + - name: raw-image + build: + mpp-format-string: '{buildroot}' + stages: + - type: org.osbuild.truncate + options: + filename: disk.img + size: + mpp-format-string: '{image.size}' + - type: org.osbuild.sfdisk + devices: + device: + type: org.osbuild.loopback + options: + filename: disk.img + options: + mpp-format-json: '{image.layout}' + - type: org.osbuild.mkfs.fat + devices: + device: + type: org.osbuild.loopback + options: + filename: disk.img + start: + mpp-format-int: '{image.layout[''EFI-SYSTEM''].start}' + size: + mpp-format-int: '{image.layout[''EFI-SYSTEM''].size}' + lock: true + options: + label: EFI-SYSTEM + volid: 7B7795E7 + - type: org.osbuild.mkfs.ext4 + devices: + device: + type: org.osbuild.loopback + options: + filename: disk.img + start: + mpp-format-int: '{image.layout[''boot''].start}' + size: + mpp-format-int: '{image.layout[''boot''].size}' + lock: true + options: + uuid: + mpp-format-string: '{boot_fs_uuid}' + label: + mpp-format-string: '{boot_fs_label}' + # Set manually the metadata_csum_seed ext4 option otherwise changing the + # filesystem UUID while it's mounted doesn't work. Can remove this when + # metadata_csum_seed is default in RHEL, which can be checked by looking + # in /etc/mke2fs.conf. + metadata_csum_seed: true + - type: org.osbuild.mkfs.xfs + devices: + device: + type: org.osbuild.loopback + options: + filename: disk.img + start: + mpp-format-int: '{image.layout[''root''].start}' + size: + mpp-format-int: '{image.layout[''root''].size}' + lock: true + options: + uuid: + mpp-format-string: '{root_fs_uuid}' + label: + mpp-format-string: '{root_fs_label}' + # We've created the filesystems. Now let's create the mountpoints (directories) + # on the filesystems and label them with appropriate SELinux labels. This also + # covers things like filesystem autogenerated files like 'lost+found'. The labeling + # will happen once with just the root filesystem mounted and once with the boot + # filesystem mounted too (to make sure we get all potentially hidden mountpoints). + # https://github.com/coreos/fedora-coreos-tracker/issues/1771 + - type: org.osbuild.mkdir + options: + paths: + - path: mount://root/boot + mode: 493 + - path: mount://boot/efi + mode: 493 + 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: /root-mount-point + - name: boot + type: org.osbuild.ext4 + source: disk + partition: + mpp-format-int: '{image.layout[''boot''].partnum}' + target: /boot-mount-point + # Set the context of the root of disk so that we avoid unlabeled_t files. + # Here we make sure to not mount the boot partition because we want to label + # the directory mount point + # https://github.com/coreos/fedora-coreos-tracker/issues/1772 + - 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: / + # Then we mount le boot parition and label again so the /boot/efi + # mount point is labeled properly + - 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 + 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 + # 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: + mpp-if: ociarchive != '' + then: + type: org.osbuild.containers + origin: org.osbuild.pipeline + references: + name:oci-archive: + name: coreos.ociarchive + else: + type: org.osbuild.containers-storage + origin: org.osbuild.source + mpp-resolve-images: + images: + - source: $container_repo + tag: $container_tag + options: + kernel-args: + - '$ignition_firstboot' + - mpp-format-string: '{extra_kargs}' + target-imgref: + mpp-format-string: '{container_imgref}' + stateroot: + mpp-format-string: '{osname}' + # Empty strings mean mount spec kargs are ommited entirely. + # See github.com/bootc-dev/bootc/issues/1441 + boot-mount-spec: "" + root-mount-spec: "" + 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 + # set up the `ignition.firstboot` stamp at the end because + # bootc want empty filesystems + - type: org.osbuild.ignition + options: + target: mount://boot/ + 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.ln + options: + paths: + - target: ".bootc-aleph.json" + link_name: "mount://root/.coreos-aleph-version.json" + symbolic: true + - target: ".bootc-aleph.json" + link_name: "mount://root/.aleph-version.json" + symbolic: 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: raw-4k-image + build: + mpp-format-string: '{buildroot}' + stages: + - type: org.osbuild.truncate + options: + filename: disk.img + size: + mpp-format-string: '{image4k.size}' + - type: org.osbuild.sfdisk + devices: + device: + type: org.osbuild.loopback + options: + filename: disk.img + sector-size: + mpp-format-int: "{four_k_sector_size}" + options: + mpp-format-json: '{image4k.layout}' + - type: org.osbuild.mkfs.fat + devices: + device: + type: org.osbuild.loopback + options: + filename: disk.img + start: + mpp-format-int: '{image4k.layout[''EFI-SYSTEM''].start}' + size: + mpp-format-int: '{image4k.layout[''EFI-SYSTEM''].size}' + lock: true + sector-size: + mpp-format-int: "{four_k_sector_size}" + options: + label: EFI-SYSTEM + volid: 7B7795E7 + - type: org.osbuild.mkfs.ext4 + devices: + device: + type: org.osbuild.loopback + options: + filename: disk.img + start: + mpp-format-int: '{image4k.layout[''boot''].start}' + size: + mpp-format-int: '{image4k.layout[''boot''].size}' + lock: true + sector-size: + mpp-format-int: "{four_k_sector_size}" + options: + uuid: + mpp-format-string: '{boot_fs_uuid}' + label: + mpp-format-string: '{boot_fs_label}' + # Set manually the metadata_csum_seed ext4 option otherwise changing the + # filesystem UUID while it's mounted doesn't work. Can remove this when + # metadata_csum_seed is default in RHEL, which can be checked by looking + # in /etc/mke2fs.conf. + metadata_csum_seed: true + - type: org.osbuild.mkfs.xfs + devices: + device: + type: org.osbuild.loopback + options: + filename: disk.img + start: + mpp-format-int: '{image4k.layout[''root''].start}' + size: + mpp-format-int: '{image4k.layout[''root''].size}' + lock: true + sector-size: + mpp-format-int: "{four_k_sector_size}" + options: + uuid: + mpp-format-string: '{root_fs_uuid}' + label: + mpp-format-string: '{root_fs_label}' + # We've created the filesystems. Now let's create the mountpoints (directories) + # on the filesystems and label them with appropriate SELinux labels. This also + # covers things like filesystem autogenerated files like 'lost+found'. The labeling + # will happen once with just the root filesystem mounted and once with the boot + # filesystem mounted too (to make sure we get all potentially hidden mountpoints). + # https://github.com/coreos/fedora-coreos-tracker/issues/1771 + - type: org.osbuild.mkdir + options: + paths: + - path: mount://root/boot + mode: 493 + - path: mount://boot/efi + mode: 493 + 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: /root-mount-point + - name: boot + type: org.osbuild.ext4 + source: disk + partition: + mpp-format-int: '{image4k.layout[''boot''].partnum}' + target: /boot-mount-point + # Set the context of the root of disk so that we avoid unlabeled_t files. + # Here we make sure to not mount the boot partition because we want to label + # the directory mount point + # https://github.com/coreos/fedora-coreos-tracker/issues/1772 + - 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: / + # Then we mount le boot parition and label again so the /boot/efi + # mount point is labeled properly + - 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 + 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 + # 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: + mpp-if: ociarchive != '' + then: + type: org.osbuild.containers + origin: org.osbuild.pipeline + references: + name:oci-archive: + name: coreos.ociarchive + else: + type: org.osbuild.containers-storage + origin: org.osbuild.source + mpp-resolve-images: + images: + - source: $container_repo + tag: $container_tag + options: + kernel-args: + - '$ignition_firstboot' + - mpp-format-string: '{extra_kargs}' + target-imgref: + mpp-format-string: '{container_imgref}' + stateroot: + mpp-format-string: '{osname}' + # Empty strings mean mount spec kargs are ommited entirely. + # See github.com/bootc-dev/bootc/issues/1441 + boot-mount-spec: "" + root-mount-spec: "" + 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 + # set up the `ignition.firstboot` stamp at the end because + # bootc want empty filesystems + - type: org.osbuild.ignition + options: + target: mount://boot/ + 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 + - type: org.osbuild.ln + options: + paths: + - target: ".bootc-aleph.json" + link_name: "mount://root/.coreos-aleph-version.json" + symbolic: true + - target: ".bootc-aleph.json" + link_name: "mount://root/.aleph-version.json" + symbolic: 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: / + - mpp-import-pipelines: + path: platform.aliyun.ipp.yaml + - mpp-import-pipelines: + path: platform.applehv.ipp.yaml + - mpp-import-pipelines: + path: platform.aws.ipp.yaml + - mpp-import-pipelines: + path: platform.azure.ipp.yaml + - mpp-import-pipelines: + path: platform.azurestack.ipp.yaml + - mpp-import-pipelines: + path: platform.digitalocean.ipp.yaml + - mpp-import-pipelines: + path: platform.exoscale.ipp.yaml + - mpp-import-pipelines: + path: platform.gcp.ipp.yaml + - mpp-import-pipelines: + path: platform.hetzner.ipp.yaml + - mpp-import-pipelines: + path: platform.hyperv.ipp.yaml + - mpp-import-pipelines: + path: platform.ibmcloud.ipp.yaml + - mpp-import-pipelines: + path: platform.kubevirt.ipp.yaml + - mpp-import-pipelines: + path: platform.openstack.ipp.yaml + - mpp-import-pipelines: + path: platform.oraclecloud.ipp.yaml + - mpp-import-pipelines: + path: platform.proxmoxve.ipp.yaml + - mpp-import-pipelines: + path: platform.metal.ipp.yaml + - mpp-import-pipelines: + path: platform.nutanix.ipp.yaml + - mpp-import-pipelines: + path: platform.qemu.ipp.yaml + - mpp-import-pipelines: + path: platform.vultr.ipp.yaml + - mpp-import-pipelines: + path: platform.live.ipp.yaml diff --git a/src/runvm-osbuild b/src/runvm-osbuild index 5193db3eb3..dcc0feabf8 100755 --- a/src/runvm-osbuild +++ b/src/runvm-osbuild @@ -117,11 +117,18 @@ set -x; osbuild-mpp \ "${mppyaml}" "${processed_json}" set +x -log_disk_usage +if [[ -z "${RUNVM_SHELL:-}" ]]; then + log_disk_usage +fi # 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" \ diff --git a/src/supermin-init-prelude.sh b/src/supermin-init-prelude.sh index e17f7ff542..d5c506c63a 100644 --- a/src/supermin-init-prelude.sh +++ b/src/supermin-init-prelude.sh @@ -87,3 +87,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 <