summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBruce Ashfield <bruce.ashfield@gmail.com>2026-05-10 13:58:10 +0000
committerBruce Ashfield <bruce.ashfield@gmail.com>2026-05-10 13:58:10 +0000
commit3d431848b32caae67b9dcbf7fe04f08ddcd448b5 (patch)
treeab48eaceb7931a73159348e0bf67d93beda3256d
parent84e81eea1a581e10528b2ba95f9c34ee67c8ad3c (diff)
downloadmeta-virtualization-3d431848b32caae67b9dcbf7fe04f08ddcd448b5.tar.gz
oci-multiarch: fix MC defaults, deploy dependency, and OCI layout
Three issues prevented oci-multiarch.bbclass from producing usable multi-architecture container images: 1. MC defaults pointed to vruntime-* multiconfigs, whose BBMASK blocks OCI tooling. Changed to container-* multiconfigs which use the new vcontainer distro without BBMASK. 2. mcdepends targeted do_image_oci, but the OCI output is only deployed to deploy/images/ by the later do_image_complete task. The bbclass then failed to find the OCI directory at the expected deploy path. The original implementation assumed do_image_oci was the final step, but OE-core's image pipeline has a separate deploy phase. 3. The OCI Image Index was written directly into index.json with multiple manifest entries. This is valid per the OCI spec but skopeo requires index.json to reference a single entry when there are multiple images. The fix writes the multi-platform image index as a blob in blobs/sha256/ and has index.json reference it with a single entry of mediaType application/vnd.oci.image.index.v1+json. This nested layout is what tools like buildah and crane produce for multi-arch images, and is required for 'skopeo copy --all' to work. Also adds container-base-multiarch.bb recipe that wires up container-base for aarch64 + x86_64 builds via the oci-multiarch class. Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
-rw-r--r--classes/oci-multiarch.bbclass47
-rw-r--r--recipes-extended/images/container-base-multiarch.bb9
2 files changed, 44 insertions, 12 deletions
diff --git a/classes/oci-multiarch.bbclass b/classes/oci-multiarch.bbclass
index 9960b7cc..3923a52e 100644
--- a/classes/oci-multiarch.bbclass
+++ b/classes/oci-multiarch.bbclass
@@ -17,9 +17,9 @@
17# OCI_MULTIARCH_RECIPE = "myapp-container" 17# OCI_MULTIARCH_RECIPE = "myapp-container"
18# OCI_MULTIARCH_PLATFORMS = "aarch64 x86_64" 18# OCI_MULTIARCH_PLATFORMS = "aarch64 x86_64"
19# 19#
20# # Optional: custom multiconfig mapping 20# # Optional: custom multiconfig mapping (defaults use vcontainer distro)
21# OCI_MULTIARCH_MC[aarch64] = "vruntime-aarch64" 21# OCI_MULTIARCH_MC[aarch64] = "container-aarch64"
22# OCI_MULTIARCH_MC[x86_64] = "vruntime-x86-64" 22# OCI_MULTIARCH_MC[x86_64] = "container-x86-64"
23# 23#
24# OUTPUT: 24# OUTPUT:
25# ${DEPLOY_DIR_IMAGE}/${PN}-multiarch-oci/ 25# ${DEPLOY_DIR_IMAGE}/${PN}-multiarch-oci/
@@ -28,8 +28,8 @@
28# blobs/sha256/ - Combined blobs from all architectures 28# blobs/sha256/ - Combined blobs from all architectures
29# 29#
30# REQUIREMENTS: 30# REQUIREMENTS:
31# - Multiconfig must be enabled in local.conf: 31# - Multiconfig must be enabled (meta-virt-host.conf provides defaults):
32# BBMULTICONFIG = "vruntime-aarch64 vruntime-x86-64" 32# BBMULTICONFIG = "... container-aarch64 container-x86-64"
33# - OCI_MULTIARCH_RECIPE must inherit image-oci or produce OCI output 33# - OCI_MULTIARCH_RECIPE must inherit image-oci or produce OCI output
34# 34#
35# =========================================================================== 35# ===========================================================================
@@ -42,9 +42,9 @@ INHIBIT_DEFAULT_DEPS = "1"
42OCI_MULTIARCH_RECIPE ?= "" 42OCI_MULTIARCH_RECIPE ?= ""
43OCI_MULTIARCH_PLATFORMS ?= "" 43OCI_MULTIARCH_PLATFORMS ?= ""
44 44
45# Default multiconfig mapping (uses existing vruntime-* configs) 45# Default multiconfig mapping (uses vcontainer distro -- no BBMASK)
46OCI_MULTIARCH_MC[aarch64] ?= "vruntime-aarch64" 46OCI_MULTIARCH_MC[aarch64] ?= "container-aarch64"
47OCI_MULTIARCH_MC[x86_64] ?= "vruntime-x86-64" 47OCI_MULTIARCH_MC[x86_64] ?= "container-x86-64"
48 48
49# Machine mapping for deploy directory paths 49# Machine mapping for deploy directory paths
50OCI_MULTIARCH_MACHINE[aarch64] ?= "qemuarm64" 50OCI_MULTIARCH_MACHINE[aarch64] ?= "qemuarm64"
@@ -87,7 +87,7 @@ python __anonymous() {
87 mc = d.getVarFlag('OCI_MULTIARCH_MC', platform) 87 mc = d.getVarFlag('OCI_MULTIARCH_MC', platform)
88 if not mc: 88 if not mc:
89 bb.fatal(f"No multiconfig defined for platform '{platform}'. Set OCI_MULTIARCH_MC[{platform}]") 89 bb.fatal(f"No multiconfig defined for platform '{platform}'. Set OCI_MULTIARCH_MC[{platform}]")
90 mcdepends.append(f"mc::{mc}:{recipe}:do_image_oci") 90 mcdepends.append(f"mc::{mc}:{recipe}:do_image_complete")
91 91
92 # Set the mcdepends for our main task 92 # Set the mcdepends for our main task
93 d.setVarFlag('do_create_multiarch_index', 'mcdepends', ' '.join(mcdepends)) 93 d.setVarFlag('do_create_multiarch_index', 'mcdepends', ' '.join(mcdepends))
@@ -191,17 +191,40 @@ python do_create_multiarch_index() {
191 if not index_manifests: 191 if not index_manifests:
192 bb.fatal("No manifests collected - cannot create multi-arch index") 192 bb.fatal("No manifests collected - cannot create multi-arch index")
193 193
194 # Create the OCI Image Index 194 # Create the OCI Image Index as a blob (not directly in index.json).
195 # skopeo requires index.json to reference a single entry; the actual
196 # multi-platform manifest list lives in blobs/sha256/ and index.json
197 # points to it.
195 image_index = { 198 image_index = {
196 'schemaVersion': 2, 199 'schemaVersion': 2,
197 'mediaType': 'application/vnd.oci.image.index.v1+json', 200 'mediaType': 'application/vnd.oci.image.index.v1+json',
198 'manifests': index_manifests 201 'manifests': index_manifests
199 } 202 }
200 203
201 # Write index.json 204 image_index_json = json.dumps(image_index, indent=2).encode('utf-8')
205 image_index_digest = hashlib.sha256(image_index_json).hexdigest()
206 image_index_size = len(image_index_json)
207
208 # Write the image index as a blob
209 blob_path = os.path.join(output_dir, 'blobs', 'sha256', image_index_digest)
210 with open(blob_path, 'wb') as f:
211 f.write(image_index_json)
212
213 # Write index.json pointing to the image index blob
214 top_index = {
215 'schemaVersion': 2,
216 'manifests': [
217 {
218 'mediaType': 'application/vnd.oci.image.index.v1+json',
219 'digest': f'sha256:{image_index_digest}',
220 'size': image_index_size
221 }
222 ]
223 }
224
202 index_path = os.path.join(output_dir, 'index.json') 225 index_path = os.path.join(output_dir, 'index.json')
203 with open(index_path, 'w') as f: 226 with open(index_path, 'w') as f:
204 json.dump(image_index, f, indent=2) 227 json.dump(top_index, f, indent=2)
205 228
206 # Write oci-layout 229 # Write oci-layout
207 layout_path = os.path.join(output_dir, 'oci-layout') 230 layout_path = os.path.join(output_dir, 'oci-layout')
diff --git a/recipes-extended/images/container-base-multiarch.bb b/recipes-extended/images/container-base-multiarch.bb
new file mode 100644
index 00000000..220e3555
--- /dev/null
+++ b/recipes-extended/images/container-base-multiarch.bb
@@ -0,0 +1,9 @@
1SUMMARY = "Multi-architecture OCI container base image"
2DESCRIPTION = "Builds container-base for multiple architectures and \
3combines them into a single OCI Image Index (manifest list)."
4LICENSE = "MIT"
5
6inherit oci-multiarch
7
8OCI_MULTIARCH_RECIPE = "container-base"
9OCI_MULTIARCH_PLATFORMS = "aarch64 x86_64"