Phase 1: resilient SSH handling + Push Conf button

partnership_onboard.sh (--phase1-only):
- Test if SSH already works first (BatchMode) — skip ssh-copy-id if yes
- If ssh-copy-id fails (no TTY in background): soft-fail, generate key locally,
  print pubkey for manual install, write HOST2_KEY_READY=true, run local setup
- Only skip conf push if SSH truly unavailable; otherwise proceeds normally
- Exit 0 with clear manual-step instructions instead of hard failure

include/partnership.php:
- Read HOST2_KEY_READY from setup.db; expose as key_ready on remote nodes

pages/partnership.php:
- Node card: amber "Key generated · install on HOST2 then Push Conf" badge
  when key_ready=true and phase=0
- "Push Conf (key installed)" button appears when key_ready=true — runs
  --phase1-only --skip-ssh (assumes user manually did ssh-copy-id)
- vvPtPushConf() top-level function
This commit is contained in:
Gmer4Lfe
2026-05-30 20:27:30 -04:00
parent 4aaa3c507a
commit 95fd38799d
3 changed files with 86 additions and 3 deletions
+3
View File
@@ -156,6 +156,8 @@ function vv_pt_nodes(): array {
$onboardPhase = $isMe ? null
: (($setupDb[$nodeIdUpper . '_PHASE2_DONE'] ?? '') === 'true' ? 2
: (($setupDb[$nodeIdUpper . '_PHASE1_DONE'] ?? '') === 'true' ? 1 : 0));
// key_ready: local key generated but not yet installed on HOST2 (SSH pending manual step)
$keyReady = !$isMe && ($setupDb[$nodeIdUpper . '_KEY_READY'] ?? '') === 'true';
// For self: local setup complete flag (set by partnership_manager --onboard --local-only)
$localDone = $isMe && ($setupDb[$nodeIdUpper . '_LOCAL_DONE'] ?? '') === 'true';
@@ -172,6 +174,7 @@ function vv_pt_nodes(): array {
'partnership' => $ptDb,
'system' => $system,
'onboard_phase' => $onboardPhase,
'key_ready' => $keyReady,
'local_done' => $localDone,
];
}
+19 -2
View File
@@ -106,6 +106,16 @@ function vvPtOnboard(btn) {
.finally(() => setTimeout(() => { btn.disabled = false; btn.textContent = '▶ Onboard (Mirror)'; }, 4000));
}
function vvPtPushConf(btn, hostId) {
if (!confirm(`Push conf to ${hostId}?\n\nAssumes SSH key is already installed on ${hostId}.\nSkips key generation/install, goes straight to conf push + local setup.`)) return;
btn.disabled = true;
btn.textContent = '⟳ Pushing…';
_vvPtRun('Partnership/partnership_onboard.sh', '--phase1-only --skip-ssh')
.then(d => { if (!d.ok) alert('Failed: ' + (d.error ?? 'Unknown error')); })
.catch(e => alert('Error: ' + e))
.finally(() => setTimeout(() => { btn.disabled = false; btn.textContent = '▶ Push Conf (key installed)'; }, 4000));
}
function vvPtLocalSetup(btn) {
if (!confirm('Complete HOST1 local setup?\n\nRuns FolderView3 integration and marks HOST1 as locally ready.\nDoes not require HOST2 to be online.')) return;
btn.disabled = true;
@@ -245,7 +255,8 @@ function _nodeCard(node) {
: '')
: (phase === 2 ? '' :
phase === 1 ? `<div style="font-size:10px;color:#ff9800;margin-bottom:6px;padding:2px 6px;background:#1a1200;border:1px solid #3a2800;border-radius:3px;">⏳ SSH ready · awaiting onboard</div>` :
`<div style="font-size:10px;color:#555;margin-bottom:6px;padding:2px 6px;background:#111;border:1px solid #222;border-radius:3px;">○ Not yet provisioned</div>`);
node.key_ready ? `<div style="font-size:10px;color:#ff9800;margin-bottom:6px;padding:2px 6px;background:#1a1200;border:1px solid #3a2800;border-radius:3px;">🔑 Key generated · install on HOST2 then Push Conf</div>` :
`<div style="font-size:10px;color:#555;margin-bottom:6px;padding:2px 6px;background:#111;border:1px solid #222;border-radius:3px;">○ Not yet provisioned</div>`);
let body = '';
@@ -328,9 +339,15 @@ function _renderActions(nodes, cfg) {
if (phase === 0) {
// Not yet provisioned — offer Phase 1 (safe before HOST2 has Varaverk)
html += `<button class="vv-pt-action-btn run" onclick="vvPtPhase1(this, '${remote.id}')"
title="SSH key exchange + push master.conf to ${remote.hostname}. Safe to run before ${remote.id} has Varaverk installed.">
title="Generate SSH key + install on ${remote.hostname} + push conf. First run needs terminal access to ${remote.hostname} for password — subsequent runs auto-detect the installed key.">
▶ Phase 1: SSH + Conf Push
</button>`;
if (remote.key_ready) {
html += `<button class="vv-pt-action-btn run" onclick="vvPtPushConf(this, '${remote.id}')"
title="Key is already installed on ${remote.hostname} — push conf files and complete Phase 1 without re-running SSH setup">
▶ Push Conf (key installed)
</button>`;
}
html += `<button class="vv-pt-action-btn info" onclick="vvPtOnboard(this)"
title="Run full onboard (Phase 1 + 2 together) — requires ${remote.id} to already have Varaverk installed"
style="opacity:.5;">