[PATCH 4/4] Try to add new device to an existing container if disks are full.
David Lehman
dlehman at redhat.com
Wed Nov 21 19:44:40 UTC 2012
VGs have a freeSpace attribute while btrfs vols do not. Choose the
existing container with the most free space or the most total space.
---
pyanaconda/storage/__init__.py | 17 +++++++++----
pyanaconda/ui/gui/spokes/custom.py | 47 +++++++++++++++++++++++++++++------
2 files changed, 51 insertions(+), 13 deletions(-)
diff --git a/pyanaconda/storage/__init__.py b/pyanaconda/storage/__init__.py
index 07f2cce..32ca2cb 100644
--- a/pyanaconda/storage/__init__.py
+++ b/pyanaconda/storage/__init__.py
@@ -1992,15 +1992,15 @@ class Storage(object):
self, size, [d.name for d in disks], raid_level))
return factory_class(self, size, disks, raid_level, encrypted)
- def getContainer(self, factory, device=None, container_name=None):
+ def getContainer(self, factory, device=None, name=None, existing=False):
# XXX would it be useful to implement this as a series of fallbacks
# instead of mutually exclusive branches?
container = None
- if container_name:
- container = self.devicetree.getDeviceByName(container_name)
+ if name:
+ container = self.devicetree.getDeviceByName(name)
if container and container not in factory.container_list:
log.debug("specified container name %s is wrong type (%s)"
- % (container_name, container.type))
+ % (name, container.type))
container = None
elif device:
if hasattr(device, "vg"):
@@ -2012,6 +2012,13 @@ class Storage(object):
if containers:
container = containers[0]
+ if container is None and existing:
+ containers = [c for c in factory.container_list if c.exists]
+ if containers:
+ containers.sort(key=lambda c: getattr(c, "freeSpace", c.size),
+ reverse=True)
+ container = containers[0]
+
return container
def __cleanUpMemberDevices(self, members, container=None):
@@ -2108,7 +2115,7 @@ class Storage(object):
container = self.getContainer(factory, device=device,
- container_name=container_name)
+ name=container_name)
# TODO: striping, mirroring, &c
# TODO: non-partition members (pv-on-md)
diff --git a/pyanaconda/ui/gui/spokes/custom.py b/pyanaconda/ui/gui/spokes/custom.py
index c52789c..ee70c14 100644
--- a/pyanaconda/ui/gui/spokes/custom.py
+++ b/pyanaconda/ui/gui/spokes/custom.py
@@ -24,7 +24,6 @@
# - Add a way for users to specify the names of md, lv, subvol devices.
# - We should either remove boot disk selection from the cart we show from here
# or re-partition when it gets changed to make a best-effort at keeping up.
-# - Add new LVs to existing VG if creating a new VG fails outright.
# - Deleting an LV is not reflected in available space in the bottom left.
# - this is only true for preexisting LVs
# - Device descriptions, suggested sizes, etc. should be moved out into a support file.
@@ -35,6 +34,7 @@
# - If you click to add a mountpoint while editing a device the lightbox
# screenshot is taken prior to the ui update so the background shows the old
# size and free space while you're deciding on a size for the new device.
+# - DeviceTree.populate brings back deleted devices when unlocking LUKS.
import gettext
_ = lambda x: gettext.ldgettext("anaconda", x)
@@ -122,6 +122,11 @@ DEVICE_TEXT_PARTITION = N_("Standard Partition")
DEVICE_TEXT_BTRFS = N_("BTRFS")
DEVICE_TEXT_DISK = N_("Disk")
+device_text_map = {DEVICE_TYPE_LVM: DEVICE_TEXT_LVM,
+ DEVICE_TYPE_MD: DEVICE_TEXT_MD,
+ DEVICE_TYPE_PARTITION: DEVICE_TEXT_PARTITION,
+ DEVICE_TYPE_BTRFS: DEVICE_TEXT_BTRFS}
+
options_page_dict = {DEVICE_TYPE_LVM: 0,
DEVICE_TYPE_MD: 1,
DEVICE_TYPE_BTRFS: 2}
@@ -1005,7 +1010,7 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker):
old_container = self.__storage.getContainer(factory,
device=device)
container = self.__storage.getContainer(factory,
- container_name=self._device_container_name)
+ name=self._device_container_name)
if self._device_container_name != old_container.name:
old_container_name = old_container.name
changed_container = True
@@ -1713,12 +1718,13 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker):
encrypted = False
disks = self._clearpartDevices
+ size = float(size.convertTo(spec="mb"))
self.clear_errors()
with ui_storage_logger():
try:
self.__storage.newDevice(device_type,
- size=float(size.convertTo(spec="mb")),
+ size=size,
fstype=fstype,
mountpoint=mountpoint,
encrypted=encrypted,
@@ -1732,11 +1738,36 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker):
self._reset_storage()
except StorageError as e:
log.error("newDevice failed: %s" % e)
- self._error = e
- self.window.set_info(Gtk.MessageType.ERROR,
- _("Failed to add new device. Click for "
- "details."))
- self.window.show_all()
+ log.debug("trying to find an existing container to use")
+ factory = self.__storage.getDeviceFactory(device_type, size)
+ container = self.__storage.getContainer(factory, existing=True)
+ log.debug("found container %s" % container)
+ if container:
+ try:
+ self.__storage.newDevice(device_type,
+ size=size,
+ fstype=fstype,
+ mountpoint=mountpoint,
+ encrypted=encrypted,
+ disks=disks,
+ container_name=container.name)
+ except StorageError as e2:
+ log.error("newDevice failed w/ old container: %s" % e2)
+ else:
+ type_str = device_text_map[device_type]
+ self.window.set_info(Gtk.MessageType.INFO,
+ _("Added new %s to existing "
+ "container %s.")
+ % (type_str, container.name))
+ self.window.show_all()
+ e = None
+
+ if e:
+ self._error = e
+ self.window.set_info(Gtk.MessageType.ERROR,
+ _("Failed to add new device. Click for "
+ "details."))
+ self.window.show_all()
self._devices = self.__storage.devices
self._do_refresh()
--
1.7.7.6
More information about the anaconda-patches
mailing list