pod

package
v0.2.2 Latest Latest
Warning

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

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

Documentation

Overview

Package pod defines the in-VM PodSpec — what the guest init is told to run. The on-the-wire form is weft-proto's guestv1.PodSpec; this Go type mirrors it so init code stays decoupled from the proto regeneration cycle.

One PodSpec drives one micro-VM. A pod with a single Container is the mono-container case ; multiple Containers share the pod's network + IPC namespaces (the "infra"/pause container pattern).

Index

Constants

View Source
const BackendCubeFS = "cubefs"

BackendCubeFS is the platform's RWX share backend — CubeFS, a CNCF distributed POSIX + S3 filesystem. The Backend field is kept so other backends can return without reshaping the event-bus contract.

Variables

This section is empty.

Functions

func EnrichFromImage added in v0.2.2

func EnrichFromImage(c *Container, rootfsMount string) error

EnrichFromImage fills empty Container fields (Command, Env, Workdir, User) from the rootfs-resolved OCI image config. Already-set fields are preserved : a host that explicitly overrides Command/Env wins.

rootfsMount is the path where the container's rootfs share is mounted inside the guest (typically /run/weft/rootfs/<id>). It must be called AFTER mountShares — the .weft-microvm/config.json lives inside the share, so the share must be mounted first.

Returns os.ErrNotExist when no image config is present and the container had no Command — that surfaces back as the runtime's "command is required" error, with a clearer message.

Types

type Container

type Container struct {
	ID         string            `json:"id"`
	RootfsTag  string            `json:"rootfs_tag"`        // matches a Share.Tag (virtio-fs) OR a local dir under /run/weft/rootfs/<id>
	Command    []string          `json:"command,omitempty"` // overrides image entrypoint
	Args       []string          `json:"args,omitempty"`
	Env        map[string]string `json:"env,omitempty"`
	Workdir    string            `json:"workdir,omitempty"`
	User       string            `json:"user,omitempty"` // "uid:gid" or username
	Restart    RestartPolicy     `json:"restart,omitempty"`
	Mounts     []Mount           `json:"mounts,omitempty"`
	Resources  Resources         `json:"resources,omitempty"`
	Privileged bool              `json:"privileged,omitempty"`
}

Container is one OCI container in the pod.

type CubeFSMount

type CubeFSMount struct {
	// Volume is the CubeFS volume name (the platform "share" maps 1:1 to
	// a CubeFS volume).
	Volume string `json:"volume"`

	// Masters are the CubeFS master node addresses ("host:port"), reached
	// over the wg0 overlay.
	Masters []string `json:"masters"`

	// Owner is the volume owner CubeFS authorizes against.
	Owner string `json:"owner"`

	// AccessKey / SecretKey authenticate to CubeFS (the volume's keypair).
	AccessKey string `json:"access_key,omitempty"`
	SecretKey string `json:"secret_key,omitempty"`

	// SubDir optionally mounts only a subtree of the volume.
	SubDir string `json:"subdir,omitempty"`
}

CubeFSMount is the connection detail for a CubeFS volume — what the in-guest CubeFS client (cfs-client) needs to attach the volume.

type Firewall

type Firewall struct {
	Rules []FirewallRule `json:"rules"`
}

Firewall is the per-VM desired stateful filter ruleset. weft publishes this whole-state on the event bus (subject "weft.firewall.<vm-uuid>") whenever the effective rules for the VM change (Security-Group rules edited, group attached/detached, network defaults changed). The agent inside the microVM atomically reconciles its nftables table against the new state — replace-set, idempotent, missed-message-self-heals — same model pkg/mesh / pkg/mounts use for their concerns.

The set is pre-resolved by the publisher: every Security-Group rule that references another group by UUID is expanded into one or more FirewallRule entries with concrete RemoteCIDR values. The guest never sees group references and never has to query the control plane.

func LoadFirewall

func LoadFirewall(path string) (*Firewall, error)

LoadFirewall reads a standalone firewall ruleset from path. Returns (nil, nil) if the file does not exist — boot without a pre-staged ruleset is legal; the agent will receive the first state via NATS.

func (*Firewall) Validate

func (f *Firewall) Validate() error

Validate checks every rule has a recognised Direction and Protocol, a coherent port range, and a parseable RemoteCIDR. The empty ruleset is valid and means "default policy only" — typically default-deny ingress, default-allow egress at the chain level.

type FirewallRule

type FirewallRule struct {
	// Direction is "ingress" (traffic into the VM) or "egress" (traffic
	// out of the VM). Empty is rejected by Validate.
	Direction string `json:"direction"`
	// Protocol is "tcp", "udp", "icmp" (any code/type), or "" meaning any
	// L4 protocol. PortMin/PortMax are ignored when Protocol is "" or
	// "icmp".
	Protocol string `json:"protocol,omitempty"`
	// PortMin / PortMax describe an inclusive destination port range
	// (for ingress) or source port range (for egress). 0 = unset; if
	// set, PortMin must be ≤ PortMax. A single port is encoded as
	// PortMin == PortMax.
	PortMin uint16 `json:"port_min,omitempty"`
	PortMax uint16 `json:"port_max,omitempty"`
	// RemoteCIDR is the peer subnet matched on the rule. Empty means
	// any. Validated as a parseable CIDR by Validate.
	RemoteCIDR string `json:"remote_cidr,omitempty"`
}

