Skip to content

Commit 1f2aad3

Browse files
author
Michal Hecko
committed
feat(arm,bootloader,efi): use separate BLS directory for upgrades
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.
1 parent 5d56393 commit 1f2aad3

File tree

2 files changed

+83
-0
lines changed

2 files changed

+83
-0
lines changed

Diff for: repos/system_upgrade/el8toel9/actors/addarmbootloaderworkaround/libraries/addupgradebootloader.py

+75
Original file line numberDiff line numberDiff line change
@@ -66,13 +66,16 @@ def process():
6666
leapp_efi_grubenv = os.path.join(EFI_MOUNTPOINT, LEAPP_EFIDIR_CANONICAL_PATH, 'grubenv')
6767
patch_efi_redhat_grubcfg_to_load_correct_grubenv()
6868

69+
upgrade_bls_dir = modify_our_grubenv_to_have_separate_blsdir(leapp_efi_grubenv)
70+
6971
_set_bootnext(upgrade_boot_entry.boot_number)
7072

7173
efibootentry_fields = ['boot_number', 'label', 'active', 'efi_bin_source']
7274
api.produce(
7375
ArmWorkaroundEFIBootloaderInfo(
7476
original_entry=EFIBootEntry(**{f: getattr(current_boot_entry, f) for f in efibootentry_fields}),
7577
upgrade_entry=EFIBootEntry(**{f: getattr(upgrade_boot_entry, f) for f in efibootentry_fields}),
78+
upgrade_bls_dir=upgrade_bls_dir,
7679
)
7780
)
7881

@@ -231,3 +234,75 @@ def patch_efi_redhat_grubcfg_to_load_correct_grubenv():
231234
shutil.copy(patched_grub2_cfg_path, leapp_grub_cfg_path)
232235

233236

237+
def _list_grubenv_variables():
238+
try:
239+
output_lines = run(['grub2-editenv', 'list'], split=True)['stdout']
240+
except CalledProcessError:
241+
raise StopActorExecutionError('Failed to list grubenv variables used by the system')
242+
243+
vars_with_values = {}
244+
for line in output_lines:
245+
var_with_value = line.lsplit('=')
246+
if len(var_with_value) <= 1:
247+
api.current_logger().warning(
248+
'Skipping \'{}\' in grub2-editenv output, the line does not have the form <var>=<value>'
249+
)
250+
continue
251+
vars_with_values[var_with_value[0]] = var_with_value[1]
252+
253+
return vars_with_values
254+
255+
256+
def modify_our_grubenv_to_have_separate_blsdir(leapp_efi_grubenv_path):
257+
api.current_logger().debug(
258+
'Setting up separate blsdir for the upgrade using grubenv: {}'.format(leapp_efi_grubenv_path)
259+
)
260+
261+
grubenv_vars = _list_grubenv_variables()
262+
system_bls_dir = grubenv_vars.get('blsdir', '/boot/loader/entries')
263+
264+
# Find our loader enty
265+
try:
266+
bls_entries = os.listdir(system_bls_dir)
267+
except FileNotFoundError:
268+
details = {
269+
'details': 'Failed to list {}.'.format(system_bls_dir)
270+
}
271+
raise StopActorExecutionError('Failed to set up bootloader for the upgrade.', details=details)
272+
273+
leapp_bls_entry = None
274+
for bls_entry in bls_entries:
275+
if bls_entry.endswith('upgrade.aarch64.conf'):
276+
leapp_bls_entry = bls_entry
277+
break
278+
279+
if not leapp_bls_entry:
280+
details = {
281+
'details': 'Failed to identify BLS entry that belongs to leapp in {}'.format(system_bls_dir)
282+
}
283+
raise StopActorExecutionError('Failed to set up bootloader for the upgrade.')
284+
285+
# The 'blsdir' grubenv variable specifies location of bls directory relative to /boot
286+
leapp_bls_dir_rel_to_boot = '/upgrade-loader/entries'
287+
leapp_bls_dir = os.path.join('/boot/', leapp_bls_dir_rel_to_boot.lstrip('/'))
288+
os.makedirs(leapp_bls_dir)
289+
api.current_logger().debug('Successfully created upgrade BLS directory: {}'.format(leapp_bls_dir))
290+
291+
leapp_bls_entry_fullpath = os.path.join(system_bls_dir, leapp_bls_entry)
292+
bls_entry_dst = os.path.join(leapp_bls_dir, leapp_bls_entry)
293+
api.current_logger().debug(
294+
'Moving leapp\'s BLS entry ({}) into a separate BLS dir located at {}'.format(leapp_bls_entry, leapp_bls_dir)
295+
)
296+
297+
shutil.move(leapp_bls_entry_fullpath, bls_entry_dst)
298+
299+
# Modify leapp's grubenv to define our own BLSDIR
300+
try:
301+
run(['grub2-editenv', leapp_efi_grubenv_path, 'set', 'blsdir="{}"'.format(leapp_bls_dir_rel_to_boot)])
302+
except CalledProcessError as error:
303+
details = {
304+
'details': 'Failed to modify upgrade grubenv to contain a custom blsdir definition. Error {}'.format(error)
305+
}
306+
raise StopActorExecutionError('Failed to set up bootloader for the upgrade.', details=details)
307+
308+
return leapp_bls_dir

Diff for: repos/system_upgrade/el8toel9/models/upgradeefientry.py

+8
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,11 @@ class ArmWorkaroundEFIBootloaderInfo(Model):
1212
original_entry = fields.Model(EFIBootEntry)
1313

1414
upgrade_entry = fields.Model(EFIBootEntry)
15+
16+
upgrade_bls_dir = fields.Nullable(fields.String())
17+
"""
18+
Path to custom BLS dir used by the upgrade EFI bootloader
19+
20+
The path is absolute w.r.t. '/'. The actual value of the 'blsdir' variable
21+
that is set in the upgrade grubenv will be relative to '/boot/'.
22+
"""

0 commit comments

Comments
 (0)