- Package #9-11: catatonit (pod infra init), nftables (netavark firewall backend), docker-compose (external compose provider for `podman compose`) — all vendored prebuilt binaries, versions.env pinned, propagated through build-packages.sh/release.sh/podman.plg/verify+update-packages.sh. - Fix WebUI: every POST action was silently failing (empty response body) because Unraid's own CSRF protection was never satisfied — app.js now sends the page's csrf_token as X-CSRF-Token. - Fix WebUI: PodmanClient::pullImage() assumed a single JSON response, but /images/pull actually streams newline-delimited JSON — every successful pull was throwing "Expected a JSON object/array response". - Fix WebUI: compose.php's up/down status detection had the same single-JSON-vs-NDJSON bug for `podman compose ps`, plus stderr was corrupting the parse. - Add cache-busting (?v=<mtime>) to Podman.page's script/style tags so a redeployed JS/CSS fix isn't served stale from browser cache. - Add a reusable modal dialog (app.js openFormModal) replacing prompt()/alert() for New Volume/Network/Pull Image. - Add host-path (bind-mount) support when creating a named volume. - Add Create Container (image, name, network mode incl. custom networks, ports, volumes, env, restart policy, privileged, start-after-create), auto-pulling the image on first use since /containers/create doesn't. All fixes verified live against a real podman system service and, where reachable, via the actual WebUI over the real socket — not just unit-level. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
80 lines
2.3 KiB
PHP
80 lines
2.3 KiB
PHP
<?php
|
|
/**
|
|
* ajax/system.php
|
|
*
|
|
* Backs the Dashboard panel's summary tiles and the service-status line
|
|
* shown in the page header — aggregates across several libpod endpoints
|
|
* into the one shape javascript/dashboard.js needs, so the frontend
|
|
* doesn't have to make (and wait on) five separate round trips.
|
|
*
|
|
* Actions (?action=...):
|
|
* summary GET -> counts, storage usage, engine version, ping status
|
|
*/
|
|
|
|
declare(strict_types=1);
|
|
|
|
require __DIR__ . '/../include/bootstrap.php';
|
|
|
|
$action = $_GET['action'] ?? '';
|
|
|
|
switch ($action) {
|
|
case 'summary':
|
|
podman_json_response(system_summary($client, $podmanConfig));
|
|
break;
|
|
|
|
default:
|
|
podman_json_error("Unknown action '{$action}'", 400);
|
|
}
|
|
|
|
/** @return array<string,mixed> */
|
|
function system_summary(PodmanClient $client, PodmanConfig $config): array
|
|
{
|
|
if (!$client->ping()) {
|
|
return [
|
|
'reachable' => false,
|
|
'socketPath' => $config->socketPath,
|
|
];
|
|
}
|
|
|
|
$containers = $client->listContainers(true);
|
|
$running = 0;
|
|
foreach ($containers as $c) {
|
|
if (strtolower((string) ($c['State'] ?? '')) === 'running') {
|
|
$running++;
|
|
}
|
|
}
|
|
|
|
$pods = $client->listPods();
|
|
$images = $client->listImages();
|
|
$volumes = $client->listVolumes();
|
|
$networks = $client->listNetworks();
|
|
$info = $client->info();
|
|
$df = $client->systemDf();
|
|
|
|
$imagesSize = 0;
|
|
foreach (($df['Images'] ?? []) as $img) {
|
|
$imagesSize += (int) ($img['Size'] ?? 0);
|
|
}
|
|
|
|
return [
|
|
'reachable' => true,
|
|
'socketPath' => $config->socketPath,
|
|
// libpod's /info nests the version block under lowercase "version"
|
|
// (unlike most other libpod endpoints, which are PascalCase
|
|
// throughout) — verified live against a real podman system service.
|
|
'podmanVersion' => $info['version']['Version'] ?? null,
|
|
'containers' => [
|
|
'total' => count($containers),
|
|
'running' => $running,
|
|
],
|
|
'pods' => count($pods),
|
|
'images' => count($images),
|
|
'volumes' => count($volumes),
|
|
'networks' => count($networks),
|
|
'storage' => [
|
|
'imagesSizeBytes' => $imagesSize,
|
|
'imagesSizeFormatted' => podman_format_bytes($imagesSize),
|
|
],
|
|
];
|
|
}
|