pyanaconda/storage/__init__.py | 9 +++- pyanaconda/storage/devicelibs/mdraid.py | 14 +++--- pyanaconda/storage/partitioning.py | 8 ++-- pyanaconda/ui/gui/spokes/custom.glade | 9 ++++ pyanaconda/ui/gui/spokes/custom.py | 63 +++++++++++++++++++++---------- pyanaconda/ui/gui/spokes/lib/resize.py | 14 ++----- pyanaconda/ui/gui/spokes/storage.py | 34 ++++++++++++++-- 7 files changed, 102 insertions(+), 49 deletions(-)
ValueError makes exception handling difficult since you can't know if the error is something expected as opposed to a programming error. --- pyanaconda/storage/devicelibs/mdraid.py | 14 +++++++------- 1 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/pyanaconda/storage/devicelibs/mdraid.py b/pyanaconda/storage/devicelibs/mdraid.py index c2aad01..432a24e 100644 --- a/pyanaconda/storage/devicelibs/mdraid.py +++ b/pyanaconda/storage/devicelibs/mdraid.py @@ -89,20 +89,20 @@ def raidLevel(descriptor): if isRaid(level, descriptor): return level else: - raise ValueError, "invalid raid level descriptor %s" % descriptor + raise MDRaidError("invalid raid level descriptor %s" % descriptor)
def raidLevelString(level): if level in raid_descriptors.keys(): return raid_descriptors[level][0] else: - raise ValueError("invalid raid level constant %s") % level + raise MDRaidError("invalid raid level constant %s" % level)
def isRaid(raid, raidlevel): """Return whether raidlevel is a valid descriptor of raid""" if raid in raid_descriptors: return raidlevel in raid_descriptors[raid] else: - raise ValueError, "invalid raid level %d" % raid + raise MDRaidError("invalid raid level %d" % raid)
def get_raid_min_members(raidlevel): """Return the minimum number of raid members required for raid level""" @@ -117,7 +117,7 @@ def get_raid_min_members(raidlevel): if isRaid(raid, raidlevel): return min_members
- raise ValueError, "invalid raid level %d" % raidlevel + raise MDRaidError("invalid raid level %d" % raidlevel)
def get_raid_max_spares(raidlevel, nummembers): """Return the maximum number of raid spares for raidlevel.""" @@ -132,7 +132,7 @@ def get_raid_max_spares(raidlevel, nummembers): if isRaid(raid, raidlevel): return max_spares_func()
- raise ValueError, "invalid raid level %d" % raidlevel + raise MDRaidError("invalid raid level %d" % raidlevel)
def get_member_space(size, disks, level=None): space = 0 # size of *each* member device @@ -142,7 +142,7 @@ def get_member_space(size, disks, level=None):
min_members = get_raid_min_members(level) if disks < min_members: - raise ValueError("raid%d requires at least %d disks" + raise MDRaidError("raid%d requires at least %d disks" % (level, min_members))
if level == RAID0: @@ -211,7 +211,7 @@ def mdadd(device):
def mdactivate(device, members=[], super_minor=None, uuid=None): if super_minor is None and not uuid: - raise ValueError("mdactivate requires either a uuid or a super-minor") + raise MDRaidError("mdactivate requires either a uuid or a super-minor")
if uuid: identifier = "--uuid=%s" % uuid
--- pyanaconda/ui/gui/spokes/custom.glade | 9 +++++++++ 1 files changed, 9 insertions(+), 0 deletions(-)
diff --git a/pyanaconda/ui/gui/spokes/custom.glade b/pyanaconda/ui/gui/spokes/custom.glade index 8e6d728..c377e6a 100644 --- a/pyanaconda/ui/gui/spokes/custom.glade +++ b/pyanaconda/ui/gui/spokes/custom.glade @@ -746,6 +746,7 @@ you'll be able to view their details here.</property> <property name="use_action_appearance">False</property> <property name="xalign">0</property> <property name="draw_indicator">True</property> + <signal name="toggled" handler="on_raid_feature_toggled" swapped="no"/> </object> <packing> <property name="expand">False</property> @@ -791,6 +792,7 @@ you'll be able to view their details here.</property> <property name="use_action_appearance">False</property> <property name="xalign">0</property> <property name="draw_indicator">True</property> + <signal name="toggled" handler="on_raid_feature_toggled" swapped="no"/> </object> <packing> <property name="expand">False</property> @@ -845,6 +847,7 @@ you'll be able to view their details here.</property> <property name="use_action_appearance">False</property> <property name="xalign">0</property> <property name="draw_indicator">True</property> + <signal name="toggled" handler="on_raid_feature_toggled" swapped="no"/> </object> <packing> <property name="expand">False</property> @@ -890,6 +893,7 @@ you'll be able to view their details here.</property> <property name="use_action_appearance">False</property> <property name="xalign">0</property> <property name="draw_indicator">True</property> + <signal name="toggled" handler="on_raid_feature_toggled" swapped="no"/> </object> <packing> <property name="expand">False</property> @@ -934,6 +938,7 @@ you'll be able to view their details here.</property> <property name="use_action_appearance">False</property> <property name="xalign">0</property> <property name="draw_indicator">True</property> + <signal name="toggled" handler="on_raid_feature_toggled" swapped="no"/> </object> <packing> <property name="expand">False</property> @@ -979,6 +984,7 @@ you'll be able to view their details here.</property> <property name="use_action_appearance">False</property> <property name="xalign">0</property> <property name="draw_indicator">True</property> + <signal name="toggled" handler="on_raid_feature_toggled" swapped="no"/> </object> <packing> <property name="expand">False</property> @@ -1012,6 +1018,7 @@ you'll be able to view their details here.</property> <property name="use_action_appearance">False</property> <property name="xalign">0</property> <property name="draw_indicator">True</property> + <signal name="toggled" handler="on_raid_feature_toggled" swapped="no"/> </object> <packing> <property name="expand">False</property> @@ -1091,6 +1098,7 @@ you'll be able to view their details here.</property> <property name="use_action_appearance">False</property> <property name="xalign">0</property> <property name="draw_indicator">True</property> + <signal name="toggled" handler="on_raid_feature_toggled" swapped="no"/> </object> <packing> <property name="expand">False</property> @@ -1136,6 +1144,7 @@ you'll be able to view their details here.</property> <property name="use_action_appearance">False</property> <property name="xalign">0</property> <property name="draw_indicator">True</property> + <signal name="toggled" handler="on_raid_feature_toggled" swapped="no"/> </object> <packing> <property name="expand">False</property>
--- pyanaconda/ui/gui/spokes/custom.py | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/pyanaconda/ui/gui/spokes/custom.py b/pyanaconda/ui/gui/spokes/custom.py index 114cffb..9838e22 100644 --- a/pyanaconda/ui/gui/spokes/custom.py +++ b/pyanaconda/ui/gui/spokes/custom.py @@ -339,6 +339,7 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker): self.storage.devicetree.registerAction(action)
def apply(self): + self.clear_errors() ui_devicetree = self.__storage.devicetree
log.debug("converting custom spoke changes into actions") @@ -609,6 +610,7 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker): self._unused_devices = None
def refresh(self): + self.clear_errors() NormalSpoke.refresh(self)
# Make sure the storage spoke execute method has finished before we
This is used to prevent combinations of features that do not reduce to a valid raid level. --- pyanaconda/ui/gui/spokes/custom.py | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-)
diff --git a/pyanaconda/ui/gui/spokes/custom.py b/pyanaconda/ui/gui/spokes/custom.py index 9838e22..bd1088f 100644 --- a/pyanaconda/ui/gui/spokes/custom.py +++ b/pyanaconda/ui/gui/spokes/custom.py @@ -125,7 +125,11 @@ raid_level_features = {"raid0": ["Performance"], "single": []}
# disabled features by raid_level -raid_disabled_features = {"raid1": ["Error", "DistError", "RedundantError"]} +raid_disabled_features = {"raid1": ["Error", "DistError", "RedundantError"], + "raid10": ["Error", "DistError", "RedundantError"], + "raid4": ["Redundancy", "DistError", "RedundantError"], + "raid5": ["Redundancy", "Error", "RedundantError"], + "raid6": ["Redundancy", "Error", "DistError"]}
# reference raid level by feature name feature_raid_levels = {"Performance": "raid0",
--- pyanaconda/ui/gui/spokes/custom.py | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/pyanaconda/ui/gui/spokes/custom.py b/pyanaconda/ui/gui/spokes/custom.py index bd1088f..054124c 100644 --- a/pyanaconda/ui/gui/spokes/custom.py +++ b/pyanaconda/ui/gui/spokes/custom.py @@ -1011,6 +1011,7 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker): try: # XXX FIXME: pass old raid level -- not new one self._replace_device(device_type, device.size, + disks=disks, fstype=device.format.type, mountpoint=old_mountpoint, label=old_label,
This also uses Storage.recursiveRemove to remove dependent devices before trying to remove the partition. --- pyanaconda/ui/gui/spokes/lib/resize.py | 10 +++------- 1 files changed, 3 insertions(+), 7 deletions(-)
diff --git a/pyanaconda/ui/gui/spokes/lib/resize.py b/pyanaconda/ui/gui/spokes/lib/resize.py index fcccbeb..47054c1 100644 --- a/pyanaconda/ui/gui/spokes/lib/resize.py +++ b/pyanaconda/ui/gui/spokes/lib/resize.py @@ -24,7 +24,6 @@ from __future__ import division from gi.repository import Gtk
from pyanaconda.ui.gui import GUIObject -from pyanaconda.storage.deviceaction import * from pyanaconda.storage.size import Size
import gettext @@ -220,14 +219,11 @@ class ResizeDialog(GUIObject): return False elif action == SHRINK: if device.resizable: - self.storage.devicetree.registerAction(ActionResizeFormat(device, device.minSize)) - self.storage.devicetree.registerAction(ActionResizeDevice(device, device.minSize)) + self.storage.resizeDevice(device, device.minSize) else: - self.storage.devicetree.registerAction(ActionDestroyFormat(device)) - self.storage.devicetree.registerAction(ActionDestroyDevice(device)) + self.storage.recursiveRemove(device) elif action == DELETE: - self.storage.devicetree.registerAction(ActionDestroyFormat(device)) - self.storage.devicetree.registerAction(ActionDestroyDevice(device)) + self.storage.recursiveRemove(device)
return False
The parted list should be pretty much in sync, but this way saves some trouble with resolving the parted partition paths to devices in the devicetree. --- pyanaconda/ui/gui/spokes/lib/resize.py | 4 +--- 1 files changed, 1 insertions(+), 3 deletions(-)
diff --git a/pyanaconda/ui/gui/spokes/lib/resize.py b/pyanaconda/ui/gui/spokes/lib/resize.py index 47054c1..7b89ea0 100644 --- a/pyanaconda/ui/gui/spokes/lib/resize.py +++ b/pyanaconda/ui/gui/spokes/lib/resize.py @@ -116,9 +116,7 @@ class ResizeDialog(GUIObject): diskReclaimableSpace = 0
# Then add all its partitions. - for part in disk.format.partitions: - dev = self.storage.devicetree.getDeviceByPath(part.path) - + for dev in self.storage.devicetree.getChildren(disk): if dev.isExtended and disk.format.logicalPartitions: continue
--- pyanaconda/ui/gui/spokes/custom.py | 32 ++++++++++++++++++++++++++------ 1 files changed, 26 insertions(+), 6 deletions(-)
diff --git a/pyanaconda/ui/gui/spokes/custom.py b/pyanaconda/ui/gui/spokes/custom.py index 054124c..edc2cd0 100644 --- a/pyanaconda/ui/gui/spokes/custom.py +++ b/pyanaconda/ui/gui/spokes/custom.py @@ -939,9 +939,6 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker): encrypted=encrypted, raid_level=raid_level)
- # for raid settings, we'll need to adjust the member set and container, - # and possibly also its devices - # for member type, we'll have to adjust the member set. # XXX not going to worry about this for now
@@ -951,14 +948,37 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker): device_types = {"partition": AUTOPART_TYPE_PLAIN, "lvmlv": AUTOPART_TYPE_LVM, "btrfs subvolume": AUTOPART_TYPE_BTRFS, + "btrfs volume": AUTOPART_TYPE_BTRFS, "mdarray": None} current_device_type = device.type + use_dev = device if current_device_type == "luks/dm-crypt": current_device_type = device.slave.type + use_dev = device.slave current_device_type = device_types.get(current_device_type) - if current_device_type != device_type: - log.info("changing device type from %s to %s" % (current_device_type, - device_type)) + + old_raid_level = None + if current_device_type is None: + old_raid_level = mdraid.raidLevelString(use_dev.level) + elif current_device_type == AUTOPART_TYPE_BTRFS: + if hasattr(use_dev, "dataLevel"): + old_raid_level = use_dev.dataLevel or "single" + else: + old_raid_level = use_dev.volume.dataLevel or "single" + + changed_device_type = (current_device_type != device_type) + changed_raid_level = (current_device_type == device_type and + device_type in (None, AUTOPART_TYPE_BTRFS) and + old_raid_level != raid_level) + + if changed_device_type or changed_raid_level: + if changed_device_type: + log.info("changing device type from %s to %s" + % (current_device_type, device_type)) + else: + log.info("changing raid level from %s to %s" + % (old_raid_level, raid_level)) + # remove the current device self.clear_errors() root = self._current_selector._root
--- pyanaconda/ui/gui/spokes/custom.py | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-)
diff --git a/pyanaconda/ui/gui/spokes/custom.py b/pyanaconda/ui/gui/spokes/custom.py index edc2cd0..53cf302 100644 --- a/pyanaconda/ui/gui/spokes/custom.py +++ b/pyanaconda/ui/gui/spokes/custom.py @@ -111,6 +111,10 @@ DEVICE_TYPE_MD = 1 DEVICE_TYPE_PARTITION = 2 DEVICE_TYPE_BTRFS = 3
+options_page_dict = {DEVICE_TYPE_LVM: 0, + DEVICE_TYPE_MD: 1, + DEVICE_TYPE_BTRFS: 2} + # raid feature names. These are the basis for some UI widget names. raid_features = ["Performance", "Redundancy", "Error", "DistError", "RedundantError"] @@ -1910,7 +1914,7 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker): self._optionsNotebook.hide() else: self._optionsNotebook.show() - self._optionsNotebook.set_current_page(new_type) + self._optionsNotebook.set_current_page(options_page_dict[new_type])
raid_level = None if new_type == DEVICE_TYPE_BTRFS:
It already gets called from _do_refresh and multiple calls to save_right_side are both wasteful and potentially dangerous. --- pyanaconda/ui/gui/spokes/custom.py | 5 ----- 1 files changed, 0 insertions(+), 5 deletions(-)
diff --git a/pyanaconda/ui/gui/spokes/custom.py b/pyanaconda/ui/gui/spokes/custom.py index 53cf302..6f70bb6 100644 --- a/pyanaconda/ui/gui/spokes/custom.py +++ b/pyanaconda/ui/gui/spokes/custom.py @@ -1749,7 +1749,6 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker): self._unused_devices = None # why do we cache this? self._do_refresh() self._updateSpaceDisplay() - self._show_first_mountpoint()
def on_summary_clicked(self, button): dialog = SelectedDisksDialog(self.data) @@ -1874,10 +1873,6 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker): log.debug("updating space display") self._updateSpaceDisplay() log.debug("finished updating space display") - self._accordion.expandPage(new_install_name) - - # And then display the first filesystem on the RHS. - self._show_first_mountpoint()
def on_fs_type_changed(self, combo): if not self._initialized:
If we skip accounting for any requests, the set's data will no longer match the state of its devices. We need to know how much every device has grown. This bug was leading to severely overgrown sets in some cases. --- pyanaconda/storage/partitioning.py | 3 --- 1 files changed, 0 insertions(+), 3 deletions(-)
diff --git a/pyanaconda/storage/partitioning.py b/pyanaconda/storage/partitioning.py index ee3c997..f0e0191 100644 --- a/pyanaconda/storage/partitioning.py +++ b/pyanaconda/storage/partitioning.py @@ -1652,9 +1652,6 @@ def manageSizeSets(size_sets, chunks):
for device in ss.devices: request = requests_by_device[device] - if request.done: - continue - chunk = chunks_by_request[request] new_growth = request.growth - growth_by_request[request] ss.allocate(chunk.lengthToSize(new_growth))
There is no guarantee of growth, so be sure to start with a size that can hold the specified formatting. --- pyanaconda/storage/__init__.py | 9 ++++++--- 1 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/pyanaconda/storage/__init__.py b/pyanaconda/storage/__init__.py index 6f60ec4..6f1ca3b 100644 --- a/pyanaconda/storage/__init__.py +++ b/pyanaconda/storage/__init__.py @@ -1851,6 +1851,7 @@ class Storage(object): device_space = factory.device_size log.debug("device requires %d" % device_space) container_size += device_space + base_size = max(1, getFormat(factory.member_format).minSize)
# XXX TODO: multiple member devices per disk
@@ -1859,7 +1860,7 @@ class Storage(object): if isinstance(member, LUKSDevice): member = member.slave
- member.req_base_size = 1 + member.req_base_size = base_size member.req_size = member.req_base_size member.req_grow = True
@@ -1873,7 +1874,8 @@ class Storage(object): member_format = factory.member_format
try: - member = self.newPartition(parents=[disk], grow=True, size=1, + member = self.newPartition(parents=[disk], grow=True, + size=base_size, fmt_type=member_format) except StorageError as e: log.error("failed to create new member partition: %s" % e) @@ -3226,7 +3228,8 @@ class PartitionFactory(DeviceFactory): log.info("adjusting device size from %.2f to %.2f" % (device.size, size))
- device.req_base_size = min(PartitionFactory.default_size, size) + size = min(PartitionFactory.default_size, size) + device.req_base_size = max(size, device.format.minSize) device.req_size = device.req_base_size device.req_max_size = size device.req_grow = size > device.req_base_size
--- pyanaconda/storage/partitioning.py | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/pyanaconda/storage/partitioning.py b/pyanaconda/storage/partitioning.py index f0e0191..4f14cb5 100644 --- a/pyanaconda/storage/partitioning.py +++ b/pyanaconda/storage/partitioning.py @@ -770,6 +770,9 @@ def doPartitioning(storage): partition.req_base_size = partition.size partition.req_size = partition.size finally: + # these are only valid for one allocation run + storage.size_sets = [] + # The number and thus the name of partitions may have changed now, # allocatePartitions() takes care of this for new partitions, but not # for pre-existing ones, so we update the name of all partitions here
This was only triggered if none of the partitions being allocated were growable, which has become a very rare case. --- pyanaconda/storage/partitioning.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/pyanaconda/storage/partitioning.py b/pyanaconda/storage/partitioning.py index 4f14cb5..0b9e99c 100644 --- a/pyanaconda/storage/partitioning.py +++ b/pyanaconda/storage/partitioning.py @@ -1006,7 +1006,7 @@ def allocatePartitions(storage, disks, partitions, freespace):
# update the chosen free region unless the previous # choice yielded greater total growth - if new_growth <= growth: + if free is not None and new_growth <= growth: log.debug("keeping old free: %d <= %d" % (new_growth, growth)) update = False
They won't show up in /etc/fstab and they don't have mountpoints, so it really doesn't matter if they exist or not. We want to include them in the new root regardless. --- pyanaconda/ui/gui/spokes/custom.py | 11 ++++------- 1 files changed, 4 insertions(+), 7 deletions(-)
diff --git a/pyanaconda/ui/gui/spokes/custom.py b/pyanaconda/ui/gui/spokes/custom.py index 6f70bb6..4eabdee 100644 --- a/pyanaconda/ui/gui/spokes/custom.py +++ b/pyanaconda/ui/gui/spokes/custom.py @@ -553,13 +553,10 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker): if d.format.type == "swap" and d.format.exists]
@property - def existingBootLoaderDevices(self): + def bootLoaderDevices(self): devices = [] format_types = ["biosboot", "prepboot"] for device in self._devices: - if not device.format.exists: - continue - if device.format.type not in format_types: continue
@@ -668,7 +665,7 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker): if new_mounts or new_devices: new_devices.extend(self.__storage.mountpoints.values()) new_devices.extend(self.existingSwaps) - new_devices.extend(self.existingBootLoaderDevices) + new_devices.extend(self.bootLoaderDevices)
new_devices = list(set(new_devices))
@@ -697,7 +694,7 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker): if getattr(d.format, "mountpoint", None)])
for device in new_devices: - if device in self.existingBootLoaderDevices: + if device in self.bootLoaderDevices: mounts[device.format.type] = device
new_root = Root(mounts=mounts, swaps=swaps, name=new_install_name) @@ -811,7 +808,7 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker): devices.extend(self.existingSwaps)
# also pull in biosboot and prepboot that are on our boot disk - devices.extend(self.existingBootLoaderDevices) + devices.extend(self.bootLoaderDevices)
for _device in devices: mountpoint = getattr(_device.format, "mountpoint", "") or ""
This will only help if the disks and/or their free regions are very small. --- pyanaconda/ui/gui/spokes/storage.py | 37 ++++++++++++++++++++++++++++------ 1 files changed, 30 insertions(+), 7 deletions(-)
diff --git a/pyanaconda/ui/gui/spokes/storage.py b/pyanaconda/ui/gui/spokes/storage.py index 0eaabb1..711ad0c 100644 --- a/pyanaconda/ui/gui/spokes/storage.py +++ b/pyanaconda/ui/gui/spokes/storage.py @@ -378,15 +378,38 @@ class StorageSpoke(NormalSpoke, StorageChecker): try: doKickstartStorage(self.storage, self.data, self.instclass) except StorageError as e: - log.error("storage configuration failed: %s" % e) - self.errors = str(e).split("\n") communication.send_message(self.__class__.__name__, _("Failed to save storage configuration...")) - self.data.clearpart.type = CLEARPART_TYPE_NONE - self.data.clearpart.initAll = False - self.storage.config.update(self.data) - self.storage.autoPartType = self.data.autopart.type - self.storage.reset() + log.error("storage configuration failed: %s" % e) + self.errors = str(e).split("\n") + original_type = self.data.autopart.type + if original_type != AUTOPART_TYPE_LVM: + communication.send_message(self.__class__.__name__, + _("Automatic partitioning failed...")) + log.info("trying with lvm...") + self.storage.reset() + communication.send_message(self.__class__.__name__, + _("Trying fallback configuration...")) + self.data.autopart.type = AUTOPART_TYPE_LVM + self.storage.autoPartType = AUTOPART_TYPE_LVM + try: + doKickstartStorage(self.storage, self.data, self.instclass) + except StorageError as e2: + log.error("lvm failed, too: %s" % e2) + else: + self.errors = [] + + if self.errors: + communication.send_message(self.__class__.__name__, + _("Failed to save storage configuration...")) + self.data.autopart.type = original_type + self.data.clearpart.type = CLEARPART_TYPE_NONE + self.data.clearpart.initAll = False + self.storage.config.update(self.data) + self.storage.autoPartType = original_type + self.storage.reset() + else: + self.run() # emulating success path below else: if self.autopart: # this was already run as part of doAutoPartition. dumb.
On Thu, Oct 11, 2012 at 06:45:50PM -0500, David Lehman wrote:
pyanaconda/storage/__init__.py | 9 +++- pyanaconda/storage/devicelibs/mdraid.py | 14 +++--- pyanaconda/storage/partitioning.py | 8 ++-- pyanaconda/ui/gui/spokes/custom.glade | 9 ++++ pyanaconda/ui/gui/spokes/custom.py | 63 +++++++++++++++++++++---------- pyanaconda/ui/gui/spokes/lib/resize.py | 14 ++----- pyanaconda/ui/gui/spokes/storage.py | 34 ++++++++++++++-- 7 files changed, 102 insertions(+), 49 deletions(-)
These all look good to me.
anaconda-patches@lists.fedorahosted.org