From 81c875726b9fc8acac9f4ec2126c3198c25cc703 Mon Sep 17 00:00:00 2001 From: Michel Peterson Date: Sun, 19 Apr 2026 11:40:28 +0300 Subject: [PATCH] feat(ansible): add corosync-qnetd role for NAS quorum MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a lightweight Ansible role to provision the corosync-qnetd quorum device on a dedicated VM (qnetd-01). This provides a third vote for the 2-node NAS cluster, enabling proper majority quorum instead of relying on two_node mode with no-quorum-policy=ignore. Components: - roles/corosync_qnetd: installs corosync-qnetd, configures firewall (port 5403), initializes NSS cert database, enables the service - playbooks/corosync_qnetd/setup.yaml: targets the qnetd host group - sample_inventory/qnetd.yaml: sample inventory for the qnetd host - playbooks/setup.yaml: imports the new qnetd playbook DNS zone update (qnetd-01 A record → 10.3.25.13) and serial bump must be applied to the local inventories zone file at deploy time. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- ansible/playbooks/corosync_qnetd/setup.yaml | 6 ++++ ansible/playbooks/setup.yaml | 3 ++ .../roles/corosync_qnetd/defaults/main.yaml | 14 +++++++++ .../roles/corosync_qnetd/handlers/main.yaml | 6 ++++ ansible/roles/corosync_qnetd/tasks/main.yaml | 29 +++++++++++++++++++ ansible/sample_inventory/qnetd.yaml | 6 ++++ 6 files changed, 64 insertions(+) create mode 100644 ansible/playbooks/corosync_qnetd/setup.yaml create mode 100644 ansible/roles/corosync_qnetd/defaults/main.yaml create mode 100644 ansible/roles/corosync_qnetd/handlers/main.yaml create mode 100644 ansible/roles/corosync_qnetd/tasks/main.yaml create mode 100644 ansible/sample_inventory/qnetd.yaml diff --git a/ansible/playbooks/corosync_qnetd/setup.yaml b/ansible/playbooks/corosync_qnetd/setup.yaml new file mode 100644 index 00000000..8e9fd177 --- /dev/null +++ b/ansible/playbooks/corosync_qnetd/setup.yaml @@ -0,0 +1,6 @@ +--- +- hosts: qnetd + name: Configure corosync-qnetd quorum device + + roles: + - corosync_qnetd diff --git a/ansible/playbooks/setup.yaml b/ansible/playbooks/setup.yaml index 3b59d603..021ccb52 100644 --- a/ansible/playbooks/setup.yaml +++ b/ansible/playbooks/setup.yaml @@ -4,3 +4,6 @@ - name: Run bind9 setup playbook ansible.builtin.import_playbook: bind9/setup.yaml + +- name: Run corosync-qnetd setup playbook + ansible.builtin.import_playbook: corosync_qnetd/setup.yaml diff --git a/ansible/roles/corosync_qnetd/defaults/main.yaml b/ansible/roles/corosync_qnetd/defaults/main.yaml new file mode 100644 index 00000000..1faae004 --- /dev/null +++ b/ansible/roles/corosync_qnetd/defaults/main.yaml @@ -0,0 +1,14 @@ +--- +# corosync-qnetd defaults + +# Network port for the qnetd daemon +corosync_qnetd_port: 5403 + +# NSS certificate database path +corosync_qnetd_nss_db: /etc/corosync/qnetd/nssdb + +# Quorum algorithm: ffsplit (fifty-fifty split) is correct for 2-node clusters +corosync_qnetd_algorithm: ffsplit + +# Firewall service name for high-availability (includes port 5403) +corosync_qnetd_firewall_service: high-availability diff --git a/ansible/roles/corosync_qnetd/handlers/main.yaml b/ansible/roles/corosync_qnetd/handlers/main.yaml new file mode 100644 index 00000000..ac51b917 --- /dev/null +++ b/ansible/roles/corosync_qnetd/handlers/main.yaml @@ -0,0 +1,6 @@ +--- +- name: Restart corosync-qnetd + ansible.builtin.systemd: + name: corosync-qnetd + state: restarted + daemon_reload: true diff --git a/ansible/roles/corosync_qnetd/tasks/main.yaml b/ansible/roles/corosync_qnetd/tasks/main.yaml new file mode 100644 index 00000000..ae1901d3 --- /dev/null +++ b/ansible/roles/corosync_qnetd/tasks/main.yaml @@ -0,0 +1,29 @@ +--- +- name: Install corosync-qnetd package + ansible.builtin.dnf: + name: corosync-qnetd + state: present + +- name: Open firewall for high-availability services (port {{ corosync_qnetd_port }}) + ansible.posix.firewalld: + service: "{{ corosync_qnetd_firewall_service }}" + permanent: true + immediate: true + state: enabled + +- name: Check if NSS certificate database exists + ansible.builtin.stat: + path: "{{ corosync_qnetd_nss_db }}/cert9.db" + register: nss_db + +- name: Initialize NSS certificate database for qnetd + ansible.builtin.command: corosync-qnetd-certutil -i + when: not nss_db.stat.exists + changed_when: true + notify: Restart corosync-qnetd + +- name: Enable and start corosync-qnetd service + ansible.builtin.systemd: + name: corosync-qnetd + enabled: true + state: started diff --git a/ansible/sample_inventory/qnetd.yaml b/ansible/sample_inventory/qnetd.yaml new file mode 100644 index 00000000..7a9c6f6d --- /dev/null +++ b/ansible/sample_inventory/qnetd.yaml @@ -0,0 +1,6 @@ +--- +qnetd: + hosts: + qnetd-01.local.example.com: + ansible_user: mpeterson + ansible_become: true