--- - name: Get available storage on target node ansible.builtin.uri: url: "https://{{ proxmox_api_host }}:8006/api2/json/nodes/{{ target_node }}/storage" method: GET headers: Authorization: "PVEAPIToken={{ proxmox_api_user }}!{{ proxmox_api_token_id }}={{ proxmox_api_token_secret }}" validate_certs: false register: storage_info - name: Set target storage backend (prefer local-zfs if available) ansible.builtin.set_fact: target_storage: "{{ 'local-zfs' if storage_info.json.data | selectattr('storage', 'equalto', 'local-zfs') | list | length > 0 else 'local-lvm' }}" - name: Display selected storage ansible.builtin.debug: msg: "Target node {{ target_node }} will use storage: {{ target_storage }}" - name: Clone LXC from template (on template's node) community.proxmox.proxmox: api_host: "{{ proxmox_api_host }}" api_user: "{{ proxmox_api_user }}" api_token_id: "{{ proxmox_api_token_id }}" api_token_secret: "{{ proxmox_api_token_secret }}" node: "{{ lxc_template_node }}" clone: "{{ lxc_template_id }}" hostname: "{{ vm_hostname }}" full: true storage: "local-lvm" timeout: 600 register: cloned_lxc - name: Migrate LXC to target node via API ansible.builtin.uri: url: "https://{{ proxmox_api_host }}:8006/api2/json/nodes/{{ lxc_template_node }}/lxc/{{ cloned_lxc.vmid }}/migrate" method: POST headers: Authorization: "PVEAPIToken={{ proxmox_api_user }}!{{ proxmox_api_token_id }}={{ proxmox_api_token_secret }}" body_format: form-urlencoded body: target: "{{ target_node }}" restart: "0" validate_certs: false status_code: [200] register: migrate_task when: lxc_template_node != target_node - name: Wait for migration task to complete ansible.builtin.uri: url: "https://{{ proxmox_api_host }}:8006/api2/json/nodes/{{ target_node }}/lxc/{{ cloned_lxc.vmid }}/status/current" method: GET headers: Authorization: "PVEAPIToken={{ proxmox_api_user }}!{{ proxmox_api_token_id }}={{ proxmox_api_token_secret }}" validate_certs: false register: lxc_check until: lxc_check.status == 200 retries: 60 delay: 10 when: lxc_template_node != target_node - name: Wait for LXC to unlock after migration ansible.builtin.wait_for: timeout: 30 when: lxc_template_node != target_node - name: Move LXC rootfs to target storage (if different from local-lvm) ansible.builtin.uri: url: "https://{{ proxmox_api_host }}:8006/api2/json/nodes/{{ target_node }}/lxc/{{ cloned_lxc.vmid }}/move_volume" method: POST headers: Authorization: "PVEAPIToken={{ proxmox_api_user }}!{{ proxmox_api_token_id }}={{ proxmox_api_token_secret }}" body_format: form-urlencoded body: volume: "rootfs" storage: "{{ target_storage }}" delete: "1" validate_certs: false status_code: [200] register: move_volume_task when: target_storage != 'local-lvm' - name: Wait for volume move to complete ansible.builtin.uri: url: "https://{{ proxmox_api_host }}:8006/api2/json/nodes/{{ target_node }}/lxc/{{ cloned_lxc.vmid }}/status/current" method: GET headers: Authorization: "PVEAPIToken={{ proxmox_api_user }}!{{ proxmox_api_token_id }}={{ proxmox_api_token_secret }}" validate_certs: false register: lxc_status until: lxc_status.json.data.lock is not defined retries: 60 delay: 10 when: target_storage != 'local-lvm' - name: Wait for LXC to unlock ansible.builtin.wait_for: timeout: 30 when: target_storage != 'local-lvm' - name: Configure LXC resources community.proxmox.proxmox: api_host: "{{ proxmox_api_host }}" api_user: "{{ proxmox_api_user }}" api_token_id: "{{ proxmox_api_token_id }}" api_token_secret: "{{ proxmox_api_token_secret }}" node: "{{ target_node }}" vmid: "{{ cloned_lxc.vmid }}" cores: "{{ cpu_cores }}" memory: "{{ ram_gb | int * 1024 }}" netif: net0: "name=eth0,bridge=vmbr0,ip=dhcp" state: present - name: Start the LXC container community.proxmox.proxmox: api_host: "{{ proxmox_api_host }}" api_user: "{{ proxmox_api_user }}" api_token_id: "{{ proxmox_api_token_id }}" api_token_secret: "{{ proxmox_api_token_secret }}" node: "{{ target_node }}" vmid: "{{ cloned_lxc.vmid }}" state: started - name: Set VMID fact for later use ansible.builtin.set_fact: created_vmid: "{{ cloned_lxc.vmid }}"