From fcf072636e85022f1a40846e565e3edb14f28c82 Mon Sep 17 00:00:00 2001 From: Jerry Date: Fri, 18 Jul 2025 16:42:03 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=AB=AF=E7=82=B9=EF=BC=9A?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E9=80=82=E9=85=8D=E5=99=A8=E7=BD=91=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/app/api/endpoints.py | 50 +++++++++++++++---------- src/backend/app/services/ai_services.py | 4 +- src/backend/requirements.txt | 1 - 3 files changed, 33 insertions(+), 22 deletions(-) diff --git a/src/backend/app/api/endpoints.py b/src/backend/app/api/endpoints.py index 039ca13..0f92bc1 100644 --- a/src/backend/app/api/endpoints.py +++ b/src/backend/app/api/endpoints.py @@ -1,3 +1,4 @@ +import socket from datetime import datetime, timedelta from fastapi import (APIRouter, HTTPException, Response, WebSocket, WebSocketDisconnect) from typing import List @@ -7,6 +8,8 @@ from fastapi.responses import HTMLResponse import matplotlib.pyplot as plt import io import base64 +import psutil +import ipaddress from ..services.switch_traffic_monitor import get_switch_monitor from ..utils import logger @@ -271,7 +274,7 @@ async def get_switch_current_traffic(switch_ip: str, interface: str = None): try: monitor = get_switch_monitor(switch_ip) - # 如果没有指定接口,获取所有接口的流量 + if not interface: traffic_data = {} for iface in monitor.interface_oids: @@ -281,7 +284,6 @@ async def get_switch_current_traffic(switch_ip: str, interface: str = None): "traffic": traffic_data } - # 获取指定接口的流量 return await get_interface_current_traffic(switch_ip, interface) except Exception as e: logger.error(f"获取交换机流量失败: {str(e)}") @@ -292,7 +294,7 @@ async def get_interface_current_traffic(switch_ip: str, interface: str) -> dict: """获取指定交换机接口的当前流量数据""" try: with SessionLocal() as session: - # 获取最新记录 + record = session.query(SwitchTrafficRecord).filter( SwitchTrafficRecord.switch_ip == switch_ip, SwitchTrafficRecord.interface == interface @@ -327,26 +329,21 @@ async def get_switch_traffic_history(switch_ip: str, interface: str = None, minu try: monitor = get_switch_monitor(switch_ip) - # 如果没有指定接口,返回所有接口的历史数据 if not interface: return { "switch_ip": switch_ip, "history": monitor.get_traffic_history() } - # 获取指定接口的历史数据 with SessionLocal() as session: - # 计算时间范围 time_threshold = datetime.now() - timedelta(minutes=minutes) - # 查询历史记录 records = session.query(SwitchTrafficRecord).filter( SwitchTrafficRecord.switch_ip == switch_ip, SwitchTrafficRecord.interface == interface, SwitchTrafficRecord.timestamp >= time_threshold ).order_by(SwitchTrafficRecord.timestamp.asc()).all() - # 提取数据 history_data = { "in": [record.rate_in for record in records], "out": [record.rate_out for record in records], @@ -371,13 +368,10 @@ async def websocket_switch_traffic(websocket: WebSocket, switch_ip: str, interfa monitor = get_switch_monitor(switch_ip) while True: - # 获取流量数据 if interface: - # 单个接口 traffic_data = await get_interface_current_traffic(switch_ip, interface) await websocket.send_json(traffic_data) else: - # 所有接口 traffic_data = {} for iface in monitor.interface_oids: traffic_data[iface] = await get_interface_current_traffic(switch_ip, iface) @@ -387,7 +381,6 @@ async def websocket_switch_traffic(websocket: WebSocket, switch_ip: str, interfa "traffic": traffic_data }) - # 每秒更新一次 await asyncio.sleep(1) except WebSocketDisconnect: logger.info(f"客户端断开交换机流量连接: {switch_ip}") @@ -395,22 +388,17 @@ async def websocket_switch_traffic(websocket: WebSocket, switch_ip: str, interfa logger.error(f"交换机流量WebSocket错误: {str(e)}") await websocket.close(code=1011, reason=str(e)) - -# 交换机流量可视化 @router.get("/traffic/switch/plot", response_class=HTMLResponse, summary="交换机流量可视化") async def plot_switch_traffic(switch_ip: str, interface: str, minutes: int = 10): """生成交换机流量图表""" try: - # 获取历史数据 history = await get_switch_traffic_history(switch_ip, interface, minutes) history_data = history["history"] - # 提取数据点 time_points = [datetime.fromisoformat(t) for t in history_data["time"]] in_rates = history_data["in"] out_rates = history_data["out"] - # 创建图表 plt.figure(figsize=(12, 6)) plt.plot(time_points, in_rates, label="流入流量 (B/s)") plt.plot(time_points, out_rates, label="流出流量 (B/s)") @@ -421,8 +409,6 @@ async def plot_switch_traffic(switch_ip: str, interface: str, minutes: int = 10) plt.grid(True) plt.xticks(rotation=45) plt.tight_layout() - - # 转换为HTML图像 buf = io.BytesIO() plt.savefig(buf, format="png") buf.seek(0) @@ -450,3 +436,29 @@ async def plot_switch_traffic(switch_ip: str, interface: str, minutes: int = 10) except Exception as e: logger.error(f"生成流量图表失败: {str(e)}") return HTMLResponse(content=f"

