Пример #1
0
def final_check():
    """
    Check for any conflicting options, and warn the user of any potential pitfalls.
    """

    #Check and warn about conflicting settings.
    #Warn if any OSs aren't modifyable.
    unmodifyable_oss = []

    keys = list(BOOTLOADER_INFO.keys())
    keys.sort()

    for _os in keys:
        if BOOTLOADER_INFO[_os]["IsModifyable"] is False:
            unmodifyable_oss.append(_os+", because "+BOOTLOADER_INFO[_os]["Comments"])

    if unmodifyable_oss != []:
        DialogTools.show_msg_dlg(message="Some of the OSs found on your system cannot be "
                                 + "modified! These are:\n\n"+'\n'.join(unmodifyable_oss)
                                 + "\n\nClick okay to continue.")

    #Warn if any bootloaders need reinstalling.
    need_reinstalling = []

    for _os in keys:
        if "MenuEntries" not in BOOTLOADER_INFO[_os].keys():
            need_reinstalling.append(_os)

    if need_reinstalling != []:
        DialogTools.show_msg_dlg(message="Some of the OSs found on your system have damaged "
                                 + "bootloaders! These are:\n\n"+'\n'.join(need_reinstalling)
                                 + "\n\nPlease reinstall the bootloaders for these operating "
                                 + "systems using \"Bootloader Options\".\n\nClick okay to "
                                 + "continue.")
Пример #2
0
def get_firmware_type():
    """Get the firmware type"""
    #Check if the firmware type is UEFI.
    #Also, look for UEFI variables.
    #Make sure efivars module is loaded. If it doesn't exist, continue anyway.
    CoreTools.start_process("modprobe efivars", privileged=True)

    #Look for the UEFI vars in some common directories.
    if os.path.isdir("/sys/firmware/efi/vars") \
        and CoreTools.start_process("ls /sys/firmware/efi/vars", return_output=True)[1] != "":

        uefi_variables = True
        logger.info("get_firmware_type(): Found UEFI Variables at /sys/firmware/efi/vars...")

    elif os.path.isdir("/proc/efi/vars") \
        and CoreTools.start_process("ls /proc/efi/vars", return_output=True)[1] != "":

        uefi_variables = True
        logger.info("get_firmware_type(): Found UEFI Variables at /proc/efi/vars...")

    elif os.path.isdir("/sys/firmware/efi/efivars") \
        and CoreTools.start_process("ls /sys/firmware/efi/efivars", return_output=True)[1] != "":

        uefi_variables = True
        logger.info("get_firmware_type(): Found UEFI Variables at /sys/firmware/efi/efivars...")

    else:
        logger.info("get_firmware_type(): UEFI vars not found in /sys/firmware/efi/vars, "
                    + "/sys/firmware/efi/efivars, or /proc/efi/vars. This is normal if running "
                    + "on a BIOS system. Determining firmware type a different way...")

        uefi_variables = False

    if uefi_variables:
        #It's UEFI.
        logger.info("get_firmware_type(): Detected Firmware Type as UEFI.")
        SYSTEM_INFO["FirmwareType"] = "UEFI"

    else:
        #Look a second way.
        output = CoreTools.start_process("dmidecode -q -t BIOS", return_output=True,
                                         privileged=True)[1]

        if "UEFI" not in output:
            #It's BIOS.
            logger.info("get_firmware_type(): Detected Firmware Type as BIOS...")
            SYSTEM_INFO["FirmwareType"] = "BIOS"

        else:
            #It's UEFI.
            logger.warning("get_firmware_type(): Detected Firmware Type as UEFI, but couldn't "
                           + "find UEFI variables!")

            SYSTEM_INFO["FirmwareType"] = "UEFI"
            DialogTools.show_msg_dlg(kind="warning", message="Your computer uses UEFI firmware, "
                                     + "but the UEFI variables couldn't be mounted or weren't "
                                     + "found. Please ensure you've booted in UEFI mode rather "
                                     + "than legacy mode to enable access to the UEFI variables. "
                                     + "You can attempt installing a UEFI bootloader without "
                                     + "them, but it might not work, and it isn't recommended.")
Пример #3
0
def ask_for_os_name(partition, is_current_os):
    """Ask the user if an OS exists on the given partition."""
    logger.info("ask_for_os_name(): Asking the user for the name of the OS in "+partition+"...")

    if is_current_os:
        DialogTools.show_msg_dlg(kind="warning", message="WxFixBoot couldn't find the name of the "
                                 + "current OS. Please name it so that WxFixBoot can function "
                                 + "correctly.")

        result = True

    else:
        result = DialogTools.show_yes_no_dlg(message="There is a Linux operating system on "
                                             + "partition: "+partition+" but WxFixBoot couldn't "
                                             + "find its name. It isn't the currently running OS. "
                                             + "Do you want to name it and include it in the "
                                             + "list? Only click yes if you believe it is a "
                                             + "recent OS. Click Yes if you want to name it, "
                                             + "otherwise click No",
                                             buttons=("Name it", "Don't name it."))

    if result is False:
        logger.info("ask_for_os_name(): User didn't want to name the OS in "+partition
                    + "! Ignoring it...")

        #User reported no OS in this partition, ignore it.
        return None

    #otherwise...
    logger.debug("ask_for_os_name(): User reported recent Linux OS in "+partition
                 + " (or OS is current OS). Asking name of OS...")

    #User reported that an OS is here.
    result = DialogTools.show_text_entry_dlg(message="Please enter the name of the operating "
                                             + "system that is on "+partition+".\nThe name you "
                                             + "specify will be used later in the program",
                                             title="WxFixBoot - Enter OS Name")

    return result
Пример #4
0
def backup_uefi_files(mount_point):
    """Backup some .efi files, just in case something goes wrong."""
    #TODO: Make this smarter when we detect Windows.
    logger.info("backup_uefi_files(): Backing up UEFI Files...")

    #We'll backup /EFI/boot/bootx64.efi if it exists, and we'll also backup Windows's uefi files,
    #if they exist. First do /EFI/boot/bootx64.efi. Fortunately, the UEFI partition is always a
    #fat32/fat16 filesystem, so case doesn't matter.
    logger.info("backup_uefi_files(): Backing up "+mount_point+"/boot/efi/boot/boot*.efi...")

    if os.path.isfile(mount_point+"/boot/efi/EFI/boot/boot*.efi"):
        if CoreTools.start_process("cp -v "+mount_point+"/boot/efi/EFI/boot/boot*.efi "
                                   + mount_point+"/boot/efi/EFI/boot/bkpbootx64.efi",
                                   show_output=False, privileged=True) != 0:
            #Log and warn user if this went wrong.
            logger.error("backup_uefi_files(): Failed to backup failsafe UEFI boot file! "
                         + "Warning user and continuing...")

            DialogTools.show_msg_dlg(kind="warning", message="WxFixBoot failed to save "
                                     + "your UEFI boot files to the backup directory! Click okay to continue.")

    #Now do Windows's files, if they exist.
    logger.info("backup_uefi_files(): Backing up Windows's boot files if they exist...")

    if os.path.isfile(mount_point+"/boot/efi/EFI/Microsoft/boot/bootmgfw.efi"):
        if CoreTools.start_process("cp -v "+mount_point+"/boot/efi/EFI/Microsoft/boot/bootmgfw.efi "
                                   + mount_point+"/boot/efi/EFI/Microsoft/boot/bkpbootmgfw.efi",
                                   show_output=False, privileged=True) != 0:
            #Log and warn user if this went wrong.
            logger.error("backup_uefi_files(): Failed to backup Windows's UEFI boot files! "
                         + "Warning user and continuing...")

            DialogTools.show_msg_dlg(kind="warning", message="WxFixBoot failed to "
                                     + "backup Windows's UEFI boot files! Click okay to continue.")

    logger.info("backup_uefi_files(): Done!")
