Skip to main content

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}