rustcracker/model/machine_configuration.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
use log::error;
use serde::{Deserialize, Serialize};
use crate::{components::machine::MachineError, utils::Json};
use super::cpu_template::CPUTemplate;
/// # Example
///
/// ```
/// // This piece of code will give you a machine configuration with
/// // CPU template set to C3, 8 virtual CPU, memory
/// // size set to 1024 MiB, hyperthreading enabled and
/// // dirty pages tracking disabled.
/// use rustcracker::model::machine_configuration::MachineConfiguration;
/// use rustcracker::model::cpu_template::{CPUTemplate, CPUTemplateString};
/// let machine_config =
/// MachineConfiguration::default()
/// .with_cpu_template(&CPUTemplate(CPUTemplateString::C3))
/// .with_vcpu_count(8)
/// .with_mem_size_mib(1024)
/// .set_hyperthreading(true)
/// .set_track_dirty_pages(false);
/// ```
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct MachineConfiguration {
/// cpu template
#[serde(rename = "cpu_template", skip_serializing_if = "Option::is_none")]
pub cpu_template: Option<CPUTemplate>,
/// Flag for enabling/disabling Hyperthreading
/// Required: true
#[serde(rename = "smt", skip_serializing_if = "Option::is_none")]
pub ht_enabled: Option<bool>,
/// Memory size of VM
/// Required: true
#[serde(rename = "mem_size_mib")]
pub mem_size_mib: isize,
/// Enable dirty page tracking.
/// If this is enabled, then incremental guest memory snapshots can be created.
/// These belong to diff snapshots, which contain, besides the microVM state, only the memory dirtied since
/// a previous snapshot. Full snapshots each contain a full copy of the guest memory.
#[serde(rename = "track_dirty_pages", skip_serializing_if = "Option::is_none")]
pub track_dirty_pages: Option<bool>,
/// Number of vCPUs (either 1 or an even number)
/// Required: true
/// Maximum: 32
/// Minimum: 1
#[serde(rename = "vcpu_count")]
pub vcpu_count: isize,
}
impl<'a> Json<'a> for MachineConfiguration {
type Item = MachineConfiguration;
}
impl Default for MachineConfiguration {
/// Get a default MachineConfiguration instance.
/// By default, it disables hyperthreading, set memory
/// size to 0 and allocate no vCPU for the machine.
fn default() -> Self {
Self {
cpu_template: None,
ht_enabled: Some(false),
mem_size_mib: 0,
track_dirty_pages: None,
vcpu_count: 0,
}
}
}
impl MachineConfiguration {
pub fn with_cpu_template(mut self, cpu_template: &CPUTemplate) -> Self {
self.cpu_template = Some(cpu_template.to_owned());
self
}
pub fn set_hyperthreading(mut self, b: bool) -> Self {
self.ht_enabled = Some(b);
self
}
pub fn with_mem_size_mib(mut self, m: isize) -> Self {
self.mem_size_mib = m;
self
}
pub fn set_track_dirty_pages(mut self, b: bool) -> Self {
self.track_dirty_pages = Some(b);
self
}
pub fn with_vcpu_count(mut self, c: isize) -> Self {
self.vcpu_count = c;
self
}
pub fn get_vcpu_count(&self) -> isize {
self.vcpu_count
}
pub fn is_ht_enabled(&self) -> bool {
if self.ht_enabled.is_none() {
return false;
} else {
return *self.ht_enabled.as_ref().unwrap();
}
}
pub fn get_mem_size_in_mib(&self) -> isize {
self.mem_size_mib
}
#[must_use="must validate MachineConfiguration before putting it to microVm"]
pub fn validate(&self) -> Result<(), MachineError> {
if self.vcpu_count < 1 {
error!(target: "MachineConfiguration::validate", "machine needs a non-zero vcpu count");
return Err(MachineError::Validation(
"machine needs a non-zero vcpu count".to_string(),
));
}
if self.mem_size_mib < 1 {
error!(target: "MachineConfiguration::validate", "machine needs a non-zero amount of memory");
return Err(MachineError::Validation(
"machine needs a non-zero amount of memory".to_string(),
));
}
Ok(())
}
}