diff --git a/repos/system_upgrade/el8toel9/actors/addarmbootloaderworkaround/libraries/addupgradebootloader.py b/repos/system_upgrade/el8toel9/actors/addarmbootloaderworkaround/libraries/addupgradebootloader.py index f287bd3efd..3263f21dc5 100644 --- a/repos/system_upgrade/el8toel9/actors/addarmbootloaderworkaround/libraries/addupgradebootloader.py +++ b/repos/system_upgrade/el8toel9/actors/addarmbootloaderworkaround/libraries/addupgradebootloader.py @@ -66,6 +66,8 @@ 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'] @@ -73,6 +75,7 @@ def process(): 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, ) ) @@ -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 =' + ) + 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 + 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 diff --git a/repos/system_upgrade/el8toel9/models/upgradeefientry.py b/repos/system_upgrade/el8toel9/models/upgradeefientry.py index 877cdc8fc6..1e9da6b32b 100644 --- a/repos/system_upgrade/el8toel9/models/upgradeefientry.py +++ b/repos/system_upgrade/el8toel9/models/upgradeefientry.py @@ -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/'. + """