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 /// If set, the VM boots from a snapshot via `PUT /snapshot/load` instead of cold-booting.
71 /// The spec's `kernel`, `rootfs`, `vcpu_count`, `mem_size_mib`, `boot_args`, and
72 /// `network_interfaces` are ignored when restoring (the snapshot encodes its own machine
73 /// config). Use [`SnapshotRef::network_overrides`] to swap network interfaces on restore.
74 pub restore_from: Option<SnapshotRef>,
75 /// Track dirty pages during execution — required to later capture diff snapshots.
76 /// None = enabled (FC's safer default for snapshot-friendly workloads).
77 pub track_dirty_pages: Option<bool>,
78}
79
80/// Firecracker `RateLimiter` config, applicable to drives and network interfaces.
81///
82/// At least one of `bandwidth` / `ops` should be set; setting both is allowed.
83/// See <https://github.com/firecracker-microvm/firecracker/blob/main/docs/api_requests/patch-rate-limiter.md>.
84#[derive(Debug, Clone, Default)]
85pub struct RateLimiter {
86 /// Bandwidth token bucket (units = bytes).
87 pub bandwidth: Option<TokenBucket>,
88 /// Operations token bucket (units = IO ops).
89 pub ops: Option<TokenBucket>,
90}
91
92/// Token bucket parameters. Caller specifies `refill_time_ms`; serialization translates
93/// to Firecracker's `refill_time` (also in ms — but we keep the suffix explicit on our side
94/// to avoid the "is this seconds?" question).
95#[derive(Debug, Clone)]
96pub struct TokenBucket {
97 /// Bucket size (bytes for bandwidth, ops for ops).
98 pub size: u64,
99 /// Optional one-time burst capacity used at start. Defaults to `size` if `None`.
100 pub one_time_burst: Option<u64>,
101 /// Refill period in milliseconds.
102 pub refill_time_ms: u64,
103}
104
105/// Network interface attached to a VM.
106#[derive(Debug, Clone)]
107pub struct NetworkInterface {
108 /// Identifier used by FC for this interface (e.g. `"eth0"`).
109 pub iface_id: String,
110 /// Host-side TAP device name (e.g. `"tap-abcd1234"`).
111 pub host_dev_name: String,
112 /// Guest-visible MAC address. None = let Firecracker assign one.
113 pub guest_mac: Option<String>,
114 /// Rate limit applied to received traffic on this NIC.
115 pub rx_rate_limiter: Option<RateLimiter>,
116 /// Rate limit applied to transmitted traffic on this NIC.
117 pub tx_rate_limiter: Option<RateLimiter>,
118}
119
120/// Reference to a snapshot used to restore a VM.
121#[derive(Debug, Clone)]
122pub struct SnapshotRef {
123 /// VM the snapshot was taken from.
124 pub vm_id: String,
125 /// Snapshot name.
126 pub snapshot_id: String,
127 /// If true, transition straight to `Running` after restore (Firecracker's `resume_vm` flag).
128 /// If false, the VM is restored in Paused state and needs an explicit `start_vm`.
129 pub resume_immediately: bool,
130 /// If non-empty, replace the snapshot's recorded network interfaces with these on load.
131 /// Use this for warm-pool handoff: a pre-restored VM swaps its TAP/MAC to a new tenant
132 /// without a full re-boot. Firecracker 1.10+ required; earlier versions reject the field.
133 pub network_overrides: Vec<NetworkInterface>,
134}