Merge "Build ISO out of EFI system partition image"

This commit is contained in:
Zuul 2019-02-15 16:16:42 +00:00 committed by Gerrit Code Review
commit 8978237388
8 changed files with 268 additions and 79 deletions

View File

@ -222,27 +222,33 @@ def create_isolinux_image_for_bios(output_file, kernel, ramdisk,
raise exception.ImageCreationFailed(image_type='iso', error=e)
def create_isolinux_image_for_uefi(output_file, deploy_iso, kernel, ramdisk,
def create_isolinux_image_for_uefi(output_file, kernel, ramdisk,
deploy_iso=None, esp_image=None,
kernel_params=None):
"""Creates an isolinux image on the specified file.
Copies the provided kernel, ramdisk, efiboot.img to a directory, creates
the path for grub config file, generates the isolinux configuration file
using the kernel parameters provided, generates the grub configuration
file using kernel parameters and then generates a bootable ISO image
for uefi.
Copies the provided kernel, ramdisk and EFI system partition image to
a directory, generates the grub configuration file using kernel parameters
and then generates a bootable ISO image for UEFI.
:param output_file: the path to the file where the iso image needs to be
created.
:param deploy_iso: deploy iso used to initiate the deploy.
:param kernel: the kernel to use.
:param ramdisk: the ramdisk to use.
:param deploy_iso: deploy ISO image to extract EFI system partition image
from. If not specified, the `esp_image` option is required.
:param esp_image: FAT12/16/32-formatted EFI system partition image
containing the EFI boot loader (e.g. GRUB2) for each hardware
architecture to boot. This image will be embedded into the ISO image.
If not specified, the `deploy_iso` option is required.
:param kernel_params: a list of strings(each element being a string like
'K=V' or 'K' or combination of them like 'K1=V1,K2,...') to be added
as the kernel cmdline.
:raises: ImageCreationFailed, if image creation failed while copying files
or while running command to generate iso.
"""
EFIBOOT_LOCATION = 'boot/grub/efiboot.img'
grub_options = {'linux': '/vmlinuz', 'initrd': '/initrd'}
with utils.tempdir() as tmpdir:
@ -251,26 +257,48 @@ def create_isolinux_image_for_uefi(output_file, deploy_iso, kernel, ramdisk,
ramdisk: 'initrd',
}
# Open the deploy iso used to initiate deploy and copy the
# efiboot.img i.e. boot loader to the current temporary
# directory.
with utils.tempdir() as mountdir:
uefi_path_info, e_img_rel_path, grub_rel_path = (
_mount_deploy_iso(deploy_iso, mountdir))
# Open the deploy iso used to initiate deploy and copy the
# efiboot.img i.e. boot loader to the current temporary
# directory.
if deploy_iso:
uefi_path_info, e_img_rel_path, grub_rel_path = (
_mount_deploy_iso(deploy_iso, mountdir))
grub_cfg = os.path.join(tmpdir, grub_rel_path)
# Use ELF boot loader provided
elif esp_image:
e_img_rel_path = EFIBOOT_LOCATION
grub_rel_path = CONF.grub_config_path.strip()
while grub_rel_path.startswith(os.sep):
grub_rel_path = grub_rel_path[1:]
grub_cfg = os.path.join(tmpdir, grub_rel_path)
uefi_path_info = {
esp_image: e_img_rel_path,
grub_cfg: grub_rel_path
}
else:
raise exception.ImageCreationFailed(
image_type='iso',
error='Neither `deploy_iso` nor `esp_image` configured')
# if either of these variables are not initialized then the
# uefi efiboot.img cannot be created.
files_info.update(uefi_path_info)
try:
_create_root_fs(tmpdir, files_info)
except (OSError, IOError) as e:
LOG.exception("Creating the filesystem root failed.")
raise exception.ImageCreationFailed(image_type='iso', error=e)
finally:
_umount_without_raise(mountdir)
if deploy_iso:
_umount_without_raise(mountdir)
# Generate and copy grub config file.
grub_cfg = os.path.join(tmpdir, grub_rel_path)
grub_conf = _generate_cfg(kernel_params,
CONF.grub_config_template, grub_options)
utils.write_to_file(grub_cfg, grub_conf)
@ -401,8 +429,8 @@ def get_temp_url_for_glance_image(context, image_uuid):
def create_boot_iso(context, output_filename, kernel_href,
ramdisk_href, deploy_iso_href, root_uuid=None,
kernel_params=None, boot_mode=None):
ramdisk_href, deploy_iso_href=None, esp_image_href=None,
root_uuid=None, kernel_params=None, boot_mode=None):
"""Creates a bootable ISO image for a node.
Given the hrefs for kernel, ramdisk, root partition's UUID and
@ -414,8 +442,15 @@ def create_boot_iso(context, output_filename, kernel_href,
:param output_filename: the absolute path of the output ISO file
:param kernel_href: URL or glance uuid of the kernel to use
:param ramdisk_href: URL or glance uuid of the ramdisk to use
:param deploy_iso_href: URL or glance uuid of the deploy iso used
:param root_uuid: uuid of the root filesystem (optional)
:param deploy_iso_href: URL or glance UUID of the deploy ISO image
to extract EFI system partition image. If not specified,
the `esp_image_href` option must be present if UEFI-bootable
ISO is desired.
:param esp_image_href: URL or glance UUID of FAT12/16/32-formatted EFI
system partition image containing the EFI boot loader (e.g. GRUB2)
for each hardware architecture to boot. This image will be embedded
into the ISO image. If not specified, the `deploy_iso_href` option
is only required for building UEFI-bootable ISO.
:param kernel_params: a string containing whitespace separated values
kernel cmdline arguments of the form K=V or K (optional).
:boot_mode: the boot mode in which the deploy is to happen.
@ -424,6 +459,7 @@ def create_boot_iso(context, output_filename, kernel_href,
with utils.tempdir() as tmpdir:
kernel_path = os.path.join(tmpdir, kernel_href.split('/')[-1])
ramdisk_path = os.path.join(tmpdir, ramdisk_href.split('/')[-1])
fetch(context, kernel_href, kernel_path)
fetch(context, ramdisk_href, ramdisk_path)
@ -434,13 +470,28 @@ def create_boot_iso(context, output_filename, kernel_href,
params.append(kernel_params)
if boot_mode == 'uefi':
deploy_iso = os.path.join(tmpdir, deploy_iso_href.split('/')[-1])
fetch(context, deploy_iso_href, deploy_iso)
deploy_iso_path = esp_image_path = None
if deploy_iso_href:
deploy_iso_path = os.path.join(
tmpdir, deploy_iso_href.split('/')[-1])
fetch(context, deploy_iso_href, deploy_iso_path)
elif esp_image_href:
esp_image_path = os.path.join(
tmpdir, esp_image_href.split('/')[-1])
fetch(context, esp_image_href, esp_image_path)
elif CONF.esp_image:
esp_image_path = CONF.esp_image
create_isolinux_image_for_uefi(output_filename,
deploy_iso,
kernel_path,
ramdisk_path,
params)
deploy_iso=deploy_iso_path,
esp_image=esp_image_path,
kernel_params=params)
else:
create_isolinux_image_for_bios(output_filename,
kernel_path,

View File

@ -210,6 +210,10 @@ image_opts = [
default=os.path.join('$pybasedir',
'common/isolinux_config.template'),
help=_('Template file for isolinux configuration file.')),
cfg.StrOpt('grub_config_path',
default='/boot/grub/grub.cfg',
help=_('GRUB2 configuration file location on the UEFI ISO '
'images produced by ironic.')),
cfg.StrOpt('grub_config_template',
default=os.path.join('$pybasedir',
'common/grub_conf.template'),
@ -220,6 +224,17 @@ image_opts = [
'looked for in '
'"/usr/lib/syslinux/modules/bios/ldlinux.c32" and '
'"/usr/share/syslinux/ldlinux.c32".')),
cfg.StrOpt('esp_image',
help=_('Path to EFI System Partition image file. This file is '
'recommended for creating UEFI bootable ISO images '
'efficiently. ESP image should contain a '
'FAT12/16/32-formatted file system holding EFI boot '
'loaders (e.g. GRUB2) for each hardware architecture '
'ironic needs to boot. If not configured, ironic '
'will attempt to fetch ESP image from some remote '
'store (if configured) or extract ESP image from '
'UEFI-bootable deploy ISO image.')),
]
img_cache_opts = [

View File

@ -198,8 +198,10 @@ def _get_boot_iso(task, root_uuid):
boot_iso_tmp_file = fileobj.name
images.create_boot_iso(task.context, boot_iso_tmp_file,
kernel_href, ramdisk_href,
deploy_iso_uuid, root_uuid,
kernel_params, boot_mode)
deploy_iso_href=deploy_iso_uuid,
root_uuid=root_uuid,
kernel_params=kernel_params,
boot_mode=boot_mode)
if CONF.ilo.use_web_server_for_images:
boot_iso_url = (

View File

@ -314,8 +314,10 @@ def _prepare_boot_iso(task, root_uuid):
images.create_boot_iso(task.context, boot_iso_fullpathname,
kernel_href, ramdisk_href,
deploy_iso_href, root_uuid,
kernel_params, boot_mode)
deploy_iso_href=deploy_iso_href,
root_uuid=root_uuid,
kernel_params=kernel_params,
boot_mode=boot_mode)
driver_internal_info['irmc_boot_iso'] = boot_iso_filename

View File

@ -438,9 +438,9 @@ class FsImageTestCase(base.TestCase):
@mock.patch.object(os.path, 'relpath', autospec=True)
@mock.patch.object(os, 'walk', autospec=True)
@mock.patch.object(utils, 'mount', autospec=True)
def test__mount_deploy_iso_fail_no_efibootimg(self, mount_mock,
walk_mock, relpath_mock,
umount_mock):
def test__mount_deploy_iso_fail_no_esp_imageimg(self, mount_mock,
walk_mock, relpath_mock,
umount_mock):
walk_mock.return_value = [('/tmpdir1/EFI/ubuntu', [], ['grub.cfg']),
('/tmpdir1/isolinux', [],
['isolinux.bin', 'isolinux.cfg'])]
@ -489,16 +489,17 @@ class FsImageTestCase(base.TestCase):
@mock.patch.object(images, '_mount_deploy_iso', autospec=True)
@mock.patch.object(utils, 'tempdir', autospec=True)
@mock.patch.object(images, '_generate_cfg', autospec=True)
def test_create_isolinux_image_for_uefi(
def test_create_isolinux_image_for_uefi_with_deploy_iso(
self, gen_cfg_mock, tempdir_mock, mount_mock, execute_mock,
write_to_file_mock, create_root_fs_mock, umount_mock):
files_info = {
'path/to/kernel': 'vmlinuz',
'path/to/ramdisk': 'initrd',
'path/to/grub': 'relpath/to/grub.cfg',
'sourceabspath/to/efiboot.img': 'path/to/efiboot.img'
'sourceabspath/to/efiboot.img': 'path/to/efiboot.img',
'path/to/grub': 'relpath/to/grub.cfg'
}
grubcfg = "grubcfg"
grub_file = 'tmpdir/relpath/to/grub.cfg'
gen_cfg_mock.side_effect = (grubcfg,)
@ -520,9 +521,10 @@ class FsImageTestCase(base.TestCase):
mount_mock.return_value = (uefi_path_info,
e_img_rel_path, grub_rel_path)
images.create_isolinux_image_for_uefi('tgt_file', 'path/to/deploy_iso',
images.create_isolinux_image_for_uefi('tgt_file',
'path/to/kernel',
'path/to/ramdisk',
deploy_iso='path/to/deploy_iso',
kernel_params=params)
mount_mock.assert_called_once_with('path/to/deploy_iso', 'mountdir')
create_root_fs_mock.assert_called_once_with('tmpdir', files_info)
@ -534,6 +536,49 @@ class FsImageTestCase(base.TestCase):
'path/to/efiboot.img', '-no-emul-boot', '-o', 'tgt_file', 'tmpdir')
umount_mock.assert_called_once_with('mountdir')
@mock.patch.object(images, '_create_root_fs', autospec=True)
@mock.patch.object(utils, 'write_to_file', autospec=True)
@mock.patch.object(utils, 'execute', autospec=True)
@mock.patch.object(utils, 'tempdir', autospec=True)
@mock.patch.object(images, '_generate_cfg', autospec=True)
def test_create_isolinux_image_for_uefi_with_esp_image(
self, gen_cfg_mock, tempdir_mock, execute_mock,
write_to_file_mock, create_root_fs_mock):
files_info = {
'path/to/kernel': 'vmlinuz',
'path/to/ramdisk': 'initrd',
'sourceabspath/to/efiboot.img': 'boot/grub/efiboot.img',
'tmpdir/boot/grub/grub.cfg': 'boot/grub/grub.cfg'
}
grubcfg = "grubcfg"
grub_file = 'tmpdir/boot/grub/grub.cfg'
gen_cfg_mock.side_effect = (grubcfg,)
params = ['a=b', 'c']
grub_options = {'linux': '/vmlinuz',
'initrd': '/initrd'}
mock_file_handle = mock.MagicMock(spec=file)
mock_file_handle.__enter__.return_value = 'tmpdir'
mock_file_handle1 = mock.MagicMock(spec=file)
mock_file_handle1.__enter__.return_value = 'mountdir'
tempdir_mock.side_effect = mock_file_handle, mock_file_handle1
images.create_isolinux_image_for_uefi(
'tgt_file', 'path/to/kernel', 'path/to/ramdisk',
esp_image='sourceabspath/to/efiboot.img',
kernel_params=params)
create_root_fs_mock.assert_called_once_with('tmpdir', files_info)
gen_cfg_mock.assert_any_call(params, CONF.grub_config_template,
grub_options)
write_to_file_mock.assert_any_call(grub_file, grubcfg)
execute_mock.assert_called_once_with(
'mkisofs', '-r', '-V', 'VMEDIA_BOOT_ISO', '-l', '-e',
'boot/grub/efiboot.img', '-no-emul-boot', '-o', 'tgt_file',
'tmpdir')
@mock.patch.object(images, '_create_root_fs', autospec=True)
@mock.patch.object(utils, 'write_to_file', autospec=True)
@mock.patch.object(utils, 'tempdir', autospec=True)
@ -615,9 +660,10 @@ class FsImageTestCase(base.TestCase):
self.assertRaises(exception.ImageCreationFailed,
images.create_isolinux_image_for_uefi,
'tgt_file', 'path/to/deployiso',
'tgt_file',
'path/to/kernel',
'path/to/ramdisk')
'path/to/ramdisk',
deploy_iso='path/to/deployiso')
umount_mock.assert_called_once_with('mountdir')
@mock.patch.object(images, '_create_root_fs', autospec=True)
@ -660,9 +706,10 @@ class FsImageTestCase(base.TestCase):
self.assertRaises(exception.ImageCreationFailed,
images.create_isolinux_image_for_uefi,
'tgt_file', 'path/to/deployiso',
'tgt_file',
'path/to/kernel',
'path/to/ramdisk')
'path/to/ramdisk',
deploy_iso='path/to/deployiso')
umount_mock.assert_called_once_with('mountdir')
@mock.patch.object(images, '_create_root_fs', autospec=True)
@ -689,15 +736,17 @@ class FsImageTestCase(base.TestCase):
@mock.patch.object(images, 'create_isolinux_image_for_uefi', autospec=True)
@mock.patch.object(images, 'fetch', autospec=True)
@mock.patch.object(utils, 'tempdir', autospec=True)
def test_create_boot_iso_for_uefi(
def test_create_boot_iso_for_uefi_deploy_iso(
self, tempdir_mock, fetch_images_mock, create_isolinux_mock):
mock_file_handle = mock.MagicMock(spec=file)
mock_file_handle.__enter__.return_value = 'tmpdir'
tempdir_mock.return_value = mock_file_handle
images.create_boot_iso('ctx', 'output_file', 'kernel-uuid',
'ramdisk-uuid', 'deploy_iso-uuid',
'root-uuid', 'kernel-params', 'uefi')
images.create_boot_iso(
'ctx', 'output_file', 'kernel-uuid',
'ramdisk-uuid', deploy_iso_href='deploy_iso-uuid',
root_uuid='root-uuid', kernel_params='kernel-params',
boot_mode='uefi')
fetch_images_mock.assert_any_call(
'ctx', 'kernel-uuid', 'tmpdir/kernel-uuid')
@ -708,21 +757,53 @@ class FsImageTestCase(base.TestCase):
params = ['root=UUID=root-uuid', 'kernel-params']
create_isolinux_mock.assert_called_once_with(
'output_file', 'tmpdir/deploy_iso-uuid', 'tmpdir/kernel-uuid',
'tmpdir/ramdisk-uuid', params)
'output_file', 'tmpdir/kernel-uuid', 'tmpdir/ramdisk-uuid',
deploy_iso='tmpdir/deploy_iso-uuid', esp_image=None,
kernel_params=params)
@mock.patch.object(images, 'create_isolinux_image_for_uefi', autospec=True)
@mock.patch.object(images, 'fetch', autospec=True)
@mock.patch.object(utils, 'tempdir', autospec=True)
def test_create_boot_iso_for_uefi_for_hrefs(
def test_create_boot_iso_for_uefi_esp_image(
self, tempdir_mock, fetch_images_mock, create_isolinux_mock):
mock_file_handle = mock.MagicMock(spec=file)
mock_file_handle.__enter__.return_value = 'tmpdir'
tempdir_mock.return_value = mock_file_handle
images.create_boot_iso('ctx', 'output_file', 'http://kernel-href',
'http://ramdisk-href', 'http://deploy_iso-href',
'root-uuid', 'kernel-params', 'uefi')
images.create_boot_iso(
'ctx', 'output_file', 'kernel-uuid',
'ramdisk-uuid', esp_image_href='efiboot-uuid',
root_uuid='root-uuid', kernel_params='kernel-params',
boot_mode='uefi')
fetch_images_mock.assert_any_call(
'ctx', 'kernel-uuid', 'tmpdir/kernel-uuid')
fetch_images_mock.assert_any_call(
'ctx', 'ramdisk-uuid', 'tmpdir/ramdisk-uuid')
fetch_images_mock.assert_any_call(
'ctx', 'efiboot-uuid', 'tmpdir/efiboot-uuid')
params = ['root=UUID=root-uuid', 'kernel-params']
create_isolinux_mock.assert_called_once_with(
'output_file', 'tmpdir/kernel-uuid', 'tmpdir/ramdisk-uuid',
deploy_iso=None, esp_image='tmpdir/efiboot-uuid',
kernel_params=params)
@mock.patch.object(images, 'create_isolinux_image_for_uefi', autospec=True)
@mock.patch.object(images, 'fetch', autospec=True)
@mock.patch.object(utils, 'tempdir', autospec=True)
def test_create_boot_iso_for_uefi_deploy_iso_for_hrefs(
self, tempdir_mock, fetch_images_mock, create_isolinux_mock):
mock_file_handle = mock.MagicMock(spec=file)
mock_file_handle.__enter__.return_value = 'tmpdir'
tempdir_mock.return_value = mock_file_handle
images.create_boot_iso(
'ctx', 'output_file', 'http://kernel-href', 'http://ramdisk-href',
deploy_iso_href='http://deploy_iso-href',
root_uuid='root-uuid', kernel_params='kernel-params',
boot_mode='uefi')
expected_calls = [mock.call('ctx', 'http://kernel-href',
'tmpdir/kernel-href'),
mock.call('ctx', 'http://ramdisk-href',
@ -732,8 +813,37 @@ class FsImageTestCase(base.TestCase):
fetch_images_mock.assert_has_calls(expected_calls)
params = ['root=UUID=root-uuid', 'kernel-params']
create_isolinux_mock.assert_called_once_with(
'output_file', 'tmpdir/deploy_iso-href', 'tmpdir/kernel-href',
'tmpdir/ramdisk-href', params)
'output_file', 'tmpdir/kernel-href', 'tmpdir/ramdisk-href',
deploy_iso='tmpdir/deploy_iso-href', esp_image=None,
kernel_params=params)
@mock.patch.object(images, 'create_isolinux_image_for_uefi', autospec=True)
@mock.patch.object(images, 'fetch', autospec=True)
@mock.patch.object(utils, 'tempdir', autospec=True)
def test_create_boot_iso_for_uefi_esp_image_for_hrefs(
self, tempdir_mock, fetch_images_mock, create_isolinux_mock):
mock_file_handle = mock.MagicMock(spec=file)
mock_file_handle.__enter__.return_value = 'tmpdir'
tempdir_mock.return_value = mock_file_handle
images.create_boot_iso(
'ctx', 'output_file', 'http://kernel-href', 'http://ramdisk-href',
esp_image_href='http://efiboot-href',
root_uuid='root-uuid', kernel_params='kernel-params',
boot_mode='uefi')
expected_calls = [mock.call('ctx', 'http://kernel-href',
'tmpdir/kernel-href'),
mock.call('ctx', 'http://ramdisk-href',
'tmpdir/ramdisk-href'),
mock.call('ctx', 'http://efiboot-href',
'tmpdir/efiboot-href')]
fetch_images_mock.assert_has_calls(expected_calls)
params = ['root=UUID=root-uuid', 'kernel-params']
create_isolinux_mock.assert_called_once_with(
'output_file', 'tmpdir/kernel-href', 'tmpdir/ramdisk-href',
deploy_iso=None, esp_image='tmpdir/efiboot-href',
kernel_params=params)
@mock.patch.object(images, 'create_isolinux_image_for_bios', autospec=True)
@mock.patch.object(images, 'fetch', autospec=True)
@ -746,7 +856,8 @@ class FsImageTestCase(base.TestCase):
images.create_boot_iso('ctx', 'output_file', 'kernel-uuid',
'ramdisk-uuid', 'deploy_iso-uuid',
'root-uuid', 'kernel-params', 'bios')
'efiboot-uuid', 'root-uuid', 'kernel-params',
'bios')
fetch_images_mock.assert_any_call(
'ctx', 'kernel-uuid', 'tmpdir/kernel-uuid')
@ -777,7 +888,8 @@ class FsImageTestCase(base.TestCase):
images.create_boot_iso('ctx', 'output_file', 'kernel-uuid',
'ramdisk-uuid', 'deploy_iso-uuid',
'root-uuid', 'kernel-params', None)
'efiboot-uuid', 'root-uuid', 'kernel-params',
None)
fetch_images_mock.assert_any_call(
'ctx', 'kernel-uuid', 'tmpdir/kernel-uuid')

View File

@ -204,14 +204,12 @@ class IloBootPrivateMethodsTestCase(test_common.BaseIloTest):
task.context, 'image-uuid',
['boot_iso', 'kernel_id', 'ramdisk_id'])
boot_object_name_mock.assert_called_once_with(task.node)
create_boot_iso_mock.assert_called_once_with(task.context,
'tmpfile',
'kernel_uuid',
'ramdisk_uuid',
'deploy_iso_uuid',
'root-uuid',
'kernel-params',
'uefi')
create_boot_iso_mock.assert_called_once_with(
task.context, 'tmpfile', 'kernel_uuid', 'ramdisk_uuid',
deploy_iso_href='deploy_iso_uuid',
root_uuid='root-uuid',
kernel_params='kernel-params',
boot_mode='uefi')
swift_obj_mock.create_object.assert_called_once_with('ilo-cont',
'abcdef',
'tmpfile')
@ -273,14 +271,12 @@ class IloBootPrivateMethodsTestCase(test_common.BaseIloTest):
task.context, 'image-uuid',
['boot_iso', 'kernel_id', 'ramdisk_id'])
boot_object_name_mock.assert_called_once_with(task.node)
create_boot_iso_mock.assert_called_once_with(task.context,
'tmpfile',
kernel_href,
ramdisk_href,
'deploy_iso_uuid',
'root-uuid',
'kernel-params',
'uefi')
create_boot_iso_mock.assert_called_once_with(
task.context, 'tmpfile', kernel_href, ramdisk_href,
deploy_iso_href='deploy_iso_uuid',
root_uuid='root-uuid',
kernel_params='kernel-params',
boot_mode='uefi')
boot_iso_expected = 'http://10.10.1.30/httpboot/new_boot_iso'
self.assertEqual(boot_iso_expected, boot_iso_actual)
copy_file_mock.assert_called_once_with(fileobj_mock.name,
@ -336,14 +332,12 @@ class IloBootPrivateMethodsTestCase(test_common.BaseIloTest):
task.context, 'image-uuid',
['boot_iso', 'kernel_id', 'ramdisk_id'])
boot_object_name_mock.assert_called_once_with(task.node)
create_boot_iso_mock.assert_called_once_with(task.context,
'tmpfile',
kernel_href,
ramdisk_href,
'deploy_iso_uuid',
'root-uuid',
'kernel-params',
'uefi')
create_boot_iso_mock.assert_called_once_with(
task.context, 'tmpfile', kernel_href, ramdisk_href,
deploy_iso_href='deploy_iso_uuid',
root_uuid='root-uuid',
kernel_params='kernel-params',
boot_mode='uefi')
boot_iso_expected = 'http://10.10.1.30/httpboot/abcdef'
self.assertEqual(boot_iso_expected, boot_iso_actual)
copy_file_mock.assert_called_once_with(fileobj_mock.name,

View File

@ -498,8 +498,9 @@ class IRMCDeployPrivateMethodsTestCase(test_common.BaseIRMCTest):
'/remote_image_share_root/'
"boot-%s.iso" % self.node.uuid,
'kernel_uuid', 'ramdisk_uuid',
'02f9d414-2ce0-4cf5-b48f-dbc1bf678f55',
'root-uuid', 'kernel-params', 'uefi')
deploy_iso_href='02f9d414-2ce0-4cf5-b48f-dbc1bf678f55',
root_uuid='root-uuid', kernel_params='kernel-params',
boot_mode='uefi')
task.node.refresh()
self.assertEqual("boot-%s.iso" % self.node.uuid,
task.node.driver_internal_info['irmc_boot_iso'])

View File

@ -0,0 +1,12 @@
---
features:
- |
Allows the user to supply EFI system partition image to ironic, for
building UEFI-bootable ISO images, in form of a local file or UUID
or URI reference. The new ``[conductor]esp_image`` option can be used
to configure ironic to use local file.
other:
- |
Makes ironic building UEFI-only bootable ISO image (when being asked to
build a UEFI-bootable image) rather than building a hybrid
BIOS/UEFI-bootable ISO.