Feature: Disk-ID Namen + SMART-Daten on demand im VdevTree

- Backend: get_disk_id_map() liest /dev/disk/by-id/ dynamisch aus (ata/nvme/scsi/wwn)
- Backend: _annotate_disk_ids() hängt disk_id an Leaf-Vdevs in get_pool_status()
- Backend: get_smart_info() liest smartctl --json (Modell, Temp, Health, Stunden, Sektoren)
- Backend: GET /api/pools/disks/{disk}/smart Endpoint
- Frontend: DiskRow zeigt Modellname neben sda/sdb, aufklappbar für SMART-Details
- Frontend: Temp-Spalte farbcodiert (grün/gelb/rot), SMART-Spalte zeigt PASSED/FAILED

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-05 09:36:36 +02:00
parent 202fdfaaeb
commit ce78f0ae95
4 changed files with 273 additions and 38 deletions
+17
View File
@@ -5,6 +5,7 @@ Pool management endpoints
from fastapi import APIRouter, Depends, HTTPException, status
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from typing import List
import re
from services.zfs_runner import zfs_runner
from services.auth import auth_service
@@ -164,6 +165,22 @@ async def disk_detach(pool_name: str, disk: str, current_user: str = Depends(get
raise HTTPException(status_code=500, detail=str(e))
@router.get("/disks/{disk}/smart")
async def get_disk_smart(disk: str, current_user: str = Depends(get_current_user)):
"""
Get SMART data for a specific disk (e.g. sda, sdb, nvme0n1).
Requires smartmontools installed on the system.
"""
# Basic validation to prevent path traversal
if not re.match(r'^[a-zA-Z0-9]+$', disk):
raise HTTPException(status_code=400, detail="Invalid disk name")
try:
data = zfs_runner.get_smart_info(disk)
return data
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.post("/clear-cache")
async def clear_cache(current_user: str = Depends(get_current_user)):
"""