summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--data/ui/autopart.glade49
-rw-r--r--pyanaconda/installclass.py7
-rw-r--r--pyanaconda/iw/autopart_type.py8
-rw-r--r--pyanaconda/storage/__init__.py1
-rw-r--r--pyanaconda/storage/partitioning.py67
-rw-r--r--pyanaconda/storage/partspec.py10
6 files changed, 120 insertions, 22 deletions
diff --git a/data/ui/autopart.glade b/data/ui/autopart.glade
index ce4177829..b1346f66d 100644
--- a/data/ui/autopart.glade
+++ b/data/ui/autopart.glade
@@ -24,7 +24,7 @@
<child>
<widget class="GtkTable" id="parttypeTable">
<property name="visible">True</property>
- <property name="n_rows">4</property>
+ <property name="n_rows">5</property>
<property name="n_columns">1</property>
<property name="homogeneous">False</property>
<property name="row_spacing">0</property>
@@ -59,6 +59,45 @@
</child>
<child>
+ <widget class="GtkHBox" id="hbox3">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkCheckButton" id="lvmButton">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">Use _LVM</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <property name="active">False</property>
+ <property name="inconsistent">False</property>
+ <property name="draw_indicator">True</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <placeholder/>
+ </child>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options">fill</property>
+ <property name="y_options">fill</property>
+ </packing>
+ </child>
+
+ <child>
<widget class="GtkHBox" id="hbox5">
<property name="visible">True</property>
<property name="homogeneous">False</property>
@@ -90,8 +129,8 @@
<packing>
<property name="left_attach">0</property>
<property name="right_attach">1</property>
- <property name="top_attach">2</property>
- <property name="bottom_attach">3</property>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
<property name="x_options">fill</property>
<property name="y_options">fill</property>
</packing>
@@ -127,8 +166,8 @@
<packing>
<property name="left_attach">0</property>
<property name="right_attach">1</property>
- <property name="top_attach">3</property>
- <property name="bottom_attach">4</property>
+ <property name="top_attach">4</property>
+ <property name="bottom_attach">5</property>
<property name="x_options">fill</property>
<property name="y_options">fill</property>
</packing>
diff --git a/pyanaconda/installclass.py b/pyanaconda/installclass.py
index 0819b6b9d..440b97c44 100644
--- a/pyanaconda/installclass.py
+++ b/pyanaconda/installclass.py
@@ -175,9 +175,10 @@ class BaseInstallClass(object):
def setDefaultPartitioning(self, storage, platform):
autorequests = [PartSpec(mountpoint="/", fstype=storage.defaultFSType,
size=1024, maxSize=50*1024, grow=True,
- asVol=True),
+ asVol=True, encrypted=True),
PartSpec(mountpoint="/home", fstype=storage.defaultFSType,
- size=100, grow=True, asVol=True, requiredSpace=50*1024)]
+ size=100, grow=True, requiredSpace=50*1024,
+ asVol=True, encrypted=True)]
bootreq = platform.setDefaultPartitioning()
if bootreq:
@@ -185,7 +186,7 @@ class BaseInstallClass(object):
(minswap, maxswap) = iutil.swapSuggestion()
autorequests.append(PartSpec(fstype="swap", size=minswap, maxSize=maxswap,
- grow=True, asVol=True))
+ grow=True, asVol=True, encrypted=True))
storage.autoPartitionRequests = autorequests
diff --git a/pyanaconda/iw/autopart_type.py b/pyanaconda/iw/autopart_type.py
index 6eef3aca2..c50ba49d3 100644
--- a/pyanaconda/iw/autopart_type.py
+++ b/pyanaconda/iw/autopart_type.py
@@ -186,6 +186,11 @@ class PartitionTypeWindow(InstallWindow):
self.dispatch.request_steps("autopartitionexecute", "cleardiskssel")
+ if self.lvmButton.get_active():
+ self.storage.lvmAutoPart = True
+ else:
+ self.storage.lvmAutoPart = False
+
if self.encryptButton.get_active():
self.storage.encryptedAutoPart = True
else:
@@ -241,11 +246,13 @@ class PartitionTypeWindow(InstallWindow):
(self.xml, vbox) = gui.getGladeWidget("autopart.glade", "parttypeTable")
self.encryptButton = self.xml.get_widget("encryptButton")
self.reviewButton = self.xml.get_widget("reviewButton")
+ self.lvmButton = self.xml.get_widget("lvmButton")
self.table = self.xml.get_widget("parttypeTable")
self.prevrev = None
self.reviewButton.set_active(self.dispatch.step_enabled("partition"))
self.encryptButton.set_active(self.storage.encryptedAutoPart)
+ self.lvmButton.set_active(self.storage.lvmAutoPart)
self.buttonGroup = pixmapRadioButtonGroup()
self.buttonGroup.addEntry("all", _("Use _All Space"),
@@ -306,5 +313,6 @@ class PartitionTypeWindow(InstallWindow):
self.reviewButton.set_active(True)
self.reviewButton.set_sensitive(False)
self.encryptButton.set_sensitive(False)
+ self.lvmButton.set_sensitive(False)
return vbox
diff --git a/pyanaconda/storage/__init__.py b/pyanaconda/storage/__init__.py
index 5d8b9c3e7..bdb3bfa04 100644
--- a/pyanaconda/storage/__init__.py
+++ b/pyanaconda/storage/__init__.py
@@ -349,6 +349,7 @@ class Storage(object):
self.doAutoPart = False
self.clearPartChoice = None
self.encryptedAutoPart = False
+ self.lvmAutoPart = True
self.encryptionPassphrase = None
self.escrowCertificates = {}
self.autoPartEscrowCert = None
diff --git a/pyanaconda/storage/partitioning.py b/pyanaconda/storage/partitioning.py
index 25aa16939..6cb9c9233 100644
--- a/pyanaconda/storage/partitioning.py
+++ b/pyanaconda/storage/partitioning.py
@@ -40,9 +40,8 @@ _ = lambda x: gettext.ldgettext("anaconda", x)
import logging
log = logging.getLogger("storage")
-def _createFreeSpacePartitions(storage):
- # get a list of disks that have at least one free space region of at
- # least the default size for new partitions
+def _getCandidateDisks(storage):
+ """ Return a list of disks with space for a default-sized partition. """
disks = []
for disk in storage.partitioned:
if storage.config.clearPartDisks and \
@@ -61,8 +60,17 @@ def _createFreeSpacePartitions(storage):
part = part.nextPartition()
+ return disks
+
+def _schedulePVs(storage, disks):
+ """ Schedule creation of an lvm pv partition on each disk in disks. """
# create a separate pv partition for each disk with free space
devs = []
+
+ # only schedule PVs if there are LV autopart reqs
+ if not storage.lvmAutoPart:
+ return devs
+
for disk in disks:
if storage.encryptedAutoPart:
fmt_type = "luks"
@@ -78,17 +86,32 @@ def _createFreeSpacePartitions(storage):
storage.createDevice(part)
devs.append(part)
- return (disks, devs)
+ return devs
def _schedulePartitions(storage, disks):
- #
- # Convert storage.autoPartitionRequests into Device instances and
- # schedule them for creation
+ """ Schedule creation of autopart partitions. """
+ # basis for requests with requiredSpace is the sum of the sizes of the
+ # two largest free regions
+ all_free = getFreeRegions(disks)
+ all_free.sort(key=lambda f: f.length, reverse=True)
+ if not all_free:
+ # this should never happen since we've already filtered the disks
+ # to those with at least 500MB free
+ log.error("no free space on disks %s" % ([d.name for d in disks],))
+ return
+
+ free = all_free[0].getSize()
+ if len(all_free) > 1:
+ free += all_free[1].getSize()
+
#
# First pass is for partitions only. We'll do LVs later.
#
for request in storage.autoPartitionRequests:
- if request.asVol:
+ if request.asVol and storage.lvmAutoPart:
+ continue
+
+ if request.requiredSpace and request.requiredSpace > free:
continue
if request.fstype is None:
@@ -119,7 +142,12 @@ def _schedulePartitions(storage, disks):
if request.mountpoint == "/" and storage.liveImage:
request.fstype = storage.liveImage.format.type
- dev = storage.newPartition(fmt_type=request.fstype,
+ if request.encrypted and storage.encryptedAutoPart:
+ fstype = "luks"
+ else:
+ fstype = request.fstype
+
+ dev = storage.newPartition(fmt_type=fstype,
size=request.size,
grow=request.grow,
maxsize=request.maxSize,
@@ -130,10 +158,24 @@ def _schedulePartitions(storage, disks):
# 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,
+ format=luks_fmt,
+ size=dev.size,
+ parents=dev)
+ storage.createDevice(luks_dev)
+
# make sure preexisting broken lvm/raid configs get out of the way
return
def _scheduleLVs(storage, devs):
+ """ Schedule creation of autopart lvm lvs. """
+ if not devs:
+ return
+
if storage.encryptedAutoPart:
pvs = []
for dev in devs:
@@ -158,7 +200,7 @@ def _scheduleLVs(storage, devs):
#
# Second pass, for LVs only.
for request in storage.autoPartitionRequests:
- if not request.asVol:
+ if not request.asVol or not storage.lvmAutoPart:
continue
if request.requiredSpace and request.requiredSpace > initialVGSize:
@@ -188,6 +230,8 @@ def _scheduleLVs(storage, devs):
def doAutoPartition(anaconda):
log.debug("doAutoPartition(%s)" % anaconda)
log.debug("doAutoPart: %s" % anaconda.storage.doAutoPart)
+ log.debug("encryptedAutoPart: %s" % anaconda.storage.encryptedAutoPart)
+ log.debug("lvmAutoPart: %s" % anaconda.storage.lvmAutoPart)
log.debug("clearPartType: %s" % anaconda.storage.config.clearPartType)
log.debug("clearPartDisks: %s" % anaconda.storage.config.clearPartDisks)
log.debug("autoPartitionRequests: %s" % anaconda.storage.autoPartitionRequests)
@@ -208,7 +252,8 @@ def doAutoPartition(anaconda):
anaconda.bootloader.clear_drive_list()
if anaconda.storage.doAutoPart:
- (disks, devs) = _createFreeSpacePartitions(anaconda.storage)
+ disks = _getCandidateDisks(anaconda.storage)
+ devs = _schedulePVs(anaconda.storage, disks)
if disks == []:
if anaconda.ksdata:
diff --git a/pyanaconda/storage/partspec.py b/pyanaconda/storage/partspec.py
index a126c3f97..1602b8a29 100644
--- a/pyanaconda/storage/partspec.py
+++ b/pyanaconda/storage/partspec.py
@@ -22,7 +22,7 @@
class PartSpec(object):
def __init__(self, mountpoint=None, fstype=None, size=None, maxSize=None,
grow=False, asVol=False, singlePV=False, weight=0,
- requiredSpace=0):
+ requiredSpace=0, encrypted=False):
""" Create a new storage specification. These are used to specify
the default partitioning layout as an object before we have the
storage system up and running. The attributes are obvious
@@ -45,6 +45,9 @@ class PartSpec(object):
other LVs are created inside it. If not enough
space exists, this PartSpec will never get turned
into an LV.
+ encrypted -- Should this request be encrypted? For logical volume
+ requests, this is satisfied if the PVs are encrypted
+ as in the case of encrypted LVM autopart.
"""
self.mountpoint = mountpoint
@@ -56,6 +59,7 @@ class PartSpec(object):
self.singlePV = singlePV
self.weight = weight
self.requiredSpace = requiredSpace
+ self.encrypted = encrypted
if self.singlePV and not self.asVol:
self.asVol = True
@@ -63,12 +67,12 @@ class PartSpec(object):
def __str__(self):
s = ("%(type)s instance (%(id)s) -- \n"
" mountpoint = %(mountpoint)s asVol = %(asVol)s singlePV = %(singlePV)s\n"
- " weight = %(weight)s fstype = %(fstype)s\n"
+ " weight = %(weight)s fstype = %(fstype)s encrypted = %(enc)s\n"
" size = %(size)s maxSize = %(maxSize)s grow = %(grow)s\n" %
{"type": self.__class__.__name__, "id": "%#x" % id(self),
"mountpoint": self.mountpoint, "asVol": self.asVol,
"singlePV": self.singlePV, "weight": self.weight,
- "fstype": self.fstype, "size": self.size,
+ "fstype": self.fstype, "size": self.size, "enc": self.encrypted,
"maxSize": self.maxSize, "grow": self.grow})
return s