[blivet][PATCH 2/3] Move autopart code out of blivet

Vratislav Podzimek vpodzime at redhat.com
Fri Jan 23 14:18:17 UTC 2015


Blivet is not a library doing magic. Autopartitioning is only performed as part
of the installation process and thus doesn't belong to blivet's codebase.

Signed-off-by: Vratislav Podzimek <vpodzime at redhat.com>
---
 blivet/__init__.py     |   2 +-
 blivet/partitioning.py | 395 +------------------------------------------------
 2 files changed, 2 insertions(+), 395 deletions(-)

diff --git a/blivet/__init__.py b/blivet/__init__.py
index 88809fb..fff7fb5 100644
--- a/blivet/__init__.py
+++ b/blivet/__init__.py
@@ -66,7 +66,7 @@ import parted
 from pykickstart.constants import AUTOPART_TYPE_LVM, CLEARPART_TYPE_ALL, CLEARPART_TYPE_LINUX, CLEARPART_TYPE_LIST, CLEARPART_TYPE_NONE
 
 from .storage_log import log_exception_info, log_method_call
-from .errors import DeviceError, FSResizeError, FSTabTypeMismatchError, UnknownSourceDeviceError, StorageError, UnrecognizedFSTabEntryError
+from .errors import FSResizeError, FSTabTypeMismatchError, UnknownSourceDeviceError, StorageError, UnrecognizedFSTabEntryError
 from .devices import BTRFSDevice, BTRFSSubVolumeDevice, BTRFSVolumeDevice, DirectoryDevice, FileDevice, LVMLogicalVolumeDevice, LVMThinLogicalVolumeDevice, LVMThinPoolDevice, LVMVolumeGroupDevice, MDRaidArrayDevice, NetworkStorageDevice, NFSDevice, NoDevice, OpticalDevice, PartitionDevice, TmpFSDevice, devicePathToName
 from .devicetree import DeviceTree
 from .deviceaction import ActionCreateDevice, ActionCreateFormat, ActionDestroyDevice, ActionDestroyFormat, ActionResizeDevice, ActionResizeFormat
diff --git a/blivet/partitioning.py b/blivet/partitioning.py
index f33d78d..8762f3e 100644
--- a/blivet/partitioning.py
+++ b/blivet/partitioning.py
@@ -24,12 +24,10 @@ from operator import gt, lt
 from decimal import Decimal
 
 import parted
-from pykickstart.constants import AUTOPART_TYPE_BTRFS, AUTOPART_TYPE_LVM, AUTOPART_TYPE_LVM_THINP, AUTOPART_TYPE_PLAIN
 
-from .errors import DeviceError, NoDisksError, NotEnoughFreeSpaceError, PartitioningError
+from .errors import DeviceError, PartitioningError
 from .flags import flags
 from .devices import PartitionDevice, LUKSDevice, devicePathToName
-from .formats import getFormat
 from .devicelibs.lvm import get_pool_padding
 from .size import Size
 from .i18n import _
@@ -38,397 +36,6 @@ from .util import stringize, unicodeize
 import logging
 log = logging.getLogger("blivet")
 
