113 lines
4.8 KiB
YAML
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 }}."
|