Пример #5
0
def get_bootloaders():
    """
    Find all bootloaders (for each OS), and gather some information about them
    """

    SYSTEM_INFO["ModifyableOSs"] = []

    keys = list(OS_INFO.keys())
    keys.sort()

    for _os in keys:
        #If this is a windows OS, create a standard entry.
        if "Windows" in _os:
            CoreStartupTools.make_bootloaderinfo_entry_for_windows(_os)
            continue

        #Same for macOS.
        elif "macOS" in _os:
            CoreStartupTools.make_bootloaderinfo_entry_for_macos(_os)
            continue

        #If this isn't the current OS, do some preparation.
        if not OS_INFO[_os]["IsCurrentOS"]:
            #Mount the OS's partition.
            mount_point = "/mnt/wxfixboot/mountpoints"+OS_INFO[_os]["Partition"]

            if CoreTools.mount_partition(OS_INFO[_os]["Partition"], mount_point) != 0:
                logger.error("get_bootloaders(): Failed to mount "+_os+"'s partition! Skipping "
                             + "bootloader detection for this OS.")

                continue

            #Set up chroot.
            if CoreTools.setup_chroot(mount_point) != 0:
                logger.error("get_bootloaders(): Couldn't set up chroot on "+mount_point
                             + "! Attempting to remove it in case it's partially set up, "
                             + "and then skipping this OS...")

                CoreTools.teardown_chroot(mount_point)
                continue

        else:
            mount_point = ""

        #Mount a /boot partition if it exists.
        if OS_INFO[_os]["BootPartition"] != "Unknown":
            if CoreTools.mount_partition(OS_INFO[_os]["BootPartition"], mount_point+"/boot") != 0:
                logger.error("get_bootloaders(): Failed to mount "+_os+"'s /boot partition! "
                             + "Skipping bootloader detection for this OS.")

                if not OS_INFO[_os]["IsCurrentOS"]:
                    CoreTools.teardown_chroot(mount_point)
                    CoreTools.unmount(mount_point)

                continue

        #Mount a /boot/efi partition if it exists.
        if OS_INFO[_os]["EFIPartition"] != "Unknown":
            if CoreTools.mount_partition(OS_INFO[_os]["EFIPartition"],
                                         mount_point+"/boot/efi") != 0:

                logger.error("get_bootloaders(): Failed to mount "+_os+"'s /boot/efi partition! "
                             + "Skipping bootloader detection for this OS.")

                if not OS_INFO[_os]["IsCurrentOS"]:
                    CoreTools.teardown_chroot(mount_point)
                    CoreTools.unmount(mount_point)

                continue

        #Look for bootloaders.
        BOOTLOADER_INFO[_os] = {}
        BOOTLOADER_INFO[_os]["OSName"] = _os
        BOOTLOADER_INFO[_os]["Bootloader"], BOOTLOADER_INFO[_os]["AvailableBootloaders"] = \
        CoreStartupTools.look_for_bootloaders_on_partition(_os, OS_INFO[_os]["PackageManager"],
                                                           mount_point,
                                                           not OS_INFO[_os]["IsCurrentOS"])

        BOOTLOADER_INFO[_os]["Timeout"], BOOTLOADER_INFO[_os]["GlobalKernelOptions"], \
        BOOTLOADER_INFO[_os]["BootDisk"], BOOTLOADER_INFO[_os]["BLSpecificDefaultOS"], \
        BOOTLOADER_INFO[_os]["DefaultOS"] = (10, "Unknown", "Unknown", "Unknown", "Unknown")

        BOOTLOADER_INFO[_os]["MenuEntries"] = {_os: {}}

        #For EFI bootloaders, set the boot disk to the OS's EFI Partition.
        if BOOTLOADER_INFO[_os]["Bootloader"] == "GRUB-UEFI":
            BOOTLOADER_INFO[_os]["BootDisk"] = OS_INFO[_os]["EFIPartition"]

        if BOOTLOADER_INFO[_os]["Bootloader"] in ("GRUB-UEFI", "GRUB2") \
            and os.path.isfile(mount_point+"/etc/default/grub"):

            grub_dir, BOOTLOADER_INFO[_os]["MenuEntries"] = \
            BootloaderConfigObtainingTools.parse_grub2_menu_data(menu_data="",
                                                                 mount_point=mount_point)[0:2]

            #Get GRUB2's config.
            #If we're using fedora, always look for grubenv in the EFI partition (the grubenv
            #symlink is in /boot/grub2 but it doesn't work when we're chrooting).
            if OS_INFO[_os]["PackageManager"] == "dnf":
                grub_dir = mount_point+"/boot/efi/EFI/fedora"

            BOOTLOADER_INFO[_os]["Timeout"], BOOTLOADER_INFO[_os]["GlobalKernelOptions"], \
            BOOTLOADER_INFO[_os]["BLSpecificDefaultOS"] = \
            BootloaderConfigObtainingTools.get_grub2_config(mount_point+"/etc/default/grub",
                                                            grub_dir+"/grubenv",
                                                            BOOTLOADER_INFO[_os]["MenuEntries"])

            #Try to find GRUB's location if this is GRUB2.
            if BOOTLOADER_INFO[_os]["Bootloader"] == "GRUB2":
                BOOTLOADER_INFO[_os]["BootDisk"] = \
                BootloaderConfigObtainingTools.find_grub(OS_INFO[_os]["Partition"], "GRUB2")

        #If we didn't find the kernel options, set some defaults here, and warn the user.
        if BOOTLOADER_INFO[_os]["GlobalKernelOptions"] == "Unknown":
            BOOTLOADER_INFO[_os]["GlobalKernelOptions"] = "quiet splash nomodeset"
            logger.warning("get_bootloaders(): Couldn't find "+_os+"'s global kernel options! "
                           + "Assuming 'quiet splash nomodeset'...")

            DialogTools.show_msg_dlg(message="Couldn't find "+_os+"'s default kernel options! "
                                     + "Loading safe defaults instead. Click okay to continue.",
                                     kind="warning")

        #If we didn't find the timeout, set it to 10 seconds here, and warn the user.
        if BOOTLOADER_INFO[_os]["Timeout"] == "Unknown":
            BOOTLOADER_INFO[_os]["Timeout"] = 10
            logger.warning("get_bootloaders(): Couldn't find "+_os+"'s bootloader timeout! "
                           + "Assuming 10 seconds...")

            DialogTools.show_msg_dlg(message="Couldn't find "+_os+"'s bootloader timeout! "
                                     + "Loading safe defaults instead. Click okay to continue.",
                                     kind="warning")

        #Determine if we can modify this OS from our current one.
        if OS_INFO[_os]["Arch"] == SYSTEM_INFO["CurrentOSArch"] \
            or (OS_INFO[_os]["Arch"] == "i386" and SYSTEM_INFO["CurrentOSArch"] == "x86_64"):

            BOOTLOADER_INFO[_os]["IsModifyable"] = True
            BOOTLOADER_INFO[_os]["Comments"] = "Architecture is "+OS_INFO[_os]["Arch"]+"."
            SYSTEM_INFO["ModifyableOSs"].append(_os)

        else:
            BOOTLOADER_INFO[_os]["IsModifyable"] = False
            BOOTLOADER_INFO[_os]["Comments"] = "Architecture is "+OS_INFO[_os]["Arch"] \
                                               + ". Not modifyable because current OS is " \
                                               + SYSTEM_INFO["CurrentOSArch"]+"."

        #Initialise some default no-action settings.
        BOOTLOADER_INFO[_os]["Settings"] = {}
        BOOTLOADER_INFO[_os]["Settings"]["Reinstall"] = False
        BOOTLOADER_INFO[_os]["Settings"]["Update"] = False
        BOOTLOADER_INFO[_os]["Settings"]["KeepExistingTimeout"] = False
        BOOTLOADER_INFO[_os]["Settings"]["KeepExistingKernelOptions"] = False
        BOOTLOADER_INFO[_os]["Settings"]["NewKernelOptions"] = \
        BOOTLOADER_INFO[_os]["GlobalKernelOptions"]

        BOOTLOADER_INFO[_os]["Settings"]["NewTimeout"] = BOOTLOADER_INFO[_os]["Timeout"]
        BOOTLOADER_INFO[_os]["Settings"]["DefaultOS"] = BOOTLOADER_INFO[_os]["DefaultOS"]
        BOOTLOADER_INFO[_os]["Settings"]["InstallNewBootloader"] = False
        BOOTLOADER_INFO[_os]["Settings"]["NewBootloader"] = "-- Please Select --"
        BOOTLOADER_INFO[_os]["Settings"]["BackupBootloader"] = False
        BOOTLOADER_INFO[_os]["Settings"]["BootloaderBackupTarget"] = "-- Please Select --"
        BOOTLOADER_INFO[_os]["Settings"]["RestoreBootloader"] = False
        BOOTLOADER_INFO[_os]["Settings"]["BootloaderRestoreSource"] = "-- Please Select --"
        BOOTLOADER_INFO[_os]["Settings"]["ChangeThisOS"] = False

        #Initialise GUI state for this OS (True = Enabled, False = Disabled).
        BOOTLOADER_INFO[_os]["GUIState"] = {}
        BOOTLOADER_INFO[_os]["GUIState"]["ReinstallCheckBoxState"] = True
        BOOTLOADER_INFO[_os]["GUIState"]["UpdateCheckBoxState"] = True
        BOOTLOADER_INFO[_os]["GUIState"]["KeepExistingTimeoutCheckBoxState"] = False
        BOOTLOADER_INFO[_os]["GUIState"]["NewTimeoutSpinnerState"] = False
        BOOTLOADER_INFO[_os]["GUIState"]["KeepExistingKernelOptionsCheckBoxState"] = False
        BOOTLOADER_INFO[_os]["GUIState"]["NewKernelOptionsTextCtrlState"] = False
        BOOTLOADER_INFO[_os]["GUIState"]["DefaultOSChoiceState"] = False
        BOOTLOADER_INFO[_os]["GUIState"]["InstallNewBootloaderCheckBoxState"] = True
        BOOTLOADER_INFO[_os]["GUIState"]["NewBootloaderChoiceState"] = False
        BOOTLOADER_INFO[_os]["GUIState"]["BackupBootloaderCheckBoxState"] = True
        BOOTLOADER_INFO[_os]["GUIState"]["BackupBootloaderChoiceState"] = False
        BOOTLOADER_INFO[_os]["GUIState"]["RestoreBootloaderCheckBoxState"] = True
        BOOTLOADER_INFO[_os]["GUIState"]["RestoreBootloaderChoiceState"] = False

        #If there's a seperate EFI partition for this OS,
        #make sure it's unmounted before removing the chroot.
        if OS_INFO[_os]["EFIPartition"] != "Unknown":
            if CoreTools.unmount(mount_point+"/boot/efi") != 0:
                logger.error("MainBackendTools: get_bootloaders(): Failed to unmount "+mount_point
                             + "/boot/efi! This probably doesn't matter...")

        #unmount a /boot partition if it exists.
        if OS_INFO[_os]["BootPartition"] != "Unknown":
            if CoreTools.unmount(mount_point+"/boot") != 0:
                logger.error("get_bootloaders(): Failed to unmount "+_os+"'s /boot partition! "
                             + "Continuing anyway...")

        #Clean up if needed.
        if not OS_INFO[_os]["IsCurrentOS"]:
            #Remove chroot.
            if CoreTools.teardown_chroot(mount_point) != 0:
                logger.error("get_bootloaders(): Failed to remove chroot from "+mount_point
                             + "! Attempting to continue anyway...")

            #unmount the OS's partition.
            if CoreTools.unmount(mount_point) != 0:
                logger.error("get_bootloaders(): Failed to unmount "+_os+"'s partition! This "
                             + "could indicate that chroot wasn't removed correctly. Continuing "
                             + "anyway...")

    #Get default OSs.
    for _os in OS_INFO:
        #Set sensible defaults for Windows.
        if "Windows" in _os:
            BOOTLOADER_INFO[_os]["DefaultBootDevice"] = OS_INFO[_os]["Partition"]
            BOOTLOADER_INFO[_os]["DefaultOS"] = _os
            continue

        #Same for macOS.
        elif "macOS" in _os:
            BOOTLOADER_INFO[_os]["DefaultBootDevice"] = OS_INFO[_os]["Partition"]
            BOOTLOADER_INFO[_os]["DefaultOS"] = _os
            continue

        #Match the bootloader-specific default OS to WxFixBoot's OSs by partition.
        logger.info("get_bootloaders(): Attempting to match "+_os+"'s default OS to any OS that "
                    + "WxFixBoot detected...")

        BOOTLOADER_INFO[_os]["DefaultBootDevice"] = "Unknown"

        if "MenuEntries" in BOOTLOADER_INFO[_os].keys():
            CoreStartupTools.get_defaultoss_partition(_os)

        else:
            #Bootloader's configuration is missing.
            logger.error("get_bootloaders(): "+_os+"'s bootloader configuration is missing. A "
                         + "reinstall will be required for that bootloader...")

        #We have the partition, so now find the OS that resides on that partition.
        CoreStartupTools.match_partition_to_os(_os)

        #Log if we couldn't match them.
        if BOOTLOADER_INFO[_os]["DefaultOS"] == "Unknown":
            logger.warning("get_bootloaders(): Couldn't match! We will instead use the first OS "
                           + "in the list as the default OS, which is "
                           + SYSTEM_INFO["ModifyableOSs"][0]+"...")

            BOOTLOADER_INFO[_os]["DefaultOS"] = SYSTEM_INFO["ModifyableOSs"][0]

        #Set this.
        BOOTLOADER_INFO[_os]["Settings"]["DefaultOS"] = BOOTLOADER_INFO[_os]["DefaultOS"]
