Merge "Follow-up of AMD SEV-ES support"

This commit is contained in:
Zuul
2025-09-01 11:59:27 +00:00
committed by Gerrit Code Review
7 changed files with 332 additions and 169 deletions
@@ -330,10 +330,12 @@ class LibvirtReportSevTraitsTests(LibvirtReportTraitsTestBase):
def setUp(self):
super(LibvirtReportSevTraitsTests, self).setUp()
def _init_compute(self, sev, sev_es):
sev_features = (fakelibvirt.virConnect.
_domain_capability_features_with_SEV_max_guests)
with test.nested(
self._patch_sev_exists(True, True),
self._patch_sev_exists(sev, sev_es),
self._patch_sev_open(),
mock.patch.object(fakelibvirt.virConnect,
'_domain_capability_features',
@@ -346,20 +348,106 @@ class LibvirtReportSevTraitsTests(LibvirtReportTraitsTestBase):
self.start_compute()
def test_sev_trait_on_off(self):
"""Test that the compute service reports the SEV/SEV-ES trait in
"""Test that the compute service reports the SEV trait in
the list of global traits, and immediately registers it on the compute
host resource provider in the placement API, due to the SEV/SEV-ES
host resource provider in the placement API, due to the SEV
capability being (mocked as) present.
Then test that if the SEV/SEV-ES capability disappears (again via
Then test that if the SEV capability disappears (again via mocking),
after a restart of the compute service, the trait gets removed from
the compute host.
Also test that on both occasions, the inventory of the
MEM_ENCRYPTION_CONTEXT resource class on the compute host
corresponds to the absence or presence of the SEV capability.
"""
self._init_compute(True, False)
# Make sure that SEV is enabled but SEV-ES is not enabled
self.assertTrue(self.compute.driver._host.supports_amd_sev)
self.assertFalse(self.compute.driver._host.supports_amd_sev_es)
global_traits = self._get_all_traits()
self.assertIn(ost.HW_CPU_X86_AMD_SEV, global_traits)
self.assertIn(ost.HW_CPU_X86_AMD_SEV_ES, global_traits)
# sev capabilities are managed by sub rp and are not present in root rp
traits = self._get_provider_traits(self.host_uuid)
self.assertNotIn(ost.HW_CPU_X86_AMD_SEV, traits)
self.assertMemEncryptionSlotsEqual(self.host_uuid, 0)
sev_rps = self._get_amd_sev_rps()
self.assertEqual(1, len(sev_rps['sev']))
sev_rp_uuid = sev_rps['sev'][0]['uuid']
sev_rp_traits = self._get_provider_traits(sev_rp_uuid)
self.assertIn(ost.HW_CPU_X86_AMD_SEV, sev_rp_traits)
self.assertMemEncryptionSlotsEqual(sev_rp_uuid, 100)
self.assertEqual(0, len(sev_rps['sev-es']))
# Now simulate the host losing SEV functionality. Here we
# simulate a kernel downgrade or reconfiguration which causes
# the kvm-amd kernel module's "sev-" parameter to become
# unavailable.
sev_features = (fakelibvirt.virConnect.
_domain_capability_features_with_SEV)
with test.nested(
self._patch_sev_exists(False, False),
self._patch_sev_open(),
mock.patch.object(fakelibvirt.virConnect,
'_domain_capability_features',
new=sev_features)
) as (mock_exists, mock_open, mock_features):
# Retrigger the detection code. In the real world this
# would be a restart of the compute service.
self.compute.driver._host._domain_caps = None
self.compute.driver._host._supports_amd_sev = None
self.compute.driver._host._supports_amd_sev_es = None
self.assertFalse(self.compute.driver._host.supports_amd_sev)
self.assertFalse(self.compute.driver._host.supports_amd_sev_es)
mock_exists.assert_has_calls([
mock.call(libvirt_host.SEV_KERNEL_PARAM_FILE % 'sev'),
])
# However it won't disappear in the provider tree and get synced
# back to placement until we force a reinventory:
self.compute.manager.reset()
# reset cached traits so they are recalculated.
self.compute.driver._static_traits = None
self._run_periodics()
# Sanity check that we've still got the trait globally.
global_traits = self._get_all_traits()
self.assertIn(ost.HW_CPU_X86_AMD_SEV, global_traits)
self.assertIn(ost.HW_CPU_X86_AMD_SEV_ES, global_traits)
traits = self._get_provider_traits(self.host_uuid)
self.assertNotIn(ost.HW_CPU_X86_AMD_SEV, traits)
self.assertNotIn(ost.HW_CPU_X86_AMD_SEV_ES, traits)
sev_rps = self._get_amd_sev_rps()
self.assertEqual(0, len(sev_rps['sev']))
self.assertEqual(0, len(sev_rps['sev-es']))
def test_sev_es_trait_on_off(self):
"""Test that the compute service reports the SEV-ES trait in
the list of global traits, and immediately registers it on the compute
host resource provider in the placement API, due to the SEV-ES
capability being (mocked as) present.
Then test that if the SEV-ES capability disappears (again via
mocking), after a restart of the compute service, the trait
gets removed from the compute host.
Also test that on both occasions, the inventory of the
MEM_ENCRYPTION_CONTEXT resource class on the compute host
corresponds to the absence or presence of the SEV/SEV-ES capability.
corresponds to the absence or presence of the SEV-ES capability.
"""
self._init_compute(True, True)
# Make sure that both SEV and SEV-ES are enabled
self.assertTrue(self.compute.driver._host.supports_amd_sev)
self.assertTrue(self.compute.driver._host.supports_amd_sev_es)
@@ -437,10 +525,54 @@ class LibvirtReportSevTraitsTests(LibvirtReportTraitsTestBase):
self.assertEqual(1, len(sev_rps['sev']))
self.assertEqual(0, len(sev_rps['sev-es']))
# Now simulate the host losing SEV functionality. Here we
def test_sev_all_trait_on_off(self):
"""Test that the compute service reports the SEV/SEV-ES trait in
the list of global traits, and immediately registers it on the compute
host resource provider in the placement API, due to the SEV/SEV-ES
capability being (mocked as) present.
Then test that if the SEV/SEV-ES capability disappears (again via
mocking), after a restart of the compute service, the trait
gets removed from the compute host.
Also test that on both occasions, the inventory of the
MEM_ENCRYPTION_CONTEXT resource class on the compute host
corresponds to the absence or presence of the SEV/SEV-ES capability.
"""
self._init_compute(True, True)
# Make sure that both SEV and SEV-ES are enabled
self.assertTrue(self.compute.driver._host.supports_amd_sev)
self.assertTrue(self.compute.driver._host.supports_amd_sev_es)
global_traits = self._get_all_traits()
self.assertIn(ost.HW_CPU_X86_AMD_SEV, global_traits)
self.assertIn(ost.HW_CPU_X86_AMD_SEV_ES, global_traits)
# sev capabilities are managed by sub rp and are not present in root rp
traits = self._get_provider_traits(self.host_uuid)
self.assertNotIn(ost.HW_CPU_X86_AMD_SEV, traits)
self.assertMemEncryptionSlotsEqual(self.host_uuid, 0)
sev_rps = self._get_amd_sev_rps()
self.assertEqual(1, len(sev_rps['sev']))
sev_rp_uuid = sev_rps['sev'][0]['uuid']
sev_rp_traits = self._get_provider_traits(sev_rp_uuid)
self.assertIn(ost.HW_CPU_X86_AMD_SEV, sev_rp_traits)
self.assertMemEncryptionSlotsEqual(sev_rp_uuid, 100)
self.assertEqual(1, len(sev_rps['sev-es']))
sev_es_rp_uuid = sev_rps['sev-es'][0]['uuid']
sev_es_rp_traits = self._get_provider_traits(sev_es_rp_uuid)
self.assertIn(ost.HW_CPU_X86_AMD_SEV_ES, sev_es_rp_traits)
self.assertMemEncryptionSlotsEqual(sev_es_rp_uuid, 15)
self.assertEqual(1, len(sev_rps['sev']))
# Now simulate the host losing SEV/SEV-ES functionality. Here we
# simulate a kernel downgrade or reconfiguration which causes
# the kvm-amd kernel module's "sev-" parameter to become
# unavailable.
# the kvm-amd kernel module's "sev" parameter and "sev-es" parameter
# to become unavailable, however it could also happen via a libvirt
# downgrade, for instance.
sev_features = (fakelibvirt.virConnect.
_domain_capability_features_with_SEV)
with test.nested(
@@ -280,6 +280,7 @@ class SevResphapeTests(base.ServersTestBase):
compute_rp_uuid = self._get_provider_uuid_by_name('compute1')
inventories = self.placement.get(
'/resource_providers/%s/inventories' % compute_rp_uuid).body
# MEM_ENCRYPTION_CONTEXT inventory was added to compute RP
inventories['inventories']['MEM_ENCRYPTION_CONTEXT'] = {
'allocation_ratio': 1.0,
'max_unit': 1,
@@ -290,6 +291,7 @@ class SevResphapeTests(base.ServersTestBase):
self.placement.put(
'/resource_providers/%s/inventories' % compute_rp_uuid,
inventories)
# SEV trait was also added to compute RP
traits = self._get_provider_traits(compute_rp_uuid)
traits.append(os_traits.HW_CPU_X86_AMD_SEV)
self._set_provider_traits(compute_rp_uuid, traits)
@@ -322,13 +324,14 @@ class SevResphapeTests(base.ServersTestBase):
self.assertNotIn('MEM_ENCRYPTION_CONTEXT', compute_inventories)
compute_usages = self._get_provider_usages(compute_rp_uuid)
self.assertNotIn('MEM_ENCRYPTION_CONTEXT', compute_usages)
# MEM_ENCRYPTION_CONTEXT inventory/usage should be moreved to child RP
sev_rp_uuid = self._get_provider_uuid_by_name('compute1_amd_sev')
sev_inventories = self._get_provider_inventory(sev_rp_uuid)
self.assertEqual(
16, sev_inventories['MEM_ENCRYPTION_CONTEXT']['total'])
sev_usages = self._get_provider_usages(sev_rp_uuid)
self.assertEqual(1, sev_usages['MEM_ENCRYPTION_CONTEXT'])
# SEV trait should be also moved to child RP
sev_traits = self._get_provider_traits(sev_rp_uuid)
self.assertIn(os_traits.HW_CPU_X86_AMD_SEV, sev_traits)
@@ -370,6 +373,7 @@ class SevResphapeTests(base.ServersTestBase):
compute_rp_uuid = self._get_provider_uuid_by_name(name)
inventories = self.placement.get(
'/resource_providers/%s/inventories' % compute_rp_uuid).body
# MEM_ENCRYPTION_CONTEXT inventory was added to compute RP
inventories['inventories']['MEM_ENCRYPTION_CONTEXT'] = {
'allocation_ratio': 1.0,
'max_unit': 1,
@@ -380,6 +384,7 @@ class SevResphapeTests(base.ServersTestBase):
self.placement.put(
'/resource_providers/%s/inventories' % compute_rp_uuid,
inventories)
# SEV trait was also added to compute root RP
traits = self._get_provider_traits(compute_rp_uuid)
traits.append(os_traits.HW_CPU_X86_AMD_SEV)
self._set_provider_traits(compute_rp_uuid, traits)
@@ -444,7 +449,7 @@ class SevResphapeTests(base.ServersTestBase):
sev_usages = self._get_provider_usages(sev_rp_uuid)
self.assertEqual(1, sev_usages['MEM_ENCRYPTION_CONTEXT'])
# server2 should allocate M_E_C from compute RP
# server2 should allocate M_E_C from compute root RP
compute_rp_uuid = self._get_provider_uuid_by_name('compute2')
compute_usages = self._get_provider_usages(compute_rp_uuid)
self.assertEqual(1, compute_usages['MEM_ENCRYPTION_CONTEXT'])
+152 -141
View File
@@ -10,6 +10,7 @@
# License for the specific language governing permissions and limitations
# under the License.
import itertools
from unittest import mock
import ddt
@@ -2301,6 +2302,7 @@ class TestUtils(TestUtilsBase):
mock_map.assert_called_once_with(allocation, {uuids.rp_uuid: traits})
@ddt.ddt
class TestEncryptedMemoryTranslation(TestUtilsBase):
flavor_name = 'm1.test'
image_name = 'cirros'
@@ -2333,13 +2335,13 @@ class TestEncryptedMemoryTranslation(TestUtilsBase):
'MEMORY_MB': 1024,
'DISK_GB': 15,
}
required_traits = []
required_traits = set()
if mem_encryption_model == 'amd-sev':
expected_resources[orc.MEM_ENCRYPTION_CONTEXT] = 1
required_traits = ['HW_CPU_X86_AMD_SEV']
required_traits |= {'HW_CPU_X86_AMD_SEV'}
elif mem_encryption_model == 'amd-sev-es':
expected_resources[orc.MEM_ENCRYPTION_CONTEXT] = 1
required_traits = ['HW_CPU_X86_AMD_SEV_ES']
required_traits |= {'HW_CPU_X86_AMD_SEV_ES'}
elif mem_encryption_model is not None:
self.fail('invalid mem_encryption_model: %s'
% mem_encryption_model)
@@ -2348,7 +2350,7 @@ class TestEncryptedMemoryTranslation(TestUtilsBase):
expected._rg_by_id[None] = objects.RequestGroup(
use_same_provider=False,
resources=expected_resources,
required_traits=set(required_traits)
required_traits=required_traits
)
return expected
@@ -2362,34 +2364,35 @@ class TestEncryptedMemoryTranslation(TestUtilsBase):
def test_encrypted_memory_support_empty_extra_specs(self):
self._test_encrypted_memory_support_not_required(extra_specs={})
def test_encrypted_memory_support_false_extra_spec(self):
for extra_spec in ('0', 'false', 'False'):
self._test_encrypted_memory_support_not_required(
extra_specs={'hw:mem_encryption': extra_spec})
@ddt.data('0', 'false', 'False')
def test_encrypted_memory_support_false_extra_spec(self, extra_spec):
self._test_encrypted_memory_support_not_required(
extra_specs={'hw:mem_encryption': extra_spec})
def test_encrypted_memory_support_empty_image_props(self):
self._test_encrypted_memory_support_not_required(
extra_specs={},
image=objects.ImageMeta(properties=objects.ImageMetaProps()))
def test_encrypted_memory_support_false_image_prop(self):
for image_prop in ('0', 'false', 'False'):
self._test_encrypted_memory_support_not_required(
extra_specs={},
image=objects.ImageMeta(
properties=objects.ImageMetaProps(
hw_mem_encryption=image_prop))
)
@ddt.data('0', 'false', 'False')
def test_encrypted_memory_support_false_image_prop(self, image_prop):
self._test_encrypted_memory_support_not_required(
extra_specs={},
image=objects.ImageMeta(
properties=objects.ImageMetaProps(
hw_mem_encryption=image_prop))
)
def test_encrypted_memory_support_both_false(self):
for extra_spec in ('0', 'false', 'False'):
for image_prop in ('0', 'false', 'False'):
self._test_encrypted_memory_support_not_required(
extra_specs={'hw:mem_encryption': extra_spec},
image=objects.ImageMeta(
properties=objects.ImageMetaProps(
hw_mem_encryption=image_prop))
)
@ddt.unpack
@ddt.data(*itertools.product(
('0', 'false', 'False'), ('0', 'false', 'False')))
def test_encrypted_memory_support_both_false(self, image_prop, extra_spec):
self._test_encrypted_memory_support_not_required(
extra_specs={'hw:mem_encryption': extra_spec},
image=objects.ImageMeta(
properties=objects.ImageMetaProps(
hw_mem_encryption=image_prop))
)
def _test_encrypted_memory_support_conflict(self, extra_spec,
image_prop_in,
@@ -2432,19 +2435,25 @@ class TestEncryptedMemoryTranslation(TestUtilsBase):
}
self.assertEqual(error % error_data, str(exc))
def test_encrypted_memory_support_conflict1(self):
for extra_spec in ('0', 'false', 'False'):
for image_prop_in in ('1', 'true', 'True'):
self._test_encrypted_memory_support_conflict(
extra_spec, image_prop_in, True
)
@ddt.unpack
@ddt.data(*itertools.product(
('1', 'true', 'True'),
('0', 'false', 'False')))
def test_encrypted_memory_support_conflict1(
self, image_prop_in, extra_spec):
self._test_encrypted_memory_support_conflict(
extra_spec, image_prop_in, True
)
def test_encrypted_memory_support_conflict2(self):
for extra_spec in ('1', 'true', 'True'):
for image_prop_in in ('0', 'false', 'False'):
self._test_encrypted_memory_support_conflict(
extra_spec, image_prop_in, False
)
@ddt.unpack
@ddt.data(*itertools.product(
('0', 'false', 'False'),
('1', 'true', 'True')))
def test_encrypted_memory_support_conflict2(
self, image_prop_in, extra_spec):
self._test_encrypted_memory_support_conflict(
extra_spec, image_prop_in, False
)
@mock.patch.object(utils, 'LOG')
def _test_encrypted_memory_support_required(self, requesters, extra_specs,
@@ -2467,120 +2476,122 @@ class TestEncryptedMemoryTranslation(TestUtilsBase):
model, me_trait)
])
def test_encrypted_memory_support_extra_spec(self):
for extra_spec in ('1', 'true', 'True'):
self._test_encrypted_memory_support_required(
'hw:mem_encryption extra spec',
{'hw:mem_encryption': extra_spec},
image=objects.ImageMeta(
id='005249be-3c2f-4351-9df7-29bb13c21b14',
properties=objects.ImageMetaProps(
hw_machine_type='q35',
hw_firmware_type='uefi'))
)
@ddt.data('1', 'true', 'True')
def test_encrypted_memory_support_extra_spec(self, extra_spec):
self._test_encrypted_memory_support_required(
'hw:mem_encryption extra spec',
{'hw:mem_encryption': extra_spec},
image=objects.ImageMeta(
id='005249be-3c2f-4351-9df7-29bb13c21b14',
properties=objects.ImageMetaProps(
hw_machine_type='q35',
hw_firmware_type='uefi'))
)
def test_encrypted_memory_support_image_prop(self):
for image_prop in ('1', 'true', 'True'):
self._test_encrypted_memory_support_required(
'hw_mem_encryption image property',
{},
image=objects.ImageMeta(
id='005249be-3c2f-4351-9df7-29bb13c21b14',
name=self.image_name,
properties=objects.ImageMetaProps(
hw_machine_type='q35',
hw_firmware_type='uefi',
hw_mem_encryption=image_prop))
)
@ddt.data('1', 'true', 'True')
def test_encrypted_memory_support_image_prop(self, image_prop):
self._test_encrypted_memory_support_required(
'hw_mem_encryption image property',
{},
image=objects.ImageMeta(
id='005249be-3c2f-4351-9df7-29bb13c21b14',
name=self.image_name,
properties=objects.ImageMetaProps(
hw_machine_type='q35',
hw_firmware_type='uefi',
hw_mem_encryption=image_prop))
)
def test_encrypted_memory_support_both_required(self):
for extra_spec in ('1', 'true', 'True'):
for image_prop in ('1', 'true', 'True'):
self._test_encrypted_memory_support_required(
'hw:mem_encryption extra spec and '
'hw_mem_encryption image property',
{'hw:mem_encryption': extra_spec},
image=objects.ImageMeta(
id='005249be-3c2f-4351-9df7-29bb13c21b14',
name=self.image_name,
properties=objects.ImageMetaProps(
hw_machine_type='q35',
hw_firmware_type='uefi',
hw_mem_encryption=image_prop))
)
@ddt.unpack
@ddt.data(*itertools.product(
('1', 'true', 'True'), ('1', 'true', 'True')))
def test_encrypted_memory_support_both_required(
self, image_prop, extra_spec):
self._test_encrypted_memory_support_required(
'hw:mem_encryption extra spec and '
'hw_mem_encryption image property',
{'hw:mem_encryption': extra_spec},
image=objects.ImageMeta(
id='005249be-3c2f-4351-9df7-29bb13c21b14',
name=self.image_name,
properties=objects.ImageMetaProps(
hw_machine_type='q35',
hw_firmware_type='uefi',
hw_mem_encryption=image_prop))
)
def test_encrypted_memory_model_extra_spec(self):
for model in ('amd-sev', 'amd-sev-es'):
self._test_encrypted_memory_support_required(
'hw:mem_encryption extra spec',
{'hw:mem_encryption': 'true',
'hw:mem_encryption_model': model},
image=objects.ImageMeta(
id='005249be-3c2f-4351-9df7-29bb13c21b14',
properties=objects.ImageMetaProps(
hw_machine_type='q35',
hw_firmware_type='uefi')),
model=model
)
@ddt.data('amd-sev', 'amd-sev-es')
def test_encrypted_memory_model_extra_spec(self, model):
self._test_encrypted_memory_support_required(
'hw:mem_encryption extra spec',
{'hw:mem_encryption': 'true',
'hw:mem_encryption_model': model},
image=objects.ImageMeta(
id='005249be-3c2f-4351-9df7-29bb13c21b14',
properties=objects.ImageMetaProps(
hw_machine_type='q35',
hw_firmware_type='uefi')),
model=model
)
def test_encrypted_memory_model_image_prop(self):
for model in ('amd-sev', 'amd-sev-es'):
self._test_encrypted_memory_support_required(
'hw_mem_encryption image property',
{},
image=objects.ImageMeta(
id='005249be-3c2f-4351-9df7-29bb13c21b14',
name=self.image_name,
properties=objects.ImageMetaProps(
hw_machine_type='q35',
hw_firmware_type='uefi',
hw_mem_encryption='true',
hw_mem_encryption_model=model)),
model=model
)
def test_encrypted_memory_model_both_required(self):
for model in ('amd-sev', 'amd-sev-es'):
self._test_encrypted_memory_support_required(
'hw:mem_encryption extra spec and '
'hw_mem_encryption image property',
{'hw:mem_encryption': 'true',
'hw:mem_encryption_model': model},
image=objects.ImageMeta(
id='005249be-3c2f-4351-9df7-29bb13c21b14',
name=self.image_name,
properties=objects.ImageMetaProps(
hw_machine_type='q35',
hw_firmware_type='uefi',
hw_mem_encryption='true',
hw_mem_encryption_model=model)),
model=model
)
def test_encrypted_memory_model_conflict_1(self):
for f_model, i_model in (
('amd-sev', 'amd-sev-es'),
('amd-sev-es', 'amd-sev')
):
image = objects.ImageMeta(
@ddt.data('amd-sev', 'amd-sev-es')
def test_encrypted_memory_model_image_prop(self, model):
self._test_encrypted_memory_support_required(
'hw_mem_encryption image property',
{},
image=objects.ImageMeta(
id='005249be-3c2f-4351-9df7-29bb13c21b14',
name=self.image_name,
properties=objects.ImageMetaProps(
hw_machine_type='q35',
hw_firmware_type='uefi',
hw_mem_encryption='true',
hw_mem_encryption_model=i_model
)
)
reqspec = self._get_request_spec(
extra_specs={
'hw:mem_encryption': 'true',
'hw:mem_encryption_model': f_model,
},
image=image)
self.assertRaises(
exception.FlavorImageConflict,
utils.ResourceRequest.from_request_spec, reqspec
hw_mem_encryption_model=model)),
model=model
)
@ddt.data('amd-sev', 'amd-sev-es')
def test_encrypted_memory_model_both_required(self, model):
self._test_encrypted_memory_support_required(
'hw:mem_encryption extra spec and '
'hw_mem_encryption image property',
{'hw:mem_encryption': 'true',
'hw:mem_encryption_model': model},
image=objects.ImageMeta(
id='005249be-3c2f-4351-9df7-29bb13c21b14',
name=self.image_name,
properties=objects.ImageMetaProps(
hw_machine_type='q35',
hw_firmware_type='uefi',
hw_mem_encryption='true',
hw_mem_encryption_model=model)),
model=model
)
@ddt.unpack
@ddt.data(
('amd-sev', 'amd-sev-es'),
('amd-sev-es', 'amd-sev'))
def test_encrypted_memory_model_conflict_1(self, f_model, i_model):
image = objects.ImageMeta(
name=self.image_name,
properties=objects.ImageMetaProps(
hw_machine_type='q35',
hw_firmware_type='uefi',
hw_mem_encryption='true',
hw_mem_encryption_model=i_model
)
)
reqspec = self._get_request_spec(
extra_specs={
'hw:mem_encryption': 'true',
'hw:mem_encryption_model': f_model,
},
image=image)
self.assertRaises(
exception.FlavorImageConflict,
utils.ResourceRequest.from_request_spec, reqspec
)
class TestResourcesFromRequestGroupDefaultPolicy(test.NoDBTestCase):
+2 -2
View File
@@ -2716,11 +2716,11 @@ class LibvirtConfigGuestTest(LibvirtConfigBaseTest):
self.assertXmlEqual(launch_security_expected, xml)
obj.policy = 0x0035
obj.policy = obj.DEFAULT_SEV_ES_POLICY
xml = obj.to_xml()
launch_security_expected = """
<launchSecurity type="sev">
<policy>0x0035</policy>
<policy>0x0037</policy>
<cbitpos>47</cbitpos>
<reducedPhysBits>1</reducedPhysBits>
</launchSecurity>"""
+1 -1
View File
@@ -3974,7 +3974,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
@ddt.data(
{'sev_model': None, 'sev_policy': 0x0033},
{'sev_model': 'amd-sev', 'sev_policy': 0x0033},
{'sev_model': 'amd-sev-es', 'sev_policy': 0x0035}
{'sev_model': 'amd-sev-es', 'sev_policy': 0x0037}
)
@mock.patch.object(host.Host, 'get_domain_capabilities')
@mock.patch.object(designer, 'set_driver_iommu_for_all_devices')
+17 -3
View File
@@ -3018,13 +3018,27 @@ class LibvirtConfigGuestFeatureHyperV(LibvirtConfigGuestFeature):
class LibvirtConfigGuestSEVLaunchSecurity(LibvirtConfigObject):
# NOTE(tkajinam): See also
# https://gitlab.com/qemu-project/qemu/-/blob/v10.1.0/target/i386/sev.h
SEV_POLICY_NODEBG = 0x1
SEV_POLICY_NOKS = 0x2
SEV_POLICY_ES = 0x4
SEV_POLICY_NOSEND = 0x8
SEV_POLICY_DOMAIN = 0x10
SEV_POLICY_SEV = 0x20
DEFAULT_SEV_POLICY = (
SEV_POLICY_NODEBG | SEV_POLICY_NOKS |
SEV_POLICY_DOMAIN | SEV_POLICY_SEV)
DEFAULT_SEV_ES_POLICY = (
DEFAULT_SEV_POLICY | SEV_POLICY_ES)
def __init__(self, **kwargs):
super(LibvirtConfigGuestSEVLaunchSecurity, self).__init__(
root_name='launchSecurity', **kwargs)
# hardcoded default for SEV according to the spec
self.policy = 0x0033
# Use SEV policy as default, because SEV is the default encryption
# model
self.policy = self.DEFAULT_SEV_POLICY
self.cbitpos = None
self.reduced_phys_bits = None
+13 -12
View File
@@ -7702,8 +7702,9 @@ class LibvirtDriver(driver.ComputeDriver):
launch_security = vconfig.LibvirtConfigGuestSEVLaunchSecurity()
launch_security.cbitpos = sev.cbitpos
launch_security.reduced_phys_bits = sev.reduced_phys_bits
# NOTE(tkajinam): Default policy is for SEV
if model == fields.MemEncryptionModel.AMD_SEV_ES:
launch_security.policy = 0x0035
launch_security.policy = launch_security.DEFAULT_SEV_ES_POLICY
guest.launch_security = launch_security
def _find_sev_feature(self, arch, mach_type):
@@ -9560,8 +9561,8 @@ class LibvirtDriver(driver.ComputeDriver):
metadata=vpmem)
resources[rc].add(resource_obj)
def _update_provider_tree_for_memory_encryption(self, provider_tree,
nodename, allocations):
def _update_provider_tree_for_memory_encryption(
self, provider_tree, nodename, allocations):
"""Updates the provider tree for MEM_ENCRYPTION_CONTEXT inventory.
Before 2025.2, MEM_ENCRYPTION_CONTEXT inventory and allocations were on
@@ -9626,8 +9627,8 @@ class LibvirtDriver(driver.ComputeDriver):
root_node = provider_tree.data(nodename)
return orc.MEM_ENCRYPTION_CONTEXT in root_node.inventory
def _ensure_memory_encryption_providers(self, inventories_dict,
provider_tree, nodename):
def _ensure_memory_encryption_providers(
self, inventories_dict, provider_tree, nodename):
"""Ensures MEM_ENCRYPTION_CONTEXT inventory providers exist in the tree
for $nodename.
@@ -9660,7 +9661,7 @@ class LibvirtDriver(driver.ComputeDriver):
if not inventory['total']:
if provider_tree.exists(me_rp_name):
provider_tree.remove(me_rp_name)
break
continue
if not provider_tree.exists(me_rp_name):
provider_tree.new_child(me_rp_name, nodename)
me_rp = provider_tree.data(me_rp_name)
@@ -9847,8 +9848,8 @@ class LibvirtDriver(driver.ComputeDriver):
root_node = provider_tree.data(nodename)
return orc.VGPU in root_node.inventory
def _ensure_pgpu_providers(self, inventories_dict, provider_tree,
nodename):
def _ensure_pgpu_providers(
self, inventories_dict, provider_tree, nodename):
"""Ensures GPU inventory providers exist in the tree for $nodename.
GPU providers are named $nodename_$gpu-device-id, e.g.
@@ -10116,8 +10117,8 @@ class LibvirtDriver(driver.ComputeDriver):
rp_uuid, root_node, consumer_uuid, alloc_data,
resources, pgpu_rps)
def _update_provider_tree_for_vgpu(self, provider_tree, nodename,
allocations=None):
def _update_provider_tree_for_vgpu(
self, provider_tree, nodename, allocations=None):
"""Updates the provider tree for VGPU inventory.
Before Stein, VGPU inventory and allocations were on the root compute
@@ -10173,8 +10174,8 @@ class LibvirtDriver(driver.ComputeDriver):
del root_node.inventory[orc.VGPU]
provider_tree.update_inventory(nodename, root_node.inventory)
def _update_provider_tree_for_pcpu(self, provider_tree, nodename,
allocations=None):
def _update_provider_tree_for_pcpu(
self, provider_tree, nodename, allocations=None):
"""Updates the provider tree for PCPU inventory.
Before Train, pinned instances consumed VCPU inventory just like