Add a new configuration option, `bootloader_by_arch
`
Adds a new configuration option ``bootloader_by_arch`` to support architecture-specific ESP images for virtual media boot, similar to how ``pxe_bootfile_name_by_arch`` works for PXE. Closes-Bug: #2110132 Change-Id: I54fb4b2f379c2d06a7c49402d32403aa2ee67e70 Signed-off-by: Afonne-CID <afonnepaulc@gmail.com>
This commit is contained in:
@@ -279,7 +279,8 @@ opts = [
|
||||
'partition image containing EFI boot loader. This image '
|
||||
'will be used by ironic when building UEFI-bootable ISO '
|
||||
'out of kernel and ramdisk. Required for UEFI boot from '
|
||||
'partition images.')),
|
||||
'partition images. Can be overridden per-architecture '
|
||||
'using the bootloader_by_arch option.')),
|
||||
cfg.MultiOpt('clean_step_priority_override',
|
||||
item_type=types.Dict(),
|
||||
default={},
|
||||
@@ -546,6 +547,16 @@ opts = [
|
||||
'here are validated as absolute paths and will be rejected'
|
||||
'if they contain path traversal mechanisms, such as "..".'
|
||||
)),
|
||||
cfg.DictOpt('bootloader_by_arch',
|
||||
default={},
|
||||
help=_(
|
||||
'Bootloader ESP image parameter per node architecture. '
|
||||
'For example: x86_64:bootx64.efi,aarch64:grubaa64.efi. '
|
||||
'A node\'s cpu_arch property is used as the key to get '
|
||||
'the appropriate bootloader ESP image. If the node\'s '
|
||||
'cpu_arch is not in the dictionary, '
|
||||
'the [conductor]bootloader value will be used instead.'
|
||||
)),
|
||||
]
|
||||
|
||||
|
||||
|
@@ -567,6 +567,11 @@ def prepare_deploy_iso(task, params, mode, d_info):
|
||||
kernel_href = _find_param(kernel_str, d_info)
|
||||
ramdisk_href = _find_param(ramdisk_str, d_info)
|
||||
iso_href = _find_param(iso_str, d_info)
|
||||
|
||||
if not d_info.get('bootloader'):
|
||||
d_info['bootloader'] = driver_utils.get_field(
|
||||
task.node, 'bootloader', use_conf=True)
|
||||
|
||||
bootloader_href = _find_param(bootloader_str, d_info)
|
||||
|
||||
params = override_api_url(params)
|
||||
|
@@ -122,6 +122,9 @@ def _parse_driver_info(node):
|
||||
{option: d_info.get(option, getattr(CONF.conductor, option, None))
|
||||
for option in OPTIONAL_PROPERTIES})
|
||||
|
||||
deploy_info['bootloader'] = driver_utils.get_field(
|
||||
node, 'bootloader', use_conf=True)
|
||||
|
||||
if (d_info.get('config_via_removable') is None
|
||||
and d_info.get('config_via_floppy') is not None):
|
||||
LOG.warning('The config_via_floppy driver_info option is deprecated, '
|
||||
|
@@ -451,18 +451,27 @@ def get_field(node, name, deprecated_prefix=None, use_conf=False,
|
||||
"""Get a driver_info field with deprecated prefix."""
|
||||
node_coll = getattr(node, collection)
|
||||
value = node_coll.get(name)
|
||||
if value or not deprecated_prefix:
|
||||
if value:
|
||||
return value
|
||||
|
||||
deprecated_name = f'{deprecated_prefix}_{name}'
|
||||
value = node_coll.get(deprecated_name)
|
||||
if value:
|
||||
LOG.warning("The %s field %s of node %s is deprecated, "
|
||||
"please use %s instead",
|
||||
collection, deprecated_name, node.uuid, name)
|
||||
return value
|
||||
if deprecated_prefix:
|
||||
deprecated_name = f'{deprecated_prefix}_{name}'
|
||||
value = node_coll.get(deprecated_name)
|
||||
if value:
|
||||
LOG.warning("The %s field %s of node %s is deprecated, "
|
||||
"please use %s instead",
|
||||
collection, deprecated_name, node.uuid, name)
|
||||
return value
|
||||
|
||||
if use_conf:
|
||||
if name == 'bootloader':
|
||||
cpu_arch = node.properties.get('cpu_arch')
|
||||
if cpu_arch:
|
||||
bootloader_by_arch = getattr(
|
||||
CONF.conductor, 'bootloader_by_arch', {})
|
||||
bootloader_href = bootloader_by_arch.get(cpu_arch)
|
||||
if bootloader_href:
|
||||
return bootloader_href
|
||||
return getattr(CONF.conductor, name)
|
||||
|
||||
|
||||
|
@@ -848,6 +848,29 @@ class RedfishImageUtilsTestCase(db_base.DbTestCase):
|
||||
task, 'kernel', 'ramdisk', 'bootloader', params={},
|
||||
inject_files={}, base_iso=None)
|
||||
|
||||
@mock.patch.object(image_utils, '_prepare_iso_image', autospec=True)
|
||||
def test_prepare_deploy_iso_bootloader_by_arch(self,
|
||||
mock__prepare_iso_image):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=True) as task:
|
||||
|
||||
self.config(bootloader_by_arch={'x86_64': 'bootx64.efi'},
|
||||
group='conductor')
|
||||
|
||||
d_info = {
|
||||
'deploy_kernel': 'kernel',
|
||||
'deploy_ramdisk': 'ramdisk',
|
||||
}
|
||||
task.node.driver_info.update(d_info)
|
||||
|
||||
task.node.instance_info.update(deploy_boot_mode='uefi')
|
||||
|
||||
image_utils.prepare_deploy_iso(task, {}, 'deploy', d_info)
|
||||
|
||||
mock__prepare_iso_image.assert_called_once_with(
|
||||
task, 'kernel', 'ramdisk', 'bootx64.efi', params={},
|
||||
inject_files={}, base_iso=None)
|
||||
|
||||
@mock.patch.object(image_utils, '_prepare_iso_image', autospec=True)
|
||||
def test_prepare_deploy_iso_existing_iso(self, mock__prepare_iso_image):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
|
@@ -221,6 +221,28 @@ class UtilsTestCase(db_base.DbTestCase):
|
||||
mac_clean = driver_utils.normalize_mac(mac_raw)
|
||||
self.assertEqual("0a1b2c3d4f", mac_clean)
|
||||
|
||||
def test_get_field_bootloader(self):
|
||||
driver_info = self.node.driver_info
|
||||
driver_info['bootloader'] = 'custom.efi'
|
||||
self.node.driver_info = driver_info
|
||||
result = driver_utils.get_field(self.node, 'bootloader', use_conf=True)
|
||||
self.assertEqual('custom.efi', result)
|
||||
|
||||
self.config(bootloader='global.efi', group='conductor')
|
||||
del self.node.driver_info['bootloader']
|
||||
result = driver_utils.get_field(self.node, 'bootloader', use_conf=True)
|
||||
self.assertEqual('global.efi', result)
|
||||
|
||||
def test_get_field_bootloader_by_arch(self):
|
||||
self.config(bootloader_by_arch={'aarch64': 'grubaa64.efi'},
|
||||
group='conductor')
|
||||
properties = self.node.properties
|
||||
properties['cpu_arch'] = 'aarch64'
|
||||
self.node.properties = properties
|
||||
|
||||
result = driver_utils.get_field(self.node, 'bootloader', use_conf=True)
|
||||
self.assertEqual('grubaa64.efi', result)
|
||||
|
||||
|
||||
class UtilsRamdiskLogsTestCase(tests_base.TestCase):
|
||||
|
||||
|
@@ -0,0 +1,8 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Adds a new configuration option ``bootloader_by_arch``, a dictionary value
|
||||
that maps architecture names to a Glance ID, http:// or file:// URL
|
||||
of an EFI system partition image containing EFI boot loader, to support
|
||||
architecture-specific images for virtual media boot in mixed-architecture
|
||||
clouds.
|
Reference in New Issue
Block a user