summaryrefslogtreecommitdiffstats
path: root/recipes-core
diff options
context:
space:
mode:
authorBruce Ashfield <bruce.ashfield@gmail.com>2026-02-18 14:07:49 +0000
committerBruce Ashfield <bruce.ashfield@gmail.com>2026-02-26 01:05:01 +0000
commit9377aede3157a3e7b702dc389c15f27523b673e7 (patch)
tree9ea01493815cfb58e642b65b5b31472235b5a09a /recipes-core
parentfa4b171a436559787cfcebd4046a1354a1f5cacf (diff)
downloadmeta-virtualization-9377aede3157a3e7b702dc389c15f27523b673e7.tar.gz
vxn: add containerd OCI runtime integration
Add shell-based OCI runtime (vxn-oci-runtime) that enables containerd to manage Xen DomU containers through the standard runc shim. Non-terminal container output flows back to ctr via the shim's pipe mechanism. New files: - vxn-oci-runtime: OCI runtime (create/start/state/kill/delete/features/logs) - vxn-sendtty.c: SCM_RIGHTS helper for terminal mode PTY passing - containerd-shim-vxn-v2: PATH trick wrapper for runc shim coexistence - containerd-config-vxn.toml: CRI config (vxn default, runc fallback) - vctr: convenience wrapper injecting --runtime io.containerd.vxn.v2 Key design: - Monitor subprocess uses wait on xl console (not sleep-polling) for instant reaction when domain dies, then extracts output markers and writes to stdout (shim pipe -> containerd FIFO -> ctr client) - cmd_state checks monitor PID liveness (not domain status) to prevent premature cleanup race that killed monitor before output - cmd_delete always destroys remnant domains (no --force needed) - Coexists with runc: /usr/libexec/vxn/shim/runc symlink + PATH trick Verified: vctr run --rm, vctr run -d, vxn standalone, vxn daemon mode. Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
Diffstat (limited to 'recipes-core')
-rw-r--r--recipes-core/vxn/vxn_1.0.bb196
1 files changed, 149 insertions, 47 deletions
diff --git a/recipes-core/vxn/vxn_1.0.bb b/recipes-core/vxn/vxn_1.0.bb
index 2a36274a..d16cbc77 100644
--- a/recipes-core/vxn/vxn_1.0.bb
+++ b/recipes-core/vxn/vxn_1.0.bb
@@ -14,9 +14,13 @@
14# - vcontainer-common.sh (shared CLI code) 14# - vcontainer-common.sh (shared CLI code)
15# - Kernel, initramfs, and rootfs blobs for booting DomU guests 15# - Kernel, initramfs, and rootfs blobs for booting DomU guests
16# 16#
17# The blobs are sourced from the vxn-initramfs-create recipe which 17# Blobs are sourced directly from the vruntime multiconfig deploy
18# reuses the same rootfs images built by vdkr/vpdmn (the init scripts 18# directory. The rootfs squashfs is unsquashed, vxn init scripts are
19# detect the hypervisor at boot time). 19# injected, and it is re-squashed — all within do_compile. This keeps
20# the entire dependency chain in one recipe so that SRC_URI hash
21# tracking and mcdepends work correctly without relying on a separate
22# deploy-only recipe (which cannot be task-depended on from a packaged
23# recipe without breaking image do_rootfs sstate manifest checks).
20# 24#
21# =========================================================================== 25# ===========================================================================
22# BUILD INSTRUCTIONS 26# BUILD INSTRUCTIONS
@@ -49,21 +53,31 @@ LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda
49inherit features_check 53inherit features_check
50REQUIRED_DISTRO_FEATURES = "xen" 54REQUIRED_DISTRO_FEATURES = "xen"
51 55
56# Host scripts + guest init scripts (all from the vcontainer files dir)
52SRC_URI = "\ 57SRC_URI = "\
53 file://vxn.sh \ 58 file://vxn.sh \
54 file://vrunner.sh \ 59 file://vrunner.sh \
55 file://vrunner-backend-xen.sh \ 60 file://vrunner-backend-xen.sh \
56 file://vrunner-backend-qemu.sh \ 61 file://vrunner-backend-qemu.sh \
57 file://vcontainer-common.sh \ 62 file://vcontainer-common.sh \
63 file://vxn-init.sh \
64 file://vcontainer-init-common.sh \
65 file://vxn-oci-runtime \
66 file://vxn-sendtty.c \
67 file://containerd-config-vxn.toml \
68 file://containerd-shim-vxn-v2 \
69 file://vctr \
58" 70"
59 71
60FILESEXTRAPATHS:prepend := "${THISDIR}/../../recipes-containers/vcontainer/files:" 72FILESEXTRAPATHS:prepend := "${THISDIR}/../../recipes-containers/vcontainer/files:"
61 73
62S = "${UNPACKDIR}" 74S = "${UNPACKDIR}"
75B = "${WORKDIR}/build"
63 76
64# Runtime dependencies on Dom0 77# Runtime dependencies on Dom0
65RDEPENDS:${PN} = "\ 78RDEPENDS:${PN} = "\
66 xen-tools-xl \ 79 xen-tools-xl \
80 xen-tools-xenstore \
67 bash \ 81 bash \
68 jq \ 82 jq \
69 socat \ 83 socat \
@@ -73,23 +87,12 @@ RDEPENDS:${PN} = "\
73 skopeo \ 87 skopeo \
74" 88"
75 89
76# Blobs are sourced from vxn-initramfs-create deploy output. 90# squashfs-tools-native for unsquash/resquash of rootfs.img
77# Build blobs first: bitbake vxn-initramfs-create 91DEPENDS += "squashfs-tools-native"
78# No task dependency here - vxn-initramfs-create is deploy-only (no packages). 92
79# Adding any dependency from a packaged recipe to a deploy-only recipe 93# ===========================================================================
80# breaks do_rootfs (sstate manifest not found for package_write_rpm). 94# Architecture and multiconfig helpers
81 95# ===========================================================================
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.
87do_install[nostamp] = "1"
88do_package[nostamp] = "1"
89do_packagedata[nostamp] = "1"
90do_package_write_rpm[nostamp] = "1"
91do_package_write_ipk[nostamp] = "1"
92do_package_write_deb[nostamp] = "1"
93 96
94def vxn_get_blob_arch(d): 97def vxn_get_blob_arch(d):
95 arch = d.getVar('TARGET_ARCH') 98 arch = d.getVar('TARGET_ARCH')
@@ -109,15 +112,114 @@ def vxn_get_kernel_image_name(d):
109 return 'zImage' 112 return 'zImage'
110 return 'Image' 113 return 'Image'
111 114
115def vxn_get_multiconfig_name(d):
116 arch = d.getVar('TARGET_ARCH')
117 if arch == 'aarch64':
118 return 'vruntime-aarch64'
119 elif arch in ['x86_64', 'i686', 'i586']:
120 return 'vruntime-x86-64'
121 return 'vruntime-aarch64'
122
112BLOB_ARCH = "${@vxn_get_blob_arch(d)}" 123BLOB_ARCH = "${@vxn_get_blob_arch(d)}"
113KERNEL_IMAGETYPE_VXN = "${@vxn_get_kernel_image_name(d)}" 124KERNEL_IMAGETYPE_VXN = "${@vxn_get_kernel_image_name(d)}"
125VXN_MULTICONFIG = "${@vxn_get_multiconfig_name(d)}"
126VXN_RUNTIME = "vdkr"
127
128# Multiconfig deploy directory (where vdkr-rootfs-image deploys blobs)
129VXN_MC_DEPLOY = "${TOPDIR}/tmp-${VXN_MULTICONFIG}/deploy/images/${MACHINE}"
130
131# ===========================================================================
132# Multiconfig dependencies — ensures blobs are built before do_compile.
133# mcdepends are cross-config and don't pollute the same-config package
134# dependency tree, so they don't break image do_rootfs sstate checks.
135# ===========================================================================
136
137python () {
138 mc = d.getVar('VXN_MULTICONFIG')
139 runtime = d.getVar('VXN_RUNTIME')
140 bbmulticonfig = (d.getVar('BBMULTICONFIG') or "").split()
141 if mc in bbmulticonfig:
142 mcdeps = ' '.join([
143 'mc::%s:%s-tiny-initramfs-image:do_image_complete' % (mc, runtime),
144 'mc::%s:%s-rootfs-image:do_image_complete' % (mc, runtime),
145 'mc::%s:virtual/kernel:do_deploy' % mc,
146 ])
147 d.setVarFlag('do_compile', 'mcdepends', mcdeps)
148}
149
150# ===========================================================================
151# do_compile: source blobs from MC deploy, inject init scripts into rootfs
152# ===========================================================================
153# SRC_URI includes vxn-init.sh and vcontainer-init-common.sh, so their
154# content hashes are part of the task signature. When they change, this
155# task re-runs and produces a fresh rootfs.img with the updated scripts.
156
157do_compile() {
158 mkdir -p ${B}
159
160 # Compile vxn-sendtty (SCM_RIGHTS helper for OCI terminal mode)
161 ${CC} ${CFLAGS} ${S}/vxn-sendtty.c ${LDFLAGS} -o ${B}/vxn-sendtty
162
163 MC_DEPLOY="${VXN_MC_DEPLOY}"
164
165 # --- Initramfs ---
166 INITRAMFS_SRC="${MC_DEPLOY}/${VXN_RUNTIME}-tiny-initramfs-image-${MACHINE}.cpio.gz"
167 if [ ! -f "${INITRAMFS_SRC}" ]; then
168 bbfatal "Initramfs not found at ${INITRAMFS_SRC}. Build with: bitbake mc:${VXN_MULTICONFIG}:${VXN_RUNTIME}-tiny-initramfs-image"
169 fi
170 cp "${INITRAMFS_SRC}" ${B}/initramfs.cpio.gz
114 171
115VXN_DEPLOY = "${DEPLOY_DIR_IMAGE}" 172 # --- Rootfs (unsquash, inject scripts, resquash) ---
173 ROOTFS_SRC="${MC_DEPLOY}/${VXN_RUNTIME}-rootfs-image-${MACHINE}.rootfs.squashfs"
174 if [ ! -f "${ROOTFS_SRC}" ]; then
175 bbfatal "Rootfs not found at ${ROOTFS_SRC}. Build with: bitbake mc:${VXN_MULTICONFIG}:${VXN_RUNTIME}-rootfs-image"
176 fi
177
178 UNSQUASH_DIR="${B}/rootfs-unsquash"
179 rm -rf "${UNSQUASH_DIR}"
180 unsquashfs -d "${UNSQUASH_DIR}" "${ROOTFS_SRC}"
181
182 # Inject vxn init scripts (tracked via SRC_URI → task hash changes on edit)
183 install -m 0755 ${S}/vxn-init.sh ${UNSQUASH_DIR}/vxn-init.sh
184 install -m 0755 ${S}/vcontainer-init-common.sh ${UNSQUASH_DIR}/vcontainer-init-common.sh
185
186 rm -f ${B}/rootfs.img
187 mksquashfs "${UNSQUASH_DIR}" ${B}/rootfs.img -noappend -comp xz
188 rm -rf "${UNSQUASH_DIR}"
189
190 # --- Kernel ---
191 KERNEL_FILE="${DEPLOY_DIR_IMAGE}/${KERNEL_IMAGETYPE_VXN}"
192 if [ -f "${KERNEL_FILE}" ]; then
193 cp "${KERNEL_FILE}" ${B}/kernel
194 else
195 bbwarn "Kernel not found at ${KERNEL_FILE}"
196 fi
197}
198
199# ===========================================================================
200# do_install: install CLI scripts (from SRC_URI) and blobs (from do_compile)
201# ===========================================================================
116 202
117do_install() { 203do_install() {
118 # Install CLI wrapper 204 # Install CLI wrapper, OCI runtime, and sendtty helper
119 install -d ${D}${bindir} 205 install -d ${D}${bindir}
120 install -m 0755 ${S}/vxn.sh ${D}${bindir}/vxn 206 install -m 0755 ${S}/vxn.sh ${D}${bindir}/vxn
207 install -m 0755 ${S}/vxn-oci-runtime ${D}${bindir}/vxn-oci-runtime
208 install -m 0755 ${B}/vxn-sendtty ${D}${bindir}/vxn-sendtty
209
210 # Install containerd config (makes vxn-oci-runtime the default CRI runtime)
211 install -d ${D}${sysconfdir}/containerd
212 install -m 0644 ${S}/containerd-config-vxn.toml ${D}${sysconfdir}/containerd/config.toml
213
214 # Install vxn shim wrapper: PATH trick makes runc shim find vxn-oci-runtime
215 install -m 0755 ${S}/containerd-shim-vxn-v2 ${D}${bindir}/containerd-shim-vxn-v2
216
217 # Private shim dir: runc symlink so the runc shim execs vxn-oci-runtime
218 install -d ${D}${libexecdir}/vxn/shim
219 ln -sf ${bindir}/vxn-oci-runtime ${D}${libexecdir}/vxn/shim/runc
220
221 # Install vctr convenience wrapper
222 install -m 0755 ${S}/vctr ${D}${bindir}/vctr
121 223
122 # Install shared scripts into libdir 224 # Install shared scripts into libdir
123 install -d ${D}${libdir}/vxn 225 install -d ${D}${libdir}/vxn
@@ -126,39 +228,39 @@ do_install() {
126 install -m 0755 ${S}/vrunner-backend-qemu.sh ${D}${libdir}/vxn/ 228 install -m 0755 ${S}/vrunner-backend-qemu.sh ${D}${libdir}/vxn/
127 install -m 0644 ${S}/vcontainer-common.sh ${D}${libdir}/vxn/ 229 install -m 0644 ${S}/vcontainer-common.sh ${D}${libdir}/vxn/
128 230
129 # Install blobs from vxn-initramfs-create deployment 231 # Install blobs from do_compile output
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} 232 install -d ${D}${datadir}/vxn/${BLOB_ARCH}
132 233
133 VXN_BLOB_SRC="${VXN_DEPLOY}/vxn/${BLOB_ARCH}" 234 if [ -f "${B}/kernel" ]; then
134 if [ -d "${VXN_BLOB_SRC}" ]; then 235 install -m 0644 "${B}/kernel" ${D}${datadir}/vxn/${BLOB_ARCH}/${KERNEL_IMAGETYPE_VXN}
135 if [ -f "${VXN_BLOB_SRC}/${KERNEL_IMAGETYPE_VXN}" ]; then 236 bbnote "Installed kernel ${KERNEL_IMAGETYPE_VXN}"
136 install -m 0644 "${VXN_BLOB_SRC}/${KERNEL_IMAGETYPE_VXN}" ${D}${datadir}/vxn/${BLOB_ARCH}/ 237 else
137 bbnote "Installed kernel ${KERNEL_IMAGETYPE_VXN}" 238 bbwarn "Kernel blob not found in build dir"
138 else 239 fi
139 bbwarn "Kernel not found at ${VXN_BLOB_SRC}/${KERNEL_IMAGETYPE_VXN}" 240
140 fi 241 if [ -f "${B}/initramfs.cpio.gz" ]; then
141 242 install -m 0644 "${B}/initramfs.cpio.gz" ${D}${datadir}/vxn/${BLOB_ARCH}/
142 if [ -f "${VXN_BLOB_SRC}/initramfs.cpio.gz" ]; then 243 bbnote "Installed initramfs"
143 install -m 0644 "${VXN_BLOB_SRC}/initramfs.cpio.gz" ${D}${datadir}/vxn/${BLOB_ARCH}/ 244 else
144 bbnote "Installed initramfs" 245 bbwarn "Initramfs blob not found in build dir"
145 else 246 fi
146 bbwarn "Initramfs not found at ${VXN_BLOB_SRC}/initramfs.cpio.gz" 247
147 fi 248 if [ -f "${B}/rootfs.img" ]; then
148 249 install -m 0644 "${B}/rootfs.img" ${D}${datadir}/vxn/${BLOB_ARCH}/
149 if [ -f "${VXN_BLOB_SRC}/rootfs.img" ]; then 250 bbnote "Installed rootfs.img"
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 251 else
156 bbwarn "VXN blob directory not found at ${VXN_BLOB_SRC}. Build with: bitbake vxn-initramfs-create" 252 bbwarn "Rootfs blob not found in build dir"
157 fi 253 fi
158} 254}
159 255
160FILES:${PN} = "\ 256FILES:${PN} = "\
161 ${bindir}/vxn \ 257 ${bindir}/vxn \
258 ${bindir}/vxn-oci-runtime \
259 ${bindir}/vxn-sendtty \
260 ${bindir}/containerd-shim-vxn-v2 \
261 ${bindir}/vctr \
262 ${libexecdir}/vxn/ \
263 ${sysconfdir}/containerd/config.toml \
162 ${libdir}/vxn/ \ 264 ${libdir}/vxn/ \
163 ${datadir}/vxn/ \ 265 ${datadir}/vxn/ \
164" 266"