From 982b79f32e06fa411f92a0243b6709db1a4cebe4 Mon Sep 17 00:00:00 2001 From: ogrechko Date: Wed, 6 May 2026 19:26:33 +0300 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D1=82?= =?UTF-8?q?=D1=8C=20ansible/expand=5Fubuntu=5Fdisk.yml?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ansible/expand_ubuntu_disk.yml | 161 +++++++++++++++++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 ansible/expand_ubuntu_disk.yml diff --git a/ansible/expand_ubuntu_disk.yml b/ansible/expand_ubuntu_disk.yml new file mode 100644 index 0000000..20959a5 --- /dev/null +++ b/ansible/expand_ubuntu_disk.yml @@ -0,0 +1,161 @@ +--- +- name: Expand Ubuntu disk in vCenter and inside guest + hosts: all + gather_facts: yes + become: yes + + vars: + disk_unit_number: 0 + disk_controller_number: 0 + + tasks: + - name: Gather VM info from vCenter + community.vmware.vmware_guest_info: + hostname: "{{ vcenter_hostname }}" + username: "{{ vcenter_username }}" + password: "{{ vcenter_password }}" + validate_certs: false + datacenter: "{{ vcenter_datacenter }}" + name: "{{ vm_name }}" + delegate_to: localhost + register: vm_info + + - name: Get current disk size in GB + ansible.builtin.set_fact: + current_disk_gb: >- + {{ + ( + vm_info.instance.hw_disk + | selectattr('controller_number', 'equalto', disk_controller_number) + | selectattr('unit_number', 'equalto', disk_unit_number) + | map(attribute='capacity_in_kb') + | first + ) | int // 1024 // 1024 + }} + + - name: Calculate target disk size in GB + ansible.builtin.set_fact: + target_disk_gb: "{{ current_disk_gb + (increase_gb | int) }}" + + - name: Show resize plan + ansible.builtin.debug: + msg: "Disk will be expanded from {{ current_disk_gb }} GB to {{ target_disk_gb }} GB" + + - name: Expand disk in vCenter + community.vmware.vmware_guest_disk: + hostname: "{{ vcenter_hostname }}" + username: "{{ vcenter_username }}" + password: "{{ vcenter_password }}" + validate_certs: false + datacenter: "{{ vcenter_datacenter }}" + name: "{{ vm_name }}" + disk: + - state: present + unit_number: "{{ disk_unit_number }}" + controller_number: "{{ disk_controller_number }}" + size_gb: "{{ target_disk_gb }}" + delegate_to: localhost + + - name: Rescan SCSI bus + ansible.builtin.shell: | + for host in /sys/class/scsi_host/host*; do + echo "- - -" > "$host/scan" + done + args: + executable: /bin/bash + changed_when: true + + - name: Wait a moment after rescan + ansible.builtin.pause: + seconds: 5 + + - name: Detect root source device + ansible.builtin.command: findmnt -n -o SOURCE / + register: root_source + changed_when: false + + - name: Detect base disk and partition number + ansible.builtin.shell: | + set -e + ROOT_SRC="$(findmnt -n -o SOURCE /)" + PKNAME="$(lsblk -no PKNAME "$ROOT_SRC" | head -n1)" + PARTNUM="$(lsblk -no PARTN "$ROOT_SRC" | head -n1)" + if [ -z "$PKNAME" ]; then + PKNAME="$(basename "$(readlink -f "$ROOT_SRC")" | sed 's/[0-9]*$//')" + PARTNUM="$(basename "$(readlink -f "$ROOT_SRC")" | grep -o '[0-9]*$')" + fi + echo "DISK=/dev/${PKNAME}" + echo "PARTNUM=${PARTNUM}" + args: + executable: /bin/bash + register: root_layout + changed_when: false + + - name: Parse disk layout + ansible.builtin.set_fact: + root_disk: "{{ (root_layout.stdout_lines | select('match', '^DISK=') | first).split('=')[1] }}" + root_partnum: "{{ (root_layout.stdout_lines | select('match', '^PARTNUM=') | first).split('=')[1] }}" + + - name: Ensure growpart is installed + ansible.builtin.apt: + name: cloud-guest-utils + state: present + update_cache: yes + + - name: Expand root partition + ansible.builtin.command: "growpart {{ root_disk }} {{ root_partnum }}" + register: growpart_result + changed_when: "'NOCHANGE' not in growpart_result.stdout" + failed_when: false + + - name: Detect filesystem source after partition grow + ansible.builtin.command: findmnt -n -o SOURCE / + register: root_source_after + changed_when: false + + - name: Detect filesystem type + ansible.builtin.command: findmnt -n -o FSTYPE / + register: root_fstype + changed_when: false + + - name: Check if root is on LVM + ansible.builtin.shell: | + lsblk -no TYPE "$(readlink -f {{ root_source_after.stdout | quote }})" | head -n1 + args: + executable: /bin/bash + register: root_dev_type + changed_when: false + + - name: Resize LVM physical volume + ansible.builtin.command: "pvresize {{ root_disk }}{{ root_partnum }}" + when: root_dev_type.stdout == "lvm" + failed_when: false + changed_when: true + + - name: Extend root logical volume and filesystem + ansible.builtin.command: "lvextend -r -l +100%FREE {{ root_source_after.stdout }}" + when: root_dev_type.stdout == "lvm" + changed_when: true + + - name: Resize ext4 filesystem on non-LVM root + ansible.builtin.command: "resize2fs {{ root_source_after.stdout }}" + when: + - root_dev_type.stdout != "lvm" + - root_fstype.stdout in ["ext4", "ext3", "ext2"] + changed_when: true + + - name: Resize xfs filesystem on non-LVM root + ansible.builtin.command: "xfs_growfs /" + when: + - root_dev_type.stdout != "lvm" + - root_fstype.stdout == "xfs" + changed_when: true + + - name: Show final disk usage + ansible.builtin.command: df -h / + register: df_root + changed_when: false + + - name: Print final disk usage + ansible.builtin.debug: + var: df_root.stdout_lines