Browse Source

Merge "Support reporting multi CPU model traits"

changes/93/671793/24
Zuul 1 week ago
parent
commit
91e145deb3
2 changed files with 154 additions and 16 deletions
  1. 132
    2
      nova/tests/unit/virt/libvirt/test_driver.py
  2. 22
    14
      nova/virt/libvirt/driver.py

+ 132
- 2
nova/tests/unit/virt/libvirt/test_driver.py View File

@@ -22446,6 +22446,138 @@ class LibvirtDriverTestCase(test.NoDBTestCase, TraitsComparisonMixin):
22446 22446
 </cpu>
22447 22447
 '''], 1)
22448 22448
 
22449
+    @mock.patch('nova.virt.libvirt.host.libvirt.Connection.getCapabilities')
22450
+    @mock.patch('nova.virt.libvirt.host.libvirt.Connection.baselineCPU')
22451
+    def test_cpu_traits_with_mode_custom_multi_models(self, mocked_baseline,
22452
+                                                      mocked_cap):
22453
+        """Test getting CPU traits when cpu_mode is 'custom' and cpu_model is
22454
+        ['qemu64', 'SandyBridge'], and guest CPU model is Broadwell-noTSX,
22455
+        traits are calculated from _fake_qemu64_cpu_feature and
22456
+        _fake_sandy_bridge_cpu_feature.
22457
+        """
22458
+        self.flags(cpu_mode='custom',
22459
+                   cpu_models=['QEMU64', 'sandybridge'],
22460
+                   group='libvirt')
22461
+        mocked_cap.return_value = '''
22462
+            <capabilities>
22463
+                <host>
22464
+                    <uuid>cef19ce0-0ca2-11df-855d-b19fbce37686</uuid>
22465
+                    <cpu>
22466
+                      <arch>x86_64</arch>
22467
+                      <model>Broadwell-noTSX</model>
22468
+                      <topology sockets='1' cores='2' threads='2'/>
22469
+                      <feature policy='require' name='erms'/>
22470
+                      <pages unit='KiB' size='4' />
22471
+                      <pages unit='KiB' size='1024' />
22472
+                    </cpu>
22473
+                </host>
22474
+            </capabilities>
22475
+        '''
22476
+        mocked_baseline.side_effect = (_fake_broadwell_cpu_feature,
22477
+                                       _fake_qemu64_cpu_feature,
22478
+                                       _fake_sandy_bridge_cpu_feature)
22479
+
22480
+        self.assertTraitsEqual(
22481
+            [
22482
+                'HW_CPU_X86_AVX',
22483
+                'HW_CPU_X86_AESNI',
22484
+                'HW_CPU_X86_SSE42',
22485
+                'HW_CPU_X86_SSE41',
22486
+                'HW_CPU_X86_CLMUL',
22487
+                'HW_CPU_X86_SSSE3',
22488
+                'HW_CPU_X86_SSE2',
22489
+                'HW_CPU_X86_SSE',
22490
+                'HW_CPU_X86_MMX',
22491
+                'HW_CPU_X86_SVM'
22492
+            ], self.drvr._get_cpu_feature_traits()
22493
+        )
22494
+
22495
+        calls = [mock.call([u'''<cpu>
22496
+  <arch>x86_64</arch>
22497
+  <model>Broadwell-noTSX</model>
22498
+  <topology sockets="1" cores="2" threads="2"/>
22499
+  <feature name="erms"/>
22500
+</cpu>
22501
+'''], 1), mock.call([u'''<cpu>
22502
+  <arch>x86_64</arch>
22503
+  <model>qemu64</model>
22504
+  <topology sockets="1" cores="2" threads="2"/>
22505
+</cpu>
22506
+'''], 1), mock.call([u'''<cpu>
22507
+  <arch>x86_64</arch>
22508
+  <model>SandyBridge</model>
22509
+  <topology sockets="1" cores="2" threads="2"/>
22510
+</cpu>
22511
+'''], 1)]
22512
+        mocked_baseline.assert_has_calls(calls)
22513
+
22514
+    @mock.patch('nova.virt.libvirt.host.libvirt.Connection.getCapabilities')
22515
+    @mock.patch('nova.virt.libvirt.host.libvirt.Connection.baselineCPU')
22516
+    def test_cpu_traits_with_mode_custom_multi_models_and_extra_flags(self,
22517
+            mocked_baseline, mocked_cap):
22518
+        """Test getting CPU traits when cpu_mode is 'custom' and cpu_model is
22519
+        ['qemu64', 'SandyBridge'], cpu_model_extra_specs is ['pcid', 'avx2']
22520
+        and guest CPU model is Broadwell-noTSX, traits are calculated from
22521
+        _fake_qemu64_cpu_feature and _fake_sandy_bridge_cpu_feature.
22522
+        """
22523
+        self.flags(cpu_mode='custom',
22524
+                   cpu_models=['QEMU64', 'sandybridge'],
22525
+                   cpu_model_extra_flags=['pcid', 'avx2'],
22526
+                   group='libvirt')
22527
+        mocked_cap.return_value = '''
22528
+            <capabilities>
22529
+                <host>
22530
+                    <uuid>cef19ce0-0ca2-11df-855d-b19fbce37686</uuid>
22531
+                    <cpu>
22532
+                      <arch>x86_64</arch>
22533
+                      <model>Broadwell-noTSX</model>
22534
+                      <topology sockets='1' cores='2' threads='2'/>
22535
+                      <feature policy='require' name='erms'/>
22536
+                      <pages unit='KiB' size='4' />
22537
+                      <pages unit='KiB' size='1024' />
22538
+                    </cpu>
22539
+                </host>
22540
+            </capabilities>
22541
+        '''
22542
+        mocked_baseline.side_effect = (_fake_broadwell_cpu_feature,
22543
+                                       _fake_qemu64_cpu_feature,
22544
+                                       _fake_sandy_bridge_cpu_feature)
22545
+
22546
+        self.assertTraitsEqual(
22547
+            [
22548
+                'HW_CPU_X86_AVX',
22549
+                'HW_CPU_X86_AVX2',
22550
+                'HW_CPU_X86_AESNI',
22551
+                'HW_CPU_X86_SSE42',
22552
+                'HW_CPU_X86_SSE41',
22553
+                'HW_CPU_X86_CLMUL',
22554
+                'HW_CPU_X86_SSSE3',
22555
+                'HW_CPU_X86_SSE2',
22556
+                'HW_CPU_X86_SSE',
22557
+                'HW_CPU_X86_MMX',
22558
+                'HW_CPU_X86_SVM'
22559
+            ], self.drvr._get_cpu_feature_traits()
22560
+        )
22561
+
22562
+        calls = [mock.call([u'''<cpu>
22563
+  <arch>x86_64</arch>
22564
+  <model>Broadwell-noTSX</model>
22565
+  <topology sockets="1" cores="2" threads="2"/>
22566
+  <feature name="erms"/>
22567
+</cpu>
22568
+'''], 1), mock.call([u'''<cpu>
22569
+  <arch>x86_64</arch>
22570
+  <model>qemu64</model>
22571
+  <topology sockets="1" cores="2" threads="2"/>
22572
+</cpu>
22573
+'''], 1), mock.call([u'''<cpu>
22574
+  <arch>x86_64</arch>
22575
+  <model>SandyBridge</model>
22576
+  <topology sockets="1" cores="2" threads="2"/>
22577
+</cpu>
22578
+'''], 1)]
22579
+        mocked_baseline.assert_has_calls(calls)
22580
+
22449 22581
     @mock.patch('nova.virt.libvirt.host.libvirt.Connection.baselineCPU')
22450 22582
     def test_cpu_traits_with_no_baseline_support(self, mock_baseline):
22451 22583
         """Test getting CPU traits when baseline call is not supported."""
@@ -22543,7 +22675,6 @@ class LibvirtDriverTestCase(test.NoDBTestCase, TraitsComparisonMixin):
22543 22675
                 <model fallback='forbid'>IvyBridge</model>
22544 22676
                 <vendor>Intel</vendor>
22545 22677
                 <feature policy='require' name='erms'/>
22546
-                <feature policy='require' name='pcid'/>
22547 22678
             </cpu>
22548 22679
             """
22549 22680
         self.drvr._get_cpu_feature_traits()
@@ -22552,7 +22683,6 @@ class LibvirtDriverTestCase(test.NoDBTestCase, TraitsComparisonMixin):
22552 22683
   <model>IvyBridge</model>
22553 22684
   <vendor>Intel</vendor>
22554 22685
   <topology sockets="1" cores="2" threads="1"/>
22555
-  <feature name="pcid"/>
22556 22686
 </cpu>
22557 22687
 '''], 1)
