From 06d5273f71e16ea0033ddb796198d93b80bd20f0 Mon Sep 17 00:00:00 2001 From: Thierry Escande Date: Mon, 5 Aug 2024 17:41:05 +0200 Subject: [PATCH 1/3] Add helper function is_rootfs_uefi() This function searches for the /boot/efi mount point in the /etc/fstab file of the mount point directory passed as parameter and returns True if present, False otherwise. This will allow to check that an existing installation or backup boot mode matches with the installer boot mode. Signed-off-by: Thierry Escande --- product.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/product.py b/product.py index e9e2c0bc..f778f980 100644 --- a/product.py +++ b/product.py @@ -28,6 +28,18 @@ class SettingsNotAvailable(Exception): XENSERVER_7_0_0 = Version([2, 1, 0]) # Platform version XENSERVER_MIN_VERSION = XENSERVER_7_0_0 +def is_rootfs_uefi(mount_point): + try: + with open(os.path.join(mount_point, 'etc', 'fstab'), 'r') as fstab: + for line in fstab: + m = re.search(r'^\s*[^#]+\s/boot/efi\s', line) + if m: + return True + except FileNotFoundError: + pass + + return False + class ExistingInstallation: def __init__(self, primary_disk, boot_device, state_device): self.primary_disk = primary_disk From cd2aac82241946b080103402fb987e111714432f Mon Sep 17 00:00:00 2001 From: Thierry Escande Date: Fri, 2 Aug 2024 16:54:02 +0200 Subject: [PATCH 2/3] Ignore backup if boot modes don't match This patch checks the boot mode of an existing backups and disallows its restoration if it differs from the installer one. This uses the new helper function is_rootf_uefi(). Signed-off-by: Thierry Escande --- product.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/product.py b/product.py index f778f980..a81a75b4 100644 --- a/product.py +++ b/product.py @@ -576,7 +576,12 @@ def findXenSourceBackups(): if os.path.exists(os.path.join(b.mount_point, '.xen-backup-partition')): backup = XenServerBackup(p, b.mount_point) logger.log("Found a backup: %s" % (repr(backup),)) - if backup.version >= XENSERVER_MIN_VERSION and \ + # Don't restore a BIOS backup with a UEFI installer and conversely + backup_is_uefi = is_rootfs_uefi(b.mount_point) + if backup_is_uefi != constants.UEFI_INSTALLER: + logger.log("Ignoring backup, installer mode (%s) does not match backup boot mode (%s)" % + ("uefi" if constants.UEFI_INSTALLER else "legacy", "uefi" if backup_is_uefi else "legacy" )) + elif backup.version >= XENSERVER_MIN_VERSION and \ backup.version <= THIS_PLATFORM_VERSION: backups.append(backup) except: From a07cc29ba5c5fd4dfe23abfae08866e2acf205d0 Mon Sep 17 00:00:00 2001 From: Thierry Escande Date: Fri, 2 Aug 2024 18:07:46 +0200 Subject: [PATCH 3/3] Ignore existing installation for upgrade if boot modes don't match This patch checks that the current installation is not proposed as upgradeable if its boot mode differs from the installer one. This uses the helper function is_rootfs_uefi(). Signed-off-by: Thierry Escande --- product.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/product.py b/product.py index a81a75b4..aa2e40a8 100644 --- a/product.py +++ b/product.py @@ -75,6 +75,15 @@ def isUpgradeable(self): self.mount_state() result = True try: + # Don't propose to upgrade a BIOS installation with a UEFI installer and conversely + existing_is_uefi = is_rootfs_uefi(self.join_state_path()) + if existing_is_uefi != constants.UEFI_INSTALLER: + logger.log("Cannot upgrade %s, installer mode (%s) does not match existing boot mode (%s)" % + (self.primary_disk, + "uefi" if constants.UEFI_INSTALLER else "legacy", + "uefi" if existing_is_uefi else "legacy")) + return False + # CA-38459: handle missing firstboot directory e.g. Rio if os.path.exists(self.join_state_path('etc/firstboot.d/state')): firstboot_files = [ f for f in os.listdir(self.join_state_path('etc/firstboot.d')) \