summaryrefslogtreecommitdiffstats
path: root/recipes-core/vxn
diff options
context:
space:
mode:
authorBruce Ashfield <bruce.ashfield@gmail.com>2026-02-19 01:53:36 +0000
committerBruce Ashfield <bruce.ashfield@gmail.com>2026-02-26 01:05:01 +0000
commit035e0daebeb53880ea2a6bd0f0e31785f3ec9e55 (patch)
tree1ae711e61d79ad2f7b0afba6fc4489f61d1a6202 /recipes-core/vxn
parentbf5abfe3d55604c6b22416cc23cbfaba1ff7bee2 (diff)
downloadmeta-virtualization-035e0daebeb53880ea2a6bd0f0e31785f3ec9e55.tar.gz
vxn: add Docker/Podman integration and CLI frontends
Add vdkr/vpdmn as Dom0 target packages with Xen auto-detection, native Docker/Podman config sub-packages, and OCI runtime fixes for Docker compatibility (JSON logging, root.path, kill --all, monitor PID lifecycle). Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
Diffstat (limited to 'recipes-core/vxn')
-rw-r--r--recipes-core/vxn/README.md159
-rw-r--r--recipes-core/vxn/vxn_1.0.bb36
2 files changed, 195 insertions, 0 deletions
diff --git a/recipes-core/vxn/README.md b/recipes-core/vxn/README.md
new file mode 100644
index 00000000..35802e31
--- /dev/null
+++ b/recipes-core/vxn/README.md
@@ -0,0 +1,159 @@
1# vxn — Docker CLI for Xen DomU Containers
2
3vxn runs OCI containers as Xen DomU guests. The VM IS the container — no
4Docker/Podman daemon runs inside the guest. The guest boots a minimal Linux,
5mounts the container's filesystem, and directly executes the entrypoint.
6
7## Packages
8
9| Package | Contents | Usage |
10|---------|----------|-------|
11| `vxn` | CLI, OCI runtime, blobs, containerd config | Base package (required) |
12| `vxn-vdkr` | `vdkr` — Docker-like CLI frontend | `IMAGE_INSTALL:append = " vxn-vdkr"` |
13| `vxn-vpdmn` | `vpdmn` — Podman-like CLI frontend | `IMAGE_INSTALL:append = " vxn-vpdmn"` |
14| `vxn-docker-config` | `/etc/docker/daemon.json` (vxn as default runtime) | `IMAGE_INSTALL:append = " vxn-docker-config"` |
15| `vxn-podman-config` | `/etc/containers/containers.conf.d/50-vxn-runtime.conf` | `IMAGE_INSTALL:append = " vxn-podman-config"` |
16
17## Execution Paths
18
19### 1. containerd (vctr/ctr) — recommended
20
21No additional packages needed beyond `vxn`. containerd is configured
22automatically via `/etc/containerd/config.toml`.
23
24```bash
25ctr image pull docker.io/library/alpine:latest
26vctr run --rm docker.io/library/alpine:latest test1 /bin/echo hello
27ctr run -t --rm --runtime io.containerd.vxn.v2 docker.io/library/alpine:latest tty1 /bin/sh
28```
29
30### 2. vdkr/vpdmn (Docker/Podman-like CLI, no daemon)
31
32Install `vxn-vdkr` or `vxn-vpdmn`. These are standalone frontends that
33auto-detect Xen (via `xl`) and manage containers without any daemon process.
34They handle OCI image pull/unpack on the host via skopeo.
35
36```bash
37vdkr run --rm alpine echo hello # Docker-like
38vpdmn run --rm alpine echo hello # Podman-like
39```
40
41Persistent DomU (memres) for faster subsequent runs:
42```bash
43vdkr vmemres start # Boot persistent DomU (~10s)
44vdkr run --rm alpine echo hello # Hot-plug container (~1s)
45vdkr vmemres stop # Shutdown DomU
46```
47
48### 3. Native Docker with vxn runtime
49
50Install `vxn-docker-config` to register vxn-oci-runtime as Docker's default
51OCI runtime. Docker manages images (pull/tag/rmi) natively.
52
53```bash
54docker run --rm --network=none alpine echo hello
55docker run --rm --network=host alpine echo hello
56```
57
58**IMPORTANT: Networking** — Docker's default bridge networking is incompatible
59with VM-based runtimes. Docker tries to create veth pairs and move them into
60a Linux network namespace, but vxn containers are Xen DomUs with their own
61kernel network stack. You MUST use `--network=none` or `--network=host`.
62
63This is the same limitation as kata-containers. The long-term fix is a TAP
64bridge that connects Docker's network namespace to the DomU's vif (see TODO).
65
66For selective use (keep runc as default, use vxn per-run):
67```bash
68docker run --rm --runtime=vxn --network=none alpine echo hello
69```
70
71### 4. Native Podman with vxn runtime
72
73Install `vxn-podman-config` to register vxn-oci-runtime as Podman's default
74OCI runtime. Same networking constraints as Docker.
75
76```bash
77podman run --rm --network=none alpine echo hello
78```
79
80## Build Instructions
81
82```bash
83# Prerequisites in local.conf:
84DISTRO_FEATURES:append = " xen virtualization vcontainer"
85BBMULTICONFIG = "vruntime-aarch64 vruntime-x86-64"
86
87# Build (mcdepends auto-builds vruntime blobs)
88bitbake vxn
89
90# Dom0 image with containerd + Docker-like CLI
91IMAGE_INSTALL:append = " vxn vxn-vdkr"
92
93# Dom0 image with native Docker integration
94IMAGE_INSTALL:append = " vxn vxn-docker-config docker"
95
96bitbake xen-image-minimal
97```
98
99## Architecture
100
101```
102Docker/Podman/containerd → vxn-oci-runtime → xl create/unpause/destroy → Xen DomU
103
104 vxn-init.sh
105 mount rootfs
106 chroot + exec
107```
108
109The OCI runtime (`/usr/bin/vxn-oci-runtime`) implements the standard
110create/start/state/kill/delete lifecycle by mapping to xl commands:
111
112| OCI Command | xl Equivalent |
113|-------------|---------------|
114| create | xl create -p (paused) |
115| start | xl unpause |
116| state | xl list + monitor PID check |
117| kill SIGTERM | xl shutdown (10s grace) + xl destroy |
118| kill SIGKILL | xl destroy |
119| delete | xl destroy + cleanup state |
120
121## Networking Constraints (Native Docker/Podman)
122
123Docker and Podman's default bridge networking creates Linux veth pairs and
124moves one end into a container network namespace. This is fundamentally
125incompatible with VM-based runtimes where the "container" is a VM with its
126own kernel networking.
127
128**Current workarounds:**
129- `--network=none` — DomU uses its own xenbr0 networking
130- `--network=host` — Tells Docker/Podman to skip namespace setup
131
132**Future fix (TODO):**
133TAP bridge integration — read Docker's network namespace config from
134config.json, create a TAP device bridged to the DomU's vif. This is the
135approach kata-containers uses to provide Docker-compatible networking with
136VM isolation.
137
138**Not affected:**
139- `vctr`/`ctr` (containerd) — CNI is separate and opt-in
140- `vdkr`/`vpdmn` — Handle networking independently via xenbr0
141
142## Debugging
143
144```bash
145# OCI runtime log (all invocations)
146cat /var/log/vxn-oci-runtime.log
147
148# Per-container console capture (persists after container exit)
149ls /var/log/vxn-oci-runtime/containers/
150
151# Xen domain status
152xl list
153
154# Watch domain console
155xl console <domname>
156
157# Kill stuck domain
158xl destroy <domname>
159```
diff --git a/recipes-core/vxn/vxn_1.0.bb b/recipes-core/vxn/vxn_1.0.bb
index d16cbc77..a08dac09 100644
--- a/recipes-core/vxn/vxn_1.0.bb
+++ b/recipes-core/vxn/vxn_1.0.bb
@@ -67,6 +67,8 @@ SRC_URI = "\
67 file://containerd-config-vxn.toml \ 67 file://containerd-config-vxn.toml \
68 file://containerd-shim-vxn-v2 \ 68 file://containerd-shim-vxn-v2 \
69 file://vctr \ 69 file://vctr \
70 file://vdkr.sh \
71 file://vpdmn.sh \
70" 72"
71 73
72FILESEXTRAPATHS:prepend := "${THISDIR}/../../recipes-containers/vcontainer/files:" 74FILESEXTRAPATHS:prepend := "${THISDIR}/../../recipes-containers/vcontainer/files:"
@@ -221,6 +223,24 @@ do_install() {
221 # Install vctr convenience wrapper 223 # Install vctr convenience wrapper
222 install -m 0755 ${S}/vctr ${D}${bindir}/vctr 224 install -m 0755 ${S}/vctr ${D}${bindir}/vctr
223 225
226 # Docker/Podman CLI frontends (sub-packages)
227 install -m 0755 ${S}/vdkr.sh ${D}${bindir}/vdkr
228 install -m 0755 ${S}/vpdmn.sh ${D}${bindir}/vpdmn
229
230 # Docker daemon config: register vxn-oci-runtime (vxn-docker-config sub-package)
231 # no-new-privileges=false is needed because vxn ignores Linux security features.
232 # Users must use --network=none or --network=host with vxn containers since
233 # Xen DomUs have their own kernel network stack and Docker's veth/namespace
234 # setup is incompatible with VM-based runtimes.
235 install -d ${D}${sysconfdir}/docker
236 printf '{\n "runtimes": {\n "vxn": {\n "path": "/usr/bin/vxn-oci-runtime"\n }\n },\n "default-runtime": "vxn"\n}\n' \
237 > ${D}${sysconfdir}/docker/daemon.json
238
239 # Podman config: register vxn-oci-runtime (vxn-podman-config sub-package)
240 install -d ${D}${sysconfdir}/containers/containers.conf.d
241 printf '[engine]\nruntime = "vxn"\n\n[engine.runtimes]\nvxn = ["/usr/bin/vxn-oci-runtime"]\n' \
242 > ${D}${sysconfdir}/containers/containers.conf.d/50-vxn-runtime.conf
243
224 # Install shared scripts into libdir 244 # Install shared scripts into libdir
225 install -d ${D}${libdir}/vxn 245 install -d ${D}${libdir}/vxn
226 install -m 0755 ${S}/vrunner.sh ${D}${libdir}/vxn/ 246 install -m 0755 ${S}/vrunner.sh ${D}${libdir}/vxn/
@@ -253,6 +273,22 @@ do_install() {
253 fi 273 fi
254} 274}
255 275
276# Sub-packages for CLI frontends and native runtime config
277PACKAGES =+ "${PN}-vdkr ${PN}-vpdmn ${PN}-docker-config ${PN}-podman-config"
278
279FILES:${PN}-vdkr = "${bindir}/vdkr"
280FILES:${PN}-vpdmn = "${bindir}/vpdmn"
281FILES:${PN}-docker-config = "${sysconfdir}/docker/daemon.json"
282FILES:${PN}-podman-config = "${sysconfdir}/containers/containers.conf.d/50-vxn-runtime.conf"
283
284RDEPENDS:${PN}-vdkr = "${PN} bash"
285RDEPENDS:${PN}-vpdmn = "${PN} bash"
286RDEPENDS:${PN}-docker-config = "${PN} docker"
287RDEPENDS:${PN}-podman-config = "${PN} podman"
288
289# daemon.json conflicts with docker-registry-config (only one provider)
290RCONFLICTS:${PN}-docker-config = "docker-registry-config"
291
256FILES:${PN} = "\ 292FILES:${PN} = "\
257 ${bindir}/vxn \ 293 ${bindir}/vxn \
258 ${bindir}/vxn-oci-runtime \ 294 ${bindir}/vxn-oci-runtime \