def _clear_partitions(self, storage): """Clear partitions. :param storage: an instance of Blivet """ disk_init_proxy = STORAGE.get_proxy(DISK_INITIALIZATION) storage.config.clear_part_type = disk_init_proxy.InitializationMode storage.config.clear_part_disks = disk_init_proxy.DrivesToClear storage.config.clear_part_devices = disk_init_proxy.DevicesToClear storage.config.initialize_disks = disk_init_proxy.InitializeLabelsEnabled disk_label = disk_init_proxy.DefaultDiskLabel if disk_label and not DiskLabel.set_default_label_type(disk_label): log.warning( "%s is not a supported disklabel type on this platform. " "Using default disklabel %s instead.", disk_label, DiskLabel.get_platform_label_types()[0]) storage.clear_partitions() # Check the usable disks. if not any(d for d in storage.disks if not d.format.hidden and not d.protected): raise NoDisksError("No usable disks.")
def _do_autopart(self, storage, scheme, requests, encrypted=False, luks_fmt_args=None): """Perform automatic partitioning. :param storage: an instance of Blivet :param scheme: a type of the partitioning scheme :param requests: list of partitioning requests :param encrypted: encrypt the scheduled partitions :param luks_fmt_args: arguments for the LUKS format constructor """ log.debug("scheme: %s", scheme) log.debug("requests:\n%s", "".join([str(p) for p in requests])) log.debug("encrypted: %s", encrypted) log.debug("clear_part_type: %s", storage.config.clear_part_type) log.debug("clear_part_disks: %s", storage.config.clear_part_disks) log.debug("storage.disks: %s", [d.name for d in storage.disks]) log.debug("storage.partitioned: %s", [d.name for d in storage.partitioned if d.format.supported]) log.debug("all names: %s", [d.name for d in storage.devices]) log.debug("boot disk: %s", getattr(storage.bootloader.stage1_disk, "name", None)) if not any(d.format.supported for d in storage.partitioned): raise NoDisksError(_("No usable disks selected")) disks = get_candidate_disks(storage) devs = schedule_implicit_partitions(storage, disks, scheme, encrypted, luks_fmt_args) log.debug("candidate disks: %s", disks) log.debug("devs: %s", devs) if not disks: raise NotEnoughFreeSpaceError( _("Not enough free space on disks for " "automatic partitioning")) devs = schedule_partitions(storage, disks, devs, scheme, requests, encrypted, luks_fmt_args) # run the autopart function to allocate and grow partitions do_partitioning(storage) schedule_volumes(storage, devs, scheme, requests, encrypted) # grow LVs grow_lvm(storage) storage.set_up_bootloader() # only newly added swaps should appear in the fstab new_swaps = (dev for dev in storage.swaps if not dev.format.exists) storage.set_fstab_swaps(new_swaps)
def get_candidate_disks(storage): """Return a list of disks to be used for autopart/reqpart. Disks must be partitioned and have a single free region large enough for a default-sized (500MiB) partition. :param storage: the storage object :type storage: an instance of InstallerStorage :return: a list of partitioned disks with at least 500MiB of free space :rtype: list of :class:`blivet.devices.StorageDevice` """ usable_disks = [] for disk in storage.partitioned: if not disk.format.supported or disk.protected: continue usable_disks.append(disk) free_disks = [] for disk in usable_disks: if get_next_partition_type(disk.format.parted_disk) is None: # new partition can't be added to the disk -- there is no free slot # for a primary partition and no extended partition continue part = disk.format.first_partition while part: if not part.type & parted.PARTITION_FREESPACE: part = part.nextPartition() continue if Size(part.getLength(unit="B")) > PartitionDevice.default_size: free_disks.append(disk) break part = part.nextPartition() if not usable_disks: raise NoDisksError(_("No usable disks selected.")) if not free_disks: raise NotEnoughFreeSpaceError( _("Not enough free space on selected disks.")) return free_disks
def _clear_partitions(self, storage): """Clear partitions. :param storage: an instance of Blivet """ # Set up the initialization config. config = self._get_initialization_config() # Sort partitions by descending partition number to minimize confusing # things like multiple "destroy sda5" actions due to parted renumbering # partitions. This can still happen through the UI but it makes sense to # avoid it where possible. partitions = sorted( storage.partitions, key=lambda p: getattr(p.parted_partition, "number", 1), reverse=True) for part in partitions: log.debug("Looking at partition: %s", part.name) if not config.can_remove(storage, part): continue storage.recursive_remove(part) log.debug("Partitions: %s", [p.name for p in part.disk.children]) # Now remove any empty extended partitions. storage.remove_empty_extended_partitions() # Ensure all disks have appropriate disk labels. for disk in storage.disks: log.debug("Looking at disk: %s", disk.name) if config.can_remove(storage, disk): log.debug("Removing %s.", disk.name) storage.recursive_remove(disk) if config.can_initialize(storage, disk): log.debug("Initializing %s.", disk.name) storage.initialize_disk(disk) # Check the usable disks. if not any(d for d in storage.disks if not d.format.hidden and not d.protected): raise NoDisksError("No usable disks.")
def do_reqpart(storage, requests): """Perform automatic partitioning of just required platform-specific partitions. This is incompatible with do_autopart. :param storage: a :class:`pyanaconda.storage.InstallerStorage` instance :type storage: :class:`pyanaconda.storage.InstallerStorage` :param requests: list of partitioning requests to operate on, or `~.storage.InstallerStorage.autopart_requests` by default :type requests: list of :class:`~.storage.partspec.PartSpec` instances """ if not any(d.format.supported for d in storage.partitioned): raise NoDisksError(_("No usable disks selected")) disks = _get_candidate_disks(storage) if disks == []: raise NotEnoughFreeSpaceError(_("Not enough free space on disks for " "automatic partitioning")) _schedule_partitions(storage, disks, [], requests=requests)
def do_autopart(storage, data, min_luks_entropy=None): """ Perform automatic partitioning. :param storage: a :class:`pyanaconda.storage.InstallerStorage` instance :type storage: :class:`pyanaconda.storage.InstallerStorage` :param data: kickstart data :type data: :class:`pykickstart.BaseHandler` :param min_luks_entropy: minimum entropy in bits required for luks format creation; uses default when None :type min_luks_entropy: int :attr:`Blivet.do_autopart` controls whether this method creates the automatic partitioning layout. :attr:`Blivet.autopart_type` controls which variant of autopart used. It uses one of the pykickstart AUTOPART_TYPE_* constants. The set of eligible disks is defined in :attr:`StorageDiscoveryConfig.clear_part_disks`. .. note:: Clearing of partitions is handled separately, in :meth:`pyanaconda.storage.InstallerStorage.clear_partitions`. """ # pylint: disable=unused-argument log.debug("do_autopart: %s", storage.do_autopart) log.debug("encrypted_autopart: %s", storage.encrypted_autopart) log.debug("autopart_type: %s", storage.autopart_type) log.debug("clear_part_type: %s", storage.config.clear_part_type) log.debug("clear_part_disks: %s", storage.config.clear_part_disks) log.debug("autopart_requests:\n%s", "".join([str(p) for p in storage.autopart_requests])) log.debug("storage.disks: %s", [d.name for d in storage.disks]) log.debug("storage.partitioned: %s", [d.name for d in storage.partitioned if d.format.supported]) log.debug("all names: %s", [d.name for d in storage.devices]) log.debug("boot disk: %s", getattr(storage.bootloader.stage1_disk, "name", None)) if not storage.do_autopart: return if not any(d.format.supported for d in storage.partitioned): raise NoDisksError(_("No usable disks selected")) if min_luks_entropy is not None: luks_data.min_entropy = min_luks_entropy disks = _get_candidate_disks(storage) devs = _schedule_implicit_partitions(storage, disks) log.debug("candidate disks: %s", disks) log.debug("devs: %s", devs) if disks == []: raise NotEnoughFreeSpaceError( _("Not enough free space on disks for " "automatic partitioning")) devs = _schedule_partitions(storage, disks, devs) # run the autopart function to allocate and grow partitions do_partitioning(storage) _schedule_volumes(storage, devs) # grow LVs grow_lvm(storage) storage.set_up_bootloader() # only newly added swaps should appear in the fstab new_swaps = (dev for dev in storage.swaps if not dev.format.exists) storage.set_fstab_swaps(new_swaps)