diff options
| author | Bruce Ashfield <bruce.ashfield@gmail.com> | 2026-02-15 04:35:55 +0000 |
|---|---|---|
| committer | Bruce Ashfield <bruce.ashfield@gmail.com> | 2026-02-26 01:05:01 +0000 |
| commit | 57d267db7878180d1ecd1936df5284550d0031c3 (patch) | |
| tree | b2205ccb2e6114fdda4384518d4b9047209756ef /recipes-core | |
| parent | 0fe8c4444f3199b862a4ba52b2b62b5f9b2af85f (diff) | |
| download | meta-virtualization-57d267db7878180d1ecd1936df5284550d0031c3.tar.gz | |
vxn: add Xen DomU container runtime with OCI image support
vxn runs OCI containers as Xen DomU guests — the VM IS the container.
No Docker/containerd runs inside the guest; the init script directly
mounts the container rootfs and execs the entrypoint via chroot.
Host-side (Dom0):
- vxn.sh: Docker-like CLI wrapper (sets HYPERVISOR=xen)
- vrunner-backend-xen.sh: Xen xl backend for vrunner
- hv_prepare_container(): pulls OCI images via skopeo,
resolves entrypoint from OCI config using jq on host
- xl create for VM lifecycle (PVH on aarch64, PV on x86_64)
- Bridge networking with iptables DNAT for port forwards
- Console capture via xl console for ephemeral mode
Guest-side (DomU):
- vxn-init.sh: mounts container rootfs from input disk,
extracts OCI layers, execs entrypoint via chroot
- Supports containers with or without /bin/sh
- grep/sed fallback for OCI config parsing (no jq needed)
- Daemon mode with command loop on hvc1
- vcontainer-init-common.sh: hypervisor detection, head -n fix
- vcontainer-preinit.sh: init selection via vcontainer.init=
Build system:
- vxn-initramfs-create.inc: assembles boot blobs from vruntime
multiconfig, injects vxn-init.sh into rootfs squashfs
- vxn_1.0.bb: Dom0 package with scripts + blobs
- nostamp on install/package chain (blobs from DEPLOY_DIR
are untracked by sstate)
- vxn.cfg: Xen PV kernel config fragment
Tested: vxn -it --no-daemon run --rm hello-world
Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
Diffstat (limited to 'recipes-core')
| -rw-r--r-- | recipes-core/vxn/vxn-initramfs-create.inc | 223 | ||||
| -rw-r--r-- | recipes-core/vxn/vxn-initramfs-create_1.0.bb | 43 | ||||
| -rw-r--r-- | recipes-core/vxn/vxn_1.0.bb | 167 |
3 files changed, 433 insertions, 0 deletions
diff --git a/recipes-core/vxn/vxn-initramfs-create.inc b/recipes-core/vxn/vxn-initramfs-create.inc new file mode 100644 index 00000000..bde8bba9 --- /dev/null +++ b/recipes-core/vxn/vxn-initramfs-create.inc | |||
| @@ -0,0 +1,223 @@ | |||
| 1 | # SPDX-FileCopyrightText: Copyright (C) 2025 Bruce Ashfield | ||
| 2 | # | ||
| 3 | # SPDX-License-Identifier: MIT | ||
| 4 | # | ||
| 5 | # vxn-initramfs-create.inc | ||
| 6 | # =========================================================================== | ||
| 7 | # Shared code for building Xen DomU boot blobs for vxn | ||
| 8 | # =========================================================================== | ||
| 9 | # | ||
| 10 | # This .inc file packages boot blobs for vxn (vcontainer on Xen). | ||
| 11 | # It reuses the same initramfs and rootfs images built by vruntime | ||
| 12 | # multiconfig (same images as vdkr/vpdmn), since the init scripts | ||
| 13 | # detect the hypervisor at boot time. | ||
| 14 | # | ||
| 15 | # The kernel from vruntime already includes Xen PV support via vxn.cfg | ||
| 16 | # fragment (added to DISTRO_FEATURES in vruntime.conf). | ||
| 17 | # | ||
| 18 | # Required variables from including recipe: | ||
| 19 | # VXN_RUNTIME - runtime to source blobs from ("vdkr" or "vpdmn") | ||
| 20 | # | ||
| 21 | # Boot flow on Xen Dom0: | ||
| 22 | # xl create <domain.cfg> | ||
| 23 | # -> Xen boots kernel + tiny initramfs in DomU | ||
| 24 | # -> preinit mounts rootfs.img from /dev/xvda | ||
| 25 | # -> switch_root into rootfs.img | ||
| 26 | # -> init detects Xen, uses /dev/xvd* and trans=xen | ||
| 27 | # | ||
| 28 | # =========================================================================== | ||
| 29 | |||
| 30 | HOMEPAGE = "https://git.yoctoproject.org/meta-virtualization/" | ||
| 31 | LICENSE = "MIT" | ||
| 32 | LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302" | ||
| 33 | |||
| 34 | inherit deploy | ||
| 35 | |||
| 36 | EXCLUDE_FROM_WORLD = "1" | ||
| 37 | DEPENDS = "squashfs-tools-native" | ||
| 38 | |||
| 39 | # Default to vdkr (Docker) as the source runtime | ||
| 40 | VXN_RUNTIME ?= "vdkr" | ||
| 41 | |||
| 42 | # Always rebuild - init script injection must not be sstate-cached | ||
| 43 | # because the rootfs.img content comes from the deploy dir (untracked) | ||
| 44 | SSTATE_SKIP_CREATION = "1" | ||
| 45 | do_compile[nostamp] = "1" | ||
| 46 | do_deploy[nostamp] = "1" | ||
| 47 | |||
| 48 | python () { | ||
| 49 | |||
| 50 | mc = d.getVar('VXN_MULTICONFIG') | ||
| 51 | runtime = d.getVar('VXN_RUNTIME') | ||
| 52 | bbmulticonfig = (d.getVar('BBMULTICONFIG') or "").split() | ||
| 53 | if mc in bbmulticonfig: | ||
| 54 | # All blobs come from the vruntime multiconfig - kernel, initramfs, rootfs | ||
| 55 | mcdeps = ' '.join([ | ||
| 56 | 'mc::%s:%s-tiny-initramfs-image:do_image_complete' % (mc, runtime), | ||
| 57 | 'mc::%s:%s-rootfs-image:do_image_complete' % (mc, runtime), | ||
| 58 | 'mc::%s:virtual/kernel:do_deploy' % mc, | ||
| 59 | ]) | ||
| 60 | d.setVarFlag('do_compile', 'mcdepends', mcdeps) | ||
| 61 | } | ||
| 62 | |||
| 63 | INHIBIT_DEFAULT_DEPS = "1" | ||
| 64 | |||
| 65 | # Init scripts to inject into the rootfs squashfs | ||
| 66 | FILESEXTRAPATHS:prepend := "${THISDIR}/../../recipes-containers/vcontainer/files:" | ||
| 67 | SRC_URI = "\ | ||
| 68 | file://vxn-init.sh \ | ||
| 69 | file://vcontainer-init-common.sh \ | ||
| 70 | " | ||
| 71 | |||
| 72 | S = "${UNPACKDIR}" | ||
| 73 | B = "${WORKDIR}/build" | ||
| 74 | |||
| 75 | def vxn_get_kernel_image_name(d): | ||
| 76 | arch = d.getVar('TARGET_ARCH') | ||
| 77 | if arch == 'aarch64': | ||
| 78 | return 'Image' | ||
| 79 | elif arch in ['x86_64', 'i686', 'i586']: | ||
| 80 | return 'bzImage' | ||
| 81 | elif arch == 'arm': | ||
| 82 | return 'zImage' | ||
| 83 | return 'Image' | ||
| 84 | |||
| 85 | def vxn_get_multiconfig_name(d): | ||
| 86 | arch = d.getVar('TARGET_ARCH') | ||
| 87 | if arch == 'aarch64': | ||
| 88 | return 'vruntime-aarch64' | ||
| 89 | elif arch in ['x86_64', 'i686', 'i586']: | ||
| 90 | return 'vruntime-x86-64' | ||
| 91 | return 'vruntime-aarch64' | ||
| 92 | |||
| 93 | def vxn_get_blob_arch(d): | ||
| 94 | arch = d.getVar('TARGET_ARCH') | ||
| 95 | if arch == 'aarch64': | ||
| 96 | return 'aarch64' | ||
| 97 | elif arch in ['x86_64', 'i686', 'i586']: | ||
| 98 | return 'x86_64' | ||
| 99 | return 'aarch64' | ||
| 100 | |||
| 101 | KERNEL_IMAGETYPE_INITRAMFS = "${@vxn_get_kernel_image_name(d)}" | ||
| 102 | VXN_MULTICONFIG = "${@vxn_get_multiconfig_name(d)}" | ||
| 103 | BLOB_ARCH = "${@vxn_get_blob_arch(d)}" | ||
| 104 | |||
| 105 | VXN_MC_DEPLOY = "${TOPDIR}/tmp-${VXN_MULTICONFIG}/deploy/images/${MACHINE}" | ||
| 106 | |||
| 107 | do_compile() { | ||
| 108 | mkdir -p ${B} | ||
| 109 | |||
| 110 | MC_TMPDIR="${TOPDIR}/tmp-${VXN_MULTICONFIG}" | ||
| 111 | MC_DEPLOY="${MC_TMPDIR}/deploy/images/${MACHINE}" | ||
| 112 | |||
| 113 | # ========================================================================= | ||
| 114 | # PART 1: COPY TINY INITRAMFS (same as vdkr/vpdmn) | ||
| 115 | # ========================================================================= | ||
| 116 | bbnote "Copying tiny initramfs from image build..." | ||
| 117 | |||
| 118 | INITRAMFS_SRC="${MC_DEPLOY}/${VXN_RUNTIME}-tiny-initramfs-image-${MACHINE}.cpio.gz" | ||
| 119 | |||
| 120 | if [ ! -f "${INITRAMFS_SRC}" ]; then | ||
| 121 | bbfatal "Initramfs not found at ${INITRAMFS_SRC}. Build it first with: bitbake mc:${VXN_MULTICONFIG}:${VXN_RUNTIME}-tiny-initramfs-image" | ||
| 122 | fi | ||
| 123 | |||
| 124 | cp "${INITRAMFS_SRC}" ${B}/initramfs.cpio.gz | ||
| 125 | INITRAMFS_SIZE=$(stat -c%s ${B}/initramfs.cpio.gz) | ||
| 126 | bbnote "Initramfs copied: ${INITRAMFS_SIZE} bytes ($(expr ${INITRAMFS_SIZE} / 1024)KB)" | ||
| 127 | |||
| 128 | # ========================================================================= | ||
| 129 | # PART 2: COPY ROOTFS (same squashfs, works under both QEMU and Xen) | ||
| 130 | # ========================================================================= | ||
| 131 | bbnote "Copying rootfs from image build..." | ||
| 132 | |||
| 133 | ROOTFS_SRC="${MC_DEPLOY}/${VXN_RUNTIME}-rootfs-image-${MACHINE}.rootfs.squashfs" | ||
| 134 | |||
| 135 | if [ ! -f "${ROOTFS_SRC}" ]; then | ||
| 136 | bbfatal "Rootfs image not found at ${ROOTFS_SRC}. Build it first with: bitbake mc:${VXN_MULTICONFIG}:${VXN_RUNTIME}-rootfs-image" | ||
| 137 | fi | ||
| 138 | |||
| 139 | cp "${ROOTFS_SRC}" ${B}/rootfs.img | ||
| 140 | ROOTFS_SIZE=$(stat -c%s ${B}/rootfs.img) | ||
| 141 | bbnote "Rootfs image copied: ${ROOTFS_SIZE} bytes ($(expr ${ROOTFS_SIZE} / 1024 / 1024)MB)" | ||
| 142 | |||
| 143 | # Inject vxn init scripts into the rootfs squashfs | ||
| 144 | bbnote "Injecting vxn init scripts into rootfs..." | ||
| 145 | UNSQUASH_DIR="${B}/rootfs-unsquash" | ||
| 146 | rm -rf "${UNSQUASH_DIR}" | ||
| 147 | unsquashfs -d "${UNSQUASH_DIR}" ${B}/rootfs.img | ||
| 148 | install -m 0755 ${S}/vxn-init.sh ${UNSQUASH_DIR}/vxn-init.sh | ||
| 149 | install -m 0755 ${S}/vcontainer-init-common.sh ${UNSQUASH_DIR}/vcontainer-init-common.sh | ||
| 150 | rm -f ${B}/rootfs.img | ||
| 151 | mksquashfs "${UNSQUASH_DIR}" ${B}/rootfs.img -noappend -comp xz | ||
| 152 | rm -rf "${UNSQUASH_DIR}" | ||
| 153 | ROOTFS_SIZE=$(stat -c%s ${B}/rootfs.img) | ||
| 154 | bbnote "Rootfs with vxn init scripts: ${ROOTFS_SIZE} bytes ($(expr ${ROOTFS_SIZE} / 1024 / 1024)MB)" | ||
| 155 | |||
| 156 | # ========================================================================= | ||
| 157 | # PART 3: COPY KERNEL (Xen PV-capable via vxn.cfg fragment) | ||
| 158 | # ========================================================================= | ||
| 159 | bbnote "Copying kernel image..." | ||
| 160 | KERNEL_FILE="${DEPLOY_DIR_IMAGE}/${KERNEL_IMAGETYPE_INITRAMFS}" | ||
| 161 | if [ -f "${KERNEL_FILE}" ]; then | ||
| 162 | cp "${KERNEL_FILE}" ${B}/kernel | ||
| 163 | KERNEL_SIZE=$(stat -c%s ${B}/kernel) | ||
| 164 | bbnote "Kernel copied: ${KERNEL_SIZE} bytes ($(expr ${KERNEL_SIZE} / 1024 / 1024)MB)" | ||
| 165 | else | ||
| 166 | bbwarn "Kernel not found at ${KERNEL_FILE}" | ||
| 167 | fi | ||
| 168 | } | ||
| 169 | |||
| 170 | # This is a deploy-only recipe - no packages produced. | ||
| 171 | # PACKAGES="" prevents the rootfs task from looking for package manifests. | ||
| 172 | PACKAGES = "" | ||
| 173 | do_install[noexec] = "1" | ||
| 174 | do_package[noexec] = "1" | ||
| 175 | do_packagedata[noexec] = "1" | ||
| 176 | do_package_write_rpm[noexec] = "1" | ||
| 177 | do_package_write_ipk[noexec] = "1" | ||
| 178 | do_package_write_deb[noexec] = "1" | ||
| 179 | do_populate_sysroot[noexec] = "1" | ||
| 180 | |||
| 181 | do_deploy() { | ||
| 182 | install -d ${DEPLOYDIR}/vxn/${BLOB_ARCH} | ||
| 183 | |||
| 184 | if [ -f ${B}/initramfs.cpio.gz ]; then | ||
| 185 | install -m 0644 ${B}/initramfs.cpio.gz ${DEPLOYDIR}/vxn/${BLOB_ARCH}/ | ||
| 186 | bbnote "Deployed initramfs.cpio.gz to vxn/${BLOB_ARCH}/" | ||
| 187 | fi | ||
| 188 | |||
| 189 | if [ -f ${B}/rootfs.img ]; then | ||
| 190 | install -m 0644 ${B}/rootfs.img ${DEPLOYDIR}/vxn/${BLOB_ARCH}/ | ||
| 191 | bbnote "Deployed rootfs.img to vxn/${BLOB_ARCH}/" | ||
| 192 | fi | ||
| 193 | |||
| 194 | if [ -f ${B}/kernel ]; then | ||
| 195 | install -m 0644 ${B}/kernel ${DEPLOYDIR}/vxn/${BLOB_ARCH}/${KERNEL_IMAGETYPE_INITRAMFS} | ||
| 196 | bbnote "Deployed kernel as vxn/${BLOB_ARCH}/${KERNEL_IMAGETYPE_INITRAMFS}" | ||
| 197 | fi | ||
| 198 | |||
| 199 | cat > ${DEPLOYDIR}/vxn/${BLOB_ARCH}/README << EOF | ||
| 200 | vxn Boot Blobs (Xen DomU) | ||
| 201 | ========================== | ||
| 202 | |||
| 203 | Built for: ${TARGET_ARCH} | ||
| 204 | Machine: ${MACHINE} | ||
| 205 | Multiconfig: ${VXN_MULTICONFIG} | ||
| 206 | Source runtime: ${VXN_RUNTIME} | ||
| 207 | Date: $(date) | ||
| 208 | |||
| 209 | Files: | ||
| 210 | ${KERNEL_IMAGETYPE_INITRAMFS} - Kernel image (Xen PV-capable) | ||
| 211 | initramfs.cpio.gz - Tiny initramfs (busybox + preinit) | ||
| 212 | rootfs.img - Root filesystem with container tools | ||
| 213 | |||
| 214 | Boot flow: | ||
| 215 | xl create <domain.cfg> | ||
| 216 | -> Xen boots kernel + initramfs in DomU | ||
| 217 | -> preinit detects Xen, mounts rootfs.img from /dev/xvda | ||
| 218 | -> switch_root into rootfs.img | ||
| 219 | -> init script runs container commands | ||
| 220 | EOF | ||
| 221 | } | ||
| 222 | |||
| 223 | addtask deploy after do_compile before do_build | ||
diff --git a/recipes-core/vxn/vxn-initramfs-create_1.0.bb b/recipes-core/vxn/vxn-initramfs-create_1.0.bb new file mode 100644 index 00000000..edbef12f --- /dev/null +++ b/recipes-core/vxn/vxn-initramfs-create_1.0.bb | |||
| @@ -0,0 +1,43 @@ | |||
| 1 | # SPDX-FileCopyrightText: Copyright (C) 2025 Bruce Ashfield | ||
| 2 | # | ||
| 3 | # SPDX-License-Identifier: MIT | ||
| 4 | # | ||
| 5 | # vxn-initramfs-create_1.0.bb | ||
| 6 | # =========================================================================== | ||
| 7 | # Builds Xen DomU boot blobs for vxn | ||
| 8 | # =========================================================================== | ||
| 9 | # | ||
| 10 | # This recipe packages boot blobs for vxn (vcontainer on Xen): | ||
| 11 | # - A tiny initramfs (reused from vdkr/vpdmn build) | ||
| 12 | # - The rootfs.img squashfs (same as vdkr, with HV detection in init) | ||
| 13 | # - The kernel (Xen PV-capable via vxn.cfg fragment in vruntime) | ||
| 14 | # | ||
| 15 | # Boot flow on Xen Dom0: | ||
| 16 | # xl create domain.cfg | ||
| 17 | # -> Xen boots kernel + tiny initramfs in DomU | ||
| 18 | # -> preinit detects Xen block prefix, mounts rootfs.img from /dev/xvda | ||
| 19 | # -> switch_root into rootfs.img | ||
| 20 | # -> vdkr-init.sh detects Xen via /proc/xen, uses xvd* devices | ||
| 21 | # | ||
| 22 | # =========================================================================== | ||
| 23 | # BUILD INSTRUCTIONS | ||
| 24 | # =========================================================================== | ||
| 25 | # | ||
| 26 | # For aarch64: | ||
| 27 | # MACHINE=qemuarm64 bitbake vxn-initramfs-create | ||
| 28 | # | ||
| 29 | # For x86_64: | ||
| 30 | # MACHINE=qemux86-64 bitbake vxn-initramfs-create | ||
| 31 | # | ||
| 32 | # Blobs are deployed to: tmp/deploy/images/${MACHINE}/vxn/ | ||
| 33 | # | ||
| 34 | # =========================================================================== | ||
| 35 | |||
| 36 | SUMMARY = "Build Xen DomU boot blobs for vxn" | ||
| 37 | DESCRIPTION = "Packages kernel, initramfs and rootfs for running \ | ||
| 38 | vcontainer workloads as Xen DomU guests." | ||
| 39 | |||
| 40 | # Source blobs from vdkr (Docker) build - same rootfs works under Xen | ||
| 41 | VXN_RUNTIME = "vdkr" | ||
| 42 | |||
| 43 | require vxn-initramfs-create.inc | ||
diff --git a/recipes-core/vxn/vxn_1.0.bb b/recipes-core/vxn/vxn_1.0.bb new file mode 100644 index 00000000..2a36274a --- /dev/null +++ b/recipes-core/vxn/vxn_1.0.bb | |||
| @@ -0,0 +1,167 @@ | |||
| 1 | # SPDX-FileCopyrightText: Copyright (C) 2025 Bruce Ashfield | ||
| 2 | # | ||
| 3 | # SPDX-License-Identifier: MIT | ||
| 4 | # | ||
| 5 | # vxn_1.0.bb | ||
| 6 | # =========================================================================== | ||
| 7 | # Target integration package for vxn (vcontainer on Xen) | ||
| 8 | # =========================================================================== | ||
| 9 | # | ||
| 10 | # This recipe installs vxn onto a Xen Dom0 target. It provides: | ||
| 11 | # - vxn CLI wrapper (docker-like interface for Xen DomU containers) | ||
| 12 | # - vrunner.sh (hypervisor-agnostic VM runner) | ||
| 13 | # - vrunner-backend-xen.sh (Xen xl backend) | ||
| 14 | # - vcontainer-common.sh (shared CLI code) | ||
| 15 | # - Kernel, initramfs, and rootfs blobs for booting DomU guests | ||
| 16 | # | ||
| 17 | # The blobs are sourced from the vxn-initramfs-create recipe which | ||
| 18 | # reuses the same rootfs images built by vdkr/vpdmn (the init scripts | ||
| 19 | # detect the hypervisor at boot time). | ||
| 20 | # | ||
| 21 | # =========================================================================== | ||
| 22 | # BUILD INSTRUCTIONS | ||
| 23 | # =========================================================================== | ||
| 24 | # | ||
| 25 | # For aarch64 Dom0: | ||
| 26 | # MACHINE=qemuarm64 bitbake vxn | ||
| 27 | # | ||
| 28 | # For x86_64 Dom0: | ||
| 29 | # MACHINE=qemux86-64 bitbake vxn | ||
| 30 | # | ||
| 31 | # Add to a Dom0 image: | ||
| 32 | # IMAGE_INSTALL:append = " vxn" | ||
| 33 | # | ||
| 34 | # Usage on Dom0: | ||
| 35 | # vxn run hello-world # Run OCI container as Xen DomU | ||
| 36 | # vxn vmemres start # Start persistent DomU (daemon mode) | ||
| 37 | # vxn vexpose # Expose Docker API on Dom0 | ||
| 38 | # | ||
| 39 | # =========================================================================== | ||
| 40 | |||
| 41 | SUMMARY = "Docker CLI for Xen-based container execution" | ||
| 42 | DESCRIPTION = "vxn provides a familiar docker-like CLI that executes commands \ | ||
| 43 | inside a Xen DomU guest with Docker. It uses the vcontainer \ | ||
| 44 | infrastructure with a Xen hypervisor backend." | ||
| 45 | HOMEPAGE = "https://git.yoctoproject.org/meta-virtualization/" | ||
| 46 | LICENSE = "MIT" | ||
| 47 | LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302" | ||
| 48 | |||
| 49 | inherit features_check | ||
| 50 | REQUIRED_DISTRO_FEATURES = "xen" | ||
| 51 | |||
| 52 | SRC_URI = "\ | ||
| 53 | file://vxn.sh \ | ||
| 54 | file://vrunner.sh \ | ||
| 55 | file://vrunner-backend-xen.sh \ | ||
| 56 | file://vrunner-backend-qemu.sh \ | ||
| 57 | file://vcontainer-common.sh \ | ||
| 58 | " | ||
| 59 | |||
| 60 | FILESEXTRAPATHS:prepend := "${THISDIR}/../../recipes-containers/vcontainer/files:" | ||
| 61 | |||
| 62 | S = "${UNPACKDIR}" | ||
| 63 | |||
| 64 | # Runtime dependencies on Dom0 | ||
| 65 | RDEPENDS:${PN} = "\ | ||
| 66 | xen-tools-xl \ | ||
| 67 | bash \ | ||
| 68 | jq \ | ||
| 69 | socat \ | ||
| 70 | coreutils \ | ||
| 71 | util-linux \ | ||
| 72 | e2fsprogs \ | ||
| 73 | skopeo \ | ||
| 74 | " | ||
| 75 | |||
| 76 | # Blobs are sourced from vxn-initramfs-create deploy output. | ||
| 77 | # Build blobs first: bitbake vxn-initramfs-create | ||
| 78 | # No task dependency here - vxn-initramfs-create is deploy-only (no packages). | ||
| 79 | # Adding any dependency from a packaged recipe to a deploy-only recipe | ||
| 80 | # breaks do_rootfs (sstate manifest not found for package_write_rpm). | ||
| 81 | |||
| 82 | # Blobs come from DEPLOY_DIR which is untracked by sstate hash. | ||
| 83 | # nostamp on do_install alone is insufficient — do_package and | ||
| 84 | # do_package_write_rpm have unchanged sstate hashes so they restore | ||
| 85 | # the OLD RPM from cache, discarding the fresh do_install output. | ||
| 86 | # Force the entire install→package→RPM chain to always re-run. | ||
| 87 | do_install[nostamp] = "1" | ||
| 88 | do_package[nostamp] = "1" | ||
| 89 | do_packagedata[nostamp] = "1" | ||
| 90 | do_package_write_rpm[nostamp] = "1" | ||
| 91 | do_package_write_ipk[nostamp] = "1" | ||
| 92 | do_package_write_deb[nostamp] = "1" | ||
| 93 | |||
| 94 | def vxn_get_blob_arch(d): | ||
| 95 | arch = d.getVar('TARGET_ARCH') | ||
| 96 | if arch == 'aarch64': | ||
| 97 | return 'aarch64' | ||
| 98 | elif arch in ['x86_64', 'i686', 'i586']: | ||
| 99 | return 'x86_64' | ||
| 100 | return 'aarch64' | ||
| 101 | |||
| 102 | def vxn_get_kernel_image_name(d): | ||
| 103 | arch = d.getVar('TARGET_ARCH') | ||
| 104 | if arch == 'aarch64': | ||
| 105 | return 'Image' | ||
| 106 | elif arch in ['x86_64', 'i686', 'i586']: | ||
| 107 | return 'bzImage' | ||
| 108 | elif arch == 'arm': | ||
| 109 | return 'zImage' | ||
| 110 | return 'Image' | ||
| 111 | |||
| 112 | BLOB_ARCH = "${@vxn_get_blob_arch(d)}" | ||
| 113 | KERNEL_IMAGETYPE_VXN = "${@vxn_get_kernel_image_name(d)}" | ||
| 114 | |||
| 115 | VXN_DEPLOY = "${DEPLOY_DIR_IMAGE}" | ||
| 116 | |||
| 117 | do_install() { | ||
| 118 | # Install CLI wrapper | ||
| 119 | install -d ${D}${bindir} | ||
| 120 | install -m 0755 ${S}/vxn.sh ${D}${bindir}/vxn | ||
| 121 | |||
| 122 | # Install shared scripts into libdir | ||
| 123 | install -d ${D}${libdir}/vxn | ||
| 124 | install -m 0755 ${S}/vrunner.sh ${D}${libdir}/vxn/ | ||
| 125 | install -m 0755 ${S}/vrunner-backend-xen.sh ${D}${libdir}/vxn/ | ||
| 126 | install -m 0755 ${S}/vrunner-backend-qemu.sh ${D}${libdir}/vxn/ | ||
| 127 | install -m 0644 ${S}/vcontainer-common.sh ${D}${libdir}/vxn/ | ||
| 128 | |||
| 129 | # Install blobs from vxn-initramfs-create deployment | ||
| 130 | # Layout must match what vrunner backends expect: $BLOB_DIR/<arch>/{Image,initramfs.cpio.gz,rootfs.img} | ||
| 131 | install -d ${D}${datadir}/vxn/${BLOB_ARCH} | ||
| 132 | |||
| 133 | VXN_BLOB_SRC="${VXN_DEPLOY}/vxn/${BLOB_ARCH}" | ||
| 134 | if [ -d "${VXN_BLOB_SRC}" ]; then | ||
| 135 | if [ -f "${VXN_BLOB_SRC}/${KERNEL_IMAGETYPE_VXN}" ]; then | ||
| 136 | install -m 0644 "${VXN_BLOB_SRC}/${KERNEL_IMAGETYPE_VXN}" ${D}${datadir}/vxn/${BLOB_ARCH}/ | ||
| 137 | bbnote "Installed kernel ${KERNEL_IMAGETYPE_VXN}" | ||
| 138 | else | ||
| 139 | bbwarn "Kernel not found at ${VXN_BLOB_SRC}/${KERNEL_IMAGETYPE_VXN}" | ||
| 140 | fi | ||
| 141 | |||
| 142 | if [ -f "${VXN_BLOB_SRC}/initramfs.cpio.gz" ]; then | ||
| 143 | install -m 0644 "${VXN_BLOB_SRC}/initramfs.cpio.gz" ${D}${datadir}/vxn/${BLOB_ARCH}/ | ||
| 144 | bbnote "Installed initramfs" | ||
| 145 | else | ||
| 146 | bbwarn "Initramfs not found at ${VXN_BLOB_SRC}/initramfs.cpio.gz" | ||
| 147 | fi | ||
| 148 | |||
| 149 | if [ -f "${VXN_BLOB_SRC}/rootfs.img" ]; then | ||
| 150 | install -m 0644 "${VXN_BLOB_SRC}/rootfs.img" ${D}${datadir}/vxn/${BLOB_ARCH}/ | ||
| 151 | bbnote "Installed rootfs.img" | ||
| 152 | else | ||
| 153 | bbwarn "Rootfs not found at ${VXN_BLOB_SRC}/rootfs.img" | ||
| 154 | fi | ||
| 155 | else | ||
| 156 | bbwarn "VXN blob directory not found at ${VXN_BLOB_SRC}. Build with: bitbake vxn-initramfs-create" | ||
| 157 | fi | ||
| 158 | } | ||
| 159 | |||
| 160 | FILES:${PN} = "\ | ||
| 161 | ${bindir}/vxn \ | ||
| 162 | ${libdir}/vxn/ \ | ||
| 163 | ${datadir}/vxn/ \ | ||
| 164 | " | ||
| 165 | |||
| 166 | # Blobs are large binary files | ||
| 167 | INSANE_SKIP:${PN} += "already-stripped" | ||
