HOST1 completes local onboard independently during Phase 1

partnership_manager.sh:
- --local-only flag for --onboard: skips remote pre-flight, WebUI reconfig,
  state push; runs FolderView3 folder creation + writes HOST1_LOCAL_DONE=true
  to setup.db + pushes it; exits without writing ACTIVE (partnership not yet
  established until Phase 2)

partnership_onboard.sh:
- Phase 1 exit now runs partnership_manager.sh --onboard --local-only after
  SSH + conf push, so HOST1 is fully configured on its own side before Phase 2

include/partnership.php:
- vv_pt_nodes() reads HOST1_LOCAL_DONE from setup.db; exposes as local_done
  on the self node (null for remote nodes)

pages/partnership.php:
- Self node card shows green "Local setup complete · waiting for partner"
  badge when local_done=true
- Actions: "Complete HOST1 Setup" button appears when HOST1 hasn't run local
  setup yet but HOST2 is already at phase 1 — lets user trigger it manually
- vvPtLocalSetup() top-level function calls partnership_manager.sh via run.php
This commit is contained in:
Gmer4Lfe
2026-05-30 19:55:56 -04:00
parent b59b94099a
commit d1ee880586
4 changed files with 104 additions and 14 deletions
+36 -5
View File
@@ -106,6 +106,16 @@ function vvPtOnboard(btn) {
.finally(() => setTimeout(() => { btn.disabled = false; btn.textContent = '▶ Onboard (Mirror)'; }, 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;
btn.textContent = '⟳ Running…';
_vvPtRun('Partnership/partnership_manager.sh', '--onboard --local-only')
.then(d => { if (!d.ok) alert('Failed: ' + (d.error ?? 'Unknown error')); })
.catch(e => alert('Error: ' + e))
.finally(() => setTimeout(() => { btn.disabled = false; btn.textContent = '▶ Complete HOST1 Setup'; }, 4000));
}
function vvPtCancel(btn, hostId) {
if (!confirm(`Cancel Phase 1 for ${hostId}?\n\nThis will:\n• Remove HOST1's SSH key from ${hostId}'s authorized_keys\n• Delete the local key pair\n• Reset phase state on both hosts\n\nContinue?`)) return;
btn.disabled = true;
@@ -227,12 +237,15 @@ function _nodeCard(node) {
const [ptCol, ptLbl] = ptStates[ptState] || ['#444', ptState || '—'];
const ptUpdated = pt.updated ? _relTime(parseInt(pt.updated)) : null;
// Onboard phase (null = self, 0 = not started, 1 = SSH done, 2 = fully onboarded)
// Onboard phase badge (remote nodes) or local-done badge (self)
const phase = node.onboard_phase;
const phaseHtml = phase === null ? '' :
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 HOST2 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>`;
const phaseHtml = node.is_me
? (node.local_done
? `<div style="font-size:10px;color:#4caf50;margin-bottom:6px;padding:2px 6px;background:#0a1a0a;border:1px solid #2a5a2a;border-radius:3px;">✓ Local setup complete · waiting for partner</div>`
: '')
: (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>`);
let body = '';
@@ -286,6 +299,24 @@ function _renderActions(nodes, cfg) {
let html = '';
// ── HOST1 local setup button (owner only, before local_done) ──────────────
const selfNode = nodes.find(n => n.is_me);
if (isOwner && selfNode && !selfNode.local_done && remotes.some(r => (r.onboard_phase ?? 0) >= 1)) {
html += `<div style="margin-bottom:12px;padding-bottom:12px;border-bottom:1px solid #1e1e1e;">
<div style="font-size:11px;color:#555;margin-bottom:6px;">${selfNode.id} — ${selfNode.hostname} <span style="color:#333;">(this server)</span></div>
<div class="vv-pt-actions">
<button class="vv-pt-action-btn run" onclick="vvPtLocalSetup(this)"
title="Run HOST1-local onboard steps (FolderView3, setup state) without needing HOST2 to be present">
▶ Complete HOST1 Setup
</button>
</div>
<div style="font-size:10px;color:#444;margin-top:6px;">
Configures HOST1's local side independently — FolderView3 folder, state flags.
Does not require HOST2 to be online.
</div>
</div>`;
}
// ── Per-partner onboard phase actions (owner only) ─────────────────────────
if (isOwner && hasPartner) {
for (const remote of remotes) {