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)
Exemple #3
0
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.")
Exemple #5
0
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)
Exemple #6
0
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)