From 0121462576dea6667d8a2c8a7b4f278073596f24 Mon Sep 17 00:00:00 2001 From: Gmer4Lfe Date: Sat, 30 May 2026 16:01:44 -0400 Subject: [PATCH] Graceful degradation before partnership/SSH is set up MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix 1 — Monitor partner card (common.php + monitor.php): vv_remote_hosts_stats() no longer skips hosts with no API key. Returns no_api_key:true entry instead. Monitor JS renders "API key not configured — complete Onboard to enable" instead of a blank space. Fix 2 — rawconf push not alarming pre-onboard (config.php + scheduler.php): Probe failures (Tailscale not found, plugin not installed) now carry ready:false. JS treats ready:false results silently — button shows "✓ Saved" not "push failed: HOST2" before SSH is set up. Only genuine post-onboard failures (ready not false) show as errors. Fix 3 — Partnership Onboard button (partnership.php): Disabled with tooltip when no partner hostname is in master.conf. When partner configured but not onboarded, adds explanation note: "Onboard will generate your SSH key, exchange it with the partner..." No partner configured: "Edit master.conf and set HOST2." --- Plugin/unraid/include/common.php | 6 +++++- Plugin/unraid/include/config.php | 4 ++-- Plugin/unraid/pages/monitor.php | 2 ++ Plugin/unraid/pages/partnership.php | 20 ++++++++++++++++++-- Plugin/unraid/pages/scheduler.php | 15 +++++++++------ 5 files changed, 36 insertions(+), 11 deletions(-) diff --git a/Plugin/unraid/include/common.php b/Plugin/unraid/include/common.php index 814b809..7dcf3ed 100644 --- a/Plugin/unraid/include/common.php +++ b/Plugin/unraid/include/common.php @@ -572,7 +572,11 @@ function vv_remote_hosts_stats(): array { foreach ($hostIds as $id) { if (strtolower($id) === strtolower($myHost)) continue; $key = $vars[strtoupper($id) . '_UNRAID_API_KEY'] ?? ''; - if (!$key) continue; + if (!$key) { + $results[$id] = ['available' => false, 'no_api_key' => true, + 'host_id' => $id, 'hostname' => $vars[$id]]; + continue; + } $cacheFile = "/tmp/vv_remote_{$id}.json"; if (file_exists($cacheFile) && (time() - filemtime($cacheFile)) < 30) { diff --git a/Plugin/unraid/include/config.php b/Plugin/unraid/include/config.php index 4826720..f8bce97 100644 --- a/Plugin/unraid/include/config.php +++ b/Plugin/unraid/include/config.php @@ -84,7 +84,7 @@ function vv_push_master_conf(): array { $hostname = trim($m[2][$i]); $ip = vv_resolve_tailscale_ip($hostname); if (!$ip) { - $results[] = ['host' => $hostKey, 'ok' => false, 'error' => 'Tailscale IP not found']; + $results[] = ['host' => $hostKey, 'ok' => false, 'ready' => false, 'error' => 'Tailscale IP not found']; continue; } @@ -102,7 +102,7 @@ function vv_push_master_conf(): array { ) ?: ''); if ($probe === '') { - $results[] = ['host' => $hostKey, 'ok' => false, + $results[] = ['host' => $hostKey, 'ok' => false, 'ready' => false, 'error' => 'plugin not installed, dir missing, or master.conf absent — skipped']; continue; } diff --git a/Plugin/unraid/pages/monitor.php b/Plugin/unraid/pages/monitor.php index fd2d238..ddd21b2 100644 --- a/Plugin/unraid/pages/monitor.php +++ b/Plugin/unraid/pages/monitor.php @@ -579,6 +579,8 @@ function vvPollMonitor() { Uptime ${uptimeStr} ${verWarn}`; + } else if (rs && rs.no_api_key) { + statsHtml = `
API key not configured — complete Onboard to enable
`; } else if (rs && !rs.available) { statsHtml = `
API unreachable
`; } diff --git a/Plugin/unraid/pages/partnership.php b/Plugin/unraid/pages/partnership.php index 2a89d46..f4c4472 100644 --- a/Plugin/unraid/pages/partnership.php +++ b/Plugin/unraid/pages/partnership.php @@ -207,11 +207,15 @@ function _renderActions(nodes, cfg) { const remoteOpts = remotes.map(n => ``).join(''); + const hasPartner = remotes.length > 0 && remotes.some(n => n.hostname); + let html = '
'; - // Onboard + // Onboard — disabled until a partner hostname is configured in master.conf html += ``; @@ -223,6 +227,18 @@ function _renderActions(nodes, cfg) { html += '
'; + // Contextual note under actions + if (!hasPartner) { + html += `
+ No partner hostname configured. Edit master.conf (Scheduler tab) and set HOST2. +
`; + } else if (!cfg.enabled) { + html += `
+ Onboard will generate your SSH key, exchange it with the partner, and establish the partnership. + Run on the mirror (HOST2) first, then on the owner (HOST1). +
`; + } + // Transfer — show manual command, too destructive to one-click if (cfg.enabled && isOwner) { const confirmStr = 'i-understand-this-transfers-ownership'; diff --git a/Plugin/unraid/pages/scheduler.php b/Plugin/unraid/pages/scheduler.php index 90b8d12..2a32fda 100644 --- a/Plugin/unraid/pages/scheduler.php +++ b/Plugin/unraid/pages/scheduler.php @@ -2635,13 +2635,16 @@ function vvSaveRawConf() { } // Normal save: show push status - const push = d.push ?? []; - if (push.length === 0) { - btn.textContent = '✓ Saved'; - } else if (push.every(p => p.ok)) { - btn.textContent = '✓ Saved · synced to ' + push.map(p => p.host).join(', '); + // ready:false = partner not set up yet (pre-onboard) — treat as silent, not an error + const push = d.push ?? []; + const synced = push.filter(p => p.ok); + const realFailed = push.filter(p => !p.ok && p.ready !== false); + if (realFailed.length > 0) { + btn.textContent = '✓ Saved · push failed: ' + realFailed.map(p => p.host).join(', '); + } else if (synced.length > 0) { + btn.textContent = '✓ Saved · synced to ' + synced.map(p => p.host).join(', '); } else { - btn.textContent = '✓ Saved · push failed: ' + push.filter(p => !p.ok).map(p => p.host).join(', '); + btn.textContent = '✓ Saved'; } setTimeout(() => { btn.textContent = 'Save Conf'; }, 3500); })