Пример #6
0
def find_checkable_file_systems():
    """
    Find all checkable filesystems, and then return them to
    EssentialBackendTools().filesystem_check()
    """

    logger.info("find_checkable_file_systems(): Finding and returning all filesystems/partitions "
                + "that can be checked...")

    #Do setup.
    do_not_check_list = []
    filesystems_to_check = {}
    root_fs = CoreTools.get_partition_mounted_at("/")

    #Get a list of missing fsck modules (if any) based on the existing filesystems.
    missing_fsck_modules = find_missing_fsck_modules()

    keys = list(DISK_INFO.keys())
    keys.sort()

    #Determine checkable partitions.
    for disk in keys:
        #Ignore all devices.
        if DISK_INFO[disk]["Type"] == "Device":
            continue

        #Check if the required fsck module is present, and that the partition isn't root_fs
        if "fsck."+DISK_INFO[disk]["FileSystem"] in missing_fsck_modules:
            mount_point = "None"
            check_this_fs = False
            remount_fs_after = False
            reason = "filesystem checker was not found."

        elif SYSTEM_INFO["IsLiveDisk"] is False and disk == root_fs:
            #If we're not running on a live disk, skip the filesystem if it's the same as root_fs
            #(in which case checking it may corrupt data).
            mount_point = "/"
            check_this_fs = False
            remount_fs_after = False
            reason = "disk is busy."

        #Extra check for LVM disks using aliases.
        elif DISK_INFO[disk]["Product"] == "LVM Partition" and root_fs in DISK_INFO[disk]["Aliases"]:
            mount_point = "/"
            check_this_fs = False
            remount_fs_after = False
            reason = "disk is busy."

        else:
            #If filesystem is unknown, or not applicable (extended partitions), don't check it.
            if DISK_INFO[disk]["FileSystem"] in ("Unknown", "N/A"):
                mount_point = "None"
                check_this_fs = False
                remount_fs_after = False
                reason = "filesystem was not recognised."

            else:
                #Check if the partition is mounted.
                if CoreTools.is_mounted(disk) is False:
                    mount_point = "None"
                    check_this_fs = True
                    remount_fs_after = False

                #Extra check for LVM disks using aliases.
                elif DISK_INFO[disk]["Product"] == "LVM Partition" and \
                     CoreTools.any_mounted(DISK_INFO[disk]["Aliases"]) is False:

                    mount_point = "None"
                    check_this_fs = True
                    remount_fs_after = False

                else:
                    #Unmount the FS temporarily, to avoid data corruption.
                    mount_point = CoreTools.get_mount_point_of(disk)

                    if CoreTools.unmount(disk) != 0:
                        logger.warning("find_checkable_file_systems(): Failed to unmount "+disk
                                       +", which is necessary for safe disk checking! Ignoring it.")

                        check_this_fs = False
                        remount_fs_after = False
                        reason = "disk is busy."

                    else:
                        check_this_fs = True
                        remount_fs_after = True

        if check_this_fs:
            #Add it to the dictionary for checking.
            filesystems_to_check[disk] = {}
            filesystems_to_check[disk]["Remount"] = remount_fs_after
            filesystems_to_check[disk]["MountPoint"] = mount_point

        else:
            #Add it to the non-checkable list
            do_not_check_list.append(disk+", because the "+reason)

    #Report uncheckable partitions.
    if do_not_check_list != []:
        #Some filesystems will not be checked. Tell the user.
        DialogTools.show_msg_dlg(kind="info",
                                 message="The following filesystems will not be checked:\n\n"
                                 + '\n'.join(do_not_check_list)+"\n\nThe most likely reason for "
                                 + "this is that some of the filesystems are in use, or that the "
                                 + "required filesystem checkers weren't found. WxFixBoot will "
                                 + "now continue to check the remaining filesystems.")

    logger.info("find_checkable_file_systems(): Done! Filesystems that won't be checked: "
                + '\n'.join(do_not_check_list)+"...")

    return filesystems_to_check
Пример #7
0
def handle_filesystem_check_return_values(exec_cmds, retval, partition,
                                          manage_bootloader_function):
    """Handle Filesystem Checker return codes."""
    exec_list = exec_cmds.split()

    #Return values of 1,2 or 3 happen if errors were corrected.
    if retval in (1, 2, 3) and exec_list[0] != "badblocks":
        if exec_list[0] == "xfs_repair":
            #Fs Corruption Detected.
            logger.warning(
                "handle_filesystem_check_return_values(): xfs_repair detected "
                + "filesystem corruption on FileSystem: " + partition +
                ". It's probably (and hopefully) been fixed, but we're logging "
                + "this anyway.")

            DialogTools.show_msg_dlg(
                kind="warning",
                message="Corruption was found on the filesystem: " +
                partition +
                "! Fortunately, it looks like the checker utility has " +
                "fixed the corruption. Click okay to continue.")

        elif exec_list[0] in ('fsck.jfs', 'fsck.minix', 'fsck.reiserfs',
                              'fsck.vfat', 'fsck.ext2', 'fsck.ex3',
                              'fsck.ext4', 'fsck.ext4dev'):

            #Fixed Errors.
            logger.info("handle_filesystem_check_return_values(): " +
                        exec_list[0] +
                        " successfully fixed errors on the partition: " +
                        partition + ". Continuing...")

            DialogTools.show_msg_dlg(
                kind="warning",
                message="The filesystem checker found and " +
                "successfully fixed errors on partition: " + partition +
                ". Click okay to continue.")

    else:
        #Something bad happened!
        #If we're doing bootloader operations, prompt the user to disable them.
        doing_bootloader_operations = False

        for function in OPERATIONS:
            if isinstance(function, tuple):
                if manage_bootloader_function == function[0]:
                    doing_bootloader_operations = True
                    break

        logger.error(
            "handle_filesystem_check_return_values(): " + exec_list[0] +
            " Errored with exit value " + str(retval) +
            "! This could indicate filesystem corruption or bad sectors!")

        if doing_bootloader_operations:
            logger.error(
                "handle_filesystem_check_return_values(): Asking the user whether to "
                + "skip bootloader operations...")

            result = DialogTools.show_yes_no_dlg(
                message="Error! The filesystem checker gave " +
                "exit value: " + str(retval) + "! This could " +
                "indicate filesystem corruption, a problem " +
                "with the filesystem checker, or bad sectors " +
                "on partition: " + partition + ". If you perform " +
                "bootloader operations on this partition, your " +
                "system could become unstable or unbootable. " +
                "Do you want to disable bootloader operations, " +
                "as is strongly recommended?",
                title="WxFixBoot - Disable Bootloader " + "Operations?",
                buttons=("Disable Bootloader Operations",
                         "Ignore and Continue Anyway"))

            if result:
                #A good choice. WxFixBoot will now disable any bootloader operations.
                logger.warning(
                    "handle_filesystem_check_return_values(): User disabled bootloader "
                    +
                    "operations as recommended, due to bad sectors/HDD problems/FS "
                    + "Checker problems...")

                SYSTEM_INFO["DisableBootloaderOperations"] = True
                SYSTEM_INFO["DisableBootloaderOperationsBecause"] \
                .append("Filesystem corruption was detected on "+partition)

            else:
                #Seriously? Well, okay, we'll do it anyway... This is probably a very bad idea...
                logger.warning(
                    "handle_filesystem_check_return_values(): User ignored the warning "
                    +
                    "and went ahead with bootloader modifications (if any) anyway, "
                    +
                    "even with possible HDD problems/Bad sectors! This is a REALLY "
                    + "bad idea, but we'll do it anyway, as requested...")
