Support reporting multi CPU model traits
Change existing method: '_get_cpu_traits'. Make it support report multi CPU model's traits. Change-Id: I448f9fe02acda111aa90b3ea17e53bc0c27cd09d Implements: blueprint cpu-model-selection
This commit is contained in:
parent
ac7a0e8409
commit
3d31d97eca
|
@ -22242,6 +22242,138 @@ class LibvirtDriverTestCase(test.NoDBTestCase, TraitsComparisonMixin):
|
|||
</cpu>
|
||||
'''], 1)
|
||||
|
||||
@mock.patch('nova.virt.libvirt.host.libvirt.Connection.getCapabilities')
|
||||
@mock.patch('nova.virt.libvirt.host.libvirt.Connection.baselineCPU')
|
||||
def test_cpu_traits_with_mode_custom_multi_models(self, mocked_baseline,
|
||||
mocked_cap):
|
||||
"""Test getting CPU traits when cpu_mode is 'custom' and cpu_model is
|
||||
['qemu64', 'SandyBridge'], and guest CPU model is Broadwell-noTSX,
|
||||
traits are calculated from _fake_qemu64_cpu_feature and
|
||||
_fake_sandy_bridge_cpu_feature.
|
||||
"""
|
||||
self.flags(cpu_mode='custom',
|
||||
cpu_models=['QEMU64', 'sandybridge'],
|
||||
group='libvirt')
|
||||
mocked_cap.return_value = '''
|
||||
<capabilities>
|
||||
<host>
|
||||
<uuid>cef19ce0-0ca2-11df-855d-b19fbce37686</uuid>
|
||||
<cpu>
|
||||
<arch>x86_64</arch>
|
||||
<model>Broadwell-noTSX</model>
|
||||
<topology sockets='1' cores='2' threads='2'/>
|
||||
<feature policy='require' name='erms'/>
|
||||
<pages unit='KiB' size='4' />
|
||||
<pages unit='KiB' size='1024' />
|
||||
</cpu>
|
||||
</host>
|
||||
</capabilities>
|
||||
'''
|
||||
mocked_baseline.side_effect = (_fake_broadwell_cpu_feature,
|
||||
_fake_qemu64_cpu_feature,
|
||||
_fake_sandy_bridge_cpu_feature)
|
||||
|
||||
self.assertTraitsEqual(
|
||||
[
|
||||
'HW_CPU_X86_AVX',
|
||||
'HW_CPU_X86_AESNI',
|
||||
'HW_CPU_X86_SSE42',
|
||||
'HW_CPU_X86_SSE41',
|
||||
'HW_CPU_X86_CLMUL',
|
||||
'HW_CPU_X86_SSSE3',
|
||||
'HW_CPU_X86_SSE2',
|
||||
'HW_CPU_X86_SSE',
|
||||
'HW_CPU_X86_MMX',
|
||||
'HW_CPU_X86_SVM'
|
||||
], self.drvr._get_cpu_feature_traits()
|
||||
)
|
||||
|
||||
calls = [mock.call([u'''<cpu>
|
||||
<arch>x86_64</arch>
|
||||
<model>Broadwell-noTSX</model>
|
||||
<topology sockets="1" cores="2" threads="2"/>
|
||||
<feature name="erms"/>
|
||||
</cpu>
|
||||
'''], 1), mock.call([u'''<cpu>
|
||||
<arch>x86_64</arch>
|
||||
<model>qemu64</model>
|
||||
<topology sockets="1" cores="2" threads="2"/>
|
||||
</cpu>
|
||||
'''], 1), mock.call([u'''<cpu>
|
||||
<arch>x86_64</arch>
|
||||
<model>SandyBridge</model>
|
||||
<topology sockets="1" cores="2" threads="2"/>
|
||||
</cpu>
|
||||
'''], 1)]
|
||||
mocked_baseline.assert_has_calls(calls)
|
||||
|
||||
@mock.patch('nova.virt.libvirt.host.libvirt.Connection.getCapabilities')
|
||||
@mock.patch('nova.virt.libvirt.host.libvirt.Connection.baselineCPU')
|
||||
def test_cpu_traits_with_mode_custom_multi_models_and_extra_flags(self,
|
||||
mocked_baseline, mocked_cap):
|
||||
"""Test getting CPU traits when cpu_mode is 'custom' and cpu_model is
|
||||
['qemu64', 'SandyBridge'], cpu_model_extra_specs is ['pcid', 'avx2']
|
||||
and guest CPU model is Broadwell-noTSX, traits are calculated from
|
||||
_fake_qemu64_cpu_feature and _fake_sandy_bridge_cpu_feature.
|
||||
"""
|
||||
self.flags(cpu_mode='custom',
|
||||
cpu_models=['QEMU64', 'sandybridge'],
|
||||
cpu_model_extra_flags=['pcid', 'avx2'],
|
||||
group='libvirt')
|
||||
mocked_cap.return_value = '''
|
||||
<capabilities>
|
||||
<host>
|
||||
<uuid>cef19ce0-0ca2-11df-855d-b19fbce37686</uuid>
|
||||
<cpu>
|
||||
<arch>x86_64</arch>
|
||||
<model>Broadwell-noTSX</model>
|
||||
<topology sockets='1' cores='2' threads='2'/>
|
||||
<feature policy='require' name='erms'/>
|
||||
<pages unit='KiB' size='4' />
|
||||
<pages unit='KiB' size='1024' />
|
||||
</cpu>
|
||||
</host>
|
||||
</capabilities>
|
||||
'''
|
||||
mocked_baseline.side_effect = (_fake_broadwell_cpu_feature,
|
||||
_fake_qemu64_cpu_feature,
|
||||
_fake_sandy_bridge_cpu_feature)
|
||||
|
||||
self.assertTraitsEqual(
|
||||
[
|
||||
'HW_CPU_X86_AVX',
|
||||
'HW_CPU_X86_AVX2',
|
||||
'HW_CPU_X86_AESNI',
|
||||
'HW_CPU_X86_SSE42',
|
||||
'HW_CPU_X86_SSE41',
|
||||
'HW_CPU_X86_CLMUL',
|
||||
'HW_CPU_X86_SSSE3',
|
||||
'HW_CPU_X86_SSE2',
|
||||
'HW_CPU_X86_SSE',
|
||||
'HW_CPU_X86_MMX',
|
||||
'HW_CPU_X86_SVM'
|
||||
], self.drvr._get_cpu_feature_traits()
|
||||
)
|
||||
|
||||
calls = [mock.call([u'''<cpu>
|
||||
<arch>x86_64</arch>
|
||||
<model>Broadwell-noTSX</model>
|
||||
<topology sockets="1" cores="2" threads="2"/>
|
||||
<feature name="erms"/>
|
||||
</cpu>
|
||||
'''], 1), mock.call([u'''<cpu>
|
||||
<arch>x86_64</arch>
|
||||
<model>qemu64</model>
|
||||
<topology sockets="1" cores="2" threads="2"/>
|
||||
</cpu>
|
||||
'''], 1), mock.call([u'''<cpu>
|
||||
<arch>x86_64</arch>
|
||||
<model>SandyBridge</model>
|
||||
<topology sockets="1" cores="2" threads="2"/>
|
||||
</cpu>
|
||||
'''], 1)]
|
||||
mocked_baseline.assert_has_calls(calls)
|
||||
|
||||
@mock.patch('nova.virt.libvirt.host.libvirt.Connection.baselineCPU')
|
||||
def test_cpu_traits_with_no_baseline_support(self, mock_baseline):
|
||||
"""Test getting CPU traits when baseline call is not supported."""
|
||||
|
@ -22339,7 +22471,6 @@ class LibvirtDriverTestCase(test.NoDBTestCase, TraitsComparisonMixin):
|
|||
<model fallback='forbid'>IvyBridge</model>
|
||||
<vendor>Intel</vendor>
|
||||
<feature policy='require' name='erms'/>
|
||||
<feature policy='require' name='pcid'/>
|
||||
</cpu>
|
||||
"""
|
||||
self.drvr._get_cpu_feature_traits()
|
||||
|
@ -22348,7 +22479,6 @@ class LibvirtDriverTestCase(test.NoDBTestCase, TraitsComparisonMixin):
|
|||
<model>IvyBridge</model>
|
||||
<vendor>Intel</vendor>
|
||||
<topology sockets="1" cores="2" threads="1"/>
|
||||
<feature name="pcid"/>
|
||||
</cpu>
|
||||
'''], 1)
|
||||
self.assertItemsEqual(['pcid', 'erms'], mock_to_traits.call_args[0][0])
|
||||
|
|
|
@ -9781,27 +9781,35 @@ class LibvirtDriver(driver.ComputeDriver):
|
|||
caps.host.cpu.features | cpu.features]
|
||||
return libvirt_utils.cpu_features_to_traits(host_features)
|
||||
|
||||
def _resolve_features(cpu):
|
||||
xml_str = cpu.to_xml()
|
||||
features_xml = self._get_guest_baseline_cpu_features(xml_str)
|
||||
feature_names = []
|
||||
if features_xml:
|
||||
cpu = vconfig.LibvirtConfigCPU()
|
||||
cpu.parse_str(features_xml)
|
||||
feature_names = [f.name for f in cpu.features]
|
||||
return feature_names
|
||||
|
||||
features = set()
|
||||
# Choose a default CPU model when cpu_mode is not specified
|
||||
if cpu.mode is None:
|
||||
caps.host.cpu.model = libvirt_utils.get_cpu_model_from_arch(
|
||||
caps.host.cpu.arch)
|
||||
caps.host.cpu.features = set()
|
||||
features = features.union(_resolve_features(caps.host.cpu))
|
||||
else:
|
||||
# For custom mode, set model to guest CPU model
|
||||
caps.host.cpu.model = cpu.model
|
||||
caps.host.cpu.features = set()
|
||||
models = [self._get_cpu_model_mapping(model)
|
||||
for model in CONF.libvirt.cpu_models]
|
||||
# For custom mode, iterate through cpu models
|
||||
for model in models:
|
||||
caps.host.cpu.model = model
|
||||
caps.host.cpu.features = set()
|
||||
features = features.union(_resolve_features(caps.host.cpu))
|
||||
# Account for features in cpu_model_extra_flags conf
|
||||
for f in cpu.features:
|
||||
caps.host.cpu.add_feature(
|
||||
vconfig.LibvirtConfigCPUFeature(name=f.name))
|
||||
features = features.union([f.name for f in cpu.features])
|
||||
|
||||
xml_str = caps.host.cpu.to_xml()
|
||||
features_xml = self._get_guest_baseline_cpu_features(xml_str)
|
||||
feature_names = []
|
||||
if features_xml:
|
||||
cpu.parse_str(features_xml)
|
||||
feature_names = [f.name for f in cpu.features]
|
||||
return libvirt_utils.cpu_features_to_traits(feature_names)
|
||||
return libvirt_utils.cpu_features_to_traits(features)
|
||||
|
||||
def _get_guest_baseline_cpu_features(self, xml_str):
|
||||
"""Calls libvirt's baselineCPU API to compute the biggest set of
|
||||
|
|
Loading…
Reference in New Issue