diff --git a/.gitignore b/.gitignore index 9bda8fb..616bbbc 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,6 @@ inventory/* *.bak test*.yml misc +filter_plugins/__pycache__ +filter_plugins/*.bak +python/ diff --git a/bigboot-v3.yml b/bigboot-v3.yml new file mode 100644 index 0000000..c80a739 --- /dev/null +++ b/bigboot-v3.yml @@ -0,0 +1,19 @@ +--- +- name: Shrink logical volumes + hosts: bigboot + become: false + gather_facts: true + + vars: + bigboot_size: 2G + + tasks: + - name: Capture boot device details + ansible.builtin.import_tasks: tasks/capture_boot_device_details.yml + + - name: Shrink a logical volume for /boot expansion if needed + ansible.builtin.import_tasks: tasks/bigboot_manage_lv.yml + + - name: Expand the /boot partition as requested + ansible.builtin.import_role: + name: infra.lvm_snapshots.bigboot diff --git a/collections/ansible_collections/infra/lvm_snapshots/FILES.json b/collections/ansible_collections/infra/lvm_snapshots/FILES.json index 5597b84..4292e71 100644 --- a/collections/ansible_collections/infra/lvm_snapshots/FILES.json +++ b/collections/ansible_collections/infra/lvm_snapshots/FILES.json @@ -263,7 +263,7 @@ "name": "roles/bigboot/templates/increase-boot-partition.sh.j2", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f125865dca89db42ab397132207e038d645bef7ab3d6f151b72624d55ac36dd8", + "chksum_sha256": "14c7557901b1d79e51593fe03c91b64e96c02f8032f89c74600ce1dac944051c", "format": 1 }, { diff --git a/collections/ansible_collections/infra/lvm_snapshots/MANIFEST.json b/collections/ansible_collections/infra/lvm_snapshots/MANIFEST.json index 5d4c941..0ca4445 100644 --- a/collections/ansible_collections/infra/lvm_snapshots/MANIFEST.json +++ b/collections/ansible_collections/infra/lvm_snapshots/MANIFEST.json @@ -28,7 +28,7 @@ "name": "FILES.json", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ebc781493080569053657782010cf8835d45e10f26f7055780997ce3389e5424", + "chksum_sha256": "9f8f48dbcdee8dfa68367c409f646da5af0b06b9b2ccab8d1b48e15885974994", "format": 1 }, "format": 1 diff --git a/collections/ansible_collections/infra/lvm_snapshots/roles/bigboot/templates/increase-boot-partition.sh.j2 b/collections/ansible_collections/infra/lvm_snapshots/roles/bigboot/templates/increase-boot-partition.sh.j2 index c18bcd2..a92bf64 100644 --- a/collections/ansible_collections/infra/lvm_snapshots/roles/bigboot/templates/increase-boot-partition.sh.j2 +++ b/collections/ansible_collections/infra/lvm_snapshots/roles/bigboot/templates/increase-boot-partition.sh.j2 @@ -12,9 +12,16 @@ disable_lvm_lock(){ mv "$tmpfile" /etc/lvm/lvm.conf } +activate_volume_groups(){ + for vg in `/usr/sbin/lvm vgs -o name --noheading 2>/dev/null`; do + /usr/sbin/lvm vgchange -ay $vg + done +} + main() { name=$(basename "$0") start=$(/usr/bin/date +%s) + activate_volume_groups disable_lvm_lock # run bigboot.sh to increase boot partition and file system size ret=$(sh /usr/bin/bigboot.sh -d="{{ bigboot_boot_device_name }}" -s="{{ bigboot_size }}" -b="{{ bigboot_boot_partition_number }}" -p="{{ bigboot_boot_device_partition_prefix }}" 2>/dev/kmsg) diff --git a/filter_plugins/get_block_size.py b/filter_plugins/get_block_size.py new file mode 100755 index 0000000..6247da3 --- /dev/null +++ b/filter_plugins/get_block_size.py @@ -0,0 +1,26 @@ +#!/usr/bin/python3 + +BLOCK_SIZE = 4 + +class FilterModule (object): + def filters (self): + return { + 'get_block_size_up': self.get_block_size_up, + 'get_block_size_down': self.get_block_size_down, + 'moo': self.moo, + } + + + def get_block_size_up(self, start_size): + while start_size % BLOCK_SIZE != 0: + start_size += 1 + return ('{}{}'.format(start_size, 'M')) + + def get_block_size_down(self, start_size): + while start_size % BLOCK_SIZE != 0: + start_size -= 1 + return ('{}{}'.format(start_size, 'M')) + + def moo(self, a_variable): + a_new_variable = (str(a_variable) + '~~~~MOOOOOOOOOOOOOOOOOOOOOOOOO! => ' + '%s' % type(a_variable)) + return a_new_variable diff --git a/tasks/bigboot_manage_lv.yml b/tasks/bigboot_manage_lv.yml new file mode 100644 index 0000000..ede91b8 --- /dev/null +++ b/tasks/bigboot_manage_lv.yml @@ -0,0 +1,83 @@ +--- +- name: Capture logical volume adjacent to /boot + ansible.builtin.shell: + cmd: | + set -o pipefail + lsblk -p -o name,type|grep lvm|head -1 + executable: /bin/bash + changed_when: false + register: bigboot_adjacent_lvm + +- name: Set adjacent LVM device name + ansible.builtin.set_fact: + bigboot_adjacent_lvm_device: "{{ bigboot_adjacent_lvm.stdout | regex_replace('.*(\\/dev.*)\\s+.*$', '\\1') }}" + +- name: Get logical volume mount information + ansible.builtin.set_fact: + bigboot_lv_info: "{{ ansible_facts.mounts \ + | selectattr('device', 'equalto', bigboot_adjacent_lvm_device | trim) | first }}" + +- name: Capture shrink size for logical volume + ansible.builtin.set_fact: + bigboot_lv_shrink_size: "{{ bigboot_lv_info.size_total - bigboot_expansion_diff | int }}" + +- name: Capture logical volume name + ansible.builtin.shell: + cmd: | + set -o pipefail + lvdisplay {{ bigboot_adjacent_lvm_device }} | grep -i 'vg name' + executable: /bin/bash + changed_when: false + register: bigboot_lv_vg_name + +- name: Format logical volume name + ansible.builtin.set_fact: + bigboot_lv_vg_name: "{{ bigboot_lv_vg_name.stdout | regex_replace('^.*?\\s+(\\w+)$', '\\1') }}" + +- name: Capture volume group free PE + ansible.builtin.shell: + cmd: | + set -o pipefail + vgdisplay {{ bigboot_lv_vg_name }} | grep -i 'free' + executable: /bin/bash + changed_when: false + register: bigboot_lv_vg_free_pe + +- name: Format logical volume free PE + ansible.builtin.set_fact: + # Ex: + # Free PE / Size 320 / 1.25 GiB" + # Free PE / Size 189 / 756.00 MiB" + # Free PE / Size 0 / 0 + bigboot_lv_vg_free_pe: "{{ bigboot_lv_vg_free_pe.stdout | regex_replace('^.*/.*/\\s+(.*)', '\\1') }}" + +- name: Get size only from the values + ansible.builtin.set_fact: + bigboot_lv_size_in_mb: + "{{ bigboot_lv_vg_free_pe | regex_replace('i|\\s+|<', '') | human_to_bytes | human_readable(unit='M') }}" + # "{{ bigboot_lv_vg_free_pe | regex_replace('i', '') | regex_replace(' ', '') | human_to_bytes | human_readable(unit='M') }}" + bigboot_size_in_mb: "{{ bigboot_size[:-1] }}" + +- name: Check if we can shrink the logical volume + block: + - name: Assert if we need to execute the shrink_lv role + ansible.builtin.assert: + that: + - bigboot_lv_vg_free_pe[:-4] != '' + - (bigboot_lv_size_in_mb[:-6] | int - bigboot_size_in_mb | int ) >= 0 + # - (bigboot_lv_info.size_available - bigboot_size | human_to_bytes) >= 0 + fail_msg: Not enough free PE available for /boot expansion. + + rescue: + - name: Assert there is free space available for shrinking + ansible.builtin.assert: + that: (bigboot_lv_info.size_available - bigboot_size | human_to_bytes) >= 0 + fail_msg: "Not enough space available on {{ bigboot_adjacent_lvm_device | trim }} for shrinking." + + - name: Execute Shrink_LV role to resize target logical volume + ansible.builtin.import_role: + name: infra.lvm_snapshots.shrink_lv + vars: + shrink_lv_devices: + - device: "{{ bigboot_adjacent_lvm_device | trim }}" + size: "{{ bigboot_lv_shrink_size | int | human_readable | regex_replace('^(.*\\.\\d+)\\s+(\\w).*$', '\\1\\2') }}" diff --git a/tasks/capture_boot_device_details.yml b/tasks/capture_boot_device_details.yml new file mode 100644 index 0000000..c279a5c --- /dev/null +++ b/tasks/capture_boot_device_details.yml @@ -0,0 +1,36 @@ +--- +- name: Get /boot mount information + ansible.builtin.set_fact: + bigboot_boot_info: "{{ ansible_facts.mounts \ + | selectattr('mount', 'equalto', '/boot') | first }}" + +- name: Capture required expansion space + ansible.builtin.set_fact: + bigboot_expansion_diff: + "{{ bigboot_size | human_to_bytes - bigboot_boot_info.size_total | int }}" + +- name: Convert size difference to MB + ansible.builtin.set_fact: + bigboot_size_expansion_mb: "{{ bigboot_expansion_diff | int | human_readable(unit='M') }}" + +- name: Set bigboot size 4k aligned + ansible.builtin.set_fact: + bigboot_size: "{{ bigboot_size_expansion_mb[:-2] \ + | regex_replace('\\.\\d+ ', '') \ + | int | get_block_size_up }}" + +- name: Validate if we need to expand boot + block: + - name: Assert that /boot requires expansion + ansible.builtin.assert: + that: bigboot_expansion_diff | int <= 0 + fail_msg: The /boot partition will need to be resized + success_msg: The /boot partition is already at the desired size + + - name: The /boot parition is already at the desired size. + ansible.builtin.meta: end_host + + rescue: + - name: Expansion of /boot required + ansible.builtin.debug: + msg: "Expanding /boot by an additional {{ bigboot_size }}."