From a55a3afad58246ebbe7edc72ff00ecf7afee79f3 Mon Sep 17 00:00:00 2001 From: Gmer4Lfe Date: Wed, 3 Jun 2026 18:20:55 -0400 Subject: [PATCH] Remote cache: extend to monitor stats; vv_local_host_stats(), 2h bg refresh covers monitor+arrs pages --- Plugin/unraid/include/common.php | 12 +++++++ Plugin/unraid/include/unraid_api.php | 51 ++++++++++++++++++++++++++++ Tools/remote_arr_cache_writer.sh | 38 +++++++++++++++------ 3 files changed, 91 insertions(+), 10 deletions(-) diff --git a/Plugin/unraid/include/common.php b/Plugin/unraid/include/common.php index d18daeb..154bc69 100644 --- a/Plugin/unraid/include/common.php +++ b/Plugin/unraid/include/common.php @@ -613,6 +613,18 @@ function vv_remote_hosts_stats(): array { $results = []; foreach ($hostIds as $id) { if (strtolower($id) === strtolower($myHost)) continue; + // Background cache written by remote_arr_cache_writer.sh every 2h — use it if present. + $bgCache = VV_CACHE_DIR . '/monitor_remote_' . strtolower($id) . '.json'; + if (file_exists($bgCache)) { + $cached = json_decode(file_get_contents($bgCache), true); + if ($cached) { + $cached['cache_age'] = time() - (int)filemtime($bgCache); + $results[$id] = $cached; + continue; + } + } + + // No background cache yet — fall back to live call (uses 30s inline cache). $key = $vars[strtoupper($id) . '_UNRAID_API_KEY'] ?? ''; if (!$key) { $results[$id] = ['available' => false, 'no_api_key' => true, diff --git a/Plugin/unraid/include/unraid_api.php b/Plugin/unraid/include/unraid_api.php index 1762b7b..cef0a81 100644 --- a/Plugin/unraid/include/unraid_api.php +++ b/Plugin/unraid/include/unraid_api.php @@ -187,6 +187,57 @@ function vv_api_node_metrics(?array $d): array { ]; } +// ── Local host stats snapshot — same shape as one entry from vv_remote_hosts_stats() ───────── +// Called locally and via SSH by remote_arr_cache_writer.sh on remote hosts. +function vv_local_host_stats(): array { + $host = vv_detect_host(); + $myId = strtoupper($host); + $vars = vv_conf_vars(); + $name = $vars[$myId] ?? gethostname(); + + $api = vv_api_data(); + $metrics = vv_api_node_metrics($api); + + if (!$api) { + return ['available' => false, 'host_id' => $myId, 'hostname' => $name, + 'no_api_key' => _vv_api_key_missing()]; + } + + $os = $api['info']['os'] ?? []; + $cpu = $api['info']['cpu'] ?? []; + $mem = $api['metrics']['memory'] ?? []; + + $memPct = round((float)($mem['percentTotal'] ?? 0)); + if ($memPct === 0) { + $tot = (float)($mem['total'] ?? 0); $avail = (float)($mem['available'] ?? 0); + $memPct = $tot > 0 ? (int)round(($tot - $avail) / $tot * 100) : 0; + } + $memTotalGb = isset($mem['total']) ? _vv_api_bytes_to_gb((float)$mem['total']) : 0; + + $uptimeRaw = $os['uptime'] ?? ''; + if (is_numeric($uptimeRaw)) { + $s = (int)$uptimeRaw; + $d = intdiv($s, 86400); $h = intdiv($s % 86400, 3600); $m = intdiv($s % 3600, 60); + $uptime = ($d ? "{$d}d " : '') . ($h ? "{$h}h " : '') . "{$m}m"; + } else { + $s = 0; $uptime = $uptimeRaw ?: '—'; + } + + return array_merge([ + 'available' => true, + 'host_id' => $myId, + 'hostname' => $os['hostname'] ?? $name, + 'version' => $os['release'] ?? '', + 'uptime' => $uptime, + 'uptime_sec' => $s, + 'cpu_load' => $metrics['cpu_pct'] ?? 0, + 'cpu_threads' => (int)($cpu['threads'] ?? 0), + 'mem_total_gb' => $memTotalGb, + 'mem_used_pct' => $memPct, + 'array_state' => $api['array']['state'] ?? 'UNKNOWN', + ], $metrics); +} + // ── Confirmed schema (Unraid 7.3, introspected 2026-05-31) ─────────────────── // Adding a new host: add HOSTn="hostname" to master.conf and HOSTn_UNRAID_API_KEY // to hostn.conf, then run Deployment/deploy.sh. No schema work needed. diff --git a/Tools/remote_arr_cache_writer.sh b/Tools/remote_arr_cache_writer.sh index 3041a40..0458784 100755 --- a/Tools/remote_arr_cache_writer.sh +++ b/Tools/remote_arr_cache_writer.sh @@ -81,38 +81,56 @@ for host_var in HOST1 HOST2 HOST3 HOST4 HOST5 HOST6 HOST7 HOST8; do fi log " $host_var: resolved $hostname → $REMOTE_IP" - # SSH and call vv_arrs_local_node() on the remote + # Single SSH connection — fetch arrs + monitor stats together RESULT=$(ssh -i "$SSH_KEY" \ -o ConnectTimeout=10 \ -o StrictHostKeyChecking=no \ -o BatchMode=yes \ "root@${REMOTE_IP}" \ - "php -r \"require_once '/usr/local/emhttp/plugins/varaverk/include/arrs.php'; echo json_encode(vv_arrs_local_node());\"" \ - 2>/dev/null) + "php -r \" + require_once '/usr/local/emhttp/plugins/varaverk/include/arrs.php'; + require_once '/usr/local/emhttp/plugins/varaverk/include/unraid_api.php'; + echo json_encode([ + 'arrs' => vv_arrs_local_node(), + 'monitor' => vv_local_host_stats(), + ]); + \"" 2>/dev/null) if [[ -z "$RESULT" ]]; then - warn " $host_var: empty response from SSH — skipping" + warn " $host_var: empty SSH response — skipping" (( FETCH_FAIL++ )) continue fi - # Validate JSON + # Validate combined JSON if ! echo "$RESULT" | php -r " \$d = json_decode(file_get_contents('php://stdin'), true); - exit(!is_array(\$d) || !isset(\$d['arrs']) ? 1 : 0); + exit(!is_array(\$d) || !isset(\$d['arrs'], \$d['monitor']) ? 1 : 0); " 2>/dev/null; then - warn " $host_var: invalid or unexpected JSON — skipping" + warn " $host_var: invalid JSON — skipping" log " Response: ${RESULT:0:200}" (( FETCH_FAIL++ )) continue fi - echo "$RESULT" > "$cache_file" + # Save arr cache + echo "$RESULT" | php -r " + \$d = json_decode(file_get_contents('php://stdin'), true); + file_put_contents('$cache_file', json_encode(\$d['arrs'])); + " 2>/dev/null + + # Save monitor cache + MONITOR_CACHE="/tmp/vv_cache/monitor_remote_${host_id}.json" + echo "$RESULT" | php -r " + \$d = json_decode(file_get_contents('php://stdin'), true); + file_put_contents('$MONITOR_CACHE', json_encode(\$d['monitor'])); + " 2>/dev/null + CACHED_TYPES=$(echo "$RESULT" | php -r " \$d = json_decode(file_get_contents('php://stdin'), true); - echo implode(', ', array_column(\$d['arrs'] ?? [], 'type')); + echo implode(', ', array_column(\$d['arrs']['arrs'] ?? [], 'type')); " 2>/dev/null) - echo " $host_var: cached ✅ — ${CACHED_TYPES:-no arrs}" + echo " $host_var: arrs [${CACHED_TYPES:-none}] + monitor stats cached ✅" (( FETCH_OK++ )) done