Merge "libvirt: Report available TPM models"

This commit is contained in:
Zuul 2024-08-30 07:27:59 +00:00 committed by Gerrit Code Review
commit cf71be0ef0
7 changed files with 106 additions and 22 deletions

View File

@ -295,14 +295,20 @@ class ResourceRequest(object):
if not vtpm_config:
return
# Require the appropriate vTPM version support trait on a host.
if vtpm_config.version == obj_fields.TPMVersion.v1_2:
trait = os_traits.COMPUTE_SECURITY_TPM_1_2
else:
trait = os_traits.COMPUTE_SECURITY_TPM_2_0
# Require the appropriate vTPM model support trait on a host.
model_trait = os_traits.COMPUTE_SECURITY_TPM_TIS
if vtpm_config.model == obj_fields.TPMModel.CRB:
model_trait = os_traits.COMPUTE_SECURITY_TPM_CRB
self._add_trait(trait, 'required')
LOG.debug("Requiring emulated TPM support via trait %s.", trait)
# Require the appropriate vTPM version support trait on a host.
version_trait = os_traits.COMPUTE_SECURITY_TPM_1_2
if vtpm_config.version == obj_fields.TPMVersion.v2_0:
version_trait = os_traits.COMPUTE_SECURITY_TPM_2_0
self._add_trait(model_trait, 'required')
self._add_trait(version_trait, 'required')
LOG.debug("Requiring emulated TPM support via trait %s and %s.",
version_trait, model_trait)
def _translate_memory_encryption(self, flavor, image):
"""When the hw:mem_encryption extra spec or the hw_mem_encryption

View File

@ -2116,7 +2116,6 @@ class Connection(object):
<tpm supported='yes'>
<enum name='model'>
<value>tpm-tis</value>
<value>tpm-crb</value>
</enum>
<enum name='backendModel'>
<value>passthrough</value>

View File

@ -1308,6 +1308,33 @@ class TestUtils(TestUtilsBase):
rr = utils.ResourceRequest.from_request_spec(rs)
self.assertResourceRequestsEqual(expected, rr)
def test_resource_request_from_request_spec_with_vtpm_version_only(self):
flavor = objects.Flavor(
vcpus=1, memory_mb=1024, root_gb=10, ephemeral_gb=5, swap=0,
extra_specs={'hw:tpm_version': '1.2'},
)
image = objects.ImageMeta(
properties=objects.ImageMetaProps(
hw_tpm_version='1.2',
)
)
expected = FakeResourceRequest()
expected._rg_by_id[None] = objects.RequestGroup(
use_same_provider=False,
required_traits={
'COMPUTE_SECURITY_TPM_1_2',
'COMPUTE_SECURITY_TPM_TIS',
},
resources={
'VCPU': 1,
'MEMORY_MB': 1024,
'DISK_GB': 15,
},
)
rs = objects.RequestSpec(flavor=flavor, image=image, is_bfv=False)
rr = utils.ResourceRequest.from_request_spec(rs)
self.assertResourceRequestsEqual(expected, rr)
def test_resource_request_from_request_spec_with_vtpm_1_2(self):
flavor = objects.Flavor(
vcpus=1, memory_mb=1024, root_gb=10, ephemeral_gb=5, swap=0,
@ -1322,7 +1349,10 @@ class TestUtils(TestUtilsBase):
expected = FakeResourceRequest()
expected._rg_by_id[None] = objects.RequestGroup(
use_same_provider=False,
required_traits={'COMPUTE_SECURITY_TPM_1_2'},
required_traits={
'COMPUTE_SECURITY_TPM_1_2',
'COMPUTE_SECURITY_TPM_TIS',
},
resources={
'VCPU': 1,
'MEMORY_MB': 1024,
@ -1347,7 +1377,10 @@ class TestUtils(TestUtilsBase):
expected = FakeResourceRequest()
expected._rg_by_id[None] = objects.RequestGroup(
use_same_provider=False,
required_traits={'COMPUTE_SECURITY_TPM_2_0'},
required_traits={
'COMPUTE_SECURITY_TPM_2_0',
'COMPUTE_SECURITY_TPM_CRB',
},
resources={
'VCPU': 1,
'MEMORY_MB': 1024,

View File

@ -1007,6 +1007,8 @@ class LibvirtConnTestCase(test.NoDBTestCase,
'COMPUTE_NET_VIRTIO_PACKED': True,
'COMPUTE_SECURITY_TPM_1_2': False,
'COMPUTE_SECURITY_TPM_2_0': False,
'COMPUTE_SECURITY_TPM_TIS': False,
'COMPUTE_SECURITY_TPM_CRB': False,
'COMPUTE_STORAGE_BUS_VIRTIO': True,
'COMPUTE_VIOMMU_MODEL_AUTO': True,
'COMPUTE_VIOMMU_MODEL_INTEL': True,
@ -1059,6 +1061,8 @@ class LibvirtConnTestCase(test.NoDBTestCase,
'COMPUTE_NET_VIRTIO_PACKED': True,
'COMPUTE_SECURITY_TPM_1_2': False,
'COMPUTE_SECURITY_TPM_2_0': False,
'COMPUTE_SECURITY_TPM_TIS': False,
'COMPUTE_SECURITY_TPM_CRB': False,
'COMPUTE_VIOMMU_MODEL_AUTO': True,
'COMPUTE_VIOMMU_MODEL_INTEL': True,
'COMPUTE_VIOMMU_MODEL_SMMUV3': True,
@ -22564,7 +22568,9 @@ class TestUpdateProviderTree(test.NoDBTestCase):
def test_update_provider_tree_with_tpm_traits(self):
self.flags(swtpm_enabled=True, group='libvirt')
self._test_update_provider_tree()
for trait in ('COMPUTE_SECURITY_TPM_2_0', 'COMPUTE_SECURITY_TPM_1_2'):
for trait in (
'COMPUTE_SECURITY_TPM_TIS', 'COMPUTE_SECURITY_TPM_CRB',
'COMPUTE_SECURITY_TPM_2_0', 'COMPUTE_SECURITY_TPM_1_2'):
self.assertIn(trait, self.pt.data(self.cn_rp['uuid']).traits)
@mock.patch.object(
@ -22574,7 +22580,9 @@ class TestUpdateProviderTree(test.NoDBTestCase):
def test_update_provider_tree_with_tpm_traits_supported(self):
self.flags(swtpm_enabled=True, group='libvirt')
self._test_update_provider_tree()
for trait in ('COMPUTE_SECURITY_TPM_2_0', 'COMPUTE_SECURITY_TPM_1_2'):
for trait in (
'COMPUTE_SECURITY_TPM_TIS', 'COMPUTE_SECURITY_TPM_CRB',
'COMPUTE_SECURITY_TPM_2_0', 'COMPUTE_SECURITY_TPM_1_2'):
self.assertIn(trait, self.pt.data(self.cn_rp['uuid']).traits)
@mock.patch.object(
@ -22585,9 +22593,9 @@ class TestUpdateProviderTree(test.NoDBTestCase):
def test_update_provider_tree_with_tpm_traits_versions(self):
self.flags(swtpm_enabled=True, group='libvirt')
self._test_update_provider_tree()
for trait in ('COMPUTE_SECURITY_TPM_2_0',):
for trait in ('COMPUTE_SECURITY_TPM_TIS', 'COMPUTE_SECURITY_TPM_2_0'):
self.assertIn(trait, self.pt.data(self.cn_rp['uuid']).traits)
for trait in ('COMPUTE_SECURITY_TPM_1_2',):
for trait in ('COMPUTE_SECURITY_TPM_CRB', 'COMPUTE_SECURITY_TPM_1_2',):
self.assertNotIn(trait, self.pt.data(self.cn_rp['uuid']).traits)
@mock.patch('nova.virt.libvirt.driver.LibvirtDriver.'

View File

@ -920,7 +920,7 @@ class HostTestCase(test.NoDBTestCase):
type(caps.devices.tpm))
self.assertTrue(caps.devices.tpm.supported)
self.assertEqual(
['tpm-tis', 'tpm-crb'],
['tpm-tis'],
caps.devices.tpm.models
)
self.assertEqual(

View File

@ -12922,23 +12922,43 @@ class LibvirtDriver(driver.ComputeDriver):
return {
ot.COMPUTE_SECURITY_TPM_2_0: False,
ot.COMPUTE_SECURITY_TPM_1_2: False,
ot.COMPUTE_SECURITY_TPM_TIS: False,
ot.COMPUTE_SECURITY_TPM_CRB: False,
}
tpm_models = self._host.tpm_models
tpm_versions = self._host.tpm_versions
# libvirt < 8.6 does not provide supported versions in domain
# capabilities
# TODO(tkajinam): Remove this once libvirt>=8.6.0 is required.
tr = {}
if tpm_models is None:
# TODO(tkajinam): Remove this fallback once libvirt>=8.0.0 is
# required.
tr.update({
ot.COMPUTE_SECURITY_TPM_TIS: True,
ot.COMPUTE_SECURITY_TPM_CRB: True,
})
else:
tr.update({
ot.COMPUTE_SECURITY_TPM_TIS: 'tpm-tis' in tpm_models,
ot.COMPUTE_SECURITY_TPM_CRB: 'tpm-crb' in tpm_models,
})
if tpm_versions is None:
return {
# TODO(tkajinam): Remove this fallback once libvirt>=8.6.0 is
# required.
tr.update({
ot.COMPUTE_SECURITY_TPM_2_0: True,
ot.COMPUTE_SECURITY_TPM_1_2: True,
}
})
else:
tr.update({
ot.COMPUTE_SECURITY_TPM_2_0: '2.0' in tpm_versions,
ot.COMPUTE_SECURITY_TPM_1_2: '1.2' in tpm_versions,
})
return {
ot.COMPUTE_SECURITY_TPM_2_0: '2.0' in tpm_versions,
ot.COMPUTE_SECURITY_TPM_1_2: '1.2' in tpm_versions,
}
return tr
def _get_vif_model_traits(self) -> ty.Dict[str, bool]:
"""Get vif model traits based on the currently enabled virt_type.

View File

@ -1878,6 +1878,24 @@ class Host(object):
# safe guard
return []
@property
def tpm_models(self) -> ty.Optional[ty.List[str]]:
# we only check the host architecture and the first machine type
# because vtpm support is independent from cpu architecture
arch = self.get_capabilities().host.cpu.arch
domain_caps = self.get_domain_capabilities()
for machine_type in domain_caps[arch]:
_tpm = domain_caps[arch][machine_type].devices.tpm
# TODO(tkajinam): Remove first check once libvirt >= 8.0.0 is
# required
# TODO(tkajinam): Remove second check once libvirt >= 8.6.0 is
# required
if _tpm is None or _tpm.models is None:
return None
return _tpm.models
# safe guard
return []
def _kernel_supports_amd_sev(self) -> bool:
if not os.path.exists(SEV_KERNEL_PARAM_FILE):
LOG.debug("%s does not exist", SEV_KERNEL_PARAM_FILE)