diff --git a/roles/cleanup/tasks/libvirt.yml b/roles/cleanup/tasks/libvirt.yml new file mode 100644 index 0000000..6c3d041 --- /dev/null +++ b/roles/cleanup/tasks/libvirt.yml @@ -0,0 +1,113 @@ +--- +- name: Remove Archiso and cloud-init disks + when: hypervisor == "libvirt" + delegate_to: localhost + become: false + block: + - name: Set libvirt image paths + vars: + cleanup_libvirt_image_dir_value: "{{ vm_path | default('/var/lib/libvirt/images') }}" + ansible.builtin.set_fact: + cleanup_libvirt_image_dir: "{{ cleanup_libvirt_image_dir_value }}" + cleanup_libvirt_cloudinit_path: >- + {{ [cleanup_libvirt_image_dir_value, hostname ~ '-cloudinit.iso'] | ansible.builtin.path_join }} + changed_when: false + + - name: Read current VM XML definition + community.libvirt.virt: + command: get_xml + name: "{{ hostname }}" + register: cleanup_libvirt_get_xml + changed_when: false + + - name: Initialize cleaned VM XML + ansible.builtin.set_fact: + cleanup_libvirt_domain_xml: "{{ cleanup_libvirt_get_xml.get_xml }}" + changed_when: false + + - name: Remove boot ISO device from VM XML (target match) + community.general.xml: + xmlstring: "{{ cleanup_libvirt_domain_xml }}" + xpath: "/domain/devices/disk[target/@dev='sda']" + state: absent + register: cleanup_libvirt_xml_strip_boot + + - name: Update cleaned VM XML after removing boot ISO + ansible.builtin.set_fact: + cleanup_libvirt_domain_xml: "{{ cleanup_libvirt_xml_strip_boot.xmlstring }}" + changed_when: false + + - name: Remove boot ISO device from VM XML (source match) + when: boot_iso is defined and (boot_iso | length > 0) + community.general.xml: + xmlstring: "{{ cleanup_libvirt_domain_xml }}" + xpath: "/domain/devices/disk[contains(source/@file, '{{ boot_iso | basename }}')]" + state: absent + register: cleanup_libvirt_xml_strip_boot_source + + - name: Update cleaned VM XML after removing boot ISO source match + when: boot_iso is defined and (boot_iso | length > 0) + ansible.builtin.set_fact: + cleanup_libvirt_domain_xml: "{{ cleanup_libvirt_xml_strip_boot_source.xmlstring }}" + changed_when: false + + - name: Remove cloud-init ISO device from VM XML (target match) + community.general.xml: + xmlstring: "{{ cleanup_libvirt_domain_xml }}" + xpath: "/domain/devices/disk[target/@dev='sdb']" + state: absent + register: cleanup_libvirt_xml_strip_cloudinit + + - name: Update cleaned VM XML after removing cloud-init ISO + ansible.builtin.set_fact: + cleanup_libvirt_domain_xml: "{{ cleanup_libvirt_xml_strip_cloudinit.xmlstring }}" + changed_when: false + + - name: Remove cloud-init ISO device from VM XML (source match) + community.general.xml: + xmlstring: "{{ cleanup_libvirt_domain_xml }}" + xpath: "/domain/devices/disk[contains(source/@file, '{{ hostname }}-cloudinit.iso')]" + state: absent + register: cleanup_libvirt_xml_strip_cloudinit_source + + - name: Update cleaned VM XML after removing cloud-init ISO source match + ansible.builtin.set_fact: + cleanup_libvirt_domain_xml: "{{ cleanup_libvirt_xml_strip_cloudinit_source.xmlstring }}" + changed_when: false + + - name: Strip XML declaration for libvirt define + ansible.builtin.set_fact: + cleanup_libvirt_domain_xml_clean: >- + {{ + cleanup_libvirt_domain_xml + | replace('\ufeff', '') + | regex_replace("(?is)<\\?xml[^>]*\\?>", "") + | regex_replace("(?i)encoding=[\"'][^\"']+[\"']", "") + | trim + }} + changed_when: false + + - name: Update VM definition without installer media + community.libvirt.virt: + command: define + xml: "{{ cleanup_libvirt_domain_xml_clean }}" + + - name: Remove cloud-init disk + ansible.builtin.file: + path: "{{ cleanup_libvirt_cloudinit_path }}" + state: absent + + - name: Ensure VM is powered off before restart + community.libvirt.virt: + name: "{{ hostname }}" + state: destroyed + + - name: Start the VM + community.libvirt.virt: + name: "{{ hostname }}" + state: running + + - name: Wait for VM to boot up + delegate_to: "{{ inventory_hostname }}" + ansible.builtin.wait_for_connection: + timeout: 300 diff --git a/roles/cleanup/tasks/main.yml b/roles/cleanup/tasks/main.yml index 5ee6628..db33ea4 100644 --- a/roles/cleanup/tasks/main.yml +++ b/roles/cleanup/tasks/main.yml @@ -1,132 +1,8 @@ --- -- name: Unmount Disks - vars: - ansible_connection: ssh - block: - - name: Disable Swap - ansible.builtin.command: swapoff -a - register: swapoff_result - changed_when: swapoff_result.rc == 0 +- name: Cleanup physical install + when: install_type == "physical" + ansible.builtin.include_tasks: physical.yml - - name: Unmount /mnt if mounted - ansible.builtin.command: umount -R /mnt - register: unmount_result - changed_when: unmount_result.rc == 0 - - - name: Verify /mnt is no longer mounted - ansible.builtin.command: grep ' /mnt ' /proc/mounts - register: verify_unmount - retries: 5 - delay: 5 - until: verify_unmount.rc != 0 - when: unmount_result.rc == 0 - changed_when: false - failed_when: verify_unmount.rc not in [0, 1] - -- name: Shutdown the VM - community.general.shutdown: - vars: - ansible_connection: ssh - -- name: Setup Cleanup - when: hypervisor == "proxmox" - delegate_to: localhost - become: false - block: - - name: Cleanup Setup Disks - community.general.proxmox_disk: - api_host: "{{ hypervisor_url }}" - api_user: "{{ hypervisor_username }}" - api_password: "{{ hypervisor_password }}" - name: "{{ hostname }}" - vmid: "{{ vm_id }}" - disk: "{{ item }}" - state: absent - loop: - - ide0 - - ide2 - - - name: Start the VM - community.general.proxmox_kvm: - api_host: "{{ hypervisor_url }}" - api_user: "{{ hypervisor_username }}" - api_password: "{{ hypervisor_password }}" - node: "{{ hypervisor_node }}" - vmid: "{{ vm_id }}" - state: restarted - -- name: Clean vCenter VM - when: hypervisor == "vmware" - delegate_to: localhost - become: false - block: - - name: Remove CD-ROM from VM in vCenter - when: hypervisor == "vmware" - failed_when: false - community.vmware.vmware_guest: - hostname: "{{ hypervisor_url }}" - username: "{{ hypervisor_username }}" - password: "{{ hypervisor_password }}" - validate_certs: false - datacenter: "{{ hypervisor_cluster }}" - name: "{{ hostname }}" - cdrom: - - controller_number: 0 - unit_number: 0 - controller_type: sata - type: iso - iso_path: "{{ boot_iso }}" - state: absent - - controller_number: 0 - unit_number: 1 - controller_type: sata - type: iso - iso_path: "{{ rhel_iso | default(omit) }}" - state: absent - - - name: Start VM in vCenter - when: hypervisor == "vmware" - community.vmware.vmware_guest_powerstate: - hostname: "{{ hypervisor_url }}" - username: "{{ hypervisor_username }}" - password: "{{ hypervisor_password }}" - validate_certs: false - datacenter: "{{ hypervisor_cluster }}" - name: "{{ hostname }}" - state: powered-on - -- name: Remove Archiso and cloud-init disks - when: hypervisor == "libvirt" - delegate_to: localhost - become: false - block: - - name: Remove cloud-init disk - ansible.builtin.file: - path: "{{ vm_path | default('/var/lib/libvirt/images/') }}{{ hostname }}-cloudinit.iso" - state: absent - - - name: Get list of CD-ROM devices - ansible.builtin.shell: set -o pipefail && virsh --connect qemu:///system domblklist {{ hostname }} --details | grep 'cdrom' | awk '{print $3}' - changed_when: false - register: cdrom_devices - - - name: Wait for VM to spin down - ansible.builtin.wait_for: - timeout: 15 - - - name: Remove CD-ROM devices - when: cdrom_devices.stdout_lines | length > 0 - ansible.builtin.command: virsh --connect qemu:///system detach-disk {{ hostname }} {{ item }} --persistent - with_items: "{{ cdrom_devices.stdout_lines | select('ne', 'sdc') | list }}" - changed_when: result.rc == 0 - register: result - - - name: Start the VM - community.libvirt.virt: - name: "{{ hostname }}" - state: running - - - name: Wait for VM to boot up - delegate_to: "{{ inventory_hostname }}" - ansible.builtin.wait_for_connection: - timeout: 300 +- name: Cleanup virtual install + when: install_type == "virtual" + ansible.builtin.include_tasks: virtual.yml diff --git a/roles/cleanup/tasks/physical.yml b/roles/cleanup/tasks/physical.yml new file mode 100644 index 0000000..1d4435f --- /dev/null +++ b/roles/cleanup/tasks/physical.yml @@ -0,0 +1,13 @@ +--- +- name: Unmount installer mounts + ansible.builtin.include_tasks: unmount.yml + +- name: Trigger reboot into installed system + ansible.builtin.command: + argv: + - reboot + async: 1 + poll: 0 + changed_when: true + failed_when: false + ignore_unreachable: true diff --git a/roles/cleanup/tasks/proxmox.yml b/roles/cleanup/tasks/proxmox.yml new file mode 100644 index 0000000..defeaad --- /dev/null +++ b/roles/cleanup/tasks/proxmox.yml @@ -0,0 +1,27 @@ +--- +- name: Setup Cleanup + when: hypervisor == "proxmox" + delegate_to: localhost + become: false + block: + - name: Cleanup Setup Disks + community.proxmox.proxmox_disk: + api_host: "{{ hypervisor_url }}" + api_user: "{{ hypervisor_username }}" + api_password: "{{ hypervisor_password }}" + name: "{{ hostname }}" + vmid: "{{ vm_id }}" + disk: "{{ item }}" + state: absent + loop: + - ide0 + - ide2 + + - name: Start the VM + community.proxmox.proxmox_kvm: + api_host: "{{ hypervisor_url }}" + api_user: "{{ hypervisor_username }}" + api_password: "{{ hypervisor_password }}" + node: "{{ hypervisor_node }}" + vmid: "{{ vm_id }}" + state: restarted diff --git a/roles/cleanup/tasks/shutdown.yml b/roles/cleanup/tasks/shutdown.yml new file mode 100644 index 0000000..0d97ed1 --- /dev/null +++ b/roles/cleanup/tasks/shutdown.yml @@ -0,0 +1,4 @@ +--- +- name: Shutdown the VM + become: true + community.general.shutdown: diff --git a/roles/cleanup/tasks/unmount.yml b/roles/cleanup/tasks/unmount.yml new file mode 100644 index 0000000..ee23251 --- /dev/null +++ b/roles/cleanup/tasks/unmount.yml @@ -0,0 +1,23 @@ +--- +- name: Unmount Disks + become: true + block: + - name: Disable Swap + ansible.builtin.command: swapoff -a + register: cleanup_swapoff_result + changed_when: cleanup_swapoff_result.rc == 0 + + - name: Unmount /mnt if mounted + ansible.builtin.command: umount -R /mnt + register: cleanup_unmount_result + changed_when: cleanup_unmount_result.rc == 0 + failed_when: false + + - name: Verify /mnt is no longer mounted + ansible.builtin.command: grep ' /mnt ' /proc/mounts + until: cleanup_verify_unmount.rc != 0 + retries: 5 + delay: 5 + register: cleanup_verify_unmount + changed_when: false + failed_when: cleanup_verify_unmount.rc not in [0, 1] diff --git a/roles/cleanup/tasks/virtual.yml b/roles/cleanup/tasks/virtual.yml new file mode 100644 index 0000000..917d33b --- /dev/null +++ b/roles/cleanup/tasks/virtual.yml @@ -0,0 +1,15 @@ +--- +- name: Unmount installer mounts + ansible.builtin.include_tasks: unmount.yml + +- name: Shutdown installer environment + ansible.builtin.include_tasks: shutdown.yml + +- name: Cleanup hypervisor resources + ansible.builtin.include_tasks: proxmox.yml + +- name: Cleanup vCenter resources + ansible.builtin.include_tasks: vmware.yml + +- name: Cleanup libvirt resources + ansible.builtin.include_tasks: libvirt.yml diff --git a/roles/cleanup/tasks/vmware.yml b/roles/cleanup/tasks/vmware.yml new file mode 100644 index 0000000..e4ae9c7 --- /dev/null +++ b/roles/cleanup/tasks/vmware.yml @@ -0,0 +1,40 @@ +--- +- name: Clean vCenter VM + when: hypervisor == "vmware" + delegate_to: localhost + become: false + block: + - name: Remove CD-ROM from VM in vCenter + when: hypervisor == "vmware" + community.vmware.vmware_guest: + hostname: "{{ hypervisor_url }}" + username: "{{ hypervisor_username }}" + password: "{{ hypervisor_password }}" + validate_certs: false + datacenter: "{{ hypervisor_datacenter }}" + name: "{{ hostname }}" + cdrom: + - controller_number: 0 + unit_number: 0 + controller_type: sata + type: iso + iso_path: "{{ boot_iso }}" + state: absent + - controller_number: 0 + unit_number: 1 + controller_type: sata + type: iso + iso_path: "{{ rhel_iso | default(omit) }}" + state: absent + failed_when: false + + - name: Start VM in vCenter + when: hypervisor == "vmware" + vmware.vmware.vm_powerstate: + hostname: "{{ hypervisor_url }}" + username: "{{ hypervisor_username }}" + password: "{{ hypervisor_password }}" + validate_certs: false + datacenter: "{{ hypervisor_datacenter }}" + name: "{{ hostname }}" + state: powered-on