'identity', 'label' => 'Server identity', 'ok' => !empty($host1), 'detail' => $host1 ? "HOST1: $host1" : 'HOST1 blank in master.conf', ]; // ── Host conf ───────────────────────────────────────────────────────────────── $confExists = $hostId !== 'unknown' && file_exists(CONF_DIR . '/' . $hostId . '.conf'); $items[] = [ 'id' => 'host_conf', 'label' => 'Host configuration', 'ok' => $confExists, 'detail' => $confExists ? "$hostId.conf present" : ($hostId === 'unknown' ? 'Server not yet identified' : "$hostId.conf missing"), ]; // ── Unraid API key ───────────────────────────────────────────────────────────── $apiKey = trim(vv_parse_conf_scalar($confRaw, $hostIdUp . '_UNRAID_API_KEY')); $items[] = [ 'id' => 'api_key', 'label' => 'Unraid API key', 'ok' => !empty($apiKey), 'detail' => $apiKey ? 'Key present' : 'Not set', 'action' => $apiKey ? null : 'create_key', ]; // ── SSH key ──────────────────────────────────────────────────────────────────── $sshPath = trim(vv_parse_conf_scalar($confRaw, $hostIdUp . '_SSH_KEY')); $sshOk = $sshPath && file_exists($sshPath); $items[] = [ 'id' => 'ssh_key', 'label' => 'SSH key', 'ok' => $sshOk, 'detail' => $sshOk ? basename($sshPath) : ($sshPath ? "Path set but file missing: $sshPath" : 'No key path in host.conf'), 'action' => $sshOk ? null : 'ssh_setup', ]; // ── Auto-populate (any service key or container detected) ────────────────────── $populated = false; foreach (['_RADARR_API_KEY','_SONARR_API_KEY','_LIDARR_API_KEY','_EMBY_CONTAINER','_JELLYFIN_CONTAINER'] as $f) { if (trim(vv_parse_conf_scalar($confRaw, $hostIdUp . $f)) !== '') { $populated = true; break; } } $items[] = [ 'id' => 'populated', 'label' => 'Auto-populate', 'ok' => $populated, 'detail' => $populated ? 'Services detected in host.conf' : 'No services detected yet', 'action' => $populated ? null : 'run_populate', ]; // ── master.conf pull (partner servers only) ─────────────────────────────────────────────────── if ($hostId !== 'host1' && $hostId !== 'unknown') { $state = vv_setup_state_read(); $pulled = !empty($state['master_conf_pulled']); $items[] = [ 'id' => 'master_conf', 'label' => 'master.conf', 'ok' => $pulled, 'detail' => $pulled ? 'Synced from HOST1' : ($host1 ? "Not yet pulled from $host1" : 'HOST1 hostname not set in master.conf'), 'action' => (!$pulled && $host1) ? 'pull_master' : null, ]; } // ── Partnership (only if a partner is configured) ────────────────────────────── preg_match('/^\s*HOST2\s*=\s*"([^"]*)"/m', $master, $m2); $host2 = trim($m2[1] ?? ''); if (!empty($host2)) { $state = vv_setup_state_read(); $p1done = !empty($state['HOST2_PHASE1_DONE']) || !empty($state['host2_phase1_done']); $p2done = !empty($state['HOST2_PHASE2_DONE']) || !empty($state['host2_phase2_done']); $items[] = [ 'id' => 'partnership', 'label' => 'Partnership', 'ok' => $p1done && $p2done, 'detail' => ($p1done && $p2done) ? "Active with $host2" : ($p1done ? "Phase 1 done — waiting for HOST2 to complete" : "Not started — run partnership_onboard.sh"), 'action' => (!$p1done) ? 'onboard' : null, ]; } $allOk = !in_array(false, array_column($items, 'ok'), true); echo json_encode(['ok' => true, 'complete' => $allOk, 'host_id' => $hostId, 'items' => $items]);