""" Endpoints API pour le suivi d'équipements (Wake-on-LAN, shutdown, etc.) """ from fastapi import APIRouter, Depends, HTTPException from sqlalchemy.orm import Session from typing import List, Optional from datetime import datetime from pydantic import BaseModel from backend.app.core.database import get_db from backend.app.models.ip import IP router = APIRouter(prefix="/api/tracking", tags=["Tracking"]) # Schémas Pydantic class IPTrackingResponse(BaseModel): """Schéma de réponse pour les IPs suivies""" ip: str name: Optional[str] known: bool tracked: bool location: Optional[str] host: Optional[str] last_status: Optional[str] mac: Optional[str] vendor: Optional[str] hostname: Optional[str] link: Optional[str] last_seen: Optional[datetime] open_ports: List[int] class Config: from_attributes = True class WOLResponse(BaseModel): """Réponse après envoi Wake-on-LAN""" message: str ip: str mac: str success: bool class ShutdownResponse(BaseModel): """Réponse après commande d'arrêt""" message: str ip: str success: bool @router.get("/", response_model=List[IPTrackingResponse]) async def get_tracked_ips(db: Session = Depends(get_db)): """ Récupère toutes les IPs marquées comme suivies Retourne la liste des équipements avec leur état actuel """ tracked_ips = db.query(IP).filter(IP.tracked == True).order_by(IP.name, IP.ip).all() return tracked_ips @router.post("/wol/{ip_address}", response_model=WOLResponse) async def wake_on_lan(ip_address: str, db: Session = Depends(get_db)): """ Envoie un paquet Magic Packet Wake-on-LAN à l'équipement Nécessite que l'IP ait une adresse MAC enregistrée """ # Récupérer l'IP depuis la base ip_obj = db.query(IP).filter(IP.ip == ip_address).first() if not ip_obj: raise HTTPException( status_code=404, detail=f"IP {ip_address} non trouvée dans la base de données" ) if not ip_obj.mac: raise HTTPException( status_code=400, detail=f"Adresse MAC manquante pour {ip_address}. Impossible d'envoyer le paquet WOL." ) try: # Importer la bibliothèque wakeonlan from wakeonlan import send_magic_packet # Envoyer le paquet Magic Packet send_magic_packet(ip_obj.mac) return WOLResponse( message=f"Paquet Wake-on-LAN envoyé avec succès", ip=ip_address, mac=ip_obj.mac, success=True ) except ImportError: raise HTTPException( status_code=500, detail="La bibliothèque 'wakeonlan' n'est pas installée. Exécutez: pip install wakeonlan" ) except Exception as e: raise HTTPException( status_code=500, detail=f"Erreur lors de l'envoi du paquet WOL: {str(e)}" ) @router.post("/shutdown/{ip_address}", response_model=ShutdownResponse) async def shutdown_device(ip_address: str, db: Session = Depends(get_db)): """ Envoie une commande shutdown via MQTT à l'équipement """ # Récupérer l'IP depuis la base ip_obj = db.query(IP).filter(IP.ip == ip_address).first() if not ip_obj: raise HTTPException( status_code=404, detail=f"IP {ip_address} non trouvée dans la base de données" ) if ip_obj.last_status != "online": raise HTTPException( status_code=400, detail=f"L'équipement {ip_address} est déjà hors ligne" ) try: from backend.app.services.mqtt_client import send_mqtt_command # Envoyer commande shutdown via MQTT success = send_mqtt_command(ip_address, "shutdown") if success: return ShutdownResponse( message=f"Commande shutdown envoyée à {ip_address} via MQTT", ip=ip_address, success=True ) else: raise HTTPException( status_code=500, detail="Échec de l'envoi de la commande MQTT" ) except ImportError: raise HTTPException( status_code=500, detail="Le service MQTT n'est pas configuré. Consultez mqtt/docs/README.md" ) except Exception as e: raise HTTPException( status_code=500, detail=f"Erreur lors de l'envoi de la commande: {str(e)}" ) @router.post("/reboot/{ip_address}", response_model=ShutdownResponse) async def reboot_device(ip_address: str, db: Session = Depends(get_db)): """ Envoie une commande reboot via MQTT à l'équipement """ # Récupérer l'IP depuis la base ip_obj = db.query(IP).filter(IP.ip == ip_address).first() if not ip_obj: raise HTTPException( status_code=404, detail=f"IP {ip_address} non trouvée" ) if ip_obj.last_status != "online": raise HTTPException( status_code=400, detail=f"L'équipement {ip_address} est hors ligne" ) try: from backend.app.services.mqtt_client import send_mqtt_command # Envoyer commande reboot via MQTT success = send_mqtt_command(ip_address, "reboot") if success: return ShutdownResponse( message=f"Commande reboot envoyée à {ip_address} via MQTT", ip=ip_address, success=True ) else: raise HTTPException( status_code=500, detail="Échec de l'envoi de la commande MQTT" ) except ImportError: raise HTTPException( status_code=500, detail="Le service MQTT n'est pas configuré" ) except Exception as e: raise HTTPException( status_code=500, detail=f"Erreur: {str(e)}" ) @router.patch("/{ip_address}/toggle", response_model=IPTrackingResponse) async def toggle_tracking(ip_address: str, db: Session = Depends(get_db)): """ Bascule l'état de suivi d'une IP (tracked true/false) """ ip_obj = db.query(IP).filter(IP.ip == ip_address).first() if not ip_obj: raise HTTPException( status_code=404, detail=f"IP {ip_address} non trouvée" ) # Inverser l'état tracked ip_obj.tracked = not ip_obj.tracked db.commit() db.refresh(ip_obj) return ip_obj