[PATCH 1/2] Move autopart and swap suggesting functionality to anaconda
Vratislav Podzimek
vpodzime at redhat.com
Fri Jan 23 14:14:48 UTC 2015
These has only very little to do with blivet and are used only as part of the
installation procedure.
Signed-off-by: Vratislav Podzimek <vpodzime at redhat.com>
---
pyanaconda/autopart.py | 497 ++++++++++++++++++++++++++++++++++++
pyanaconda/installclass.py | 4 +-
pyanaconda/kickstart.py | 10 +-
pyanaconda/ui/gui/spokes/custom.py | 2 +-
pyanaconda/ui/gui/spokes/storage.py | 4 +-
5 files changed, 507 insertions(+), 10 deletions(-)
create mode 100644 pyanaconda/autopart.py
diff --git a/pyanaconda/autopart.py b/pyanaconda/autopart.py
new file mode 100644
index 0000000..7b04246
--- /dev/null
+++ b/pyanaconda/autopart.py
@@ -0,0 +1,497 @@
+#
+# Copyright (C) 2015 Red Hat, Inc.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions of
+# the GNU General Public License v.2, or (at your option) any later version.
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY expressed or implied, including the implied warranties of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+# Public License for more details. You should have received a copy of the
+# GNU General Public License along with this program; if not, write to the
+# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA. Any Red Hat trademarks that are incorporated in the
+# source code or documentation are not subject to the GNU General Public
+# License and may only be used or replicated with the express permission of
+# Red Hat, Inc.
+#
+# Red Hat Author(s): Vratislav Podzimek <vpodzime at redhat.com>
+#
+
+"""
+This module provides functions related to autopartitioning that are installer
+specific.
+
+"""
+
+import parted
+from decimal import Decimal
+
+from blivet import util
+from blivet.size import Size
+from blivet.devices.partition import PartitionDevice
+from blivet.devices.luks import LUKSDevice
+from blivet.errors import NoDisksError, NotEnoughFreeSpaceError
+from blivet.formats import getFormat
+from blivet.partitioning import getFreeRegions, growLVM, doPartitioning
+
+from pyanaconda.i18n import _
+from pykickstart.constants import AUTOPART_TYPE_BTRFS, AUTOPART_TYPE_LVM, AUTOPART_TYPE_LVM_THINP, AUTOPART_TYPE_PLAIN
+
+import logging
+log = logging.getLogger("anaconda")
+
+# maximum ratio of swap size to disk size (10 %)
+MAX_SWAP_DISK_RATIO = Decimal('0.1')
+
+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:`~.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 _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)
diff --git a/pyanaconda/installclass.py b/pyanaconda/installclass.py
index 0a92000..21ca085 100644
--- a/pyanaconda/installclass.py
+++ b/pyanaconda/installclass.py
@@ -26,7 +26,6 @@ import os, sys
import imputil
from blivet.partspec import PartSpec
-from blivet.devicelibs import swap
from blivet.platform import platform
from blivet.size import Size
@@ -34,6 +33,7 @@ import logging
log = logging.getLogger("anaconda")
from pyanaconda.kickstart import getAvailableDiskSpace
+from pyanaconda.autopart import swap_suggestion
class BaseInstallClass(object):
# default to not being hidden
@@ -104,7 +104,7 @@ class BaseInstallClass(object):
disk_space = getAvailableDiskSpace(storage)
- swp = swap.swapSuggestion(disk_space=disk_space)
+ swp = swap_suggestion(disk_space=disk_space)
autorequests.append(PartSpec(fstype="swap", size=swp, grow=False,
lv=True, encrypted=True))
diff --git a/pyanaconda/kickstart.py b/pyanaconda/kickstart.py
index 885bcd6..11e3492 100644
--- a/pyanaconda/kickstart.py
+++ b/pyanaconda/kickstart.py
@@ -23,7 +23,6 @@ from blivet.deviceaction import ActionCreateFormat, ActionDestroyFormat, ActionR
from blivet.devices import LUKSDevice
from blivet.devicelibs.lvm import getPossiblePhysicalExtents, LVM_PE_SIZE, KNOWN_THPOOL_PROFILES
from blivet.devicelibs.crypto import MIN_CREATE_ENTROPY
-from blivet.devicelibs import swap as swap_lib
from blivet.formats import getFormat
from blivet.partitioning import doPartitioning
from blivet.partitioning import growLVM
@@ -61,6 +60,7 @@ from pyanaconda.i18n import _
from pyanaconda.ui.common import collect
from pyanaconda.addons import AddonSection, AddonData, AddonRegistry, collect_addon_paths
from pyanaconda.bootloader import GRUB2, get_bootloader
+from pyanaconda.autopart import swap_suggestion
from pykickstart.constants import CLEARPART_TYPE_NONE, FIRSTBOOT_SKIP, FIRSTBOOT_RECONFIG, KS_SCRIPT_POST, KS_SCRIPT_PRE, \
KS_SCRIPT_TRACEBACK, SELINUX_DISABLED, SELINUX_ENFORCING, SELINUX_PERMISSIVE
@@ -250,7 +250,7 @@ def refreshAutoSwapSize(storage):
for request in storage.autoPartitionRequests:
if request.fstype == "swap":
disk_space = getAvailableDiskSpace(storage)
- request.size = swap_lib.swapSuggestion(disk_space=disk_space)
+ request.size = swap_suggestion(disk_space=disk_space)
break
###
@@ -300,7 +300,7 @@ class AutoPart(commands.autopart.F21_AutoPart):
return retval
def execute(self, storage, ksdata, instClass):
- from blivet.partitioning import doAutoPartition
+ from pyanaconda.autopart import doAutoPartition
from pyanaconda.storage_utils import sanity_check
if not self.autopart:
@@ -823,7 +823,7 @@ class LogVolData(commands.logvol.F21_LogVolData):
self.mountpoint = ""
if self.recommended or self.hibernation:
disk_space = getAvailableDiskSpace(storage)
- size = swap_lib.swapSuggestion(hibernation=self.hibernation, disk_space=disk_space)
+ size = swap_suggestion(hibernation=self.hibernation, disk_space=disk_space)
self.grow = False
else:
if self.fstype != "":
@@ -1093,7 +1093,7 @@ class PartitionData(commands.partition.F18_PartData):
self.mountpoint = ""
if self.recommended or self.hibernation:
disk_space = getAvailableDiskSpace(storage)
- size = swap_lib.swapSuggestion(hibernation=self.hibernation, disk_space=disk_space)
+ size = swap_suggestion(hibernation=self.hibernation, disk_space=disk_space)
self.grow = False
# if people want to specify no mountpoint for some reason, let them
# this is really needed for pSeries boot partitions :(
diff --git a/pyanaconda/ui/gui/spokes/custom.py b/pyanaconda/ui/gui/spokes/custom.py
index dd87a4d..29528b8 100644
--- a/pyanaconda/ui/gui/spokes/custom.py
+++ b/pyanaconda/ui/gui/spokes/custom.py
@@ -55,7 +55,7 @@ from blivet.devicefactory import DEVICE_TYPE_DISK
from blivet.devicefactory import DEVICE_TYPE_LVM_THINP
from blivet.devicefactory import SIZE_POLICY_AUTO
from blivet import findExistingInstallations
-from blivet.partitioning import doAutoPartition
+from pyanaconda.autopart import doAutoPartition
from blivet.errors import StorageError
from blivet.errors import NoDisksError
from blivet.errors import NotEnoughFreeSpaceError
diff --git a/pyanaconda/ui/gui/spokes/storage.py b/pyanaconda/ui/gui/spokes/storage.py
index 4ecdfdc..d19a20b 100644
--- a/pyanaconda/ui/gui/spokes/storage.py
+++ b/pyanaconda/ui/gui/spokes/storage.py
@@ -60,7 +60,6 @@ from blivet.size import Size
from blivet.devices import MultipathDevice, ZFCPDiskDevice
from blivet.errors import StorageError, DasdFormatError
from blivet.platform import platform
-from blivet.devicelibs import swap as swap_lib
from blivet.devicelibs.dasd import make_unformatted_dasd_list, format_dasd
from pyanaconda.threads import threadMgr, AnacondaThread
from pyanaconda.product import productName
@@ -68,6 +67,7 @@ from pyanaconda.flags import flags
from pyanaconda.i18n import _, C_, CN_, P_
from pyanaconda import constants, iutil, isys
from pyanaconda.bootloader import BootLoaderError
+from pyanaconda.autopart import swap_suggestion
from pykickstart.constants import CLEARPART_TYPE_NONE, AUTOPART_TYPE_LVM
from pykickstart.errors import KickstartValueError
@@ -801,7 +801,7 @@ class StorageSpoke(NormalSpoke, StorageChecker):
if self.autopart and auto_swap == Size(0):
# autopartitioning requested, but not applied yet (=> no auto swap
# requests), ask user for enough space to fit in the suggested swap
- auto_swap = swap_lib.swapSuggestion()
+ auto_swap = swap_suggestion()
log.debug("disk free: %s fs free: %s sw needs: %s auto swap: %s",
disk_free, fs_free, required_space, auto_swap)
--
2.1.0
More information about the anaconda-patches
mailing list