Documentation
¶
Index ¶
- func IsCgroupV2Available() bool
- func SetVMLogMaxBytes(n int64)
- type CgroupLimit
- type CgroupManager
- type CommandFunc
- type Config
- type FCOption
- type FileStore
- type FirecrackerManager
- func (m *FirecrackerManager) Create(_ context.Context, cfg Config) (*VM, error)
- func (m *FirecrackerManager) Get(id string) (*VM, error)
- func (m *FirecrackerManager) Kill(_ context.Context, id string) error
- func (m *FirecrackerManager) List() []*VM
- func (m *FirecrackerManager) Remove(_ context.Context, id string) error
- func (m *FirecrackerManager) Signal(_ context.Context, id string, sig os.Signal) error
- func (m *FirecrackerManager) Start(ctx context.Context, id string) error
- func (m *FirecrackerManager) Stop(ctx context.Context, id string) error
- func (m *FirecrackerManager) Store() Store
- type HealthCheckConfig
- type HealthChecker
- type HealthStatus
- type Manager
- type MemoryStore
- func (s *MemoryStore) Create(cfg Config) (*VM, error)
- func (s *MemoryStore) Get(id string) (*VM, error)
- func (s *MemoryStore) List() []*VM
- func (s *MemoryStore) Remove(id string) error
- func (s *MemoryStore) Resolve(nameOrID string) (*VM, error)
- func (s *MemoryStore) Restore() error
- func (s *MemoryStore) Save(_ *VM) error
- type Migrator
- type MockManager
- func (m *MockManager) Create(ctx context.Context, cfg Config) (*VM, error)
- func (m *MockManager) Get(id string) (*VM, error)
- func (m *MockManager) Kill(ctx context.Context, id string) error
- func (m *MockManager) List() []*VM
- func (m *MockManager) Remove(ctx context.Context, id string) error
- func (m *MockManager) Signal(ctx context.Context, id string, sig os.Signal) error
- func (m *MockManager) Start(ctx context.Context, id string) error
- func (m *MockManager) Stop(ctx context.Context, id string) error
- type NoopStatsCollector
- type Option
- type PortMap
- type PortProtocol
- type ProcStatsCollector
- type QEMUManager
- func (m *QEMUManager) Create(_ context.Context, cfg Config) (*VM, error)
- func (m *QEMUManager) Get(id string) (*VM, error)
- func (m *QEMUManager) Kill(_ context.Context, id string) error
- func (m *QEMUManager) List() []*VM
- func (m *QEMUManager) Remove(_ context.Context, id string) error
- func (m *QEMUManager) Signal(_ context.Context, id string, sig os.Signal) error
- func (m *QEMUManager) Start(ctx context.Context, id string) error
- func (m *QEMUManager) Stop(ctx context.Context, id string) error
- func (m *QEMUManager) Store() Store
- type RestartConfig
- type RestartPolicy
- type RuntimeStats
- type SQLiteStore
- type State
- type StatsCollector
- type Store
- type VM
- func (v *VM) AttachReader() io.Reader
- func (v *VM) Done() <-chan struct{}
- func (v *VM) GetHealthStatus() HealthStatus
- func (v *VM) GetRestartCount() int
- func (v *VM) GetState() State
- func (v *VM) GetTimes() (startedAt, stoppedAt *time.Time)
- func (v *VM) IsExplicitStop() bool
- func (v *VM) Logs() []byte
- func (v *VM) SetExplicitStop()
- func (v *VM) SetHealthStatus(s HealthStatus)
- func (v *VM) SetStatsProvider(fn func() RuntimeStats)
- func (v *VM) Stats() RuntimeStats
- type VolumeMount
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func IsCgroupV2Available ¶
func IsCgroupV2Available() bool
func SetVMLogMaxBytes ¶
func SetVMLogMaxBytes(n int64)
SetVMLogMaxBytes sets the per-VM in-memory log capture limit in bytes. A non-positive value restores the 4 MiB default. Call once at daemon startup.
Types ¶
type CgroupLimit ¶
type CgroupLimit struct {
MemoryMax int64
}
type CgroupManager ¶
type CgroupManager struct {
// contains filtered or unexported fields
}
func NewCgroupManager ¶
func NewCgroupManager(vmID string) *CgroupManager
func (*CgroupManager) Apply ¶
func (m *CgroupManager) Apply(pid int, limits CgroupLimit) error
func (*CgroupManager) Remove ¶
func (m *CgroupManager) Remove() error
type CommandFunc ¶
CommandFunc builds an exec.Cmd. Defaults to exec.CommandContext; replaceable in tests.
type Config ¶
type Config struct {
// ImagePath is the raw disk image containing the kernel and application.
ImagePath string
// ImageRef is the image reference the VM was created from (e.g.
// "flaskapp:latest"), preserved for display. Empty when the VM was started
// from a raw ImagePath with no registered image.
ImageRef string
// Memory is the QEMU memory string (e.g. "256M").
Memory string
// CPUs is the number of virtual CPUs; 0 uses QEMU default.
CPUs int
// NetworkName is the TAP interface name to attach; empty disables networking.
// Networking is TAP only (SLIRP is not supported), so PortMaps require a
// non-empty NetworkName.
NetworkName string
// PortMaps is the list of host-to-guest port forwarding rules, published by
// a userspace forwarder. Requires TAP networking (a non-empty NetworkName).
PortMaps []PortMap
// Env is a list of "KEY=VALUE" environment variable pairs injected at
// boot time via QEMU fw_cfg. The kernel reads opt/uni/env to consume them.
Env []string
// Name is a human-readable identifier for the VM. If empty, the UUID is used.
Name string
// Volumes is the list of additional disk images to attach to the VM.
Volumes []VolumeMount
// Attach when true, creates a pipe for streaming serial console output.
Attach bool
// IPAddress is the static IP address to assign to the VM. Requires TAP
// networking (NetworkName). If empty, no static IP is configured.
IPAddress string
// GatewayIP is the gateway IP for the VM's network. Derived from IPAddress
// when using TAP networking. Used to assign an IP to the bridge interface.
GatewayIP string
// BridgeName is the Linux bridge interface name for the VM's network.
// When set, the daemon creates/destroys this bridge on VM start/stop.
BridgeName string
// SubnetMask is the CIDR mask for the VM's network (e.g. "24").
// Used to build the guest network configuration passed via fw_cfg.
SubnetMask string
// HealthCheck configures liveness probing for the VM. Nil disables probing.
HealthCheck *HealthCheckConfig
// Restart controls automatic restart behavior when the VM exits.
Restart RestartConfig
CPUShares uint64
// MemoryMax is the cgroup v2 memory hard limit in bytes. 0 means no limit.
MemoryMax int64
// DiskIOPS is the maximum I/O operations per second for the boot disk (QEMU throttle). 0 means no limit.
DiskIOPS uint64
// DiskBPS is the maximum bytes per second for the boot disk (QEMU throttle). 0 means no limit.
DiskBPS int64
}
Config holds the parameters used to create a VM.
type FCOption ¶
type FCOption func(*FirecrackerManager)
FCOption configures a FirecrackerManager.
func WithFCCommandFunc ¶
func WithFCCommandFunc(fn CommandFunc) FCOption
WithFCCommandFunc injects a custom command builder (for tests).
func WithFCStore ¶
WithFCStore injects a custom Store implementation.
type FileStore ¶
type FileStore struct {
MemoryStore
// contains filtered or unexported fields
}
FileStore is a Store that persists VM state to disk as JSON files. It wraps a MemoryStore for in-memory lookups and mirrors every mutation to ~/.jerboa/vms/<id>/state.json.
func NewFileStore ¶
NewFileStore returns a FileStore rooted at dir (~/.jerboa/vms). Call Restore() to load any previously persisted VMs.
type FirecrackerManager ¶
type FirecrackerManager struct {
// contains filtered or unexported fields
}
FirecrackerManager implements Manager by spawning firecracker processes configured via a JSON config file and managed via the Firecracker REST API over a per-VM Unix socket.
Limitations vs. QEMUManager:
- TAP networking only (like QEMU now): port maps require a NetworkName and are rejected at Start otherwise. Publishing is done by the userspace forwarder, shared with QEMU.
- DiskIOPS / DiskBPS throttling is not available (no Firecracker equivalent).
- On Windows, Firecracker runs inside WSL2; KVM must be available in WSL2.
- The kernel image must be a flat ELF vmlinux compatible with Firecracker (different from the BIOS-bootable kernel.img used by QEMU).
func NewFirecrackerManager ¶
func NewFirecrackerManager(fcBin, kernelImage string, opts ...FCOption) *FirecrackerManager
NewFirecrackerManager returns a FirecrackerManager. fcBin is the path to the firecracker binary. kernelImage is the path to a Firecracker-compatible vmlinux ELF kernel.
func (*FirecrackerManager) Get ¶
func (m *FirecrackerManager) Get(id string) (*VM, error)
Get returns the VM with the given id, name, or ID prefix.
func (*FirecrackerManager) Kill ¶
func (m *FirecrackerManager) Kill(_ context.Context, id string) error
Kill immediately terminates the firecracker process.
func (*FirecrackerManager) List ¶
func (m *FirecrackerManager) List() []*VM
List returns all registered VMs.
func (*FirecrackerManager) Remove ¶
func (m *FirecrackerManager) Remove(_ context.Context, id string) error
Remove deletes a stopped VM from the registry.
func (*FirecrackerManager) Signal ¶
Signal sends sig to the VM. SIGKILL kills the host process immediately; all other signals trigger a graceful SendCtrlAltDel via the Firecracker API, falling back to an OS-level signal on failure.
func (*FirecrackerManager) Start ¶
func (m *FirecrackerManager) Start(ctx context.Context, id string) error
Start writes a Firecracker config file and launches the firecracker process. The VM boots immediately upon process start (no separate InstanceStart call needed).
func (*FirecrackerManager) Stop ¶
func (m *FirecrackerManager) Stop(ctx context.Context, id string) error
Stop gracefully shuts down the VM via Firecracker's SendCtrlAltDel API action, falling back to SIGTERM → SIGKILL after gracePeriod.
func (*FirecrackerManager) Store ¶
func (m *FirecrackerManager) Store() Store
Store returns the underlying Store.
type HealthCheckConfig ¶
type HealthCheckConfig struct {
// Type is "tcp" or "http". For HTTP, a GET request is made to Path.
Type string
// Port is the guest port to probe.
Port int
// Path is the HTTP path (only used when Type is "http").
Path string
// Interval between probes. Defaults to 10s if zero.
Interval time.Duration
// Timeout per probe. Defaults to 3s if zero.
Timeout time.Duration
// Retries is the number of consecutive failures before marking unhealthy.
// Defaults to 3 if zero.
Retries int
}
HealthCheckConfig defines how to probe a VM for liveness.
type HealthChecker ¶
type HealthChecker struct {
// contains filtered or unexported fields
}
func NewHealthChecker ¶
func NewHealthChecker() *HealthChecker
func (*HealthChecker) Stop ¶
func (h *HealthChecker) Stop(id string)
type HealthStatus ¶
type HealthStatus string
HealthStatus represents the result of a health check probe.
const ( // HealthHealthy means the probe succeeded. HealthHealthy HealthStatus = "healthy" // HealthUnhealthy means the probe failed. HealthUnhealthy HealthStatus = "unhealthy" // HealthStarting means the VM is within the grace period and not yet probed. HealthStarting HealthStatus = "starting" // HealthUnknown means no health check is configured. HealthUnknown HealthStatus = "unknown" )
type Manager ¶
type Manager interface {
// Create registers a new VM with the given config.
Create(ctx context.Context, cfg Config) (*VM, error)
// Start launches the QEMU process for the VM with the given id.
Start(ctx context.Context, id string) error
// Stop gracefully shuts down the VM: SIGTERM, 30s grace, then SIGKILL.
Stop(ctx context.Context, id string) error
// Kill immediately sends SIGKILL to the VM process.
Kill(ctx context.Context, id string) error
// Signal sends an arbitrary OS signal to the VM process.
Signal(ctx context.Context, id string, sig os.Signal) error
// Remove deletes a stopped VM from the registry.
Remove(ctx context.Context, id string) error
// Get returns the VM with the given id.
Get(id string) (*VM, error)
// List returns all registered VMs.
List() []*VM
}
Manager manages the lifecycle of unikernel VMs.
type MemoryStore ¶
type MemoryStore struct {
// contains filtered or unexported fields
}
MemoryStore is a thread-safe in-memory registry of VMs.
func NewMemoryStore ¶
func NewMemoryStore() *MemoryStore
NewMemoryStore returns an empty in-memory Store.
func NewStore
deprecated
func NewStore() *MemoryStore
NewStore returns an empty in-memory Store.
Deprecated: use NewMemoryStore for clarity.
func (*MemoryStore) List ¶
func (s *MemoryStore) List() []*VM
func (*MemoryStore) Remove ¶
func (s *MemoryStore) Remove(id string) error
func (*MemoryStore) Restore ¶
func (s *MemoryStore) Restore() error
Restore is a no-op for MemoryStore; there is nothing to restore from.
func (*MemoryStore) Save ¶
func (s *MemoryStore) Save(_ *VM) error
Save is a no-op for MemoryStore; state lives only in memory.
type Migrator ¶
type Migrator struct {
// contains filtered or unexported fields
}
func NewMigrator ¶
func NewMigrator(fileRoot string, sqliteDB *SQLiteStore) *Migrator
type MockManager ¶
type MockManager struct {
CreateFn func(ctx context.Context, cfg Config) (*VM, error)
StartFn func(ctx context.Context, id string) error
StopFn func(ctx context.Context, id string) error
KillFn func(ctx context.Context, id string) error
SignalFn func(ctx context.Context, id string, sig os.Signal) error
RemoveFn func(ctx context.Context, id string) error
GetFn func(id string) (*VM, error)
ListFn func() []*VM
// contains filtered or unexported fields
}
func NewMockManager ¶
func NewMockManager() *MockManager
func (*MockManager) List ¶
func (m *MockManager) List() []*VM
type NoopStatsCollector ¶
NoopStatsCollector returns fallback stats when no collector is available.
func (NoopStatsCollector) Collect ¶
func (n NoopStatsCollector) Collect() RuntimeStats
type Option ¶
type Option func(*QEMUManager)
Option configures a QEMUManager.
func WithCommandFunc ¶
func WithCommandFunc(fn CommandFunc) Option
WithCommandFunc injects a custom command builder (for tests).
type PortMap ¶
type PortMap struct {
// HostPort is the port on the host to listen on.
HostPort uint16
// GuestPort is the port inside the VM to forward to.
GuestPort uint16
// Protocol is "tcp" or "udp"; defaults to "tcp".
Protocol PortProtocol
}
PortMap describes a single host-to-guest port forwarding rule.
func ParsePortMap ¶
ParsePortMap parses a port mapping string in one of these forms:
"8080:80" → tcp, host=8080, guest=80 "8080:80/tcp" → tcp, host=8080, guest=80 "5353:53/udp" → udp, host=5353, guest=53
func ParsePortMaps ¶
ParsePortMaps parses multiple port mapping strings (e.g. from CLI -p flags).
type PortProtocol ¶
type PortProtocol string
PortProtocol is the transport layer protocol for a port mapping.
const ( // ProtocolTCP is the TCP protocol. ProtocolTCP PortProtocol = "tcp" // ProtocolUDP is the UDP protocol. ProtocolUDP PortProtocol = "udp" )
type ProcStatsCollector ¶
type ProcStatsCollector struct {
// contains filtered or unexported fields
}
ProcStatsCollector reads /proc/[pid]/ io files for CPU, memory, and I/O stats.
func (*ProcStatsCollector) Collect ¶
func (c *ProcStatsCollector) Collect() RuntimeStats
type QEMUManager ¶
type QEMUManager struct {
// contains filtered or unexported fields
}
QEMUManager implements Manager by spawning qemu-system-x86_64 processes.
func NewQEMUManager ¶
func NewQEMUManager(qemuBin string, opts ...Option) *QEMUManager
NewQEMUManager returns a QEMUManager using qemuBin as the QEMU executable.
func (*QEMUManager) Get ¶
func (m *QEMUManager) Get(id string) (*VM, error)
Get returns the VM with the given id, name, or ID prefix.
func (*QEMUManager) Kill ¶
func (m *QEMUManager) Kill(_ context.Context, id string) error
Kill immediately sends SIGKILL to the VM process.
func (*QEMUManager) Remove ¶
func (m *QEMUManager) Remove(_ context.Context, id string) error
Remove deletes a stopped VM from the registry.
func (*QEMUManager) Signal ¶
Signal sends sig to the VM. SIGKILL terminates the QEMU host process immediately (cross-platform). All other signals request graceful guest shutdown via QEMU QMP (system_powerdown sends an ACPI power-button event); if QMP is unavailable the call falls back to an OS-level signal (Linux/macOS only).
func (*QEMUManager) Start ¶
func (m *QEMUManager) Start(ctx context.Context, id string) error
Start launches the QEMU process for the VM identified by id. The ctx parameter controls the command lifecycle; canceling ctx will kill the QEMU process via exec.CommandContext.
func (*QEMUManager) Stop ¶
func (m *QEMUManager) Stop(ctx context.Context, id string) error
Stop gracefully shuts down the VM: sends SIGTERM, waits up to gracePeriod, then kills if still running.
func (*QEMUManager) Store ¶
func (m *QEMUManager) Store() Store
Store returns the underlying Store for lifecycle operations like Restore.
type RestartConfig ¶
type RestartConfig struct {
// Policy is the restart policy: "never", "on-failure", or "always".
Policy RestartPolicy
// MaxRetries is the maximum number of restart attempts. 0 means unlimited.
MaxRetries int
}
RestartConfig controls automatic VM restart behavior.
type RestartPolicy ¶
type RestartPolicy string
RestartPolicy determines when a VM is automatically restarted after exiting.
const ( // RestartNever means the VM is never automatically restarted. RestartNever RestartPolicy = "never" // RestartOnFailure means the VM is restarted only if it exits with a non-zero // exit code (crash). RestartOnFailure RestartPolicy = "on-failure" // RestartAlways means the VM is always restarted regardless of exit status, // unless explicitly stopped. RestartAlways RestartPolicy = "always" )
type RuntimeStats ¶
type RuntimeStats struct {
ID string
State string
CPUPct float64
MemBytes int64
DiskBytes int64
NetRxBytes int64
NetTxBytes int64
Timestamp time.Time
Source string
}
RuntimeStats holds runtime resource usage for a VM.
type SQLiteStore ¶
type SQLiteStore struct {
MemoryStore
// contains filtered or unexported fields
}
func NewSQLiteStore ¶
func NewSQLiteStore(dsn string) (*SQLiteStore, error)
func (*SQLiteStore) Close ¶
func (s *SQLiteStore) Close() error
func (*SQLiteStore) Remove ¶
func (s *SQLiteStore) Remove(id string) error
func (*SQLiteStore) Restore ¶
func (s *SQLiteStore) Restore() error
func (*SQLiteStore) Save ¶
func (s *SQLiteStore) Save(v *VM) error
type State ¶
type State string
State represents a VM lifecycle state.
const ( // StateCreated is the initial state after registration. StateCreated State = "created" // StateStarting means the QEMU process is being launched. StateStarting State = "starting" // StateRunning means the QEMU process is alive. StateRunning State = "running" // StateStopping means a kill signal has been sent. StateStopping State = "stopping" // StateStopped means the QEMU process has exited. StateStopped State = "stopped" )
type StatsCollector ¶
type StatsCollector interface {
Collect() RuntimeStats
}
StatsCollector provides runtime resource usage for a VM process.
type Store ¶
type Store interface {
Create(cfg Config) (*VM, error)
Get(id string) (*VM, error)
Resolve(nameOrID string) (*VM, error)
List() []*VM
Remove(id string) error
Save(v *VM) error
Restore() error
}
Store is the interface for a VM registry. Implementations may persist state to disk (FileStore) or keep it in memory only (MemoryStore).
type VM ¶
type VM struct {
// ID uniquely identifies the VM.
ID string
// Cfg is the configuration the VM was created with.
Cfg Config
// State is the current lifecycle state.
State State
// CreatedAt is when the VM was registered.
CreatedAt time.Time
// StartedAt is when the QEMU process started (nil until then).
StartedAt *time.Time
// StoppedAt is when the QEMU process exited (nil until then).
StoppedAt *time.Time
// DaemonRecovered is true when this VM was recovered from a previous
// daemon run. The original QEMU process is gone; the VM is in StateStopped.
DaemonRecovered bool
// HealthStatus is the latest probe result. "unknown" if no health check.
HealthStatus HealthStatus
// RestartCount is the number of times this VM has been restarted.
RestartCount int
// contains filtered or unexported fields
}
VM is a managed unikernel instance. All exported fields are read-only after Start; internal mutation is guarded by mu.
func (*VM) AttachReader ¶
AttachReader returns a reader that streams QEMU serial console output. Returns nil if no attach pipe was created (VM not started in attach mode).
func (*VM) Done ¶
func (v *VM) Done() <-chan struct{}
Done returns a channel that is closed when the VM reaches StateStopped.
func (*VM) GetHealthStatus ¶
func (v *VM) GetHealthStatus() HealthStatus
GetHealthStatus returns the current health status under a read lock.
func (*VM) GetRestartCount ¶
GetRestartCount returns the number of times this VM has been restarted.
func (*VM) IsExplicitStop ¶
IsExplicitStop returns whether the VM was explicitly stopped.
func (*VM) SetExplicitStop ¶
func (v *VM) SetExplicitStop()
SetExplicitStop marks the VM as explicitly stopped by the user. When true, the monitor goroutine will not attempt to restart the VM.
func (*VM) SetHealthStatus ¶
func (v *VM) SetHealthStatus(s HealthStatus)
SetHealthStatus sets the health status under a write lock.
func (*VM) SetStatsProvider ¶
func (v *VM) SetStatsProvider(fn func() RuntimeStats)
SetStatsProvider sets the function that returns live VM stats.
func (*VM) Stats ¶
func (v *VM) Stats() RuntimeStats
Stats returns the current runtime stats for the VM. If no stats provider is available, it returns a minimal snapshot.
type VolumeMount ¶
type VolumeMount struct {
// DiskPath is the absolute path to the raw disk image on the host.
DiskPath string
// GuestPath is the mount point inside the VM. The hypervisor passes
// "Label:GuestPath" to the guest kernel (QEMU fw_cfg opt/uni/mounts or
// Firecracker boot args) so the volume is mounted there.
GuestPath string
// ReadOnly marks the volume as read-only.
ReadOnly bool
// Label is the volume's TFS filesystem label, used by the guest kernel's
// volume_match to bind this disk to GuestPath. Empty volumes are skipped
// for mount injection (attached as a bare block device only).
Label string
}
VolumeMount describes a volume attached to a VM.