FirewallRule mirrors weft-proto's SecurityRule but with remote_group_uuid already dereferenced to a CIDR (or empty = any). Stateful: the reconciler installs the rule on the matching hook (ingress/egress) with conntrack established/related already accepted at the top of the chain.

func (FirewallRule) Validate

func (r FirewallRule) Validate() error

Validate checks a single rule. Pulled out so the host-side publisher can validate one rule at a time when expanding remote_group_uuid.

type FirewallStatus

type FirewallStatus struct {
	// Overall is "Healthy" when the reconciler successfully read
	// the kernel table on the last poll, "Degraded" when the
	// nftables read errored. Defined as a string so the UI can
	// render unknown future states without code churn.
	Overall string `json:"Overall"`
	// TableInstalled is true when the "weft-fw" table is present
	// in the kernel ; false when no ruleset has been applied yet
	// (fresh boot before the first publish lands) or it was
	// flushed externally.
	TableInstalled bool `json:"TableInstalled"`
	// RulesInstalled is the total number of nftables rules across
	// the input + output chains, including the unconditional
	// ct/lo accepts the reconciler always installs. The UI
	// subtracts those defaults to show the tenant-visible count.
	RulesInstalled int `json:"RulesInstalled"`
	// LastError carries the most recent read error message ;
	// empty on success. Surfaced so an operator can tell
	// "reconciler crashed" from "no policy yet" without ssh-ing
	// into the guest.
	LastError string `json:"LastError,omitempty"`
	// PublishedAtUnix is the wall-clock time of this status
	// message (set by the emitter, not by the reconciler).
	PublishedAtUnix int64 `json:"PublishedAtUnix"`
}

FirewallStatus is the per-VM live state weft-microvm-agent publishes on "weft.firewall.<vm-uuid>.status" so the control plane (and the UI) can show whether the firewall reconciler is healthy and what's installed right now.

Reverse direction of the firewall config subject : weft-network (or weft) PUBLISHES the desired ruleset on the per-VM "weft.firewall.<vm-uuid>" subject ; the agent PUBLISHES this status back on a sibling subject. Same Subscriber+ApplyFunc / emitter pair that weft-router uses for its BGP state.

type ImageConfigFile added in v0.2.2

type ImageConfigFile struct {
	Process ImageProcess `json:"process"`
}

ImageConfigFile is the on-disk shape weft microvm pull writes at <rootfs>/.weft-microvm/config.json — the resolved OCI image entrypoint+cmd+env+cwd+user. Mirrors weft-microvm/configspec.go's processSpec exactly so both sides stay byte-compatible.

The host writes it for every pulled image (single-container and pod modes). The guest reads it as a fallback when the pod manifest (or the synthesised single-container spec) leaves Command empty — see EnrichFromImage below.

func LoadImageConfig added in v0.2.2

func LoadImageConfig(rootfsMount string) (*ImageConfigFile, error)

LoadImageConfig reads the resolved OCI process spec from <rootfsMount>/.weft-microvm/config.json. Returns os.ErrNotExist when the file is absent (host pulled the image with an older puller).

type ImageProcess added in v0.2.2

type ImageProcess struct {
	Args []string `json:"args"`
	Env  []string `json:"env"`
	Cwd  string   `json:"cwd"`
	User struct {
		UID uint32 `json:"uid"`
		GID uint32 `json:"gid"`
	} `json:"user"`
}

type Mount

type Mount struct {
	Source      string   `json:"source"`
	Destination string   `json:"destination"`
	Type        string   `json:"type,omitempty"` // "bind" | "tmpfs"
	Options     []string `json:"options,omitempty"`
}

type MountAction

type MountAction string

MountAction distinguishes a mount request from an unmount on the event bus. The zero value ("") means mount, so a boot-time Spec.ShareMounts entry needs no explicit action.

const (
	MountActionMount   MountAction = "" // also "mount"
	MountActionUnmount MountAction = "unmount"
)

type Network

type Network struct {
	Interface string   `json:"interface,omitempty"` // default "eth0"
	Address   string   `json:"address,omitempty"`   // CIDR, e.g. "10.0.2.15/24"
	Gateway   string   `json:"gateway,omitempty"`
	DNS       []string `json:"dns,omitempty"`
	Hostname  string   `json:"hostname,omitempty"`
}

Network is the pod-level network config. The init brings up eth0 before any container starts ; containers join the pod netns.

type Resources

type Resources struct {
	CPUShares uint64 `json:"cpu_shares,omitempty"`
	MemBytes  uint64 `json:"mem_bytes,omitempty"`
	PidsMax   int64  `json:"pids_max,omitempty"`
}

type RestartPolicy

type RestartPolicy string
const (
	RestartNever     RestartPolicy = ""
	RestartOnFailure RestartPolicy = "on-failure"
	RestartAlways    RestartPolicy = "always"
)

type Share

