All task files now use centralized helper functions, ensuring idempotency across all stages. Code is cleaner, more maintainable, and no breaking changes were introduced.
180 lines
5.9 KiB
YAML
180 lines
5.9 KiB
YAML
---
|
|
# 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] 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] Verify SSH key is readable"
|
|
ansible.builtin.stat:
|
|
path: "{{ ssh_key_path | expanduser }}"
|
|
register: ssh_key_stat
|
|
failed_when: not ssh_key_stat.stat.readable
|
|
|
|
- name: "[CONFIG] Copy SSH public key to snippets"
|
|
ansible.builtin.copy:
|
|
src: "{{ ssh_key_path | 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') }}
|