firecracker

package
v0.7.21 Latest Latest
Warning

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

Go to latest
Published: Jul 21, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package firecracker is a thin Go wrapper around the Firecracker VMM's HTTP-over-Unix-socket REST API. It is intentionally small: a *Client owns a single VMM's API socket and exposes one Go method per Firecracker resource (machine-config, boot-source, drives, net-ifaces, vsock, actions, vm state, snapshot/{create,load}).

The package has no daemon-side state of its own. Lifecycle ownership — spawning the `firecracker` (or `jailer`-wrapped) process, knowing where its socket lives, supervising its exit — lives in internal/runtime/firecracker/, which uses this client to talk to the VMM it manages. Mirrors pkg/caddy/client.go in spirit: thin per-resource methods, idempotent where the upstream API is idempotent, errors returned verbatim with HTTP status context attached.

Firecracker's HTTP API is documented at https://github.com/firecracker-microvm/firecracker/blob/main/src/firecracker/swagger/firecracker.yaml. Stay close to that wire shape — every type in types.go corresponds to exactly one schema there.

Index

Constants

View Source
const (
	VMStatePaused  = "Paused"
	VMStateResumed = "Resumed"
)

VM states accepted by PATCH /vm. Firecracker uses this endpoint for Paused/Resumed transitions, especially around snapshot create/load.

View Source
const (
	ActionInstanceStart = "InstanceStart"
)

Action types Firecracker accepts on PUT /actions. Pause and Resume are intentionally not here: Firecracker v1.15 exposes those through PATCH /vm, not the action endpoint.

View Source
const DefaultRequestTimeout = 30 * time.Second

DefaultRequestTimeout caps a single REST call against the VMM. Firecracker itself responds in single-digit milliseconds for normal operations; we keep a generous ceiling so snapshot-load on a large memory file (mmap is fast but the API call still blocks on the kernel side) doesn't trip on a tight deadline. Callers that need their own ctx deadline should pass it to the methods — this is only the fallback.

Variables

This section is empty.

Functions

This section is empty.

Types

type APIError

type APIError struct {
	Method string
	Path   string
	Status int
	Body   string
}

APIError carries a non-2xx response from the Firecracker API. Body is the raw response payload (typically a {"fault_message": "..."} JSON object); callers can switch on Status for retry decisions.

func (*APIError) Error

func (e *APIError) Error() string

type Action

type Action struct {
	ActionType string `json:"action_type"`
}

Action is the PUT /actions body. ActionType is one of the constants above.

type BootSource

type BootSource struct {
	KernelImagePath string `json:"kernel_image_path"`
	BootArgs        string `json:"boot_args,omitempty"`
	InitrdPath      string `json:"initrd_path,omitempty"`
}

BootSource is the PUT /boot-source request for cold-boot VMMs. The kernel_image_path must be readable by the (possibly jailer-chrooted) firecracker process; the daemon resolves it ahead of time.

BootArgs is the kernel command line. Our template VMs use:

console=ttyS0 reboot=k panic=1 pci=off nomodules \
  init=/usr/local/bin/toolboxd-init quiet

The init binary is the toolbox agent's pre-snapshot wrapper that brings the vsock listener up before the snapshot is taken; see cmd/toolboxd/.

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client is a single-VMM Firecracker API client. One Client per Firecracker process; callers must not share a Client across processes because each VMM has its own socket. Methods are safe for concurrent use — the Firecracker API serializes mutations server-side and our http.Client is goroutine-safe.

func New

func New(socketPath string) *Client

New returns a Client that talks to the Firecracker API socket at socketPath. The socket need not exist at construction time; method calls will fail with a connect error until the VMM is spawned and binds it.

The returned client uses HTTP/1.1 over a Unix-domain stream — Firecracker's only transport. The fake "http://localhost" host in request URLs is a convention of net/http when the transport ignores it; the real address is socketPath.

func (*Client) Action

func (c *Client) Action(ctx context.Context, a Action) error

Action issues a single action against the VMM. Firecracker v1.15 keeps InstanceStart on /actions; Paused/Resumed transitions use PatchVM instead.

func (*Client) CreateSnapshot

func (c *Client) CreateSnapshot(ctx context.Context, req SnapshotCreate) error

CreateSnapshot writes a memory file + state file to the paths in req. Callers should put the VM in the Paused state first. SnapshotType=Full is the only option supported at template-build time; Diff is taken automatically by enable_diff_snapshots on load and does not flow through this call.

func (*Client) InstanceInfo

func (c *Client) InstanceInfo(ctx context.Context) (*InstanceInfo, error)

InstanceInfo returns the VMM's self-reported state. Useful for confirming the guest is "Running" after InstanceStart or "Paused" after a snapshot load with resume_vm=false.

func (*Client) LoadSnapshot

func (c *Client) LoadSnapshot(ctx context.Context, req SnapshotLoad) error

