--- # tasks file for linstor_cluster # IMPORTANT: All Linstor node registrations use ansible_hostname (the real system hostname) # to ensure they match Proxmox node names, which are also derived from the system hostname. # The Ansible inventory_hostname (e.g. "pve1") may differ from the real hostname (e.g. "pve-node-01"). - name: Safely manage LINSTOR cluster nodes in /etc/hosts ansible.builtin.blockinfile: path: /etc/hosts marker: "# {mark} ANSIBLE MANAGED BLOCK - LINSTOR CLUSTER" block: | # Linstor Cluster Nodes (Primary: Private Network) {% for host in groups['proxmox'] %} {{ hostvars[host]['priv_ip'] | default(hostvars[host]['ansible_host']) }} {{ hostvars[host]['ansible_facts']['hostname'] }} {% endfor %} # Linstor Cluster Nodes (Fallback: Public Network) {% for host in groups['proxmox'] %} {{ hostvars[host]['ansible_host'] }} {{ hostvars[host]['ansible_facts']['hostname'] }}-public {% endfor %} - name: Ensure /etc/linstor directory exists ansible.builtin.file: path: /etc/linstor state: directory mode: '0755' - name: Deploy linstor-client.conf ansible.builtin.template: src: linstor-client.conf.j2 dest: /etc/linstor/linstor-client.conf mode: '0644' # --------------------------------------------------------- # LINSTOR NODE REGISTRATION (Executed ONLY on Node 1) # Uses ansible_hostname (real system hostname) for Linstor node names # to guarantee compatibility with Proxmox node names. # --------------------------------------------------------- - name: Register nodes in LINSTOR ansible.builtin.shell: | set -o pipefail NODE_NAME="{{ hostvars[item]['ansible_facts']['hostname'] }}" NODE_IP="{{ hostvars[item]['priv_ip'] | default(hostvars[item]['ansible_host']) }}" if ! linstor node list | grep -q " ${NODE_NAME} "; then linstor node create "${NODE_NAME}" "${NODE_IP}" --node-type Combined > /dev/null echo "changed" fi args: executable: /bin/bash register: linstor_cluster_node_create changed_when: "'changed' in linstor_cluster_node_create.stdout" loop: "{{ groups['proxmox'] }}" when: inventory_hostname == groups['proxmox'][0] - name: Configure Multipath Fallback Interfaces ansible.builtin.shell: | set -o pipefail NODE_NAME="{{ hostvars[item]['ansible_facts']['hostname'] }}" NODE_PUBLIC_IP="{{ hostvars[item]['ansible_host'] }}" if ! linstor node interface list "${NODE_NAME}" | grep -q " fallback "; then linstor node interface create "${NODE_NAME}" fallback "${NODE_PUBLIC_IP}" > /dev/null echo "changed" fi args: executable: /bin/bash register: linstor_cluster_int_create changed_when: "'changed' in linstor_cluster_int_create.stdout" loop: "{{ groups['proxmox'] }}" when: inventory_hostname == groups['proxmox'][0] - name: Wait for all Linstor satellite nodes to appear as Online ansible.builtin.shell: | set -o pipefail if linstor node list | sed 's/\x1b\[[0-9;]*m//g' | grep " {{ hostvars[item]['ansible_facts']['hostname'] }} " | grep -q "Online"; then echo "online" else echo "not_ready" exit 1 fi args: executable: /bin/bash register: linstor_cluster_node_status until: "'online' in linstor_cluster_node_status.stdout" retries: 12 delay: 10 changed_when: false loop: "{{ groups['proxmox'] }}" when: inventory_hostname == groups['proxmox'][0]