"""状态检查 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.core.errors import internal_error 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: raise internal_error("Trigger device status check", 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 internal_error("Scan OLT", 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 internal_error("Discover OLT devices", e)