LoadSnapshot resumes a VMM from a memory file + state file pair. With EnableDiffSnapshots=true, the loaded memory file is mmap'd as the CoW base for the clone; per-clone writes land in a dirty bitmap and do not disturb the base — the property the whole plan rests on. With ResumeVM=true, the action implicitly resumes execution; otherwise the caller must PATCH /vm state=Resumed after attaching per-clone drives. TAP rebinding for restored snapshots is supplied in network_overrides.

func (*Client) PatchDrive

func (c *Client) PatchDrive(ctx context.Context, driveID string, patch DrivePatch) error

PatchDrive updates a subset of drive fields on a running or paused VMM. Today the only mutable field is path_on_host — used by the clone path to rebind a per-sandbox overlay before Resume.

func (*Client) PatchNetworkInterface

func (c *Client) PatchNetworkInterface(ctx context.Context, ifaceID string, patch NetworkInterfacePatch) error

PatchNetworkInterface updates a subset of network-interface fields on a VMM after snapshot/load. Firecracker v1.15 does not accept host_dev_name here; snapshot restore TAP rebinding must be sent in SnapshotLoad.

func (*Client) PatchVM

func (c *Client) PatchVM(ctx context.Context, vm VM) error

PatchVM updates the microVM running state. Firecracker accepts Paused and Resumed here; sending those values to /actions is rejected by v1.15.

func (*Client) Ping

func (c *Client) Ping(ctx context.Context) error

Ping checks the VMM is reachable by issuing GET / (returns InstanceInfo). A nil error means the socket accepted a request and the VMM replied — it does NOT imply the guest has booted; for that, callers handshake with the in-VM agent over vsock.

func (*Client) PutBootSource

func (c *Client) PutBootSource(ctx context.Context, src BootSource) error

PutBootSource declares the kernel image and command line for a cold-boot VMM. Not used on snapshot-load — the kernel is in the memory file there.

func (*Client) PutDrive

func (c *Client) PutDrive(ctx context.Context, driveID string, drv Drive) error

PutDrive attaches (or replaces) a block device by drive_id. The first drive with IsRootDevice=true is the rootfs; additional drives are per-sandbox overlays / data disks.

On a snapshot-loaded VMM, this method is used between snapshot/load and Resume to swap the per-sandbox overlay onto the clone — the host_dev_path is the only piece that differs between clones of the same template.

func (*Client) PutLogger

func (c *Client) PutLogger(ctx context.Context, lg Logger) error

PutLogger attaches a file-backed logger to the VMM. Optional but useful for capturing Firecracker's own diagnostic output during early bring-up.

func (*Client) PutMachineConfig

func (c *Client) PutMachineConfig(ctx context.Context, cfg MachineConfig) error

PutMachineConfig sets the VMM-wide CPU/memory shape. Must precede InstanceStart on a fresh VMM; ignored on a VMM that loads a snapshot (the snapshot already encodes the shape).

func (*Client) PutNetworkInterface

func (c *Client) PutNetworkInterface(ctx context.Context, ifaceID string, iface NetworkInterface) error

PutNetworkInterface attaches a TAP device by iface_id during cold boot.

func (*Client) PutVsock

func (c *Client) PutVsock(ctx context.Context, v Vsock) error

PutVsock attaches a virtio-vsock device. The UDS path on the host is where in-guest connections to (CID 2, port N) appear; the toolbox agent listens on (CID 3, port N) inside the guest. Vsock is the snapshot-safe host↔guest channel; TCP over the TAP would tear on resume.

func (*Client) SocketPath

func (c *Client) SocketPath() string

SocketPath returns the API socket path this client targets. Useful for log lines that want to identify which VMM a call landed against without reaching into the runtime driver's bookkeeping.

type Drive

type Drive struct {
	DriveID      string `json:"drive_id"`
	PathOnHost   string `json:"path_on_host"`
	IsRootDevice bool   `json:"is_root_device"`
	IsReadOnly   bool   `json:"is_read_only"`
	// CacheType: "Unsafe" or "Writeback". Default Unsafe matches the
	// Firecracker default. Writeback is required for snapshot-safe
	// overlays — the daemon sets it explicitly on per-sandbox overlays.
	CacheType string `json:"cache_type,omitempty"`
}

Drive attaches a block device. PathOnHost is the file or block-device path; IsRootDevice and IsReadOnly carry the usual semantics. RateLimiter is omitted from the type — we don't throttle template I/O today and surfacing the nested rate-limiter shape would bloat this type for no gain. Add it when an actual driver path needs it.

type DrivePatch

type DrivePatch struct {
	DriveID    string `json:"drive_id"`
	PathOnHost string `json:"path_on_host,omitempty"`
}

DrivePatch is the PATCH /drives/{id} body. host_dev_path is the only mutable field today (the snapshot-clone overlay rebind path). Wire name is path_on_host — keep the JSON tag honest.

type InstanceInfo

type InstanceInfo struct {
	ID    string `json:"id"`
	State string `json:"state"`
	// VmmVersion lets the driver fail-fast when a snapshot was taken on a
	// different Firecracker build than the one trying to load it; mismatch
	// is one of the top causes of mysterious snapshot-load failures
	// (see plans/snapshot-clone-fast-boot.md §Operational concerns #6).
	VmmVersion string `json:"vmm_version,omitempty"`
	AppName    string `json:"app_name,omitempty"`
}

