228 lines
6.4 KiB
Python
228 lines
6.4 KiB
Python
"""
|
|
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
|