Merge lp:~blake-rouse/maas-images/fix-centos-efi into lp:maas-images

Proposed by Blake Rouse
Status: Merged
Merged at revision: 361
Proposed branch: lp:~blake-rouse/maas-images/fix-centos-efi
Merge into: lp:maas-images
Diff against target: 68 lines (+43/-3)
1 file modified
curtin/centos7/curtin-hooks.py (+43/-3)
To merge this branch: bzr merge lp:~blake-rouse/maas-images/fix-centos-efi
Reviewer Review Type Date Requested Status
Andres Rodriguez (community) Approve
Review via email: mp+323594@code.launchpad.net

Commit message

Fix boot loader ordering for CentOS 7 UEFI.

Previously when deploying CentOS 7 the 'centos' efi loader would become the first loader in the boot order, which prevents re-deployments of any OS as the machine will no longer boot from the network first. This branch updates the boot order for EFI and places the currently booted entry as the first in the boot order. Since this is run in ephemeral mode this ensures that the NIC that the machine booted from will start first. 'centos' entry will be after the network, so if MAAS is down the machine will still boot from 'centos' if MAAS is down and the machine reboots. Previous \EFI entries are also removed from bios as those no longer exists as curtin creates a new \EFI partition on deployment.

To post a comment you must log in.
Revision history for this message
Andres Rodriguez (andreserl) wrote :

lgtm!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'curtin/centos7/curtin-hooks.py'
2--- curtin/centos7/curtin-hooks.py 2017-04-25 01:26:36 +0000
3+++ curtin/centos7/curtin-hooks.py 2017-05-04 03:03:00 +0000
4@@ -143,13 +143,53 @@
5 in_chroot(['grub2-mkconfig', '-o', '/boot/grub2/grub.cfg'])
6
7
8-def install_uefi(target):
9- """Install the EFI data from /boot into efi partition."""
10+def get_efibootmgr_value(output, key):
11+ """Parses the `output` from 'efibootmgr' to return value for `key`."""
12+ for line in output.splitlines():
13+ split = line.split(':')
14+ if len(split) == 2:
15+ curr_key = split[0].strip()
16+ value = split[1].strip()
17+ if curr_key == key:
18+ return value
19+
20+
21+def get_file_efi_loaders(output):
22+ """Parses the `output` from 'efibootmgr' to return all loaders that exist
23+ in '\EFI' path."""
24+ return re.findall(
25+ r"^Boot(?P<hex>[0-9a-fA-F]{4})\*?\s*\S+\s+.*File\(\\EFI.*$",
26+ output, re.MULTILINE)
27+
28+
29+def grub2_install_efi(target):
30+ """Configure for EFI.
31+
32+ First capture the currently booted loader (normally a network device),
33+ then perform grub installation (adds a new bootloader and adjusts the
34+ boot order), finally re-adjust the boot order so that the currently booted
35+ loader is set to boot first in the new order.
36+ """
37 with util.RunInChroot(target) as in_chroot:
38+ stdout, _ = in_chroot(['efibootmgr', '-v'], capture=True)
39+ currently_booted = get_efibootmgr_value(stdout, 'BootCurrent')
40+ loaders = get_file_efi_loaders(stdout)
41+ if currently_booted in loaders:
42+ loaders.remove(currently_booted)
43+ for loader in loaders:
44+ in_chroot(['efibootmgr', '-B', '-b', loader], capture=True)
45 in_chroot([
46 'grub2-install', '--target=x86_64-efi',
47 '--efi-directory', '/boot/efi',
48 '--recheck'])
49+ stdout, _ = in_chroot(['efibootmgr'], capture=True)
50+ currently_booted = get_efibootmgr_value(stdout, 'BootCurrent')
51+ boot_order = get_efibootmgr_value(stdout, 'BootOrder').split(',')
52+ if currently_booted in boot_order:
53+ boot_order.remove(currently_booted)
54+ boot_order = [currently_booted] + boot_order
55+ new_boot_order = ','.join(boot_order)
56+ in_chroot(['efibootmgr', '-o', new_boot_order])
57
58
59 def set_autorelabel(target):
60@@ -283,7 +323,7 @@
61 target, extra=get_extra_kernel_parameters())
62 grub2_mkconfig(target)
63 if util.is_uefi_bootable():
64- install_uefi(target)
65+ grub2_install_efi(target)
66 else:
67 for dev in devices:
68 grub2_install(target, dev)

Subscribers

People subscribed via source and target branches