diff --git a/roles/proxmox_upgrade/defaults/main.yml b/roles/proxmox_upgrade/defaults/main.yml index 558fcdd..c5faacd 100644 --- a/roles/proxmox_upgrade/defaults/main.yml +++ b/roles/proxmox_upgrade/defaults/main.yml @@ -28,4 +28,3 @@ apt_autoremove: true migrate_exclude_tags: - nomigrate - pinned - diff --git a/roles/proxmox_upgrade/tasks/drain.yml b/roles/proxmox_upgrade/tasks/drain.yml index 54efc10..659d0e4 100644 --- a/roles/proxmox_upgrade/tasks/drain.yml +++ b/roles/proxmox_upgrade/tasks/drain.yml @@ -136,7 +136,8 @@ when: not migration_bulk | bool include_tasks: migrate_guest.yml loop: "{{ migration_plan | rejectattr('needs_fallback') | list + migration_plan | selectattr('needs_fallback') | rejectattr('needs_fallback' if live_migrate_fallback == 'skip' else 'nonexistent') | list }}" - loop_var: guest + loop_control: + loop_var: guest - name: Drain | Migrate guests (bulk — fire all at once) when: migration_bulk | bool @@ -154,7 +155,8 @@ validate_certs: false register: bulk_migration_tasks loop: "{{ migration_plan | rejectattr('needs_fallback') | list }}" - loop_var: guest + loop_control: + loop_var: guest delegate_to: localhost - name: Drain | Bulk | Wait for all migrations to complete @@ -181,6 +183,6 @@ - name: Drain | Bulk | Handle fallback guests sequentially include_tasks: migrate_guest.yml loop: "{{ migration_plan | selectattr('needs_fallback') | list }}" - loop_var: guest + loop_control: + loop_var: guest when: live_migrate_fallback != 'skip' - diff --git a/roles/proxmox_upgrade/tasks/migrate_guest.yml b/roles/proxmox_upgrade/tasks/migrate_guest.yml index 9e446d1..fd18500 100644 --- a/roles/proxmox_upgrade/tasks/migrate_guest.yml +++ b/roles/proxmox_upgrade/tasks/migrate_guest.yml @@ -114,4 +114,3 @@ live migrated to {{ migration_targets | first }} {% endif %} delegate_to: localhost - diff --git a/roles/proxmox_upgrade/tasks/node_upgrade.yml b/roles/proxmox_upgrade/tasks/node_upgrade.yml index 34b65b5..089cc79 100644 --- a/roles/proxmox_upgrade/tasks/node_upgrade.yml +++ b/roles/proxmox_upgrade/tasks/node_upgrade.yml @@ -38,4 +38,3 @@ - name: "Node {{ current_node }} | Complete" ansible.builtin.debug: msg: "━━━ Node {{ current_node }} upgrade complete ━━━" - diff --git a/roles/proxmox_upgrade/tasks/preflight.yml b/roles/proxmox_upgrade/tasks/preflight.yml index ec126af..a858abe 100644 --- a/roles/proxmox_upgrade/tasks/preflight.yml +++ b/roles/proxmox_upgrade/tasks/preflight.yml @@ -73,4 +73,3 @@ msg: "Cluster health check passed — all nodes online, quorum OK{{ ', CEPH checked' if ceph_enabled else '' }}" delegate_to: localhost run_once: true - diff --git a/roles/proxmox_upgrade/tasks/proxmox_upgrade.yml b/roles/proxmox_upgrade/tasks/proxmox_upgrade.yml new file mode 100644 index 0000000..0febe22 --- /dev/null +++ b/roles/proxmox_upgrade/tasks/proxmox_upgrade.yml @@ -0,0 +1,42 @@ +--- +# ============================================================================= +# proxmox_upgrade.yml +# ============================================================================= +# Rolling Proxmox cluster upgrade playbook. +# Runs on the first node in upgrade_order — all other nodes are handled +# via API calls and delegate_to from within the role. +# +# Usage: +# ansible-playbook playbooks/proxmox_upgrade.yml \ +# -i inventories/client_local_eng/hypervisor_hosts.yml +# +# Override migration behaviour: +# -e migration_bulk=true +# -e live_migrate_fallback=skip +# -e migration_restore=true +# +# Dry run (check mode — no changes): +# --check +# ============================================================================= + +- name: Proxmox Rolling Upgrade + hosts: proxmox_cluster + gather_facts: true + serial: 1 + run_once: true + + pre_tasks: + - name: Confirm upgrade_order is defined + ansible.builtin.fail: + msg: "upgrade_order must be defined in hypervisor_hosts.yml" + when: upgrade_order is not defined or upgrade_order | length == 0 + + - name: Log upgrade targets + ansible.builtin.debug: + msg: >- + Proxmox upgrade starting for {{ client_name }} ({{ client_id }}) + Nodes: {{ upgrade_order | join(', ') }} + API: https://{{ api_host }}:{{ api_port }} + + roles: + - proxmox_upgrade diff --git a/roles/proxmox_upgrade/tasks/restore.yml b/roles/proxmox_upgrade/tasks/restore.yml index 474bd00..93c01fd 100644 --- a/roles/proxmox_upgrade/tasks/restore.yml +++ b/roles/proxmox_upgrade/tasks/restore.yml @@ -33,7 +33,8 @@ validate_certs: false register: restore_task loop: "{{ migration_plan | rejectattr('needs_fallback') | list }}" - loop_var: guest + loop_control: + loop_var: guest delegate_to: localhost - name: Restore | Wait for all restore migrations to complete @@ -60,4 +61,3 @@ - name: Restore | Complete ansible.builtin.debug: msg: "All guests restored to {{ current_node }}" - diff --git a/roles/proxmox_upgrade/tasks/upgrade.yml b/roles/proxmox_upgrade/tasks/upgrade.yml index 4a0dac9..14de0d4 100644 --- a/roles/proxmox_upgrade/tasks/upgrade.yml +++ b/roles/proxmox_upgrade/tasks/upgrade.yml @@ -92,4 +92,3 @@ Node {{ current_node }} upgrade complete — {{ apt_upgrade_result.stdout_lines | select('match', '.*upgraded.*') | list | first | default('packages updated') }} {{ '— rebooted' if reboot_required.stat.exists else '— no reboot needed' }} -