diff --git a/blivet/devices/partition.py b/blivet/devices/partition.py index bbc637bfd..62e34ce46 100644 --- a/blivet/devices/partition.py +++ b/blivet/devices/partition.py @@ -736,7 +736,10 @@ def _setSize(self, newsize): raise ValueError("new size must of type Size") if not self.exists: - raise errors.DeviceError("device does not exist", self.name) + # device does not exist (a partition request), just set basic values + self._size = newsize + self.req_size = newsize + self.req_base_size = newsize if newsize > self.disk.size: raise ValueError("partition size would exceed disk size") diff --git a/blivet/partitioning.py b/blivet/partitioning.py index 8b5269287..8e0776321 100644 --- a/blivet/partitioning.py +++ b/blivet/partitioning.py @@ -115,7 +115,7 @@ def _scheduleImplicitPartitions(storage, disks, min_luks_entropy=0): return devs -def _schedulePartitions(storage, disks, min_luks_entropy=0, requests=None): +def _schedulePartitions(storage, disks, implicit_devices, min_luks_entropy=0, requests=None): """ Schedule creation of autopart/reqpart partitions. This only schedules the requests for actual partitions. @@ -242,8 +242,29 @@ def _schedulePartitions(storage, disks, min_luks_entropy=0, requests=None): parents=dev) storage.createDevice(luks_dev) - # make sure preexisting broken lvm/raid configs get out of the way - return + 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. @@ -419,7 +440,7 @@ def doAutoPartition(storage, data, min_luks_entropy=0): raise NotEnoughFreeSpaceError(_("Not enough free space on disks for " "automatic partitioning")) - _schedulePartitions(storage, disks, min_luks_entropy=min_luks_entropy) + devs = _schedulePartitions(storage, disks, devs, min_luks_entropy=min_luks_entropy) # run the autopart function to allocate and grow partitions doPartitioning(storage)