mirror of
https://github.com/Jerryplusy/AI-powered-switches.git
synced 2025-07-04 05:09:19 +00:00
Compare commits
3 Commits
5c6e89b937
...
a32d4803b7
Author | SHA1 | Date | |
---|---|---|---|
![]() |
a32d4803b7 | ||
![]() |
46ac2e63b4 | ||
3e8da7c8d2 |
@ -3,8 +3,8 @@ from src.backend.app.api.endpoints import router
|
||||
from src.backend.app.utils.logger import setup_logging
|
||||
from src.backend.config import settings
|
||||
|
||||
app = FastAPI()
|
||||
app.include_router(router,prefix="/api")
|
||||
api_app = FastAPI()
|
||||
api_app.include_router(router,prefix="/api")
|
||||
|
||||
def create_app() -> FastAPI:
|
||||
# 设置日志
|
||||
|
@ -1,8 +1,7 @@
|
||||
from typing import Dict, Any
|
||||
from typing import Dict, Any, Optional
|
||||
from src.backend.app.services.ai_services import AIService
|
||||
from src.backend.config import settings
|
||||
|
||||
|
||||
class CommandParser:
|
||||
def __init__(self):
|
||||
self.ai_service = AIService(settings.SILICONFLOW_API_KEY, settings.SILICONFLOW_API_URL)
|
||||
@ -19,7 +18,8 @@ class CommandParser:
|
||||
# 本地无法解析则调用AI服务
|
||||
return await self.ai_service.parse_command(command)
|
||||
|
||||
def _try_local_parse(self, command: str) -> Dict[str, Any]:
|
||||
@staticmethod
|
||||
def _try_local_parse(command: str) -> Optional[Dict[str, Any]]:
|
||||
"""
|
||||
尝试本地解析常见命令
|
||||
"""
|
||||
@ -28,12 +28,13 @@ class CommandParser:
|
||||
# VLAN配置
|
||||
if "vlan" in command and "创建" in command:
|
||||
parts = command.split()
|
||||
vlan_id = next((p for p in parts if p.isdigit()), None)
|
||||
if vlan_id:
|
||||
vlan_id_str = next((p for p in parts if p.isdigit()), None)
|
||||
if vlan_id_str:
|
||||
vlan_id = int(vlan_id_str) # 转换为整数
|
||||
return {
|
||||
"type": "vlan",
|
||||
"vlan_id": int(vlan_id),
|
||||
"name": f"VLAN{vlan_id}",
|
||||
"vlan_id": vlan_id, # 使用整数
|
||||
"name": f"VLAN{vlan_id}", # 使用转换后的整数
|
||||
"interfaces": []
|
||||
}
|
||||
|
||||
@ -60,9 +61,9 @@ class CommandParser:
|
||||
config["description"] = description
|
||||
|
||||
if "vlan" in command:
|
||||
vlan_id = next((p for p in parts if p.isdigit()), None)
|
||||
if vlan_id:
|
||||
config["vlan"] = int(vlan_id)
|
||||
vlan_id_str = next((p for p in parts if p.isdigit()), None)
|
||||
if vlan_id_str:
|
||||
config["vlan"] = int(vlan_id_str) # 转换为整数
|
||||
|
||||
return config
|
||||
|
||||
|
@ -3,7 +3,7 @@ from typing import List, Dict
|
||||
from pydantic import BaseModel
|
||||
from ...config import settings
|
||||
from ..services.network_scanner import NetworkScanner
|
||||
from ..api.network_config import SwitchConfigurator, SwitchConfig
|
||||
from ..api.network_config import SwitchConfigurator
|
||||
|
||||
router = APIRouter(prefix="/api", tags=["API"])
|
||||
scanner = NetworkScanner()
|
||||
|
@ -1,6 +1,7 @@
|
||||
import asyncio
|
||||
import logging
|
||||
import telnetlib3
|
||||
import time
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Optional, Union
|
||||
@ -142,6 +143,14 @@ class SwitchConfigurator:
|
||||
except Exception as e:
|
||||
raise EnspConnectionException(f"eNSP连接失败: {str(e)}")
|
||||
|
||||
async def _clean_idle_connections(self):
|
||||
"""连接池清理机制"""
|
||||
now = time.time()
|
||||
for ip, (conn, last_used) in list(self._connection_pool.items()):
|
||||
if now - last_used > 300: # 5分钟空闲超时
|
||||
conn.close()
|
||||
del self._connection_pool[ip]
|
||||
|
||||
async def _send_ssh_commands(self, ip: str, commands: List[str]) -> str:
|
||||
"""SSH协议执行"""
|
||||
async with self.semaphore:
|
||||
|
0
src/backend/app/experiments/network_experiment.py
Normal file
0
src/backend/app/experiments/network_experiment.py
Normal file
0
src/backend/app/experiments/performance_analysis.py
Normal file
0
src/backend/app/experiments/performance_analysis.py
Normal file
0
src/backend/app/services/ai_configurator.py
Normal file
0
src/backend/app/services/ai_configurator.py
Normal file
@ -58,4 +58,7 @@ class AIService:
|
||||
return json.loads(config_str)
|
||||
raise SiliconFlowAPIException("Invalid JSON format returned from AI")
|
||||
except httpx.HTTPError as e:
|
||||
raise SiliconFlowAPIException(str(e))
|
||||
raise SiliconFlowAPIException(
|
||||
detail=f"API请求失败: {str(e)}",
|
||||
status_code=e.response.status_code if hasattr(e, "response") else 500
|
||||
)
|
36
src/backend/app/services/network_optimizer.py
Normal file
36
src/backend/app/services/network_optimizer.py
Normal file
@ -0,0 +1,36 @@
|
||||
|
||||
import networkx as nx
|
||||
from scipy.optimize import minimize
|
||||
|
||||
|
||||
class NetworkOptimizer:
|
||||
def __init__(self, devices):
|
||||
"""基于图论的网络优化模型"""
|
||||
self.graph = self.build_topology_graph(devices)
|
||||
|
||||
def build_topology_graph(self, devices):
|
||||
"""构建网络拓扑图"""
|
||||
G = nx.Graph()
|
||||
for device in devices:
|
||||
G.add_node(device['ip'], type=device['type'])
|
||||
# 添加连接关系(示例)
|
||||
G.add_edge('192.168.1.1', '192.168.1.2', bandwidth=1000)
|
||||
return G
|
||||
|
||||
def optimize_path(self, source, target):
|
||||
"""计算最优路径"""
|
||||
return nx.shortest_path(self.graph, source, target)
|
||||
|
||||
def bandwidth_optimization(self):
|
||||
"""带宽优化模型"""
|
||||
|
||||
def objective(x):
|
||||
# 最小化最大链路利用率
|
||||
return max(x)
|
||||
|
||||
constraints = (
|
||||
{'type': 'eq', 'fun': lambda x: sum(x) - total_bandwidth}
|
||||
)
|
||||
|
||||
result = minimize(objective, initial_guess, constraints=constraints)
|
||||
return result.x
|
@ -1,5 +1,14 @@
|
||||
from fastapi import HTTPException, status
|
||||
from typing import Optional
|
||||
|
||||
class SiliconFlowAPIException(Exception):
|
||||
"""硅基流动API异常"""
|
||||
def __init__(self, detail: str, status_code: int = 500):
|
||||
self.detail = detail
|
||||
self.status_code = status_code
|
||||
super().__init__(detail)
|
||||
|
||||
def __str__(self):
|
||||
return f"SiliconFlowAPI Error [{self.status_code}]: {self.detail}"
|
||||
|
||||
class AICommandParseException(HTTPException):
|
||||
def __init__(self, detail: str):
|
||||
@ -23,9 +32,9 @@ class ConfigBackupException(SwitchConfigException):
|
||||
"""配置备份失败异常"""
|
||||
def __init__(self, ip: str):
|
||||
super().__init__(
|
||||
detail=f"无法备份设备 {ip} 的配置",
|
||||
recovery_guide="检查设备存储空间或权限"
|
||||
detail=f"无法备份设备 {ip} 的配置"
|
||||
)
|
||||
self.recovery_guide = "检查设备存储空间或权限" # 在子类中存储恢复指南
|
||||
|
||||
class ConfigRollbackException(SwitchConfigException):
|
||||
"""回滚失败异常"""
|
||||
@ -34,3 +43,4 @@ class ConfigRollbackException(SwitchConfigException):
|
||||
detail=f"设备 {ip} 回滚失败(原始错误:{original_error})",
|
||||
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY
|
||||
)
|
||||
self.recovery_guide = "尝试手动恢复配置或重启设备"
|
0
src/backend/app/utils/visualization/topology_3d.py
Normal file
0
src/backend/app/utils/visualization/topology_3d.py
Normal file
@ -24,8 +24,8 @@ class BulkConfigurator:
|
||||
return "\n".join(r.stdout for r in results)
|
||||
finally:
|
||||
await self.pool.release_connection(ip, conn)
|
||||
|
||||
def _generate_commands(self, config: BulkSwitchConfig) -> List[str]:
|
||||
@staticmethod
|
||||
def _generate_commands(config: BulkSwitchConfig) -> List[str]:
|
||||
"""命令生成(纯业务逻辑)"""
|
||||
commands = []
|
||||
if config.vlan_id:
|
||||
|
@ -1,9 +1,7 @@
|
||||
import asyncio
|
||||
import time
|
||||
import asyncssh
|
||||
from typing import Dict
|
||||
|
||||
|
||||
class SwitchConnectionPool:
|
||||
"""
|
||||
交换机连接池(支持自动重连和负载均衡)
|
||||
@ -35,10 +33,15 @@ class SwitchConnectionPool:
|
||||
|
||||
async def release_connection(self, ip: str, conn: asyncssh.SSHClientConnection):
|
||||
async with self._lock:
|
||||
if conn.is_connected() and self._pools[ip].qsize() < self._max_conn:
|
||||
if hasattr(conn, 'is_closed') and not conn.is_closed() and self._pools[ip].qsize() < self._max_conn:
|
||||
await self._pools[ip].put(conn)
|
||||
elif hasattr(conn, 'closed') and not conn.closed and self._pools[ip].qsize() < self._max_conn:
|
||||
await self._pools[ip].put(conn)
|
||||
else:
|
||||
conn.close()
|
||||
try:
|
||||
conn.close()
|
||||
except:
|
||||
pass
|
||||
|
||||
async def close_all(self):
|
||||
async with self._lock:
|
||||
|
@ -11,4 +11,9 @@ typing-extensions>=4.0.0
|
||||
aiofiles>=24.1.0
|
||||
telnetlib3>=2.0.4
|
||||
asyncssh>=2.14.0
|
||||
aiofiles>=24.1.0
|
||||
aiofiles>=24.1.0
|
||||
networkx==3.1
|
||||
scipy==1.11.1
|
||||
stable-baselines3==2.0.0
|
||||
plotly==5.15.0
|
||||
pandas==2.0.3
|
Binary file not shown.
Before Width: | Height: | Size: 869 KiB |
@ -1 +0,0 @@
|
||||
# 论文(markdown形式)
|
Loading…
x
Reference in New Issue
Block a user