- WEBGUI_PHP_WAIT was referenced by webgui_watchdog.sh but never defined
in master.conf, always silently falling back to a hardcoded default
- arrs.php/confform.php still pointed at Media/ for arr cleanup/discovery
scripts moved to Arrs_Stack/ in b4bc926 — broke the Arrs page's stats
and the per-script settings editor for those scripts
- docker_folders.php read directly from the optional folder.view3 plugin's
file instead of Varaverk's own docker_folders.json (the primary store
since the Docker tab got its own config) — left the Monitor page's
Docker Folders widget empty on any host without folder.view3 installed
- vv_wd_remote_data() read remote watchdog state files from hardcoded
/tmp or /boot/config paths instead of the remote's actual STATE_DIR
(which resolves dynamically and can differ under flash mode) — remote
node's Watchdog panel was always empty; same wrong path also used for
two local reads (system_watchdog_oom.db, watchdog_appdata_growth.db)
- rsync.php referenced a {HOST}_MONTHLY_SYNC_SHARES conf var that never
existed (monthly_maintenance.sh has no rsync section) — nulled out to
match the existing pattern used for the fallback window
- vv_arr_node_names() did a pointless identity array_map
- vv_dk_webui() had its own duplicate local-IP resolution instead of
using vv_local_ip(), despite config.php's comment claiming that exact
duplication was already consolidated
95 lines
3.2 KiB
PHP
95 lines
3.2 KiB
PHP
<?php
|
|
require_once __DIR__ . '/config.php';
|
|
require_once __DIR__ . '/docker.php';
|
|
|
|
function vv_container_webui(string $name, array $portMap): string {
|
|
$template = '/boot/config/plugins/dockerMan/templates-user/my-' . $name . '.xml';
|
|
if (!file_exists($template)) return '';
|
|
|
|
$xml = @file_get_contents($template) ?: '';
|
|
if (!preg_match('/<WebUI>(.*?)<\/WebUI>/s', $xml, $m)) return '';
|
|
|
|
$url = trim($m[1]);
|
|
if (!$url) return '';
|
|
|
|
$url = str_replace('[IP]', vv_local_ip(), $url);
|
|
|
|
// [PORT:XXXX] → mapped host port
|
|
$url = preg_replace_callback('/\[PORT:(\d+)\]/', function($pm) use ($name, $portMap) {
|
|
return $portMap[$name][$pm[1]] ?? $pm[1];
|
|
}, $url);
|
|
|
|
return $url;
|
|
}
|
|
|
|
function vv_get_docker_folders(): array {
|
|
// Varaverk's own docker_folders.json is the primary store (see include/docker.php) —
|
|
// reading folder.view3's mirror directly here left this widget empty on any host
|
|
// without that optional third-party plugin installed.
|
|
$folderData = vv_dk_read_json();
|
|
|
|
// One docker ps call: names, status, port mappings
|
|
$raw = shell_exec("docker ps -a --format '{{.Names}}\t{{.Status}}\t{{.Ports}}' 2>/dev/null") ?? '';
|
|
$statusMap = [];
|
|
$portMap = [];
|
|
foreach (explode("\n", trim($raw)) as $line) {
|
|
$parts = explode("\t", $line, 3);
|
|
if (count($parts) < 2) continue;
|
|
[$cname, $status, $ports] = array_pad($parts, 3, '');
|
|
$cname = trim($cname);
|
|
if ($cname === '') continue;
|
|
$statusMap[$cname] = trim($status);
|
|
foreach (explode(',', $ports) as $entry) {
|
|
if (preg_match('/(\d+)->(\d+)\/tcp/', trim($entry), $pm)) {
|
|
$portMap[$cname][$pm[2]] = $pm[1]; // containerPort => hostPort
|
|
}
|
|
}
|
|
}
|
|
|
|
$folderContainerNames = [];
|
|
$folders = [];
|
|
|
|
foreach ($folderData as $id => $f) {
|
|
$containers = [];
|
|
foreach ($f['containers'] ?? [] as $cname) {
|
|
$folderContainerNames[] = $cname;
|
|
$status = $statusMap[$cname] ?? '';
|
|
$running = str_starts_with($status, 'Up');
|
|
$containers[] = [
|
|
'name' => $cname,
|
|
'running' => $running,
|
|
'status' => $status,
|
|
'webui' => vv_container_webui($cname, $portMap),
|
|
];
|
|
}
|
|
usort($containers, fn($a, $b) => $b['running'] <=> $a['running'] ?: strcmp($a['name'], $b['name']));
|
|
|
|
$folders[] = [
|
|
'id' => $id,
|
|
'name' => $f['name'] ?? 'Unnamed',
|
|
'icon' => $f['icon'] ?? '',
|
|
'containers' => $containers,
|
|
];
|
|
}
|
|
usort($folders, fn($a, $b) => strcmp($a['name'], $b['name']));
|
|
|
|
$ungrouped = [];
|
|
foreach ($statusMap as $cname => $status) {
|
|
if (in_array($cname, $folderContainerNames, true)) continue;
|
|
$running = str_starts_with($status, 'Up');
|
|
$ungrouped[] = [
|
|
'name' => $cname,
|
|
'running' => $running,
|
|
'status' => $status,
|
|
'webui' => vv_container_webui($cname, $portMap),
|
|
];
|
|
}
|
|
usort($ungrouped, fn($a, $b) => strcmp($a['name'], $b['name']));
|
|
|
|
return [
|
|
'available' => true,
|
|
'folders' => $folders,
|
|
'ungrouped' => $ungrouped,
|
|
];
|
|
}
|