use crate::validation::{validate_existing_path, validate_unix_path};
use lazy_static::lazy_static;
use regex::Regex;
use serde::{Deserialize, Serialize};
use validator::Validate;
pub use crate::logger::Logger;
#[derive(Debug, Serialize, Deserialize)]
pub struct Balloon {
pub amount_mib: u32,
#[serde(skip_serializing_if = "Option::is_none")]
pub deflate_on_oom: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub stats_polling_interval_s: Option<u32>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct BalloonStats {
pub actual_mib: u32,
pub actual_pages: u32,
#[serde(skip_serializing_if = "Option::is_none")]
pub available_memory: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub disk_caches: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub free_memory: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub hugetlb_allocations: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub hugetlb_failures: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub major_faults: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub minor_faults: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub swap_in: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub swap_out: Option<i64>,
pub target_mib: u32,
pub target_pages: u32,
#[serde(skip_serializing_if = "Option::is_none")]
pub total_memory: Option<i64>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct BalloonStatsUpdate {
pub stats_polling_interval_s: u32,
}
#[derive(Debug, Default, Serialize, Deserialize, Validate)]
pub struct BootSource {
#[serde(skip_serializing_if = "Option::is_none")]
pub boot_args: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
#[validate(custom = "validate_existing_path")]
pub initrd_path: Option<String>,
#[validate(custom = "validate_existing_path")]
pub kernel_image_path: String,
}
#[derive(Debug, Default, Serialize, Deserialize)]
pub struct CpuConfig {
#[serde(skip_serializing_if = "Option::is_none")]
pub cpuid_modifiers: Option<serde_json::Value>,
#[serde(skip_serializing_if = "Option::is_none")]
pub kvm_capabilities: Option<serde_json::Value>,
#[serde(skip_serializing_if = "Option::is_none")]
pub msr_modifiers: Option<serde_json::Value>,
#[serde(skip_serializing_if = "Option::is_none")]
pub reg_modifiers: Option<serde_json::Value>,
#[serde(skip_serializing_if = "Option::is_none")]
pub vcpu_features: Option<serde_json::Value>,
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub enum CpuTemplate {
C3,
None,
T2,
T2A,
T2CL,
T2S,
V1N1,
}
#[derive(Debug, Default, Serialize, Deserialize, Validate)]
pub struct Drive {
#[serde(skip_serializing_if = "Option::is_none")]
pub cache_type: Option<String>,
pub drive_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub io_engine: Option<String>,
pub is_read_only: bool,
pub is_root_device: bool,
#[serde(skip_serializing_if = "Option::is_none")]
#[validate(regex(path = "PARTUUID_REGEX", message = "Invalid partition UUID format"))]
pub partuuid: Option<String>,
#[validate(custom = "validate_existing_path")]
pub path_on_host: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub rate_limiter: Option<RateLimiter>,
#[serde(skip_serializing_if = "Option::is_none")]
pub socket: Option<String>,
}
#[derive(Debug, Default, Serialize, Deserialize)]
pub struct EntropyDevice {
#[serde(skip_serializing_if = "Option::is_none")]
pub rate_limiter: Option<RateLimiter>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Error {
pub fault_message: String,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct FirecrackerVersion {
pub firecracker_version: String,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct InstanceInfo {
pub app_name: String,
pub id: String,
pub state: String,
pub vmm_version: String,
}
#[derive(Debug, Default, Serialize, Deserialize, Validate)]
pub struct MachineConfig {
#[serde(skip_serializing_if = "Option::is_none")]
pub cpu_template: Option<CpuTemplate>,
#[serde(skip_serializing_if = "Option::is_none")]
pub huge_pages: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub mem_size_mib: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub smt: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub track_dirty_pages: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub vcpu_count: Option<u32>,
}
#[derive(Debug, Default, Serialize, Deserialize)]
pub struct Metrics {
pub metrics_path: String,
}
#[derive(Debug, Default, Serialize, Deserialize)]
pub struct MmdsConfig {
#[serde(skip_serializing_if = "Option::is_none")]
pub ipv4_address: Option<String>,
pub network_interfaces: Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub version: Option<String>,
}
#[derive(Debug, Default, Serialize, Deserialize, Validate)]
pub struct NetworkInterface {
#[serde(skip_serializing_if = "Option::is_none")]
#[validate(regex(path = "MAC_ADDRESS_REGEX", message = "Invalid MAC address format"))]
pub guest_mac: Option<String>,
#[validate(custom = "validate_unix_path")]
pub host_dev_name: String,
#[validate(length(min = 1))]
pub iface_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub rx_rate_limiter: Option<RateLimiter>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tx_rate_limiter: Option<RateLimiter>,
}
#[derive(Debug, Default, Serialize, Deserialize)]
pub struct RateLimiter {
#[serde(skip_serializing_if = "Option::is_none")]
pub bandwidth: Option<TokenBucket>,
#[serde(skip_serializing_if = "Option::is_none")]
pub ops: Option<TokenBucket>,
}
#[derive(Debug, Default, Serialize, Deserialize)]
pub struct TokenBucket {
pub one_time_burst: Option<i64>,
pub refill_time: i64,
pub size: i64,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Vm {
pub state: String,
}
#[derive(Debug, Serialize, Deserialize, Validate)]
pub struct Vsock {
pub guest_cid: u32,
#[validate(custom = "validate_unix_path")]
pub uds_path: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub vsock_id: Option<String>,
}
#[derive(Debug, Default, Serialize, Deserialize, Validate)]
pub struct VmConfig {
pub balloon: Option<Balloon>,
pub boot_source: Option<BootSource>,
pub drives: Vec<Drive>,
pub machine_config: Option<MachineConfig>,
pub network_interfaces: Vec<NetworkInterface>,
}
lazy_static! {
static ref MAC_ADDRESS_REGEX: Regex =
Regex::new(r"^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$").unwrap();
static ref PARTUUID_REGEX: Regex = Regex::new(
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}$"
)
.unwrap();
}