Skip to content

Commit 5416099

Browse files
committed
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 f0faa7f commit 5416099

File tree

3 files changed

+215
-12
lines changed

3 files changed

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

0 commit comments

Comments
 (0)