Skip to content

Commit 2f81cc0

Browse files
bchaliosManciukic
authored andcommitted
test: VirtIO PCI device create and restoration
Refactor the test code that inserts VirtIO devices in a Vmm object and then add a test which creates a Vmm with PCI devices and then serializes and deserializes the device manager and ensures that everything is as restored as expected. Signed-off-by: Babis Chalios <[email protected]>
1 parent 29d1017 commit 2f81cc0

File tree

3 files changed

+214
-12
lines changed

3 files changed

+214
-12
lines changed

src/vmm/src/builder.rs

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -848,7 +848,6 @@ pub(crate) mod tests {
848848

849849
assert!(
850850
vmm.device_manager
851-
.mmio_devices
852851
.get_virtio_device(TYPE_VSOCK, &vsock_dev_id)
853852
.is_some()
854853
);
@@ -874,7 +873,6 @@ pub(crate) mod tests {
874873

875874
assert!(
876875
vmm.device_manager
877-
.mmio_devices
878876
.get_virtio_device(TYPE_RNG, ENTROPY_DEV_ID)
879877
.is_some()
880878
);
@@ -909,7 +907,6 @@ pub(crate) mod tests {
909907

910908
assert!(
911909
vmm.device_manager
912-
.mmio_devices
913910
.get_virtio_device(TYPE_BALLOON, BALLOON_DEV_ID)
914911
.is_some()
915912
);
@@ -961,7 +958,6 @@ pub(crate) mod tests {
961958
assert!(cmdline_contains(&cmdline, "root=/dev/vda ro"));
962959
assert!(
963960
vmm.device_manager
964-
.mmio_devices
965961
.get_virtio_device(TYPE_BLOCK, drive_id.as_str())
966962
.is_some()
967963
);
@@ -983,7 +979,6 @@ pub(crate) mod tests {
983979
assert!(cmdline_contains(&cmdline, "root=PARTUUID=0eaa91a0-01 rw"));
984980
assert!(
985981
vmm.device_manager
986-
.mmio_devices
987982
.get_virtio_device(TYPE_BLOCK, drive_id.as_str())
988983
.is_some()
989984
);
@@ -1006,7 +1001,6 @@ pub(crate) mod tests {
10061001
assert!(!cmdline_contains(&cmdline, "root=/dev/vda"));
10071002
assert!(
10081003
vmm.device_manager
1009-
.mmio_devices
10101004
.get_virtio_device(TYPE_BLOCK, drive_id.as_str())
10111005
.is_some()
10121006
);
@@ -1044,19 +1038,16 @@ pub(crate) mod tests {
10441038
assert!(cmdline_contains(&cmdline, "root=PARTUUID=0eaa91a0-01 rw"));
10451039
assert!(
10461040
vmm.device_manager
1047-
.mmio_devices
10481041
.get_virtio_device(TYPE_BLOCK, "root")
10491042
.is_some()
10501043
);
10511044
assert!(
10521045
vmm.device_manager
1053-
.mmio_devices
10541046
.get_virtio_device(TYPE_BLOCK, "secondary")
10551047
.is_some()
10561048
);
10571049
assert!(
10581050
vmm.device_manager
1059-
.mmio_devices
10601051
.get_virtio_device(TYPE_BLOCK, "third")
10611052
.is_some()
10621053
);
@@ -1086,7 +1077,6 @@ pub(crate) mod tests {
10861077
assert!(cmdline_contains(&cmdline, "root=/dev/vda rw"));
10871078
assert!(
10881079
vmm.device_manager
1089-
.mmio_devices
10901080
.get_virtio_device(TYPE_BLOCK, drive_id.as_str())
10911081
.is_some()
10921082
);
@@ -1108,7 +1098,6 @@ pub(crate) mod tests {
11081098
assert!(cmdline_contains(&cmdline, "root=PARTUUID=0eaa91a0-01 ro"));
11091099
assert!(
11101100
vmm.device_manager
1111-
.mmio_devices
11121101
.get_virtio_device(TYPE_BLOCK, drive_id.as_str())
11131102
.is_some()
11141103
);
@@ -1130,7 +1119,6 @@ pub(crate) mod tests {
11301119
assert!(cmdline_contains(&cmdline, "root=/dev/vda rw"));
11311120
assert!(
11321121
vmm.device_manager
1133-
.mmio_devices
11341122
.get_virtio_device(TYPE_BLOCK, drive_id.as_str())
11351123
.is_some()
11361124
);

src/vmm/src/device_manager/mod.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,36 @@ impl DeviceManager {
375375
Self::do_mark_virtio_queue_memory_dirty(virtio_device, mem);
376376
}
377377
}
378+
379+
/// Get a VirtIO device of type `virtio_type` with ID `device_id`
380+
pub fn get_virtio_device(
381+
&self,
382+
virtio_type: u32,
383+
device_id: &str,
384+
) -> Option<Arc<Mutex<dyn VirtioDevice>>> {
385+
if self.pci_devices.pci_segment.is_some() {
386+
let pci_device = self.pci_devices.get_virtio_device(virtio_type, device_id)?;
387+
Some(
388+
pci_device
389+
.lock()
390+
.expect("Poisoned lock")
391+
.virtio_device()
392+
.clone(),
393+
)
394+
} else {
395+
let mmio_device = self
396+
.mmio_devices
397+
.get_virtio_device(virtio_type, device_id)?;
398+
Some(
399+
mmio_device
400+
.inner
401+
.lock()
402+
.expect("Poisoned lock")
403+
.device()
404+
.clone(),
405+
)
406+
}
407+
}
378408
}
379409

380410
#[derive(Debug, Default, Clone, Serialize, Deserialize)]

src/vmm/src/device_manager/pci_mngr.rs

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -585,3 +585,187 @@ impl<'a> Persist<'a> for PciDevices {
585585
Ok(pci_devices)
586586
}
587587
}
588+
589+
#[cfg(test)]
590+
mod tests {
591+
use vmm_sys_util::tempfile::TempFile;
592+
593+
use super::*;
594+
use crate::builder::tests::*;
595+
use crate::device_manager;
596+
use crate::devices::virtio::block::CacheType;
597+
use crate::mmds::data_store::MmdsVersion;
598+
use crate::resources::VmmConfig;
599+
use crate::snapshot::Snapshot;
600+
use crate::vmm_config::balloon::BalloonDeviceConfig;
601+
use crate::vmm_config::entropy::EntropyDeviceConfig;
602+
use crate::vmm_config::net::NetworkInterfaceConfig;
603+
use crate::vmm_config::vsock::VsockDeviceConfig;
604+
605+
#[test]
606+
fn test_device_manager_persistence() {
607+
let mut buf = vec![0; 65536];
608+
// These need to survive so the restored blocks find them.
609+
let _block_files;
610+
let mut tmp_sock_file = TempFile::new().unwrap();
611+
tmp_sock_file.remove().unwrap();
612+
// Set up a vmm with one of each device, and get the serialized DeviceStates.
613+
{
614+
let mut event_manager = EventManager::new().expect("Unable to create EventManager");
615+
let mut vmm = default_vmm();
616+
vmm.device_manager.enable_pci(&vmm.vm).unwrap();
617+
let mut cmdline = default_kernel_cmdline();
618+
619+
// Add a balloon device.
620+
let balloon_cfg = BalloonDeviceConfig {
621+
amount_mib: 123,
622+
deflate_on_oom: false,
623+
stats_polling_interval_s: 1,
624+
};
625+
insert_balloon_device(&mut vmm, &mut cmdline, &mut event_manager, balloon_cfg);
626+
// Add a block device.
627+
let drive_id = String::from("root");
628+
let block_configs = vec![CustomBlockConfig::new(
629+
drive_id,
630+
true,
631+
None,
632+
true,
633+
CacheType::Unsafe,
634+
)];
635+
_block_files =
636+
insert_block_devices(&mut vmm, &mut cmdline, &mut event_manager, block_configs);
637+
// Add a net device.
638+
let network_interface = NetworkInterfaceConfig {
639+
iface_id: String::from("netif"),
640+
host_dev_name: String::from("hostname"),
641+
guest_mac: None,
642+
rx_rate_limiter: None,
643+
tx_rate_limiter: None,
644+
};
645+
insert_net_device_with_mmds(
646+
&mut vmm,
647+
&mut cmdline,
648+
&mut event_manager,
649+
network_interface,
650+
MmdsVersion::V2,
651+
);
652+
// Add a vsock device.
653+
let vsock_dev_id = "vsock";
654+
let vsock_config = VsockDeviceConfig {
655+
vsock_id: Some(vsock_dev_id.to_string()),
656+
guest_cid: 3,
657+
uds_path: tmp_sock_file.as_path().to_str().unwrap().to_string(),
658+
};
659+
insert_vsock_device(&mut vmm, &mut cmdline, &mut event_manager, vsock_config);
660+
// Add an entropy device.
661+
let entropy_config = EntropyDeviceConfig::default();
662+
insert_entropy_device(&mut vmm, &mut cmdline, &mut event_manager, entropy_config);
663+
664+
Snapshot::serialize(&mut buf.as_mut_slice(), &vmm.device_manager.save()).unwrap();
665+
}
666+
667+
tmp_sock_file.remove().unwrap();
668+
669+
let mut event_manager = EventManager::new().expect("Unable to create EventManager");
670+
// Keep in mind we are re-creating here an empty DeviceManager. Restoring later on
671+
// will create a new PciDevices manager different than vmm.pci_devices. We're doing
672+
// this to avoid restoring the whole Vmm, since what we really need from Vmm is the Vm
673+
// object and calling default_vmm() is the easiest way to create one.
674+
let vmm = default_vmm();
675+
let device_manager_state: device_manager::DevicesState =
676+
Snapshot::deserialize(&mut buf.as_slice()).unwrap();
677+
let vm_resources = &mut VmResources::default();
678+
let restore_args = PciDevicesConstructorArgs {
679+
vm: vmm.vm.clone(),
680+
mem: vmm.vm.guest_memory(),
681+
vm_resources,
682+
instance_id: "microvm-id",
683+
restored_from_file: true,
684+
event_manager: &mut event_manager,
685+
};
686+
let _restored_dev_manager =
687+
PciDevices::restore(restore_args, &device_manager_state.pci_state).unwrap();
688+
689+
let expected_vm_resources = format!(
690+
r#"{{
691+
"balloon": {{
692+
"amount_mib": 123,
693+
"deflate_on_oom": false,
694+
"stats_polling_interval_s": 1
695+
}},
696+
"drives": [
697+
{{
698+
"drive_id": "root",
699+
"partuuid": null,
700+
"is_root_device": true,
701+
"cache_type": "Unsafe",
702+
"is_read_only": true,
703+
"path_on_host": "{}",
704+
"rate_limiter": null,
705+
"io_engine": "Sync",
706+
"socket": null
707+
}}
708+
],
709+
"boot-source": {{
710+
"kernel_image_path": "",
711+
"initrd_path": null,
712+
"boot_args": null
713+
}},
714+
"cpu-config": null,
715+
"logger": null,
716+
"machine-config": {{
717+
"vcpu_count": 1,
718+
"mem_size_mib": 128,
719+
"smt": false,
720+
"track_dirty_pages": false,
721+
"huge_pages": "None"
722+
}},
723+
"metrics": null,
724+
"mmds-config": {{
725+
"version": "V2",
726+
"network_interfaces": [
727+
"netif"
728+
],
729+
"ipv4_address": "169.254.169.254"
730+
}},
731+
"network-interfaces": [
732+
{{
733+
"iface_id": "netif",
734+
"host_dev_name": "hostname",
735+
"guest_mac": null,
736+
"rx_rate_limiter": null,
737+
"tx_rate_limiter": null
738+
}}
739+
],
740+
"vsock": {{
741+
"guest_cid": 3,
742+
"uds_path": "{}"
743+
}},
744+
"entropy": {{
745+
"rate_limiter": null
746+
}}
747+
}}"#,
748+
_block_files.last().unwrap().as_path().to_str().unwrap(),
749+
tmp_sock_file.as_path().to_str().unwrap()
750+
);
751+
752+
assert_eq!(
753+
vm_resources
754+
.mmds
755+
.as_ref()
756+
.unwrap()
757+
.lock()
758+
.unwrap()
759+
.version(),
760+
MmdsVersion::V2
761+
);
762+
assert_eq!(
763+
device_manager_state.pci_state.mmds_version.unwrap(),
764+
MmdsVersion::V2.into()
765+
);
766+
assert_eq!(
767+
expected_vm_resources,
768+
serde_json::to_string_pretty(&VmmConfig::from(&*vm_resources)).unwrap()
769+
);
770+
}
771+
}

0 commit comments

Comments
 (0)