in src/vmm/src/resources.rs [524:829]
fn test_from_json() {
let kernel_file = TempFile::new().unwrap();
let rootfs_file = TempFile::new().unwrap();
let default_instance_info = InstanceInfo::default();
// We will test different scenarios with invalid resources configuration and
// check the expected errors. We include configuration for the kernel and rootfs
// in every json because they are mandatory fields. If we don't configure
// these resources, it is considered an invalid json and the test will crash.
// Invalid JSON string must yield a `serde_json` error.
match VmResources::from_json(r#"}"#, &default_instance_info) {
Err(Error::InvalidJson(_)) => (),
_ => unreachable!(),
}
// Valid JSON string without the configuration for kernel or rootfs
// result in an invalid JSON error.
match VmResources::from_json(r#"{}"#, &default_instance_info) {
Err(Error::InvalidJson(_)) => (),
_ => unreachable!(),
}
// Invalid kernel path.
let mut json = format!(
r#"{{
"boot-source": {{
"kernel_image_path": "/invalid/path",
"boot_args": "console=ttyS0 reboot=k panic=1 pci=off"
}},
"drives": [
{{
"drive_id": "rootfs",
"path_on_host": "{}",
"is_root_device": true,
"is_read_only": false
}}
]
}}"#,
rootfs_file.as_path().to_str().unwrap()
);
match VmResources::from_json(json.as_str(), &default_instance_info) {
Err(Error::BootSource(BootSourceConfigError::InvalidKernelPath(_))) => (),
_ => unreachable!(),
}
// Invalid rootfs path.
json = format!(
r#"{{
"boot-source": {{
"kernel_image_path": "{}",
"boot_args": "console=ttyS0 reboot=k panic=1 pci=off"
}},
"drives": [
{{
"drive_id": "rootfs",
"path_on_host": "/invalid/path",
"is_root_device": true,
"is_read_only": false
}}
]
}}"#,
kernel_file.as_path().to_str().unwrap()
);
match VmResources::from_json(json.as_str(), &default_instance_info) {
Err(Error::BlockDevice(DriveError::InvalidBlockDevicePath(_))) => (),
_ => unreachable!(),
}
// Invalid vCPU number.
json = format!(
r#"{{
"boot-source": {{
"kernel_image_path": "{}",
"boot_args": "console=ttyS0 reboot=k panic=1 pci=off"
}},
"drives": [
{{
"drive_id": "rootfs",
"path_on_host": "{}",
"is_root_device": true,
"is_read_only": false
}}
],
"machine-config": {{
"vcpu_count": 0,
"mem_size_mib": 1024
}}
}}"#,
kernel_file.as_path().to_str().unwrap(),
rootfs_file.as_path().to_str().unwrap()
);
match VmResources::from_json(json.as_str(), &default_instance_info) {
Err(Error::VmConfig(VmConfigError::InvalidVcpuCount)) => (),
_ => unreachable!(),
}
// Invalid memory size.
json = format!(
r#"{{
"boot-source": {{
"kernel_image_path": "{}",
"boot_args": "console=ttyS0 reboot=k panic=1 pci=off"
}},
"drives": [
{{
"drive_id": "rootfs",
"path_on_host": "{}",
"is_root_device": true,
"is_read_only": false
}}
],
"machine-config": {{
"vcpu_count": 2,
"mem_size_mib": 0
}}
}}"#,
kernel_file.as_path().to_str().unwrap(),
rootfs_file.as_path().to_str().unwrap()
);
match VmResources::from_json(json.as_str(), &default_instance_info) {
Err(Error::VmConfig(VmConfigError::InvalidMemorySize)) => (),
_ => unreachable!(),
}
// Invalid path for logger pipe.
json = format!(
r#"{{
"boot-source": {{
"kernel_image_path": "{}",
"boot_args": "console=ttyS0 reboot=k panic=1 pci=off"
}},
"drives": [
{{
"drive_id": "rootfs",
"path_on_host": "{}",
"is_root_device": true,
"is_read_only": false
}}
],
"logger": {{
"log_path": "/invalid/path"
}}
}}"#,
kernel_file.as_path().to_str().unwrap(),
rootfs_file.as_path().to_str().unwrap()
);
match VmResources::from_json(json.as_str(), &default_instance_info) {
Err(Error::Logger(LoggerConfigError::InitializationFailure { .. })) => (),
_ => unreachable!(),
}
// The previous call enables the logger. We need to disable it.
LOGGER.set_max_level(LevelFilter::Off);
// Invalid path for metrics pipe.
json = format!(
r#"{{
"boot-source": {{
"kernel_image_path": "{}",
"boot_args": "console=ttyS0 reboot=k panic=1 pci=off"
}},
"drives": [
{{
"drive_id": "rootfs",
"path_on_host": "{}",
"is_root_device": true,
"is_read_only": false
}}
],
"metrics": {{
"metrics_path": "/invalid/path"
}}
}}"#,
kernel_file.as_path().to_str().unwrap(),
rootfs_file.as_path().to_str().unwrap()
);
match VmResources::from_json(json.as_str(), &default_instance_info) {
Err(Error::Metrics(MetricsConfigError::InitializationFailure { .. })) => (),
_ => unreachable!(),
}
// Reuse of a host name.
json = format!(
r#"{{
"boot-source": {{
"kernel_image_path": "{}",
"boot_args": "console=ttyS0 reboot=k panic=1 pci=off"
}},
"drives": [
{{
"drive_id": "rootfs",
"path_on_host": "{}",
"is_root_device": true,
"is_read_only": false
}}
],
"network-interfaces": [
{{
"iface_id": "netif1",
"host_dev_name": "hostname7"
}},
{{
"iface_id": "netif2",
"host_dev_name": "hostname7"
}}
]
}}"#,
kernel_file.as_path().to_str().unwrap(),
rootfs_file.as_path().to_str().unwrap()
);
match VmResources::from_json(json.as_str(), &default_instance_info) {
Err(Error::NetDevice(NetworkInterfaceError::CreateNetworkDevice(
devices::virtio::net::Error::TapOpen { .. },
))) => (),
_ => unreachable!(),
}
// Let's try now passing a valid configuration. We won't include any logger
// or metrics configuration because these were already initialized in other
// tests of this module and the reinitialization of them will cause crashing.
json = format!(
r#"{{
"boot-source": {{
"kernel_image_path": "{}",
"boot_args": "console=ttyS0 reboot=k panic=1 pci=off"
}},
"drives": [
{{
"drive_id": "rootfs",
"path_on_host": "{}",
"is_root_device": true,
"is_read_only": false
}}
],
"network-interfaces": [
{{
"iface_id": "netif",
"host_dev_name": "hostname8"
}}
],
"machine-config": {{
"vcpu_count": 2,
"mem_size_mib": 1024,
"smt": false
}},
"mmds-config": {{
"version": "V2",
"ipv4_address": "169.254.170.2",
"network_interfaces": ["netif"]
}}
}}"#,
kernel_file.as_path().to_str().unwrap(),
rootfs_file.as_path().to_str().unwrap(),
);
assert!(VmResources::from_json(json.as_str(), &default_instance_info).is_ok());
// Test all configuration, this time trying to set default configuration
// for version and IPv4 address.
let kernel_file = TempFile::new().unwrap();
json = format!(
r#"{{
"balloon": {{
"amount_mib": 0,
"deflate_on_oom": false,
"stats_polling_interval_s": 0
}},
"boot-source": {{
"kernel_image_path": "{}",
"boot_args": "console=ttyS0 reboot=k panic=1 pci=off"
}},
"drives": [
{{
"drive_id": "rootfs",
"path_on_host": "{}",
"is_root_device": true,
"is_read_only": false
}}
],
"network-interfaces": [
{{
"iface_id": "netif",
"host_dev_name": "hostname9"
}}
],
"machine-config": {{
"vcpu_count": 2,
"mem_size_mib": 1024,
"smt": false
}},
"mmds-config": {{
"network_interfaces": ["netif"]
}}
}}"#,
kernel_file.as_path().to_str().unwrap(),
rootfs_file.as_path().to_str().unwrap(),
);
assert!(VmResources::from_json(json.as_str(), &default_instance_info).is_ok());
}