-def _getCandidateDisks(storage):
-    """ Return a list of disks to be used for autopart.
-
-        Disks must be partitioned and have a single free region large enough
-        for a default-sized (500MiB) partition. They must also be in
-        :attr:`StorageDiscoveryConfig.clearPartDisks` if it is non-empty.
-
-        :param storage: a Blivet instance
-        :type storage: :class:`~.Blivet`
-        :returns: a list of partitioned disks with at least 500MiB of free space
-        :rtype: list of :class:`~.devices.StorageDevice`
-    """
-    disks = []
-    for disk in storage.partitioned:
-        if storage.config.clearPartDisks and \
-           (disk.name not in storage.config.clearPartDisks):
-            continue
-
-        part = disk.format.firstPartition
-        while part:
-            if not part.type & parted.PARTITION_FREESPACE:
-                part = part.nextPartition()
-                continue
-
-            if Size(part.getLength(unit="B")) > PartitionDevice.defaultSize:
-                disks.append(disk)
-                break
-
-            part = part.nextPartition()
-
-    return disks
-
-def _scheduleImplicitPartitions(storage, disks, min_luks_entropy=0):
-    """ Schedule creation of a lvm/btrfs member partitions for autopart.
-
-        We create one such partition on each disk. They are not allocated until
-        later (in :func:`doPartitioning`).
-
-        :param storage: a :class:`~.Blivet` instance
-        :type storage: :class:`~.Blivet`
-        :param disks: list of partitioned disks with free space
-        :type disks: list of :class:`~.devices.StorageDevice`
-        :param min_luks_entropy: minimum entropy in bits required for
-                                 luks format creation
-        :type min_luks_entropy: int
-        :returns: list of newly created (unallocated) partitions
-        :rtype: list of :class:`~.devices.PartitionDevice`
-    """
-    # create a separate pv or btrfs partition for each disk with free space
-    devs = []
-
-    # only schedule the partitions if either lvm or btrfs autopart was chosen
-    if storage.autoPartType == AUTOPART_TYPE_PLAIN:
-        return devs
-
-    for disk in disks:
-        if storage.encryptedAutoPart:
-            fmt_type = "luks"
-            fmt_args = {"passphrase": storage.encryptionPassphrase,
-                        "cipher": storage.encryptionCipher,
-                        "escrow_cert": storage.autoPartEscrowCert,
-                        "add_backup_passphrase": storage.autoPartAddBackupPassphrase,
-                        "min_luks_entropy": min_luks_entropy}
-        else:
-            if storage.autoPartType in (AUTOPART_TYPE_LVM, AUTOPART_TYPE_LVM_THINP):
-                fmt_type = "lvmpv"
-            else:
-                fmt_type = "btrfs"
-            fmt_args = {}
-        part = storage.newPartition(fmt_type=fmt_type,
-                                                fmt_args=fmt_args,
-                                                grow=True,
-                                                parents=[disk])
-        storage.createDevice(part)
-        devs.append(part)
-
-    return devs
-
-def _schedulePartitions(storage, disks, implicit_devices, min_luks_entropy=0):
-    """ Schedule creation of autopart partitions.
-
-        This only schedules the requests for actual partitions.
-
-        :param storage: a :class:`~.Blivet` instance
-        :type storage: :class:`~.Blivet`
-        :param disks: list of partitioned disks with free space
-        :type disks: list of :class:`~.devices.StorageDevice`
-        :param min_luks_entropy: minimum entropy in bits required for
-                                 luks format creation
-        :type min_luks_entropy: int
-        :returns: None
-        :rtype: None
-    """
-    # basis for requests with requiredSpace is the sum of the sizes of the
-    # two largest free regions
-    all_free = (Size(reg.getLength(unit="B")) for reg in getFreeRegions(disks))
-    all_free = sorted(all_free, reverse=True)
-    if not all_free:
-        # this should never happen since we've already filtered the disks
-        # to those with at least 500MiB free
-        log.error("no free space on disks %s", [d.name for d in disks])
-        return
-
-    free = all_free[0]
-    if len(all_free) > 1:
-        free += all_free[1]
-
-    # The boot disk must be set at this point. See if any platform-specific
-    # stage1 device we might allocate already exists on the boot disk.
-    stage1_device = None
-    for device in storage.devices:
-        if storage.bootloader.stage1_disk not in device.disks:
-            continue
-
-        if storage.bootloader.is_valid_stage1_device(device, early=True):
-            stage1_device = device
-            break
-
-    #
-    # First pass is for partitions only. We'll do LVs later.
-    #
-    for request in storage.autoPartitionRequests:
-        if ((request.lv and
-             storage.autoPartType in (AUTOPART_TYPE_LVM,
-                                      AUTOPART_TYPE_LVM_THINP)) or
-            (request.btr and storage.autoPartType == AUTOPART_TYPE_BTRFS)):
-            continue
-
-        if request.requiredSpace and request.requiredSpace > free:
-            continue
-
-        elif request.fstype in ("prepboot", "efi", "macefi", "hfs+") and \
-             (storage.bootloader.skip_bootloader or stage1_device):
-            # there should never be a need for more than one of these
-            # partitions, so skip them.
-            log.info("skipping unneeded stage1 %s request", request.fstype)
-            log.debug("%s", request)
-
-            if request.fstype in ["efi", "macefi"] and stage1_device:
-                # Set the mountpoint for the existing EFI boot partition
-                stage1_device.format.mountpoint = "/boot/efi"
-
-            log.debug("%s", stage1_device)
-            continue
-        elif request.fstype == "biosboot":
-            is_gpt = (stage1_device and
-                      getattr(stage1_device.format, "labelType", None) == "gpt")
-            has_bios_boot = (stage1_device and
-                             any([p.format.type == "biosboot"
-                                    for p in storage.partitions
-                                        if p.disk == stage1_device]))
-            if (storage.bootloader.skip_bootloader or
-                not (stage1_device and stage1_device.isDisk and
-                    is_gpt and not has_bios_boot)):
-                # there should never be a need for more than one of these
-                # partitions, so skip them.
-                log.info("skipping unneeded stage1 %s request", request.fstype)
-                log.debug("%s", request)
-                log.debug("%s", stage1_device)
-                continue
-
-        if request.size > all_free[0]:
-            # no big enough free space for the requested partition
-            raise NotEnoughFreeSpaceError(_("No big enough free space on disks for "
-                                            "automatic partitioning"))
-
-        if request.encrypted and storage.encryptedAutoPart:
-            fmt_type = "luks"
-            fmt_args = {"passphrase": storage.encryptionPassphrase,
-                        "cipher": storage.encryptionCipher,
-                        "escrow_cert": storage.autoPartEscrowCert,
-                        "add_backup_passphrase": storage.autoPartAddBackupPassphrase,
-                        "min_luks_entropy": min_luks_entropy}
-        else:
-            fmt_type = request.fstype
-            fmt_args = {}
-
-        dev = storage.newPartition(fmt_type=fmt_type,
-                                            fmt_args=fmt_args,
-                                            size=request.size,
-                                            grow=request.grow,
-                                            maxsize=request.maxSize,
-                                            mountpoint=request.mountpoint,
-                                            parents=disks,
-                                            weight=request.weight)
-
-        # schedule the device for creation
-        storage.createDevice(dev)
-
-        if request.encrypted and storage.encryptedAutoPart:
-            luks_fmt = getFormat(request.fstype,
-                                 device=dev.path,
-                                 mountpoint=request.mountpoint)
-            luks_dev = LUKSDevice("luks-%s" % dev.name,
-                                  fmt=luks_fmt,
-                                  size=dev.size,
-                                  parents=dev)
-            storage.createDevice(luks_dev)
-
-        if storage.autoPartType in (AUTOPART_TYPE_LVM, AUTOPART_TYPE_LVM_THINP,
-                                    AUTOPART_TYPE_BTRFS):
-            # doing LVM/BTRFS -- make sure the newly created partition fits in some
-            # free space together with one of the implicitly requested partitions
-            smallest_implicit = sorted(implicit_devices, key=lambda d: d.size)[0]
-            if (request.size + smallest_implicit.size) > all_free[0]:
-                # not enough space to allocate the smallest implicit partition
-                # and the request, make the implicit partition smaller with
-                # fixed size in order to make space for the request
-                new_size = all_free[0] - request.size
-
-                # subtract the size from the biggest free region and reorder the
-                # list
-                all_free[0] -= request.size
-                all_free.sort(reverse=True)
-
-                if new_size > Size(0):
-                    smallest_implicit.size = new_size
-                else:
-                    implicit_devices.remove(smallest_implicit)
-                    storage.destroyDevice(smallest_implicit)
-
-    return implicit_devices
-
-def _scheduleVolumes(storage, devs):
-    """ Schedule creation of autopart lvm/btrfs volumes.
-
-        Schedules encryption of member devices if requested, schedules creation
-        of the container (:class:`~.devices.LVMVolumeGroupDevice` or
-        :class:`~.devices.BTRFSVolumeDevice`) then schedules creation of the
-        autopart volume requests.
-
-        :param storage: a :class:`~.Blivet` instance
-        :type storage: :class:`~.Blivet`
-        :param devs: list of member partitions
-        :type devs: list of :class:`~.devices.PartitionDevice`
-        :returns: None
-        :rtype: None
-
-        If an appropriate bootloader stage1 device exists on the boot drive, any
-        autopart request to create another one will be skipped/discarded.
-    """
-    if not devs:
-        return
-
-    if storage.autoPartType in (AUTOPART_TYPE_LVM, AUTOPART_TYPE_LVM_THINP):
-        new_container = storage.newVG
-        new_volume = storage.newLV
-        format_name = "lvmpv"
-    else:
-        new_container = storage.newBTRFS
-        new_volume = storage.newBTRFS
-        format_name = "btrfs"
-
-    if storage.encryptedAutoPart:
-        pvs = []
-        for dev in devs:
-            pv = LUKSDevice("luks-%s" % dev.name,
-                            fmt=getFormat(format_name, device=dev.path),
-                            size=dev.size,
-                            parents=dev)
-            pvs.append(pv)
-            storage.createDevice(pv)
-    else:
-        pvs = devs
-
-    # create a vg containing all of the autopart pvs
-    container = new_container(parents=pvs)
-    storage.createDevice(container)
-
-    #
-    # Convert storage.autoPartitionRequests into Device instances and
-    # schedule them for creation.
-    #
-    # Second pass, for LVs only.
-    pool = None
-    for request in storage.autoPartitionRequests:
-        btr = storage.autoPartType == AUTOPART_TYPE_BTRFS and request.btr
-        lv = (storage.autoPartType in (AUTOPART_TYPE_LVM,
-                                       AUTOPART_TYPE_LVM_THINP) and request.lv)
-        thinlv = (storage.autoPartType == AUTOPART_TYPE_LVM_THINP and
-                  request.lv and request.thin)
-        if thinlv and pool is None:
-            # create a single thin pool in the vg
-            pool = storage.newLV(parents=[container], thin_pool=True, grow=True)
-            storage.createDevice(pool)
-
-        if not btr and not lv and not thinlv:
-            continue
-
-        # required space isn't relevant on btrfs
-        if (lv or thinlv) and \
-           request.requiredSpace and request.requiredSpace > container.size:
-            continue
-
-        if request.fstype is None:
-            if btr:
-                # btrfs volumes can only contain btrfs filesystems
-                request.fstype = "btrfs"
-            else:
-                request.fstype = storage.defaultFSType
-
-        kwargs = {"mountpoint": request.mountpoint,
-                  "fmt_type": request.fstype}
-        if lv or thinlv:
-            if thinlv:
-                parents = [pool]
-            else:
-                parents = [container]
-
-            kwargs.update({"parents": parents,
-                           "grow": request.grow,
-                           "maxsize": request.maxSize,
-                           "size": request.size,
-                           "thin_volume": thinlv})
-        else:
-            kwargs.update({"parents": [container],
-                           "size": request.size,
-                           "subvol": True})
-
-        dev = new_volume(**kwargs)
-
-        # schedule the device for creation
-        storage.createDevice(dev)
-
-def doAutoPartition(storage, data, min_luks_entropy=0):
-    """ Perform automatic partitioning.
-
-        :param storage: a :class:`~.Blivet` instance
-        :type storage: :class:`~.Blivet`
-        :param data: kickstart data
-        :type data: :class:`pykickstart.BaseHandler`
-        :param min_luks_entropy: minimum entropy in bits required for
-                                 luks format creation
-        :type min_luks_entropy: int
-
-        :attr:`Blivet.doAutoPart` controls whether this method creates the
-        automatic partitioning layout. :attr:`Blivet.autoPartType` 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.clearPartDisks`.
-
-        .. note::
-
-            Clearing of partitions is handled separately, in
-            :meth:`~.Blivet.clearPartitions`.
-    """
-    # pylint: disable=unused-argument
-    log.debug("doAutoPart: %s", storage.doAutoPart)
-    log.debug("encryptedAutoPart: %s", storage.encryptedAutoPart)
-    log.debug("autoPartType: %s", storage.autoPartType)
-    log.debug("clearPartType: %s", storage.config.clearPartType)
-    log.debug("clearPartDisks: %s", storage.config.clearPartDisks)
-    log.debug("autoPartitionRequests:\n%s", "".join([str(p) for p in storage.autoPartitionRequests]))
-    log.debug("storage.disks: %s", [d.name for d in storage.disks])
-    log.debug("storage.partitioned: %s", [d.name for d in storage.partitioned])
-    log.debug("all names: %s", [d.name for d in storage.devices])
-    log.debug("boot disk: %s", getattr(storage.bootDisk, "name", None))
-
-    disks = []
-    devs = []
-
-    if not storage.doAutoPart:
-        return
-
-    if not storage.partitioned:
-        raise NoDisksError(_("No usable disks selected"))
-
-    disks = _getCandidateDisks(storage)
-    devs = _scheduleImplicitPartitions(storage, disks, min_luks_entropy)
-    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 = _schedulePartitions(storage, disks, devs, min_luks_entropy=min_luks_entropy)
-
-    # run the autopart function to allocate and grow partitions
-    doPartitioning(storage)
-    _scheduleVolumes(storage, devs)
-
-    # grow LVs
-    growLVM(storage)
-
-    storage.setUpBootLoader()
-
-    # only newly added swaps should appear in the fstab
-    new_swaps = (dev for dev in storage.swaps if not dev.format.exists)
-    storage.setFstabSwaps(new_swaps)
-
 def partitionCompare(part1, part2):
     """ More specifically defined partitions come first.
 
-- 
2.1.0



More information about the anaconda-patches mailing list