Add enhanced terminal history panel UI with animations, keyboard navigation, advanced filtering, search highlighting, and improved storage metrics display with detailed filesystem tables and ZFS/LVM support
Tests / Backend Tests (Python) (3.10) (push) Has been cancelled
Tests / Backend Tests (Python) (3.11) (push) Has been cancelled
Tests / Backend Tests (Python) (3.12) (push) Has been cancelled
Tests / Frontend Tests (JS) (push) Has been cancelled
Tests / Integration Tests (push) Has been cancelled
Tests / All Tests Passed (push) Has been cancelled
Tests / Backend Tests (Python) (3.10) (push) Has been cancelled
Tests / Backend Tests (Python) (3.11) (push) Has been cancelled
Tests / Backend Tests (Python) (3.12) (push) Has been cancelled
Tests / Frontend Tests (JS) (push) Has been cancelled
Tests / Integration Tests (push) Has been cancelled
Tests / All Tests Passed (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,288 @@
|
||||
---
|
||||
# Builtin Playbook: Collecte détaillée du stockage
|
||||
# Ce playbook collecte les informations de stockage détaillées (disques, partitions, mounts, ZFS, LVM)
|
||||
# Compatible: Linux (Alpine/Debian), TrueNAS CORE (FreeBSD), TrueNAS SCALE (Linux+ZFS)
|
||||
|
||||
- name: Collect Detailed Storage Information
|
||||
hosts: all
|
||||
become: false
|
||||
gather_facts: true
|
||||
vars:
|
||||
_builtin_playbook: true
|
||||
_builtin_id: collect_storage_details
|
||||
_collect_metrics: true
|
||||
tasks:
|
||||
- name: Detect OS type
|
||||
ansible.builtin.set_fact:
|
||||
detected_os_type: >-
|
||||
{%- if ansible_system == 'FreeBSD' -%}truenas-core
|
||||
{%- elif ansible_distribution | lower == 'debian' and 'truenas' in (ansible_product_name | default('') | lower) -%}truenas-scale
|
||||
{%- elif ansible_distribution | lower == 'alpine' -%}linux-alpine
|
||||
{%- elif ansible_os_family | lower == 'debian' -%}linux-debian
|
||||
{%- elif ansible_os_family | lower == 'redhat' -%}linux-redhat
|
||||
{%- else -%}linux-generic{%- endif -%}
|
||||
|
||||
- name: Initialize collection metadata
|
||||
ansible.builtin.set_fact:
|
||||
storage_commands_run: []
|
||||
storage_partial_failures: []
|
||||
storage_collection_start: "{{ ansible_date_time.iso8601 }}"
|
||||
|
||||
- name: Get block devices via lsblk (Linux)
|
||||
ansible.builtin.shell: |
|
||||
if command -v lsblk >/dev/null 2>&1; then
|
||||
lsblk -J -b -o NAME,TYPE,SIZE,FSTYPE,MOUNTPOINT,MODEL,SERIAL,UUID,LABEL,ROTA 2>/dev/null || \
|
||||
lsblk -J -b -o NAME,TYPE,SIZE,FSTYPE,MOUNTPOINT 2>/dev/null || \
|
||||
echo '{"blockdevices":[]}'
|
||||
else
|
||||
echo '{"blockdevices":[]}'
|
||||
fi
|
||||
register: lsblk_output
|
||||
changed_when: false
|
||||
ignore_errors: true
|
||||
when: ansible_system == 'Linux'
|
||||
|
||||
- name: Parse lsblk JSON
|
||||
block:
|
||||
- name: Parse lsblk
|
||||
ansible.builtin.set_fact:
|
||||
block_devices_raw: "{{ (lsblk_output.stdout | default('{}') | from_json).blockdevices | default([]) }}"
|
||||
storage_commands_run: "{{ storage_commands_run + [{'cmd': 'lsblk', 'status': 'ok'}] }}"
|
||||
rescue:
|
||||
- name: Fallback block_devices
|
||||
ansible.builtin.set_fact:
|
||||
block_devices_raw: []
|
||||
storage_partial_failures: "{{ storage_partial_failures + ['lsblk parse failed'] }}"
|
||||
when: ansible_system == 'Linux'
|
||||
|
||||
- name: Get mounts via findmnt (Linux)
|
||||
ansible.builtin.shell: |
|
||||
if command -v findmnt >/dev/null 2>&1; then
|
||||
findmnt -J -b -o TARGET,SOURCE,FSTYPE,OPTIONS,SIZE,USED,AVAIL,USE% 2>/dev/null || echo '{"filesystems":[]}'
|
||||
else
|
||||
echo '{"filesystems":[]}'
|
||||
fi
|
||||
register: findmnt_output
|
||||
changed_when: false
|
||||
ignore_errors: true
|
||||
when: ansible_system == 'Linux'
|
||||
|
||||
- name: Parse findmnt JSON
|
||||
block:
|
||||
- name: Parse findmnt
|
||||
ansible.builtin.set_fact:
|
||||
mounts_raw: "{{ (findmnt_output.stdout | default('{}') | from_json).filesystems | default([]) }}"
|
||||
storage_commands_run: "{{ storage_commands_run + [{'cmd': 'findmnt', 'status': 'ok'}] }}"
|
||||
rescue:
|
||||
- name: Fallback mounts
|
||||
ansible.builtin.set_fact:
|
||||
mounts_raw: []
|
||||
storage_partial_failures: "{{ storage_partial_failures + ['findmnt parse failed'] }}"
|
||||
when: ansible_system == 'Linux'
|
||||
|
||||
- name: Get filesystems via df (Linux)
|
||||
ansible.builtin.shell: |
|
||||
df -B1 -PT -x tmpfs -x devtmpfs -x squashfs -x overlay 2>/dev/null | tail -n +2 | awk '{
|
||||
gsub(/%/,"",$6);
|
||||
printf "{\"device\":\"%s\",\"fstype\":\"%s\",\"size_bytes\":%s,\"used_bytes\":%s,\"avail_bytes\":%s,\"use_pct\":%s,\"mountpoint\":\"%s\"}\n", $1, $2, $3, $4, $5, $6, $7
|
||||
}' | paste -sd "," | awk '{print "["$0"]"}' 2>/dev/null || echo '[]'
|
||||
register: df_output
|
||||
changed_when: false
|
||||
ignore_errors: true
|
||||
when: ansible_system == 'Linux'
|
||||
|
||||
- name: Parse df JSON
|
||||
block:
|
||||
- name: Parse df
|
||||
ansible.builtin.set_fact:
|
||||
filesystems_raw: "{{ df_output.stdout | default('[]') | from_json }}"
|
||||
storage_commands_run: "{{ storage_commands_run + [{'cmd': 'df', 'status': 'ok'}] }}"
|
||||
rescue:
|
||||
- name: Fallback filesystems
|
||||
ansible.builtin.set_fact:
|
||||
filesystems_raw: []
|
||||
storage_partial_failures: "{{ storage_partial_failures + ['df parse failed'] }}"
|
||||
when: ansible_system == 'Linux'
|
||||
|
||||
- name: Get filesystems via df (FreeBSD)
|
||||
ansible.builtin.shell: |
|
||||
df -k -T 2>/dev/null | tail -n +2 | awk '{
|
||||
size_bytes=$3*1024; used_bytes=$4*1024; avail_bytes=$5*1024;
|
||||
gsub(/%/,"",$6);
|
||||
printf "{\"device\":\"%s\",\"fstype\":\"%s\",\"size_bytes\":%d,\"used_bytes\":%d,\"avail_bytes\":%d,\"use_pct\":%d,\"mountpoint\":\"%s\"}\n", $1, $2, size_bytes, used_bytes, avail_bytes, $6, $7
|
||||
}' | paste -sd "," | awk '{print "["$0"]"}' 2>/dev/null || echo '[]'
|
||||
register: df_bsd_output
|
||||
changed_when: false
|
||||
ignore_errors: true
|
||||
when: ansible_system == 'FreeBSD'
|
||||
|
||||
- name: Parse df FreeBSD JSON
|
||||
block:
|
||||
- name: Parse df FreeBSD
|
||||
ansible.builtin.set_fact:
|
||||
filesystems_raw: "{{ df_bsd_output.stdout | default('[]') | from_json }}"
|
||||
storage_commands_run: "{{ storage_commands_run + [{'cmd': 'df', 'status': 'ok'}] }}"
|
||||
rescue:
|
||||
- name: Fallback filesystems FreeBSD
|
||||
ansible.builtin.set_fact:
|
||||
filesystems_raw: []
|
||||
storage_partial_failures: "{{ storage_partial_failures + ['df (FreeBSD) parse failed'] }}"
|
||||
when: ansible_system == 'FreeBSD'
|
||||
|
||||
- name: Get LVM info
|
||||
ansible.builtin.shell: |
|
||||
if command -v pvs >/dev/null 2>&1 && command -v vgs >/dev/null 2>&1 && command -v lvs >/dev/null 2>&1; then
|
||||
pvs_json=$(pvs --reportformat json --units b 2>/dev/null | tr -d '\n' || echo '{"report":[{"pv":[]}]}')
|
||||
vgs_json=$(vgs --reportformat json --units b 2>/dev/null | tr -d '\n' || echo '{"report":[{"vg":[]}]}')
|
||||
lvs_json=$(lvs --reportformat json --units b 2>/dev/null | tr -d '\n' || echo '{"report":[{"lv":[]}]}')
|
||||
echo "{\"pvs_raw\":$pvs_json,\"vgs_raw\":$vgs_json,\"lvs_raw\":$lvs_json}"
|
||||
else
|
||||
echo '{"pvs_raw":{"report":[{"pv":[]}]},"vgs_raw":{"report":[{"vg":[]}]},"lvs_raw":{"report":[{"lv":[]}]}}'
|
||||
fi
|
||||
register: lvm_output
|
||||
changed_when: false
|
||||
ignore_errors: true
|
||||
when: ansible_system == 'Linux'
|
||||
|
||||
- name: Parse LVM JSON
|
||||
block:
|
||||
- name: Parse LVM
|
||||
ansible.builtin.set_fact:
|
||||
lvm_parsed: "{{ lvm_output.stdout | default('{}') | from_json }}"
|
||||
- name: Extract LVM components
|
||||
ansible.builtin.set_fact:
|
||||
lvm_info_raw:
|
||||
pvs: "{{ (lvm_parsed.pvs_raw.report[0].pv | default([])) if lvm_parsed.pvs_raw is defined else [] }}"
|
||||
vgs: "{{ (lvm_parsed.vgs_raw.report[0].vg | default([])) if lvm_parsed.vgs_raw is defined else [] }}"
|
||||
lvs: "{{ (lvm_parsed.lvs_raw.report[0].lv | default([])) if lvm_parsed.lvs_raw is defined else [] }}"
|
||||
storage_commands_run: "{{ storage_commands_run + [{'cmd': 'lvm', 'status': 'ok'}] }}"
|
||||
rescue:
|
||||
- name: Fallback LVM
|
||||
ansible.builtin.set_fact:
|
||||
lvm_info_raw:
|
||||
pvs: []
|
||||
vgs: []
|
||||
lvs: []
|
||||
storage_partial_failures: "{{ storage_partial_failures + ['lvm parse failed'] }}"
|
||||
when: ansible_system == 'Linux'
|
||||
|
||||
- name: Get ZFS pools
|
||||
ansible.builtin.shell: |
|
||||
if command -v zpool >/dev/null 2>&1; then
|
||||
zpool list -H -p -o name,size,alloc,free,cap,health 2>/dev/null | awk -F'\t' '{
|
||||
printf "{\"name\":\"%s\",\"size_bytes\":%s,\"alloc_bytes\":%s,\"free_bytes\":%s,\"cap_pct\":%s,\"health\":\"%s\"}\n", $1, $2, $3, $4, $5, $6
|
||||
}' | paste -sd "," | awk '{print "["$0"]"}' 2>/dev/null || echo '[]'
|
||||
else
|
||||
echo '[]'
|
||||
fi
|
||||
register: zpool_output
|
||||
changed_when: false
|
||||
ignore_errors: true
|
||||
|
||||
- name: Parse ZFS pools JSON
|
||||
block:
|
||||
- name: Parse zpool
|
||||
ansible.builtin.set_fact:
|
||||
zfs_pools_raw: "{{ zpool_output.stdout | default('[]') | from_json }}"
|
||||
storage_commands_run: "{{ storage_commands_run + [{'cmd': 'zpool list', 'status': 'ok'}] }}"
|
||||
rescue:
|
||||
- name: Fallback zfs pools
|
||||
ansible.builtin.set_fact:
|
||||
zfs_pools_raw: []
|
||||
storage_partial_failures: "{{ storage_partial_failures + ['zpool parse failed'] }}"
|
||||
|
||||
- name: Get ZFS datasets
|
||||
ansible.builtin.shell: |
|
||||
if command -v zfs >/dev/null 2>&1; then
|
||||
zfs list -H -p -o name,used,avail,refer,mountpoint,type 2>/dev/null | awk -F'\t' '{
|
||||
mp = ($5 == "-") ? "null" : sprintf("\"%s\"", $5);
|
||||
printf "{\"name\":\"%s\",\"used_bytes\":%s,\"avail_bytes\":%s,\"refer_bytes\":%s,\"mountpoint\":%s,\"type\":\"%s\"}\n", $1, $2, $3, $4, mp, $6
|
||||
}' | paste -sd "," | awk '{print "["$0"]"}' 2>/dev/null || echo '[]'
|
||||
else
|
||||
echo '[]'
|
||||
fi
|
||||
register: zfs_datasets_output
|
||||
changed_when: false
|
||||
ignore_errors: true
|
||||
|
||||
- name: Parse ZFS datasets JSON
|
||||
block:
|
||||
- name: Parse zfs list
|
||||
ansible.builtin.set_fact:
|
||||
zfs_datasets_raw: "{{ zfs_datasets_output.stdout | default('[]') | from_json }}"
|
||||
storage_commands_run: "{{ storage_commands_run + [{'cmd': 'zfs list', 'status': 'ok'}] }}"
|
||||
rescue:
|
||||
- name: Fallback zfs datasets
|
||||
ansible.builtin.set_fact:
|
||||
zfs_datasets_raw: []
|
||||
storage_partial_failures: "{{ storage_partial_failures + ['zfs list parse failed'] }}"
|
||||
|
||||
- name: Initialize missing Linux variables (FreeBSD)
|
||||
ansible.builtin.set_fact:
|
||||
block_devices_raw: []
|
||||
mounts_raw: []
|
||||
lvm_info_raw:
|
||||
pvs: []
|
||||
vgs: []
|
||||
lvs: []
|
||||
when: ansible_system == 'FreeBSD'
|
||||
|
||||
- name: Initialize missing variables (fallbacks)
|
||||
ansible.builtin.set_fact:
|
||||
block_devices_raw: "{{ block_devices_raw | default([]) }}"
|
||||
mounts_raw: "{{ mounts_raw | default([]) }}"
|
||||
filesystems_raw: "{{ filesystems_raw | default([]) }}"
|
||||
lvm_info_raw: "{{ lvm_info_raw | default({'pvs':[], 'vgs':[], 'lvs':[]}) }}"
|
||||
zfs_pools_raw: "{{ zfs_pools_raw | default([]) }}"
|
||||
zfs_datasets_raw: "{{ zfs_datasets_raw | default([]) }}"
|
||||
|
||||
- name: Compute storage summary
|
||||
ansible.builtin.set_fact:
|
||||
storage_summary:
|
||||
total_bytes: "{{ filesystems_raw | map(attribute='size_bytes') | select('number') | sum | int }}"
|
||||
used_bytes: "{{ filesystems_raw | map(attribute='used_bytes') | select('number') | sum | int }}"
|
||||
free_bytes: "{{ filesystems_raw | map(attribute='avail_bytes') | select('number') | sum | int }}"
|
||||
|
||||
- name: Determine collection status
|
||||
ansible.builtin.set_fact:
|
||||
storage_status: >-
|
||||
{%- if storage_partial_failures | length > 0 -%}partial
|
||||
{%- elif (block_devices_raw | length > 0) or (filesystems_raw | length > 0) or (zfs_pools_raw | length > 0) -%}ok
|
||||
{%- else -%}error{%- endif -%}
|
||||
storage_collection_end: "{{ ansible_date_time.iso8601 }}"
|
||||
|
||||
- name: Build storage metrics output
|
||||
ansible.builtin.set_fact:
|
||||
metrics_output:
|
||||
host: "{{ inventory_hostname }}"
|
||||
data:
|
||||
storage_details:
|
||||
os_type: "{{ detected_os_type | trim }}"
|
||||
status: "{{ storage_status | trim }}"
|
||||
collected_at: "{{ storage_collection_start }}"
|
||||
commands_run: "{{ storage_commands_run }}"
|
||||
partial_failures: "{{ storage_partial_failures }}"
|
||||
summary:
|
||||
total_bytes: "{{ storage_summary.total_bytes | int }}"
|
||||
used_bytes: "{{ storage_summary.used_bytes | int }}"
|
||||
free_bytes: "{{ storage_summary.free_bytes | int }}"
|
||||
used_pct: "{{ ((storage_summary.used_bytes | int) / (storage_summary.total_bytes | int) * 100) | round(1) if (storage_summary.total_bytes | int) > 0 else 0 }}"
|
||||
block_devices: "{{ block_devices_raw }}"
|
||||
mounts: "{{ mounts_raw }}"
|
||||
filesystems: "{{ filesystems_raw }}"
|
||||
lvm:
|
||||
pvs: "{{ lvm_info_raw.pvs | default([]) }}"
|
||||
vgs: "{{ lvm_info_raw.vgs | default([]) }}"
|
||||
lvs: "{{ lvm_info_raw.lvs | default([]) }}"
|
||||
zfs:
|
||||
pools: "{{ zfs_pools_raw }}"
|
||||
datasets: "{{ zfs_datasets_raw }}"
|
||||
feature_flags:
|
||||
has_lvm: "{{ (lvm_info_raw.vgs | default([]) | length) > 0 }}"
|
||||
has_zfs: "{{ (zfs_pools_raw | length) > 0 }}"
|
||||
has_lsblk: "{{ (block_devices_raw | length) > 0 }}"
|
||||
has_findmnt: "{{ (mounts_raw | length) > 0 }}"
|
||||
|
||||
- name: Output metrics in parseable format
|
||||
ansible.builtin.debug:
|
||||
msg: "METRICS_JSON_START:{{ metrics_output | to_json }}:METRICS_JSON_END"
|
||||
Reference in New Issue
Block a user