Documentation
¶
Overview ¶
Package control is the client half of the holder protocol: it spawns a holder process, waits for its members to come up, and queries or stops them over the per-member unix sockets. It is backend-neutral — it imports only internal/opts and internal/store, never a hypervisor or the orchestrator — so the darwin library client and CLI (which both drive a holder over this protocol) stay pure Go and need no codesign (ADR-0017, R1).
Two spawn modes share one wire protocol. The CLI spawns DETACHED (the holder is a session leader via Setsid and its VMs outlive the command — cattle-with-persistence). The library spawns BOUND/attached: the holder is a child of the test process, is handed the client PID, and holds one long-lived control connection open; when the test process dies the holder reaps itself and its VMs (ADR-0017, R4). The server half lives in internal/holder.
Index ¶
- Constants
- func AddMember(st *store.Store, sibling, name string) error
- func IsRunning(st *store.Store, name string) bool
- func Stop(st *store.Store, name string) error
- func WaitMembers(st *store.Store, names []string, timeout time.Duration) (map[string]*Status, error)
- type Session
- type SpawnConfig
- type Status
Constants ¶
const ( // RunnerFlag marks a process as a holder and is followed by the // comma-separated member names it owns. The holder server parses it; Spawn // passes it. RunnerFlag = "--fleetbox-runner" // EnvOpts carries the JSON-encoded VM options (opts.Encode) to the holder. EnvOpts = "FLEETBOX_OPTS" // EnvParentPID is set only in bound mode: it is the client PID the holder // watches so it can reap itself when the test process is gone (R4). EnvParentPID = "FLEETBOX_PARENT_PID" // ProtocolVersion is exchanged on the bind handshake. The client and the // helper bake in this constant from the same source, so a download (whose // filename is version-stamped) always matches; a mismatch means a stale // FLEETBOX_HELPER override pointing at a different build, which Spawn rejects // loudly rather than driving with an incompatible protocol (ADR-0017, R5). ProtocolVersion = "1" // Wire commands, shared with the holder server half (internal/holder) so the // two ends never drift. CmdStatus = "status" CmdStop = "stop" CmdAddMember = "addmember" CmdBind = "bind" // CmdBindAck confirms the bind handshake. The client sends it only after it // has accepted the helper's version and is committing to hold the connection; // the helper arms its EOF death-watch only after receiving it. This keeps a // connection that closes mid-handshake (a dial retry, a stray probe) from // being mistaken for the parent dying and tearing the cluster down (R4). CmdBindAck = "ack" // Member states reported over the status socket. StateDownloading is the // one-time pull of the image + VMM binaries that precedes booting; it is // reported separately so the readiness wait does not charge that // (potentially multi-GB) download against the per-boot budget (ADR-0013). StateDownloading = "downloading" StateStarting = "starting" StateRunning = "running" StateStopped = "stopped" StateError = "error" )
Variables ¶
This section is empty.
Functions ¶
func AddMember ¶
AddMember asks a running holder — reached through a live sibling's socket — to boot name onto its existing shared network, then waits for it to come up. This is how a stopped node re-joins a live cluster instead of getting its own, isolated network.
func IsRunning ¶
IsRunning reports whether the holder serving a member is alive, by reading its pidfile and signalling the process.
func Stop ¶
Stop gracefully shuts down a single member (the holder keeps running for its siblings until the last one leaves).
func WaitMembers ¶
func WaitMembers(st *store.Store, names []string, timeout time.Duration) (map[string]*Status, error)
WaitMembers polls per-member status until every name is running with an IP, returning early with an error if any member enters the error state. While any member is downloading the image/VMM binaries it announces the pull once and keeps the boot deadline ahead of the (bounded) download.
Types ¶
type Session ¶
type Session struct {
// contains filtered or unexported fields
}
Session is a handle to a spawned holder. In bound mode it owns the control connection whose EOF triggers holder teardown and reaps the child process; in detached mode Close merely releases the persistent process.
func Spawn ¶
func Spawn(st *store.Store, cfg SpawnConfig) (*Session, error)
Spawn launches a holder for the given member names. In detached mode the holder is a persistent session leader; in bound mode it is an attached child handed the client PID, and Spawn additionally opens the holder's control connection so its EOF reaps the holder when the client goes away (R4). It does not wait for the members to boot — call WaitMembers (or use the returned Session) for that.
type SpawnConfig ¶
SpawnConfig configures a holder launch. Exe is the binary to run (the downloaded fleetbox-helper on darwin, os.Executable() for the linux re-exec-self CLI). Bound selects the library lifetime mode (attached + parent PID + control connection); false is the CLI's detached/persistent mode.
type Status ¶
type Status struct {
Name string `json:"name"`
PID int `json:"pid"`
Running bool `json:"running"`
IP string `json:"ip"`
State string `json:"state"` // "starting", "running", "stopped", "error"
Error string `json:"error,omitempty"`
}
Status represents the state of a VM member.
func GetStatus ¶
GetStatus returns the status of a member. A live holder is authoritative — even for a member still downloading or booting, whose config.json does not exist yet (it is written during boot) — so the holder socket is consulted first. Only when no holder serves the name do we fall back to on-disk state: stopped if the VM exists, otherwise an error that it is absent.