@@ -585,3 +585,187 @@ impl<'a> Persist<'a> for PciDevices {
585
585
Ok ( pci_devices)
586
586
}
587
587
}
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