Fix real STORAGE_PATH bug; add Start Podman + format-disk from the WebUI
Root cause of a fresh-install "cannot reach the Podman API socket" report (a friend's Unraid box, cache pool present and mounted): unlike Docker-for-Unraid's docker.img path, this plugin never auto-created STORAGE_PATH itself — only podman.img inside it. A perfectly normal, already-mounted cache pool still failed preflight/storage-create with "does not exist", just because its own .../system/podman subdirectory had never been created. Fixed by walking up to the nearest existing ancestor and checking whether it's on a different device than / (real mount vs. nothing mounted at all) — see podman-common.sh's new podman_path_has_real_mount_ancestor(), used by both podman-preflight.sh and podman-storage.sh. Settings gets a "Podman Service" card (status chip + Start/Restart, backed by new ajax/settings.php service_status/start/restart actions that just shell out to rc.podman) so a fresh install that failed to start can be diagnosed and retried without SSH/terminal access at all — exactly what was missing when this was first needed live. Also adds "Format a Disk for Podman Storage" (new ajax/disks.php) for a single-disk system with no cache pool at all. Only ever lists disks with literally no existing partition/filesystem/RAID-or-ZFS-membership signature and that aren't Unraid's boot flash — found live, twice, during development: the boot USB (FAT, labeled "UNRAID") passed the initial mounted-only check because this host's /boot is backed by a ZFS dataset rather than a direct partition mount, and active RAID-member cache disks passed a data-vs-blank *warning* rather than a hard exclusion. Both are now excluded outright, not just flagged — see disks.php's device_or_children_labeled_unraid() and the hasData exclusion in list_candidate_disks(). A disk formatted this way is remounted by UUID on every boot via a new plugin/sbin/podman-mount-managed-disk.sh, called from plugin/event/disks_mounted before rc.podman start. Unrelated fix bundled in: scripts/lib/slackbuild-common.sh now sets SOURCE_DATE_EPOCH (derived from the repo's last commit) before calling makepkg, so two separate builds of the same commit produce byte-identical .txz files — makepkg already supports this (`--clamp-mtime` when $SOURCE_DATE_EPOCH is set, confirmed by reading a real host's /sbin/makepkg) but nothing was setting the variable, so release.yml's "rebuild in CI and verify it matches the committed checksums" step was guaranteed to fail on the first package it checked alphabetically (observed live: aardvark-dns). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -20,6 +20,12 @@
|
||||
# blocked on podman's full startup sequence (preflight, storage mount,
|
||||
# service start, autostart chain) — mirrors how unassigned.devices
|
||||
# backgrounds its own longer-running "started" hook.
|
||||
#
|
||||
# podman-mount-managed-disk.sh runs first, still within the same
|
||||
# backgrounded subshell: it's a no-op unless the WebUI's "Format a Disk
|
||||
# for Podman Storage" flow (ajax/disks.php) was ever used, and rc.podman
|
||||
# start's own storage step needs that disk already mounted at
|
||||
# $STORAGE_PATH to succeed — see that script's own header comment.
|
||||
# =============================================================================
|
||||
|
||||
/etc/rc.d/rc.podman start > /dev/null 2>&1 & disown
|
||||
(/usr/local/sbin/podman-mount-managed-disk.sh; /etc/rc.d/rc.podman start) > /dev/null 2>&1 & disown
|
||||
|
||||
@@ -168,6 +168,33 @@ podman_storage_path_is_safe() {
|
||||
return 0
|
||||
}
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# podman_path_has_real_mount_ancestor <path>
|
||||
#
|
||||
# True if <path> itself, or its nearest EXISTING ancestor directory, lives
|
||||
# on a different filesystem than / (root) — i.e. something is genuinely
|
||||
# mounted along this path (a cache pool, a dedicated disk, ...), even if
|
||||
# the exact leaf directory doesn't exist yet. False only when nothing real
|
||||
# is mounted anywhere along the path (root/RAM all the way up), which is
|
||||
# the one case that's actually unsafe to silently `mkdir -p` into.
|
||||
#
|
||||
# This exists because this project never auto-created $STORAGE_PATH
|
||||
# itself (only podman.img inside it) — found live: a perfectly normal,
|
||||
# already-mounted cache pool still failed preflight/storage-create with
|
||||
# "does not exist", because the pool's own .../system/podman subdirectory
|
||||
# had simply never been created. "Does the exact leaf directory exist" was
|
||||
# always the wrong question; "is a real filesystem mounted somewhere along
|
||||
# this path" is the one that actually matters.
|
||||
# -----------------------------------------------------------------------------
|
||||
podman_path_has_real_mount_ancestor() {
|
||||
local path="$1"
|
||||
local parent="$path"
|
||||
while [ ! -d "$parent" ] && [ "$parent" != "/" ]; do
|
||||
parent="$(dirname "$parent")"
|
||||
done
|
||||
[ "$parent" != "/" ] && [ "$(stat -c %d "$parent")" != "$(stat -c %d /)" ]
|
||||
}
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# podman_require_command <binary>
|
||||
#
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
#!/bin/bash
|
||||
# =============================================================================
|
||||
# plugin/sbin/podman-mount-managed-disk.sh
|
||||
#
|
||||
# Remounts, on every boot, a disk the WebUI's "Format a Disk for Podman
|
||||
# Storage" flow (webui/plugins/podman/ajax/disks.php's "format" action)
|
||||
# formatted and mounted for a single-disk system with no cache pool —
|
||||
# that disk is deliberately outside Unraid's own array/cache pool
|
||||
# management (it's just a plain XFS filesystem on an otherwise-unassigned
|
||||
# disk), so nothing else on the system would remount it after a reboot.
|
||||
#
|
||||
# Called from plugin/event/disks_mounted, BEFORE rc.podman start, so
|
||||
# $STORAGE_PATH (pointed at this disk's mountpoint via Settings) is a real
|
||||
# mounted filesystem by the time podman-storage.sh's `create`/`mount`
|
||||
# steps run — see that script's "does not exist or is not mounted" check.
|
||||
#
|
||||
# Does nothing (exit 0) if the plugin was never used to format a disk —
|
||||
# /boot/config/plugins/podman/managed-disk.cfg only exists after that flow
|
||||
# has actually run at least once.
|
||||
# =============================================================================
|
||||
|
||||
set -eu
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# shellcheck source=./podman-common.sh
|
||||
. "$SCRIPT_DIR/podman-common.sh"
|
||||
|
||||
MANAGED_DISK_CFG="$PODMAN_BOOT_DIR/managed-disk.cfg"
|
||||
[ -f "$MANAGED_DISK_CFG" ] || exit 0
|
||||
|
||||
UUID=""
|
||||
MOUNTPOINT=""
|
||||
# shellcheck source=/dev/null
|
||||
. "$MANAGED_DISK_CFG"
|
||||
|
||||
if [ -z "$UUID" ] || [ -z "$MOUNTPOINT" ]; then
|
||||
podman_log_error "mount-managed-disk: $MANAGED_DISK_CFG is missing UUID/MOUNTPOINT, skipping"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if mountpoint -q "$MOUNTPOINT" 2> /dev/null; then
|
||||
podman_log "mount-managed-disk: $MOUNTPOINT already mounted"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
mkdir -p "$MOUNTPOINT"
|
||||
if mount "UUID=$UUID" "$MOUNTPOINT"; then
|
||||
podman_log "mount-managed-disk: mounted UUID=$UUID at $MOUNTPOINT"
|
||||
else
|
||||
podman_log_error "mount-managed-disk: failed to mount UUID=$UUID at $MOUNTPOINT (disk removed/renamed?)"
|
||||
fi
|
||||
@@ -75,6 +75,14 @@ elif [ -d "$STORAGE_PATH" ]; then
|
||||
else
|
||||
fail "STORAGE_PATH ($STORAGE_PATH) does not appear to be on a mounted filesystem"
|
||||
fi
|
||||
elif podman_path_has_real_mount_ancestor "$STORAGE_PATH"; then
|
||||
# The leaf directory doesn't exist yet, but a real filesystem IS mounted
|
||||
# somewhere along its path (e.g. the cache pool itself) — podman-storage.sh
|
||||
# create will mkdir -p it. Not a failure; see that check's own comment
|
||||
# for the live bug this used to cause (a normal, already-mounted cache
|
||||
# pool failing preflight just because its .../system/podman subdirectory
|
||||
# had never been created).
|
||||
ok "STORAGE_PATH ($STORAGE_PATH) doesn't exist yet, but resolves onto a mounted filesystem — will be created"
|
||||
else
|
||||
fail "STORAGE_PATH ($STORAGE_PATH) does not exist — is the configured cache pool/disk present and started?"
|
||||
fi
|
||||
|
||||
@@ -46,9 +46,13 @@ cmd_create() {
|
||||
fi
|
||||
|
||||
if [ ! -d "$STORAGE_PATH" ]; then
|
||||
podman_log_error "storage: $STORAGE_PATH does not exist or is not mounted."
|
||||
podman_log_error "storage: check that the configured cache pool/disk is present before starting podman."
|
||||
return 1
|
||||
if ! podman_path_has_real_mount_ancestor "$STORAGE_PATH"; then
|
||||
podman_log_error "storage: $STORAGE_PATH does not exist or is not mounted."
|
||||
podman_log_error "storage: check that the configured cache pool/disk is present before starting podman."
|
||||
return 1
|
||||
fi
|
||||
podman_log "storage: $STORAGE_PATH doesn't exist yet under an already-mounted filesystem — creating it"
|
||||
mkdir -p "$STORAGE_PATH"
|
||||
fi
|
||||
|
||||
# Free space check: refuse to create an image bigger than what's actually
|
||||
|
||||
Reference in New Issue
Block a user