--- - name: Expand VM disk in vCenter and discover guest IP hosts: localhost gather_facts: no vars: disk_controller_number: 0 disk_unit_number: 0 tasks: - name: Get 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 }}" register: vm_info - name: Fail if VM has no guest IP in vCenter ansible.builtin.fail: msg: "VM {{ vm_name }} has no detected guest IP in vCenter" when: not vm_info.instance.ipv4 - 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 ansible.builtin.set_fact: target_disk_gb: "{{ current_disk_gb + (increase_gb | int) }}" - name: Show resize plan ansible.builtin.debug: msg: - "VM: {{ vm_name }}" - "Guest IP: {{ vm_info.instance.ipv4 }}" - "Current disk: {{ current_disk_gb }} GB" - "Target disk: {{ 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 }}" - name: Add discovered VM to temporary inventory ansible.builtin.add_host: name: resized_ubuntu_target ansible_host: "{{ vm_info.instance.ipv4 }}" ansible_user: "{{ guest_ssh_user }}" ansible_password: "{{ guest_ssh_password }}" ansible_become: true ansible_become_password: "{{ guest_become_password }}" ansible_ssh_common_args: "-o StrictHostKeyChecking=no" - name: Expand disk inside Ubuntu guest hosts: resized_ubuntu_target gather_facts: yes become: yes vars: root_disk: /dev/sda root_partition: /dev/sda3 root_partition_number: 3 root_lv: /dev/mapper/ubuntu--vg-ubuntu--lv tasks: - 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 after rescan ansible.builtin.pause: seconds: 5 - name: Ensure growpart is installed ansible.builtin.apt: name: cloud-guest-utils state: present update_cache: yes - name: Expand partition if needed ansible.builtin.command: "growpart {{ root_disk }} {{ root_partition_number }}" register: growpart_result changed_when: "'CHANGED:' in growpart_result.stdout" failed_when: > growpart_result.rc != 0 and 'NOCHANGE:' not in growpart_result.stdout - name: Resize LVM physical volume ansible.builtin.command: "pvresize {{ root_partition }}" register: pvresize_result changed_when: "'resized' in (pvresize_result.stdout | lower) or 'changed' in (pvresize_result.stdout | lower)" failed_when: false - name: Extend root logical volume and filesystem ansible.builtin.command: "lvextend -r -l +100%FREE {{ root_lv }}" register: lvextend_result changed_when: "'size of logical volume' in (lvextend_result.stdout | lower) or 'logical volume' in (lvextend_result.stdout | lower)" failed_when: false - name: Show final disk state ansible.builtin.shell: | pvs vgs lvs df -h / args: executable: /bin/bash register: final_state changed_when: false - name: Print final disk state ansible.builtin.debug: var: final_state.stdout_lines