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:
@@ -16,12 +16,17 @@
|
||||
* save POST {"storagePath": "...", "storageImageSizeGb": 20,
|
||||
* "enabled": true, "stopTimeoutSeconds": 10}
|
||||
* autostart_save POST {"names": ["postgres", "nextcloud", ...]}
|
||||
* service_status GET -> {"running": bool, "output": "..."}
|
||||
* service_start POST -> {"running": bool, "output": "..."}
|
||||
* service_restart POST -> {"running": bool, "output": "..."}
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
require __DIR__ . '/../include/bootstrap.php';
|
||||
|
||||
const RC_PODMAN = '/etc/rc.d/rc.podman';
|
||||
|
||||
$action = $_GET['action'] ?? '';
|
||||
|
||||
switch ($action) {
|
||||
@@ -45,10 +50,60 @@ switch ($action) {
|
||||
podman_json_response(['status' => 'saved']);
|
||||
break;
|
||||
|
||||
case 'service_status':
|
||||
podman_json_response(rc_podman('status', 15));
|
||||
break;
|
||||
|
||||
case 'service_start':
|
||||
podman_json_response(rc_podman('start', 120));
|
||||
break;
|
||||
|
||||
case 'service_restart':
|
||||
podman_json_response(rc_podman('restart', 120));
|
||||
break;
|
||||
|
||||
default:
|
||||
podman_json_error("Unknown action '{$action}'", 400);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shells out to /etc/rc.d/rc.podman <verb> — the plugin's own real
|
||||
* start/stop/status script, the SAME one the array-start event hook and
|
||||
* a terminal `rc.podman status` use (see plugin/rc.d/rc.podman's header
|
||||
* comment). This exists specifically so a fresh install where podman
|
||||
* failed to start (e.g. no cache pool configured yet, see
|
||||
* podman-storage.sh's "does not exist or is not mounted" error) can be
|
||||
* diagnosed and retried from the WebUI itself — no SSH/terminal access
|
||||
* needed, which is exactly what was missing when this was first needed
|
||||
* live (a fresh install on a different Unraid box with nobody able to
|
||||
* reach a terminal to run `rc.podman start` by hand).
|
||||
*
|
||||
* @return array{running: bool, output: string}
|
||||
*/
|
||||
function rc_podman(string $verb, int $timeoutSeconds): array
|
||||
{
|
||||
$descriptors = [1 => ['pipe', 'w'], 2 => ['pipe', 'w']];
|
||||
$process = proc_open([RC_PODMAN, $verb], $descriptors, $pipes);
|
||||
if (!is_resource($process)) {
|
||||
podman_json_error("Could not run rc.podman {$verb}", 500);
|
||||
}
|
||||
|
||||
stream_set_timeout($pipes[1], $timeoutSeconds);
|
||||
$stdout = stream_get_contents($pipes[1]) ?: '';
|
||||
$stderr = stream_get_contents($pipes[2]) ?: '';
|
||||
fclose($pipes[1]);
|
||||
fclose($pipes[2]);
|
||||
proc_close($process);
|
||||
|
||||
$combined = trim($stdout . $stderr);
|
||||
// rc.podman status/start both print "service: running (pid ..., socket ...)"
|
||||
// on success — cheaper and more honest than re-implementing the same
|
||||
// socket/pid check PHP-side when the shell script already did it.
|
||||
$running = (bool) preg_match('/service:\s+running/', $combined);
|
||||
|
||||
return ['running' => $running, 'output' => $combined];
|
||||
}
|
||||
|
||||
/** @return array<string,mixed> */
|
||||
function settings_get(PodmanConfig $config): array
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user