Skip to content

Add a real SSH-reachability signal to fc/ch's List() - #1105

Merged
cdalar merged 1 commit into
mainfrom
feat/ssh-ready-probe
Sep 9, 2026
Merged

cdalar merged 1 commit into
mainfrom
feat/ssh-ready-probe

Conversation

@cdalar

@cdalar cdalar commented Sep 9, 2026

Copy link
Copy Markdown
Owner

Summary

  • Status only ever reflected "the VMM process is alive" (set at Deploy time, checked afterward via isAlive's process-liveness check), never "the guest OS actually finished booting" -- for a Windows/ch guest, that gap can be minutes wide, but any consumer polling onctl ls mid-boot has no way to tell a genuinely usable VM apart from one still booting.
  • List() now also TCP-probes each running VM's SSH port (300ms timeout, concurrently across every not-yet-confirmed VM) and reports the result as a new Vm.SSHReady field, persisting true once confirmed so it's never re-probed again.
  • Deliberately a TCP-connect check, not a full SSH auth handshake: reusing WaitForSSH's handshake would need the operator's private key material threaded into pkg/cloud, and its passphrase-prompt fallback can block on stdin -- fine synchronously in a CLI command, a real bug in List(), which also runs unattended from a periodic poll (see boxctl-vms-agent.sh).
  • fc/ch now persist each VM's actual SSHPort (previously implicit/hardcoded as 22 nowhere in particular) so the probe targets the right one.

Found while adding a "don't show Terminal until the VM is actually ready" indicator to the boxctl-vms dashboard -- discovered onctl ls had no signal for that distinction at all.

Test plan

  • go build ./..., go vet ./pkg/cloud/..., gofmt -l clean
  • go test ./pkg/cloud/... -- new tests cover ProbeTCP/ProbeSSHReady directly (reachable/unreachable/no-IP), and ch's List() end-to-end against a real local listener (becomes SSHReady, persists to metadata.json) and against a freshly-deployed VM with no reachable IP (stays false, no false positive)

🤖 Generated with Claude Code

Status only ever reflected "the VMM process is alive" (set once at
Deploy time, checked afterward via isAlive's process-liveness check),
never "the guest OS actually finished booting" -- for a Windows/ch
guest in particular, that gap can be minutes wide, but any dashboard
polling `onctl ls` mid-boot would already see Status=="running" and
have no way to tell a genuinely usable VM apart from one that's still
booting.

List() now also TCP-probes (300ms timeout, concurrently across every
not-yet-confirmed VM, so this doesn't meaningfully slow down `ls`) each
running VM's SSH port and reports the result as a new Vm.SSHReady field,
persisting a true result to that VM's metadata.json so it's never
re-probed once confirmed. A deliberate TCP-connect check, not the full
SSH auth handshake WaitForSSH already does at create time: reusing that
would need the operator's actual private key material threaded into
this package, and its passphrase-prompt fallback can block on stdin --
fine once, synchronously, in a CLI command a human is driving, but a
real bug in List(), which also runs from an unattended, non-interactive
periodic poll (see boxctl-vms-agent.sh). fc/ch also now persist each
VM's actual SSHPort (previously implicit/hardcoded as 22 nowhere in
particular) so the probe targets the right one.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012iVNj3mykz8m7QfuxWN3ae
@cdalar
cdalar merged commit e85f5ee into main Sep 9, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

⌂ 换网址