@@ -589,3 +589,188 @@ impl<'a> Persist<'a> for PciDevices {
589
589
Ok ( pci_devices)
590
590
}
591
591
}
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