use crate::machine::MachineState;
use uuid::Uuid;
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct VmId(String);
impl VmId {
#[must_use]
pub fn new() -> Self {
Self(Uuid::new_v4().to_string())
}
#[cfg(test)]
pub(crate) fn from_string(id: String) -> Self {
Self(id)
}
#[must_use]
pub fn as_str(&self) -> &str {
&self.0
}
}
impl Default for VmId {
fn default() -> Self {
Self::new()
}
}
impl std::fmt::Display for VmId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
#[must_use]
pub fn bridge_nic_mac_for_vm_id(vm_id: &VmId) -> String {
let hex: String = vm_id
.as_str()
.chars()
.filter(|ch| ch.is_ascii_hexdigit())
.collect();
let mut bytes = [0_u8; 6];
bytes[0] = 0x02;
for (index, chunk) in hex.as_bytes().chunks(2).take(5).enumerate() {
let text = std::str::from_utf8(chunk).unwrap_or("00");
bytes[index + 1] = u8::from_str_radix(text, 16).unwrap_or(0);
}
format!(
"{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5]
)
}
#[derive(Debug, Clone)]
pub struct VmInfo {
pub id: VmId,
pub state: MachineState,
pub cpus: u32,
pub memory_mb: u64,
}
#[derive(Debug, Clone)]
pub struct SharedDirConfig {
pub host_path: String,
pub tag: String,
pub read_only: bool,
}
impl SharedDirConfig {
#[must_use]
pub fn new(host_path: impl Into<String>, tag: impl Into<String>) -> Self {
Self {
host_path: host_path.into(),
tag: tag.into(),
read_only: false,
}
}
#[must_use]
pub const fn read_only(mut self) -> Self {
self.read_only = true;
self
}
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct BlockDeviceConfig {
pub path: String,
pub read_only: bool,
}
#[derive(Debug, Clone)]
pub struct VmConfig {
pub cpus: u32,
pub memory_mb: u64,
pub kernel: Option<String>,
pub cmdline: Option<String>,
pub shared_dirs: Vec<SharedDirConfig>,
pub block_devices: Vec<BlockDeviceConfig>,
pub networking: bool,
pub vsock: bool,
pub guest_cid: Option<u32>,
pub balloon: bool,
pub rosetta: bool,
pub backend: arcbox_vmm::VmBackend,
}
impl Default for VmConfig {
fn default() -> Self {
Self {
cpus: arcbox_hypervisor::default_vm_cpu_count(),
memory_mb: 4096,
kernel: None,
cmdline: None,
shared_dirs: Vec::new(),
block_devices: Vec::new(),
networking: true,
vsock: true,
guest_cid: None,
balloon: true,
rosetta: cfg!(all(target_os = "macos", target_arch = "aarch64")),
backend: arcbox_vmm::VmBackend::default(),
}
}
}