mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-11-04 19:11:11 +00:00
main, vmm: Let the user define distincts memory zones
Introducing a new CLI option --memory-zone letting the user specify custom memory zones. When this option is present, the --memory size must be explicitly set to 0. Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
parent
d25ec66bb6
commit
be475ddc22
13
src/main.rs
13
src/main.rs
@ -114,6 +114,18 @@ fn create_app<'a, 'b>(
|
||||
.default_value(&default_memory)
|
||||
.group("vm-config"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("memory-zone")
|
||||
.long("memory-zone")
|
||||
.help(
|
||||
"User defined memory zone parameters \
|
||||
\"size=<guest_memory_region_size>,file=<backing_file>,\
|
||||
mergeable=on|off,shared=on|off,hugepages=on|off\"",
|
||||
)
|
||||
.takes_value(true)
|
||||
.min_values(1)
|
||||
.group("vm-config"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("kernel")
|
||||
.long("kernel")
|
||||
@ -522,6 +534,7 @@ mod unit_tests {
|
||||
hugepages: false,
|
||||
balloon: false,
|
||||
balloon_size: 0,
|
||||
zones: None,
|
||||
},
|
||||
kernel: Some(KernelConfig {
|
||||
path: PathBuf::from("/path/to/kernel"),
|
||||
|
@ -448,6 +448,27 @@ components:
|
||||
topology:
|
||||
$ref: '#/components/schemas/CpuTopology'
|
||||
|
||||
MemoryZoneConfig:
|
||||
required:
|
||||
- size
|
||||
type: object
|
||||
properties:
|
||||
size:
|
||||
type: integer
|
||||
format: int64
|
||||
default: 512 MB
|
||||
file:
|
||||
type: string
|
||||
mergeable:
|
||||
type: boolean
|
||||
default: false
|
||||
shared:
|
||||
type: boolean
|
||||
default: false
|
||||
hugepages:
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
MemoryConfig:
|
||||
required:
|
||||
- size
|
||||
@ -477,6 +498,10 @@ components:
|
||||
balloon:
|
||||
type: boolean
|
||||
default: false
|
||||
zones:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/MemoryZoneConfig'
|
||||
|
||||
KernelConfig:
|
||||
required:
|
||||
|
@ -42,6 +42,8 @@ pub enum Error {
|
||||
ParseCpus(OptionParserError),
|
||||
/// Error parsing memory options
|
||||
ParseMemory(OptionParserError),
|
||||
/// Error parsing memory zone options
|
||||
ParseMemoryZone(OptionParserError),
|
||||
/// Error parsing disk options
|
||||
ParseDisk(OptionParserError),
|
||||
/// Error parsing network options
|
||||
@ -147,6 +149,7 @@ impl fmt::Display for Error {
|
||||
ParseVsockCidMissing => write!(f, "Error parsing --vsock: cid missing"),
|
||||
ParseVsockSockMissing => write!(f, "Error parsing --vsock: socket missing"),
|
||||
ParseMemory(o) => write!(f, "Error parsing --memory: {}", o),
|
||||
ParseMemoryZone(o) => write!(f, "Error parsing --memory-zone: {}", o),
|
||||
ParseNetwork(o) => write!(f, "Error parsing --net: {}", o),
|
||||
ParseDisk(o) => write!(f, "Error parsing --disk: {}", o),
|
||||
ParseRNG(o) => write!(f, "Error parsing --rng: {}", o),
|
||||
@ -166,6 +169,7 @@ pub type Result<T> = result::Result<T, Error>;
|
||||
pub struct VmParams<'a> {
|
||||
pub cpus: &'a str,
|
||||
pub memory: &'a str,
|
||||
pub memory_zones: Option<Vec<&'a str>>,
|
||||
pub kernel: Option<&'a str>,
|
||||
pub initramfs: Option<&'a str>,
|
||||
pub cmdline: Option<&'a str>,
|
||||
@ -187,6 +191,7 @@ impl<'a> VmParams<'a> {
|
||||
// These .unwrap()s cannot fail as there is a default value defined
|
||||
let cpus = args.value_of("cpus").unwrap();
|
||||
let memory = args.value_of("memory").unwrap();
|
||||
let memory_zones: Option<Vec<&str>> = args.values_of("memory-zone").map(|x| x.collect());
|
||||
let rng = args.value_of("rng").unwrap();
|
||||
let serial = args.value_of("serial").unwrap();
|
||||
|
||||
@ -207,6 +212,7 @@ impl<'a> VmParams<'a> {
|
||||
VmParams {
|
||||
cpus,
|
||||
memory,
|
||||
memory_zones,
|
||||
kernel,
|
||||
initramfs,
|
||||
cmdline,
|
||||
@ -337,6 +343,19 @@ impl Default for CpusConfig {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
|
||||
pub struct MemoryZoneConfig {
|
||||
pub size: u64,
|
||||
#[serde(default)]
|
||||
pub file: Option<PathBuf>,
|
||||
#[serde(default)]
|
||||
pub mergeable: bool,
|
||||
#[serde(default)]
|
||||
pub shared: bool,
|
||||
#[serde(default)]
|
||||
pub hugepages: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
|
||||
pub struct MemoryConfig {
|
||||
pub size: u64,
|
||||
@ -356,10 +375,12 @@ pub struct MemoryConfig {
|
||||
pub balloon: bool,
|
||||
#[serde(default)]
|
||||
pub balloon_size: u64,
|
||||
#[serde(default)]
|
||||
pub zones: Option<Vec<MemoryZoneConfig>>,
|
||||
}
|
||||
|
||||
impl MemoryConfig {
|
||||
pub fn parse(memory: &str) -> Result<Self> {
|
||||
pub fn parse(memory: &str, memory_zones: Option<Vec<&str>>) -> Result<Self> {
|
||||
let mut parser = OptionParser::new();
|
||||
parser
|
||||
.add("size")
|
||||
@ -407,6 +428,53 @@ impl MemoryConfig {
|
||||
.unwrap_or(Toggle(false))
|
||||
.0;
|
||||
|
||||
let zones: Option<Vec<MemoryZoneConfig>> = if let Some(memory_zones) = &memory_zones {
|
||||
let mut zones = Vec::new();
|
||||
for memory_zone in memory_zones.iter() {
|
||||
let mut parser = OptionParser::new();
|
||||
parser
|
||||
.add("size")
|
||||
.add("file")
|
||||
.add("mergeable")
|
||||
.add("shared")
|
||||
.add("hugepages");
|
||||
parser.parse(memory_zone).map_err(Error::ParseMemoryZone)?;
|
||||
|
||||
let size = parser
|
||||
.convert::<ByteSized>("size")
|
||||
.map_err(Error::ParseMemoryZone)?
|
||||
.unwrap_or(ByteSized(DEFAULT_MEMORY_MB << 20))
|
||||
.0;
|
||||
let file = parser.get("file").map(PathBuf::from);
|
||||
let mergeable = parser
|
||||
.convert::<Toggle>("mergeable")
|
||||
.map_err(Error::ParseMemoryZone)?
|
||||
.unwrap_or(Toggle(false))
|
||||
.0;
|
||||
let shared = parser
|
||||
.convert::<Toggle>("shared")
|
||||
.map_err(Error::ParseMemoryZone)?
|
||||
.unwrap_or(Toggle(false))
|
||||
.0;
|
||||
let hugepages = parser
|
||||
.convert::<Toggle>("hugepages")
|
||||
.map_err(Error::ParseMemoryZone)?
|
||||
.unwrap_or(Toggle(false))
|
||||
.0;
|
||||
|
||||
zones.push(MemoryZoneConfig {
|
||||
size,
|
||||
file,
|
||||
mergeable,
|
||||
shared,
|
||||
hugepages,
|
||||
});
|
||||
}
|
||||
Some(zones)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Ok(MemoryConfig {
|
||||
size,
|
||||
file,
|
||||
@ -417,6 +485,7 @@ impl MemoryConfig {
|
||||
hugepages,
|
||||
balloon,
|
||||
balloon_size: 0,
|
||||
zones,
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -433,6 +502,7 @@ impl Default for MemoryConfig {
|
||||
hugepages: false,
|
||||
balloon: false,
|
||||
balloon_size: 0,
|
||||
zones: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1388,7 +1458,7 @@ impl VmConfig {
|
||||
|
||||
let config = VmConfig {
|
||||
cpus: CpusConfig::parse(vm_params.cpus)?,
|
||||
memory: MemoryConfig::parse(vm_params.memory)?,
|
||||
memory: MemoryConfig::parse(vm_params.memory, vm_params.memory_zones)?,
|
||||
kernel,
|
||||
initramfs,
|
||||
cmdline: CmdlineConfig::parse(vm_params.cmdline)?,
|
||||
@ -1481,11 +1551,14 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_mem_parsing() -> Result<()> {
|
||||
assert_eq!(MemoryConfig::parse("")?, MemoryConfig::default());
|
||||
assert_eq!(MemoryConfig::parse("", None)?, MemoryConfig::default());
|
||||
// Default string
|
||||
assert_eq!(MemoryConfig::parse("size=512M")?, MemoryConfig::default());
|
||||
assert_eq!(
|
||||
MemoryConfig::parse("size=512M,file=/some/file")?,
|
||||
MemoryConfig::parse("size=512M", None)?,
|
||||
MemoryConfig::default()
|
||||
);
|
||||
assert_eq!(
|
||||
MemoryConfig::parse("size=512M,file=/some/file", None)?,
|
||||
MemoryConfig {
|
||||
size: 512 << 20,
|
||||
file: Some(PathBuf::from("/some/file")),
|
||||
@ -1493,7 +1566,7 @@ mod tests {
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
MemoryConfig::parse("size=512M,mergeable=on")?,
|
||||
MemoryConfig::parse("size=512M,mergeable=on", None)?,
|
||||
MemoryConfig {
|
||||
size: 512 << 20,
|
||||
mergeable: true,
|
||||
@ -1501,14 +1574,14 @@ mod tests {
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
MemoryConfig::parse("mergeable=on")?,
|
||||
MemoryConfig::parse("mergeable=on", None)?,
|
||||
MemoryConfig {
|
||||
mergeable: true,
|
||||
..Default::default()
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
MemoryConfig::parse("size=1G,mergeable=off")?,
|
||||
MemoryConfig::parse("size=1G,mergeable=off", None)?,
|
||||
MemoryConfig {
|
||||
size: 1 << 30,
|
||||
mergeable: false,
|
||||
@ -1516,20 +1589,20 @@ mod tests {
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
MemoryConfig::parse("hotplug_method=acpi")?,
|
||||
MemoryConfig::parse("hotplug_method=acpi", None)?,
|
||||
MemoryConfig {
|
||||
..Default::default()
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
MemoryConfig::parse("hotplug_method=acpi,hotplug_size=512M")?,
|
||||
MemoryConfig::parse("hotplug_method=acpi,hotplug_size=512M", None)?,
|
||||
MemoryConfig {
|
||||
hotplug_size: Some(512 << 20),
|
||||
..Default::default()
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
MemoryConfig::parse("hotplug_method=virtio-mem,hotplug_size=512M")?,
|
||||
MemoryConfig::parse("hotplug_method=virtio-mem,hotplug_size=512M", None)?,
|
||||
MemoryConfig {
|
||||
hotplug_size: Some(512 << 20),
|
||||
hotplug_method: HotplugMethod::VirtioMem,
|
||||
@ -1951,6 +2024,7 @@ mod tests {
|
||||
hugepages: false,
|
||||
balloon: false,
|
||||
balloon_size: 0,
|
||||
zones: None,
|
||||
},
|
||||
kernel: Some(KernelConfig {
|
||||
path: PathBuf::from("/path/to/kernel"),
|
||||
|
Loading…
Reference in New Issue
Block a user