Merge "block_device: Add encryption attributes to swap disks"

This commit is contained in:
Zuul 2024-02-28 00:41:44 +00:00 committed by Gerrit Code Review
commit 4c3640599a
5 changed files with 97 additions and 24 deletions

View File

@ -3490,7 +3490,11 @@ class ComputeTestCase(BaseTestCase,
'swap': {
'device_name': '/dev/vdd',
'swap_size': 1,
'disk_bus': 'virtio'
'disk_bus': 'virtio',
'encrypted': False,
'encryption_secret_uuid': None,
'encryption_format': None,
'encryption_options': None,
},
'ephemerals': [
{

View File

@ -62,12 +62,20 @@ class TestDriverBlockDevice(test.NoDBTestCase):
'guest_format': 'swap',
'disk_bus': 'scsi',
'volume_size': 2,
'boot_index': -1})
'boot_index': -1,
'encrypted': False,
'encryption_secret_uuid': None,
'encryption_format': None,
'encryption_options': None})
swap_driver_bdm = {
'device_name': '/dev/sdb1',
'swap_size': 2,
'disk_bus': 'scsi'}
'disk_bus': 'scsi',
'encrypted': False,
'encryption_secret_uuid': None,
'encryption_format': None,
'encryption_options': None}
ephemeral_bdm_dict = block_device.BlockDeviceDict(
{'id': 2, 'instance_uuid': uuids.instance,
@ -366,29 +374,49 @@ class TestDriverBlockDevice(test.NoDBTestCase):
cls,
getattr(self, '%s_bdm' % name))
def assign_fake_changed_value(test_bdm, field, alias=None):
# We can't set fake values on enums, like device_type,
# so skip those.
if not isinstance(test_bdm._bdm_obj.fields[field],
fields.BaseEnumField):
field_or_alias = alias or field
if field_or_alias == 'attachment_id':
# Must set UUID values on UUID fields.
fake_value = ATTACHMENT_ID
elif isinstance(test_bdm._bdm_obj.fields[field],
fields.UUIDField):
# Generically handle other UUID fields.
fake_value = uuids.fake_value
elif isinstance(test_bdm._bdm_obj.fields[field],
fields.BooleanField):
fake_value = not test_bdm[field_or_alias]
else:
fake_value = 'fake_changed_value'
test_bdm[field_or_alias] = fake_value
# Test the save method
with mock.patch.object(test_bdm._bdm_obj, 'save') as save_mock:
# First test saveable fields.
for fld, alias in test_bdm._update_on_save.items():
# We can't set fake values on enums, like device_type,
# so skip those.
if not isinstance(test_bdm._bdm_obj.fields[fld],
fields.BaseEnumField):
field = alias or fld
if field == 'attachment_id':
# Must set UUID values on UUID fields.
fake_value = ATTACHMENT_ID
elif isinstance(test_bdm._bdm_obj.fields[fld],
fields.UUIDField):
# Generically handle other UUID fields.
fake_value = uuids.fake_value
else:
fake_value = 'fake_changed_value'
test_bdm[field] = fake_value
assign_fake_changed_value(test_bdm, fld, alias=alias)
test_bdm.save()
for fld, alias in test_bdm._update_on_save.items():
self.assertEqual(test_bdm[alias or fld],
getattr(test_bdm._bdm_obj, fld))
# Then test read-only fields.
for field in test_bdm._readonly_fields:
value = test_bdm[field]
assign_fake_changed_value(test_bdm, field)
self.assertRaises(AttributeError, test_bdm.save)
# Reset to original value so this already tested field won't
# be considered during the next save().
test_bdm[field] = value
save_mock.assert_called_once_with()
def check_save():

View File

@ -102,6 +102,7 @@ class DriverBlockDevice(dict):
"""
_fields = set()
_readonly_fields = set()
_proxy_as_attr_inherited = set(['uuid', 'is_volume'])
_update_on_save = {'disk_bus': None,
@ -204,6 +205,11 @@ class DriverBlockDevice(dict):
raise NotImplementedError()
def save(self):
for attr_name in self._readonly_fields:
if self[attr_name] != getattr(self._bdm_obj, attr_name):
raise AttributeError(
f"can't set read-only attribute: '{attr_name}'")
for attr_name, key_name in self._update_on_save.items():
lookup_name = key_name or attr_name
if self[lookup_name] != getattr(self._bdm_obj, attr_name):
@ -212,10 +218,26 @@ class DriverBlockDevice(dict):
class DriverSwapBlockDevice(DriverBlockDevice):
_fields = set(['device_name', 'swap_size', 'disk_bus'])
_update_on_save = {'disk_bus': None,
'device_name': None}
_fields = set([
'device_name',
'swap_size',
'disk_bus',
'encrypted',
'encryption_secret_uuid',
'encryption_format',
'encryption_options',
])
_readonly_fields = set(['encrypted'])
_update_on_save = {
'disk_bus': None,
'device_name': None,
# We don't update the 'encrypted' attribute on save because we are not
# going to encrypt or decrypt an existing disk due to a change in the
# 'encrypted' attribute value.
'encryption_secret_uuid': None,
'encryption_format': None,
'encryption_options': None,
}
def _transform(self):
if not block_device.new_format_is_swap(self._bdm_obj):
@ -223,7 +245,11 @@ class DriverSwapBlockDevice(DriverBlockDevice):
self.update({
'device_name': self._bdm_obj.device_name,
'swap_size': self._bdm_obj.volume_size or 0,
'disk_bus': self._bdm_obj.disk_bus
'disk_bus': self._bdm_obj.disk_bus,
'encrypted': self._bdm_obj.encrypted,
'encryption_secret_uuid': self._bdm_obj.encryption_secret_uuid,
'encryption_format': self._bdm_obj.encryption_format,
'encryption_options': self._bdm_obj.encryption_options
})
@ -243,12 +269,16 @@ class DriverImageBlockDevice(DriverBlockDevice):
_fields = set([
'device_name',
'size']) | _new_only_fields
_readonly_fields = set(['encrypted'])
_legacy_fields = (
_fields - _new_only_fields | set(['num', 'virtual_name']))
_update_on_save = {
'disk_bus': None,
'device_name': None,
'device_type': None,
# We don't update the 'encrypted' attribute on save because we are not
# going to encrypt or decrypt an existing disk due to a change in the
# 'encrypted' attribute value.
'encryption_secret_uuid': None,
'encryption_format': None,
'encryption_options': None,
@ -283,10 +313,14 @@ class DriverEphemeralBlockDevice(DriverBlockDevice):
'encryption_format',
'encryption_options'])
_fields = set(['device_name', 'size']) | _new_only_fields
_readonly_fields = set(['encrypted'])
_update_on_save = {
'disk_bus': None,
'device_name': None,
'device_type': None,
# We don't update the 'encrypted' attribute on save because we are not
# going to encrypt or decrypt an existing disk due to a change in the
# 'encrypted' attribute value.
'encryption_secret_uuid': None,
'encryption_format': None,
'encryption_options': None,

View File

@ -109,10 +109,16 @@ def block_device_info_get_encrypted_disks(
block_device_info: ty.Mapping[str, ty.Any],
) -> ty.List['nova.virt.block_device.DriverBlockDevice']:
block_device_info = block_device_info or {}
# swap is a single device, not a list
swap = block_device_info.get('swap')
swap = [swap] if swap else []
return [
driver_bdm for driver_bdm in itertools.chain(
block_device_info.get('image', []),
block_device_info.get('ephemerals', []),
swap,
)
if driver_bdm.get('encrypted')
]

View File

@ -4910,7 +4910,8 @@ class LibvirtDriver(driver.ComputeDriver):
if swap_mb > 0:
size = swap_mb * units.Mi
swap = image('disk.swap')
disk_info_mapping = disk_mapping['disk.swap']
swap = image('disk.swap', disk_info_mapping=disk_info_mapping)
# Short circuit the exists() tests if we already created a disk
created_disks = created_disks or not swap.exists()
swap.cache(fetch_func=self._create_swap, context=context,