diff --git a/library/blivet.py b/library/blivet.py index 67122ea7..1151c98b 100644 --- a/library/blivet.py +++ b/library/blivet.py @@ -785,16 +785,28 @@ def _resize(self): if not self._device.resizable: return - trim_percent = (1.0 - float(self._device.max_size / size)) * 100 - log.debug("resize: size=%s->%s ; trim=%s", self._device.size, size, trim_percent) - if size > self._device.max_size and trim_percent <= MAX_TRIM_PERCENT: - log.info("adjusting %s resize target from %s to %s to fit in free space", - self._volume['name'], - size, - self._device.max_size) - size = self._device.max_size - if size == self._device.size: - return + if size > self._device.size: + trim_percent = abs((1.0 - float(self._device.max_size / size)) * 100) + log.debug("resize: size=%s->%s ; trim=%s", self._device.size, size, trim_percent) + if size > self._device.max_size and trim_percent <= MAX_TRIM_PERCENT: + log.info("adjusting %s resize target from %s to %s to fit in free space", + self._volume['name'], + size, + self._device.max_size) + size = self._device.max_size + if size == self._device.size: + return + elif size < self._device.size: + trim_percent = abs((1.0 - float(self._device.min_size / size)) * 100) + log.debug("resize: size=%s->%s ; trim=%s", self._device.size, size, trim_percent) + if size < self._device.min_size and trim_percent <= MAX_TRIM_PERCENT: + log.info("adjusting %s resize target from %s to %s match device min size", + self._volume['name'], + size, + self._device.min_size) + size = self._device.min_size + if size == self._device.size: + return if not self._device.min_size <= size <= self._device.max_size: raise BlivetAnsibleError("volume '%s' cannot be resized to '%s'" % (self._volume['name'], size)) diff --git a/tests/tests_resize.yml b/tests/tests_resize.yml index f07f835c..fb24ed19 100644 --- a/tests/tests_resize.yml +++ b/tests/tests_resize.yml @@ -12,6 +12,8 @@ invalid_size2: none unused_disk_subfact: '{{ ansible_devices[unused_disks[0]] }}' too_large_size: '{{ unused_disk_subfact.sectors | int * 1.2 * 512 }}' + acc_large_size: '{{ unused_disk_subfact.sectors | int * 1.015 * 512 }}' + acc_small_size: '{{ unused_disk_subfact.sectors | int * 0.985 * 512 }}' disk_size: '{{ unused_disk_subfact.sectors | int * 512 }}' tags: - tests::lvm @@ -129,6 +131,26 @@ - name: Verify role results include_tasks: verify-role-results.yml + - name: Test for correct handling of acceptable size difference (slightly bigger than max) + block: + - name: >- + Try to resize LVM volume size to disk size + 1.5 % (less than 2 % than + maximum size should be tolerated) + include_role: + name: linux-system-roles.storage + vars: + storage_pools: + - name: foo + disks: "{{ unused_disks }}" + volumes: + - name: test1 + fs_type: ext4 + size: "{{ acc_large_size }}" + mount_point: "{{ mount_location }}" + + - name: Verify role results + include_tasks: verify-role-results.yml + - name: Test for correct handling of invalid size specification include_tasks: verify-role-failed.yml vars: @@ -428,3 +450,118 @@ - name: Verify role results include_tasks: verify-role-results.yml + + # For XFS + + - name: Test xfs + block: + - name: Run test on supported platforms + when: ((is_fedora and blivet_pkg_version is version("3.12.1-3", ">=")) or + (is_rhel8 and blivet_pkg_version is version("3.4.0-1", ">=")) or + is_rhel9 or is_rhel10) + block: + - name: >- + Create a LVM logical volume with for XFS size + {{ volume_size_before }} + include_role: + name: linux-system-roles.storage + vars: + storage_pools: + - name: foo + type: lvm + disks: "{{ unused_disks }}" + volumes: + - name: test1 + fs_type: xfs + size: "{{ volume_size_before }}" + mount_point: "{{ mount_location }}" + + - name: Verify role results + include_tasks: verify-role-results.yml + + - name: Change volume size to {{ volume_size_after }} + include_role: + name: linux-system-roles.storage + vars: + storage_pools: + - name: foo + type: lvm + disks: "{{ unused_disks }}" + volumes: + - name: test1 + fs_type: xfs + size: "{{ volume_size_after }}" + mount_point: "{{ mount_location }}" + + - name: Verify role results + include_tasks: verify-role-results.yml + + - name: Repeat for idempotency test + include_role: + name: linux-system-roles.storage + vars: + storage_pools: + - name: foo + type: lvm + disks: "{{ unused_disks }}" + volumes: + - name: test1 + fs_type: xfs + size: "{{ volume_size_after }}" + mount_point: "{{ mount_location }}" + + - name: Verify role results + include_tasks: verify-role-results.yml + + - name: Test for correct handling of shrinking (not supported by XFS) + include_tasks: verify-role-failed.yml + vars: + __storage_failed_regex: volume.+cannot be resized.+ + __storage_failed_msg: >- + Unexpected behavior w/ invalid volume size + __storage_failed_params: + storage_pools: + - name: foo + disks: "{{ unused_disks }}" + volumes: + - name: test1 + fs_type: xfs + size: "{{ volume_size_before }}" + mount_point: "{{ mount_location }}" + + - name: Test for correct handling of acceptable size difference (slightly smaller than min) + block: + - name: >- + Try to resize LVM volume size to disk size - 1.5 % (less than 2 % than + minimum size should be tolerated) + include_role: + name: linux-system-roles.storage + vars: + storage_pools: + - name: foo + disks: "{{ unused_disks }}" + volumes: + - name: test1 + fs_type: xfs + size: "{{ acc_small_size }}" + mount_point: "{{ mount_location }}" + + - name: Verify role results + include_tasks: verify-role-results.yml + + always: + - name: Clean up + include_role: + name: linux-system-roles.storage + vars: + storage_pools: + - name: foo + disks: "{{ unused_disks }}" + state: absent + volumes: + - name: test1 + size: "{{ volume_size_before }}" + mount_point: "{{ mount_location }}" + + - name: Verify role results + include_tasks: verify-role-results.yml