def suggest_swap_size(quiet=False, hibernation=False, disk_space=None): """Suggest the size of the swap partition that will be created. :param bool quiet: whether to log size information or not :param bool hibernation: calculate swap size big enough for hibernation :param disk_space: how much disk space is available :return: calculated swap size """ mem = total_memory() mem = ((mem / 16) + 1) * 16 if not quiet: log.info("Detected %s of memory", mem) sixty_four_gib = Size("64 GiB") # the succeeding if-statement implements the following formula for # suggested swap size. # # swap(mem) = 2 * mem, if mem < 2 GiB # = mem, if 2 GiB <= mem < 8 GiB # = mem / 2, if 8 GIB <= mem < 64 GiB # = 4 GiB, if mem >= 64 GiB if mem < Size("2 GiB"): swap = 2 * mem elif mem < Size("8 GiB"): swap = mem elif mem < sixty_four_gib: swap = mem / 2 else: swap = Size("4 GiB") if hibernation: if mem <= sixty_four_gib: swap = mem + swap else: log.info( "Ignoring --hibernation option on systems with %s of RAM or more", sixty_four_gib) if disk_space is not None and not hibernation: max_swap = disk_space * MAX_SWAP_DISK_RATIO if swap > max_swap: log.info( "Suggested swap size (%(swap)s) exceeds %(percent)d %% of " "disk space, using %(percent)d %% of disk space (%(size)s) " "instead.", { "percent": MAX_SWAP_DISK_RATIO * 100, "swap": swap, "size": max_swap }) swap = max_swap if not quiet: log.info("Swap attempt of %s", swap) return swap
def verify_swap(storage, constraints, report_error, report_warning): """ Verify the existence of swap. :param storage: a storage to check :param constraints: a dictionary of constraints :param report_error: a function for error reporting :param report_warning: a function for warning reporting """ swaps = storage.fsset.swap_devices if not swaps: installed = util.total_memory() required = Size("%s MiB" % (constraints[STORAGE_MIN_RAM] + isys.NO_SWAP_EXTRA_RAM)) if not constraints[STORAGE_SWAP_IS_RECOMMENDED]: if installed < required: report_warning(_("You have not specified a swap partition. " "%(requiredMem)s of memory is recommended to continue " "installation without a swap partition, but you only " "have %(installedMem)s.") % {"requiredMem": required, "installedMem": installed}) else: if installed < required: report_error(_("You have not specified a swap partition. " "%(requiredMem)s of memory is required to continue " "installation without a swap partition, but you only " "have %(installedMem)s.") % {"requiredMem": required, "installedMem": installed}) else: report_warning(_("You have not specified a swap partition. " "Although not strictly required in all cases, " "it will significantly improve performance " "for most installations."))
def swap_suggestion(quiet=False, hibernation=False, disk_space=None): """ Suggest the size of the swap partition that will be created. :param quiet: whether to log size information or not :type quiet: bool :param hibernation: calculate swap size big enough for hibernation :type hibernation: bool :param disk_space: how much disk space is available :type disk_space: :class:`blivet.size.Size` :return: calculated swap size """ mem = util.total_memory() mem = ((mem / 16) + 1) * 16 if not quiet: log.info("Detected %s of memory", mem) sixtyfour_GiB = Size("64 GiB") # the succeeding if-statement implements the following formula for # suggested swap size. # # swap(mem) = 2 * mem, if mem < 2 GiB # = mem, if 2 GiB <= mem < 8 GiB # = mem / 2, if 8 GIB <= mem < 64 GiB # = 4 GiB, if mem >= 64 GiB if mem < Size("2 GiB"): swap = 2 * mem elif mem < Size("8 GiB"): swap = mem elif mem < sixtyfour_GiB: swap = mem / 2 else: swap = Size("4 GiB") if hibernation: if mem <= sixtyfour_GiB: swap = mem + swap else: log.info("Ignoring --hibernation option on systems with %s of RAM or more", sixtyfour_GiB) if disk_space is not None and not hibernation: max_swap = disk_space * MAX_SWAP_DISK_RATIO if swap > max_swap: log.info("Suggested swap size (%(swap)s) exceeds %(percent)d %% of " "disk space, using %(percent)d %% of disk space (%(size)s) " "instead.", {"percent": MAX_SWAP_DISK_RATIO * 100, "swap": swap, "size": max_swap}) swap = max_swap if not quiet: log.info("Swap attempt of %s", swap) return swap
def verify_swap(storage, constraints, report_error, report_warning): """ Verify the existence of swap. :param storage: a storage to check :param constraints: a dictionary of constraints :param report_error: a function for error reporting :param report_warning: a function for warning reporting """ swaps = storage.fsset.swap_devices if not swaps: installed = util.total_memory() required = Size( "%s MiB" % (constraints[STORAGE_MIN_RAM] + isys.NO_SWAP_EXTRA_RAM)) if not constraints[STORAGE_SWAP_IS_RECOMMENDED]: if installed < required: report_warning( _("You have not specified a swap partition. " "%(requiredMem)s of memory is recommended to continue " "installation without a swap partition, but you only " "have %(installedMem)s.") % { "requiredMem": required, "installedMem": installed }) else: if installed < required: report_error( _("You have not specified a swap partition. " "%(requiredMem)s of memory is required to continue " "installation without a swap partition, but you only " "have %(installedMem)s.") % { "requiredMem": required, "installedMem": installed }) else: report_warning( _("You have not specified a swap partition. " "Although not strictly required in all cases, " "it will significantly improve performance " "for most installations.")) else: swap_space = sum((device.size for device in swaps), Size(0)) disk_space = sum( (device.size for device in storage.mountpoints.values()), Size(0)) recommended = swap_suggestion(disk_space=disk_space, quiet=True) log.debug("Total swap space: %s", swap_space) log.debug("Used disk space: %s", disk_space) log.debug("Recommended swaps space: %s", recommended) if swap_space < recommended: report_warning( _("Your swap space is less than %(size)s " "which is lower than recommended.") % {"size": recommended})
def verify_swap(storage, constraints, report_error, report_warning): """ Verify the existence of swap. :param storage: a storage to check :param constraints: a dictionary of constraints :param report_error: a function for error reporting :param report_warning: a function for warning reporting """ swaps = storage.fsset.swap_devices if not swaps: installed = util.total_memory() required = Size("%s MiB" % (constraints[STORAGE_MIN_RAM] + isys.NO_SWAP_EXTRA_RAM)) if not constraints[STORAGE_SWAP_IS_RECOMMENDED]: if installed < required: report_warning(_("You have not specified a swap partition. " "%(requiredMem)s of memory is recommended to continue " "installation without a swap partition, but you only " "have %(installedMem)s.") % {"requiredMem": required, "installedMem": installed}) else: if installed < required: report_error(_("You have not specified a swap partition. " "%(requiredMem)s of memory is required to continue " "installation without a swap partition, but you only " "have %(installedMem)s.") % {"requiredMem": required, "installedMem": installed}) else: report_warning(_("You have not specified a swap partition. " "Although not strictly required in all cases, " "it will significantly improve performance " "for most installations.")) else: swap_space = sum((device.size for device in swaps), Size(0)) disk_space = sum((device.size for device in storage.mountpoints.values()), Size(0)) recommended = swap_suggestion(disk_space=disk_space, quiet=True) log.debug("Total swap space: %s", swap_space) log.debug("Used disk space: %s", disk_space) log.debug("Recommended swaps space: %s", recommended) if swap_space < recommended: report_warning(_("Your swap space is less than %(size)s " "which is lower than recommended.") % {"size": recommended})
def sanity_check(storage, min_ram=isys.MIN_RAM): """ Run a series of tests to verify the storage configuration. This function is called at the end of partitioning so that we can make sure you don't have anything silly (like no /, a really small /, etc). :param storage: an instance of the :class:`blivet.Blivet` class to check :param min_ram: minimum RAM (in MiB) needed for the installation with swap space available :rtype: a list of SanityExceptions :return: a list of accumulated errors and warnings """ exns = [] checkSizes = [('/usr', Size("250 MiB")), ('/tmp', Size("50 MiB")), ('/var', Size("384 MiB")), ('/home', Size("100 MiB")), ('/boot', Size("200 MiB"))] mustbeonlinuxfs = ['/', '/var', '/tmp', '/usr', '/home', '/usr/share', '/usr/lib'] mustbeonroot = ['/bin', '/dev', '/sbin', '/etc', '/lib', '/root', '/mnt', 'lost+found', '/proc'] filesystems = storage.mountpoints root = storage.fsset.rootDevice swaps = storage.fsset.swapDevices if root: if root.size < Size("250 MiB"): exns.append( SanityWarning(_("Your root partition is less than 250 " "megabytes which is usually too small to " "install %s.") % (productName,))) else: exns.append( SanityError(_("You have not defined a root partition (/), " "which is required for installation of %s " "to continue.") % (productName,))) # Prevent users from installing on s390x with (a) no /boot volume, (b) the # root volume on LVM, and (c) the root volume not restricted to a single # PV # NOTE: There is not really a way for users to create a / volume # restricted to a single PV. The backend support is there, but there are # no UI hook-ups to drive that functionality, but I do not personally # care. --dcantrell if arch.isS390() and '/boot' not in storage.mountpoints and root: if root.type == 'lvmlv' and not root.singlePV: exns.append( SanityError(_("This platform requires /boot on a dedicated " "partition or logical volume. If you do not " "want a /boot volume, you must place / on a " "dedicated non-LVM partition."))) # FIXME: put a check here for enough space on the filesystems. maybe? for (mount, size) in checkSizes: if mount in filesystems and filesystems[mount].size < size: exns.append( SanityWarning(_("Your %(mount)s partition is less than " "%(size)s which is lower than recommended " "for a normal %(productName)s install.") % {'mount': mount, 'size': size, 'productName': productName})) for (mount, device) in filesystems.items(): problem = filesystems[mount].checkSize() if problem < 0: exns.append( SanityError(_("Your %(mount)s partition is too small for %(format)s formatting " "(allowable size is %(minSize)s to %(maxSize)s)") % {"mount": mount, "format": device.format.name, "minSize": device.minSize, "maxSize": device.maxSize})) elif problem > 0: exns.append( SanityError(_("Your %(mount)s partition is too large for %(format)s formatting " "(allowable size is %(minSize)s to %(maxSize)s)") % {"mount":mount, "format": device.format.name, "minSize": device.minSize, "maxSize": device.maxSize})) if storage.bootloader and not storage.bootloader.skip_bootloader: stage1 = storage.bootloader.stage1_device if not stage1: exns.append( SanityError(_("No valid boot loader target device found. " "See below for details."))) pe = _platform.stage1MissingError if pe: exns.append(SanityError(_(pe))) else: storage.bootloader.is_valid_stage1_device(stage1) exns.extend(SanityError(msg) for msg in storage.bootloader.errors) exns.extend(SanityWarning(msg) for msg in storage.bootloader.warnings) stage2 = storage.bootloader.stage2_device if stage1 and not stage2: exns.append(SanityError(_("You have not created a bootable partition."))) else: storage.bootloader.is_valid_stage2_device(stage2) exns.extend(SanityError(msg) for msg in storage.bootloader.errors) exns.extend(SanityWarning(msg) for msg in storage.bootloader.warnings) if not storage.bootloader.check(): exns.extend(SanityError(msg) for msg in storage.bootloader.errors) # # check that GPT boot disk on BIOS system has a BIOS boot partition # if _platform.weight(fstype="biosboot") and \ stage1 and stage1.isDisk and \ getattr(stage1.format, "labelType", None) == "gpt": missing = True for part in [p for p in storage.partitions if p.disk == stage1]: if part.format.type == "biosboot": missing = False break if missing: exns.append( SanityError(_("Your BIOS-based system needs a special " "partition to boot from a GPT disk label. " "To continue, please create a 1MiB " "'biosboot' type partition."))) if not swaps: installed = util.total_memory() required = Size("%s MiB" % (min_ram + isys.NO_SWAP_EXTRA_RAM)) if installed < required: exns.append( SanityError(_("You have not specified a swap partition. " "%(requiredMem)s of memory is required to continue installation " "without a swap partition, but you only have %(installedMem)s.") % {"requiredMem": required, "installedMem": installed})) else: exns.append( SanityWarning(_("You have not specified a swap partition. " "Although not strictly required in all cases, " "it will significantly improve performance " "for most installations."))) no_uuid = [s for s in swaps if s.format.exists and not s.format.uuid] if no_uuid: exns.append( SanityWarning(_("At least one of your swap devices does not have " "a UUID, which is common in swap space created " "using older versions of mkswap. These devices " "will be referred to by device path in " "/etc/fstab, which is not ideal since device " "paths can change under a variety of " "circumstances. "))) for (mountpoint, dev) in filesystems.items(): if mountpoint in mustbeonroot: exns.append( SanityError(_("This mount point is invalid. The %s directory must " "be on the / file system.") % mountpoint)) if mountpoint in mustbeonlinuxfs and (not dev.format.mountable or not dev.format.linuxNative): exns.append( SanityError(_("The mount point %s must be on a linux file system.") % mountpoint)) if storage.rootDevice and storage.rootDevice.format.exists: e = storage.mustFormat(storage.rootDevice) if e: exns.append(SanityError(e)) exns += verify_LUKS_devices_have_key(storage) return exns
def sanity_check(storage, min_ram=isys.MIN_RAM): """ Run a series of tests to verify the storage configuration. This function is called at the end of partitioning so that we can make sure you don't have anything silly (like no /, a really small /, etc). :param storage: an instance of the :class:`blivet.Blivet` class to check :param min_ram: minimum RAM (in MiB) needed for the installation with swap space available :rtype: a list of SanityExceptions :return: a list of accumulated errors and warnings """ exns = [] checkSizes = [('/usr', Size("250 MiB")), ('/tmp', Size("50 MiB")), ('/var', Size("384 MiB")), ('/home', Size("100 MiB")), ('/boot', Size("200 MiB"))] mustbeonlinuxfs = [ '/', '/var', '/tmp', '/usr', '/home', '/usr/share', '/usr/lib' ] mustbeonroot = [ '/bin', '/dev', '/sbin', '/etc', '/lib', '/root', '/mnt', 'lost+found', '/proc' ] filesystems = storage.mountpoints root = storage.fsset.rootDevice swaps = storage.fsset.swapDevices if root: if root.size < Size("250 MiB"): exns.append( SanityWarning( _("Your root partition is less than 250 " "megabytes which is usually too small to " "install %s.") % (productName, ))) else: exns.append( SanityError( _("You have not defined a root partition (/), " "which is required for installation of %s " "to continue.") % (productName, ))) # FIXME: put a check here for enough space on the filesystems. maybe? for (mount, size) in checkSizes: if mount in filesystems and filesystems[mount].size < size: exns.append( SanityWarning( _("Your %(mount)s partition is less than " "%(size)s which is lower than recommended " "for a normal %(productName)s install.") % { 'mount': mount, 'size': size, 'productName': productName })) for (mount, device) in filesystems.items(): problem = filesystems[mount].checkSize() if problem < 0: exns.append( SanityError( _("Your %(mount)s partition is too small for %(format)s formatting " "(allowable size is %(minSize)s to %(maxSize)s)") % { "mount": mount, "format": device.format.name, "minSize": device.minSize, "maxSize": device.maxSize })) elif problem > 0: exns.append( SanityError( _("Your %(mount)s partition is too large for %(format)s formatting " "(allowable size is %(minSize)s to %(maxSize)s)") % { "mount": mount, "format": device.format.name, "minSize": device.minSize, "maxSize": device.maxSize })) if storage.bootloader and not storage.bootloader.skip_bootloader: stage1 = storage.bootloader.stage1_device if not stage1: exns.append( SanityError( _("No valid boot loader target device found. " "See below for details."))) pe = _platform.stage1MissingError if pe: exns.append(SanityError(_(pe))) else: storage.bootloader.is_valid_stage1_device(stage1) exns.extend(SanityError(msg) for msg in storage.bootloader.errors) exns.extend( SanityWarning(msg) for msg in storage.bootloader.warnings) stage2 = storage.bootloader.stage2_device if stage1 and not stage2: exns.append( SanityError(_("You have not created a bootable partition."))) else: storage.bootloader.is_valid_stage2_device(stage2) exns.extend(SanityError(msg) for msg in storage.bootloader.errors) exns.extend( SanityWarning(msg) for msg in storage.bootloader.warnings) if not storage.bootloader.check(): exns.extend( SanityError(msg) for msg in storage.bootloader.errors) # # check that GPT boot disk on BIOS system has a BIOS boot partition # if _platform.weight(fstype="biosboot") and \ stage1 and stage1.isDisk and \ getattr(stage1.format, "labelType", None) == "gpt": missing = True for part in [p for p in storage.partitions if p.disk == stage1]: if part.format.type == "biosboot": missing = False break if missing: exns.append( SanityError( _("Your BIOS-based system needs a special " "partition to boot from a GPT disk label. " "To continue, please create a 1MiB " "'biosboot' type partition."))) if not swaps: installed = util.total_memory() required = Size("%s MiB" % (min_ram + isys.NO_SWAP_EXTRA_RAM)) if installed < required: exns.append( SanityError( _("You have not specified a swap partition. " "%(requiredMem)s of memory is required to continue installation " "without a swap partition, but you only have %(installedMem)s." ) % { "requiredMem": required, "installedMem": installed })) else: exns.append( SanityWarning( _("You have not specified a swap partition. " "Although not strictly required in all cases, " "it will significantly improve performance " "for most installations."))) no_uuid = [s for s in swaps if s.format.exists and not s.format.uuid] if no_uuid: exns.append( SanityWarning( _("At least one of your swap devices does not have " "a UUID, which is common in swap space created " "using older versions of mkswap. These devices " "will be referred to by device path in " "/etc/fstab, which is not ideal since device " "paths can change under a variety of " "circumstances. "))) for (mountpoint, dev) in filesystems.items(): if mountpoint in mustbeonroot: exns.append( SanityError( _("This mount point is invalid. The %s directory must " "be on the / file system.") % mountpoint)) if mountpoint in mustbeonlinuxfs and (not dev.format.mountable or not dev.format.linuxNative): exns.append( SanityError( _("The mount point %s must be on a linux file system.") % mountpoint)) if storage.rootDevice and storage.rootDevice.format.exists: e = storage.mustFormat(storage.rootDevice) if e: exns.append(SanityError(e)) exns += verify_LUKS_devices_have_key(storage) return exns