use std::fmt;
pub const MAX_SUPPORTED_VCPUS: u8 = 64;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct HostCpuId {
pub group: u16,
pub index: u16,
}
impl HostCpuId {
pub const fn new(index: u16) -> Self {
Self { group: 0, index }
}
pub const fn in_group(group: u16, index: u16) -> Self {
Self { group, index }
}
}
#[derive(Debug, Eq, PartialEq)]
pub enum VmConfigError {
InvalidVcpuCount,
InvalidMemorySize,
InvalidMaxVcpuCount,
InvalidMaxMemorySize,
MaxCapacityUnsupported,
}
impl fmt::Display for VmConfigError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::VmConfigError::*;
match *self {
InvalidVcpuCount => write!(
f,
"The vCPU number is invalid! The vCPU number can only \
be 1 or an even number when hyperthreading is enabled.",
),
InvalidMemorySize => write!(f, "The memory size (MiB) is invalid.",),
InvalidMaxVcpuCount => write!(
f,
"The maximum vCPU number is invalid! It must be at least the \
vCPU count and no larger than the supported vCPU limit.",
),
InvalidMaxMemorySize => write!(
f,
"The maximum memory size (MiB) is invalid! It must be at least \
the boot memory size.",
),
MaxCapacityUnsupported => write!(
f,
"Reserving CPU or memory capacity above the initial resources \
is not supported on this platform yet.",
),
}
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct VmConfig {
pub vcpu_count: Option<u8>,
pub mem_size_mib: Option<usize>,
pub max_vcpu_count: Option<u8>,
pub max_mem_size_mib: Option<usize>,
pub ht_enabled: Option<bool>,
pub cpu_template: Option<CpuFeaturesTemplate>,
}
impl Default for VmConfig {
fn default() -> Self {
VmConfig {
vcpu_count: Some(1),
mem_size_mib: Some(128),
max_vcpu_count: None,
max_mem_size_mib: None,
ht_enabled: Some(false),
cpu_template: None,
}
}
}
impl fmt::Display for VmConfig {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let vcpu_count = self.vcpu_count.unwrap_or(1);
let mem_size = self.mem_size_mib.unwrap_or(128);
let max_vcpu_count = self.max_vcpu_count.unwrap_or(vcpu_count);
let max_mem_size = self.max_mem_size_mib.unwrap_or(mem_size);
let ht_enabled = self.ht_enabled.unwrap_or(false);
let cpu_template = self
.cpu_template
.map_or("Uninitialized".to_string(), |c| c.to_string());
write!(f, "{{ \"vcpu_count\": {vcpu_count:?}, \"mem_size_mib\": {mem_size:?}, \"max_vcpu_count\": {max_vcpu_count:?}, \"max_mem_size_mib\": {max_mem_size:?}, \"ht_enabled\": {ht_enabled:?}, \"cpu_template\": {cpu_template:?} }}")
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum CpuFeaturesTemplate {
C3,
T2,
}
impl fmt::Display for CpuFeaturesTemplate {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
CpuFeaturesTemplate::C3 => write!(f, "C3"),
CpuFeaturesTemplate::T2 => write!(f, "T2"),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_display_cpu_features_template() {
assert_eq!(CpuFeaturesTemplate::C3.to_string(), "C3".to_string());
assert_eq!(CpuFeaturesTemplate::T2.to_string(), "T2".to_string());
}
#[test]
fn test_display_vm_config_error() {
let expected_str = "The vCPU number is invalid! The vCPU number can only \
be 1 or an even number when hyperthreading is enabled.";
assert_eq!(VmConfigError::InvalidVcpuCount.to_string(), expected_str);
let expected_str = "The memory size (MiB) is invalid.";
assert_eq!(VmConfigError::InvalidMemorySize.to_string(), expected_str);
}
}