Watchdog and Monitor looked the partner up by exact key, and the remote probe passed a quote to cut as a filename

This commit is contained in:
Gmer4Lfe
2026-08-22 00:59:24 -04:00
parent 0f228020ef
commit a89b704fa1
3 changed files with 31 additions and 10 deletions
+6 -1
View File
@@ -1,5 +1,6 @@
<?php
require_once __DIR__ . '/common.php';
require_once __DIR__ . '/partnership.php'; // vv_pt_peer_match() — tailnet name vs conf hostname
// ═══════════════════════════════════════════════════════════════════════════════════════════════
// PURPOSE
@@ -94,7 +95,11 @@ function vv_partner_state(): array {
if (!$hostname) continue;
$isMe = ($id === $myHostId);
$isOwner = strcasecmp($id, $vars['PARTNERSHIP_OWNER_HOST'] ?? '') === 0;
$online = $isMe ? true : ($tsPeers[strtolower($hostname)] ?? null);
// Exact-key lookup, until now. The tailnet name and the conf hostname differ by one
// character on this mesh, so the partner card reported a host that was up as unknown.
// Same unambiguous-prefix rule as everywhere else — one candidate or none.
$peerKey = $isMe ? null : vv_pt_peer_match(array_keys($tsPeers), $hostname);
$online = $isMe ? true : ($peerKey !== null ? $tsPeers[$peerKey] : null);
$onboardPhase = $isMe ? null
: (($setupDb[$id . '_PHASE2_DONE'] ?? '') === 'true' ? 2
: (($setupDb[$id . '_PHASE1_DONE'] ?? '') === 'true' ? 1 : 0));
+14 -5
View File
@@ -199,15 +199,24 @@ function vv_pt_ts_peers(): array {
// none — server1 must never resolve to server10 because it happens to share a prefix, and this
// is never similarity scoring. Same rule as vv_resolve_tailscale_ip(), which applies it to
// `tailscale status` text rather than to the parsed peer array.
function vv_pt_peer_lookup(array $tsPeers, string $hostname): array {
// The matching rule itself, separated from the value it looks up, because the peer map is not
// always the same shape: include/monitor.php keys hostname => bool while everything else keys
// hostname => array. Four call sites had each written their own exact-key lookup and all four
// rendered this mesh's partner as dark. Returns the matching KEY, or null.
function vv_pt_peer_match(array $peerNames, string $hostname): ?string {
$label = strtolower($hostname);
if (isset($tsPeers[$label])) return $tsPeers[$label];
if (in_array($label, $peerNames, true)) return $label;
$cand = [];
foreach ($tsPeers as $peerName => $peer) {
if (str_starts_with($peerName, $label) || str_starts_with($label, $peerName)) $cand[] = $peer;
foreach ($peerNames as $peerName) {
if (str_starts_with($peerName, $label) || str_starts_with($label, $peerName)) $cand[] = $peerName;
}
return count($cand) === 1 ? $cand[0] : ['online' => null, 'active' => false, 'ip' => null];
return count($cand) === 1 ? $cand[0] : null;
}
function vv_pt_peer_lookup(array $tsPeers, string $hostname): array {
$key = vv_pt_peer_match(array_keys($tsPeers), $hostname);
return $key !== null ? $tsPeers[$key] : ['online' => null, 'active' => false, 'ip' => null];
}
// ── SSH helper — run a single command on a remote host ────────────────────────
+11 -4
View File
@@ -366,8 +366,12 @@ function vv_wd_remote_data(string $ip, string $sshKey, string $restartLogPath):
. 'sf="$sd/data/state"; [ -d "$sf" ] || sf="$sd/State_Files"; '
. 'db="$sd/data/db"; [ -d "$db" ] || db="$sd/data"; '
. "printf 'UPTIME:%s\nLOAD:%s\nCORES:%s\nDAEMON:%s\nOOM:%s\nBASELINECOUNT:%s\nBASELINEAGE:%s\n---MEMINFO---\n%s\n---RW---\n%s\n---DOCK---\n%s\n---SKIP---\n%s\n---SYS---\n%s\n---REBOOT---\n%s\n---RESTART---\n%s\n---STORAGE---\n%s\n---NETWORK---\n%s\n' "
. '"$(cat /proc/uptime|cut -d\" \" -f1)" '
. '"$(cat /proc/loadavg|cut -d\" \" -f1)" '
// awk, not `cut -d" "`. This is a PHP SINGLE-quoted string, which does not process \" —
// so the shell received a literal backslash-quote, cut read the quote as a FILENAME
// ("cut: '\"': No such file or directory"), and UPTIME and LOAD came back empty while every
// quote-free field beside them parsed fine. awk needs no delimiter argument at all.
. '"$(awk \'{print $1}\' /proc/uptime)" '
. '"$(awk \'{print $1}\' /proc/loadavg)" '
. '"$(nproc)" '
. '"$(docker info >/dev/null 2>&1 && echo ok || echo err)" '
. '"$(cat "$sf/system_watchdog_oom.db" 2>/dev/null||echo 0)" '
@@ -550,8 +554,11 @@ function vv_wd_all(): array {
$nodes = [];
foreach ($hosts as $slot => $hostname) {
$isMe = ($slot === $currentHost || $currentHost === 'unknown');
$tsLabel = strtolower($hostname);
$ts = $tsPeers[$tsLabel] ?? ['online' => null, 'active' => false, 'ip' => null];
// Exact-key only, until now — the third copy of that lookup in this codebase and the
// third to render a live partner as dark. This mesh's conf name and tailnet name differ
// by one character, so HOST2 missed every time and its whole card read UNREACHABLE /
// "No data" while HOST2's own page showed the same watchdogs reporting OK.
$ts = vv_pt_peer_lookup($tsPeers, $hostname);
$ip = $ts['ip'] ?? null;
$raw = vv_read_conf_raw($slot . '.conf');