InstanceInfo is the GET / response. The runtime driver uses State to distinguish "Not started" / "Running" / "Paused" without re-deriving from process signals -- useful as a sanity check before issuing VMStateResumed.

type Logger

type Logger struct {
	LogPath string `json:"log_path"`
	Level   string `json:"level,omitempty"`
}

Logger attaches a file-backed logger. Optional; useful for capturing Firecracker's own diagnostic output (boot errors, snapshot fault messages) alongside the VMM process group's stderr.

type MachineConfig

type MachineConfig struct {
	VcpuCount       int    `json:"vcpu_count"`
	MemSizeMib      int    `json:"mem_size_mib"`
	SMT             bool   `json:"smt,omitempty"`
	TrackDirtyPages bool   `json:"track_dirty_pages,omitempty"`
	HugePages       string `json:"huge_pages,omitempty"`
}

MachineConfig is the PUT /machine-config request. Memory is in MiB, matching Firecracker's wire shape (do not multiply by 1024×1024 here). SMT defaults false; hugepages are off by default but flipped on for template VMs so clones can share huge pages with the page cache.

type MemoryBackend

type MemoryBackend struct {
	BackendType string `json:"backend_type"`
	BackendPath string `json:"backend_path"`
}

MemoryBackend selects how Firecracker loads the snapshot memory file. BackendType "File" plus a file path is what we use; "Uffd" (userfaultfd) is a future axis for lazy fault-handler-driven page-in.

type NetworkInterface

type NetworkInterface struct {
	IfaceID     string `json:"iface_id"`
	HostDevName string `json:"host_dev_name"`
	GuestMAC    string `json:"guest_mac,omitempty"`
}

NetworkInterface attaches a TAP device. HostDevName is the host-visible TAP name (e.g. "fc-tap-<sandbox-id-prefix>"); GuestMAC is what the guest sees on eth0 — fixing it per-sandbox lets the host-side DHCP/static-IP machinery key off MAC. RX/TX rate limiters are intentionally omitted for the same reason as Drive's: add when needed.

type NetworkInterfacePatch

type NetworkInterfacePatch struct {
	IfaceID     string `json:"iface_id"`
	HostDevName string `json:"host_dev_name,omitempty"`
}

NetworkInterfacePatch is the PATCH /network-interfaces/{id} body. Firecracker v1.15 rejects host_dev_name on this endpoint, so current snapshot restore rebinding must use SnapshotLoad.NetworkOverrides. HostDevName remains here only for older API compatibility and tests that exercise the raw client.

type NetworkOverride

type NetworkOverride struct {
	IfaceID     string `json:"iface_id"`
	HostDevName string `json:"host_dev_name"`
}

NetworkOverride is one entry in SnapshotLoad.network_overrides. Firecracker applies these while restoring device state from the snapshot, before the VM is resumed.

type SnapshotCreate

type SnapshotCreate struct {
	SnapshotType string `json:"snapshot_type,omitempty"`
	SnapshotPath string `json:"snapshot_path"`
	MemFilePath  string `json:"mem_file_path"`
	Version      string `json:"version,omitempty"`
}

SnapshotCreate is the PUT /snapshot/create body. SnapshotType=Full is what template builds use; diff snapshots are an internal property of LoadSnapshot via EnableDiffSnapshots and do not flow through this type. Paths are host-side absolute paths (jailer chroot already resolved by the runtime driver).

type SnapshotLoad

type SnapshotLoad struct {
	SnapshotPath        string            `json:"snapshot_path"`
	MemBackend          *MemoryBackend    `json:"mem_backend,omitempty"`
	EnableDiffSnapshots bool              `json:"enable_diff_snapshots,omitempty"`
	ResumeVM            bool              `json:"resume_vm,omitempty"`
	NetworkOverrides    []NetworkOverride `json:"network_overrides,omitempty"`
}

SnapshotLoad is the PUT /snapshot/load body. EnableDiffSnapshots=true is the load-time flag that gives us per-clone CoW: the memory file stays mmap'd read-only and per-VMM writes go to a dirty bitmap. ResumeVM=false keeps the clone paused so the daemon can rebind the per-sandbox overlay before issuing PATCH /vm state=Resumed. Per-sandbox TAP rebinding is part of the load request itself via NetworkOverrides.

type VM

type VM struct {
	State string `json:"state"`
}

VM is the PATCH /vm body.

type Vsock

type Vsock struct {
	GuestCID int    `json:"guest_cid"`
	UDSPath  string `json:"uds_path"`
}

Vsock attaches a virtio-vsock device. UDSPath is the listen-side UDS on the host: in-guest connect(CID=2, port=N) becomes a connection accepted at <UDSPath>_<N>. GuestCID is the guest's own context ID (must be >= 3 per the virtio spec; CIDs 0–2 are reserved). The daemon allocates GuestCID from a SQLite pool — see internal/store/vsock_cids.

Jump to

Keyboard shortcuts

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