Files
ansible-msp-automations/playbooks/proxmox_upgrade.yml
2026-03-15 15:48:59 -07:00

84 lines
3.1 KiB
YAML

---
# =============================================================================
# proxmox_upgrade.yml
# Rolling Proxmox upgrade orchestrator.
#
# Workflow per node (cluster mode):
# 1. Backup config
# 2. Set CEPH noout (if CEPH enabled)
# 3. Enable HA maintenance mode
# 4. Drain guests to best available node
# 5. apt dist-upgrade
# 6. Reboot if required, wait for rejoin
# 7. Clear CEPH noout
# 8. Disable HA maintenance mode
# 9. Restore guests (if migration_restore=true)
#
# Standalone mode skips all cluster/HA/CEPH/drain steps.
#
# Variables (set in inventory or pass with -e):
# upgrade_order — ordered list of nodes to upgrade (cluster only)
# migration_restore — return VMs to origin node after upgrade (default: false)
# drain_target_strategy — resources | explicit (default: resources)
# backup_destination — local | sftp (default: local)
# =============================================================================
- name: "Proxmox Rolling Upgrade"
hosts: proxmox_cluster
gather_facts: true
run_once: true # Play runs once — loops over nodes internally
serial: 1 # Safety: only one Ansible host processes at a time
vars:
migration_restore: false
upgrade_order: "{{ groups['proxmox_cluster'] | sort }}"
pre_tasks:
- name: "Upgrade | Confirm upgrade_order is defined"
ansible.builtin.fail:
msg: "upgrade_order must be defined in inventory or passed with -e"
when: upgrade_order is not defined or upgrade_order | length == 0
- name: "Upgrade | Log targets"
ansible.builtin.debug:
msg: >-
Proxmox upgrade starting for {{ client_name | default('Unknown') }}
({{ client_id | default('?') }})
Nodes: {{ upgrade_order | join(', ') }}
API: https://{{ api_host }}:{{ api_port }}
roles:
- role: proxmox_preflight
tasks:
# ── Cluster: loop through each node ────────────────────────────────────────
- name: "Upgrade | Rolling upgrade — cluster mode"
ansible.builtin.include_tasks: tasks/proxmox_upgrade_node_loop.yml
loop: "{{ upgrade_order }}"
loop_control:
loop_var: current_node
label: "{{ current_node }}"
when: proxmox_is_cluster
# ── Standalone: upgrade this host directly ────────────────────────────────
- name: "Upgrade | Standalone | Backup config"
ansible.builtin.include_role:
name: proxmox_config_backup
vars:
current_node: "{{ inventory_hostname }}"
when: not proxmox_is_cluster
- name: "Upgrade | Standalone | Run upgrade"
ansible.builtin.include_role:
name: proxmox_upgrade_node
vars:
current_node: "{{ inventory_hostname }}"
when: not proxmox_is_cluster
- name: "Upgrade | Complete"
ansible.builtin.debug:
msg: >-
✓ Proxmox upgrade complete for
{{ client_name | default('Unknown') }} —
{{ upgrade_order | length }} node(s) upgraded.