Some checks failed
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
115 lines
3.5 KiB
Python
115 lines
3.5 KiB
Python
"""
|
|
Routes API pour les health checks.
|
|
"""
|
|
|
|
from datetime import datetime, timezone
|
|
import sys
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException
|
|
|
|
from app.core.dependencies import verify_api_key
|
|
from app.schemas.health import HealthCheck
|
|
from app.schemas.common import LogEntry, SystemMetrics
|
|
from app.services import ws_manager, db
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
@router.get("", response_model=SystemMetrics)
|
|
async def get_metrics(api_key_valid: bool = Depends(verify_api_key)):
|
|
"""Récupère les métriques système."""
|
|
return db.metrics
|
|
|
|
|
|
@router.get("/global")
|
|
async def global_health_check():
|
|
"""Endpoint de healthcheck global utilisé par Docker.
|
|
|
|
Ne nécessite pas de clé API pour permettre aux orchestrateurs
|
|
de vérifier l'état du service facilement.
|
|
"""
|
|
return {
|
|
"status": "ok",
|
|
"service": "homelab-automation-api",
|
|
"timestamp": datetime.now(timezone.utc).isoformat()
|
|
}
|
|
|
|
|
|
@router.get("/runtime")
|
|
async def runtime_info(api_key_valid: bool = Depends(verify_api_key)):
|
|
"""Runtime diagnostics (python executable, asyncssh availability)."""
|
|
try:
|
|
import asyncssh # type: ignore
|
|
asyncssh_ok = True
|
|
asyncssh_version = getattr(asyncssh, "__version__", None)
|
|
except Exception as e:
|
|
asyncssh_ok = False
|
|
asyncssh_version = None
|
|
asyncssh_error = str(e)
|
|
else:
|
|
asyncssh_error = None
|
|
|
|
return {
|
|
"python_executable": sys.executable,
|
|
"python_version": sys.version,
|
|
"asyncssh_available": asyncssh_ok,
|
|
"asyncssh_version": asyncssh_version,
|
|
"asyncssh_error": asyncssh_error,
|
|
}
|
|
|
|
|
|
@router.get("/{host_name}", response_model=HealthCheck)
|
|
async def check_host_health(host_name: str, api_key_valid: bool = Depends(verify_api_key)):
|
|
"""Effectue un health check sur un hôte spécifique."""
|
|
host = next((h for h in db.hosts if h.name == host_name), None)
|
|
if not host:
|
|
raise HTTPException(status_code=404, detail="Hôte non trouvé")
|
|
|
|
# Simuler un health check
|
|
health_check = HealthCheck(
|
|
host=host_name,
|
|
ssh_ok=host.status == "online",
|
|
ansible_ok=host.status == "online",
|
|
sudo_ok=host.status == "online",
|
|
reachable=host.status != "offline",
|
|
response_time=0.123 if host.status == "online" else None,
|
|
error_message=None if host.status != "offline" else "Hôte injoignable"
|
|
)
|
|
|
|
# Mettre à jour le statut runtime
|
|
new_status = "online" if health_check.reachable else "offline"
|
|
db.update_host_status(host_name, new_status, host.os)
|
|
|
|
log_entry = LogEntry(
|
|
timestamp=datetime.now(timezone.utc),
|
|
level="INFO" if health_check.reachable else "ERROR",
|
|
message=f"Health check {'réussi' if health_check.reachable else 'échoué'} pour {host_name}",
|
|
source="health_check",
|
|
host=host_name
|
|
)
|
|
|
|
db.logs.insert(0, log_entry)
|
|
|
|
await ws_manager.broadcast({
|
|
"type": "health_check",
|
|
"data": health_check.dict()
|
|
})
|
|
|
|
return health_check
|
|
|
|
|
|
@router.post("/refresh")
|
|
async def refresh_hosts(api_key_valid: bool = Depends(verify_api_key)):
|
|
"""Force le rechargement des hôtes depuis l'inventaire Ansible."""
|
|
from app.services import ansible_service
|
|
|
|
ansible_service.invalidate_cache()
|
|
hosts = db.refresh_hosts()
|
|
|
|
await ws_manager.broadcast({
|
|
"type": "hosts_refreshed",
|
|
"data": {"count": len(hosts)}
|
|
})
|
|
|
|
return {"message": f"{len(hosts)} hôtes rechargés depuis l'inventaire Ansible"}
|