--- - name: Assert proxmox_cluster inventory group is populated ansible.builtin.assert: that: - groups['proxmox_cluster'] is defined - groups['proxmox_cluster'] | length >= 2 fail_msg: "Inventory group proxmox_cluster must contain at least two nodes." - name: Assert join node and anchor node are valid and distinct ansible.builtin.assert: that: - join_node in groups['proxmox_cluster'] - join_target_host in groups['proxmox_cluster'] - join_node != join_target_host fail_msg: "join_node and join_target_host must both be valid proxmox_cluster hosts and cannot be identical." - name: Resolve join anchor IP ansible.builtin.set_fact: proxmox_cluster_reconcile_v2_anchor_ip: >- {{ join_target_ip | trim if join_target_ip | trim | length > 0 else (hostvars[join_target_host].ansible_host | default(join_target_host)) }} proxmox_cluster_reconcile_v2_join_node_ip: "{{ hostvars[join_node].ansible_host | default(join_node) }}" - name: Ensure join anchor SSH is reachable from controller ansible.builtin.wait_for: host: "{{ proxmox_cluster_reconcile_v2_anchor_ip }}" port: 22 timeout: 10 connect_timeout: 3 state: started delegate_to: localhost - name: Capture cluster status from anchor ansible.builtin.command: pvecm status register: proxmox_cluster_reconcile_v2_anchor_status changed_when: false become: true delegate_to: "{{ join_target_host }}" - name: Assert anchor cluster is quorate before join ansible.builtin.assert: that: - proxmox_cluster_reconcile_v2_anchor_status.rc == 0 - proxmox_cluster_reconcile_v2_anchor_status.stdout is search('Quorate:\\s+Yes') fail_msg: >- Anchor node {{ join_target_host }} is not quorate. Resolve quorum before joining {{ join_node }}. - name: Capture current cluster nodes from anchor ansible.builtin.command: pvecm nodes register: proxmox_cluster_reconcile_v2_anchor_nodes changed_when: false become: true delegate_to: "{{ join_target_host }}" - name: Extract current cluster node names from anchor ansible.builtin.shell: "pvecm nodes | awk 'NR>2 && NF>=3 {print $3}'" register: proxmox_cluster_reconcile_v2_anchor_node_names_cmd changed_when: false become: true delegate_to: "{{ join_target_host }}" - name: Build normalized anchor node name list ansible.builtin.set_fact: proxmox_cluster_reconcile_v2_anchor_node_names: >- {{ proxmox_cluster_reconcile_v2_anchor_node_names_cmd.stdout_lines | map('trim') | reject('equalto', '') | list }} - name: Capture join node cluster membership file state ansible.builtin.stat: path: /etc/pve/corosync.conf register: proxmox_cluster_reconcile_v2_join_corosync_file become: true delegate_to: "{{ join_node }}"