"""主机管理路由""" from fastapi import APIRouter, HTTPException from app.hosts import ( list_hosts, get_host, add_host, remove_host, test_connection, update_host_status, HostCreate, ) from app.libvirt_conn import conn_pool import time router = APIRouter() @router.get("/list") async def api_list_hosts(): """列出所有已注册主机""" hosts = list_hosts() result = [] for h in hosts: info = h.model_dump() # 尝试获取实时状态 try: mgr = conn_pool.get(h.id) conn = mgr.conn alive = conn.isAlive() info["status"] = "online" if alive else "offline" if alive: host_data = conn.getInfo() info["cpu_cores"] = host_data[2] info["memory_mb"] = host_data[1] # getInfo()[1] 已经是 MiB 单位 info["hostname"] = conn.getHostname() # 虚拟机数 domains = conn.listAllDomains(0) info["vm_total"] = len(domains) info["vm_running"] = sum(1 for d in domains if d.isActive()) update_host_status(h.id, info["status"]) except Exception: info["status"] = "offline" update_host_status(h.id, "offline") result.append(info) return {"hosts": result, "total": len(result)} @router.get("/detail/{host_id}") async def api_get_host(host_id: str): """获取单台主机详情""" host = get_host(host_id) if not host: raise HTTPException(status_code=404, detail=f"主机 '{host_id}' 不存在") info = host.model_dump() try: mgr = conn_pool.get(host_id) info["host_info"] = mgr.get_host_info() info["status"] = "online" # 虚拟机数 domains = mgr.conn.listAllDomains(0) info["vm_total"] = len(domains) info["vm_running"] = sum(1 for d in domains if d.isActive()) update_host_status(host_id, "online") except Exception as e: info["status"] = "offline" info["error"] = str(e) update_host_status(host_id, "offline") return info @router.post("/add") async def api_add_host(req: HostCreate): """添加新主机""" # 先测试连接 result = test_connection(req.uri) if not result["success"]: raise HTTPException(status_code=400, detail=f"连接测试失败: {result['error']}") host = add_host(req) # 更新状态为在线 update_host_status(host.id, "online") return {"message": f"主机 '{host.name}' 添加成功", "host": host.model_dump()} @router.delete("/delete/{host_id}") async def api_delete_host(host_id: str): """删除主机""" if host_id == "local": raise HTTPException(status_code=400, detail="不能删除本机") if not remove_host(host_id): raise HTTPException(status_code=404, detail=f"主机 '{host_id}' 不存在") conn_pool.remove(host_id) return {"message": f"主机 '{host_id}' 已删除"} @router.post("/test") async def api_test_connection(req: HostCreate): """测试连接(不添加主机)""" result = test_connection(req.uri) return result @router.post("/refresh/{host_id}") async def api_refresh_host(host_id: str): """刷新主机状态""" host = get_host(host_id) if not host: raise HTTPException(status_code=404, detail=f"主机 '{host_id}' 不存在") try: # 重新建立连接 conn_pool.remove(host_id) mgr = conn_pool.get(host_id) conn = mgr.conn alive = conn.isAlive() status = "online" if alive else "offline" update_host_status(host_id, status) return {"status": status, "hostname": conn.getHostname()} except Exception as e: update_host_status(host_id, "offline") conn_pool.remove(host_id) return {"status": "offline", "error": str(e)}