summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBruce Ashfield <bruce.ashfield@gmail.com>2026-01-08 04:46:41 +0000
committerBruce Ashfield <bruce.ashfield@gmail.com>2026-02-09 03:32:52 +0000
commit9e17cd687de956fd421454f1918131f824b95dbf (patch)
tree64841606793f703758ce7e7b05a5e89434e7d4f1
parent70a9de6c79b916991fcbf6fcc714891592a41a8b (diff)
downloadmeta-virtualization-9e17cd687de956fd421454f1918131f824b95dbf.tar.gz
vcontainer: add auto-start daemon with idle timeout
Add automatic daemon startup and idle timeout cleanup for vdkr/vpdmn: - vmemres daemon auto-starts on first command (no manual start needed) - Daemon auto-stops after idle timeout (default: 30 minutes) - --no-daemon flag for ephemeral mode (single-shot QEMU) - New config keys: idle-timeout, auto-daemon Changes: - vcontainer-init-common.sh: Parse idle_timeout from cmdline, add read -t timeout to daemon loop for auto-shutdown - vrunner.sh: Add --idle-timeout option, pass to kernel cmdline - vcontainer-common.sh: Auto-start logic in run_runtime_command(), --no-daemon flag, config defaults - container-cross-install.bbclass: Add --no-daemon for explicit ephemeral mode during Yocto builds Configuration: vdkr vconfig idle-timeout 3600 # 1 hour timeout vdkr vconfig auto-daemon false # Disable auto-start Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
-rw-r--r--classes/container-cross-install.bbclass2
-rwxr-xr-xrecipes-containers/vcontainer/files/vcontainer-common.sh81
-rwxr-xr-xrecipes-containers/vcontainer/files/vcontainer-init-common.sh19
-rwxr-xr-xrecipes-containers/vcontainer/files/vrunner.sh15
4 files changed, 102 insertions, 15 deletions
diff --git a/classes/container-cross-install.bbclass b/classes/container-cross-install.bbclass
index e0fc63da..8137a857 100644
--- a/classes/container-cross-install.bbclass
+++ b/classes/container-cross-install.bbclass
@@ -261,6 +261,7 @@ merge_installed_bundles() {
261 local docker_storage="${WORKDIR}/docker-storage-$$.tar" 261 local docker_storage="${WORKDIR}/docker-storage-$$.tar"
262 262
263 ${VRUNNER_PATH} \ 263 ${VRUNNER_PATH} \
264 --no-daemon \
264 --runtime docker \ 265 --runtime docker \
265 --arch ${BLOB_ARCH} \ 266 --arch ${BLOB_ARCH} \
266 --blob-dir ${VDKR_BLOB_DIR} \ 267 --blob-dir ${VDKR_BLOB_DIR} \
@@ -292,6 +293,7 @@ merge_installed_bundles() {
292 local podman_storage="${WORKDIR}/podman-storage-$$.tar" 293 local podman_storage="${WORKDIR}/podman-storage-$$.tar"
293 294
294 ${VRUNNER_PATH} \ 295 ${VRUNNER_PATH} \
296 --no-daemon \
295 --runtime podman \ 297 --runtime podman \
296 --arch ${BLOB_ARCH} \ 298 --arch ${BLOB_ARCH} \
297 --blob-dir ${VPDMN_BLOB_DIR} \ 299 --blob-dir ${VPDMN_BLOB_DIR} \
diff --git a/recipes-containers/vcontainer/files/vcontainer-common.sh b/recipes-containers/vcontainer/files/vcontainer-common.sh
index c63d2b3c..7fd62514 100755
--- a/recipes-containers/vcontainer/files/vcontainer-common.sh
+++ b/recipes-containers/vcontainer/files/vcontainer-common.sh
@@ -36,7 +36,7 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
36# 3. Default: ~/.config/${VCONTAINER_RUNTIME_NAME} 36# 3. Default: ~/.config/${VCONTAINER_RUNTIME_NAME}
37# 37#
38# Config file format: key=value (one per line) 38# Config file format: key=value (one per line)
39# Supported keys: arch, timeout, state-dir, verbose 39# Supported keys: arch, timeout, state-dir, verbose, idle-timeout, auto-daemon
40# ============================================================================ 40# ============================================================================
41 41
42# Pre-parse --config-dir from command line (needs to happen before detect_default_arch) 42# Pre-parse --config-dir from command line (needs to happen before detect_default_arch)
@@ -128,11 +128,13 @@ config_list() {
128config_default() { 128config_default() {
129 local key="$1" 129 local key="$1"
130 case "$key" in 130 case "$key" in
131 arch) uname -m ;; 131 arch) uname -m ;;
132 timeout) echo "300" ;; 132 timeout) echo "300" ;;
133 state-dir) echo "$HOME/.$VCONTAINER_RUNTIME_NAME" ;; 133 state-dir) echo "$HOME/.$VCONTAINER_RUNTIME_NAME" ;;
134 verbose) echo "false" ;; 134 verbose) echo "false" ;;
135 *) echo "" ;; 135 idle-timeout) echo "1800" ;; # 30 minutes
136 auto-daemon) echo "true" ;; # Auto-start daemon by default
137 *) echo "" ;;
136 esac 138 esac
137} 139}
138 140
@@ -387,9 +389,12 @@ ${BOLD}CONFIGURATION (vconfig):${NC}
387 ${CYAN}vconfig${NC} <key> <value> Set configuration value 389 ${CYAN}vconfig${NC} <key> <value> Set configuration value
388 ${CYAN}vconfig${NC} <key> --reset Reset to default value 390 ${CYAN}vconfig${NC} <key> --reset Reset to default value
389 391
390 Supported keys: arch, timeout, state-dir, verbose 392 Supported keys: arch, timeout, state-dir, verbose, idle-timeout, auto-daemon
391 Config file: \$CONFIG_DIR/config (default: ~/.config/${VCONTAINER_RUNTIME_NAME}/config) 393 Config file: \$CONFIG_DIR/config (default: ~/.config/${VCONTAINER_RUNTIME_NAME}/config)
392 394
395 idle-timeout: Daemon idle timeout in seconds [default: 1800]
396 auto-daemon: Auto-start daemon on first command [default: true]
397
393${BOLD}GLOBAL OPTIONS:${NC} 398${BOLD}GLOBAL OPTIONS:${NC}
394 --arch, -a <arch> Target architecture: x86_64 or aarch64 [default: ${DEFAULT_ARCH}] 399 --arch, -a <arch> Target architecture: x86_64 or aarch64 [default: ${DEFAULT_ARCH}]
395 --config-dir <path> Configuration directory [default: ~/.config/${VCONTAINER_RUNTIME_NAME}] 400 --config-dir <path> Configuration directory [default: ~/.config/${VCONTAINER_RUNTIME_NAME}]
@@ -400,6 +405,7 @@ ${BOLD}GLOBAL OPTIONS:${NC}
400 --storage <file> Export ${VCONTAINER_RUNTIME_CMD} storage after command (tar file) 405 --storage <file> Export ${VCONTAINER_RUNTIME_CMD} storage after command (tar file)
401 --input-storage <tar> Load ${RUNTIME_UPPER} state from tar before command 406 --input-storage <tar> Load ${RUNTIME_UPPER} state from tar before command
402 --no-kvm Disable KVM acceleration (use TCG emulation) 407 --no-kvm Disable KVM acceleration (use TCG emulation)
408 --no-daemon Run in ephemeral mode (don't auto-start/use daemon)
403 --verbose, -v Enable verbose output 409 --verbose, -v Enable verbose output
404 --help, -h Show this help 410 --help, -h Show this help
405 411
@@ -529,6 +535,7 @@ NETWORK="true"
529INTERACTIVE="false" 535INTERACTIVE="false"
530PORT_FORWARDS=() 536PORT_FORWARDS=()
531DISABLE_KVM="false" 537DISABLE_KVM="false"
538NO_DAEMON="false"
532COMMAND="" 539COMMAND=""
533COMMAND_ARGS=() 540COMMAND_ARGS=()
534 541
@@ -585,6 +592,10 @@ while [ $# -gt 0 ]; do
585 DISABLE_KVM="true" 592 DISABLE_KVM="true"
586 shift 593 shift
587 ;; 594 ;;
595 --no-daemon)
596 NO_DAEMON="true"
597 shift
598 ;;
588 -it|--interactive) 599 -it|--interactive)
589 INTERACTIVE="true" 600 INTERACTIVE="true"
590 shift 601 shift
@@ -682,13 +693,37 @@ run_runtime_command() {
682 local runtime_cmd="$1" 693 local runtime_cmd="$1"
683 local runner_args=$(build_runner_args) 694 local runner_args=$(build_runner_args)
684 695
696 # Check for --no-daemon flag - use ephemeral mode
697 if [ "$NO_DAEMON" = "true" ]; then
698 [ "$VERBOSE" = "true" ] && echo -e "${CYAN}[$VCONTAINER_RUNTIME_NAME]${NC} Using ephemeral mode (--no-daemon)" >&2
699 "$RUNNER" $runner_args -- "$runtime_cmd"
700 return $?
701 fi
702
685 if daemon_is_running; then 703 if daemon_is_running; then
686 # Use daemon mode - faster 704 # Use daemon mode - faster
687 [ "$VERBOSE" = "true" ] && echo -e "${CYAN}[$VCONTAINER_RUNTIME_NAME]${NC} Using daemon mode" >&2 705 [ "$VERBOSE" = "true" ] && echo -e "${CYAN}[$VCONTAINER_RUNTIME_NAME]${NC} Using daemon mode" >&2
688 "$RUNNER" $runner_args --daemon-send "$runtime_cmd" 706 "$RUNNER" $runner_args --daemon-send "$runtime_cmd"
689 else 707 else
690 # Regular mode - start QEMU for this command 708 # Check if auto-daemon is enabled
691 "$RUNNER" $runner_args -- "$runtime_cmd" 709 local auto_daemon=$(config_get "auto-daemon" "true")
710 if [ "$auto_daemon" = "true" ]; then
711 # Auto-start daemon
712 echo -e "${CYAN}[$VCONTAINER_RUNTIME_NAME]${NC} Starting daemon..." >&2
713 local idle_timeout=$(config_get "idle-timeout" "1800")
714 "$RUNNER" $runner_args --idle-timeout "$idle_timeout" --daemon-start
715
716 if daemon_is_running; then
717 [ "$VERBOSE" = "true" ] && echo -e "${CYAN}[$VCONTAINER_RUNTIME_NAME]${NC} Using daemon mode" >&2
718 "$RUNNER" $runner_args --daemon-send "$runtime_cmd"
719 else
720 echo -e "${RED}[$VCONTAINER_RUNTIME_NAME]${NC} Failed to start daemon, using ephemeral mode" >&2
721 "$RUNNER" $runner_args -- "$runtime_cmd"
722 fi
723 else
724 # Auto-daemon disabled - use ephemeral mode
725 "$RUNNER" $runner_args -- "$runtime_cmd"
726 fi
692 fi 727 fi
693} 728}
694 729
@@ -700,13 +735,37 @@ run_runtime_command_with_input() {
700 local runtime_cmd="$3" 735 local runtime_cmd="$3"
701 local runner_args=$(build_runner_args) 736 local runner_args=$(build_runner_args)
702 737
738 # Check for --no-daemon flag - use ephemeral mode
739 if [ "$NO_DAEMON" = "true" ]; then
740 [ "$VERBOSE" = "true" ] && echo -e "${CYAN}[$VCONTAINER_RUNTIME_NAME]${NC} Using ephemeral mode (--no-daemon)" >&2
741 "$RUNNER" $runner_args --input "$input_path" --input-type "$input_type" -- "$runtime_cmd"
742 return $?
743 fi
744
703 if daemon_is_running; then 745 if daemon_is_running; then
704 # Use daemon mode with virtio-9p shared directory 746 # Use daemon mode with virtio-9p shared directory
705 [ "$VERBOSE" = "true" ] && echo -e "${CYAN}[$VCONTAINER_RUNTIME_NAME]${NC} Using daemon mode for file I/O" >&2 747 [ "$VERBOSE" = "true" ] && echo -e "${CYAN}[$VCONTAINER_RUNTIME_NAME]${NC} Using daemon mode for file I/O" >&2
706 "$RUNNER" $runner_args --input "$input_path" --input-type "$input_type" --daemon-send-input -- "$runtime_cmd" 748 "$RUNNER" $runner_args --input "$input_path" --input-type "$input_type" --daemon-send-input -- "$runtime_cmd"
707 else 749 else
708 # Regular mode - start QEMU for this command 750 # Check if auto-daemon is enabled
709 "$RUNNER" $runner_args --input "$input_path" --input-type "$input_type" -- "$runtime_cmd" 751 local auto_daemon=$(config_get "auto-daemon" "true")
752 if [ "$auto_daemon" = "true" ]; then
753 # Auto-start daemon
754 echo -e "${CYAN}[$VCONTAINER_RUNTIME_NAME]${NC} Starting daemon..." >&2
755 local idle_timeout=$(config_get "idle-timeout" "1800")
756 "$RUNNER" $runner_args --idle-timeout "$idle_timeout" --daemon-start
757
758 if daemon_is_running; then
759 [ "$VERBOSE" = "true" ] && echo -e "${CYAN}[$VCONTAINER_RUNTIME_NAME]${NC} Using daemon mode for file I/O" >&2
760 "$RUNNER" $runner_args --input "$input_path" --input-type "$input_type" --daemon-send-input -- "$runtime_cmd"
761 else
762 echo -e "${RED}[$VCONTAINER_RUNTIME_NAME]${NC} Failed to start daemon, using ephemeral mode" >&2
763 "$RUNNER" $runner_args --input "$input_path" --input-type "$input_type" -- "$runtime_cmd"
764 fi
765 else
766 # Auto-daemon disabled - use ephemeral mode
767 "$RUNNER" $runner_args --input "$input_path" --input-type "$input_type" -- "$runtime_cmd"
768 fi
710 fi 769 fi
711} 770}
712 771
diff --git a/recipes-containers/vcontainer/files/vcontainer-init-common.sh b/recipes-containers/vcontainer/files/vcontainer-init-common.sh
index 872508db..5bfee9b7 100755
--- a/recipes-containers/vcontainer/files/vcontainer-init-common.sh
+++ b/recipes-containers/vcontainer/files/vcontainer-init-common.sh
@@ -106,6 +106,7 @@ parse_cmdline() {
106 RUNTIME_NETWORK="0" 106 RUNTIME_NETWORK="0"
107 RUNTIME_INTERACTIVE="0" 107 RUNTIME_INTERACTIVE="0"
108 RUNTIME_DAEMON="0" 108 RUNTIME_DAEMON="0"
109 RUNTIME_IDLE_TIMEOUT="1800" # Default: 30 minutes
109 110
110 for param in $(cat /proc/cmdline); do 111 for param in $(cat /proc/cmdline); do
111 case "$param" in 112 case "$param" in
@@ -130,6 +131,9 @@ parse_cmdline() {
130 ${VCONTAINER_RUNTIME_PREFIX}_daemon=*) 131 ${VCONTAINER_RUNTIME_PREFIX}_daemon=*)
131 RUNTIME_DAEMON="${param#${VCONTAINER_RUNTIME_PREFIX}_daemon=}" 132 RUNTIME_DAEMON="${param#${VCONTAINER_RUNTIME_PREFIX}_daemon=}"
132 ;; 133 ;;
134 ${VCONTAINER_RUNTIME_PREFIX}_idle_timeout=*)
135 RUNTIME_IDLE_TIMEOUT="${param#${VCONTAINER_RUNTIME_PREFIX}_idle_timeout=}"
136 ;;
133 esac 137 esac
134 done 138 done
135 139
@@ -284,6 +288,7 @@ DNSEOF
284 288
285run_daemon_mode() { 289run_daemon_mode() {
286 log "=== Daemon Mode ===" 290 log "=== Daemon Mode ==="
291 log "Idle timeout: ${RUNTIME_IDLE_TIMEOUT}s"
287 292
288 # Find the virtio-serial port for command channel 293 # Find the virtio-serial port for command channel
289 DAEMON_PORT="" 294 DAEMON_PORT=""
@@ -321,10 +326,10 @@ run_daemon_mode() {
321 326
322 log "Daemon ready, waiting for commands..." 327 log "Daemon ready, waiting for commands..."
323 328
324 # Command loop 329 # Command loop with idle timeout
325 while true; do 330 while true; do
326 CMD_B64="" 331 CMD_B64=""
327 if read -r CMD_B64 <&3; then 332 if read -t "$RUNTIME_IDLE_TIMEOUT" -r CMD_B64 <&3; then
328 log "Received: '$CMD_B64'" 333 log "Received: '$CMD_B64'"
329 # Handle special commands 334 # Handle special commands
330 case "$CMD_B64" in 335 case "$CMD_B64" in
@@ -414,7 +419,15 @@ run_daemon_mode() {
414 419
415 log "Command completed (exit code: $EXEC_EXIT_CODE)" 420 log "Command completed (exit code: $EXEC_EXIT_CODE)"
416 else 421 else
417 sleep 1 422 # Read returned non-zero: either timeout or error
423 if [ -z "$CMD_B64" ]; then
424 # Timeout expired with no data - shut down
425 log "Idle timeout (${RUNTIME_IDLE_TIMEOUT}s), shutting down..."
426 echo "===IDLE_SHUTDOWN===" | cat >&3
427 break
428 fi
429 # Empty line or other issue - just continue
430 sleep 0.1
418 fi 431 fi
419 done 432 done
420 433
diff --git a/recipes-containers/vcontainer/files/vrunner.sh b/recipes-containers/vcontainer/files/vrunner.sh
index 2be33765..cd504f7b 100755
--- a/recipes-containers/vcontainer/files/vrunner.sh
+++ b/recipes-containers/vcontainer/files/vrunner.sh
@@ -122,7 +122,9 @@ OPTIONS:
122 --network, -n Enable networking (slirp user-mode, outbound only) 122 --network, -n Enable networking (slirp user-mode, outbound only)
123 --interactive, -it Run in interactive mode (connects terminal to container) 123 --interactive, -it Run in interactive mode (connects terminal to container)
124 --timeout <secs> QEMU timeout [default: 300] 124 --timeout <secs> QEMU timeout [default: 300]
125 --idle-timeout <s> Daemon idle timeout in seconds [default: 1800]
125 --no-kvm Disable KVM acceleration (use TCG emulation) 126 --no-kvm Disable KVM acceleration (use TCG emulation)
127 --no-daemon Placeholder for CLI wrapper (ignored by vrunner)
126 --batch-import Batch import mode: import multiple OCI containers in one session 128 --batch-import Batch import mode: import multiple OCI containers in one session
127 --keep-temp Keep temporary files for debugging 129 --keep-temp Keep temporary files for debugging
128 --verbose, -v Enable verbose output 130 --verbose, -v Enable verbose output
@@ -195,6 +197,7 @@ BATCH_IMPORT="false"
195# Daemon mode options 197# Daemon mode options
196DAEMON_MODE="" # start, send, stop, status 198DAEMON_MODE="" # start, send, stop, status
197DAEMON_SOCKET_DIR="" # Directory for daemon socket/PID files 199DAEMON_SOCKET_DIR="" # Directory for daemon socket/PID files
200IDLE_TIMEOUT="1800" # Default: 30 minutes
198 201
199while [ $# -gt 0 ]; do 202while [ $# -gt 0 ]; do
200 case $1 in 203 case $1 in
@@ -293,6 +296,15 @@ while [ $# -gt 0 ]; do
293 DAEMON_SOCKET_DIR="$2" 296 DAEMON_SOCKET_DIR="$2"
294 shift 2 297 shift 2
295 ;; 298 ;;
299 --idle-timeout)
300 IDLE_TIMEOUT="$2"
301 shift 2
302 ;;
303 --no-daemon)
304 # Placeholder for CLI wrapper - vrunner.sh itself doesn't use this
305 # but we accept it so callers can pass it through
306 shift
307 ;;
296 --verbose|-v) 308 --verbose|-v)
297 VERBOSE="true" 309 VERBOSE="true"
298 shift 310 shift
@@ -1061,8 +1073,9 @@ if [ "$DAEMON_MODE" = "start" ]; then
1061 QEMU_OPTS="$QEMU_OPTS -device virtio-serial-pci" 1073 QEMU_OPTS="$QEMU_OPTS -device virtio-serial-pci"
1062 QEMU_OPTS="$QEMU_OPTS -device virtserialport,chardev=vdkr,name=vdkr" 1074 QEMU_OPTS="$QEMU_OPTS -device virtserialport,chardev=vdkr,name=vdkr"
1063 1075
1064 # Tell init script to run in daemon mode 1076 # Tell init script to run in daemon mode with idle timeout
1065 KERNEL_APPEND="$KERNEL_APPEND ${CMDLINE_PREFIX}_daemon=1" 1077 KERNEL_APPEND="$KERNEL_APPEND ${CMDLINE_PREFIX}_daemon=1"
1078 KERNEL_APPEND="$KERNEL_APPEND ${CMDLINE_PREFIX}_idle_timeout=$IDLE_TIMEOUT"
1066 1079
1067 # Always enable networking for daemon mode 1080 # Always enable networking for daemon mode
1068 if [ "$NETWORK" != "true" ]; then 1081 if [ "$NETWORK" != "true" ]; then