错误

{str(e)}

", status_code=500) + + +@router.get("/network_adapters", summary="获取网络适配器网段") +async def get_network_adapters(): + try: + net_if_addrs = psutil.net_if_addrs() + + networks = [] + for interface, addrs in net_if_addrs.items(): + for addr in addrs: + if addr.family == socket.AF_INET: + ip = addr.address + netmask = addr.netmask + + network = ipaddress.IPv4Network(f"{ip}/{netmask}", strict=False) + networks.append({ + "adapter": interface, + "network": str(network), + "ip": ip, + "subnet_mask": netmask + }) + + return {"networks": networks} + + except Exception as e: + return {"error": f"获取网络适配器信息失败: {str(e)}"} \ No newline at end of file diff --git a/src/backend/app/services/ai_services.py b/src/backend/app/services/ai_services.py index f0b1ab5..da000c8 100644 --- a/src/backend/app/services/ai_services.py +++ b/src/backend/app/services/ai_services.py @@ -30,9 +30,9 @@ class AIService: 2. 必须包含'commands'字段,包含可直接执行的命令列表 3. 其他参数根据配置类型动态添加 4. 不要包含解释性文本、步骤说明或注释 - 5.要包含使用ssh连接交换机后的完整命令包括但不完全包括system-view,退出,保存等完整操作 + 5.要包含使用ssh连接交换机后的完整命令包括但不完全包括system-view,退出,保存等完整操作,注意保存还需要输入Y和回车 示例命令:'创建VLAN 100,名称为TEST' - 示例返回:{"type": "vlan", "vlan_id": 100, "name": "TEST", "commands": ["vlan 100", "name TEST"]} + 示例返回:{"type": "vlan", "vlan_id": 100, "name": "TEST", "commands": ["system-view\n","vlan 100\n", "name TEST\n","quit\n","\x1A\n","save\n","Y\n"]} 注意:这里生成的commands中需包含登录交换机和保存等所有操作命令,我们使ssh连接交换机,你不需要给出连接ssh的命令,你只需要给出使用ssh连接到交换机后所输入的全部命令 """ diff --git a/src/backend/requirements.txt b/src/backend/requirements.txt index eaacebc..37910c5 100644 --- a/src/backend/requirements.txt +++ b/src/backend/requirements.txt @@ -12,7 +12,6 @@ pysnmp==7.1.21 aiofiles==23.2.1 loguru==0.7.2 - tenacity==8.2.3 asyncio==3.4.3