Files
ansible-msp-automations/roles/proxmox_restore/tasks/main.yml
2026-03-15 15:48:59 -07:00

113 lines
4.8 KiB
YAML

---
# =============================================================================
# proxmox_restore — tasks
# Returns VMs to their origin nodes using state written by proxmox_drain.
#
# Required vars:
# current_node — the node whose VMs should be restored
# restore_state_file — path to the JSON state file (set by caller or discovered)
# =============================================================================
# ── Find state file ───────────────────────────────────────────────────────────
- name: "Restore | {{ current_node }} | Find state files"
ansible.builtin.find:
paths: "{{ restore_state_dir }}"
patterns: "{{ current_node }}_*.json"
file_type: file
register: restore_found_files
delegate_to: localhost
- name: "Restore | {{ current_node }} | No state files found — skipping"
ansible.builtin.debug:
msg: >-
No drain state files found for {{ current_node }} in {{ restore_state_dir }}.
Skipping restore.
when: restore_found_files.files | length == 0
- name: "Restore | {{ current_node }} | End if no state files"
ansible.builtin.meta: end_play
when: restore_found_files.files | length == 0
- name: "Restore | {{ current_node }} | Use most recent state file"
ansible.builtin.set_fact:
restore_state_file: >-
{{ (restore_found_files.files | sort(attribute='mtime') | last).path }}
delegate_to: localhost
- name: "Restore | {{ current_node }} | Load state file"
ansible.builtin.slurp:
src: "{{ restore_state_file }}"
register: restore_state_raw
delegate_to: localhost
- name: "Restore | {{ current_node }} | Parse VM origin list"
ansible.builtin.set_fact:
restore_vm_list: "{{ restore_state_raw.content | b64decode | from_json }}"
delegate_to: localhost
- name: "Restore | {{ current_node }} | Log restore plan"
ansible.builtin.debug:
msg: >-
Restoring {{ restore_vm_list | length }} guest(s) to {{ current_node }}:
{{ restore_vm_list | map(attribute='vmid') | list }}
# ── Get current VM locations ──────────────────────────────────────────────────
- name: "Restore | {{ current_node }} | Get current VM locations"
community.proxmox.proxmox_vm_info:
api_host: "{{ api_host }}"
api_user: "{{ api_user }}"
api_token_id: "{{ api_token_id }}"
api_token_secret: "{{ api_token_secret }}"
api_port: "{{ api_port }}"
validate_certs: "{{ validate_certs }}"
register: restore_all_vms
delegate_to: localhost
# ── Migrate KVM guests back ───────────────────────────────────────────────────
- name: "Restore | {{ current_node }} | KVM | Migrate back"
ansible.builtin.command: >
qm migrate {{ item.vmid }} {{ current_node }}
{% if item.status == 'running' %}--online{% endif %}
--with-local-disks 0
loop: "{{ restore_vm_list | selectattr('type', 'equalto', 'qemu') | list }}"
loop_control:
label: "{{ item.name }} (VMID {{ item.vmid }})"
changed_when: true
vars:
current_location: >-
{{ restore_all_vms.proxmox_vms
| selectattr('vmid', 'equalto', item.vmid)
| map(attribute='node')
| first
| default('unknown') }}
when: current_location != current_node
# ── Migrate LXC guests back ───────────────────────────────────────────────────
- name: "Restore | {{ current_node }} | LXC | Migrate back"
ansible.builtin.command: >
pct migrate {{ item.vmid }} {{ current_node }} --restart --timeout 120
loop: "{{ restore_vm_list | selectattr('type', 'equalto', 'lxc') | list }}"
loop_control:
label: "{{ item.name | default(item.vmid) }} (VMID {{ item.vmid }})"
changed_when: true
vars:
current_location: >-
{{ restore_all_vms.proxmox_vms
| selectattr('vmid', 'equalto', item.vmid)
| map(attribute='node')
| first
| default('unknown') }}
when: current_location != current_node
# ── Cleanup ───────────────────────────────────────────────────────────────────
- name: "Restore | {{ current_node }} | Remove state file"
ansible.builtin.file:
path: "{{ restore_state_file }}"
state: absent
delegate_to: localhost
when: restore_cleanup_state_file
- name: "Restore | {{ current_node }} | Complete"
ansible.builtin.debug:
msg: "✓ Restore complete — {{ restore_vm_list | length }} guest(s) returned to {{ current_node }}."