package model // VMHandles captures the transient, per-boot kernel/process handles // that banger obtains while starting a VM and releases when stopping // it. Unlike VMRuntime (durable spec + identity + derived paths), // VMHandles is the authoritative live-handle view while the daemon is // up. On restart, the daemon rebuilds it from the OS plus the per-VM // scratch file; teardown-critical fields are also mirrored onto // VMRuntime so cleanup can still proceed if that scratch file is // missing or corrupt. // // The daemon keeps an in-memory cache keyed by VM ID. Lifecycle // transitions update the cache and a small `handles.json` scratch // file in the VM's state directory; daemon startup reconciles // by loading that file and verifying each handle against the live // OS state. If anything is stale the VM is marked stopped and the // cache entry is dropped. // // VMHandles itself never appears in the `vms` SQLite rows. Some fields // are mirrored onto VMRuntime as crash-recovery fallback state, but the // cache + scratch file remain the canonical live source. type VMHandles struct { // PID is the firecracker process PID. Zero means "not running // (from our perspective)". Always verifiable via // /proc//cmdline matching the api socket path. PID int `json:"pid,omitempty"` // TapDevice is the kernel tap interface name (e.g. "tap-fc-0001") // bound to the VM's virtio-net. Released on stop. TapDevice string `json:"tap_device,omitempty"` // BaseLoop and COWLoop are the two loop devices backing the // dm-snapshot layer (read-only base = rootfs; read-write overlay // = per-VM COW file). Released via losetup -d on stop. BaseLoop string `json:"base_loop,omitempty"` COWLoop string `json:"cow_loop,omitempty"` // DMName is the device-mapper target name; deterministic from the // VM ID (see dmsnap.SnapshotName). DMDev is the corresponding // /dev/mapper/ path. Torn down by `dmsetup remove` on stop. DMName string `json:"dm_name,omitempty"` DMDev string `json:"dm_dev,omitempty"` } // IsZero reports whether every handle field is unset. Useful as a // cheap "this VM has no kernel/process resources held on our behalf" // check. func (h VMHandles) IsZero() bool { return h.PID == 0 && h.TapDevice == "" && h.BaseLoop == "" && h.COWLoop == "" && h.DMName == "" && h.DMDev == "" }