firecracker_http_client/
models.rs

1use crate::validation::{validate_existing_path, validate_unix_path};
2use lazy_static::lazy_static;
3use regex::Regex;
4use serde::{Deserialize, Serialize};
5use validator::Validate;
6
7// Re-exports
8pub use crate::logger::Logger;
9
10// Core types
11
12/// Represents a memory balloon device that can dynamically adjust guest memory size.
13/// This device allows for memory overcommitment by reclaiming unused memory from the guest
14/// and making it available to the host or other guests. It's particularly useful in
15/// environments where memory resources need to be managed efficiently across multiple VMs.
16#[derive(Debug, Serialize, Deserialize)]
17pub struct Balloon {
18    /// Target balloon size in MiB
19    pub amount_mib: u32,
20    /// Whether the balloon should deflate when the guest has memory pressure
21    #[serde(skip_serializing_if = "Option::is_none")]
22    pub deflate_on_oom: Option<bool>,
23    /// Interval in seconds between refreshing statistics. A non-zero value will enable the statistics. Defaults to 0
24    #[serde(skip_serializing_if = "Option::is_none")]
25    pub stats_polling_interval_s: Option<u32>,
26}
27
28/// Provides detailed memory statistics from the balloon device, helping monitor
29/// memory usage patterns and performance of the guest VM. These statistics are
30/// essential for making informed decisions about memory allocation and identifying
31/// potential memory-related issues.
32#[derive(Debug, Serialize, Deserialize)]
33pub struct BalloonStats {
34    /// Actual amount of memory (in MiB) the device is holding
35    pub actual_mib: u32,
36    /// Actual number of pages the device is holding
37    pub actual_pages: u32,
38    /// An estimate of how much memory is available (in bytes) for starting new applications, without pushing the system to swap
39    #[serde(skip_serializing_if = "Option::is_none")]
40    pub available_memory: Option<i64>,
41    /// The amount of memory, in bytes, that can be quickly reclaimed without additional I/O. Typically these pages are used for caching files from disk
42    #[serde(skip_serializing_if = "Option::is_none")]
43    pub disk_caches: Option<i64>,
44    /// The amount of memory not being used for any purpose (in bytes)
45    #[serde(skip_serializing_if = "Option::is_none")]
46    pub free_memory: Option<i64>,
47    /// The number of successful hugetlb page allocations in the guest
48    #[serde(skip_serializing_if = "Option::is_none")]
49    pub hugetlb_allocations: Option<i64>,
50    /// The number of failed hugetlb page allocations in the guest
51    #[serde(skip_serializing_if = "Option::is_none")]
52    pub hugetlb_failures: Option<i64>,
53    /// The number of major page faults that have occurred
54    #[serde(skip_serializing_if = "Option::is_none")]
55    pub major_faults: Option<i64>,
56    /// The number of minor page faults that have occurred
57    #[serde(skip_serializing_if = "Option::is_none")]
58    pub minor_faults: Option<i64>,
59    /// The amount of memory that has been swapped in (in bytes)
60    #[serde(skip_serializing_if = "Option::is_none")]
61    pub swap_in: Option<i64>,
62    /// The amount of memory that has been swapped out to disk (in bytes)
63    #[serde(skip_serializing_if = "Option::is_none")]
64    pub swap_out: Option<i64>,
65    /// Target amount of memory (in MiB) the device aims to hold
66    pub target_mib: u32,
67    /// Target number of pages the device aims to hold
68    pub target_pages: u32,
69    /// The total amount of memory available (in bytes)
70    #[serde(skip_serializing_if = "Option::is_none")]
71    pub total_memory: Option<i64>,
72}
73
74/// Used to update the statistics polling interval of a balloon device.
75/// This allows for dynamic adjustment of how frequently memory statistics
76/// are collected without needing to recreate the balloon device.
77#[derive(Debug, Serialize, Deserialize)]
78pub struct BalloonStatsUpdate {
79    /// Interval in seconds between refreshing statistics
80    pub stats_polling_interval_s: u32,
81}
82
83/// Defines the boot configuration for a microVM, specifying the kernel image,
84/// optional initial ramdisk, and kernel boot parameters. This configuration
85/// must be set before starting the microVM and cannot be modified after boot.
86#[derive(Debug, Default, Serialize, Deserialize, Validate)]
87pub struct BootSource {
88    /// Kernel boot arguments
89    #[serde(skip_serializing_if = "Option::is_none")]
90    pub boot_args: Option<String>,
91    /// Host level path to the initrd image used to boot the guest
92    #[serde(skip_serializing_if = "Option::is_none")]
93    #[validate(custom = "validate_existing_path")]
94    pub initrd_path: Option<String>,
95    /// Host level path to the kernel image used to boot the guest
96    #[validate(custom = "validate_existing_path")]
97    pub kernel_image_path: String,
98}
99
100/// Provides fine-grained control over CPU features exposed to the guest VM.
101/// This allows for platform-specific optimizations and security configurations
102/// by enabling or disabling specific CPU capabilities on both x86_64 and aarch64
103/// architectures.
104#[derive(Debug, Default, Serialize, Deserialize)]
105pub struct CpuConfig {
106    /// A collection of CPUIDs to be modified (x86_64)
107    #[serde(skip_serializing_if = "Option::is_none")]
108    pub cpuid_modifiers: Option<serde_json::Value>,
109    /// A collection of kvm capabilities to be modified (aarch64)
110    #[serde(skip_serializing_if = "Option::is_none")]
111    pub kvm_capabilities: Option<serde_json::Value>,
112    /// A collection of model specific registers to be modified (x86_64)
113    #[serde(skip_serializing_if = "Option::is_none")]
114    pub msr_modifiers: Option<serde_json::Value>,
115    /// A collection of registers to be modified (aarch64)
116    #[serde(skip_serializing_if = "Option::is_none")]
117    pub reg_modifiers: Option<serde_json::Value>,
118    /// A collection of vcpu features to be modified (aarch64)
119    #[serde(skip_serializing_if = "Option::is_none")]
120    pub vcpu_features: Option<serde_json::Value>,
121}
122
123/// Predefined CPU templates that configure sets of CPU features to match
124/// specific AWS EC2 instance types. This ensures consistent CPU feature
125/// sets across different Firecracker deployments and helps with workload
126/// compatibility.
127#[derive(Debug, Serialize, Deserialize)]
128#[serde(rename_all = "PascalCase")]
129pub enum CpuTemplate {
130    C3,
131    None,
132    T2,
133    T2A,
134    T2CL,
135    T2S,
136    V1N1,
137}
138
139/// Represents a block device in the guest VM. This can be either a regular
140/// file or a block device on the host that is exposed to the guest. Supports
141/// both read-only and read-write modes, and can be configured as the root
142/// device for the guest filesystem.
143#[derive(Debug, Default, Serialize, Deserialize, Validate)]
144pub struct Drive {
145    /// Represents the caching strategy for the block device
146    #[serde(skip_serializing_if = "Option::is_none")]
147    pub cache_type: Option<String>,
148    /// Unique identifier for the drive
149    pub drive_id: String,
150    /// Type of IO engine
151    #[serde(skip_serializing_if = "Option::is_none")]
152    pub io_engine: Option<String>,
153    /// Whether the block device is read-only
154    pub is_read_only: bool,
155    /// Whether this is the root device
156    pub is_root_device: bool,
157    /// Unique id of the boot partition (only used if is_root_device is true)
158    #[serde(skip_serializing_if = "Option::is_none")]
159    #[validate(regex(path = "PARTUUID_REGEX", message = "Invalid partition UUID format"))]
160    pub partuuid: Option<String>,
161    /// Host level path for the guest drive
162    #[validate(custom = "validate_existing_path")]
163    pub path_on_host: String,
164    /// Rate limiter for the drive
165    #[serde(skip_serializing_if = "Option::is_none")]
166    pub rate_limiter: Option<RateLimiter>,
167    /// Socket path for the drive
168    #[serde(skip_serializing_if = "Option::is_none")]
169    pub socket: Option<String>,
170}
171
172/// Configures a virtual device that provides entropy/randomness to the guest VM.
173/// This is crucial for applications in the guest that require cryptographic
174/// operations or random number generation.
175#[derive(Debug, Default, Serialize, Deserialize)]
176pub struct EntropyDevice {
177    /// Rate limiter for the entropy device
178    #[serde(skip_serializing_if = "Option::is_none")]
179    pub rate_limiter: Option<RateLimiter>,
180}
181
182/// Represents an error response from the Firecracker API. Used to provide
183/// detailed information about what went wrong during an API operation.
184#[derive(Debug, Serialize, Deserialize)]
185pub struct Error {
186    /// Error message describing the fault
187    pub fault_message: String,
188}
189
190/// Contains version information about the Firecracker service.
191/// Used to ensure compatibility between the client and server.
192#[derive(Debug, Serialize, Deserialize)]
193pub struct FirecrackerVersion {
194    /// Version of the Firecracker service
195    pub firecracker_version: String,
196}
197
198/// Provides metadata about a Firecracker instance, including its
199/// identity, current state, and version information. This is useful
200/// for monitoring and managing multiple Firecracker instances.
201#[derive(Debug, Serialize, Deserialize)]
202pub struct InstanceInfo {
203    /// Name of the application
204    pub app_name: String,
205    /// Instance identifier
206    pub id: String,
207    /// Current state of the instance
208    pub state: String,
209    /// Version of the VMM
210    pub vmm_version: String,
211}
212
213/// Defines the core configuration of a microVM, including CPU and memory
214/// resources. These settings determine the computational capacity and
215/// performance characteristics of the VM.
216#[derive(Debug, Default, Serialize, Deserialize, Validate)]
217pub struct MachineConfig {
218    /// CPU template for configuring guest CPU features
219    #[serde(skip_serializing_if = "Option::is_none")]
220    pub cpu_template: Option<CpuTemplate>,
221    /// Huge pages configuration
222    #[serde(skip_serializing_if = "Option::is_none")]
223    pub huge_pages: Option<String>,
224    /// Memory size in MiB
225    #[serde(skip_serializing_if = "Option::is_none")]
226    pub mem_size_mib: Option<u32>,
227    /// Enable/disable Simultaneous Multi-Threading
228    #[serde(skip_serializing_if = "Option::is_none")]
229    pub smt: Option<bool>,
230    /// Enable/disable dirty page tracking
231    #[serde(skip_serializing_if = "Option::is_none")]
232    pub track_dirty_pages: Option<bool>,
233    /// Number of vCPUs
234    #[serde(skip_serializing_if = "Option::is_none")]
235    pub vcpu_count: Option<u32>,
236}
237
238/// Configures the metrics system for Firecracker, allowing for monitoring
239/// of various performance and operational metrics of the microVM.
240#[derive(Debug, Default, Serialize, Deserialize)]
241pub struct Metrics {
242    /// Path to store metrics
243    pub metrics_path: String,
244}
245
246/// Configures the Microvm Metadata Service (MMDS), which provides a way
247/// for the guest to securely access metadata and user data. This is similar
248/// to AWS EC2's instance metadata service.
249#[derive(Debug, Default, Serialize, Deserialize)]
250pub struct MmdsConfig {
251    /// IPv4 address for the MMDS
252    #[serde(skip_serializing_if = "Option::is_none")]
253    pub ipv4_address: Option<String>,
254    /// List of network interfaces for MMDS
255    pub network_interfaces: Vec<String>,
256    /// Version of the MMDS
257    #[serde(skip_serializing_if = "Option::is_none")]
258    pub version: Option<String>,
259}
260
261/// Defines a network interface for the guest VM, allowing for network
262/// connectivity. Supports configuration of MAC addresses and rate limiting
263/// for both receive and transmit traffic.
264#[derive(Debug, Default, Serialize, Deserialize, Validate)]
265pub struct NetworkInterface {
266    /// MAC address of the guest network interface
267    #[serde(skip_serializing_if = "Option::is_none")]
268    #[validate(regex(path = "MAC_ADDRESS_REGEX", message = "Invalid MAC address format"))]
269    pub guest_mac: Option<String>,
270    /// Host level path for the guest network interface
271    #[validate(custom = "validate_unix_path")]
272    pub host_dev_name: String,
273    /// Network interface identifier
274    #[validate(length(min = 1))]
275    pub iface_id: String,
276    /// Rate limiter for received traffic
277    #[serde(skip_serializing_if = "Option::is_none")]
278    pub rx_rate_limiter: Option<RateLimiter>,
279    /// Rate limiter for transmitted traffic
280    #[serde(skip_serializing_if = "Option::is_none")]
281    pub tx_rate_limiter: Option<RateLimiter>,
282}
283
284/// Implements rate limiting for I/O operations, allowing control over
285/// bandwidth and operations per second. This is used by various devices
286/// like network interfaces and block devices to prevent resource exhaustion.
287#[derive(Debug, Default, Serialize, Deserialize)]
288pub struct RateLimiter {
289    /// Bandwidth rate limiter
290    #[serde(skip_serializing_if = "Option::is_none")]
291    pub bandwidth: Option<TokenBucket>,
292    /// Operations rate limiter
293    #[serde(skip_serializing_if = "Option::is_none")]
294    pub ops: Option<TokenBucket>,
295}
296
297/// Implements the token bucket algorithm for rate limiting. This provides
298/// a way to control both the steady-state rate and burst capacity for
299/// operations or bandwidth.
300#[derive(Debug, Default, Serialize, Deserialize)]
301pub struct TokenBucket {
302    /// Initial burst size
303    pub one_time_burst: Option<i64>,
304    /// Refill time in milliseconds
305    pub refill_time: i64,
306    /// Bucket size
307    pub size: i64,
308}
309
310/// Represents the state of a Firecracker microVM. Used primarily in
311/// the context of VM lifecycle management and snapshotting operations.
312#[derive(Debug, Serialize, Deserialize)]
313pub struct Vm {
314    /// Current state of the VM
315    pub state: String,
316}
317
318/// Configures a vsock device, which provides a communication channel
319/// between the host and guest. This is particularly useful for services
320/// that need to communicate across the VM boundary without using traditional
321/// networking.
322#[derive(Debug, Serialize, Deserialize, Validate)]
323pub struct Vsock {
324    /// CID for the guest vsock
325    pub guest_cid: u32,
326    /// Path to the vsock device
327    #[validate(custom = "validate_unix_path")]
328    pub uds_path: String,
329    /// Vsock identifier
330    #[serde(skip_serializing_if = "Option::is_none")]
331    pub vsock_id: Option<String>,
332}
333
334/// Represents the configuration of a Firecracker microVM, including its
335/// boot source, drives, network interfaces, and machine configuration.
336#[derive(Debug, Default, Serialize, Deserialize, Validate)]
337pub struct VmConfig {
338    /// Balloon configuration
339    pub balloon: Option<Balloon>,
340    /// Boot source configuration
341    pub boot_source: Option<BootSource>,
342    /// List of drives
343    pub drives: Vec<Drive>,
344    /// Machine configuration
345    pub machine_config: Option<MachineConfig>,
346    /// List of network interfaces
347    pub network_interfaces: Vec<NetworkInterface>,
348}
349
350lazy_static! {
351    static ref MAC_ADDRESS_REGEX: Regex =
352        Regex::new(r"^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$").unwrap();
353    static ref PARTUUID_REGEX: Regex = Regex::new(
354        r"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"
355    )
356    .unwrap();
357}