Add reproducible build system, native Unraid plugin, and WebUI
- versions.env pins podman, conmon, crun, netavark, aardvark-dns, passt, and fuse-overlayfs to verified upstream source checksums; SlackBuild recipes, scripts/build-packages.sh, checksums.sh, release.sh, and update-versions.sh implement the reproducible pipeline; GitHub Actions workflows build in a Slackware container and publish releases without committing any binaries. - plugin/podman.plg installs/updates/removes all eight packages (the seven components plus the plugin's own unraid-podman scaffolding package) via upgradepkg, using the official Unraid array-event hook mechanism (event/disks_mounted, event/stopping) instead of editing /boot/config/go. rc.podman and the sbin/ helper scripts implement storage creation, config seeding/sync, preflight checks, autostart with per-container Safe-Mode, and package verify/update/rollback. - webui/plugins/podman implements the Dashboard, Containers, Pods, Images, Volumes, Networks, Logs, Terminal, Compose, and Settings panels against the approved mockup (webui/mockups/prototype.html), talking to podman system service exclusively via PodmanClient.php (libpod REST API over the Unix socket), with two documented exceptions: Terminal's one-shot exec model and Compose's use of the podman compose CLI, since libpod has no REST equivalent for either. - docs/ARCHITECTURE.md and docs/ROADMAP.md record the design decisions and honest current status (syntax-checked, unit- and integration-tested against fake sockets/servers; not yet run against a real Unraid/Podman/Slackware system). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Executable
+150
@@ -0,0 +1,150 @@
|
||||
#!/bin/bash
|
||||
# =============================================================================
|
||||
# plugin/sbin/podman-preflight.sh
|
||||
#
|
||||
# Startup validation, run by `rc.podman start` BEFORE anything is mounted or
|
||||
# started. The goal is to fail fast with one clear message, instead of
|
||||
# letting `podman system service` fail three steps later with a cryptic
|
||||
# error. See docs/ARCHITECTURE.md section 16.1 (Startup-Robustheit).
|
||||
#
|
||||
# Every check below is independent and all of them run even if an earlier
|
||||
# one fails, so a single invocation reports every problem at once rather
|
||||
# than forcing the user through a fix-one-rerun-find-the-next loop.
|
||||
#
|
||||
# Exit code: 0 if every check passed, 1 if any failed (with all failures
|
||||
# already logged/notified by that point).
|
||||
# =============================================================================
|
||||
|
||||
set -u # deliberately not -e: see the "run every check" note above
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# shellcheck source=./podman-common.sh
|
||||
. "$SCRIPT_DIR/podman-common.sh"
|
||||
|
||||
podman_load_cfg
|
||||
|
||||
FAILURES=0
|
||||
|
||||
fail() {
|
||||
podman_log_error "preflight: $1"
|
||||
FAILURES=$((FAILURES + 1))
|
||||
}
|
||||
|
||||
ok() {
|
||||
podman_log "preflight: OK - $1"
|
||||
}
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# 1. Required binaries are actually installed.
|
||||
# -----------------------------------------------------------------------------
|
||||
for bin in podman conmon crun mount umount xfs_repair mkfs.xfs; do
|
||||
if command -v "$bin" > /dev/null 2>&1; then
|
||||
ok "$bin found"
|
||||
else
|
||||
fail "required binary '$bin' not found on PATH — is the plugin fully installed?"
|
||||
fi
|
||||
done
|
||||
|
||||
for helper in /usr/libexec/podman/netavark /usr/libexec/podman/aardvark-dns; do
|
||||
if [ -x "$helper" ]; then
|
||||
ok "$helper found"
|
||||
else
|
||||
fail "required helper '$helper' not found — is the plugin fully installed?"
|
||||
fi
|
||||
done
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# 2. Storage path configured, safe, and mounted (cache pool / disk, not
|
||||
# /mnt/user — see docs/ARCHITECTURE.md section 4.3).
|
||||
# -----------------------------------------------------------------------------
|
||||
if podman_storage_path_is_safe "$STORAGE_PATH" 2> /tmp/podman-preflight-storage-safety.log; then
|
||||
ok "STORAGE_PATH ($STORAGE_PATH) is not under /mnt/user"
|
||||
else
|
||||
fail "$(cat /tmp/podman-preflight-storage-safety.log)"
|
||||
fi
|
||||
rm -f /tmp/podman-preflight-storage-safety.log
|
||||
|
||||
if [ -d "$STORAGE_PATH" ] && mountpoint -q "$STORAGE_PATH" 2> /dev/null; then
|
||||
ok "STORAGE_PATH ($STORAGE_PATH) is a mounted filesystem"
|
||||
elif [ -d "$STORAGE_PATH" ]; then
|
||||
# Not every valid target is a mountpoint itself (e.g. a subdirectory of a
|
||||
# cache pool root) — warn rather than fail, but only if the parent chain
|
||||
# is mounted somewhere.
|
||||
if findmnt -T "$STORAGE_PATH" > /dev/null 2>&1; then
|
||||
ok "STORAGE_PATH ($STORAGE_PATH) resolves onto a mounted filesystem"
|
||||
else
|
||||
fail "STORAGE_PATH ($STORAGE_PATH) does not appear to be on a mounted filesystem"
|
||||
fi
|
||||
else
|
||||
fail "STORAGE_PATH ($STORAGE_PATH) does not exist — is the configured cache pool/disk present and started?"
|
||||
fi
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# 3. Free space check (only meaningful once STORAGE_PATH exists).
|
||||
# -----------------------------------------------------------------------------
|
||||
if [ -d "$STORAGE_PATH" ]; then
|
||||
available_kb=$(df --output=avail -k "$STORAGE_PATH" 2> /dev/null | tail -n1 | tr -d '[:space:]')
|
||||
if [ -n "${available_kb:-}" ]; then
|
||||
available_gb=$((available_kb / 1024 / 1024))
|
||||
if [ -f "$PODMAN_STORAGE_IMAGE" ]; then
|
||||
# Image already exists — just warn if the pool itself is nearly full,
|
||||
# since podman.img growth or new image pulls need headroom too.
|
||||
if [ "$available_gb" -lt 2 ]; then
|
||||
fail "less than 2G free on $STORAGE_PATH (${available_gb}G) — image pulls will likely fail"
|
||||
else
|
||||
ok "${available_gb}G free on $STORAGE_PATH"
|
||||
fi
|
||||
elif [ "$available_gb" -lt "$STORAGE_IMAGE_SIZE_GB" ]; then
|
||||
fail "not enough free space on $STORAGE_PATH to create a ${STORAGE_IMAGE_SIZE_GB}G podman.img (only ${available_gb}G free)"
|
||||
else
|
||||
ok "${available_gb}G free on $STORAGE_PATH (enough for a fresh ${STORAGE_IMAGE_SIZE_GB}G podman.img)"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# 4. Kernel supports cgroup v2 (required by crun/netavark's expectations).
|
||||
# -----------------------------------------------------------------------------
|
||||
if [ -f /sys/fs/cgroup/cgroup.controllers ]; then
|
||||
ok "cgroup v2 unified hierarchy is active"
|
||||
else
|
||||
fail "cgroup v2 unified hierarchy not detected (/sys/fs/cgroup/cgroup.controllers missing) — check Unraid's syslinux cgroup boot parameters"
|
||||
fi
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# 5. No orphaned socket/pidfile from a previous unclean shutdown.
|
||||
# -----------------------------------------------------------------------------
|
||||
if [ -S "$PODMAN_SOCKET" ]; then
|
||||
if [ -f "$PODMAN_SERVICE_PID_FILE" ] && kill -0 "$(cat "$PODMAN_SERVICE_PID_FILE")" 2> /dev/null; then
|
||||
fail "podman system service already appears to be running (pid $(cat "$PODMAN_SERVICE_PID_FILE")) — is rc.podman already started?"
|
||||
else
|
||||
podman_log "preflight: removing orphaned socket $PODMAN_SOCKET from a previous unclean shutdown"
|
||||
rm -f "$PODMAN_SOCKET"
|
||||
ok "cleared orphaned socket"
|
||||
fi
|
||||
else
|
||||
ok "no orphaned podman.sock"
|
||||
fi
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# 6. Boot-config directory exists (i.e. 'seed' has run at least once).
|
||||
# -----------------------------------------------------------------------------
|
||||
if [ -f "$PODMAN_CFG_FILE" ]; then
|
||||
ok "$PODMAN_CFG_FILE present"
|
||||
else
|
||||
fail "$PODMAN_CFG_FILE missing — run 'podman-config.sh seed' (should happen automatically on install)"
|
||||
fi
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Summary
|
||||
# -----------------------------------------------------------------------------
|
||||
if [ "$FAILURES" -gt 0 ]; then
|
||||
podman_notify "Podman preflight checks failed" \
|
||||
"$FAILURES check(s) failed — podman was not started. See $PODMAN_PLUGIN_LOG for details." \
|
||||
"alert"
|
||||
podman_log_error "preflight: $FAILURES check(s) failed, aborting start"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
podman_log "preflight: all checks passed"
|
||||
exit 0
|
||||
Reference in New Issue
Block a user