Browse Source

Merge "Prevent broken partition image UEFI deploys" into stable/train

changes/49/795349/1
Zuul 2 weeks ago
committed by Gerrit Code Review
parent
commit
5e518c9ff5
3 changed files with 860 additions and 118 deletions
  1. +358
    -95
      ironic_python_agent/extensions/image.py
  2. +495
    -23
      ironic_python_agent/tests/unit/extensions/test_image.py
  3. +7
    -0
      releasenotes/notes/preserve-efi-folder-contents-ea1e278b3093ec55.yaml

+ 358
- 95
ironic_python_agent/extensions/image.py View File

@ -68,8 +68,8 @@ def _get_partition(device, uuid):
# UUID and use the "normal" discovery instead?
if hardware.is_md_device(device):
md_partition = device + 'p1'
if (not os.path.exists(md_partition) or
not stat.S_ISBLK(os.stat(md_partition).st_mode)):
if (not os.path.exists(md_partition)
or not stat.S_ISBLK(os.stat(md_partition).st_mode)):
error_msg = ("Could not find partition %(part)s on md "
"device %(dev)s" % {'part': md_partition,
'dev': device})
@ -330,6 +330,7 @@ def _manage_uefi(device, efi_system_part_uuid=None):
LOG.error(error_msg)
raise errors.CommandExecutionError(error_msg)
finally:
LOG.debug('Executing _manage_uefi clean-up.')
umount_warn_msg = "Unable to umount %(local_path)s. Error: %(error)s"
try:
@ -382,9 +383,11 @@ def _install_grub2(device, root_uuid, efi_system_part_uuid=None,
"""Install GRUB2 bootloader on a given device."""
LOG.debug("Installing GRUB2 bootloader on device %s", device)
efi_partition = None
efi_partitions = None
efi_partition_mount_point = None
efi_mounted = False
efi_preserved = False
path_variable = _get_path_variable()
# NOTE(TheJulia): Seems we need to get this before ever possibly
# restart the device in the case of multi-device RAID as pyudev
@ -408,18 +411,14 @@ def _install_grub2(device, root_uuid, efi_system_part_uuid=None,
"as it is already marked bootable.", device)
return
try:
# Add /bin to PATH variable as grub requires it to find efibootmgr
# when running in uefi boot mode.
# Add /usr/sbin to PATH variable to ensure it is there as we do
# not use full path to grub binary anymore.
path_variable = os.environ.get('PATH', '')
path_variable = '%s:/bin:/usr/sbin:/sbin' % path_variable
# Mount the partition and binds
path = tempfile.mkdtemp()
if efi_system_part_uuid:
efi_partition = _get_partition(device, uuid=efi_system_part_uuid)
efi_part = _get_partition(device, uuid=efi_system_part_uuid)
efi_partitions = [efi_part]
if efi_partitions:
efi_partition_mount_point = os.path.join(path, "boot/efi")
# For power we want to install grub directly onto the PreP partition
@ -434,16 +433,33 @@ def _install_grub2(device, root_uuid, efi_system_part_uuid=None,
disks = [device]
utils.execute('mount', root_partition, path)
for fs in BIND_MOUNTS:
utils.execute('mount', '-o', 'bind', fs, path + fs)
utils.execute('mount', '-t', 'sysfs', 'none', path + '/sys')
if efi_partition:
if not os.path.exists(efi_partition_mount_point):
os.makedirs(efi_partition_mount_point)
utils.execute('mount', efi_partition, efi_partition_mount_point)
efi_mounted = True
_mount_for_chroot(path)
# UEFI asset management for RAID is handled elsewhere
if not hardware.is_md_device(device) and efi_partition_mount_point:
# NOTE(TheJulia): It may make sense to retool all efi
# asset preservation logic at some point since the paths
# can be a little different, but largely this is JUST for
# partition images as there _should not_ be a mount
# point if we have no efi partitions at all.
efi_preserved = _try_preserve_efi_assets(
device, path, efi_system_part_uuid,
efi_partitions, efi_partition_mount_point)
if efi_preserved:
# Success preserving efi assets
return
else:
# Failure, either via exception or not found
# which in this case the partition needs to be
# remounted.
LOG.debug('No EFI assets were preserved for setup or the '
'ramdisk was unable to complete the setup. '
'falling back to bootloader installation from'
'deployed image.')
if not os.path.ismount(root_partition):
LOG.debug('Re-mounting the root partition.')
utils.execute('mount', root_partition, path)
binary_name = "grub"
if os.path.exists(os.path.join(path, 'usr/sbin/grub2-install')):
@ -457,55 +473,81 @@ def _install_grub2(device, root_uuid, efi_system_part_uuid=None,
{'path': path}, shell=True,
env_variables={'PATH': path_variable})
# Install grub. Normally, grub goes to one disk only. In case of
# md devices, grub goes to all underlying holder (RAID-1) disks.
LOG.info("GRUB2 will be installed on disks %s", disks)
for grub_disk in disks:
LOG.debug("Installing GRUB2 on disk %s", grub_disk)
utils.execute('chroot %(path)s /bin/sh -c '
'"%(bin)s-install %(dev)s"' %
{'path': path, 'bin': binary_name,
'dev': grub_disk},
shell=True, env_variables={'PATH': path_variable})
LOG.debug("GRUB2 successfully installed on device %s", grub_disk)
# Also run grub-install with --removable, this installs grub to the
# EFI fallback path. Useful if the NVRAM wasn't written correctly,
# was reset or if testing with virt as libvirt resets the NVRAM
# on instance start.
# This operation is essentially a copy operation. Use of the
# --removable flag, per the grub-install source code changes
# the default file to be copied, destination file name, and
# prevents NVRAM from being updated.
# We only run grub2_install for uefi if we can't verify the uefi bits
if efi_partition:
utils.execute('chroot %(path)s /bin/sh -c '
'"%(bin)s-install %(dev)s --removable"' %
{'path': path, 'bin': binary_name, 'dev': device},
shell=True, env_variables={'PATH': path_variable})
# If the image has dracut installed, set the rd.md.uuid kernel
# parameter for discovered md devices.
if hardware.is_md_device(device) and _has_dracut(path):
rd_md_uuids = ["rd.md.uuid=%s" % x['UUID']
for x in hardware.md_get_raid_devices().values()]
LOG.debug("Setting rd.md.uuid kernel parameters: %s", rd_md_uuids)
with open('%s/etc/default/grub' % path, 'r') as g:
contents = g.read()
with open('%s/etc/default/grub' % path, 'w') as g:
g.write(
re.sub(r'GRUB_CMDLINE_LINUX="(.*)"',
r'GRUB_CMDLINE_LINUX="\1 %s"'
% " ".join(rd_md_uuids),
contents))
# Generate the grub configuration file
utils.execute('chroot %(path)s /bin/sh -c '
'"%(bin)s-mkconfig -o '
'/boot/%(bin)s/grub.cfg"' %
{'path': path, 'bin': binary_name}, shell=True,
env_variables={'PATH': path_variable})
if efi_partitions:
if not os.path.exists(efi_partition_mount_point):
os.makedirs(efi_partition_mount_point)
LOG.warning("GRUB2 will be installed for UEFI on efi partitions "
"%s using the install command which does not place "
"Secure Boot signed binaries.", efi_partitions)
for efi_partition in efi_partitions:
utils.execute(
'mount', efi_partition, efi_partition_mount_point)
efi_mounted = True
# FIXME(rg): does not work in cross boot mode case (target
# boot mode differs from ramdisk one)
# Probe for the correct target (depends on the arch, example
# --target=x86_64-efi)
utils.execute('chroot %(path)s /bin/sh -c '
'"%(bin)s-install"' %
{'path': path, 'bin': binary_name},
shell=True,
env_variables={
'PATH': path_variable
})
# Also run grub-install with --removable, this installs grub to
# the EFI fallback path. Useful if the NVRAM wasn't written
# correctly, was reset or if testing with virt as libvirt
# resets the NVRAM on instance start.
# This operation is essentially a copy operation. Use of the
# --removable flag, per the grub-install source code changes
# the default file to be copied, destination file name, and
# prevents NVRAM from being updated.
# We only run grub2_install for uefi if we can't verify the
# uefi bits
utils.execute('chroot %(path)s /bin/sh -c '
'"%(bin)s-install --removable"' %
{'path': path, 'bin': binary_name},
shell=True,
env_variables={
'PATH': path_variable
})
utils.execute('umount', efi_partition_mount_point, attempts=3,
delay_on_retry=True)
efi_mounted = False
# NOTE: probably never needed for grub-mkconfig, does not hurt in
# case of doubt, cleaned in the finally clause anyway
utils.execute('mount', efi_partitions[0],
efi_partition_mount_point)
efi_mounted = True
else:
# FIXME(rg): does not work if ramdisk boot mode is not the same
# as the target (--target=i386-pc, arch dependent).
# See previous FIXME
# Install grub. Normally, grub goes to one disk only. In case of
# md devices, grub goes to all underlying holder (RAID-1) disks.
LOG.info("GRUB2 will be installed on disks %s", disks)
for grub_disk in disks:
LOG.debug("Installing GRUB2 on disk %s", grub_disk)
utils.execute(
'chroot %(path)s /bin/sh -c "%(bin)s-install %(dev)s"' %
{
'path': path,
'bin': binary_name,
'dev': grub_disk
},
shell=True,
env_variables={
'PATH': path_variable
}
)
LOG.debug("GRUB2 successfully installed on device %s",
grub_disk)
# NOTE(TheJulia): Setup grub configuration again since IF we reach
# this point, then we've manually installed grub which is not the
# recommended path.
_configure_grub(device, path)
LOG.info("GRUB2 successfully installed on %s", device)
@ -516,6 +558,7 @@ def _install_grub2(device, root_uuid, efi_system_part_uuid=None,
raise errors.CommandExecutionError(error_msg)
finally:
LOG.debug('Executing _install_grub2 clean-up.')
# Umount binds and partition
umount_warn_msg = "Unable to umount %(path)s. Error: %(error)s"
@ -532,7 +575,9 @@ def _install_grub2(device, root_uuid, efi_system_part_uuid=None,
raise errors.CommandExecutionError(error_msg)
# If umounting the binds succeed then we can try to delete it
if _umount_all_partitions(path, path_variable, umount_warn_msg):
if _umount_all_partitions(path,
path_variable,
umount_warn_msg):
try:
utils.execute('umount', path, attempts=3, delay_on_retry=True)
except processutils.ProcessExecutionError as e:
@ -543,6 +588,242 @@ def _install_grub2(device, root_uuid, efi_system_part_uuid=None,
shutil.rmtree(path)
def _get_path_variable():
# Add /bin to PATH variable as grub requires it to find efibootmgr
# when running in uefi boot mode.
# Add /usr/sbin to PATH variable to ensure it is there as we do
# not use full path to grub binary anymore.
path_variable = os.environ.get('PATH', '')
return '%s:/bin:/usr/sbin:/sbin' % path_variable
def _configure_grub(device, path):
"""Make consolidated grub configuration as it is device aware.
:param device: The device for the filesystem.
:param path: The path in which the filesystem is mounted.
"""
LOG.debug('Attempting to generate grub Configuration')
path_variable = _get_path_variable()
binary_name = "grub"
if os.path.exists(os.path.join(path, 'usr/sbin/grub2-install')):
binary_name = "grub2"
# If the image has dracut installed, set the rd.md.uuid kernel
# parameter for discovered md devices.
if hardware.is_md_device(device) and _has_dracut(path):
rd_md_uuids = ["rd.md.uuid=%s" % x['UUID']
for x in hardware.md_get_raid_devices().values()]
LOG.debug("Setting rd.md.uuid kernel parameters: %s", rd_md_uuids)
with open('%s/etc/default/grub' % path, 'r') as g:
contents = g.read()
with open('%s/etc/default/grub' % path, 'w') as g:
g.write(
re.sub(r'GRUB_CMDLINE_LINUX="(.*)"',
r'GRUB_CMDLINE_LINUX="\1 %s"'
% " ".join(rd_md_uuids),
contents))
utils.execute('chroot %(path)s /bin/sh -c '
'"%(bin)s-mkconfig -o '
'/boot/%(bin)s/grub.cfg"' %
{'path': path, 'bin': binary_name}, shell=True,
env_variables={'PATH': path_variable,
'GRUB_DISABLE_OS_PROBER': 'true',
'GRUB_SAVEDEFAULT': 'true'},
use_standard_locale=True)
LOG.debug('Completed basic grub configuration.')
def _mount_for_chroot(path):
"""Mount items for grub-mkconfig to succeed."""
LOG.debug('Mounting Linux standard partitions for bootloader '
'configuration generation')
for fs in BIND_MOUNTS:
utils.execute('mount', '-o', 'bind', fs, path + fs)
utils.execute('mount', '-t', 'sysfs', 'none', path + '/sys')
def _try_preserve_efi_assets(device, path,
efi_system_part_uuid,
efi_partitions,
efi_partition_mount_point):
"""Attempt to preserve UEFI boot assets.
:param device: The device upon which wich to try to preserve
assets.
:param path: The path in which the filesystem is already mounted
which we should examine to preserve assets from.
:param efi_system_part_uuid: The partition ID representing the
created EFI system partition.
:param efi_partitions: The list of partitions upon wich to
write the preserved assets to.
:param efi_partition_mount_point: The folder at which to mount
the assets for the process of
preservation.
:returns: True if assets have been preserved, otherwise False.
None is the result of this method if a failure has
occured.
"""
efi_assets_folder = efi_partition_mount_point + '/EFI'
if os.path.exists(efi_assets_folder):
# We appear to have EFI Assets, that need to be preserved
# and as such if we succeed preserving them, we will be returned
# True from _preserve_efi_assets to correspond with success or
# failure in this action.
# NOTE(TheJulia): Still makes sense to invoke grub-install as
# fragmentation of grub has occured.
if (os.path.exists(os.path.join(path, 'usr/sbin/grub2-install'))
or os.path.exists(os.path.join(path, 'usr/sbin/grub-install'))):
_configure_grub(device, path)
# But first, if we have grub, we should try to build a grub config!
LOG.debug('EFI asset folder detected, attempting to preserve assets.')
if _preserve_efi_assets(path, efi_assets_folder,
efi_partitions,
efi_partition_mount_point):
try:
# Since we have preserved the assets, we should be able
# to call the _efi_boot_setup method to scan the device
# and add loader entries
efi_preserved = _efi_boot_setup(device, efi_system_part_uuid)
# Executed before the return so we don't return and then begin
# execution.
return efi_preserved
except Exception as e:
# Remount the partition and proceed as we were.
LOG.debug('Exception encountered while attempting to '
'setup the EFI loader from a root '
'filesystem. Error: %s', e)
def _efi_boot_setup(device, efi_system_part_uuid=None, target_boot_mode=None):
"""Identify and setup an EFI bootloader from supplied partition/disk.
:param device: The device upon which to attempt the EFI bootloader setup.
:param efi_system_part_uuid: The partition UUID to utilize in searching
for an EFI bootloader.
:param target_boot_mode: The requested boot mode target for the
machine. This is optional and is mainly used
for the purposes of identifying a mismatch and
reporting a warning accordingly.
:returns: True if we succeeded in setting up an EFI bootloader in the
EFI nvram table.
False if we were unable to set the machine to EFI boot,
due to inability to locate assets required OR the efibootmgr
tool not being present.
None is returned if the node is NOT in UEFI boot mode or
the system is deploying upon a software RAID device.
"""
boot = hardware.dispatch_to_managers('get_boot_info')
# Explicitly only run if a target_boot_mode is set which prevents
# callers following-up from re-logging the same message
if target_boot_mode and boot.current_boot_mode != target_boot_mode:
LOG.warning('Boot mode mismatch: target boot mode is %(target)s, '
'current boot mode is %(current)s. Installing boot '
'loader may fail or work incorrectly.',
{'target': target_boot_mode,
'current': boot.current_boot_mode})
# FIXME(arne_wiebalck): make software RAID work with efibootmgr
if (boot.current_boot_mode == 'uefi'
and not hardware.is_md_device(device)):
try:
utils.execute('efibootmgr', '--version')
except FileNotFoundError:
LOG.warning("efibootmgr is not available in the ramdisk")
else:
if _manage_uefi(device,
efi_system_part_uuid=efi_system_part_uuid):
return True
return False
def _preserve_efi_assets(path, efi_assets_folder, efi_partitions,
efi_partition_mount_point):
"""Preserve the EFI assets in a partition image.
:param path: The path used for the mounted image filesystem.
:param efi_assets_folder: The folder where we can find the
UEFI assets required for booting.
:param efi_partitions: The list of partitions upon which to
write the perserved assets to.
:param efi_partition_mount_point: The folder at which to mount
the assets for the process of
preservation.
:returns: True if EFI assets were able to be located and preserved
to their appropriate locations based upon the supplied
efi_partitions list.
False if any error is encountered in this process.
"""
try:
save_efi = os.path.join(tempfile.mkdtemp(), 'efi_loader')
LOG.debug('Copying EFI assets to %s.', save_efi)
shutil.copytree(efi_assets_folder, save_efi)
# Identify grub2 config file for EFI booting as grub may require it
# in the folder.
destlist = os.listdir(efi_assets_folder)
grub2_file = os.path.join(path, 'boot/grub2/grub.cfg')
if os.path.isfile(grub2_file):
LOG.debug('Local Grub2 configuration detected.')
# A grub2 config seems to be present, we should preserve it!
for dest in destlist:
grub_dest = os.path.join(save_efi, dest, 'grub.cfg')
if not os.path.isfile(grub_dest):
LOG.debug('A grub.cfg file was not found in %s. %s'
'will be copied to that location.',
grub_dest, grub2_file)
try:
shutil.copy2(grub2_file, grub_dest)
except (IOError, OSError, shutil.SameFileError) as e:
LOG.warning('Failed to copy grub.cfg file for '
'EFI boot operation. Error %s', e)
grub2_env_file = os.path.join(path, 'boot/grub2/grubenv')
# NOTE(TheJulia): By saving the default, this file should be created.
# this appears to what diskimage-builder does.
# if the file is just a file, then we'll need to copy it. If it is
# anything else like a link, we're good. This behaivor is inconsistent
# depending on packager install scripts for grub.
if os.path.isfile(grub2_env_file):
LOG.debug('Detected grub environment file %s, will attempt '
'to copy this file to align with apparent bootloaders',
grub2_env_file)
for dest in destlist:
grub2env_dest = os.path.join(save_efi, dest, 'grubenv')
if not os.path.isfile(grub2env_dest):
LOG.debug('A grubenv file was not found. Copying '
'to %s along with the grub.cfg file as '
'grub generally expects it is present.',
grub2env_dest)
try:
shutil.copy2(grub2_env_file, grub2env_dest)
except (IOError, OSError, shutil.SameFileError) as e:
LOG.warning('Failed to copy grubenv file. '
'Error: %s', e)
# Loop through partitions because software RAID.
for efi_part in efi_partitions:
utils.execute('mount', '-t', 'vfat', efi_part,
efi_partition_mount_point)
shutil.copytree(save_efi, efi_assets_folder)
LOG.debug('Files preserved to %(disk)s for %(part)s. '
'Files: %(filelist)s From: %(from)s',
{'disk': efi_part,
'part': efi_partition_mount_point,
'filelist': os.listdir(efi_assets_folder),
'from': save_efi})
utils.execute('umount', efi_partition_mount_point)
return True
except Exception as e:
LOG.debug('Failed to preserve EFI assets. Error %s', e)
try:
utils.execute('umount', efi_partition_mount_point)
except Exception as e:
LOG.debug('Exception encountered while attempting unmount '
'the EFI partition mount point. Error: %s', e)
return False
class ImageExtension(base.BaseAgentExtension):
@base.sync_command('install_bootloader')
@ -573,31 +854,13 @@ class ImageExtension(base.BaseAgentExtension):
else:
ignore_failure = ignore_bootloader_failure
boot = hardware.dispatch_to_managers('get_boot_info')
if boot.current_boot_mode == 'uefi':
has_efibootmgr = True
# NOTE(iurygregory): adaptation for py27 since we don't have
# FileNotFoundError defined.
try:
FileNotFoundError
except NameError:
FileNotFoundError = OSError
try:
utils.execute('efibootmgr', '--version')
except FileNotFoundError:
LOG.warning("efibootmgr is not available in the ramdisk")
has_efibootmgr = False
if has_efibootmgr:
try:
if _manage_uefi(
device,
efi_system_part_uuid=efi_system_part_uuid):
return
except Exception as e:
LOG.error('Error setting up bootloader. Error %s', e)
if not ignore_failure:
raise
try:
if _efi_boot_setup(device, efi_system_part_uuid):
return
except Exception as e:
LOG.error('Error setting up bootloader. Error %s', e)
if not ignore_failure:
raise
# In case we can't use efibootmgr for uefi we will continue using grub2
LOG.debug('Using grub2-install to set up boot files')


+ 495
- 23
ironic_python_agent/tests/unit/extensions/test_image.py View File

@ -204,6 +204,7 @@ class TestImageExtension(base.IronicAgentTest):
)
mock_iscsi_clean.assert_called_once_with(self.fake_dev)
@mock.patch.object(hardware, 'is_md_device', lambda *_: False)
@mock.patch.object(os.path, 'exists', lambda *_: False)
@mock.patch.object(iscsi, 'clean_up', autospec=True)
@mock.patch.object(image, '_get_efi_bootloaders', autospec=True)
@ -252,6 +253,7 @@ class TestImageExtension(base.IronicAgentTest):
mock_utils_efi_part.assert_called_once_with(self.fake_dev)
self.assertEqual(8, mock_execute.call_count)
@mock.patch.object(hardware, 'is_md_device', lambda *_: False)
@mock.patch.object(os.path, 'exists', lambda *_: False)
@mock.patch.object(iscsi, 'clean_up', autospec=True)
@mock.patch.object(image, '_get_efi_bootloaders', autospec=True)
@ -299,6 +301,7 @@ class TestImageExtension(base.IronicAgentTest):
mock_utils_efi_part.assert_called_once_with(self.fake_dev)
self.assertEqual(8, mock_execute.call_count)
@mock.patch.object(hardware, 'is_md_device', lambda *_: False)
@mock.patch.object(os.path, 'exists', lambda *_: False)
@mock.patch.object(iscsi, 'clean_up', autospec=True)
@mock.patch.object(image, '_get_efi_bootloaders', autospec=True)
@ -353,6 +356,7 @@ efibootmgr: ** Warning ** : Boot0005 has same label ironic1\n
mock_utils_efi_part.assert_called_once_with(self.fake_dev)
self.assertEqual(10, mock_execute.call_count)
@mock.patch.object(hardware, 'is_md_device', lambda *_: False)
@mock.patch.object(os.path, 'exists', lambda *_: False)
@mock.patch.object(iscsi, 'clean_up', autospec=True)
@mock.patch.object(image, '_get_efi_bootloaders', autospec=True)
@ -428,6 +432,7 @@ efibootmgr: ** Warning ** : Boot0005 has same label ironic1\n
prep_boot_part_uuid=self.fake_prep_boot_part_uuid)
mock_iscsi_clean.assert_called_once_with(self.fake_dev)
@mock.patch.object(hardware, 'is_md_device', lambda *_: False)
@mock.patch.object(os.path, 'exists', lambda *_: False)
@mock.patch.object(iscsi, 'clean_up', autospec=True)
def test_install_bootloader_failure(self, mock_iscsi_clean, mock_execute,
@ -486,8 +491,11 @@ efibootmgr: ** Warning ** : Boot0005 has same label ironic1\n
'"grub-mkconfig -o '
'/boot/grub/grub.cfg"' % self.fake_dir),
shell=True,
env_variables={'PATH':
'/sbin:/bin:/usr/sbin:/sbin'}),
env_variables={
'PATH': '/sbin:/bin:/usr/sbin:/sbin',
'GRUB_DISABLE_OS_PROBER': 'true',
'GRUB_SAVEDEFAULT': 'true'},
use_standard_locale=True),
mock.call(('chroot %s /bin/sh -c "umount -a -t vfat"' %
(self.fake_dir)), shell=True,
env_variables={
@ -546,8 +554,11 @@ efibootmgr: ** Warning ** : Boot0005 has same label ironic1\n
'"grub-mkconfig -o '
'/boot/grub/grub.cfg"' % self.fake_dir),
shell=True,
env_variables={'PATH':
'/sbin:/bin:/usr/sbin:/sbin'}),
env_variables={
'PATH': '/sbin:/bin:/usr/sbin:/sbin',
'GRUB_DISABLE_OS_PROBER': 'true',
'GRUB_SAVEDEFAULT': 'true'},
use_standard_locale=True),
mock.call(('chroot %s /bin/sh -c "umount -a -t vfat"' %
(self.fake_dir)), shell=True,
env_variables={
@ -569,6 +580,7 @@ efibootmgr: ** Warning ** : Boot0005 has same label ironic1\n
uuid=self.fake_prep_boot_part_uuid)
self.assertFalse(mock_dispatch.called)
@mock.patch.object(os.path, 'ismount', lambda *_: True)
@mock.patch.object(os.path, 'exists', lambda *_: False)
@mock.patch.object(image, '_is_bootloader_loaded', lambda *_: True)
@mock.patch.object(hardware, 'is_md_device', autospec=True)
@ -599,28 +611,34 @@ efibootmgr: ** Warning ** : Boot0005 has same label ironic1\n
self.fake_dir + '/run'),
mock.call('mount', '-t', 'sysfs', 'none',
self.fake_dir + '/sys'),
mock.call('mount', self.fake_efi_system_part,
self.fake_dir + '/boot/efi'),
mock.call(('chroot %s /bin/sh -c "mount -a -t vfat"' %
(self.fake_dir)), shell=True,
env_variables={
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
mock.call('mount', self.fake_efi_system_part,
self.fake_dir + '/boot/efi'),
mock.call(('chroot %s /bin/sh -c '
'"grub-install %s"' %
(self.fake_dir, self.fake_dev)), shell=True,
'"grub-install"' % self.fake_dir), shell=True,
env_variables={
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
mock.call(('chroot %s /bin/sh -c '
'"grub-install %s --removable"' %
(self.fake_dir, self.fake_dev)), shell=True,
'"grub-install --removable"' % self.fake_dir),
shell=True,
env_variables={
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
mock.call('umount', self.fake_dir + '/boot/efi',
attempts=3, delay_on_retry=True),
mock.call('mount', self.fake_efi_system_part,
self.fake_dir + '/boot/efi'),
mock.call(('chroot %s /bin/sh -c '
'"grub-mkconfig -o '
'/boot/grub/grub.cfg"' % self.fake_dir),
shell=True,
env_variables={
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
'PATH': '/sbin:/bin:/usr/sbin:/sbin',
'GRUB_DISABLE_OS_PROBER': 'true',
'GRUB_SAVEDEFAULT': 'true'},
use_standard_locale=True),
mock.call('umount', self.fake_dir + '/boot/efi',
attempts=3, delay_on_retry=True),
mock.call(('chroot %s /bin/sh -c "umount -a -t vfat"' %
@ -645,6 +663,463 @@ efibootmgr: ** Warning ** : Boot0005 has same label ironic1\n
uuid=self.fake_efi_system_part_uuid)
self.assertFalse(mock_dispatch.called)
@mock.patch.object(os.path, 'ismount', lambda *_: False)
@mock.patch.object(os, 'listdir', lambda *_: ['file1', 'file2'])
@mock.patch.object(image, '_is_bootloader_loaded', lambda *_: False)
@mock.patch.object(image, '_efi_boot_setup', autospec=True)
@mock.patch.object(shutil, 'copytree', autospec=True)
@mock.patch.object(os.path, 'exists', autospec=True)
@mock.patch.object(hardware, 'is_md_device', autospec=True)
@mock.patch.object(hardware, 'md_get_raid_devices', autospec=True)
@mock.patch.object(os, 'environ', autospec=True)
@mock.patch.object(os, 'makedirs', autospec=True)
@mock.patch.object(image, '_get_partition', autospec=True)
def test__install_grub2_uefi_partition_image_with_loader(
self, mock_get_part_uuid, mkdir_mock,
environ_mock, mock_md_get_raid_devices,
mock_is_md_device, mock_exists,
mock_copytree, mock_efi_setup,
mock_execute, mock_dispatch):
mock_exists.return_value = True
mock_efi_setup.return_value = True
mock_get_part_uuid.side_effect = [self.fake_root_part,
self.fake_efi_system_part]
environ_mock.get.return_value = '/sbin'
mock_is_md_device.return_value = False
mock_md_get_raid_devices.return_value = {}
image._install_grub2(
self.fake_dev, root_uuid=self.fake_root_uuid,
efi_system_part_uuid=self.fake_efi_system_part_uuid)
mock_efi_setup.assert_called_once_with(self.fake_dev,
self.fake_efi_system_part_uuid)
mock_copytree.assert_has_calls([
mock.call(self.fake_dir + '/boot/efi/EFI',
self.fake_dir + '/efi_loader'),
mock.call(self.fake_dir + '/efi_loader',
self.fake_dir + '/boot/efi/EFI')])
expected = [mock.call('mount', '/dev/fake2', self.fake_dir),
mock.call('mount', '-o', 'bind', '/dev',
self.fake_dir + '/dev'),
mock.call('mount', '-o', 'bind', '/proc',
self.fake_dir + '/proc'),
mock.call('mount', '-o', 'bind', '/run',
self.fake_dir + '/run'),
mock.call('mount', '-t', 'sysfs', 'none',
self.fake_dir + '/sys'),
mock.call('chroot %s /bin/sh -c "grub2-mkconfig -o '
'/boot/grub2/grub.cfg"' % self.fake_dir,
shell=True,
env_variables={
'PATH': '/sbin:/bin:/usr/sbin:/sbin',
'GRUB_DISABLE_OS_PROBER': 'true',
'GRUB_SAVEDEFAULT': 'true'},
use_standard_locale=True),
mock.call('mount', '-t', 'vfat', '/dev/fake1',
self.fake_dir + '/boot/efi'),
mock.call('umount', self.fake_dir + '/boot/efi'),
mock.call('chroot %s /bin/sh -c "umount -a -t '
'vfat"' % self.fake_dir, shell=True,
env_variables={
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
mock.call('umount', self.fake_dir + '/dev', attempts=3,
delay_on_retry=True),
mock.call('umount', self.fake_dir + '/proc', attempts=3,
delay_on_retry=True),
mock.call('umount', self.fake_dir + '/run', attempts=3,
delay_on_retry=True),
mock.call('umount', self.fake_dir + '/sys', attempts=3,
delay_on_retry=True),
mock.call('umount', self.fake_dir, attempts=3,
delay_on_retry=True)]
mkdir_mock.assert_not_called()
mock_execute.assert_has_calls(expected)
mock_get_part_uuid.assert_any_call(self.fake_dev,
uuid=self.fake_root_uuid)
mock_get_part_uuid.assert_any_call(self.fake_dev,
uuid=self.fake_efi_system_part_uuid)
self.assertFalse(mock_dispatch.called)
@mock.patch.object(os, 'listdir', lambda *_: ['file1', 'file2'])
@mock.patch.object(image, '_is_bootloader_loaded', lambda *_: False)
@mock.patch.object(shutil, 'copy2', autospec=True)
@mock.patch.object(os.path, 'isfile', autospec=True)
@mock.patch.object(image, '_efi_boot_setup', autospec=True)
@mock.patch.object(shutil, 'copytree', autospec=True)
@mock.patch.object(os.path, 'exists', autospec=True)
@mock.patch.object(hardware, 'is_md_device', autospec=True)
@mock.patch.object(hardware, 'md_get_raid_devices', autospec=True)
@mock.patch.object(os, 'environ', autospec=True)
@mock.patch.object(os, 'makedirs', autospec=True)
@mock.patch.object(image, '_get_partition', autospec=True)
def test__install_grub2_uefi_partition_image_with_loader_with_grubcfg(
self, mock_get_part_uuid, mkdir_mock,
environ_mock, mock_md_get_raid_devices,
mock_is_md_device, mock_exists,
mock_copytree, mock_efi_setup,
mock_isfile, mock_copy2,
mock_execute, mock_dispatch):
mock_exists.return_value = True
mock_efi_setup.return_value = True
mock_get_part_uuid.side_effect = [self.fake_root_part,
self.fake_efi_system_part]
environ_mock.get.return_value = '/sbin'
mock_is_md_device.return_value = False
mock_md_get_raid_devices.return_value = {}
mock_isfile.side_effect = [True, False, False, True, True, False]
image._install_grub2(
self.fake_dev, root_uuid=self.fake_root_uuid,
efi_system_part_uuid=self.fake_efi_system_part_uuid)
mock_efi_setup.assert_called_once_with(self.fake_dev,
self.fake_efi_system_part_uuid)
mock_copytree.assert_has_calls([
mock.call(self.fake_dir + '/boot/efi/EFI',
self.fake_dir + '/efi_loader'),
mock.call(self.fake_dir + '/efi_loader',
self.fake_dir + '/boot/efi/EFI')])
expected = [mock.call('mount', '/dev/fake2', self.fake_dir),
mock.call('mount', '-o', 'bind', '/dev',
self.fake_dir + '/dev'),
mock.call('mount', '-o', 'bind', '/proc',
self.fake_dir + '/proc'),
mock.call('mount', '-o', 'bind', '/run',
self.fake_dir + '/run'),
mock.call('mount', '-t', 'sysfs', 'none',
self.fake_dir + '/sys'),
mock.call(('chroot ' + self.fake_dir + ' /bin/sh -c '
'"grub2-mkconfig -o /boot/grub2/grub.cfg"'),
shell=True,
env_variables={
'PATH': '/sbin:/bin:/usr/sbin:/sbin',
'GRUB_DISABLE_OS_PROBER': 'true',
'GRUB_SAVEDEFAULT': 'true'},
use_standard_locale=True),
mock.call('mount', '-t', 'vfat', '/dev/fake1',
self.fake_dir + '/boot/efi'),
mock.call('umount', self.fake_dir + '/boot/efi'),
mock.call(('chroot ' + self.fake_dir
+ ' /bin/sh -c "umount -a -t vfat"'),
shell=True,
env_variables={
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
mock.call('umount', self.fake_dir + '/dev', attempts=3,
delay_on_retry=True),
mock.call('umount', self.fake_dir + '/proc', attempts=3,
delay_on_retry=True),
mock.call('umount', self.fake_dir + '/run', attempts=3,
delay_on_retry=True),
mock.call('umount', self.fake_dir + '/sys', attempts=3,
delay_on_retry=True),
mock.call('umount', self.fake_dir, attempts=3,
delay_on_retry=True)]
mkdir_mock.assert_not_called()
mock_execute.assert_has_calls(expected)
mock_copy2.assert_has_calls([])
mock_get_part_uuid.assert_any_call(self.fake_dev,
uuid=self.fake_root_uuid)
mock_get_part_uuid.assert_any_call(self.fake_dev,
uuid=self.fake_efi_system_part_uuid)
self.assertFalse(mock_dispatch.called)
@mock.patch.object(os.path, 'ismount', lambda *_: True)
@mock.patch.object(image, '_is_bootloader_loaded', lambda *_: False)
@mock.patch.object(image, '_preserve_efi_assets', autospec=True)
@mock.patch.object(image, '_efi_boot_setup', autospec=True)
@mock.patch.object(os.path, 'exists', autospec=True)
@mock.patch.object(hardware, 'is_md_device', autospec=True)
@mock.patch.object(hardware, 'md_get_raid_devices', autospec=True)
@mock.patch.object(os, 'environ', autospec=True)
@mock.patch.object(os, 'makedirs', autospec=True)
@mock.patch.object(image, '_get_partition', autospec=True)
def test__install_grub2_uefi_partition_image_with_preserve_failure(
self, mock_get_part_uuid, mkdir_mock,
environ_mock, mock_md_get_raid_devices,
mock_is_md_device, mock_exists,
mock_efi_setup,
mock_preserve_efi_assets,
mock_execute, mock_dispatch):
mock_exists.return_value = True
mock_efi_setup.side_effect = Exception('meow')
mock_get_part_uuid.side_effect = [self.fake_root_part,
self.fake_efi_system_part]
environ_mock.get.return_value = '/sbin'
mock_is_md_device.return_value = False
mock_md_get_raid_devices.return_value = {}
mock_preserve_efi_assets.return_value = False
image._install_grub2(
self.fake_dev, root_uuid=self.fake_root_uuid,
efi_system_part_uuid=self.fake_efi_system_part_uuid)
self.assertFalse(mock_efi_setup.called)
expected = [mock.call('mount', '/dev/fake2', self.fake_dir),
mock.call('mount', '-o', 'bind', '/dev',
self.fake_dir + '/dev'),
mock.call('mount', '-o', 'bind', '/proc',
self.fake_dir + '/proc'),
mock.call('mount', '-o', 'bind', '/run',
self.fake_dir + '/run'),
mock.call('mount', '-t', 'sysfs', 'none',
self.fake_dir + '/sys'),
mock.call(('chroot %s /bin/sh -c '
'"grub2-mkconfig -o '
'/boot/grub2/grub.cfg"' % self.fake_dir),
shell=True,
env_variables={
'PATH': '/sbin:/bin:/usr/sbin:/sbin',
'GRUB_DISABLE_OS_PROBER': 'true',
'GRUB_SAVEDEFAULT': 'true'},
use_standard_locale=True),
mock.call(('chroot %s /bin/sh -c "mount -a -t vfat"' %
(self.fake_dir)), shell=True,
env_variables={
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
mock.call('mount', self.fake_efi_system_part,
self.fake_dir + '/boot/efi'),
mock.call(('chroot %s /bin/sh -c "grub2-install"' %
self.fake_dir), shell=True,
env_variables={
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
mock.call(('chroot %s /bin/sh -c '
'"grub2-install --removable"' %
self.fake_dir), shell=True,
env_variables={
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
mock.call(
'umount', self.fake_dir + '/boot/efi',
attempts=3, delay_on_retry=True),
mock.call('mount', self.fake_efi_system_part,
'/tmp/fake-dir/boot/efi'),
mock.call(('chroot %s /bin/sh -c '
'"grub2-mkconfig -o '
'/boot/grub2/grub.cfg"' % self.fake_dir),
shell=True,
env_variables={
'PATH': '/sbin:/bin:/usr/sbin:/sbin',
'GRUB_DISABLE_OS_PROBER': 'true',
'GRUB_SAVEDEFAULT': 'true'},
use_standard_locale=True),
mock.call('umount', self.fake_dir + '/boot/efi',
attempts=3, delay_on_retry=True),
mock.call(('chroot %s /bin/sh -c "umount -a -t vfat"' %
(self.fake_dir)), shell=True,
env_variables={
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
mock.call('umount', self.fake_dir + '/dev',
attempts=3, delay_on_retry=True),
mock.call('umount', self.fake_dir + '/proc',
attempts=3, delay_on_retry=True),
mock.call('umount', self.fake_dir + '/run',
attempts=3, delay_on_retry=True),
mock.call('umount', self.fake_dir + '/sys',
attempts=3, delay_on_retry=True),
mock.call('umount', self.fake_dir, attempts=3,
delay_on_retry=True)]
mkdir_mock.assert_not_called()
mock_execute.assert_has_calls(expected)
mock_get_part_uuid.assert_any_call(self.fake_dev,
uuid=self.fake_root_uuid)
mock_get_part_uuid.assert_any_call(self.fake_dev,
uuid=self.fake_efi_system_part_uuid)
self.assertFalse(mock_dispatch.called)
mock_preserve_efi_assets.assert_called_with(
self.fake_dir,
self.fake_dir + '/boot/efi/EFI',
['/dev/fake1'],
self.fake_dir + '/boot/efi')
@mock.patch.object(image, '_is_bootloader_loaded', lambda *_: False)
@mock.patch.object(os, 'listdir', autospec=True)
@mock.patch.object(shutil, 'copy2', autospec=True)
@mock.patch.object(os.path, 'isfile', autospec=True)
@mock.patch.object(image, '_efi_boot_setup', autospec=True)
@mock.patch.object(shutil, 'copytree', autospec=True)
@mock.patch.object(os.path, 'exists', autospec=True)
@mock.patch.object(hardware, 'is_md_device', autospec=True)
@mock.patch.object(hardware, 'md_get_raid_devices', autospec=True)
@mock.patch.object(os, 'environ', autospec=True)
@mock.patch.object(os, 'makedirs', autospec=True)
@mock.patch.object(image, '_get_partition', autospec=True)
def test__install_grub2_uefi_partition_image_with_loader_grubcfg_fails(
self, mock_get_part_uuid, mkdir_mock,
environ_mock, mock_md_get_raid_devices,
mock_is_md_device, mock_exists,
mock_copytree, mock_efi_setup,
mock_isfile, mock_copy2,
mock_oslistdir, mock_execute,
mock_dispatch):
mock_exists.return_value = True
mock_efi_setup.return_value = True
mock_get_part_uuid.side_effect = [self.fake_root_part,
self.fake_efi_system_part]
environ_mock.get.return_value = '/sbin'
mock_is_md_device.return_value = False
mock_md_get_raid_devices.return_value = {}
mock_isfile.side_effect = [True, False, False, True, False,
True, False]
mock_copy2.side_effect = OSError('copy failed')
mock_oslistdir.return_value = ['file1', 'file2']
image._install_grub2(
self.fake_dev, root_uuid=self.fake_root_uuid,
efi_system_part_uuid=self.fake_efi_system_part_uuid)
mock_efi_setup.assert_called_once_with(self.fake_dev,
self.fake_efi_system_part_uuid)
mock_copytree.assert_has_calls([
mock.call(self.fake_dir + '/boot/efi/EFI',
self.fake_dir + '/efi_loader'),
mock.call(self.fake_dir + '/efi_loader',
self.fake_dir + '/boot/efi/EFI')])
expected = [mock.call('mount', '/dev/fake2', self.fake_dir),
mock.call('mount', '-o', 'bind', '/dev',
self.fake_dir + '/dev'),
mock.call('mount', '-o', 'bind', '/proc',
self.fake_dir + '/proc'),
mock.call('mount', '-o', 'bind', '/run',
self.fake_dir + '/run'),
mock.call('mount', '-t', 'sysfs', 'none',
self.fake_dir + '/sys'),
mock.call(('chroot ' + self.fake_dir + ' /bin/sh -c '
'"grub2-mkconfig -o /boot/grub2/grub.cfg"'),
shell=True,
env_variables={
'PATH': '/sbin:/bin:/usr/sbin:/sbin',
'GRUB_DISABLE_OS_PROBER': 'true',
'GRUB_SAVEDEFAULT': 'true'},
use_standard_locale=True),
mock.call('mount', '-t', 'vfat', '/dev/fake1',
self.fake_dir + '/boot/efi'),
mock.call('umount', self.fake_dir + '/boot/efi'),
mock.call(('chroot ' + self.fake_dir
+ ' /bin/sh -c "umount -a -t vfat"'),
shell=True,
env_variables={
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
mock.call('umount', self.fake_dir + '/dev', attempts=3,
delay_on_retry=True),
mock.call('umount', self.fake_dir + '/proc', attempts=3,
delay_on_retry=True),
mock.call('umount', self.fake_dir + '/run', attempts=3,
delay_on_retry=True),
mock.call('umount', self.fake_dir + '/sys', attempts=3,
delay_on_retry=True),
mock.call('umount', self.fake_dir, attempts=3,
delay_on_retry=True)]
mkdir_mock.assert_not_called()
mock_execute.assert_has_calls(expected)
self.assertEqual(3, mock_copy2.call_count)
mock_get_part_uuid.assert_any_call(self.fake_dev,
uuid=self.fake_root_uuid)
mock_get_part_uuid.assert_any_call(self.fake_dev,
uuid=self.fake_efi_system_part_uuid)
self.assertFalse(mock_dispatch.called)
self.assertEqual(2, mock_oslistdir.call_count)
@mock.patch.object(os.path, 'ismount', lambda *_: True)
@mock.patch.object(image, '_is_bootloader_loaded', lambda *_: False)
@mock.patch.object(os, 'listdir', autospec=True)
@mock.patch.object(image, '_efi_boot_setup', autospec=True)
@mock.patch.object(shutil, 'copytree', autospec=True)
@mock.patch.object(os.path, 'exists', autospec=True)
@mock.patch.object(hardware, 'is_md_device', autospec=True)
@mock.patch.object(hardware, 'md_get_raid_devices', autospec=True)
@mock.patch.object(os, 'environ', autospec=True)
@mock.patch.object(os, 'makedirs', autospec=True)
@mock.patch.object(image, '_get_partition', autospec=True)
def test__install_grub2_uefi_partition_image_with_no_loader(
self, mock_get_part_uuid, mkdir_mock,
environ_mock, mock_md_get_raid_devices,
mock_is_md_device, mock_exists,
mock_copytree, mock_efi_setup,
mock_oslistdir, mock_execute,
mock_dispatch):
mock_exists.side_effect = [True, False, False, True, True, True, True]
mock_efi_setup.side_effect = Exception('meow')
mock_oslistdir.return_value = ['file1']
mock_get_part_uuid.side_effect = [self.fake_root_part,
self.fake_efi_system_part]
environ_mock.get.return_value = '/sbin'
mock_is_md_device.return_value = False
mock_md_get_raid_devices.return_value = {}
image._install_grub2(
self.fake_dev, root_uuid=self.fake_root_uuid,
efi_system_part_uuid=self.fake_efi_system_part_uuid)
expected = [mock.call('mount', '/dev/fake2', self.fake_dir),
mock.call('mount', '-o', 'bind', '/dev',
self.fake_dir + '/dev'),
mock.call('mount', '-o', 'bind', '/proc',
self.fake_dir + '/proc'),
mock.call('mount', '-o', 'bind', '/run',
self.fake_dir + '/run'),
mock.call('mount', '-t', 'sysfs', 'none',
self.fake_dir + '/sys'),
mock.call('mount', '-t', 'vfat', '/dev/fake1',
self.fake_dir + '/boot/efi'),
mock.call('umount', self.fake_dir + '/boot/efi'),
mock.call(('chroot %s /bin/sh -c "mount -a -t vfat"' %
(self.fake_dir)), shell=True,
env_variables={
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
mock.call('mount', self.fake_efi_system_part,
self.fake_dir + '/boot/efi'),
mock.call(('chroot %s /bin/sh -c "grub2-install"' %
self.fake_dir), shell=True,
env_variables={
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
mock.call(('chroot %s /bin/sh -c '
'"grub2-install --removable"' %
self.fake_dir), shell=True,
env_variables={
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
mock.call(
'umount', self.fake_dir + '/boot/efi',
attempts=3, delay_on_retry=True),
mock.call('mount', self.fake_efi_system_part,
'/tmp/fake-dir/boot/efi'),
mock.call(('chroot %s /bin/sh -c '
'"grub2-mkconfig -o '
'/boot/grub2/grub.cfg"' % self.fake_dir),
shell=True,
env_variables={
'PATH': '/sbin:/bin:/usr/sbin:/sbin',
'GRUB_DISABLE_OS_PROBER': 'true',
'GRUB_SAVEDEFAULT': 'true'},
use_standard_locale=True),
mock.call('umount', self.fake_dir + '/boot/efi',
attempts=3, delay_on_retry=True),
mock.call(('chroot %s /bin/sh -c "umount -a -t vfat"' %
(self.fake_dir)), shell=True,
env_variables={
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
mock.call('umount', self.fake_dir + '/dev',
attempts=3, delay_on_retry=True),
mock.call('umount', self.fake_dir + '/proc',
attempts=3, delay_on_retry=True),
mock.call('umount', self.fake_dir + '/run',
attempts=3, delay_on_retry=True),
mock.call('umount', self.fake_dir + '/sys',
attempts=3, delay_on_retry=True),
mock.call('umount', self.fake_dir, attempts=3,
delay_on_retry=True)]
mkdir_mock.assert_not_called()
mock_execute.assert_has_calls(expected)
self.assertEqual(2, mock_copytree.call_count)
self.assertTrue(mock_efi_setup.called)
mock_get_part_uuid.assert_any_call(self.fake_dev,
uuid=self.fake_root_uuid)
mock_get_part_uuid.assert_any_call(self.fake_dev,
uuid=self.fake_efi_system_part_uuid)
self.assertFalse(mock_dispatch.called)
@mock.patch.object(image, '_is_bootloader_loaded', lambda *_: False)
@mock.patch.object(hardware, 'is_md_device', autospec=True)
@mock.patch.object(hardware, 'md_get_raid_devices', autospec=True)
@ -680,28 +1155,25 @@ efibootmgr: ** Warning ** : Boot0005 has same label ironic1\n
self.fake_dir + '/run'),
mock.call('mount', '-t', 'sysfs', 'none',
self.fake_dir + '/sys'),
mock.call('mount', self.fake_efi_system_part,
self.fake_dir + '/boot/efi'),
mock.call('mount', '/dev/fake2', self.fake_dir),
mock.call(('chroot %s /bin/sh -c "mount -a -t vfat"' %
(self.fake_dir)), shell=True,
env_variables={
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
mock.call('mount', '/dev/fake1',
self.fake_dir + '/boot/efi'),
mock.call(('chroot %s /bin/sh -c '
'"grub-install %s"' %
(self.fake_dir, self.fake_dev)), shell=True,
env_variables={'PATH':
'/sbin:/bin:/usr/sbin:/sbin'}),
mock.call(('chroot %s /bin/sh -c '
'"grub-install %s --removable"' %
(self.fake_dir, self.fake_dev)), shell=True,
'"grub-install"' % self.fake_dir),
shell=True,
env_variables={'PATH':
'/sbin:/bin:/usr/sbin:/sbin'}),
mock.call(('chroot %s /bin/sh -c '
'"grub-mkconfig -o '
'/boot/grub/grub.cfg"' % self.fake_dir),
shell=True,
'"grub-install --removable"' %
self.fake_dir), shell=True,
env_variables={'PATH':
'/sbin:/bin:/usr/sbin:/sbin'}),
mock.call('umount', self.fake_dir + '/boot/efi',
attempts=3, delay_on_retry=True),
mock.call('umount', self.fake_dir + '/boot/efi',
attempts=3, delay_on_retry=True)]
mock_execute.assert_has_calls(expected)


+ 7
- 0
releasenotes/notes/preserve-efi-folder-contents-ea1e278b3093ec55.yaml View File

@ -0,0 +1,7 @@
---
fixes:
- |
Fixes the agent's EFI boot handling such that EFI assets from a partition
image are preserved and used instead of overridden. This should permit
operators to use Secure Boot with partition images IF the assets are
already present in the partition image.

Loading…
Cancel
Save