--- # configure-vm.yml - Configure VM with UEFI, TPM, disks, GPU, and Cloud-Init - name: "[CONFIG] Configure UEFI + Secure Boot + TPM (if enabled)" block: - name: "[CONFIG] Enable UEFI and TPM" ansible.builtin.command: > qm set {{ vm_id }} --bios ovmf --efidisk0 {{ storage }}:0,pre-enrolled-keys=1 --tpmstate0 {{ storage }}:1,size=4M,version=v2.0 register: tpm_config changed_when: tpm_config.rc == 0 - name: "[CONFIG] Verify TPM configuration" ansible.builtin.debug: msg: "✓ UEFI + TPM configured for VM {{ vm_id }}" when: enable_tpm | default(false) - name: "[CONFIG] Import and attach disk" block: - name: "[CONFIG] Check if disk is already attached" ansible.builtin.include_tasks: helpers.yml vars: helper_task: check_disk_attached target_vm_id: "{{ vm_id }}" - name: "[CONFIG] Display disk status" ansible.builtin.debug: msg: "Disk status for VM {{ vm_id }}: {{ 'ALREADY ATTACHED' if disk_attached else 'WILL BE IMPORTED & ATTACHED' }}" - name: "[CONFIG] Import qcow2 disk (if not already attached)" ansible.builtin.command: > qm importdisk {{ vm_id }} {{ debian_image_path }} {{ storage }} register: disk_import retries: "{{ max_retries }}" delay: "{{ retry_delay }}" until: disk_import is succeeded when: not disk_attached - name: "[CONFIG] Verify disk import" ansible.builtin.fail: msg: "Disk import failed for VM {{ vm_id }}" when: - not disk_attached - disk_import is failed - name: "[CONFIG] Attach imported disk" ansible.builtin.command: > qm set {{ vm_id }} --scsihw virtio-scsi-pci --scsi0 {{ storage }}:vm-{{ vm_id }}-disk-0 register: disk_attach when: not disk_attached changed_when: disk_attach.rc == 0 - name: "[CONFIG] Enable serial console and set boot order" ansible.builtin.command: > qm set {{ vm_id }} --serial0 socket --boot order=scsi0 register: serial_config changed_when: serial_config.rc == 0 - name: "[CONFIG] Display disk configuration" ansible.builtin.debug: msg: "✓ Disk {{ 'attached' if disk_attached else 'imported and attached' }} to VM {{ vm_id }}" rescue: - name: "[CONFIG] Handle disk configuration error" ansible.builtin.fail: msg: | Failed to configure disk for VM {{ vm_id }}: {{ ansible_failed_result | default('Unknown error') }} - name: "[CONFIG] Resize disk (if enabled)" block: - name: "[CONFIG] Resize disk" ansible.builtin.command: "qm resize {{ vm_id }} scsi0 {{ resize_size }}" register: disk_resize changed_when: disk_resize.rc == 0 - name: "[CONFIG] Display disk resize result" ansible.builtin.debug: msg: "✓ Disk resized to {{ resize_size }}" when: resize_disk | default(false) - name: "[CONFIG] Configure GPU passthrough (if enabled)" block: - name: "[CONFIG] Enable PCI GPU passthrough" ansible.builtin.command: "qm set {{ vm_id }} --hostpci0 {{ gpu_device }}" register: gpu_config changed_when: gpu_config.rc == 0 - name: "[CONFIG] Display GPU configuration" ansible.builtin.debug: msg: "✓ GPU passthrough configured: {{ gpu_device }}" when: gpu_passthrough | default(false) - name: "[CONFIG] Configure VirtIO GPU (if enabled)" block: - name: "[CONFIG] Enable VirtIO GPU" ansible.builtin.command: "qm set {{ vm_id }} --vga virtio" register: virtio_gpu_config changed_when: virtio_gpu_config.rc == 0 - name: "[CONFIG] Display VirtIO GPU configuration" ansible.builtin.debug: msg: "✓ VirtIO GPU configured" when: virtio_gpu | default(false) - name: "[CONFIG] Create and apply Cloud-Init snippets" block: - name: "[CONFIG] Clean up old Cloud-Init snippets (if any)" ansible.builtin.include_tasks: helpers.yml vars: helper_task: cleanup_snippets target_vm_id: "{{ vm_id }}" - name: "[CONFIG] Create Cloud-Init vendor-data snippet" ansible.builtin.template: src: cloudinit_vendor.yaml.j2 dest: "/var/lib/vz/snippets/{{ vm_id }}-vendor.yaml" mode: "0644" register: vendor_snippet - name: "[CONFIG] Verify SSH key is readable" ansible.builtin.stat: path: "{{ ssh_keys_file | expanduser }}" register: ssh_key_stat failed_when: not ssh_key_stat.stat.readable - name: "[CONFIG] Create Cloud-Init user-data snippet" ansible.builtin.template: src: cloudinit_userdata.yaml.j2 dest: "/var/lib/vz/snippets/{{ vm_id }}-user.yaml" mode: "0644" register: user_snippet - name: "[CONFIG] Copy SSH public key to snippets" ansible.builtin.copy: src: "{{ ssh_keys_file | expanduser }}" dest: "/var/lib/vz/snippets/{{ vm_id }}-sshkey.pub" mode: "0644" register: ssh_snippet - name: "[CONFIG] Apply Cloud-Init configuration" ansible.builtin.command: > qm set {{ vm_id }} --ciuser {{ ci_user }} --sshkeys local:snippets/{{ vm_id }}-sshkey.pub --hostname {{ hostname }} --citype nocloud --cicustom "user=local:snippets/{{ vm_id }}-user.yaml,vendor=local:snippets/{{ vm_id }}-vendor.yaml" --ipconfig0 {{ ipconfig0 }} register: cloudinit_apply changed_when: cloudinit_apply.rc == 0 - name: "[CONFIG] Display Cloud-Init configuration" ansible.builtin.debug: msg: | ✓ Cloud-Init configured for VM {{ vm_id }} - User: {{ ci_user }} - Hostname: {{ hostname }} - IP Config: {{ ipconfig0 }} - Timezone: {{ timezone }} rescue: - name: "[CONFIG] Handle Cloud-Init configuration error" ansible.builtin.fail: msg: | Failed to configure Cloud-Init for VM {{ vm_id }}: {{ ansible_failed_result | default('Unknown error') }}