microvm_runtime/model.rs
1use std::fmt;
2use std::path::PathBuf;
3
4use serde::Serialize;
5
6/// Current lifecycle state of a microVM.
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
8#[serde(rename_all = "snake_case")]
9pub enum VmStatus {
10 /// Provisioned but not yet started.
11 Created,
12 /// Actively running.
13 Running,
14 /// Gracefully stopped; can be restarted.
15 Stopped,
16 /// Torn down; terminal state.
17 Destroyed,
18}
19
20impl fmt::Display for VmStatus {
21 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
22 match self {
23 Self::Created => f.write_str("created"),
24 Self::Running => f.write_str("running"),
25 Self::Stopped => f.write_str("stopped"),
26 Self::Destroyed => f.write_str("destroyed"),
27 }
28 }
29}
30
31/// Read-only snapshot of a microVM's current state.
32#[derive(Debug, Clone, Serialize)]
33pub struct VmView {
34 /// Unique identifier for this microVM.
35 pub vm_id: String,
36 /// Current lifecycle status.
37 pub status: VmStatus,
38 /// Names of snapshots captured for this VM, in creation order.
39 pub snapshots: Vec<String>,
40}
41
42/// Per-VM configuration override. Every field is optional; `None` falls back to the
43/// provider's workspace-level default (e.g. [`FirecrackerConfig`](crate::adapters::firecracker::FirecrackerConfig)).
44///
45/// Use [`VmSpec::default`] for cold boot with workspace defaults, or set
46/// [`VmSpec::restore_from`] to restore from a snapshot instead of cold-booting.
47///
48/// To do a warm-pool handoff — a pre-restored VM that swaps its TAP and IP onto a
49/// new tenant — set [`VmSpec::restore_from`] with [`SnapshotRef::network_overrides`]
50/// populated. Firecracker 1.10+ supports this; 1.6 rejects it.
51#[derive(Debug, Clone, Default)]
52pub struct VmSpec {
53 /// Kernel image path. None = use workspace default.
54 pub kernel: Option<PathBuf>,
55 /// Rootfs image path. None = use workspace default.
56 pub rootfs: Option<PathBuf>,
57 /// Mount rootfs read-only. None = use workspace default.
58 pub rootfs_read_only: Option<bool>,
59 /// vCPU count override.
60 pub vcpu_count: Option<u8>,
61 /// Memory size in MiB override.
62 pub mem_size_mib: Option<u32>,
63 /// Kernel command-line override.
64 pub boot_args: Option<String>,
65 /// Rate limit applied to the rootfs drive.
66 pub rootfs_rate_limit: Option<RateLimiter>,
67 /// Network interfaces to attach pre-boot. Firecracker requires these to be configured
68 /// before `InstanceStart`. Empty by default — the VM has no network unless explicitly set.
69 pub network_interfaces: Vec<NetworkInterface>,
70 /// Additional drives beyond rootfs (e.g. workspace volume, sidecar, nix store).
71 /// Empty by default. Configured via `PUT /drives/<drive_id>`.
72 pub extra_drives: Vec<DriveSpec>,
73 /// Vsock device. When `Some`, configured via `PUT /vsock` before `InstanceStart`.
74 /// Required for guest↔host RPC channels (e.g. talking to a guest sidecar).
75 pub vsock: Option<VsockSpec>,
76 /// If set, the VM boots from a snapshot via `PUT /snapshot/load` instead of cold-booting.
77 /// The spec's `kernel`, `rootfs`, `vcpu_count`, `mem_size_mib`, `boot_args`,
78 /// `network_interfaces`, `extra_drives`, and `vsock` are ignored when restoring
79 /// (the snapshot encodes its own machine config). Use
80 /// [`SnapshotRef::network_overrides`] to swap network interfaces on restore.
81 pub restore_from: Option<SnapshotRef>,
82 /// Track dirty pages during execution — required to later capture diff snapshots.
83 /// None = enabled (FC's safer default for snapshot-friendly workloads).
84 pub track_dirty_pages: Option<bool>,
85}
86
87/// Additional drive beyond the rootfs.
88#[derive(Debug, Clone)]
89pub struct DriveSpec {
90 /// Identifier used by Firecracker for this drive (must be unique per VM).
91 pub drive_id: String,
92 /// Path on host to the backing file (ext4 image, or any block file).
93 pub path_on_host: PathBuf,
94 /// Mount as read-only in guest.
95 pub is_read_only: bool,
96 /// Optional bandwidth + ops rate limit.
97 pub rate_limiter: Option<RateLimiter>,
98}
99
100/// Vsock device config.
101///
102/// Firecracker's vsock implementation uses a unix socket on the host (`uds_path`) and
103/// a 32-bit Context ID (`cid`) that the guest reads to identify the channel.
104#[derive(Debug, Clone)]
105pub struct VsockSpec {
106 /// Guest context ID. Must not collide with other VMs on the same host.
107 /// Use [`crate::vsock::VsockManager`] to allocate.
108 pub cid: u32,
109 /// Host-side unix domain socket path. The parent directory MUST exist
110 /// before snapshot/load — see [`crate::vsock::VsockManager::ensure_uds_parent`].
111 pub uds_path: PathBuf,
112}
113
114/// Firecracker `RateLimiter` config, applicable to drives and network interfaces.
115///
116/// At least one of `bandwidth` / `ops` should be set; setting both is allowed.
117/// See <https://github.com/firecracker-microvm/firecracker/blob/main/docs/api_requests/patch-rate-limiter.md>.
118#[derive(Debug, Clone, Default)]
119pub struct RateLimiter {
120 /// Bandwidth token bucket (units = bytes).
121 pub bandwidth: Option<TokenBucket>,
122 /// Operations token bucket (units = IO ops).
123 pub ops: Option<TokenBucket>,
124}
125
126/// Token bucket parameters. Caller specifies `refill_time_ms`; serialization translates
127/// to Firecracker's `refill_time` (also in ms — but we keep the suffix explicit on our side
128/// to avoid the "is this seconds?" question).
129#[derive(Debug, Clone)]
130pub struct TokenBucket {
131 /// Bucket size (bytes for bandwidth, ops for ops).
132 pub size: u64,
133 /// Optional one-time burst capacity used at start. Defaults to `size` if `None`.
134 pub one_time_burst: Option<u64>,
135 /// Refill period in milliseconds.
136 pub refill_time_ms: u64,
137}
138
139/// Network interface attached to a VM.
140#[derive(Debug, Clone)]
141pub struct NetworkInterface {
142 /// Identifier used by FC for this interface (e.g. `"eth0"`).
143 pub iface_id: String,
144 /// Host-side TAP device name (e.g. `"tap-abcd1234"`).
145 pub host_dev_name: String,
146 /// Guest-visible MAC address. None = let Firecracker assign one.
147 pub guest_mac: Option<String>,
148 /// Rate limit applied to received traffic on this NIC.
149 pub rx_rate_limiter: Option<RateLimiter>,
150 /// Rate limit applied to transmitted traffic on this NIC.
151 pub tx_rate_limiter: Option<RateLimiter>,
152}
153
154/// Reference to a snapshot used to restore a VM.
155#[derive(Debug, Clone)]
156pub struct SnapshotRef {
157 /// VM the snapshot was taken from.
158 pub vm_id: String,
159 /// Snapshot name.
160 pub snapshot_id: String,
161 /// If true, transition straight to `Running` after restore (Firecracker's `resume_vm` flag).
162 /// If false, the VM is restored in Paused state and needs an explicit `start_vm`.
163 pub resume_immediately: bool,
164 /// If non-empty, replace the snapshot's recorded network interfaces with these on load.
165 /// Use this for warm-pool handoff: a pre-restored VM swaps its TAP/MAC to a new tenant
166 /// without a full re-boot. Firecracker 1.10+ required; earlier versions reject the field.
167 pub network_overrides: Vec<NetworkInterface>,
168}