Files
H3ConuMS-v2/backend/app/api/v1/check.py
T

103 lines
2.8 KiB
Python

"""状态检查 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)