summaryrefslogtreecommitdiffstats
path: root/recipes-containers/vcontainer/files
diff options
context:
space:
mode:
authorBruce Ashfield <bruce.ashfield@gmail.com>2026-01-06 20:45:13 +0000
committerBruce Ashfield <bruce.ashfield@gmail.com>2026-01-21 18:00:26 -0500
commitf17830e62d531ad411a05e214270c5fc4939799f (patch)
treefd65fe626abb745ce1d81d281e4bd8f4d9f4a082 /recipes-containers/vcontainer/files
parent6ee20538e226d3696c73206c048f826b9aa92734 (diff)
downloadmeta-virtualization-f17830e62d531ad411a05e214270c5fc4939799f.tar.gz
vcontainer: add vpdmn Podman support
Add vpdmn - Podman CLI wrapper for cross-architecture container operations: Scripts: - vpdmn.sh: Podman CLI entry point (vpdmn-x86_64, vpdmn-aarch64) - vpdmn-init.sh: Podman init script for QEMU guest Recipes: - vpdmn-native: Installs vpdmn CLI wrappers - vpdmn-rootfs-image: Builds Podman rootfs with crun, netavark, skopeo - vpdmn-initramfs-create: Creates bootable initramfs blob The vpdmn CLI provides Podman-compatible commands executed inside a QEMU-emulated environment. Unlike vdkr, Podman is daemonless which simplifies the guest init process. Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
Diffstat (limited to 'recipes-containers/vcontainer/files')
-rw-r--r--recipes-containers/vcontainer/files/blobs/vpdmn/aarch64/README26
-rw-r--r--recipes-containers/vcontainer/files/blobs/vpdmn/x86_64/README26
-rwxr-xr-xrecipes-containers/vcontainer/files/vpdmn-init.sh181
-rwxr-xr-xrecipes-containers/vcontainer/files/vpdmn.sh25
4 files changed, 258 insertions, 0 deletions
diff --git a/recipes-containers/vcontainer/files/blobs/vpdmn/aarch64/README b/recipes-containers/vcontainer/files/blobs/vpdmn/aarch64/README
new file mode 100644
index 00000000..a4197779
--- /dev/null
+++ b/recipes-containers/vcontainer/files/blobs/vpdmn/aarch64/README
@@ -0,0 +1,26 @@
1vpdmn aarch64 Blobs
2====================
3
4This directory should contain the boot blobs for vpdmn aarch64:
5
6Required files:
7 - Image : Linux kernel for aarch64
8 - initramfs.cpio.gz : Tiny initramfs for switch_root
9 - rootfs.img : Ext4 root filesystem with Podman tools
10
11Build instructions:
12 1. Set MACHINE for aarch64:
13 MACHINE=qemuarm64
14
15 2. Build the blobs:
16 bitbake vpdmn-initramfs-create
17
18 3. Copy from deploy directory:
19 cp tmp/deploy/images/qemuarm64/vpdmn/aarch64/Image .
20 cp tmp/deploy/images/qemuarm64/vpdmn/aarch64/initramfs.cpio.gz .
21 cp tmp/deploy/images/qemuarm64/vpdmn/aarch64/rootfs.img .
22
23Once these files are present, vpdmn-native will automatically include them.
24
25Alternatively, set VPDMN_USE_DEPLOY = "1" in local.conf to use blobs
26directly from DEPLOY_DIR without copying to the layer.
diff --git a/recipes-containers/vcontainer/files/blobs/vpdmn/x86_64/README b/recipes-containers/vcontainer/files/blobs/vpdmn/x86_64/README
new file mode 100644
index 00000000..30ddb445
--- /dev/null
+++ b/recipes-containers/vcontainer/files/blobs/vpdmn/x86_64/README
@@ -0,0 +1,26 @@
1vpdmn x86_64 Blobs
2===================
3
4This directory should contain the boot blobs for vpdmn x86_64:
5
6Required files:
7 - bzImage : Linux kernel for x86_64
8 - initramfs.cpio.gz : Tiny initramfs for switch_root
9 - rootfs.img : Ext4 root filesystem with Podman tools
10
11Build instructions:
12 1. Set MACHINE for x86_64:
13 MACHINE=qemux86-64
14
15 2. Build the blobs:
16 bitbake vpdmn-initramfs-create
17
18 3. Copy from deploy directory:
19 cp tmp/deploy/images/qemux86-64/vpdmn/x86_64/bzImage .
20 cp tmp/deploy/images/qemux86-64/vpdmn/x86_64/initramfs.cpio.gz .
21 cp tmp/deploy/images/qemux86-64/vpdmn/x86_64/rootfs.img .
22
23Once these files are present, vpdmn-native will automatically include them.
24
25Alternatively, set VPDMN_USE_DEPLOY = "1" in local.conf to use blobs
26directly from DEPLOY_DIR without copying to the layer.
diff --git a/recipes-containers/vcontainer/files/vpdmn-init.sh b/recipes-containers/vcontainer/files/vpdmn-init.sh
new file mode 100755
index 00000000..52aa9129
--- /dev/null
+++ b/recipes-containers/vcontainer/files/vpdmn-init.sh
@@ -0,0 +1,181 @@
1#!/bin/sh
2# SPDX-FileCopyrightText: Copyright (C) 2025 Bruce Ashfield
3#
4# SPDX-License-Identifier: GPL-2.0-only
5#
6# vpdmn-init.sh
7# Init script for vpdmn: execute arbitrary podman commands in QEMU
8#
9# This script runs on a real ext4 filesystem after switch_root from initramfs.
10# The preinit script mounted /dev/vda (rootfs.img) and did switch_root to us.
11#
12# Drive layout (rootfs.img is always /dev/vda, mounted as /):
13# /dev/vda = rootfs.img (this script runs from here, mounted as /)
14# /dev/vdb = input disk (optional, OCI/tar/dir data)
15# /dev/vdc = state disk (optional, persistent Podman storage)
16#
17# Kernel parameters:
18# podman_cmd=<base64> Base64-encoded podman command + args
19# podman_input=<type> Input type: none, oci, tar, dir (default: none)
20# podman_output=<type> Output type: text, tar, storage (default: text)
21# podman_state=<type> State type: none, disk (default: none)
22# podman_network=1 Enable networking (configure eth0, DNS)
23#
24# Version: 1.1.0
25#
26# Note: Podman is daemonless - no containerd/dockerd required!
27
28# Set runtime-specific parameters before sourcing common code
29VCONTAINER_RUNTIME_NAME="vpdmn"
30VCONTAINER_RUNTIME_CMD="podman"
31VCONTAINER_RUNTIME_PREFIX="podman"
32VCONTAINER_STATE_DIR="/var/lib/containers/storage"
33VCONTAINER_SHARE_NAME="vpdmn_share"
34VCONTAINER_VERSION="1.1.0"
35
36# Source common init functions
37# When installed as /init, common file is at /vcontainer-init-common.sh
38. /vcontainer-init-common.sh
39
40# ============================================================================
41# Podman-Specific Functions
42# ============================================================================
43
44setup_podman_environment() {
45 # Podman needs XDG_RUNTIME_DIR
46 export XDG_RUNTIME_DIR="/run/user/0"
47 mkdir -p "$XDG_RUNTIME_DIR"
48 chmod 700 "$XDG_RUNTIME_DIR"
49}
50
51setup_podman_mounts() {
52 # Podman needs /dev/shm
53 mkdir -p /dev/shm
54 mount -t tmpfs tmpfs /dev/shm
55
56 # Mount /var/volatile for Yocto's volatile symlinks (/var/tmp -> volatile/tmp, etc.)
57 mkdir -p /var/volatile
58 mount -t tmpfs tmpfs /var/volatile
59 mkdir -p /var/volatile/tmp /var/volatile/log /var/volatile/run /var/volatile/cache
60
61 # Also mount /var/cache directly (not a symlink)
62 mount -t tmpfs tmpfs /var/cache
63}
64
65setup_podman_storage() {
66 mkdir -p /run/lock
67
68 # /var/lib/containers exists in rootfs.img (read-only), mount tmpfs over it
69 mount -t tmpfs tmpfs /var/lib/containers
70 mkdir -p /var/lib/containers/storage
71
72 # Handle Podman storage
73 if [ -n "$STATE_DISK" ] && [ -b "$STATE_DISK" ]; then
74 log "Mounting state disk $STATE_DISK as /var/lib/containers/storage..."
75 if mount -t ext4 "$STATE_DISK" /var/lib/containers/storage 2>&1; then
76 log "SUCCESS: Mounted $STATE_DISK as Podman storage"
77 log "Podman storage contents:"
78 [ "$QUIET_BOOT" = "0" ] && ls -la /var/lib/containers/storage/ 2>/dev/null || log "(empty)"
79 else
80 log "WARNING: Failed to mount state disk, using tmpfs fallback"
81 RUNTIME_STATE="none"
82 fi
83 else
84 log "Using tmpfs for Podman storage (ephemeral)..."
85 fi
86}
87
88verify_podman() {
89 # Podman is daemonless - just verify it's available
90 if [ -x "/usr/bin/podman" ]; then
91 log "Podman available: $(podman --version 2>/dev/null || echo 'version unknown')"
92 else
93 echo "===ERROR==="
94 echo "Podman not found at /usr/bin/podman"
95 sleep 2
96 reboot -f
97 fi
98}
99
100# Podman is daemonless - nothing to stop
101stop_runtime_daemons() {
102 :
103}
104
105handle_storage_output() {
106 # Export entire podman storage
107 # Tar from inside /var/lib/containers/storage so paths are vfs-images/... directly
108 echo "Packaging Podman storage..."
109 if ! cd /var/lib/containers/storage; then
110 echo "===ERROR==="
111 echo "Failed to cd to /var/lib/containers/storage"
112 echo "Contents of /var/lib/containers:"
113 ls -la /var/lib/containers/ 2>&1 || echo "(not found)"
114 poweroff -f
115 exit 1
116 fi
117 tar -cf /tmp/storage.tar .
118
119 STORAGE_SIZE=$(stat -c%s /tmp/storage.tar 2>/dev/null || echo "0")
120 echo "Storage size: $STORAGE_SIZE bytes"
121
122 if [ "$STORAGE_SIZE" -gt 1000 ]; then
123 dmesg -n 1
124 echo "===STORAGE_START==="
125 base64 /tmp/storage.tar
126 echo "===STORAGE_END==="
127 echo "===EXIT_CODE=$EXEC_EXIT_CODE==="
128 else
129 echo "===ERROR==="
130 echo "Storage too small"
131 fi
132}
133
134# ============================================================================
135# Main
136# ============================================================================
137
138# Initialize base environment
139setup_base_environment
140setup_podman_environment
141mount_base_filesystems
142
143# Check for quiet boot mode
144check_quiet_boot
145
146log "=== vpdmn Init ==="
147log "Version: $VCONTAINER_VERSION"
148
149# Mount tmpfs directories and Podman-specific mounts
150mount_tmpfs_dirs
151setup_podman_mounts
152setup_cgroups
153
154# Parse kernel command line
155parse_cmdline
156
157# Detect and configure disks
158detect_disks
159
160# Set up Podman storage (Podman-specific)
161setup_podman_storage
162
163# Mount input disk
164mount_input_disk
165
166# Configure networking
167configure_networking
168
169# Verify podman is available (no daemon to start)
170verify_podman
171
172# Handle daemon mode or single command execution
173if [ "$RUNTIME_DAEMON" = "1" ]; then
174 run_daemon_mode
175else
176 prepare_input_path
177 execute_command
178fi
179
180# Graceful shutdown
181graceful_shutdown
diff --git a/recipes-containers/vcontainer/files/vpdmn.sh b/recipes-containers/vcontainer/files/vpdmn.sh
new file mode 100755
index 00000000..30775d35
--- /dev/null
+++ b/recipes-containers/vcontainer/files/vpdmn.sh
@@ -0,0 +1,25 @@
1#!/bin/bash
2# SPDX-FileCopyrightText: Copyright (C) 2025 Bruce Ashfield
3#
4# SPDX-License-Identifier: GPL-2.0-only
5#
6# vpdmn: Podman-like interface for cross-architecture container operations
7#
8# This provides a familiar podman-like CLI that executes commands inside
9# a QEMU-emulated environment with the target architecture's Podman.
10#
11# Command naming convention:
12# - Commands matching Podman's syntax/semantics use Podman's name (import, load, save, etc.)
13# - Extended commands with non-Podman behavior use 'v' prefix (vimport)
14
15# Set runtime-specific parameters before sourcing common code
16VCONTAINER_RUNTIME_NAME="vpdmn"
17VCONTAINER_RUNTIME_CMD="podman"
18VCONTAINER_RUNTIME_PREFIX="VPDMN"
19VCONTAINER_IMPORT_TARGET="containers-storage:"
20VCONTAINER_STATE_FILE="podman-state.img"
21VCONTAINER_OTHER_PREFIX="VDKR"
22VCONTAINER_VERSION="1.2.0"
23
24# Source common implementation
25source "$(dirname "${BASH_SOURCE[0]}")/vcontainer-common.sh" "$@"