From 891bcf4caa42388307430988101511d06a8f187d Mon Sep 17 00:00:00 2001 From: Bipin B Narayan Date: Thu, 10 Jul 2025 09:50:11 -0400 Subject: [PATCH 1/4] Add `cosa import` This command takes as argument a `containers-transport(5)`-style pullspec and creates a new cosa build dir from it. It essentially bridges the gap between https://github.com/coreos/fedora-coreos-config/pull/3348 and the rest of the cosa pipeline. Co-authored-by: Jonathan Lebon --- cmd/coreos-assembler.go | 2 +- pkg/builds/cosa_v1.go | 7 +- pkg/builds/schema_doc.go | 15 ++-- src/cmd-coreos-prune | 2 +- src/cmd-import | 152 +++++++++++++++++++++++++++++++++++++++ src/cosalib/cmdlib.py | 48 ++++++++++++- src/v1.json | 13 +++- 7 files changed, 224 insertions(+), 15 deletions(-) create mode 100755 src/cmd-import diff --git a/cmd/coreos-assembler.go b/cmd/coreos-assembler.go index b0f60371b4..6fbfd27f75 100644 --- a/cmd/coreos-assembler.go +++ b/cmd/coreos-assembler.go @@ -13,7 +13,7 @@ import ( // commands we'd expect to use in the local dev path var buildCommands = []string{"init", "fetch", "build", "osbuild", "run", "prune", "clean", "list"} -var advancedBuildCommands = []string{"buildfetch", "buildupload", "oc-adm-release", "push-container"} +var advancedBuildCommands = []string{"import", "buildfetch", "buildupload", "oc-adm-release", "push-container"} var buildextendCommands = []string{"aliyun", "applehv", "aws", "azure", "digitalocean", "exoscale", "extensions-container", "gcp", "hyperv", "ibmcloud", "kubevirt", "live", "metal", "metal4k", "nutanix", "openstack", "oraclecloud", "qemu", "secex", "virtualbox", "vmware", "vultr"} var utilityCommands = []string{"aws-replicate", "coreos-prune", "compress", "copy-container", "diff", "koji-upload", "kola", "push-container-manifest", "remote-build-container", "remote-session", "sign", "tag", "update-variant"} diff --git a/pkg/builds/cosa_v1.go b/pkg/builds/cosa_v1.go index 9a7c8431c2..30045d4ea5 100644 --- a/pkg/builds/cosa_v1.go +++ b/pkg/builds/cosa_v1.go @@ -1,7 +1,7 @@ package builds // generated by 'make schema' -// source hash: 4bb5641ee8c32b122c412cbaefe3d068685ea6cbffcf3162e600a01268c92146 +// source hash: 445150ada0fe019c7bb33c793185b312111ed7538a59e1a0b424c10c6c2dbc0d type AdvisoryDiff []AdvisoryDiffItems @@ -56,6 +56,7 @@ type Build struct { CosaDelayedMetaMerge bool `json:"coreos-assembler.delayed-meta-merge,omitempty"` CosaImageChecksum string `json:"coreos-assembler.image-config-checksum,omitempty"` CosaImageVersion int `json:"coreos-assembler.image-genver,omitempty"` + CosaImportedOciImage bool `json:"coreos-assembler.oci-imported,omitempty"` Extensions *Extensions `json:"extensions,omitempty"` ExtensionsContainer *PrimaryImage `json:"extensions-container,omitempty"` FedoraCoreOsParentCommit string `json:"fedora-coreos.parent-commit,omitempty"` @@ -64,7 +65,7 @@ type Build struct { GitDirty string `json:"coreos-assembler.config-dirty,omitempty"` IbmCloud []Cloudartifact `json:"ibmcloud,omitempty"` ImageInputChecksum string `json:"coreos-assembler.image-input-checksum,omitempty"` - InputHashOfTheRpmOstree string `json:"rpm-ostree-inputhash"` + InputHashOfTheRpmOstree string `json:"rpm-ostree-inputhash,omitempty"` Koji *Koji `json:"koji,omitempty"` KubevirtContainer *PrimaryImage `json:"kubevirt,omitempty"` MetaStamp float64 `json:"coreos-assembler.meta-stamp,omitempty"` @@ -72,7 +73,7 @@ type Build struct { Oscontainer *PrimaryImage `json:"oscontainer,omitempty"` OstreeCommit string `json:"ostree-commit"` OstreeContentBytesWritten int `json:"ostree-content-bytes-written,omitempty"` - OstreeContentChecksum string `json:"ostree-content-checksum"` + OstreeContentChecksum string `json:"ostree-content-checksum,omitempty"` OstreeNCacheHits int `json:"ostree-n-cache-hits,omitempty"` OstreeNContentTotal int `json:"ostree-n-content-total,omitempty"` OstreeNContentWritten int `json:"ostree-n-content-written,omitempty"` diff --git a/pkg/builds/schema_doc.go b/pkg/builds/schema_doc.go index 4337f7e57e..48cb6df322 100644 --- a/pkg/builds/schema_doc.go +++ b/pkg/builds/schema_doc.go @@ -1,5 +1,5 @@ // Generated by ./generate-schema.sh -// Source hash: 4bb5641ee8c32b122c412cbaefe3d068685ea6cbffcf3162e600a01268c92146 +// Source hash: 445150ada0fe019c7bb33c793185b312111ed7538a59e1a0b424c10c6c2dbc0d // DO NOT EDIT package builds @@ -255,10 +255,8 @@ var generatedSchemaJSON = `{ "buildid", "name", "ostree-commit", - "ostree-content-checksum", "ostree-timestamp", - "ostree-version", - "rpm-ostree-inputhash" + "ostree-version" ], "optional": [ "aliyun", @@ -273,6 +271,7 @@ var generatedSchemaJSON = `{ "images", "koji", "oscontainer", + "ostree-content-checksum", "extensions", "extensions-container", "parent-pkgdiff", @@ -280,6 +279,7 @@ var generatedSchemaJSON = `{ "parent-advisories-diff", "advisories-diff", "release-payload", + "rpm-ostree-inputhash", "summary", "s3", "coreos-assembler.basearch", @@ -297,6 +297,7 @@ var generatedSchemaJSON = `{ "coreos-assembler.meta-stamp", "coreos-assembler.overrides-active", "coreos-assembler.yumrepos-git", + "coreos-assembeler.oci-imported", "fedora-coreos.parent-commit", "fedora-coreos.parent-version", "ref" @@ -378,6 +379,12 @@ var generatedSchemaJSON = `{ "default": "", "minLength": 1 }, + "coreos-assembler.oci-imported": { + "$id": "#/properties/coreos-assembler.oci-imported", + "type": "boolean", + "title": "COSA imported OCI image", + "default": "False" + }, "coreos-assembler.code-source": { "$id": "#/properties/coreos-assembler.code-source", "type": "string", diff --git a/src/cmd-coreos-prune b/src/cmd-coreos-prune index 08d90e2fd1..02e4d3d4a6 100755 --- a/src/cmd-coreos-prune +++ b/src/cmd-coreos-prune @@ -55,7 +55,7 @@ Build = collections.namedtuple("Build", ["id", "images", "arch", "meta_json"]) # set metadata caching to 5m CACHE_MAX_AGE_METADATA = 60 * 5 # These lists are up to date as of schema hash -# 4bb5641ee8c32b122c412cbaefe3d068685ea6cbffcf3162e600a01268c92146. If changing +# 445150ada0fe019c7bb33c793185b312111ed7538a59e1a0b424c10c6c2dbc0d. If changing # this hash, ensure that the list of SUPPORTED and UNSUPPORTED artifacts below # is up to date. SUPPORTED = ["amis", "aws-winli", "gcp"] diff --git a/src/cmd-import b/src/cmd-import new file mode 100755 index 0000000000..6a29e58d76 --- /dev/null +++ b/src/cmd-import @@ -0,0 +1,152 @@ +#!/usr/bin/python3 + +''' +This command takes a containers-transports(5) ref to an OCI image and converts +it into a `cosa build`, as if one did `cosa build ostree`. One can then e.g. +`cosa buildextend-qemu` right away. +''' + +import argparse +import datetime +import json +import os +import subprocess +import tempfile +import shutil +import sys +from stat import ( + S_IREAD, + S_IRGRP, + S_IROTH) +from cosalib.builds import Builds +from cosalib.cmdlib import ( + rfc3339_time, + get_basearch, + sha256sum_file, + import_oci_archive) + + +def main(): + args = parse_args() + + # immediate inspect to error out early if it doesn't exists/we don't have ACLs and to do some upfront checks + metadata = skopeo_inspect(args.srcimg) + + # let raise if missing + assert metadata['Labels']['containers.bootc'] == '1' + buildid = metadata['Labels']['org.opencontainers.image.version'] + + builds = Builds() + if builds.has(buildid): + print(f"ERROR: Build ID {buildid} already exists!") + sys.exit(1) + + with tempfile.TemporaryDirectory(prefix='cosa-import-', dir='tmp') as tmpd: + # create the OCI archive and manifest + tmp_oci_archive = generate_oci_archive(args, tmpd) + tmp_oci_manifest = generate_oci_manifest(args, tmpd) + + # import into the tmp/repo to get the ostree-commit but also so it's cached + ostree_commit = import_oci_archive(tmpd, tmp_oci_archive, buildid) + + # create meta.json + build_meta = generate_build_meta(tmp_oci_archive, tmp_oci_manifest, metadata, ostree_commit) + + # move into official location + finalize_build(builds, build_meta, tmp_oci_archive, tmp_oci_manifest) + + +def parse_args(): + parser = argparse.ArgumentParser(prog='cosa import') + parser.add_argument("srcimg", metavar='IMAGE', + help="image to import (containers-transports(5) format)") + return parser.parse_args() + + +def generate_oci_archive(args, tmpd): + tmpf = os.path.join(tmpd, 'out.ociarchive') + subprocess.check_call(['skopeo', 'copy', '--preserve-digests', args.srcimg, + f"oci-archive:{tmpf}"]) + return tmpf + + +def generate_oci_manifest(args, tmpd): + tmpf = os.path.join(tmpd, 'oci-manifest.json') + with open(tmpf, 'wb') as f: + f.write(subprocess.check_output(["skopeo", "inspect", "--raw", args.srcimg])) + os.fchmod(f.fileno(), S_IREAD | S_IRGRP | S_IROTH) + return tmpf + + +def generate_build_meta(tmp_oci_archive, tmp_oci_manifest, metadata, ostree_commit): + name = metadata['Labels']['com.coreos.osname'] + buildid = metadata['Labels']['org.opencontainers.image.version'] + created_timestamp = parse_timestamp(metadata['Created']) + arch = get_basearch() + + return { + 'ostree-commit': ostree_commit, + 'ostree-version': buildid, + 'buildid': buildid, + 'name': name, + 'coreos-assembler.basearch': arch, + 'coreos-assembler.build-timestamp': created_timestamp, + 'coreos-assembler.oci-imported': True, + 'ostree-timestamp': created_timestamp, + 'images': { + 'ostree': { + "path": f"{name}-{buildid}-ostree.{arch}.ociarchive", + "sha256": sha256sum_file(tmp_oci_archive), + 'size': os.path.getsize(tmp_oci_archive), + "skip-compression": True + }, + 'oci-manifest': { + 'path': f'{name}-{buildid}-ostree.{arch}-manifest.json', + 'sha256': sha256sum_file(tmp_oci_manifest), + 'size': os.path.getsize(tmp_oci_manifest), + "skip-compression": True, + }, + }, + } + + +def finalize_build(builds, build_meta, tmp_oci_archive, tmp_oci_manifest): + buildid = build_meta['buildid'] + arch = build_meta['coreos-assembler.basearch'] + + destdir = f'builds/{buildid}/{arch}' + os.makedirs(destdir) + + shutil.move(tmp_oci_archive, f'{destdir}/{build_meta['images']['ostree']['path']}') + shutil.move(tmp_oci_manifest, f'{destdir}/{build_meta['images']['oci-manifest']['path']}') + + with open(f'{destdir}/meta.json', 'w') as f: + json.dump(build_meta, f, indent=4) + + # and finally the real deal: insert the build and bump latest symlink + builds.insert_build(buildid, arch) + builds.bump_timestamp() + + if os.path.exists('builds/latest'): + os.remove('builds/latest') + os.symlink(f'{buildid}', 'builds/latest', target_is_directory=True) + + print(f'Imported OCI image as build {buildid}') + + +def skopeo_inspect(image): + return json.loads(subprocess.check_output(['skopeo', 'inspect', '-n', image])) + + +def parse_timestamp(timestamp): + # datetime's doesn't support nanoseconds. + # So trim it. + if len(timestamp) > 26 and timestamp[19] == '.': + timestamp = timestamp[:26] + "Z" + + timestamp = datetime.datetime.strptime(timestamp, '%Y-%m-%dT%H:%M:%S.%fZ') + return rfc3339_time(timestamp.replace(tzinfo=datetime.timezone.utc)) + + +if __name__ == '__main__': + main() diff --git a/src/cosalib/cmdlib.py b/src/cosalib/cmdlib.py index 00c2ce80cc..6416b818ca 100644 --- a/src/cosalib/cmdlib.py +++ b/src/cosalib/cmdlib.py @@ -295,12 +295,14 @@ def import_ostree_commit(workdir, buildpath, buildmeta, extract_json=True, parti lifetime=LOCK_DEFAULT_LIFETIME): repo = os.path.join(tmpdir, 'repo') commit = buildmeta['ostree-commit'] + is_oci_imported = buildmeta.get('coreos-assembler.oci-imported', False) tarfile = os.path.join(buildpath, buildmeta['images']['ostree']['path']) # create repo in case e.g. tmp/ was cleared out; idempotent subprocess.check_call(['ostree', 'init', '--repo', repo, '--mode=archive']) - # in the common case where we're operating on a recent build, the OSTree - # commit should already be in the tmprepo + # in the common case where we're operating on a recent build (or + # recently imported OCI image), the OSTree commit should already be in + # the tmprepo commitpartial = os.path.join(repo, f'state/{commit}.commitpartial') if (subprocess.call(['ostree', 'show', '--repo', repo, commit], stdout=subprocess.DEVNULL, @@ -332,8 +334,12 @@ def import_ostree_commit(workdir, buildpath, buildmeta, extract_json=True, parti # We do this in two stages, because right now ex-container only writes to # non-archive repos. Also, in the privileged case we need sudo to write # to `repo-build`, though it might be good to change this by default. - if os.environ.get('COSA_PRIVILEGED', '') == '1': + if is_oci_imported: + import_oci_archive(tmpdir, tarfile, buildmeta['buildid']) + elif os.environ.get('COSA_PRIVILEGED', '') == '1': build_repo = os.path.join(repo, '../../cache/repo-build') + # note: this actually is the same as `container unencapsulate` and + # so only works with "pure OSTree OCI" encapsulated commits (legacy path) subprocess.check_call(['sudo', 'ostree', 'container', 'import', '--repo', build_repo, '--write-ref', buildmeta['buildid'], 'ostree-unverified-image:oci-archive:' + tarfile]) @@ -354,6 +360,42 @@ def import_ostree_commit(workdir, buildpath, buildmeta, extract_json=True, parti extract_image_json(workdir, commit) +def import_oci_archive(parent_tmpd, ociarchive, ref): + with tempfile.TemporaryDirectory(dir=parent_tmpd) as tmpd: + subprocess.check_call(['ostree', 'init', '--repo', tmpd, '--mode=bare-user']) + + # Init tmp/repo in case it doesn't exist. + # If it exists, no problem. It's idempotent + subprocess.check_call(['ostree', 'init', '--repo', 'tmp/repo', '--mode=archive']) + + # import all the blob refs for more efficient import into bare-user repo + blob_refs = subprocess.check_output(['ostree', 'refs', '--repo', 'tmp/repo', + '--list', 'ostree/container/blob'], + encoding='utf-8').splitlines() + if len(blob_refs) > 0: + subprocess.check_call(['ostree', 'pull-local', '--repo', tmpd, 'tmp/repo'] + blob_refs) + + subprocess.check_call(['ostree', 'container', 'image', 'pull', tmpd, + f'ostree-unverified-image:oci-archive:{ociarchive}']) + + # awkwardly work around the fact that there is no --write-ref equivalent + refs = subprocess.check_output(['ostree', 'refs', '--repo', tmpd, + '--list', 'ostree/container/image'], + encoding='utf-8').splitlines() + assert len(refs) == 1 + subprocess.check_call(['ostree', 'refs', '--repo', tmpd, refs[0], '--create', ref]) + subprocess.check_call(['ostree', 'refs', '--repo', 'tmp/repo', ref, '--delete']) + subprocess.check_call(['ostree', 'pull-local', '--repo', 'tmp/repo', tmpd, ref]) + + # export back all the blob refs for more efficient imports of next builds + blob_refs = subprocess.check_output(['ostree', 'refs', '--repo', tmpd, + '--list', 'ostree/container/blob'], + encoding='utf-8').splitlines() + subprocess.check_call(['ostree', 'pull-local', '--repo', 'tmp/repo', tmpd] + blob_refs) + + return subprocess.check_output(['ostree', 'rev-parse', '--repo', 'tmp/repo', ref], encoding='utf-8').strip() + + def get_basearch(): try: return get_basearch.saved diff --git a/src/v1.json b/src/v1.json index 09d8b71d1b..1a6aa64056 100644 --- a/src/v1.json +++ b/src/v1.json @@ -249,10 +249,8 @@ "buildid", "name", "ostree-commit", - "ostree-content-checksum", "ostree-timestamp", - "ostree-version", - "rpm-ostree-inputhash" + "ostree-version" ], "optional": [ "aliyun", @@ -267,6 +265,7 @@ "images", "koji", "oscontainer", + "ostree-content-checksum", "extensions", "extensions-container", "parent-pkgdiff", @@ -274,6 +273,7 @@ "parent-advisories-diff", "advisories-diff", "release-payload", + "rpm-ostree-inputhash", "summary", "s3", "coreos-assembler.basearch", @@ -291,6 +291,7 @@ "coreos-assembler.meta-stamp", "coreos-assembler.overrides-active", "coreos-assembler.yumrepos-git", + "coreos-assembeler.oci-imported", "fedora-coreos.parent-commit", "fedora-coreos.parent-version", "ref" @@ -372,6 +373,12 @@ "default": "", "minLength": 1 }, + "coreos-assembler.oci-imported": { + "$id": "#/properties/coreos-assembler.oci-imported", + "type": "boolean", + "title": "COSA imported OCI image", + "default": "False" + }, "coreos-assembler.code-source": { "$id": "#/properties/coreos-assembler.code-source", "type": "string", From 215c3ce18e1246d394142fe035aefe63d241f0d2 Mon Sep 17 00:00:00 2001 From: Jonathan Lebon Date: Thu, 10 Jul 2025 17:26:19 -0400 Subject: [PATCH 2/4] cmd-osbuild: don't use output capture for generate_runvm_osbuild_config There's a massive gotcha with bash, which is that even with `set -e`, if you're capturing output from a function, e.g. `x=$(myfunc)`, `set -e` will not be turned on in that function. That made an error in that function much harder to diagnose because the command _kept going_ even though the function failed (and then the overall operation failed later on on a much less clear error). There's a bash option to enable this (`shopt inherit_errexit`), but I think actually that in general we shouldn't be capturing output from non-trivial bash functions. It's hard in bash to ensure clean stdout output and the longer a function gets, the harder it is to keep this up (notice e.g. how that function needs to be careful to `echo` everything to stderr). In this case, it's easy to rework the flow here to avoid this, so let's do that instead. --- src/cmd-osbuild | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/cmd-osbuild b/src/cmd-osbuild index 1dc241923c..ef2a4f69f0 100755 --- a/src/cmd-osbuild +++ b/src/cmd-osbuild @@ -163,12 +163,7 @@ postprocess_qemu_secex() { # Here we generate the input JSON we pass to runvm_osbuild for all of our image builds generate_runvm_osbuild_config() { - runvm_osbuild_config_json="${workdir}/tmp/runvm-osbuild-config-${build}.json" - echo "${runvm_osbuild_config_json}" # Let the caller know where the config will be - if [ -f "${runvm_osbuild_config_json}" ]; then - return # only need to generate this once per build - fi - rm -f "${workdir}"/tmp/runvm-osbuild-config-*.json # clean up any previous configs + local outfile=$1; shift # reread these values from the build itself rather than rely on the ones loaded # by prepare_build since the config might've changed since then @@ -223,7 +218,7 @@ generate_runvm_osbuild_config() { echo "Disk sizes: metal: ${metal_image_size_mb}M (estimated), cloud: ${cloud_image_size_mb}M" >&2 # Generate the JSON describing the disk we want to build - yaml2json /dev/stdin "${runvm_osbuild_config_json}" < Date: Tue, 15 Jul 2025 21:51:34 -0400 Subject: [PATCH 3/4] cmd-prune: prune blob refs from tmp repo We now keep blob refs in the tmp repo to make importing OCI images more efficient by avoiding having to re-import identical layers. But then we also need to prune them. Do this. The semantic here is simple: we prune any blob ref not tied to one of the kept builds. --- src/cmd-prune | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/cmd-prune b/src/cmd-prune index 660eae5790..b6818c5a8c 100755 --- a/src/cmd-prune +++ b/src/cmd-prune @@ -183,5 +183,25 @@ for build in builds_to_delete: error_during_pruning = True print(f"{e}") +# and delete any "unowned" blob refs from the tmp repo +if os.path.exists('tmp/repo'): + prefix = 'ostree/container/blob/' + referenced_blobs = set() + for build in builds.get_builds(): + meta = builds.get_build_meta(build['id']) + build_dir = builds.get_build_dir(build['id']) + with open(os.path.join(build_dir, meta['images']['oci-manifest']['path'])) as f: + oci_manifest = json.load(f) + referenced_blobs.update([prefix + layer['digest'].replace(':', '_3A_') + for layer in oci_manifest['layers']]) + blobs = set(subprocess.check_output(['ostree', 'refs', '--repo=tmp/repo', + '--list', 'ostree/container/blob'], + encoding='utf-8').splitlines()) + blobs_to_delete = blobs.difference(referenced_blobs) + if len(blobs_to_delete) > 0: + print(f"Deleting {len(blobs_to_delete)} blob refs") + subprocess.check_output(['ostree', 'refs', '--repo=tmp/repo', + '--delete'] + list(blobs_to_delete)) + if error_during_pruning: sys.exit(1) From dcefea394c700d4d5de41681d834eba849a26096 Mon Sep 17 00:00:00 2001 From: Bipin B Narayan Date: Mon, 14 Jul 2025 22:13:30 +0530 Subject: [PATCH 4/4] Patch osbuild to generate osname from os-release file Treefile.json from rpm-ostree doesn't contain `name` in the `metadata` field from images built using podman build. --- build.sh | 18 +++++------ ...read-os-name-from-usr-lib-os-release.patch | 30 +++++++++++++++++++ 2 files changed, 39 insertions(+), 9 deletions(-) create mode 100644 src/0001-live-artifacts-read-os-name-from-usr-lib-os-release.patch diff --git a/build.sh b/build.sh index 2e942dbc51..048af330c8 100755 --- a/build.sh +++ b/build.sh @@ -177,25 +177,25 @@ write_archive_info() { } patch_osbuild() { - return # we have no patches right now ## Add a few patches that either haven't made it into a release or ## that will be obsoleted with other work that will be done soon. ## To make it easier to apply patches we'll move around the osbuild ## code on the system first: - #rmdir /usr/lib/osbuild/osbuild - #mv /usr/lib/python3.13/site-packages/osbuild /usr/lib/osbuild/ - #mkdir /usr/lib/osbuild/tools - #mv /usr/bin/osbuild-mpp /usr/lib/osbuild/tools/ + rmdir /usr/lib/osbuild/osbuild + mv /usr/lib/python3.13/site-packages/osbuild /usr/lib/osbuild/ + mkdir /usr/lib/osbuild/tools + mv /usr/bin/osbuild-mpp /usr/lib/osbuild/tools/ ## 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 + ## 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 + 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 } if [ $# -ne 0 ]; then diff --git a/src/0001-live-artifacts-read-os-name-from-usr-lib-os-release.patch b/src/0001-live-artifacts-read-os-name-from-usr-lib-os-release.patch new file mode 100644 index 0000000000..ae78683f18 --- /dev/null +++ b/src/0001-live-artifacts-read-os-name-from-usr-lib-os-release.patch @@ -0,0 +1,30 @@ +From 7593b65dc77bf5dbb26fe9c54386759ab7f740a7 Mon Sep 17 00:00:00 2001 +From: Bipin B Narayan +Date: Mon, 14 Jul 2025 19:43:12 +0530 +Subject: [PATCH] live-artifacts: read os name from /usr/lib/os-release + +With importing ociarchive, the treefile.json doesn't contain osname. +--- + stages/org.osbuild.coreos.live-artifacts.mono | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/stages/org.osbuild.coreos.live-artifacts.mono b/stages/org.osbuild.coreos.live-artifacts.mono +index 1384a343..4a95b607 100755 +--- a/stages/org.osbuild.coreos.live-artifacts.mono ++++ b/stages/org.osbuild.coreos.live-artifacts.mono +@@ -131,10 +131,8 @@ def make_stream_hash(src, dest): + + + def get_os_name(tree): +- file = os.path.join(tree, 'usr/share/rpm-ostree/treefile.json') +- with open(file, encoding='utf8') as f: +- treefile = json.load(f) +- return treefile['metadata']['name'] ++ os_release = osrelease.parse_files(os.path.join(tree, 'usr', 'lib', 'os-release')) ++ return f"{os_release['ID']}-{os_release['VARIANT_ID']}" + + + def ensure_glob(pathname, n="", **kwargs): +-- +2.50.1 +