Lifecycle Package Reference
pkg/lifecycle/— VM lifecycle management, Firecracker API communication.
Overview
Section titled “Overview”The pkg/lifecycle package manages Firecracker VM lifecycle operations: start, stop, pause, resume, and state tracking.
Package Structure:
pkg/lifecycle/├── vmm.go # VMMManager and VMInstance├── mocks.go # Test mocksVMMManager
Section titled “VMMManager”File: vmm.go
The VMMManager manages Firecracker VM processes and API communication.
Type Definition
Section titled “Type Definition”type VMMManager struct { config *ManagerConfig vms map[string]*VMInstance mu sync.RWMutex socketDir string}Configuration
Section titled “Configuration”type ManagerConfig struct { KernelPath string // vmlinux path RootfsDir string // rootfs storage directory SocketDir string // API socket directory DefaultVCPUs int // default vCPU count DefaultMemoryMB int // default memory in MB EnableJailer bool // enable jailer sandbox}Constructor
Section titled “Constructor”func NewVMMManager(config interface{}) VMMManagerParameters:
config—*ManagerConfigor any interface (defaults applied)
Defaults Applied:
| Field | Default Value |
|---|---|
SocketDir |
"/var/run/firecracker" |
Example:
config := &lifecycle.ManagerConfig{ KernelPath: "/usr/share/firecracker/vmlinux", RootfsDir: "/var/lib/firecracker/rootfs", SocketDir: "/var/run/firecracker", DefaultVCPUs: 2, DefaultMemoryMB: 1024,}
vmm := lifecycle.NewVMMManager(config)VMInstance
Section titled “VMInstance”File: vmm.go
Type Definition
Section titled “Type Definition”type VMInstance struct { ID string // Task ID PID int // Firecracker process PID Config interface{} // VM configuration state VMState // Current state (private) CreatedAt time.Time // Creation timestamp SocketPath string // API socket path InitSystem string // Init type (tini/dumb-init) GracePeriodSec int // Shutdown grace period
mu sync.RWMutex // Protects state}State Methods
Section titled “State Methods”func (v *VMInstance) SetState(newState VMState)func (v *VMInstance) GetState() VMStateThread-safe state access.
VM States
Section titled “VM States”type VMState string
const ( VMStateNew VMState = "new" // Created but not started VMStateStarting VMState = "starting" // Firecracker booting VMStateRunning VMState = "running" // VM operational VMStateStopping VMState = "stopping" // Shutdown initiated VMStateStopped VMState = "stopped" // VM terminated VMStateCrashed VMState = "crashed" // Unexpected failure)Methods
Section titled “Methods”func (vm *VMMManager) Start(ctx context.Context, task *types.Task, config interface{}) errorPurpose: Start a Firecracker VM for the task.
Steps:
-
Find Firecracker binary
fcBinary, err := exec.LookPath("firecracker") -
Start process with API socket
cmd := exec.Command(fcBinary, "--api-sock", socketPath)cmd.Stdout = os.Stdoutcmd.Stderr = os.Stderrcmd.Start() -
Wait for API ready
waitForAPIServer(socketPath, 10*time.Second) -
Configure VM via API
vm.configureVM(ctx, socketPath, config) -
Send InstanceStart action
client := newUnixClient(socketPath, 5*time.Second)actions := ActionsType{ActionType: "InstanceStart"}client.Put("/actions", actions) -
Track instance
vm.vms[task.ID] = &VMInstance{ID: task.ID,PID: cmd.Process.Pid,SocketPath: socketPath,state: VMStateRunning,CreatedAt: time.Now(),}
Error Handling:
- Deferred cleanup on failure (kill process, remove socket)
- Validates config is not nil
- Checks for duplicate VM
func (vm *VMMManager) Stop(ctx context.Context, taskID string) errorPurpose: Stop a running VM.
Steps:
- Get VM instance
- Send
InstanceStopaction with timeout - Wait for process exit
- Update state to
VMStateStopped
Pause is implemented in pkg/snapshot by pauseVM(), which issues a
PATCH /vm request (Firecracker v1.14+):
payload := map[string]interface{}{"state": "Paused"}// PATCH /vmpkg/lifecycle itself has no pause method; VMMManager.Snapshot delegates to
pkg/snapshot.Manager.
Resume
Section titled “Resume”Resume is implemented in pkg/snapshot by resumeVM(), using the same
endpoint with {"state": "Resumed"}:
payload := map[string]interface{}{"state": "Resumed"}// PATCH /vmA restore resumes automatically via the resume_vm: true flag on
PUT /snapshot/load.
GetInfo
Section titled “GetInfo”func (vm *VMMManager) GetInfo(taskID string) (*VMInstance, error)Purpose: Get VM instance info.
Returns:
*VMInstance— Instance details (ID, PID, state, socket)error— Not found error
func (vm *VMMManager) List() []stringPurpose: List all managed VM IDs.
Cleanup
Section titled “Cleanup”func (vm *VMMManager) Cleanup(ctx context.Context, taskID string) errorPurpose: Cleanup VM resources after termination.
Cleanup Steps:
- Remove API socket file
- Remove VM from tracking map
- Release allocated resources
Firecracker API
Section titled “Firecracker API”Client
Section titled “Client”type unixClient struct { socketPath string timeout time.Duration}
func newUnixClient(socketPath string, timeout time.Duration) *unixClientHTTP Methods
Section titled “HTTP Methods”func (c *unixClient) Get(path string) ([]byte, error)func (c *unixClient) Put(path string, body interface{}) errorUses HTTP over Unix socket:
// Dial Unix socketconn, err := net.Dial("unix", socketPath)
// HTTP client with Unix transportclient := &http.Client{ Transport: &unixTransport{socketPath: socketPath},}API Types
Section titled “API Types”type ActionsType struct { ActionType string `json:"action_type"`}
type BootSource struct { KernelImagePath string `json:"kernel_image_path"` BootArgs string `json:"boot_args,omitempty"` Drives []Drive `json:"drives,omitempty"`}
type Drive struct { DriveID string `json:"drive_id"` IsRootDevice bool `json:"is_root_device"` IsReadOnly bool `json:"is_read_only"` PathOnHost string `json:"path_on_host"`}
type MachineConfig struct { VCPUs int `json:"vcpu_count"` MemSizeMib int `json:"mem_size_mib"` HtEnabled bool `json:"ht_enabled"`}API Endpoints
Section titled “API Endpoints”| Endpoint | Method | Purpose |
|---|---|---|
/actions |
PUT | Start/stop VM |
/boot-source |
PUT | Configure kernel |
/drives/{id} |
PUT | Configure disk |
/machine-config |
PUT | Configure CPU/memory |
/network-interfaces/{id} |
PUT | Configure network |
/vm |
GET | Get VM info |
/vm |
PATCH | Pause/resume ({"state": "Paused"} / {"state": "Resumed"}) |
Configure VM
Section titled “Configure VM”func (vm *VMMManager) configureVM(ctx context.Context, socketPath string, config interface{}) errorPurpose: Apply full VM configuration via API.
Steps:
-
Configure machine
machine := MachineConfig{VCPUs: vmConfig.VCPUs,MemSizeMib: vmConfig.MemoryMB,HtEnabled: false,}client.Put("/machine-config", machine) -
Configure boot source
boot := BootSource{KernelImagePath: vmConfig.KernelPath,BootArgs: "console=ttyS0 reboot=k panic=1 pci=off",}client.Put("/boot-source", boot) -
Configure root drive
drive := Drive{DriveID: "rootfs",PathOnHost: vmConfig.RootfsPath,IsRootDevice: true,IsReadOnly: false,}client.Put("/drives/rootfs", drive) -
Configure network interface
iface := NetworkInterface{IfaceID: "eth0",GuestMac: generateMac(taskID),HostDevName: tapDevice.Name,}client.Put("/network-interfaces/eth0", iface)
Graceful Shutdown
Section titled “Graceful Shutdown”When InitSystem is set (tini/dumb-init):
// 1. Send SIGTERM to init processsyscall.Kill(pid, syscall.SIGTERM)
// 2. Wait grace periodtime.Sleep(time.Duration(gracePeriodSec) * time.Second)
// 3. Force kill if still runningif processStillRunning { syscall.Kill(pid, syscall.SIGKILL)}Configuration:
executor: init_system: "tini" init_grace_period: 10 # secondsProcess Monitoring
Section titled “Process Monitoring”// Wait for process exitfunc waitForProcess(pid int, timeout time.Duration) error { for i := 0; i < int(timeout/time.Second); i++ { if !processExists(pid) { return nil } time.Sleep(time.Second) } return fmt.Errorf("process did not exit within timeout")}API Server Ready Check
Section titled “API Server Ready Check”func waitForAPIServer(socketPath string, timeout time.Duration) error { for i := 0; i < int(timeout/time.Millisecond); i += 100 { if _, err := net.Dial("unix", socketPath); err == nil { return nil } time.Sleep(100 * time.Millisecond) } return fmt.Errorf("API server not ready after %v", timeout)}Testing
Section titled “Testing”Mock VMMManager
Section titled “Mock VMMManager”type MockVMMManager struct { VMs map[string]*VMInstance StartErr error StopErr error}
func (m *MockVMMManager) Start(ctx context.Context, task *types.Task, config interface{}) error { if m.StartErr != nil { return m.StartErr } m.VMs[task.ID] = &VMInstance{ ID: task.ID, PID: 12345, state: VMStateRunning, } return nil}Error Handling
Section titled “Error Handling”Common Errors
Section titled “Common Errors”| Error | Cause | Resolution |
|---|---|---|
"task cannot be nil" |
Nil task passed | Provide valid task |
"VM already exists" |
Duplicate task ID | Remove existing VM first |
"firecracker binary not found" |
Not installed | Install Firecracker |
"API server not ready" |
Boot timeout | Check Firecracker logs |
"failed to configure VM" |
API error | Validate config values |
"process did not exit" |
Graceful shutdown timeout | Increase grace period |
Related Documentation
Section titled “Related Documentation”| Topic | Document |
|---|---|
| SwarmKit executor | SwarmKit Reference |
| Network setup | Network Reference |
| Init systems | Image Reference |
| Snapshot operations | Operations Guide |