Skip to content

Commit

Permalink
feat(arm,bootloader,efi): use separate BLS directory for upgrades
Browse files Browse the repository at this point in the history
Use a separate BLS directory '/boot/upgrade-loader/entries'
that mimics '/boot/loader/entries'. This allows very fine
control of what boot entries are available when booting
into upgrade environment via a separate EFI entry.
  • Loading branch information
Michal Hecko committed Jan 20, 2025
1 parent 5d56393 commit 1f2aad3
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,16 @@ def process():
leapp_efi_grubenv = os.path.join(EFI_MOUNTPOINT, LEAPP_EFIDIR_CANONICAL_PATH, 'grubenv')
patch_efi_redhat_grubcfg_to_load_correct_grubenv()

upgrade_bls_dir = modify_our_grubenv_to_have_separate_blsdir(leapp_efi_grubenv)

_set_bootnext(upgrade_boot_entry.boot_number)

efibootentry_fields = ['boot_number', 'label', 'active', 'efi_bin_source']
api.produce(
ArmWorkaroundEFIBootloaderInfo(
original_entry=EFIBootEntry(**{f: getattr(current_boot_entry, f) for f in efibootentry_fields}),
upgrade_entry=EFIBootEntry(**{f: getattr(upgrade_boot_entry, f) for f in efibootentry_fields}),
upgrade_bls_dir=upgrade_bls_dir,
)
)

Expand Down Expand Up @@ -231,3 +234,75 @@ def patch_efi_redhat_grubcfg_to_load_correct_grubenv():
shutil.copy(patched_grub2_cfg_path, leapp_grub_cfg_path)


def _list_grubenv_variables():
try:
output_lines = run(['grub2-editenv', 'list'], split=True)['stdout']
except CalledProcessError:
raise StopActorExecutionError('Failed to list grubenv variables used by the system')

vars_with_values = {}
for line in output_lines:
var_with_value = line.lsplit('=')
if len(var_with_value) <= 1:
api.current_logger().warning(
'Skipping \'{}\' in grub2-editenv output, the line does not have the form <var>=<value>'
)
continue
vars_with_values[var_with_value[0]] = var_with_value[1]

return vars_with_values


def modify_our_grubenv_to_have_separate_blsdir(leapp_efi_grubenv_path):
api.current_logger().debug(
'Setting up separate blsdir for the upgrade using grubenv: {}'.format(leapp_efi_grubenv_path)
)

grubenv_vars = _list_grubenv_variables()
system_bls_dir = grubenv_vars.get('blsdir', '/boot/loader/entries')

# Find our loader enty

Check failure on line 264 in repos/system_upgrade/el8toel9/actors/addarmbootloaderworkaround/libraries/addupgradebootloader.py

View workflow job for this annotation

GitHub Actions / Check for spelling errors

enty ==> entry, entity
try:
bls_entries = os.listdir(system_bls_dir)
except FileNotFoundError:
details = {
'details': 'Failed to list {}.'.format(system_bls_dir)
}
raise StopActorExecutionError('Failed to set up bootloader for the upgrade.', details=details)

leapp_bls_entry = None
for bls_entry in bls_entries:
if bls_entry.endswith('upgrade.aarch64.conf'):
leapp_bls_entry = bls_entry
break

if not leapp_bls_entry:
details = {
'details': 'Failed to identify BLS entry that belongs to leapp in {}'.format(system_bls_dir)
}
raise StopActorExecutionError('Failed to set up bootloader for the upgrade.')

# The 'blsdir' grubenv variable specifies location of bls directory relative to /boot
leapp_bls_dir_rel_to_boot = '/upgrade-loader/entries'
leapp_bls_dir = os.path.join('/boot/', leapp_bls_dir_rel_to_boot.lstrip('/'))
os.makedirs(leapp_bls_dir)
api.current_logger().debug('Successfully created upgrade BLS directory: {}'.format(leapp_bls_dir))

leapp_bls_entry_fullpath = os.path.join(system_bls_dir, leapp_bls_entry)
bls_entry_dst = os.path.join(leapp_bls_dir, leapp_bls_entry)
api.current_logger().debug(
'Moving leapp\'s BLS entry ({}) into a separate BLS dir located at {}'.format(leapp_bls_entry, leapp_bls_dir)
)

shutil.move(leapp_bls_entry_fullpath, bls_entry_dst)

# Modify leapp's grubenv to define our own BLSDIR
try:
run(['grub2-editenv', leapp_efi_grubenv_path, 'set', 'blsdir="{}"'.format(leapp_bls_dir_rel_to_boot)])
except CalledProcessError as error:
details = {
'details': 'Failed to modify upgrade grubenv to contain a custom blsdir definition. Error {}'.format(error)
}
raise StopActorExecutionError('Failed to set up bootloader for the upgrade.', details=details)

return leapp_bls_dir
8 changes: 8 additions & 0 deletions repos/system_upgrade/el8toel9/models/upgradeefientry.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,11 @@ class ArmWorkaroundEFIBootloaderInfo(Model):
original_entry = fields.Model(EFIBootEntry)

upgrade_entry = fields.Model(EFIBootEntry)

upgrade_bls_dir = fields.Nullable(fields.String())
"""
Path to custom BLS dir used by the upgrade EFI bootloader
The path is absolute w.r.t. '/'. The actual value of the 'blsdir' variable
that is set in the upgrade grubenv will be relative to '/boot/'.
"""

0 comments on commit 1f2aad3

Please sign in to comment.