Containers size calculations were not taking into account the size of an
already-defined device while adjusting the size of the same device. This
meant that changing an lv size from 10G to 5G _grew_ the container by 5G
instead of shrinking it by 5G.
---
pyanaconda/storage/__init__.py | 48 +++++++++++++++++++++++++++++------
pyanaconda/ui/gui/spokes/custom.py | 14 +++++++++-
2 files changed, 51 insertions(+), 11 deletions(-)
diff --git a/pyanaconda/storage/__init__.py b/pyanaconda/storage/__init__.py
index 259054f..8691bef 100644
--- a/pyanaconda/storage/__init__.py
+++ b/pyanaconda/storage/__init__.py
@@ -1771,7 +1771,8 @@ class Storage(object):
return fstype
- def setContainerMembers(self, container, factory, members=None):
+ def setContainerMembers(self, container, factory, members=None,
+ device=None):
""" Set up and return the container's member partitions.
"""
if factory.member_list is not None:
# short-circuit the logic below for partitions
@@ -1793,7 +1794,7 @@ class Storage(object):
if container:
log.debug("using container %s with %d devices" % (container.name,
len(self.devicetree.getChildren(container))))
- container_size = factory.container_size_func(container)
+ container_size = factory.container_size_func(container, device)
log.debug("raw container size reported as %d" % container_size)
if members:
@@ -1993,7 +1994,7 @@ class Storage(object):
try:
parents = self.setContainerMembers(container, factory,
- members=members)
+ members=members, device=device)
except PartitioningError as e:
# If this is a new device, just clean up and get out.
if device:
@@ -2011,7 +2012,8 @@ class Storage(object):
try:
self.setContainerMembers(container, factory,
- members=members)
+ members=members,
+ device=device)
except StorageError as e:
log.error("failed to revert device size: %s" % e)
raise ErrorRecoveryFailure("failed to revert container")
@@ -2030,6 +2032,9 @@ class Storage(object):
raise
self.createDevice(container)
+ elif container and not container.exists and \
+ hasattr(container, "dataLevel"):
+ container.dataLevel = factory.raid_level
if container:
parents = [container]
@@ -3148,9 +3153,14 @@ class DeviceFactory(object):
""" Perform actions required after device creation.
"""
pass
- def container_size_func(self, container):
- """ Return the total used space in the specified container.
"""
- return container.size
+ def container_size_func(self, container, device=None):
+ """ Return the total space needed for the specified container.
"""
+ size = container.size
+ size += self.device_size
+ if device:
+ size -= device.size
+
+ return size
@property
def device_size(self):
@@ -3219,6 +3229,20 @@ class BTRFSFactory(DeviceFactory):
kwargs["dataLevel"] = self.raid_level
return getattr(self.storage, self.new_container_attr)(*args, **kwargs)
+ def container_size_func(self, container, device=None):
+ """ Return the total space needed for the specified container.
"""
+ if container.exists:
+ container_size = container.size
+ else:
+ container_size = sum([s.req_size for s in container.subvolumes])
+
+ if device:
+ size = self.device_size
+ else:
+ size = container_size + self.device_size
+
+ return size
+
@property
def device_size(self):
# until we get/need something better
@@ -3248,8 +3272,14 @@ class LVMFactory(DeviceFactory):
size_func_kwargs["striped"] = True
return get_pv_space(self.size, len(self.disks), **size_func_kwargs)
- def container_size_func(self, container):
- return container.size - container.freeSpace
+ def container_size_func(self, container, device=None):
+ size = sum([p.size for p in container.parents])
+ size -= container.freeSpace
+ size += self.device_size
+ if device:
+ size -= get_pv_space(device.size, len(container.parents))
+
+ return size
def set_device_size(self, container, device=None):
size = self.size
diff --git a/pyanaconda/ui/gui/spokes/custom.py b/pyanaconda/ui/gui/spokes/custom.py
index 475e0e4..dfa7b52 100644
--- a/pyanaconda/ui/gui/spokes/custom.py
+++ b/pyanaconda/ui/gui/spokes/custom.py
@@ -1089,6 +1089,7 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker):
selector.props.name = (self._mountpointName(mountpoint) or
selector._device.format.name)
+ self._devices = self.__storage.devices
# update size props of all btrfs devices' selectors
self._update_btrfs_selectors()
@@ -1139,6 +1140,8 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker):
device_configuration_error_msg)
self.window.show_all()
+ self._devices = self.__storage.devices
+
log.debug("updating selector size to '%s'"
% str(Size(spec="%f MB" % device.size)).upper())
# update the selector's size property
@@ -1187,6 +1190,9 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker):
## FORMATTING
##
encryption_changed = (device != old_device)
+ if encryption_changed:
+ self._devices = self.__storage.devices
+
fs_type_changed = (fs_type_short != old_fs_type)
fs_exists = old_device.format.exists
if encryption_changed or fs_type_changed or fs_exists:
@@ -1706,17 +1712,21 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker):
device.vg._removeLogVol(device)
container = device.vg
device_type = AUTOPART_TYPE_LVM
+ raid_level = None
elif hasattr(device, "volume"):
device.volume._removeSubVolume(device.name)
container = device.volume
device_type = AUTOPART_TYPE_BTRFS
+ raid_level = container.dataLevel
if container and not container.exists and \
self.__storage.devicetree.getChildren(container):
# adjust container to size of remaining devices
with ui_storage_logger():
- # TODO: raid
- factory = self.__storage.getDeviceFactory(device_type, 0)
+ factory = self.__storage.getDeviceFactory(device_type, 0,
+ disks=container.disks,
+ encrypted=container.encrypted,
+ raid_level=raid_level)
parents = self.__storage.setContainerMembers(container, factory)
# if this device has parents with no other children, remove them too
--
1.7.7.6