From 83f49742b6a7dfec43a757ce8aedfe8492d27a08 Mon Sep 17 00:00:00 2001 From: MacRimi Date: Fri, 6 Mar 2026 14:32:23 +0100 Subject: [PATCH] Update notification service --- AppImage/components/storage-overview.tsx | 8 +- AppImage/scripts/flask_server.py | 11 +- AppImage/scripts/test_disk_observation.py | 131 ++++++++++++++++++++++ 3 files changed, 145 insertions(+), 5 deletions(-) create mode 100644 AppImage/scripts/test_disk_observation.py diff --git a/AppImage/components/storage-overview.tsx b/AppImage/components/storage-overview.tsx index 32c6789a..8373942b 100644 --- a/AppImage/components/storage-overview.tsx +++ b/AppImage/components/storage-overview.tsx @@ -273,9 +273,13 @@ export function StorageOverview() { const params = new URLSearchParams() if (disk.name) params.set('device', disk.name) if (disk.serial && disk.serial !== 'Unknown') params.set('serial', disk.serial) - const data = await fetchApi<{ observations: DiskObservation[] }>(`/api/storage/observations?${params.toString()}`) + const url = `/api/storage/observations?${params.toString()}` + console.log("[v0] Fetching observations:", url, "disk:", disk.name, disk.serial) + const data = await fetchApi<{ observations: DiskObservation[] }>(url) + console.log("[v0] Observations response:", data) setDiskObservations(data.observations || []) - } catch { + } catch (err) { + console.error("[v0] Observations fetch error:", err) setDiskObservations([]) } finally { setLoadingObservations(false) diff --git a/AppImage/scripts/flask_server.py b/AppImage/scripts/flask_server.py index f047f903..fe497ea0 100644 --- a/AppImage/scripts/flask_server.py +++ b/AppImage/scripts/flask_server.py @@ -1236,9 +1236,12 @@ def get_storage_info(): if len(parts) >= 3 and parts[2] == 'disk': disk_name = parts[0] + # Skip virtual/RAM-based block devices if disk_name.startswith('zd'): - # print(f"[v0] Skipping ZFS zvol device: {disk_name}") - pass + # ZFS zvol devices + continue + if disk_name.startswith('zram'): + # zram compressed RAM devices (used by log2ram, etc.) continue disk_size_bytes = int(parts[1]) @@ -2436,9 +2439,11 @@ def api_storage_summary(): if len(parts) >= 3 and parts[2] == 'disk': disk_name = parts[0] - # Skip ZFS zvol devices + # Skip virtual/RAM-based block devices if disk_name.startswith('zd'): continue + if disk_name.startswith('zram'): + continue disk_size_bytes = int(parts[1]) total_disk_size_bytes += disk_size_bytes diff --git a/AppImage/scripts/test_disk_observation.py b/AppImage/scripts/test_disk_observation.py new file mode 100644 index 00000000..9dfdfa9e --- /dev/null +++ b/AppImage/scripts/test_disk_observation.py @@ -0,0 +1,131 @@ +#!/usr/bin/env python3 +""" +Test script to simulate a disk error and verify observation recording. +Usage: python3 test_disk_observation.py [device_name] [error_type] + +Examples: + python3 test_disk_observation.py sdh io_error + python3 test_disk_observation.py sdh smart_error + python3 test_disk_observation.py sdh fs_error +""" + +import sys +import os + +# Add possible module locations to path +script_dir = os.path.dirname(os.path.abspath(__file__)) +sys.path.insert(0, script_dir) +sys.path.insert(0, '/usr/local/share/proxmenux') +sys.path.insert(0, '/tmp/.mount_ProxMeztyU13/usr/bin') # AppImage mount point + +# Try to find the module +for path in sys.path: + if os.path.exists(os.path.join(path, 'health_persistence.py')): + print(f"[INFO] Found health_persistence.py in: {path}") + break + +from health_persistence import HealthPersistence +from datetime import datetime + +def main(): + device_name = sys.argv[1] if len(sys.argv) > 1 else 'sdh' + error_type = sys.argv[2] if len(sys.argv) > 2 else 'io_error' + + # Known serial for sdh (WDC 2TB) + serial_map = { + 'sdh': 'WD-WX72A30AA72R', + 'nvme0n1': '2241E675EA6C', + 'nvme1n1': '2241E675EBE6', + 'sda': '22440F443504', + 'sdb': 'WWZ1SJ18', + 'sdc': '52X0A0D9FZ1G', + 'sdd': '50026B7784446E63', + 'sde': '22440F442105', + 'sdf': 'WRQ0X2GP', + 'sdg': '23Q0A0MPFZ1G', + } + + serial = serial_map.get(device_name, None) + + # Error messages by type + error_messages = { + 'io_error': f'Test I/O error on /dev/{device_name}: sector read failed at LBA 12345678', + 'smart_error': f'/dev/{device_name}: SMART warning - 1 Currently unreadable (pending) sectors detected', + 'fs_error': f'EXT4-fs error (device {device_name}1): inode 123456: block 789012: error reading data', + } + + error_signatures = { + 'io_error': f'io_test_{device_name}', + 'smart_error': f'smart_test_{device_name}', + 'fs_error': f'fs_test_{device_name}', + } + + message = error_messages.get(error_type, f'Test error on /dev/{device_name}') + signature = error_signatures.get(error_type, f'test_{device_name}') + + print(f"\n{'='*60}") + print(f"Testing Disk Observation Recording") + print(f"{'='*60}") + print(f"Device: /dev/{device_name}") + print(f"Serial: {serial or 'Unknown'}") + print(f"Error Type: {error_type}") + print(f"Message: {message}") + print(f"Signature: {signature}") + print(f"{'='*60}\n") + + # Initialize persistence + hp = HealthPersistence() + + # Record the observation + print("[1] Recording observation...") + hp.record_disk_observation( + device_name=device_name, + serial=serial, + error_type=error_type, + error_signature=signature, + raw_message=message, + severity='warning' + ) + print(" OK - Observation recorded\n") + + # Query observations for this device + print("[2] Querying observations for this device...") + observations = hp.get_disk_observations(device_name=device_name, serial=serial) + + if observations: + print(f" Found {len(observations)} observation(s):\n") + for obs in observations: + print(f" ID: {obs['id']}") + print(f" Type: {obs['error_type']}") + print(f" Signature: {obs['error_signature']}") + print(f" Message: {obs['raw_message'][:80]}...") + print(f" Severity: {obs['severity']}") + print(f" First: {obs['first_occurrence']}") + print(f" Last: {obs['last_occurrence']}") + print(f" Count: {obs['occurrence_count']}") + print(f" Dismissed: {obs['dismissed']}") + print() + else: + print(" No observations found!\n") + + # Also show the disk registry + print("[3] Checking disk registry...") + all_devices = hp.get_all_observed_devices() + for dev in all_devices: + if dev.get('device_name') == device_name or dev.get('serial') == serial: + print(f" Found in registry:") + print(f" ID: {dev.get('id')}") + print(f" Device: {dev.get('device_name')}") + print(f" Serial: {dev.get('serial')}") + print(f" First seen: {dev.get('first_seen')}") + print(f" Last seen: {dev.get('last_seen')}") + print() + + print(f"{'='*60}") + print("Test complete! Check the Storage section in the UI.") + print(f"The disk /dev/{device_name} should now show an observations badge.") + print(f"{'='*60}\n") + + +if __name__ == '__main__': + main()