guestplane

package
v0.4.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 20, 2026 License: BSD-3-Clause Imports: 11 Imported by: 0

Documentation

Overview

Package guestplane is the guest-side half of the GuestPodPlane bidi stream defined in weft-proto/guestv1. The host serves GuestPodPlane on AF_VSOCK ; this client dials CID_HOST (=2) on the agent's configured port, sends the mandatory GuestHello, receives a GuestHelloAck (carrying the operator's PodSpec when known), and stays connected to :

  • emit a PodStatus heartbeat every interval (uptime, container summary stub for now — containers aren't reconciled in-guest yet beyond the on-NATS reconciler) ;
  • read ControlRequest frames from the host and ack them via ControlResponse so the host's dispatcher doesn't stall.

The client is intentionally minimal — the wire contract here is what protects against pod-id impersonation (the host's strict- when-known peer-CID check refuses any Hello announcing the wrong pod_id). Any future per-container state machine lives in pkg/containers ; this file just owns the wire layer.

Index

Constants

View Source
const (
	DefaultDialAttempts  = 60               // ~1 minute of retries
	DefaultDialDelay     = 1 * time.Second  // between attempts
	DefaultHeartbeatTick = 10 * time.Second // PodStatus cadence
	DefaultReconnectGap  = 5 * time.Second  // after Recv error
)

Default reconnect / heartbeat cadences. Tuned for "fast enough the operator notices a flapping link, slow enough that an idle VM doesn't fill weft-agent's stderr with reconnect noise".

View Source
const DefaultPort uint32 = 7777

Default port the host-side weft-agent binds its AF_VSOCK listener on. Operators can override via the agent flag ; the guest side has to agree, so this constant is the wire contract. 7777 chosen to match cmd/weft/main.go's --vsock-port default.

Variables

This section is empty.

Functions

func Run

func Run(ctx context.Context, cfg Config) error

Run is the daemon body : dial, Hello/HelloAck handshake, then a long-lived attached session. Reconnects on every Recv error until ctx is cancelled.

Returns ctx.Err() on clean shutdown so callers can distinguish "we were told to stop" from "we failed".

Types

type Config

type Config struct {
	// HostCID is the AF_VSOCK CID to dial. Always 2 (CID_HOST) in
	// production ; the field exists so a unit test can dial a
	// loopback listener via VsockCIDLocal=1 if it ever gets one.
	HostCID uint32
	// Port is the host's GuestPodPlane vsock port.
	Port uint32
	// PodID announced via GuestHello. Must match the pod_id the
	// host has on record (= VM name, the strict-when-known guard
	// rejects a Hello where peer.CID() != adapter.PodCID(pod_id)).
	PodID string
	// KernelInfo / InitVersion go into the Hello so the host's
	// logs carry the booted kernel + guest agent build.
	KernelInfo  string
	InitVersion string

	// HeartbeatTick is how often a PodStatus frame is sent. 0 →
	// DefaultHeartbeatTick. Set negative to disable heartbeats
	// entirely (the Hello/Ack handshake still runs).
	HeartbeatTick time.Duration
	// ReconnectGap is the pause before redialing after a Recv
	// error. 0 → DefaultReconnectGap.
	ReconnectGap time.Duration
	// DialAttempts is how many times we retry the initial dial
	// before giving up. 0 → DefaultDialAttempts.
	DialAttempts int
	// DialDelay is the per-attempt delay during the initial dial
	// retry loop. 0 → DefaultDialDelay.
	DialDelay time.Duration

	Logger *log.Logger

	// Dispatcher routes incoming ControlRequest frames into the
	// in-guest reconcilers. nil = the legacy "not yet routed" stub
	// reply is returned to the host (every ACK still carries the
	// matching CallId so the host's correlator doesn't stall).
	Dispatcher *Dispatcher
}

Config carries the knobs the agent's main() wires up. Empty fields fall back to the Default* constants — letting the caller build a Config{Host: ..., Logger: ...} and ship reasonable defaults.

type Dispatcher added in v0.4.1

type Dispatcher struct {
	// StopPod is invoked on a ControlRequest_StopPod. graceSeconds is
	// the StopPod.GraceSeconds value (0 = caller-chosen default).
	StopPod func(ctx context.Context, graceSeconds uint32) error
	// Kill is invoked on a ControlRequest_Kill. signal defaults to
	// "SIGTERM" when empty.
	Kill func(ctx context.Context, containerID, signal string) error
	// Exec is invoked on a ControlRequest_Exec. The dispatcher
	// receives the proto value verbatim so it can decide whether to
	// open a pty (tty=true) or a one-shot exec.
	Exec func(ctx context.Context, e *guestv1.ExecInContainer) error
	// Update is invoked on a ControlRequest_Update. UpdateContainer
	// carries the new command + merged env for one container.
	Update func(ctx context.Context, u *guestv1.UpdateContainer) error
}

Dispatcher is the action layer behind dispatchControl : a ControlRequest frame arrives over the AF_VSOCK GuestPodPlane, the wire layer (this file) ACKs it, and routes it through these callbacks so the in-guest reconcilers (pkg/containers, pkg/execsession) actually do the work.

All fields are optional. A nil callback resolves to the legacy "not yet routed" Error so the host's operator sees a clear signal the dispatch slot hasn't been wired locally — preserving the dispatchControl-as-stub behaviour for callers that don't pass one.

Each callback returns the *string the host should surface as the ControlResponse.Error : empty / "" = success. Errors are stringified by the caller, not the dispatcher, so the wire shape stays simple.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL