"""算法服务管理路由,提供服务注册、管理等功能""" from fastapi import APIRouter, HTTPException, status, Depends from typing import List, Dict, Any, Optional from pydantic import BaseModel import uuid import os from app.models.models import AlgorithmService from app.models.database import SessionLocal from app.routes.user import get_current_active_user from app.services.project_analyzer import ProjectAnalyzer from app.services.service_generator import ServiceGenerator from app.services.service_orchestrator import ServiceOrchestrator router = APIRouter(prefix="/services", tags=["services"]) class RegisterServiceRequest(BaseModel): """注册服务请求""" repository_id: str name: str version: str = "1.0.0" service_type: str = "http" host: str = "0.0.0.0" port: int = 8000 timeout: int = 30 health_check_path: str = "/health" environment: Dict[str, str] = {} class ServiceResponse(BaseModel): """服务响应""" id: str service_id: str name: str algorithm_name: str version: str host: str port: int api_url: str status: str created_at: str updated_at: str class ServiceListResponse(BaseModel): """服务列表响应""" success: bool services: List[ServiceResponse] class ServiceDetailResponse(BaseModel): """服务详情响应""" success: bool service: ServiceResponse class ServiceOperationResponse(BaseModel): """服务操作响应""" success: bool message: str service_id: str status: str class ServiceStatusResponse(BaseModel): """服务状态响应""" success: bool status: str health: str class ServiceLogsResponse(BaseModel): """服务日志响应""" success: bool logs: List[str] class RepositoryAlgorithmsResponse(BaseModel): """仓库算法列表响应""" success: bool algorithms: List[Dict[str, Any]] # 初始化服务组件 project_analyzer = ProjectAnalyzer() service_generator = ServiceGenerator() service_orchestrator = ServiceOrchestrator() @router.post("/register", status_code=status.HTTP_201_CREATED) async def register_service( request: RegisterServiceRequest, current_user: dict = Depends(get_current_active_user) ): """注册新服务""" # 检查用户权限 if current_user.role != "admin": raise HTTPException(status_code=403, detail="Insufficient permissions") # 创建数据库会话 db = SessionLocal() try: # 1. 获取仓库信息 # 注意:在实际实现中,应该从数据库中获取仓库信息 # 这里简化处理,假设仓库存在 # 2. 分析项目 repo_path = f"/tmp/repository_{request.repository_id}" # 注意:在实际实现中,应该从算法仓库中获取项目文件 # 这里简化处理,创建一个模拟的项目结构 os.makedirs(repo_path, exist_ok=True) # 创建模拟的算法文件 with open(os.path.join(repo_path, "algorithm.py"), "w") as f: f.write(""" def predict(data): return {"result": "Prediction result", "input": data} def run(data): return {"result": "Run result", "input": data} def main(data): return {"result": "Main result", "input": data} """) # 分析项目 project_info = project_analyzer.analyze_project(repo_path) if not project_info["success"]: raise HTTPException(status_code=400, detail=f"项目分析失败: {project_info['error']}") # 3. 生成服务包装器 service_config = { "name": request.name, "version": request.version, "service_type": request.service_type, "host": request.host, "port": request.port, "timeout": request.timeout, "health_check_path": request.health_check_path, "environment": request.environment } generate_result = service_generator.generate_service(project_info, service_config) if not generate_result["success"]: raise HTTPException(status_code=400, detail=f"服务生成失败: {generate_result['error']}") # 4. 部署服务 service_id = str(uuid.uuid4()) deploy_result = service_orchestrator.deploy_service(service_id, service_config, project_info) if not deploy_result["success"]: raise HTTPException(status_code=400, detail=f"服务部署失败: {deploy_result['error']}") # 5. 保存服务信息到数据库 new_service = AlgorithmService( id=str(uuid.uuid4()), service_id=service_id, name=request.name, algorithm_name="algorithm", # 注意:在实际实现中,应该从仓库信息中获取 version=request.version, host=request.host, port=request.port, api_url=deploy_result["api_url"], status=deploy_result["status"], config={ "service_type": request.service_type, "timeout": request.timeout, "health_check_path": request.health_check_path, "environment": request.environment, "container_id": deploy_result["container_id"] } ) db.add(new_service) db.commit() db.refresh(new_service) # 6. 返回响应 return { "success": True, "message": "服务注册成功", "service": { "id": new_service.id, "service_id": new_service.service_id, "name": new_service.name, "algorithm_name": new_service.algorithm_name, "version": new_service.version, "host": new_service.host, "port": new_service.port, "api_url": new_service.api_url, "status": new_service.status, "created_at": new_service.created_at.isoformat(), "updated_at": new_service.updated_at.isoformat() } } finally: db.close() @router.get("", response_model=ServiceListResponse) async def list_services( current_user: dict = Depends(get_current_active_user) ): """获取服务列表""" # 检查用户权限 if current_user.role != "admin": raise HTTPException(status_code=403, detail="Insufficient permissions") # 创建数据库会话 db = SessionLocal() try: # 查询服务列表 services = db.query(AlgorithmService).all() # 转换为响应格式 service_list = [] for service in services: service_list.append(ServiceResponse( id=service.id, service_id=service.service_id, name=service.name, algorithm_name=service.algorithm_name, version=service.version, host=service.host, port=service.port, api_url=service.api_url, status=service.status, created_at=service.created_at.isoformat(), updated_at=service.updated_at.isoformat() )) return ServiceListResponse( success=True, services=service_list ) finally: db.close() @router.get("/{service_id}", response_model=ServiceDetailResponse) async def get_service( service_id: str, current_user: dict = Depends(get_current_active_user) ): """获取服务详情""" # 检查用户权限 if current_user.role != "admin": raise HTTPException(status_code=403, detail="Insufficient permissions") # 创建数据库会话 db = SessionLocal() try: # 查询服务 service = db.query(AlgorithmService).filter(AlgorithmService.service_id == service_id).first() if not service: raise HTTPException(status_code=404, detail="Service not found") # 返回响应 return ServiceDetailResponse( success=True, service=ServiceResponse( id=service.id, service_id=service.service_id, name=service.name, algorithm_name=service.algorithm_name, version=service.version, host=service.host, port=service.port, api_url=service.api_url, status=service.status, created_at=service.created_at.isoformat(), updated_at=service.updated_at.isoformat() ) ) finally: db.close() @router.post("/{service_id}/start") async def start_service( service_id: str, current_user: dict = Depends(get_current_active_user) ): """启动服务""" # 检查用户权限 if current_user.role != "admin": raise HTTPException(status_code=403, detail="Insufficient permissions") # 创建数据库会话 db = SessionLocal() try: # 查询服务 service = db.query(AlgorithmService).filter(AlgorithmService.service_id == service_id).first() if not service: raise HTTPException(status_code=404, detail="Service not found") # 获取容器ID container_id = service.config.get("container_id") if not container_id: raise HTTPException(status_code=400, detail="Container ID not found") # 启动服务 start_result = service_orchestrator.start_service(service_id, container_id) if not start_result["success"]: raise HTTPException(status_code=400, detail=f"服务启动失败: {start_result['error']}") # 更新服务状态 service.status = start_result["status"] db.commit() # 返回响应 return ServiceOperationResponse( success=True, message="服务启动成功", service_id=service_id, status=start_result["status"] ) finally: db.close() @router.post("/{service_id}/stop") async def stop_service( service_id: str, current_user: dict = Depends(get_current_active_user) ): """停止服务""" # 检查用户权限 if current_user.role != "admin": raise HTTPException(status_code=403, detail="Insufficient permissions") # 创建数据库会话 db = SessionLocal() try: # 查询服务 service = db.query(AlgorithmService).filter(AlgorithmService.service_id == service_id).first() if not service: raise HTTPException(status_code=404, detail="Service not found") # 获取容器ID container_id = service.config.get("container_id") if not container_id: raise HTTPException(status_code=400, detail="Container ID not found") # 停止服务 stop_result = service_orchestrator.stop_service(service_id, container_id) if not stop_result["success"]: raise HTTPException(status_code=400, detail=f"服务停止失败: {stop_result['error']}") # 更新服务状态 service.status = stop_result["status"] db.commit() # 返回响应 return ServiceOperationResponse( success=True, message="服务停止成功", service_id=service_id, status=stop_result["status"] ) finally: db.close() @router.post("/{service_id}/restart") async def restart_service( service_id: str, current_user: dict = Depends(get_current_active_user) ): """重启服务""" # 检查用户权限 if current_user.role != "admin": raise HTTPException(status_code=403, detail="Insufficient permissions") # 创建数据库会话 db = SessionLocal() try: # 查询服务 service = db.query(AlgorithmService).filter(AlgorithmService.service_id == service_id).first() if not service: raise HTTPException(status_code=404, detail="Service not found") # 获取容器ID container_id = service.config.get("container_id") if not container_id: raise HTTPException(status_code=400, detail="Container ID not found") # 重启服务 restart_result = service_orchestrator.restart_service(service_id, container_id) if not restart_result["success"]: raise HTTPException(status_code=400, detail=f"服务重启失败: {restart_result['error']}") # 更新服务状态 service.status = restart_result["status"] db.commit() # 返回响应 return ServiceOperationResponse( success=True, message="服务重启成功", service_id=service_id, status=restart_result["status"] ) finally: db.close() @router.delete("/{service_id}") async def delete_service( service_id: str, current_user: dict = Depends(get_current_active_user) ): """删除服务""" # 检查用户权限 if current_user.role != "admin": raise HTTPException(status_code=403, detail="Insufficient permissions") # 创建数据库会话 db = SessionLocal() try: # 查询服务 service = db.query(AlgorithmService).filter(AlgorithmService.service_id == service_id).first() if not service: raise HTTPException(status_code=404, detail="Service not found") # 获取容器ID和镜像名称 container_id = service.config.get("container_id") image_name = f"algorithm-service-{service_id}:{service.version}" # 删除服务 delete_result = service_orchestrator.delete_service(service_id, container_id, image_name) if not delete_result["success"]: # 继续执行,即使Docker操作失败 pass # 删除数据库记录 db.delete(service) db.commit() # 返回响应 return { "success": True, "message": "服务删除成功", "service_id": service_id } finally: db.close() @router.get("/{service_id}/status") async def get_service_status( service_id: str, current_user: dict = Depends(get_current_active_user) ): """获取服务状态""" # 检查用户权限 if current_user.role != "admin": raise HTTPException(status_code=403, detail="Insufficient permissions") # 创建数据库会话 db = SessionLocal() try: # 查询服务 service = db.query(AlgorithmService).filter(AlgorithmService.service_id == service_id).first() if not service: raise HTTPException(status_code=404, detail="Service not found") # 获取容器ID container_id = service.config.get("container_id") if not container_id: raise HTTPException(status_code=400, detail="Container ID not found") # 获取服务状态 status_result = service_orchestrator.get_service_status(container_id) if not status_result["success"]: raise HTTPException(status_code=400, detail=f"获取服务状态失败: {status_result['error']}") # 返回响应 return ServiceStatusResponse( success=True, status=status_result["status"], health=status_result["health"] ) finally: db.close() @router.get("/{service_id}/logs") async def get_service_logs( service_id: str, lines: int = 100, current_user: dict = Depends(get_current_active_user) ): """获取服务日志""" # 检查用户权限 if current_user.role != "admin": raise HTTPException(status_code=403, detail="Insufficient permissions") # 创建数据库会话 db = SessionLocal() try: # 查询服务 service = db.query(AlgorithmService).filter(AlgorithmService.service_id == service_id).first() if not service: raise HTTPException(status_code=404, detail="Service not found") # 获取容器ID container_id = service.config.get("container_id") if not container_id: raise HTTPException(status_code=400, detail="Container ID not found") # 获取服务日志 logs_result = service_orchestrator.get_service_logs(container_id, lines) if not logs_result["success"]: raise HTTPException(status_code=400, detail=f"获取服务日志失败: {logs_result['error']}") # 返回响应 return ServiceLogsResponse( success=True, logs=logs_result["logs"] ) finally: db.close() @router.get("/repository/algorithms") async def get_repository_algorithms( repository_id: str, current_user: dict = Depends(get_current_active_user) ): """获取仓库中的算法列表""" # 检查用户权限 if current_user.role != "admin": raise HTTPException(status_code=403, detail="Insufficient permissions") try: # 模拟获取仓库中的算法列表 # 注意:在实际实现中,应该从算法仓库中获取真实的算法列表 algorithms = [ { "id": "alg-001", "name": "图像分类算法", "description": "基于深度学习的图像分类算法", "type": "computer_vision", "entry_point": "algorithm.py" }, { "id": "alg-002", "name": "文本分类算法", "description": "基于BERT的文本分类算法", "type": "nlp", "entry_point": "text_algorithm.py" } ] return RepositoryAlgorithmsResponse( success=True, algorithms=algorithms ) except Exception as e: raise HTTPException(status_code=500, detail=str(e))