[pve-devel] [PATCH installer 1/2] handle bootloader installation errors gracefully

Fabian Grünbichler f.gruenbichler at proxmox.com
Tue Jul 23 14:52:46 CEST 2019


by collecting them, but proceeding with the rest of the installation. it
is possible that only either legacy or EFI boot fails, and even if both
do, manually fixing the bootloader setup by booting a live CD is very
often possible.

still display the error screen at the end if bootloader setup was not
successful, so that expectations are not set too high..

Signed-off-by: Fabian Grünbichler <f.gruenbichler at proxmox.com>
---
see https://forum.proxmox.com/threads/unable-to-unmount-zfs-after-installation.56144/#post-258894
for one scenario where this would possibly have been helpful

best viewed with -w, since most of the changes are adding eval around
certain blocks ;)

 proxinstall | 96 +++++++++++++++++++++++++++++++++++------------------
 1 file changed, 63 insertions(+), 33 deletions(-)

diff --git a/proxinstall b/proxinstall
index f7d6e29..fee13b6 100755
--- a/proxinstall
+++ b/proxinstall
@@ -1164,21 +1164,29 @@ sub prepare_grub_efi_boot_esp {
     syscmd("mount -n $espdev -t vfat $targetdir/boot/efi") == 0 ||
 	die "unable to mount $espdev\n";
 
-    my $rc = syscmd("chroot $targetdir /usr/sbin/grub-install --target x86_64-efi --no-floppy --bootloader-id='proxmox' $dev");
-    if ($rc != 0) {
-	if ($boot_type eq 'efi') {
-	    die "unable to install the EFI boot loader on '$dev'\n";
-	} else {
-	    warn "unable to install the EFI boot loader on '$dev', ignoring (not booted using UEFI)\n";
+    eval {
+	my $rc = syscmd("chroot $targetdir /usr/sbin/grub-install --target x86_64-efi --no-floppy --bootloader-id='proxmox' $dev");
+	if ($rc != 0) {
+	    if ($boot_type eq 'efi') {
+		die "unable to install the EFI boot loader on '$dev'\n";
+	    } else {
+		warn "unable to install the EFI boot loader on '$dev', ignoring (not booted using UEFI)\n";
+	    }
 	}
-    }
-    # also install fallback boot file (OVMF does not boot without)
-    mkdir("$targetdir/boot/efi/EFI/BOOT");
-    syscmd("cp $targetdir/boot/efi/EFI/proxmox/grubx64.efi $targetdir/boot/efi/EFI/BOOT/BOOTx64.EFI") == 0 ||
-	die "unable to copy efi boot loader\n";
+	# also install fallback boot file (OVMF does not boot without)
+	mkdir("$targetdir/boot/efi/EFI/BOOT");
+	syscmd("cp $targetdir/boot/efi/EFI/proxmox/grubx64.efi $targetdir/boot/efi/EFI/BOOT/BOOTx64.EFI") == 0 ||
+	    die "unable to copy efi boot loader\n";
+    };
+    my $err = $@;
+
+    eval {
+	syscmd("umount $targetdir/boot/efi") == 0 ||
+	    die "unable to umount $targetdir/boot/efi\n";
+    };
+    warn $@ if $@;
 
-    syscmd("umount $targetdir/boot/efi") == 0 ||
-	die "unable to umount $targetdir/boot/efi\n";
+    die "failed to prepare EFI boot using Grub on '$espdev': $err" if $err;
 }
 
 sub extract_data {
@@ -1219,6 +1227,8 @@ sub extract_data {
 	die "unable to load zfs kernel module\n" if !$i;
     }
 
+    my $bootloader_err;
+
     eval {
 
 
@@ -1702,29 +1712,45 @@ _EOD
 	    symlink ("/proc/mounts", "$targetdir/etc/mtab");
 	    syscmd("mount -n --bind /dev $targetdir/dev");
 
-	    syscmd("chroot $targetdir /usr/sbin/update-initramfs -c -k $kapi") == 0 ||
-		die "unable to install initramfs\n";
-
-	    foreach my $di (@$bootdevinfo) {
-		my $dev = $di->{devname};
-		syscmd("chroot $targetdir /usr/sbin/grub-install --target i386-pc --no-floppy --bootloader-id='proxmox' $dev") == 0 ||
-			die "unable to install the i386-pc boot loader on '$dev'\n";
-
-		if (my $esp = $di->{esp}) {
-		    if ($use_zfs) {
-			prepare_systemd_boot_esp($esp, $targetdir);
-		    } else {
-			prepare_grub_efi_boot_esp($dev, $esp, $targetdir);
-		    }
+	    my $bootloader_err_list = [];
+	    eval {
+		syscmd("chroot $targetdir /usr/sbin/update-initramfs -c -k $kapi") == 0 ||
+		    die "unable to install initramfs\n";
+
+		foreach my $di (@$bootdevinfo) {
+		    my $dev = $di->{devname};
+		    eval {
+			syscmd("chroot $targetdir /usr/sbin/grub-install --target i386-pc --no-floppy --bootloader-id='proxmox' $dev") == 0 ||
+				die "unable to install the i386-pc boot loader on '$dev'\n";
+		    };
+		    push @$bootloader_err_list, $@ if $@;
+
+		    eval {
+			if (my $esp = $di->{esp}) {
+			    if ($use_zfs) {
+				prepare_systemd_boot_esp($esp, $targetdir);
+			    } else {
+				prepare_grub_efi_boot_esp($dev, $esp, $targetdir);
+			    }
+			}
+		    };
+		    push @$bootloader_err_list, $@ if $@;
 		}
-	    }
 
-	    syscmd("chroot $targetdir /usr/sbin/update-grub") == 0 ||
-		die "unable to update boot loader config\n";
+		syscmd("chroot $targetdir /usr/sbin/update-grub") == 0 ||
+		    die "unable to update boot loader config\n";
 
-	    if ($use_zfs && $boot_type eq 'efi') {
-		syscmd("chroot $targetdir /etc/kernel/postinst.d/zz-pve-efiboot") == 0 ||
-		    die "unable to generate systemd-boot config\n";
+		if ($use_zfs && $boot_type eq 'efi') {
+		    syscmd("chroot $targetdir /etc/kernel/postinst.d/zz-pve-efiboot") == 0 ||
+			die "unable to generate systemd-boot config\n";
+		}
+	    };
+	    push @$bootloader_err_list, $@ if $@;
+
+	    if (scalar(@$bootloader_err_list) > 0) {
+		$bootloader_err = "bootloader setup errors:\n";
+		map { $bootloader_err .= "- $_" } @$bootloader_err_list;
+		warn $bootloader_err;
 	    }
 
 	    syscmd("umount $targetdir/dev");
@@ -1819,6 +1845,10 @@ _EOD
 	syscmd("zpool export $zfspoolname");
     }
 
+    if ($bootloader_err) {
+	$err = $err ? "$err\n$bootloader_err" : $bootloader_err;
+    }
+
     die $err if $err;
 }
 
-- 
2.20.1





More information about the pve-devel mailing list