Media Stack called every node local, and a host whose watchdogs never ran reported all clear
This commit is contained in:
@@ -460,6 +460,12 @@ function vv_arrs_all(): array {
|
|||||||
$cacheFile = VV_CACHE_DIR . '/arrs_remote_' . $h . '.json';
|
$cacheFile = VV_CACHE_DIR . '/arrs_remote_' . $h . '.json';
|
||||||
if (file_exists($cacheFile)) {
|
if (file_exists($cacheFile)) {
|
||||||
$node = json_decode(file_get_contents($cacheFile), true) ?: [];
|
$node = json_decode(file_get_contents($cacheFile), true) ?: [];
|
||||||
|
// The cache file was written by vv_arrs_local_node() ON THAT HOST, where the node is by
|
||||||
|
// definition local — so it arrives claiming 'local' => true and, re-emitted verbatim,
|
||||||
|
// made every node on every host report as this one. Ownership is decided here, by who
|
||||||
|
// is reading the file, not by who wrote it.
|
||||||
|
$node['local'] = false;
|
||||||
|
$node['host'] = $h;
|
||||||
$node['cached'] = true;
|
$node['cached'] = true;
|
||||||
$node['cache_age'] = time() - (int)filemtime($cacheFile);
|
$node['cache_age'] = time() - (int)filemtime($cacheFile);
|
||||||
$result[] = $node;
|
$result[] = $node;
|
||||||
|
|||||||
@@ -310,8 +310,27 @@ function vv_watchdog_summary(): array {
|
|||||||
&& $rwLevel === 0 && $daemonStrikes === 0 && $oomCount === 0 && $reboots === 0
|
&& $rwLevel === 0 && $daemonStrikes === 0 && $oomCount === 0 && $reboots === 0
|
||||||
&& $npmStrikes === 0 && $nicState === 'up' && $sshdOk;
|
&& $npmStrikes === 0 && $nicState === 'up' && $sshdOk;
|
||||||
|
|
||||||
|
// "No strikes" and "never ran" are not the same fact. Every strike file read above defaults an
|
||||||
|
// absent file to zero, so a host where the watchdogs have never executed reports exactly like
|
||||||
|
// one they just swept clean — a green card standing in for no information at all. HOST2 showed
|
||||||
|
// that green for four days on a STATE_DIR holding no watchdog file whatsoever, because its
|
||||||
|
// schedule.json never had the orchestrator enabled.
|
||||||
|
//
|
||||||
|
// $healthy stays a verdict about strikes; the caller is told separately whether there was
|
||||||
|
// anything to form a verdict from.
|
||||||
|
$lastRun = 0;
|
||||||
|
foreach ([
|
||||||
|
'watchdog_orch_hb.count', 'container_watchdog_state.db', 'resource_watchdog_state.db',
|
||||||
|
'system_watchdog_state.db', 'storage_watchdog_state.db', 'network_watchdog_state.db',
|
||||||
|
] as $f) {
|
||||||
|
$p = STATE_DIR . '/' . $f;
|
||||||
|
if (is_file($p)) $lastRun = max($lastRun, (int)@filemtime($p));
|
||||||
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'healthy' => $healthy,
|
'healthy' => $healthy,
|
||||||
|
'last_run' => $lastRun ?: null,
|
||||||
|
'never_ran' => $lastRun === 0,
|
||||||
'ctr_strikes' => $ctrStrikes,
|
'ctr_strikes' => $ctrStrikes,
|
||||||
'rw_level' => $rwLevel,
|
'rw_level' => $rwLevel,
|
||||||
'rw_paused' => array_values(array_filter(explode(',', $rw['rm_paused_containers'] ?? ''))),
|
'rw_paused' => array_values(array_filter(explode(',', $rw['rm_paused_containers'] ?? ''))),
|
||||||
|
|||||||
@@ -1476,8 +1476,16 @@ function vvPollMonitor(live) {
|
|||||||
const issueCount = ctrNames.length + stabNames.length + storIssues
|
const issueCount = ctrNames.length + stabNames.length + storIssues
|
||||||
+ (daemonHit ? 1 : 0) + (oom > 0 ? 1 : 0)
|
+ (daemonHit ? 1 : 0) + (oom > 0 ? 1 : 0)
|
||||||
+ (reboots > 0 ? 1 : 0) + (npmStrikes > 0 ? 1 : 0);
|
+ (reboots > 0 ? 1 : 0) + (npmStrikes > 0 ? 1 : 0);
|
||||||
const bannerCls = healthy ? 'vv-banner-ok' : (reboots || oom || daemonHit ? 'vv-banner-err' : 'vv-banner-warn');
|
// A host whose watchdogs have never executed has no verdict to report. Every strike set
|
||||||
const bannerTxt = healthy ? '✓ All clear' : `⚠ ${issueCount} issue${issueCount !== 1 ? 's' : ''}`;
|
// reads absent state as zero, so "All clear" here would be standing in for no data —
|
||||||
|
// which is the failure this card's own header warns about. Said plainly instead.
|
||||||
|
const neverRan = wd.never_ran === true;
|
||||||
|
const bannerCls = neverRan ? 'vv-banner-warn'
|
||||||
|
: healthy ? 'vv-banner-ok'
|
||||||
|
: (reboots || oom || daemonHit ? 'vv-banner-err' : 'vv-banner-warn');
|
||||||
|
const bannerTxt = neverRan ? '○ Never run on this host'
|
||||||
|
: healthy ? '✓ All clear'
|
||||||
|
: `⚠ ${issueCount} issue${issueCount !== 1 ? 's' : ''}`;
|
||||||
|
|
||||||
let html = `<div class="vv-banner ${bannerCls}">${bannerTxt}`;
|
let html = `<div class="vv-banner ${bannerCls}">${bannerTxt}`;
|
||||||
if (reboots > 0) html += `<span style="font-size:10px;">${reboots} reboot${reboots !== 1 ? 's' : ''}/12h</span>`;
|
if (reboots > 0) html += `<span style="font-size:10px;">${reboots} reboot${reboots !== 1 ? 's' : ''}/12h</span>`;
|
||||||
@@ -1601,7 +1609,7 @@ function vvPollMonitor(live) {
|
|||||||
const wdCard = document.getElementById('vv-watchdog-card');
|
const wdCard = document.getElementById('vv-watchdog-card');
|
||||||
if (wdCard) {
|
if (wdCard) {
|
||||||
wdCard.classList.remove('vv-accent-ok','vv-accent-warn','vv-accent-err');
|
wdCard.classList.remove('vv-accent-ok','vv-accent-warn','vv-accent-err');
|
||||||
if (healthy) wdCard.classList.add('vv-accent-ok');
|
if (healthy && !neverRan) wdCard.classList.add('vv-accent-ok');
|
||||||
else if (reboots > 0 || oom > 0 || daemonHit) wdCard.classList.add('vv-accent-err');
|
else if (reboots > 0 || oom > 0 || daemonHit) wdCard.classList.add('vv-accent-err');
|
||||||
else wdCard.classList.add('vv-accent-warn');
|
else wdCard.classList.add('vv-accent-warn');
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user