22558 22688
         self.assertItemsEqual(['pcid', 'erms'], mock_to_traits.call_args[0][0])

+ 22
- 14
nova/virt/libvirt/driver.py View File

@@ -9913,27 +9913,35 @@ class LibvirtDriver(driver.ComputeDriver):
9913 9913
                              caps.host.cpu.features | cpu.features]
9914 9914
             return libvirt_utils.cpu_features_to_traits(host_features)
9915 9915
 
9916
+        def _resolve_features(cpu):
9917
+            xml_str = cpu.to_xml()
9918
+            features_xml = self._get_guest_baseline_cpu_features(xml_str)
9919
+            feature_names = []
9920
+            if features_xml:
9921
+                cpu = vconfig.LibvirtConfigCPU()
9922
+                cpu.parse_str(features_xml)
9923
+                feature_names = [f.name for f in cpu.features]
9924
+            return feature_names
9925
+
9926
+        features = set()
9916 9927
         # Choose a default CPU model when cpu_mode is not specified
9917 9928
         if cpu.mode is None:
9918 9929
             caps.host.cpu.model = libvirt_utils.get_cpu_model_from_arch(
9919 9930
                 caps.host.cpu.arch)
9920 9931
             caps.host.cpu.features = set()
9932
+            features = features.union(_resolve_features(caps.host.cpu))
9921 9933
         else:
