import re from fastapi import APIRouter, HTTPException, Response from models.schemas import DriveDetail from services import store router = APIRouter(prefix="/api/drives", tags=["drives"]) @router.get("/{device}", response_model=DriveDetail) async def get_drive_detail(device: str, response: Response): """Get SMART detail for a specific block device (from the store).""" if not re.match(r"^[a-zA-Z0-9\-]+$", device): raise HTTPException(status_code=400, detail=f"Invalid device name: {device}") data = await store.get_smart(device) if data is None: raise HTTPException( status_code=404, detail=f"No SMART data for '{device}' yet (poller may not have swept it)", ) if "error" in data: raise HTTPException(status_code=502, detail=data["error"]) pool_map = await store.get_zfs_map() zfs_info = pool_map.get(device) if zfs_info: data["zfs_pool"] = zfs_info["pool"] data["zfs_vdev"] = zfs_info["vdev"] data["zfs_state"] = zfs_info.get("state") meta = await store.get_meta() if meta and meta.get("last_sweep_ts"): response.headers["X-Poll-Age"] = str(int(store.now() - meta["last_sweep_ts"])) return DriveDetail(**data)