Пример #8
0
def filesystem_check(_type, manage_bootloader_function):
    """Quickly check all filesystems."""
    logger.debug("filesystem_check(): Starting...")

    #Update Current Operation Text.
    wx.CallAfter(wx.GetApp().TopWindow.update_current_operation_text,
                 message="Preparing for Filesystem Check...")

    wx.CallAfter(wx.GetApp().TopWindow.update_current_progress, 10)
    wx.CallAfter(wx.GetApp().TopWindow.update_output_box,
                 "\n###Preparing to do the Filesystem Check...###\n")

    #Determine which Disks are to be checked.
    filesystems_to_check = HelperBackendTools.find_checkable_file_systems()
    wx.CallAfter(wx.GetApp().TopWindow.update_current_progress, 30)

    #Find the length of the list (this is needed to update the progressbars).
    filesystems_to_check_length = len(filesystems_to_check)
    checked = 0

    DialogTools.show_msg_dlg(
        kind="info",
        message="WxFixBoot will now perform the disk checks. " +
        "You may wish to open the terminal output box to view the " +
        "progress information.")

    #Run the check on the checkable Disks
    for disk in filesystems_to_check:
        #Gather info.
        logger.info("filesystem_check():: Checking " + disk + "...")
        wx.CallAfter(wx.GetApp().TopWindow.update_output_box,
                     "\n###Checking Disk: " + disk + "###\n")
        wx.CallAfter(wx.GetApp().TopWindow.update_current_operation_text,
                     message="Checking Disk: " + disk)
        wx.CallAfter(
            wx.GetApp().TopWindow.update_current_progress,
            30 + ((50 // filesystems_to_check_length) * (checked + 1)))

        run_badblocks = False

        #Create a command list that will work based on the fstype of this Disk and the type of
        #check we're performing. If there aren't any use cases for the fstype, display a message
        #to the user and skip it.
        if _type == "Quick":
            if DISK_INFO[disk]["FileSystem"] == "jfs":
                exec_cmds = "fsck.jfs -vf " + disk

            elif DISK_INFO[disk]["FileSystem"] == "minix":
                exec_cmds = "fsck.minix -avf " + disk

            elif DISK_INFO[disk]["FileSystem"] == "reiserfs":
                exec_cmds = "fsck.reiserfs -apf " + disk

            elif DISK_INFO[disk]["FileSystem"] == "xfs":
                exec_cmds = "xfs_repair -Pvd " + disk

            elif DISK_INFO[disk]["FileSystem"] in ("hfs", "hfsplus"):
                exec_cmds = "fsck.hfsplus -fy " + disk

            elif DISK_INFO[disk]["FileSystem"] == "vfat":
                exec_cmds = "fsck.vfat -yv " + disk

            elif DISK_INFO[disk]["FileSystem"] in ('ext2', 'ext3', 'ext4',
                                                   'ext4dev'):
                exec_cmds = "fsck." + DISK_INFO[disk][
                    "FileSystem"] + " -yvf " + disk

            else:
                exec_cmds = ""
                logger.warning(
                    "filesystem_check(): Skipping Disk: " + disk +
                    ", as WxFixBoot doesn't support checking it yet...")

                DialogTools.show_msg_dlg(
                    kind="error",
                    message="The filesystem on Disk: " + disk +
                    " could not be checked, as WxFixBoot doesn't support " +
                    "checking it yet. " + disk + " will now be skipped.")

        else:
            #For disks that doesn't do bad sector checks with the normal FS checker,
            #run badblocks manually on them.
            if DISK_INFO[disk]["FileSystem"] == "jfs":
                exec_cmds = "fsck.jfs -vf " + disk
                run_badblocks = True

            elif DISK_INFO[disk]["FileSystem"] == "minix":
                exec_cmds = "fsck.minix -avf " + disk
                run_badblocks = True

            elif DISK_INFO[disk]["FileSystem"] == "reiserfs":
                exec_cmds = "fsck.reiserfs -apf " + disk
                run_badblocks = True

            elif DISK_INFO[disk]["FileSystem"] == "xfs":
                exec_cmds = "xfs_repair -Pvd " + disk
                run_badblocks = True

            elif DISK_INFO[disk]["FileSystem"] in ("hfs", "hfsplus"):
                exec_cmds = "fsck.hfsplus -fy " + disk
                run_badblocks = True

            elif DISK_INFO[disk]["FileSystem"] == "vfat":
                exec_cmds = "fsck.vfat -yvt " + disk

            elif DISK_INFO[disk]["FileSystem"] in ('ext2', 'ext3', 'ext4',
                                                   'ext4dev'):
                exec_cmds = "fsck." + DISK_INFO[disk][
                    "FileSystem"] + " -yvcf " + disk

            else:
                exec_cmds = ""
                DialogTools.show_msg_dlg(
                    kind="info",
                    message="The filesystem on Disk: " + disk +
                    " could not be checked, as WxFixBoot doesn't support " +
                    "checking it yet. " + disk + " will now be skipped.")

        #Run the command, and remount the Disk if needed.
        if exec_cmds != "":
            retval = CoreTools.start_process(exec_cmds, privileged=True)

            #Check the return values, and run the handler if needed.
            if retval == 0:
                #Success.
                logger.info("filesystem_check(): Checked Disk: " + disk +
                            ". No Errors Found!")

            else:
                handle_filesystem_check_return_values(
                    exec_cmds=exec_cmds,
                    retval=retval,
                    partition=disk,
                    manage_bootloader_function=manage_bootloader_function)

        #Run bad blocks if requested.
        if run_badblocks:
            retval = CoreTools.start_process("badblocks -sv " + disk,
                                             privileged=True)

            #Check the return values, and run the handler if needed.
            if retval == 0:
                #Success.
                logger.info("filesystem_check(): Checked Disk: " + disk +
                            " for bad sectors. " + "No Errors Found!")

            else:
                handle_filesystem_check_return_values(
                    exec_cmds="badblocks -sv " + disk,
                    retval=retval,
                    partition=disk,
                    manage_bootloader_function=manage_bootloader_function)

        if filesystems_to_check[disk]["Remount"]:
            logger.debug("filesystem_check(): Remounting Disk: " + disk +
                         " Read-Write...")
            retval = CoreTools.mount_partition(
                partition=disk,
                mount_point=filesystems_to_check[disk]["MountPoint"])

            if retval != 0:
                logger.warning(
                    "filesystem_check(): Failed to remount " + disk +
                    " after check. We probably need to reboot first. Never mind..."
                )

        checked += 1

    #Update Current Operation Text.
    wx.CallAfter(wx.GetApp().TopWindow.update_current_operation_text,
                 message="Finished Filesystem Check!")
    wx.CallAfter(wx.GetApp().TopWindow.update_current_progress, 100)
    wx.CallAfter(wx.GetApp().TopWindow.update_output_box,
                 "\n###Finished Filesystem Check!###\n")
Пример #9
0
def set_new_bootloader_config(_os):
    """Manage setting new bootloader config."""
    logger.info("set_new_bootloader_config(): Setting " +
                BOOTLOADER_INFO[_os]["Settings"]["NewBootloader"] +
                "'s config for " + _os + "...")

    wx.CallAfter(wx.GetApp().TopWindow.update_current_operation_text,
                 message="Setting " +
                 BOOTLOADER_INFO[_os]["Settings"]["NewBootloader"] +
                 " config for " + _os + "...")

    wx.CallAfter(wx.GetApp().TopWindow.update_current_progress, 79)
    wx.CallAfter(
        wx.GetApp().TopWindow.update_output_box,
        "\n###Setting " + BOOTLOADER_INFO[_os]["Settings"]["NewBootloader"] +
        "'s config for " + _os + "...###\n")

    #If this is the current OS, let the config functions know that we aren't using chroot.
    if OS_INFO[_os]["IsCurrentOS"]:
        logger.debug(
            "set_new_bootloader_config(): We're modifying the current OS...")
        #If so, make sure this will work for this OS too, and avoid setting mountpoint, so the
        #config instructions below look in the right place for the config files.
        use_chroot, unmount_after, mount_point = (False, False, "")

    else:
        logger.debug(
            "set_new_bootloader_config(): We're modifying another OS...")
        use_chroot = True
        mount_point = "/mnt/wxfixboot/mountpoints" + OS_INFO[_os]["Partition"]

        #Check if the partition is mounted.
        unmount_after = not CoreTools.is_mounted(OS_INFO[_os]["Partition"],
                                                 mount_point)

        if unmount_after:
            #Mount the partition.
            if CoreTools.mount_partition(partition=OS_INFO[_os]["Partition"],
                                         mount_point=mount_point) != 0:
                #Ignore this partition.
                logger.warning(
                    "set_new_bootloader_config(): Failed to mount " +
                    OS_INFO[_os]["Partition"] + "! Giving up...")

                return False

        #Set up chroot.
        if CoreTools.setup_chroot(mount_point=mount_point) != 0:
            logger.error(
                "set_new_bootloader_config(): Failed to set up chroot at " +
                mount_point + "! Giving up...")

            DialogTools.show_msg_dlg(
                kind="error",
                message="WxFixBoot failed to set up a chroot for " + _os +
                "! Giving up. You will be prompted to try again if " +
                "you wish.")

            return False

        wx.CallAfter(wx.GetApp().TopWindow.update_current_progress, 81)

    #Mount a /boot partition if it exists.
    if OS_INFO[_os]["BootPartition"] != "Unknown":
        if CoreTools.mount_partition(OS_INFO[_os]["BootPartition"],
                                     mount_point + "/boot") != 0:
            logger.error(
                "set_new_bootloader_config(): Failed to mount " + _os +
                "'s /boot partition! Skipping bootloader config setting for this OS."
            )

            if not OS_INFO[_os]["IsCurrentOS"]:
                CoreTools.teardown_chroot(mount_point)
                CoreTools.unmount(mount_point)

            return False

    #If there's a seperate EFI partition for this OS, make sure it's mounted.
    if OS_INFO[_os]["EFIPartition"] != "Unknown":
        if CoreTools.mount_partition(
                partition=OS_INFO[_os]["EFIPartition"],
                mount_point=mount_point + "/boot/efi") != 0:
            logger.error("remove_old_bootloader(): Failed to mount " +
                         OS_INFO[_os]["EFIPartition"] +
                         "! Warn the user and skip this OS.")

            DialogTools.show_msg_dlg(
                kind="error",
                message="WxFixBoot failed to mount the partition containing " +
                _os + "'s EFI partition! Giving up. You will be prompted to " +
                "try again if you wish.")

            return False

    #On GRUB2, get the new menuentries so we can set the default OS.
    logger.info(
        "set_new_bootloader_config(): Reading GRUB2's menu entries to set default OS..."
    )

    if BOOTLOADER_INFO[_os]["Settings"]["NewBootloader"] in ("GRUB2",
                                                             "GRUB-UEFI"):
        #Update GRUB.
        logger.info(
            "set_new_bootloader_config(): Updating GRUB2 Configuration...")
        BootloaderConfigSettingTools.update_grub2(
            _os=_os,
            package_manager=OS_INFO[_os]["PackageManager"],
            use_chroot=use_chroot,
            mount_point=mount_point)

        BOOTLOADER_INFO[_os]["NewMenuEntries"] = \
        BootloaderConfigObtainingTools.parse_grub2_menu_data(menu_data="",
                                                             mount_point=mount_point)[1]

    #Look for the configuration file, based on which SetConfig() function we're about to run.
    if BOOTLOADER_INFO[_os]["Settings"]["NewBootloader"] in ("GRUB2",
                                                             "GRUB-UEFI"):
        #Check mount_point/etc/default/grub exists.
        if os.path.isfile(mount_point + "/etc/default/grub"):
            #It does, we'll run the function to set the config now.
            logger.info(
                "set_new_bootloader_config(): Setting GRUB2 Configuration...")
            BootloaderConfigSettingTools.set_grub2_config(
                _os=_os,
                filetoopen=mount_point + "/etc/default/grub",
                bootloader_timeout=BOOTLOADER_INFO[_os]["Settings"]
                ["NewTimeout"],
                kernel_options=BOOTLOADER_INFO[_os]["Settings"]
                ["NewKernelOptions"],
                package_manager=OS_INFO[_os]["PackageManager"])

        if BOOTLOADER_INFO[_os]["Settings"]["NewBootloader"] == "GRUB-UEFI":
            #Mount the UEFI partition at mount_point/boot/efi.
            if CoreTools.mount_partition(
                    partition=OS_INFO[_os]["EFIPartition"],
                    mount_point=mount_point + "/boot/efi") != 0:
                logger.error(
                    "set_new_bootloader_config(): Couldn't mount EFI partition "
                    + OS_INFO[_os]["EFIPartition"] +
                    " to install bootloader! Giving up " +
                    "and warning user...")

                DialogTools.show_msg_dlg(
                    kind="error",
                    message="WxFixBoot failed to mount " + _os +
                    "'s EFI partition! You will now be promtped to give " +
                    "up or try again.")

                return False

            #Now Install GRUB-UEFI to the UEFI Partition.
            logger.info(
                "set_new_bootloader_config(): Installing GRUB-UEFI to " +
                OS_INFO[_os]["EFIPartition"] + "...")

            BootloaderConfigSettingTools.install_grub2_to_efi_partition(
                package_manager=OS_INFO[_os]["PackageManager"],
                mount_point=mount_point,
                use_chroot=use_chroot,
                uefi_system_partition_mount_point="/boot/efi",
                arch=OS_INFO[_os]["Arch"])

        else:
            #Now Install GRUB2 to the MBR.
            logger.info("set_new_bootloader_config(): Installing GRUB2 to " +
                        DISK_INFO[OS_INFO[_os]["Partition"]]["HostDevice"] +
                        "...")

            BootloaderConfigSettingTools.install_grub2_to_mbr(
                package_manager=OS_INFO[_os]["PackageManager"],
                use_chroot=use_chroot,
                mount_point=mount_point,
                device=DISK_INFO[OS_INFO[_os]["Partition"]]["HostDevice"])

        #Update GRUB.
        logger.info(
            "set_new_bootloader_config(): Updating GRUB2 Configuration...")
        BootloaderConfigSettingTools.update_grub2(
            _os=_os,
            package_manager=OS_INFO[_os]["PackageManager"],
            use_chroot=use_chroot,
            mount_point=mount_point)

        if BOOTLOADER_INFO[_os]["Settings"]["NewBootloader"] == "GRUB-UEFI":
            #Make an entry in fstab for the UEFI Partition, if needed.
            HelperBackendTools.write_fstab_entry_for_uefi_partition(
                _os=_os, mount_point=mount_point)

            #Copy and backup EFI files where needed.
            HelperBackendTools.backup_uefi_files(mount_point=mount_point)
            HelperBackendTools.manage_uefi_files(_os=_os,
                                                 mount_point=mount_point)

        if BOOTLOADER_INFO[_os]["Settings"]["NewBootloader"] == "GRUB-UEFI" \
            and OS_INFO[_os]["PackageManager"] == "dnf":

            #If we're switching to GRUB-UEFI from BIOS it can mess up GRUB2 and change the boot
            #commands to linux and initrd instead of linuxefi and initrdefi, preventing boot.
            #Fix this. The next time GRUB is updated from within the OS it will fix itself.
            logger.info(
                "set_new_bootloader_config(): Fixing Fedora's GRUB2-UEFI config (when "
                + "booted with BIOS, it can go wrong)...")

            logger.info(
                "set_new_bootloader_config(): Finding and opening GRUB config file..."
            )

            #Find grub.cfg. (Ubuntu).
            if os.path.isdir(mount_point + "/boot/grub"):
                grub_dir = mount_point + "/boot/grub"

            #(Fedora, EFI)
            elif os.path.isdir(mount_point + "/boot/efi/EFI/fedora"):
                grub_dir = mount_point + "/boot/efi/EFI/fedora"

            #Correct the commands if needed.
            config = CoreTools.read_privileged_file(grub_dir + "/grub.cfg")

            new_config = []

            for line in config:
                if "linux16" in line and "/vmlinu" in line:
                    new_config.append(
                        line.replace("linux16", "linuxefi") + "\n")

                elif "linux" in line and "linuxefi" not in line and "/vmlinu" in line:
                    new_config.append(line.replace("linux", "linuxefi") + "\n")

                elif "initrd16" in line and ("/initrd" in line
                                             or "/initramfs" in line):
                    new_config.append(
                        line.replace("initrd16", "initrdefi") + "\n")

                elif "initrd" in line and "initrdefi" not in line \
                    and ("/initrd" in line or "/initramfs" in line):

                    new_config.append(
                        line.replace("initrd", "initrdefi") + "\n")

                else:
                    new_config.append(line + "\n")

            #Write the fixed config.
            CoreTools.write_privileged_file(grub_dir + "/grub.cfg",
                                            ''.join(new_config))

            #unmount the EFI partition.
            if CoreTools.unmount(OS_INFO[_os]["EFIPartition"]) != 0:
                logger.error(
                    "set_new_bootloader_config(): Couldn't unmount EFI partition! "
                    +
                    "This probably won't matter, so we'll continue anyway...")

            logger.info("set_new_bootloader_config(): Done!")

        elif BOOTLOADER_INFO[_os]["Settings"]["NewBootloader"] == "GRUB2" \
            and OS_INFO[_os]["PackageManager"] == "dnf":

            #If we're switching to GRUB2 from UEFI it can mess up GRUB2 and change the boot
            #commands to linuxefi and initrdefi instead of linux and initrd, preventing boot.
            #Fix this. The next time GRUB is updated from within the OS it will fix itself.
            logger.info(
                "set_new_bootloader_config(): Fixing Fedora's GRUB2-BIOS config (when "
                + "booted with EFI, it can go wrong)...")

            logger.info(
                "set_new_bootloader_config(): Finding and opening GRUB config file..."
            )

            #Find grub.cfg. (Ubuntu).
            if os.path.isdir(mount_point + "/boot/grub"):
                grub_dir = mount_point + "/boot/grub"

            #(Fedora, BIOS)
            elif os.path.isdir(mount_point + "/boot/grub2"):
                grub_dir = mount_point + "/boot/grub2"

            #Correct the commands if needed.
            config = CoreTools.read_privileged_file(grub_dir + "/grub.cfg")

            new_config = []

            for line in config:
                new_config.append(line.replace("linuxefi", "linux")\
                .replace("initrdefi", "initrd")+"\n")

            #Write the fixed config.
            CoreTools.write_privileged_file(grub_dir + "/grub.cfg",
                                            ''.join(new_config))

            logger.info("set_new_bootloader_config(): Done!")

    #If there's a seperate EFI partition for this OS, make sure it's unmounted before
    #removing the chroot.
    if OS_INFO[_os]["EFIPartition"] != "Unknown":
        if CoreTools.unmount(mount_point + "/boot/efi") != 0:
            logger.error("set_new_bootloader_config(): Failed to unmount " +
                         mount_point +
                         "/boot/efi! This probably doesn't matter...")

    #unmount a /boot partition if it exists.
    if OS_INFO[_os]["BootPartition"] != "Unknown":
        if CoreTools.unmount(mount_point + "/boot") != 0:
            logger.error("set_new_bootloader_config(): Failed to unmount " +
                         _os + "'s /boot partition! Continuing anyway...")

    #Tear down chroot if needed.
    if use_chroot:
        if CoreTools.teardown_chroot(mount_point=mount_point) != 0:
            logger.error(
                "set_new_bootloader_config(): Failed to remove chroot at " +
                mount_point + "! Attempting to continue anyway...")

    #unmount the partition if needed.
    if unmount_after:
        if CoreTools.unmount(mount_point) != 0:
            logger.error("set_new_bootloader_config(): Failed to unmount " +
                         mount_point + "! Continuing anyway...")

    #Attempt to clear any stuck logical volumes that may have been created by os-prober.
    CoreTools.start_process("dmsetup remove_all -y", privileged=True)

    #Make sure any LVM volume groups are active.
    for disk in DISK_INFO:
        if "VGName" in DISK_INFO[disk]:
            CoreTools.start_process("vgchange -a y " +
                                    DISK_INFO[disk]["VGName"],
                                    privileged=True)

    logger.debug("set_new_bootloader_config(): Finished setting " +
                 BOOTLOADER_INFO[_os]["Settings"]["NewBootloader"] +
                 "'s config for " + _os + "...")

    wx.CallAfter(
        wx.GetApp().TopWindow.update_output_box, "\n###Finished setting " +
        BOOTLOADER_INFO[_os]["Settings"]["NewBootloader"] + "'s config for " +
        _os + "...###\n")

    wx.CallAfter(wx.GetApp().TopWindow.update_current_operation_text,
                 message="Finished setting " +
                 BOOTLOADER_INFO[_os]["Settings"]["NewBootloader"] +
                 "'s config for " + _os + "!")

    wx.CallAfter(wx.GetApp().TopWindow.update_current_progress, 100)
    return True
Пример #10
0
def install_new_bootloader(_os):
    """Install a new bootloader."""
    logger.info("install_new_bootloader(): Preparing to install " +
                BOOTLOADER_INFO[_os]["Settings"]["NewBootloader"] + " in " +
                _os + "...")

    wx.CallAfter(wx.GetApp().TopWindow.update_current_progress, 52)
    wx.CallAfter(
        wx.GetApp().TopWindow.update_output_box, "\n###Preparing to install " +
        BOOTLOADER_INFO[_os]["Settings"]["NewBootloader"] + " in " + _os +
        "...###\n")

    wx.CallAfter(wx.GetApp().TopWindow.update_current_operation_text,
                 message="Preparing to install " +
                 BOOTLOADER_INFO[_os]["Settings"]["NewBootloader"] + " in " +
                 _os + "...")

    #If this is the current OS, let the installer functions know that we aren't using chroot.
    if OS_INFO[_os]["IsCurrentOS"]:
        logger.debug(
            "install_new_bootloader(): Modifying current OS so not using chroot..."
        )
        use_chroot, unmount_after, mount_point = (False, False, "")

    #Otherwise, setup the chroot and everything else first, and tell them we are using chroot,
    #and pass the mountpoint to them.
    else:
        logger.debug(
            "install_new_bootloader(): Using chroot to modify another OS...")
        use_chroot = True
        mount_point = "/mnt/wxfixboot/mountpoints" + OS_INFO[_os]["Partition"]

        #Check if the partition is mounted.
        unmount_after = not CoreTools.is_mounted(OS_INFO[_os]["Partition"],
                                                 mount_point)

        if unmount_after:
            if CoreTools.mount_partition(partition=OS_INFO[_os]["Partition"],
                                         mount_point=mount_point) != 0:
                logger.error("install_new_bootloader(): Failed to mount " +
                             OS_INFO[_os]["Partition"] +
                             "! Warn the user and skip this OS.")

                DialogTools.show_msg_dlg(
                    kind="error",
                    message="WxFixBoot failed to mount the partition " +
                    "containing " + _os + "! Bootloader installation cannot " +
                    "continue! This may leave your system, or this OS, in " +
                    "an unbootable state. Please close any open programs, " +
                    "then try again when prompted.")

                return False

        #Set up chroot.
        if CoreTools.setup_chroot(mount_point=mount_point) != 0:
            logger.error(
                "install_new_bootloader(): Failed to set up chroot at " +
                mount_point + "! Warning user and giving up...")

            DialogTools.show_msg_dlg(
                kind="error",
                message="WxFixBoot failed to set up a chroot for " + _os +
                "! Giving up. You will be prompted to try again if " +
                "you wish.")
            return False

    #If there's a seperate /boot partition for this OS, make sure it's mounted.
    if OS_INFO[_os]["BootPartition"] != "Unknown":
        if CoreTools.mount_partition(partition=OS_INFO[_os]["BootPartition"],
                                     mount_point=mount_point + "/boot") != 0:
            logger.error("remove_old_bootloader(): Failed to mount " +
                         OS_INFO[_os]["BootPartition"] +
                         "! Warn the user and skip this OS.")

            DialogTools.show_msg_dlg(
                kind="error",
                message="WxFixBoot failed to mount the partition " +
                "containing " + _os + "'s /boot partition! Giving up. " +
                "You will be prompted to try again if you wish.")

            return False

    #Update the package lists.
    if OS_INFO[_os]["PackageManager"] == "apt-get":
        cmd = "sh -c 'DEBIAN_FRONTEND=gnome DISPLAY=:0 apt-get update'"

    elif OS_INFO[_os]["PackageManager"] == "dnf":
        cmd = "dnf check-update"

    if use_chroot:
        cmd = "chroot " + mount_point + " " + cmd

    if CoreTools.start_process(cmd, privileged=True) not in (0, 100):
        logger.error(
            "install_new_bootloader(): Failed to Update the Package Information! "
            + "Continuing anyway...")

        DialogTools.show_msg_dlg(
            kind="error",
            message="WxfixBoot failed to update " + _os +
            "'s package information! Giving up. You will be prompted " +
            "to try again if you wish.")

        return False

    wx.CallAfter(wx.GetApp().TopWindow.update_current_operation_text,
                 message="Installing " +
                 BOOTLOADER_INFO[_os]["Settings"]["NewBootloader"] + " in " +
                 _os + "...")

    wx.CallAfter(wx.GetApp().TopWindow.update_current_progress, 55)
    wx.CallAfter(
        wx.GetApp().TopWindow.update_output_box, "\n###Installing " +
        BOOTLOADER_INFO[_os]["Settings"]["NewBootloader"] + " in " + _os +
        "...###\n")

    #Make sure all GNOME APT frontend dependency is installed.
    if OS_INFO[_os]["PackageManager"] == "apt-get":
        #Ubuntu 16.04.
        cmd = "sh -c 'DEBIAN_FRONTEND=noninteractive apt-get install -y libgnome2-perl'"

        if use_chroot:
            cmd = "chroot " + mount_point + " " + cmd

        retval = CoreTools.start_process(cmd, privileged=True)

        #All newer versions.
        cmd = "sh -c 'DEBIAN_FRONTEND=noninteractive apt-get install -y libgtk3-perl'"

        if use_chroot:
            cmd = "chroot " + mount_point + " " + cmd

        retval = CoreTools.start_process(cmd, privileged=True)

    #Install the bootloader.
    if BOOTLOADER_INFO[_os]["Settings"]["NewBootloader"] == "GRUB2":
        logger.info("install_new_bootloader(): Installing GRUB2...")

        if OS_INFO[_os]["PackageManager"] == "apt-get":
            cmd = "sh -c 'DEBIAN_FRONTEND=gnome DISPLAY=:0 apt-get install -y grub-pc os-prober'"

        elif OS_INFO[_os]["PackageManager"] == "dnf":
            cmd = "dnf -y install grub2"

    elif BOOTLOADER_INFO[_os]["Settings"]["NewBootloader"] == "GRUB-UEFI":
        logger.info("install_new_bootloader(): Installing GRUB-UEFI...")

        #Mount the UEFI partition at mount_point/boot/efi.
        if CoreTools.mount_partition(
                partition=OS_INFO[_os]["EFIPartition"],
                mount_point=mount_point + "/boot/efi") != 0:

            logger.error("install_new_bootloader(): Failed to mount " +
                         OS_INFO[_os]["EFIPartition"] + " to " + mount_point +
                         "/boot/efi! Aborting bootloader installation and " +
                         "warning user...")

            DialogTools.show_msg_dlg(
                kind="error",
                message="WxfixBoot failed to mount the partition containing " +
                _os + "'s EFI partition! Giving up. You will be prompted to " +
                "try again if you wish.")

            return False

        if OS_INFO[_os]["PackageManager"] == "apt-get":
            cmd = "sh -c 'DEBIAN_FRONTEND=gnome DISPLAY=:0 apt-get install -y grub-efi os-prober'"

        elif OS_INFO[_os]["PackageManager"] == "dnf":
            cmd = "dnf -y install grub2-efi-ia32 grub2-efi-x64 shim-x64 "

    if use_chroot:
        cmd = "chroot " + mount_point + " " + cmd

    retval = CoreTools.start_process(cmd, privileged=True)

    if retval != 0:
        logger.error(
            "install_new_bootloader(): Failed to install new bootloader. Warn user..."
        )
        DialogTools.show_msg_dlg(kind="error",
                                 message="WxfixBoot failed to install " + _os +
                                 "'s new bootloader! Continuing anyway...")

    #If there's a seperate EFI partition for this OS, make sure it's unmounted before removing
    #the chroot.
    if OS_INFO[_os]["EFIPartition"] != "Unknown":
        if CoreTools.unmount(mount_point + "/boot/efi") != 0:
            logger.error("install_new_bootloader(): Failed to unmount " +
                         mount_point +
                         "/boot/efi! This probably doesn't matter...")

    #If there's a seperate /boot partition for this OS, make sure it's unmounted before
    #removing the chroot.
    if OS_INFO[_os]["BootPartition"] != "Unknown":
        if CoreTools.unmount(mount_point + "/boot") != 0:
            logger.error("install_new_bootloader(): Failed to unmount " +
                         mount_point +
                         "/boot! This probably doesn't matter...")

    if use_chroot:
        logger.debug("install_new_bootloader(): Removing chroot...")

        #Tear down chroot.
        if CoreTools.teardown_chroot(mount_point=mount_point) != 0:
            logger.error(
                "install_new_bootloader(): Failed to remove chroot at " +
                mount_point + "! Attempting to continue anyway...")

    if unmount_after:
        if CoreTools.unmount(mount_point) != 0:
            logger.error("install_new_bootloader(): Failed to unmount " +
                         mount_point + "! Continuing anyway...")

    if retval != 0:
        #Something went wrong! Log it and notify the user.
        logger.error(
            "install_new_bootloader(): Failed to install " +
            BOOTLOADER_INFO[_os]["Settings"]["NewBootloader"] + " in " + _os +
            "! This may mean the system (or this OS) is now unbootable! " +
            "Warning the user and asking to try again.")

        DialogTools.show_msg_dlg(
            kind="error",
            message="WxFixBoot failed to install " +
            BOOTLOADER_INFO[_os]["Settings"]["NewBootloader"] + " in " + _os +
            "! This may leave this OS, or your system, in an unbootable " +
            "state. You will now be prompted to try again.")

        return False

    wx.CallAfter(
        wx.GetApp().TopWindow.update_output_box, "\n###Finished installing " +
        BOOTLOADER_INFO[_os]["Settings"]["NewBootloader"] + " in " + _os +
        "...###\n")

    #Attempt to clear any stuck logical volumes that may have been created by os-prober.
    CoreTools.start_process("dmsetup remove_all -y", privileged=True)

    #Make sure any LVM volume groups are active.
    for disk in DISK_INFO:
        if "VGName" in DISK_INFO[disk]:
            CoreTools.start_process("vgchange -a y " +
                                    DISK_INFO[disk]["VGName"],
                                    privileged=True)

    #Log and notify the user that we're finished installing the bootloader.
    logger.info("install_new_bootloader(): Finished installing " +
                BOOTLOADER_INFO[_os]["Settings"]["NewBootloader"] + "...")

    wx.CallAfter(wx.GetApp().TopWindow.update_current_operation_text,
                 message="Finish installing " +
                 BOOTLOADER_INFO[_os]["Settings"]["NewBootloader"] + " in " +
                 _os + "...")

    wx.CallAfter(wx.GetApp().TopWindow.update_current_progress, 75)
    return True
Пример #11
0
def remove_old_bootloader(_os):
    """Remove the currently installed bootloader."""
    logger.info("remove_old_bootloader(): Removing " +
                BOOTLOADER_INFO[_os]["Bootloader"] + " from " + _os + "...")

    wx.CallAfter(wx.GetApp().TopWindow.update_current_progress, 27)
    wx.CallAfter(wx.GetApp().TopWindow.update_current_operation_text,
                 message="Removing " + BOOTLOADER_INFO[_os]["Bootloader"] +
                 " from " + _os + "......")

    wx.CallAfter(
        wx.GetApp().TopWindow.update_output_box, "\n###Removing " +
        BOOTLOADER_INFO[_os]["Bootloader"] + " from " + _os + "...###\n")

    #If this is the current OS, let the remover function know that we aren't using chroot.
    if OS_INFO[_os]["IsCurrentOS"]:
        logger.debug(
            "remove_old_bootloader(): Modifying current OS so not using chroot..."
        )
        use_chroot, unmount_after, mount_point = (False, False, "")

    else:
        logger.debug(
            "remove_old_bootloader(): Using chroot to modify another OS...")
        use_chroot = True
        mount_point = "/mnt/wxfixboot/mountpoints" + OS_INFO[_os]["Partition"]

        #Check if the partition is mounted.
        unmount_after = not CoreTools.is_mounted(OS_INFO[_os]["Partition"],
                                                 mount_point)

        if unmount_after:
            #Mount the partition using the global mount function.
            if CoreTools.mount_partition(partition=OS_INFO[_os]["Partition"],
                                         mount_point=mount_point) != 0:

                logger.error("remove_old_bootloader(): Failed to mount " +
                             OS_INFO[_os]["Partition"] +
                             "! Warning the user and giving up...")

                DialogTools.show_msg_dlg(
                    kind="error",
                    message="WxFixBoot failed to mount the partition " +
                    "containing " + _os +
                    "! Giving up. You will be prompted " +
                    "to try again if you wish.")

                return False

        #Set up chroot.
        if CoreTools.setup_chroot(mount_point) != 0:
            logger.error(
                "remove_old_bootloader(): Failed to set up chroot at " +
                mount_point + "! Giving up...")

            DialogTools.show_msg_dlg(
                kind="error",
                message="WxFixBoot failed to set up a chroot for " + _os +
                "! Giving up. You will be prompted to try again if " +
                "you wish.")
            return False

    #Mount a /boot partition if it exists.
    if OS_INFO[_os]["BootPartition"] != "Unknown":
        if CoreTools.mount_partition(OS_INFO[_os]["BootPartition"],
                                     mount_point + "/boot") != 0:
            logger.error("remove_old_bootloader(): Failed to mount " + _os +
                         "'s /boot partition! " +
                         "Skipping bootloader removal for this OS.")

            DialogTools.show_msg_dlg(
                kind="error",
                message="WxFixBoot failed to mount the partition containing " +
                _os + "'s /boot partition! Giving up. You will be prompted " +
                "to try again if you wish.")

            if not OS_INFO[_os]["IsCurrentOS"]:
                CoreTools.teardown_chroot(mount_point)
                CoreTools.unmount(mount_point)

            return False

    #Mount the UEFI partition at mount_point/boot/efi, if it exists.
    if OS_INFO[_os]["EFIPartition"] != "Unknown":
        if CoreTools.mount_partition(
                partition=OS_INFO[_os]["EFIPartition"],
                mount_point=mount_point + "/boot/efi") != 0:
            logger.error("remove_old_bootloader(): Failed to mount " +
                         OS_INFO[_os]["EFIPartition"] + "! to " + mount_point +
                         "/boot/efi! Aborting bootloader installation and " +
                         "warning user...")

            DialogTools.show_msg_dlg(
                kind="error",
                message="WxfixBoot failed to mount the partition containing " +
                _os + "'s EFI partition! Giving up. You will be prompted to " +
                "try again if you wish.")

            return False

    #Wait until no other application is using APT/DNF.
    #Let user know what's happening.
    wx.CallAfter(wx.GetApp().TopWindow.update_current_progress, 27)
    wx.CallAfter(
        wx.GetApp().TopWindow.update_current_operation_text,
        message="Waiting until " + _os +
        "'s package manager is free.\nClose any open applications if this " +
        "message persists...")

    wx.CallAfter(
        wx.GetApp().TopWindow.update_output_box,
        "\n###Waiting until " + _os + "'s package manager is free...###\n")

    logger.debug("remove_old_bootloader(): Waiting until " + _os +
                 "'s package manager is free...")
    HelperBackendTools.wait_until_packagemanager_free(mount_point=mount_point,
                                                      package_manager=\
                                                      OS_INFO[_os]["PackageManager"])

    wx.CallAfter(wx.GetApp().TopWindow.update_current_progress, 27)
    wx.CallAfter(wx.GetApp().TopWindow.update_current_operation_text,
                 message="Removing " + BOOTLOADER_INFO[_os]["Bootloader"] +
                 " from " + _os + "...")

    wx.CallAfter(
        wx.GetApp().TopWindow.update_output_box, "\n###Removing " +
        BOOTLOADER_INFO[_os]["Bootloader"] + " from " + _os + "...###\n")

    #Make sure the GNOME APT frontend dependency is installed.
    if OS_INFO[_os]["PackageManager"] == "apt-get":
        #Ubuntu 16.04.
        cmd = "sh -c 'DEBIAN_FRONTEND=noninteractive apt-get install -y libgnome2-perl'"

        if use_chroot:
            cmd = "chroot " + mount_point + " " + cmd

        retval = CoreTools.start_process(cmd, privileged=True)

        #All newer versions.
        cmd = "sh -c 'DEBIAN_FRONTEND=noninteractive apt-get install -y libgtk3-perl'"

        if use_chroot:
            cmd = "chroot " + mount_point + " " + cmd

        retval = CoreTools.start_process(cmd, privileged=True)

    #Remove the bootloader.
    if BOOTLOADER_INFO[_os]["Bootloader"] == "GRUB2":
        logger.info("remove_old_bootloader(): Removing GRUB2...")

        if OS_INFO[_os]["PackageManager"] == "apt-get":
            cmd = "sh -c 'DEBIAN_FRONTEND=gnome DISPLAY=:0 apt-get purge -y " \
                  "--allow-remove-essential grub-pc grub-pc-bin grub-common'"

        elif OS_INFO[_os]["PackageManager"] == "dnf":
            cmd = "dnf -y remove grub2"

    elif BOOTLOADER_INFO[_os]["Bootloader"] == "GRUB-UEFI":
        logger.info("remove_old_bootloader(): Removing GRUB-UEFI...")

        if OS_INFO[_os]["PackageManager"] == "apt-get":
            cmd = "sh -c 'DEBIAN_FRONTEND=gnome DISPLAY=:0 apt-get purge -y " \
                  "--allow-remove-essential grub-efi grub-efi-amd64 grub-efi-amd64-bin" \
                  " grub-efi-ia32 grub-efi-ia32-bin grub-common grub2-common'"

        elif OS_INFO[_os]["PackageManager"] == "dnf":
            cmd = "dnf -y remove grub2-efi-x64 grub2-efi-ia32 shim-x64"

    else:
        #Bootloader is unknown. Just output a warning message.
        logger.warning(
            "remove_old_bootloader(): Cannot remove unknown bootloader! " +
            "Continuing anyway...")

        cmd = "echo 'WARNING: Bootloader is " \
              "unknown, cannot remove. Continuing anyway...'"

    if use_chroot:
        cmd = "chroot " + mount_point + " " + cmd

    retval = CoreTools.start_process(cmd, privileged=True)

    if retval != 0:
        logger.error("remove_old_bootloader(): Failed to remove " +
                     BOOTLOADER_INFO[_os]["Bootloader"] + " from " + _os +
                     "! Warning user...")

        DialogTools.show_msg_dlg(kind="error",
                                 message="WxFixBoot failed to remove " +
                                 BOOTLOADER_INFO[_os]["Bootloader"] +
                                 " from " + _os + "!")
        return False

    #If there's a seperate EFI partition for this OS, make sure it's unmounted before removing
    #the chroot.
    if OS_INFO[_os]["EFIPartition"] != "Unknown":
        if CoreTools.unmount(mount_point + "/boot/efi") != 0:
            logger.error("remove_old_bootloader(): Failed to unmount " +
                         mount_point +
                         "/boot/efi! This probably doesn't matter...")

    #unmount a /boot partition if it exists.
    if OS_INFO[_os]["BootPartition"] != "Unknown":
        if CoreTools.unmount(mount_point + "/boot") != 0:
            logger.error("remove_old_bootloader(): Failed to unmount " + _os +
                         "'s /boot partition! Continuing anyway...")

    #Tear down chroot if needed.
    if use_chroot:
        if CoreTools.teardown_chroot(mount_point=mount_point) != 0:
            logger.error(
                "remove_old_bootloader(): Failed to remove chroot at " +
                mount_point + "! Attempting to continue anyway...")

    #unmount partition if needed.
    if unmount_after:
        if CoreTools.unmount(mount_point) != 0:
            logger.error("remove_old_bootloader(): Couldn't unmount " +
                         mount_point + "! Continuing anyway...")

    wx.CallAfter(
        wx.GetApp().TopWindow.update_output_box, "\n###Finished removing " +
        BOOTLOADER_INFO[_os]["Bootloader"] + " from " + _os + "...###\n")

    if retval != 0:
        #Something went wrong! Log it and notify the user.
        logger.error("remove_old_bootloader(): Failed to remove " +
                     BOOTLOADER_INFO[_os]["Bootloader"] + " from " + _os +
                     "! We'll continue anyway. Warn the user.")

        DialogTools.show_msg_dlg(
            kind="error",
            message="WxFixBoot failed to remove " +
            BOOTLOADER_INFO[_os]["Bootloader"] + " from " + _os +
            "! This probably doesn't matter; when we install the new " +
            "bootloader, it should take precedence over the old one " +
            "anyway. Make sure you check that " + _os + " boots correctly " +
            "after WxFixBoot finishes its operations. Reinstalling the " +
            "bootloader again afterwards is recommended.")

    #Attempt to clear any stuck logical volumes that may have been created by os-prober.
    CoreTools.start_process("dmsetup remove_all -y", privileged=True)

    #Make sure any LVM volume groups are active.
    for disk in DISK_INFO:
        if "VGName" in DISK_INFO[disk]:
            CoreTools.start_process("vgchange -a y " +
                                    DISK_INFO[disk]["VGName"],
                                    privileged=True)

    #Log and notify the user that we're finished removing bootloaders.
    logger.info("remove_old_bootloader(): Finished removing " +
                BOOTLOADER_INFO[_os]["Bootloader"] + "...")

    wx.CallAfter(wx.GetApp().TopWindow.update_current_operation_text,
                 message="Finished removing " +
                 BOOTLOADER_INFO[_os]["Bootloader"] + " from " + _os +
                 "......")

    wx.CallAfter(wx.GetApp().TopWindow.update_current_progress, 50)

    return True
Пример #12
0
def set_grub2_config(_os, filetoopen, bootloader_timeout, kernel_options, package_manager):
    """Set GRUB2 config."""
    logger.info("set_grub2_config(): Setting GRUB2 Config in "+filetoopen+"...")
    set_timeout, set_kernel_options, set_default = (False, False, False)

    #Match the bootloader-specific default OS to WxFixBoot's OSs by partition.
    logger.info("set_grub2_config(): Attempting to match the WxFixBoot's default OS for this "
                + "bootloader to any OS that GRUB2 detected...")

    #Find the ID for the menu entry that correspondes to that OS (Main Menu only to avoid
    #recovery options + misc).
    bootloader_specific_default_os = "Unknown"

    for entry in BOOTLOADER_INFO[_os]["NewMenuEntries"]["MainMenu"]["Order"]:
        if HelperBackendTools.partition_matches_os(BOOTLOADER_INFO[_os]["NewMenuEntries"]["MainMenu"][entry]["Partition"],
                                                   BOOTLOADER_INFO[_os]["Settings"]["DefaultOS"]):
            bootloader_specific_default_os = \
            BOOTLOADER_INFO[_os]["NewMenuEntries"]["MainMenu"][entry]["ID"]

            logger.info("set_grub2_config(): Found Default OS's GRUB2 ID...")
            break

    #Log if we couldn't match them.
    if bootloader_specific_default_os == "Unknown":
        logger.warning("set_grub2_config(): Couldn't match! We will instead pick the 1st menu "
                       + "entry. Warning user...")

        DialogTools.show_msg_dlg(message="Couldn't match the default OS you picked to any that "
                                 + BOOTLOADER_INFO[_os]["Settings"]["NewBootloader"]
                                 + " has detected! As a fallback, the first "
                                 + "menu entry will be the default. Click okay to continue...")

        bootloader_specific_default_os = "0"

    #Open the file in read mode, so we can find the new config that needs setting. Also, use a
    #list to temporarily store the modified lines.
    logger.debug("set_grub2_config(): Attempting to modify existing lines in the config file "
                 + "first, without making any new ones...")

    config_file = CoreTools.read_privileged_file(filetoopen)

    new_file_contents = []

    #Loop through each line in the file, paying attention only to the important ones.
    for line in config_file:
        #Look for the timeout setting.
        if 'GRUB_TIMEOUT' in line and '=' in line and set_timeout is False:
            #Found it! Set the value to the current value of bootloader_timeout.
            logger.debug("set_grub2_config(): Found GRUB_TIMEOUT, setting it to '"
                         + str(bootloader_timeout)+"'...")

            set_timeout = True
            line = "GRUB_TIMEOUT="+str(bootloader_timeout)

        #Look for kernel options setting.
        elif 'GRUB_CMDLINE_LINUX_DEFAULT' in line and '=' in line and set_kernel_options is False:
            #Found it! Set it to the options in kernel_options, carefully making sure we aren't
            #double-quoting it.
            logger.debug("set_grub2_config(): Found GRUB_CMDLINE_LINUX_DEFAULT, setting it to '"
                         + kernel_options+"'...")

            set_kernel_options = True
            line = "GRUB_CMDLINE_LINUX_DEFAULT='"+kernel_options+"'"

        #Look for the "GRUB_DEFAULT" setting.
        elif "GRUB_DEFAULT" in line and '=' in line and set_default is False:
            #Found it. Set it to 'saved', so we can set the default bootloader.
            logger.debug("set_grub2_config(): Found GRUB_DEFAULT, setting it to '"
                         + bootloader_specific_default_os+"' (ID of default OS)...")

            set_default = True
            line = "GRUB_DEFAULT="+bootloader_specific_default_os

        #Comment out the GRUB_HIDDEN_TIMEOUT line.
        elif 'GRUB_HIDDEN_TIMEOUT' in line and 'GRUB_HIDDEN_TIMEOUT_QUIET' not in line \
            and '=' in line and '#' not in line:

            logger.debug("set_grub2_config(): Commenting out GRUB_HIDDEN_TIMEOUT...")
            line = "#"+line

        #Comment out the GRUB_CMDLINE_LINUX line, unless on Fedora.
        elif 'GRUB_CMDLINE_LINUX' in line and 'GRUB_CMDLINE_LINUX_DEFAULT' not in line \
            and '=' in line and '#' not in line:

            if package_manager == "apt-get":
                logger.debug("set_grub2_config(): Commenting out GRUB_CMDLINE_LINUX...")
                line = "#"+line

            elif package_manager == "dnf":
                #Found it! Set it to the options in kernel_options, carefully making sure we aren't
                #double-quoting it.
                logger.debug("set_grub2_config(): Found GRUB_CMDLINE_LINUX, setting it to '"
                             + kernel_options+"'...")

                set_kernel_options = True
                line = "GRUB_CMDLINE_LINUX='"+kernel_options+"'"

        new_file_contents.append(line+"\n")

    #Check that everything was set. If not, write that config now.
    if set_timeout is False:
        logger.debug("set_grub2_config(): Didn't find GRUB_TIMEOUT in config file. "
                     + "Creating and setting it to '"+str(bootloader_timeout)+"'...")

        new_file_contents.append("GRUB_TIMEOUT="+str(bootloader_timeout)+"\n")

    if set_kernel_options is False:
        temp = kernel_options.replace('\"', '').replace("\'", "").replace("\n", "")
        logger.debug("set_grub2_config(): Didn't find GRUB_CMDLINE_LINUX_DEFAULT in config file. "
                     + "Creating and setting it to '"+kernel_options+"'...")

        if package_manager == "apt-get":
            new_file_contents.append("GRUB_CMDLINE_LINUX_DEFAULT='"+temp+"'\n")

        elif package_manager == "dnf":
            new_file_contents.append("GRUB_CMDLINE_LINUX='"+temp+"'\n")

    if set_default is False:
        logger.debug("set_grub2_config(): Didn't find GRUB_DEFAULT in config file. "
                     + "Creating and setting it to 'saved'...")

        new_file_contents.append("GRUB_DEFAULT="+bootloader_specific_default_os+"\n")

    #Write the finished lines to the file.
    logger.info("set_grub2_config(): Writing new config to file...")
    CoreTools.write_privileged_file(filetoopen, ''.join(new_file_contents))

    logger.info("set_grub2_config(): Done!")