9922
-            # For custom mode, set model to guest CPU model
9923
-            caps.host.cpu.model = cpu.model
9924
-            caps.host.cpu.features = set()
9934
+            models = [self._get_cpu_model_mapping(model)
9935
+                      for model in CONF.libvirt.cpu_models]
9936
+            # For custom mode, iterate through cpu models
9937
+            for model in models:
9938
+                caps.host.cpu.model = model
9939
+                caps.host.cpu.features = set()
9940
+                features = features.union(_resolve_features(caps.host.cpu))
9925 9941
             # Account for features in cpu_model_extra_flags conf
9926
-            for f in cpu.features:
9927
-                caps.host.cpu.add_feature(
9928
-                    vconfig.LibvirtConfigCPUFeature(name=f.name))
9929
-
9930
-        xml_str = caps.host.cpu.to_xml()
9931
-        features_xml = self._get_guest_baseline_cpu_features(xml_str)
9932
-        feature_names = []
9933
-        if features_xml:
9934
-            cpu.parse_str(features_xml)
9935
-            feature_names = [f.name for f in cpu.features]
9936
-        return libvirt_utils.cpu_features_to_traits(feature_names)
9942
+            features = features.union([f.name for f in cpu.features])
9943
+
9944
+        return libvirt_utils.cpu_features_to_traits(features)
9937 9945
 
9938 9946
     def _get_guest_baseline_cpu_features(self, xml_str):
9939 9947
         """Calls libvirt's baselineCPU API to compute the biggest set of

Loading…
Cancel
Save