type Share struct {
	Tag        string `json:"tag"`         // virtio-fs tag, e.g. "rootfs0"
	MountPoint string `json:"mount_point"` // where init mounts it inside the guest, e.g. "/run/weft/rootfs/web"
	Readonly   bool   `json:"readonly,omitempty"`
}

Share is a host-mounted filesystem exposed to the guest (typically virtio-fs). One share usually carries the OCI rootfs of one container.

type ShareMount

type ShareMount struct {
	// ID is a stable handle, required so a later unmount (or re-publish)
	// targets the same mount deterministically.
	ID string `json:"id"`

	// Action is "" / "mount" or "unmount". Unmount only needs ID + MountPoint.
	Action MountAction `json:"action,omitempty"`

	// Backend selects the storage backend. Empty defaults to CubeFS.
	Backend string `json:"backend,omitempty"`

	// MountPoint is the absolute guest path the share appears at, e.g.
	// "/run/weft/shares/team-data". Bind-mount it into containers via
	// Container.Mounts to expose it to a workload.
	MountPoint string `json:"mount_point"`

	// Readonly mounts the share read-only.
	Readonly bool `json:"readonly,omitempty"`

	// CubeFS carries the CubeFS connection details (required when Backend
	// is CubeFS / empty).
	CubeFS *CubeFSMount `json:"cubefs,omitempty"`
}

ShareMount is one multi-attach POSIX share mounted inside the guest. It serves two roles, mirroring how pod.WireGuard is both a Spec field and the mesh update message:

  • boot-time: an entry in Spec.ShareMounts the agent mounts at startup;
  • dynamic: the JSON payload an operator (e.g. a teacher) publishes on the event bus to mount/unmount a share on a running VM — which the control plane fans out to a whole group of student VMs.

State is pushed whole and applied idempotently (replace-by-ID), so a missed message self-heals on the next publish — same model as the mesh.

func LoadShareMounts

func LoadShareMounts(path string) ([]ShareMount, error)

LoadShareMounts reads a standalone list of share mounts (JSON array) from path — the file the host drops into the config share for boot-time mounts. A missing file is not an error (returns nil, nil).

func (*ShareMount) EffectiveBackend

func (m *ShareMount) EffectiveBackend() string

EffectiveBackend reports the backend, applying the CubeFS default.

func (*ShareMount) Validate

func (m *ShareMount) Validate() error

Validate checks the fields the action+backend need. Unmount only needs ID + MountPoint ; a CubeFS mount needs the volume connection set.

type Spec

type Spec struct {
	PodID       string            `json:"pod_id"`
	Containers  []Container       `json:"containers"`
	Shares      []Share           `json:"shares,omitempty"`
	Network     *Network          `json:"network,omitempty"`
	WireGuard   *WireGuard        `json:"wireguard,omitempty"`
	ShareMounts []ShareMount      `json:"share_mounts,omitempty"`
	Labels      map[string]string `json:"labels,omitempty"`
}

Spec is the full pod description handed to weft-init.

func Load

func Load(path string) (*Spec, error)

Load reads a Spec from a JSON file. Empty path or missing file is not an error at this layer — the caller decides whether a pod-less boot is valid (e.g. interactive debug shell).

func (*Spec) Validate

func (s *Spec) Validate() error

type WGPeer

type WGPeer struct {
	PublicKey           string   `json:"public_key"`                     // base64, 32 bytes
	Endpoint            string   `json:"endpoint,omitempty"`             // underlay "host:port"
	AllowedIPs          []string `json:"allowed_ips"`                    // overlay CIDRs routed to this peer
	PersistentKeepalive uint16   `json:"persistent_keepalive,omitempty"` // seconds; 0 = disabled
}

WGPeer is one authorized WireGuard peer on the overlay.

type WireGuard

type WireGuard struct {
	Interface  string   `json:"interface,omitempty"`   // default "wg0"
	PrivateKey string   `json:"private_key"`           // base64, 32 bytes
	ListenPort uint16   `json:"listen_port,omitempty"` // UDP underlay port; 0 = ephemeral
	Address    string   `json:"address"`               // overlay CIDR, e.g. "10.9.0.1/24"
	Peers      []WGPeer `json:"peers,omitempty"`
}

WireGuard configures an optional kernel WireGuard interface the init brings up after eth0 — the encrypted overlay a micro-VM uses to reach other VMs, or to be reached by an operator CLI. Keys are base64-encoded 32-byte Curve25519 values, matching `wg`'s textual form.

func LoadWireGuard

func LoadWireGuard(path string) (*WireGuard, error)

LoadWireGuard reads a standalone WireGuard overlay config (the same shape as Spec.WireGuard) from path. This is how the host delivers a per-VM overlay without owning the whole pod spec: weft drops wireguard.json into the config share alongside pod.json, and weft-init applies it when the pod spec itself carries no WireGuard block.

A missing file is not an error — it just means no overlay was provisioned (returns nil, nil).

func (*WireGuard) Validate

func (w *WireGuard) Validate() error

Validate checks the overlay config has the minimum fields the kernel configuration needs.

Jump to

Keyboard shortcuts

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