rhel-system-roles/storage-trim-volume-size.diff
DistroBaker f6ce71d308 Merged update from upstream sources
This is an automated DistroBaker update from upstream sources.
If you do not know what this is about or would like to opt out,
contact the OSCI team.

Source: https://src.fedoraproject.org/rpms/linux-system-roles.git#490700ef996ddf949520cb4c0fedd290cc657aed
2021-02-22 23:36:10 +01:00

327 lines
12 KiB
Diff

diff --git a/library/blivet.py b/library/blivet.py
index e927121..f59f821 100644
--- a/library/blivet.py
+++ b/library/blivet.py
@@ -130,6 +130,9 @@ if BLIVET_PACKAGE:
set_up_logging()
log = logging.getLogger(BLIVET_PACKAGE + ".ansible")
+
+MAX_TRIM_PERCENT = 2
+
use_partitions = None # create partitions on pool backing device disks?
disklabel_type = None # user-specified disklabel type
safe_mode = None # do not remove any existing devices or formatting
@@ -445,8 +448,16 @@ class BlivetVolume(BlivetBase):
if not self._device.resizable:
return
- if self._device.format.resizable:
- self._device.format.update_size_info()
+ 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 not self._device.min_size <= size <= self._device.max_size:
raise BlivetAnsibleError("volume '%s' cannot be resized to '%s'" % (self._volume['name'], size))
@@ -610,10 +621,18 @@ class BlivetLVMVolume(BlivetVolume):
raise BlivetAnsibleError("invalid size '%s' specified for volume '%s'" % (self._volume['size'], self._volume['name']))
fmt = self._get_format()
+ trim_percent = (1.0 - float(parent.free_space / size))*100
+ log.debug("size: %s ; %s", size, trim_percent)
if size > parent.free_space:
- raise BlivetAnsibleError("specified size for volume '%s' exceeds available space in pool '%s' (%s)" % (size,
- parent.name,
- parent.free_space))
+ if trim_percent > MAX_TRIM_PERCENT:
+ raise BlivetAnsibleError("specified size for volume '%s' exceeds available space in pool '%s' (%s)"
+ % (size, parent.name, parent.free_space))
+ else:
+ log.info("adjusting %s size from %s to %s to fit in %s free space", self._volume['name'],
+ size,
+ parent.free_space,
+ parent.name)
+ size = parent.free_space
try:
device = self._blivet.new_lv(name=self._volume['name'],
diff --git a/tests/tests_create_lv_size_equal_to_vg.yml b/tests/tests_create_lv_size_equal_to_vg.yml
new file mode 100644
index 0000000..21a5788
--- /dev/null
+++ b/tests/tests_create_lv_size_equal_to_vg.yml
@@ -0,0 +1,48 @@
+---
+- hosts: all
+ become: true
+ vars:
+ storage_safe_mode: false
+ mount_location: '/opt/test1'
+ volume_group_size: '10g'
+ lv_size: '10g'
+ unused_disk_subfact: '{{ ansible_devices[unused_disks[0]] }}'
+ disk_size: '{{ unused_disk_subfact.sectors|int *
+ unused_disk_subfact.sectorsize|int }}'
+
+ tasks:
+ - include_role:
+ name: linux-system-roles.storage
+
+ - include_tasks: get_unused_disk.yml
+ vars:
+ min_size: "{{ volume_group_size }}"
+ max_return: 1
+
+ - name: Create one lv which size is equal to vg size
+ include_role:
+ name: linux-system-roles.storage
+ vars:
+ storage_pools:
+ - name: foo
+ disks: "{{ unused_disks }}"
+ volumes:
+ - name: test1
+ size: "{{ lv_size }}"
+ mount_point: "{{ mount_location }}"
+
+ - include_tasks: verify-role-results.yml
+
+ - name: Clean up
+ include_role:
+ name: linux-system-roles.storage
+ vars:
+ storage_pools:
+ - name: foo
+ disks: "{{ unused_disks }}"
+ state: "absent"
+ volumes:
+ - name: test1
+ mount_point: "{{ mount_location }}"
+
+ - include_tasks: verify-role-results.yml
diff --git a/tests/tests_lvm_auto_size_cap.yml b/tests/tests_lvm_auto_size_cap.yml
new file mode 100644
index 0000000..fb17c23
--- /dev/null
+++ b/tests/tests_lvm_auto_size_cap.yml
@@ -0,0 +1,89 @@
+---
+- hosts: all
+ become: true
+
+ tasks:
+ - include_role:
+ name: linux-system-roles.storage
+
+ - include_tasks: get_unused_disk.yml
+ vars:
+ min_size: 10g
+ max_return: 1
+
+ - command: lsblk -b -l --noheadings -o NAME,SIZE
+ register: storage_test_lsblk
+
+ - set_fact:
+ test_disk_size: "{{ storage_test_lsblk.stdout_lines|map('regex_search', '^' + unused_disks[0] + '\\s+\\d+$')|select('string')|first|regex_replace('^\\w+\\s+', '') }}"
+
+ - package:
+ name: bc
+ state: installed
+
+ - command:
+ cmd: bc
+ stdin: "{{ test_disk_size }} *2"
+ register: doubled_size
+
+ - name: Test handling of too-large LVM volume size
+ block:
+ - name: Try to create a pool containing one volume twice the size of the backing disk
+ include_role:
+ name: linux-system-roles.storage
+ vars:
+ storage_pools:
+ - name: foo
+ type: lvm
+ disks: "{{ unused_disks }}"
+ volumes:
+ - name: test1
+ size: "{{ doubled_size.stdout|trim }}"
+ - name: unreachable task
+ fail:
+ msg: UNREACH
+ rescue:
+ - name: Check that we failed in the role
+ assert:
+ that:
+ - ansible_failed_result.msg != 'UNREACH'
+ - blivet_output.failed and
+ blivet_output.msg|regex_search('specified size for volume.+exceeds available')
+ msg: "Role has not failed when it should have"
+
+ - name: Create a pool containing one volume the same size as the backing disk
+ include_role:
+ name: linux-system-roles.storage
+ vars:
+ storage_pools:
+ - name: foo
+ disks: "{{ unused_disks }}"
+ volumes:
+ - name: test1
+ size: "{{ test_disk_size }}"
+
+ - include_tasks: verify-role-results.yml
+
+ - name: Repeat the previous invocation to verify idempotence
+ include_role:
+ name: linux-system-roles.storage
+ vars:
+ storage_pools:
+ - name: foo
+ type: lvm
+ disks: "{{ unused_disks }}"
+ volumes:
+ - name: test1
+ size: "{{ test_disk_size }}"
+
+ - include_tasks: verify-role-results.yml
+
+ - name: Clean up
+ include_role:
+ name: linux-system-roles.storage
+ vars:
+ storage_pools:
+ - name: foo
+ disks: "{{ unused_disks }}"
+ state: absent
+ volumes: []
diff --git a/tests/tests_lvm_errors.yml b/tests/tests_lvm_errors.yml
index 37d41dc..e8dc4f4 100644
--- a/tests/tests_lvm_errors.yml
+++ b/tests/tests_lvm_errors.yml
@@ -11,8 +11,6 @@
- '/non/existent/disk'
invalid_size: 'xyz GiB'
unused_disk_subfact: '{{ ansible_devices[unused_disks[0]] }}'
- too_large_size: '{{ (unused_disk_subfact.sectors|int + 1) *
- unused_disk_subfact.sectorsize|int }}'
tasks:
- include_role:
@@ -86,39 +84,6 @@
- ansible_failed_result.msg != 'UNREACH'
msg: "Role has not failed when it should have"
- # the following does not work properly
- # - name: Verify the output
- # assert:
- # that: "{{ blivet_output.failed and
- # blivet_output.msg|regex_search('invalid size.+for volume') and
- # not blivet_output.changed }}"
- # msg: "Unexpected behavior w/ invalid volume size"
-
- - name: Test for correct handling of too-large volume size.
- block:
- - name: Try to create LVM with a too-large volume size.
- include_role:
- name: linux-system-roles.storage
- vars:
- storage_pools:
- - name: foo
- disks: "{{ unused_disks }}"
- volumes:
- - name: test1
- size: "{{ too_large_size }}"
- mount_point: "{{ mount_location1 }}"
-
- - name: unreachable task
- fail:
- msg: UNREACH
-
- rescue:
- - name: Check that we failed in the role
- assert:
- that:
- - ansible_failed_result.msg != 'UNREACH'
- msg: "Role has not failed when it should have"
-
# the following does not work properly
# - name: Verify the output
# assert:
@@ -138,7 +103,7 @@
disks: "{{ unused_disks[0] }}"
volumes:
- name: test1
- size: "{{ too_large_size }}"
+ size: "{{ volume_size }}"
mount_point: "{{ mount_location1 }}"
- name: unreachable task
@@ -171,7 +136,7 @@
disks: []
volumes:
- name: test1
- size: "{{ too_large_size }}"
+ size: "{{ volume1_size }}"
mount_point: "{{ mount_location1 }}"
- name: unreachable task
diff --git a/tests/tests_misc.yml b/tests/tests_misc.yml
index a69ee98..3139bc7 100644
--- a/tests/tests_misc.yml
+++ b/tests/tests_misc.yml
@@ -7,7 +7,7 @@
volume_group_size: '5g'
volume1_size: '4g'
unused_disk_subfact: '{{ ansible_devices[unused_disks[0]] }}'
- too_large_size: '{{ (unused_disk_subfact.sectors|int + 1) *
+ too_large_size: '{{ (unused_disk_subfact.sectors|int * 1.2) *
unused_disk_subfact.sectorsize|int }}'
tasks:
diff --git a/tests/tests_resize.yml b/tests/tests_resize.yml
index 9eeb2b9..209d129 100644
--- a/tests/tests_resize.yml
+++ b/tests/tests_resize.yml
@@ -9,7 +9,7 @@
invalid_size1: 'xyz GiB'
invalid_size2: 'none'
unused_disk_subfact: '{{ ansible_devices[unused_disks[0]] }}'
- too_large_size: '{{ (unused_disk_subfact.sectors|int + 1) *
+ too_large_size: '{{ unused_disk_subfact.sectors|int * 1.2 *
unused_disk_subfact.sectorsize|int }}'
disk_size: '{{ unused_disk_subfact.sectors|int *
unused_disk_subfact.sectorsize|int }}'
@@ -122,23 +122,7 @@
size: "{{ disk_size }}"
mount_point: "{{ mount_location }}"
- - name: Unreachable task
- fail:
- msg: UNREACH
-
- rescue:
- - name: Check that we failed in the role
- assert:
- that:
- - ansible_failed_result.msg != 'UNREACH'
- msg: "Role has not failed when it should have"
-
- - name: Verify the output
- assert:
- that: "blivet_output.failed and
- blivet_output.msg|regex_search('volume.+cannot be resized to.+') and
- not blivet_output.changed"
- msg: "Unexpected behavior w/ invalid volume size"
+ - include_tasks: verify-role-results.yml
- name: Test for correct handling of invalid size specification
block: