--- - name: Validate required Proxmox variables ansible.builtin.assert: that: - proxmox_api_host | length > 0 - proxmox_api_user | length > 0 - proxmox_api_token_id | length > 0 - proxmox_api_token_secret | length > 0 - proxmox_node | length > 0 - proxmox_template | length > 0 - proxmox_vmid | int > 99 - vm_ci_user | length > 0 - vm_ipconfig0 is match('^ip=.+') fail_msg: "Missing required VM provisioning variables." - name: Gather current VMs on Proxmox node community.proxmox.proxmox_vm_info: api_host: "{{ proxmox_api_host }}" api_user: "{{ proxmox_api_user }}" api_token_id: "{{ proxmox_api_token_id }}" api_token_secret: "{{ proxmox_api_token_secret }}" validate_certs: "{{ proxmox_validate_certs }}" node: "{{ proxmox_node }}" register: proxmox_vms - name: Detect whether target VM already exists ansible.builtin.set_fact: vm_exists: >- {{ (proxmox_vms.proxmox_vms | default([]) | selectattr('vmid', 'equalto', proxmox_vmid | int) | list | length) > 0 }} - name: Clone VM from cloud-init template when missing community.proxmox.proxmox_kvm: api_host: "{{ proxmox_api_host }}" api_user: "{{ proxmox_api_user }}" api_token_id: "{{ proxmox_api_token_id }}" api_token_secret: "{{ proxmox_api_token_secret }}" validate_certs: "{{ proxmox_validate_certs }}" node: "{{ proxmox_node }}" clone: "{{ proxmox_template }}" newid: "{{ proxmox_vmid }}" name: "{{ proxmox_vm_name }}" storage: "{{ proxmox_storage }}" full: true timeout: 600 state: present when: not vm_exists - name: Apply VM hardware, network, and cloud-init settings community.proxmox.proxmox_kvm: api_host: "{{ proxmox_api_host }}" api_user: "{{ proxmox_api_user }}" api_token_id: "{{ proxmox_api_token_id }}" api_token_secret: "{{ proxmox_api_token_secret }}" validate_certs: "{{ proxmox_validate_certs }}" node: "{{ proxmox_node }}" vmid: "{{ proxmox_vmid }}" name: "{{ proxmox_vm_name }}" cores: "{{ proxmox_cores }}" memory: "{{ proxmox_memory_mb }}" scsihw: virtio-scsi-pci scsi: scsi0: "{{ proxmox_storage }}:{{ proxmox_disk_gb }}" net: net0: "virtio,bridge={{ proxmox_bridge }}" ciuser: "{{ vm_ci_user }}" cipassword: "{{ vm_ci_password }}" ipconfig: ipconfig0: "{{ vm_ipconfig0 }}" nameservers: - "{{ vm_nameserver }}" searchdomains: - "{{ vm_searchdomain }}" sshkeys: "{{ vm_ssh_public_key | default(omit) }}" onboot: true agent: true update: true state: present - name: Ensure VM is running community.proxmox.proxmox_kvm: api_host: "{{ proxmox_api_host }}" api_user: "{{ proxmox_api_user }}" api_token_id: "{{ proxmox_api_token_id }}" api_token_secret: "{{ proxmox_api_token_secret }}" validate_certs: "{{ proxmox_validate_certs }}" node: "{{ proxmox_node }}" vmid: "{{ proxmox_vmid }}" state: started - name: Derive VM IPv4 address from cloud-init ipconfig ansible.builtin.set_fact: vm_ipv4: "{{ (vm_ipconfig0.split('ip=')[1].split(',')[0]).split('/')[0] }}" - name: Wait for SSH on provisioned VM ansible.builtin.wait_for: host: "{{ vm_ipv4 }}" port: 22 timeout: "{{ vm_boot_timeout_seconds }}" delay: 5 delegate_to: localhost - name: Add new VM to in-memory inventory ansible.builtin.add_host: name: "{{ proxmox_vm_name }}" groups: aitutor_vm ansible_host: "{{ vm_ipv4 }}" ansible_user: "{{ vm_ci_user }}" ansible_ssh_private_key_file: "{{ vm_ssh_private_key_file }}" ansible_python_interpreter: /usr/bin/python3