This commit is contained in:
martin.fencl
2025-12-23 20:45:36 +01:00
parent fd57e6b566
commit 1b1806907a

View File

@@ -1,7 +1,7 @@
# check_raid.yml # check_raid.yml
- name: Check mdadm RAID status on VM (via SSH from Semaphore host) - name: Check mdadm RAID status on VM (via SSH from proxmox_nextcloud)
hosts: linux_servers hosts: proxmox_nextcloud
gather_facts: false gather_facts: false
become: true become: true
become_user: root become_user: root
@@ -81,35 +81,59 @@
success_msg: "Successfully read /proc/mdstat from {{ vm_ip }}." success_msg: "Successfully read /proc/mdstat from {{ vm_ip }}."
changed_when: false changed_when: false
- name: Parse RAID status from mdstat # English comments - name: Build base variables # English comments
ansible.builtin.set_fact: ansible.builtin.set_fact:
raid_md: "{{ RAID_DEVICE | regex_replace('^/dev/', '') }}" raid_md: "{{ RAID_DEVICE | regex_replace('^/dev/', '') }}"
mdstat_text: "{{ mdstat_cmd.stdout | default('') }}" mdstat_text: "{{ mdstat_cmd.stdout | default('') }}"
raid_present: "{{ (mdstat_cmd.stdout | default('')) is search('(?m)^' ~ (RAID_DEVICE | regex_replace('^/dev/','')) ~ '\\s*:') }}" changed_when: false
- name: Extract selected md block from mdstat # English comments
ansible.builtin.set_fact:
raid_block: >-
{{
(
mdstat_text
| regex_findall(
'(?ms)^' ~ raid_md ~ '\\s*:.*?(?=^md\\d+\\s*:|^unused devices:|\\Z)'
)
| first
| default('', true)
)
}}
changed_when: false
- name: Parse RAID status from mdstat (safe parsing) # English comments
ansible.builtin.set_fact:
raid_present: "{{ (raid_block | length) > 0 }}"
raid_status: >- raid_status: >-
{{ {{
(mdstat_cmd.stdout | default('')) | (
regex_search( raid_block
'(?ms)^' ~ (RAID_DEVICE | regex_replace('^/dev/','')) ~ '\\s*:.*?\\n.*?\\[[0-9]+/[0-9]+\\]\\s*\\[([U_]+)\\]', | regex_findall('\\[[0-9]+/[0-9]+\\]\\s*\\[([U_]+)\\]')
'\\1' | first
) | default('') | default('', true)
)
}} }}
raid_is_degraded: "{{ (raid_status | length > 0) and ('_' in raid_status) }}" raid_is_degraded: "{{ (raid_status | length > 0) and ('_' in raid_status) }}"
raid_is_rebuilding: "{{ (mdstat_cmd.stdout | default('')) is search('(?i)\\b(resync|recovery|reshape|repair)\\b') }}" raid_is_rebuilding: "{{ raid_block is search('(?i)\\b(resync|recovery|reshape|repair)\\b') }}"
raid_is_checking: "{{ (mdstat_cmd.stdout | default('')) is search('(?i)\\bcheck\\b') }}" raid_is_checking: "{{ raid_block is search('(?i)\\bcheck\\b') }}"
raid_action_line: >- raid_action_line: >-
{{ {{
(mdstat_cmd.stdout | default('')) | (
regex_search( raid_block
'(?im)^(\\s*\\[[^\\]]+\\].*\\b(resync|recovery|reshape|repair|check)\\b.*)$', | regex_findall('(?im)^(\\s*\\[[^\\]]+\\].*\\b(?:resync|recovery|reshape|repair|check)\\b.*)$')
'\\1' | first
) | default('') | default('', true)
)
}} }}
raid_progress: >- raid_progress: >-
{{ {{
(mdstat_cmd.stdout | default('')) | (
regex_search('(?i)\\b(resync|recovery|reshape|repair|check)\\b\\s*=\\s*([0-9.]+)%', '\\2') | raid_block
default('') | regex_findall('(?i)\\b(?:resync|recovery|reshape|repair|check)\\b\\s*=\\s*([0-9.]+)%')
| first
| default('', true)
)
}} }}
changed_when: false changed_when: false
@@ -118,8 +142,9 @@
msg: | msg: |
--- /proc/mdstat --- --- /proc/mdstat ---
{{ mdstat_text }} {{ mdstat_text }}
--- md block ({{ raid_md }}) ---
{{ raid_block }}
--- Parsed --- --- Parsed ---
raid_md={{ raid_md }}
raid_present={{ raid_present }} raid_present={{ raid_present }}
raid_status={{ raid_status }} raid_status={{ raid_status }}
raid_is_degraded={{ raid_is_degraded }} raid_is_degraded={{ raid_is_degraded }}
@@ -133,7 +158,7 @@
ansible.builtin.assert: ansible.builtin.assert:
that: that:
- raid_present - raid_present
fail_msg: "RAID {{ raid_md }} not found in /proc/mdstat on {{ vm_ip }}." fail_msg: "RAID {{ raid_md }} not found in /proc/mdstat on VM {{ vm_ip }}."
success_msg: "RAID {{ raid_md }} found in /proc/mdstat." success_msg: "RAID {{ raid_md }} found in /proc/mdstat."
changed_when: false changed_when: false
@@ -143,7 +168,7 @@
- not raid_is_degraded - not raid_is_degraded
fail_msg: >- fail_msg: >-
RAID {{ raid_md }} is DEGRADED: status={{ raid_status }}. RAID {{ raid_md }} is DEGRADED: status={{ raid_status }}.
mdstat excerpt={{ (mdstat_text | trim) }} mdstat excerpt={{ (raid_block | trim) }}
success_msg: "RAID {{ raid_md }} is OK: status={{ raid_status }}." success_msg: "RAID {{ raid_md }} is OK: status={{ raid_status }}."
changed_when: false changed_when: false
@@ -154,7 +179,7 @@
fail_msg: >- fail_msg: >-
RAID {{ raid_md }} is rebuilding/resyncing. RAID {{ raid_md }} is rebuilding/resyncing.
{{ 'progress=' ~ raid_progress ~ '%; ' if (raid_progress | length) > 0 else '' }} {{ 'progress=' ~ raid_progress ~ '%; ' if (raid_progress | length) > 0 else '' }}
line={{ raid_action_line | default('n/a') }} line={{ (raid_action_line | default('n/a', true)) }}
success_msg: "RAID {{ raid_md }} is not rebuilding/resyncing." success_msg: "RAID {{ raid_md }} is not rebuilding/resyncing."
when: FAIL_ON_RESYNC | int == 1 when: FAIL_ON_RESYNC | int == 1
changed_when: false changed_when: false
@@ -166,7 +191,7 @@
fail_msg: >- fail_msg: >-
RAID {{ raid_md }} is running a periodic check. RAID {{ raid_md }} is running a periodic check.
{{ 'progress=' ~ raid_progress ~ '%; ' if (raid_progress | length) > 0 else '' }} {{ 'progress=' ~ raid_progress ~ '%; ' if (raid_progress | length) > 0 else '' }}
line={{ raid_action_line | default('n/a') }} line={{ (raid_action_line | default('n/a', true)) }}
success_msg: "RAID {{ raid_md }} is not running a periodic check." success_msg: "RAID {{ raid_md }} is not running a periodic check."
when: FAIL_ON_CHECK | int == 1 when: FAIL_ON_CHECK | int == 1
changed_when: false changed_when: false