"""状态检查 API""" import asyncio import logging from fastapi import APIRouter, HTTPException, Depends, Request from celery.result import AsyncResult from pydantic import BaseModel from typing import Optional, List from sqlalchemy.orm import Session from slowapi import Limiter from slowapi.util import get_remote_address from app.tasks.check_tasks import check_all_devices from app.core.celery_app import celery_app from app.core.database import get_db from app.services.check_service import CheckService from app.middleware.permission_middleware import require_permission logger = logging.getLogger(__name__) router = APIRouter(prefix="/api/check", tags=["状态检查"]) limiter = Limiter(key_func=get_remote_address) class CheckResult(BaseModel): olt_id: int olt_name: str online: Optional[int] = 0 offline: Optional[int] = 0 success: bool class CheckError(BaseModel): olt_id: int olt_name: str error: str @router.post("/status") @limiter.limit("3/minute") def trigger_check(request: Request, _: dict = Depends(require_permission('device.check'))): """手动触发状态检查""" try: task = check_all_devices.delay() return {"task_id": task.id, "status": "started"} except Exception as e: logger.error(f"触发状态检查失败: {str(e)}") raise HTTPException(status_code=500, detail=f"触发状态检查失败: {str(e)}") @router.get("/status/{task_id}") def get_check_status( task_id: str, _: dict = Depends(require_permission('device.check')), ): """查询状态检查任务进度和结果""" task_result = AsyncResult(task_id, app=celery_app) state = task_result.state result = { "task_id": task_id, "status": state, "progress": None, "result": None } if state == 'PROGRESS': result["progress"] = task_result.info if state == 'SUCCESS': result["result"] = task_result.result elif state == 'FAILURE': result["error"] = str(task_result.info) return result @router.post("/scan/{olt_id}") def scan_olt( olt_id: int, db: Session = Depends(get_db), _: dict = Depends(require_permission('device.check')), ): """扫描单台 OLT,预览发现的设备(不写入数据库)""" try: service = CheckService(db) result = asyncio.run(service.scan_olt(olt_id)) return result except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @router.post("/discover/{olt_id}") def discover_olt( olt_id: int, db: Session = Depends(get_db), _: dict = Depends(require_permission('olt.discover')), ): """扫描单台 OLT 并将新发现的 MAC 自动入库关联""" try: service = CheckService(db) result = service.scan_and_discover(olt_id) return result except Exception as e: raise HTTPException(status_code=500, detail=str(e))