@@ -62,6 +62,9 @@ def setUp(self):
62
62
def _to_device_spec_conf (spec_list ):
63
63
return [jsonutils .dumps (x ) for x in spec_list ]
64
64
65
+
66
+ class PlacementPCIInventoryReportingTests (PlacementPCIReportingTests ):
67
+
65
68
def test_new_compute_init_with_pci_devs (self ):
66
69
"""A brand new compute is started with multiple pci devices configured
67
70
for nova.
@@ -748,3 +751,188 @@ def test_reporting_cannot_be_disable_once_it_is_enabled(self):
748
751
"enabled." ,
749
752
str (ex )
750
753
)
754
+
755
+
756
+ class PlacementPCIAllocationHealingTests (PlacementPCIReportingTests ):
757
+ def setUp (self ):
758
+ super ().setUp ()
759
+ # Pre-configure a PCI alias to consume our devs
760
+ alias_pci = {
761
+ "vendor_id" : fakelibvirt .PCI_VEND_ID ,
762
+ "product_id" : fakelibvirt .PCI_PROD_ID ,
763
+ "name" : "a-pci-dev" ,
764
+ }
765
+ alias_pf = {
766
+ "vendor_id" : fakelibvirt .PCI_VEND_ID ,
767
+ "product_id" : fakelibvirt .PF_PROD_ID ,
768
+ "device_type" : "type-PF" ,
769
+ "name" : "a-pf" ,
770
+ }
771
+ alias_vf = {
772
+ "vendor_id" : fakelibvirt .PCI_VEND_ID ,
773
+ "product_id" : fakelibvirt .VF_PROD_ID ,
774
+ "device_type" : "type-VF" ,
775
+ "name" : "a-vf" ,
776
+ }
777
+ self .flags (
778
+ group = 'pci' ,
779
+ alias = self ._to_pci_alias_conf ([alias_pci , alias_pf , alias_vf ]))
780
+
781
+ @staticmethod
782
+ def _to_pci_alias_conf (alias_list ):
783
+ return [jsonutils .dumps (x ) for x in alias_list ]
784
+
785
+ def test_heal_single_pci_allocation (self ):
786
+ # The fake libvirt will emulate on the host:
787
+ # * one type-PCI in slot 0
788
+ pci_info = fakelibvirt .HostPCIDevicesInfo (
789
+ num_pci = 1 , num_pfs = 0 , num_vfs = 0 )
790
+ # the config matches the PCI dev
791
+ device_spec = self ._to_device_spec_conf (
792
+ [
793
+ {
794
+ "vendor_id" : fakelibvirt .PCI_VEND_ID ,
795
+ "product_id" : fakelibvirt .PCI_PROD_ID ,
796
+ },
797
+ ]
798
+ )
799
+ self .flags (group = 'pci' , device_spec = device_spec )
800
+
801
+ # Start a compute *without* PCI tracking in placement
802
+ self .mock_pci_report_in_placement .return_value = False
803
+ self .start_compute (hostname = "compute1" , pci_info = pci_info )
804
+ self .assertPCIDeviceCounts ("compute1" , total = 1 , free = 1 )
805
+
806
+ # Create an instance that consume our PCI dev
807
+ extra_spec = {"pci_passthrough:alias" : "a-pci-dev:1" }
808
+ flavor_id = self ._create_flavor (extra_spec = extra_spec )
809
+ server = self ._create_server (flavor_id = flavor_id , networks = [])
810
+ self .assertPCIDeviceCounts ("compute1" , total = 1 , free = 0 )
811
+
812
+ # Restart the compute but now with PCI tracking enabled
813
+ self .mock_pci_report_in_placement .return_value = True
814
+ self .restart_compute_service ("compute1" )
815
+ # Assert that the PCI allocation is healed in placement
816
+ self .assertPCIDeviceCounts ("compute1" , total = 1 , free = 0 )
817
+ expected_placement_view = {
818
+ "inventories" : {
819
+ "0000:81:00.0" : {self .PCI_RC : 1 },
820
+ },
821
+ "traits" : {
822
+ "0000:81:00.0" : [],
823
+ },
824
+ "usages" : {
825
+ "0000:81:00.0" : {self .PCI_RC : 1 }
826
+ },
827
+ "allocations" : {
828
+ server ['id' ]: {
829
+ "0000:81:00.0" : {self .PCI_RC : 1 }
830
+ }
831
+ }
832
+ }
833
+ self .assert_placement_pci_view ("compute1" , ** expected_placement_view )
834
+
835
+ # run an update_available_resources periodic and assert that the usage
836
+ # and allocation stays
837
+ self ._run_periodics ()
838
+ self .assert_placement_pci_view ("compute1" , ** expected_placement_view )
839
+
840
+ def test_heal_multiple_allocations (self ):
841
+ # The fake libvirt will emulate on the host:
842
+ # * two type-PCI devs (slot 0 and 1)
843
+ # * two type-PFs (slot 2 and 3) with 4 type-VFs each
844
+ pci_info = fakelibvirt .HostPCIDevicesInfo (
845
+ num_pci = 2 , num_pfs = 2 , num_vfs = 8 )
846
+ # the config matches:
847
+ device_spec = self ._to_device_spec_conf (
848
+ [
849
+ # both type-PCI
850
+ {
851
+ "vendor_id" : fakelibvirt .PCI_VEND_ID ,
852
+ "product_id" : fakelibvirt .PCI_PROD_ID ,
853
+ },
854
+ # the PF in slot 2
855
+ {
856
+ "vendor_id" : fakelibvirt .PCI_VEND_ID ,
857
+ "product_id" : fakelibvirt .PF_PROD_ID ,
858
+ "address" : "0000:81:02.0" ,
859
+ },
860
+ # the VFs in slot 3
861
+ {
862
+ "vendor_id" : fakelibvirt .PCI_VEND_ID ,
863
+ "product_id" : fakelibvirt .VF_PROD_ID ,
864
+ "address" : "0000:81:03.*" ,
865
+ },
866
+ ]
867
+ )
868
+ self .flags (group = 'pci' , device_spec = device_spec )
869
+
870
+ # Start a compute *without* PCI tracking in placement
871
+ self .mock_pci_report_in_placement .return_value = False
872
+ self .start_compute (hostname = "compute1" , pci_info = pci_info )
873
+ # 2 PCI + 1 PF + 4 VFs
874
+ self .assertPCIDeviceCounts ("compute1" , total = 7 , free = 7 )
875
+
876
+ # Create three instances consuming devices:
877
+ # * server_2pci: two type-PCI
878
+ # * server_pf_vf: one PF and one VF
879
+ # * server_2vf: two VFs
880
+ extra_spec = {"pci_passthrough:alias" : "a-pci-dev:2" }
881
+ flavor_id = self ._create_flavor (extra_spec = extra_spec )
882
+ server_2pci = self ._create_server (flavor_id = flavor_id , networks = [])
883
+ self .assertPCIDeviceCounts ("compute1" , total = 7 , free = 5 )
884
+
885
+ extra_spec = {"pci_passthrough:alias" : "a-pf:1,a-vf:1" }
886
+ flavor_id = self ._create_flavor (extra_spec = extra_spec )
887
+ server_pf_vf = self ._create_server (flavor_id = flavor_id , networks = [])
888
+ self .assertPCIDeviceCounts ("compute1" , total = 7 , free = 3 )
889
+
890
+ extra_spec = {"pci_passthrough:alias" : "a-vf:2" }
891
+ flavor_id = self ._create_flavor (extra_spec = extra_spec )
892
+ server_2vf = self ._create_server (flavor_id = flavor_id , networks = [])
893
+ self .assertPCIDeviceCounts ("compute1" , total = 7 , free = 1 )
894
+
895
+ # Restart the compute but now with PCI tracking enabled
896
+ self .mock_pci_report_in_placement .return_value = True
897
+ self .restart_compute_service ("compute1" )
898
+ # Assert that the PCI allocation is healed in placement
899
+ self .assertPCIDeviceCounts ("compute1" , total = 7 , free = 1 )
900
+ expected_placement_view = {
901
+ "inventories" : {
902
+ "0000:81:00.0" : {self .PCI_RC : 1 },
903
+ "0000:81:01.0" : {self .PCI_RC : 1 },
904
+ "0000:81:02.0" : {self .PF_RC : 1 },
905
+ "0000:81:03.0" : {self .VF_RC : 4 },
906
+ },
907
+ "traits" : {
908
+ "0000:81:00.0" : [],
909
+ "0000:81:01.0" : [],
910
+ "0000:81:02.0" : [],
911
+ "0000:81:03.0" : [],
912
+ },
913
+ "usages" : {
914
+ "0000:81:00.0" : {self .PCI_RC : 1 },
915
+ "0000:81:01.0" : {self .PCI_RC : 1 },
916
+ "0000:81:02.0" : {self .PF_RC : 1 },
917
+ "0000:81:03.0" : {self .VF_RC : 3 },
918
+ },
919
+ "allocations" : {
920
+ server_2pci ['id' ]: {
921
+ "0000:81:00.0" : {self .PCI_RC : 1 },
922
+ "0000:81:01.0" : {self .PCI_RC : 1 },
923
+ },
924
+ server_pf_vf ['id' ]: {
925
+ "0000:81:02.0" : {self .PF_RC : 1 },
926
+ "0000:81:03.0" : {self .VF_RC : 1 },
927
+ },
928
+ server_2vf ['id' ]: {
929
+ "0000:81:03.0" : {self .VF_RC : 2 }
930
+ },
931
+ },
932
+ }
933
+ self .assert_placement_pci_view ("compute1" , ** expected_placement_view )
934
+
935
+ # run an update_available_resources periodic and assert that the usage
936
+ # and allocation stays
937
+ self ._run_periodics ()
938
+ self .assert_placement_pci_view ("compute1" , ** expected_placement_view )
0 commit comments