diff --git a/src/backend/app/api/endpoints.py b/src/backend/app/api/endpoints.py index 44e75fa..e1835ac 100644 --- a/src/backend/app/api/endpoints.py +++ b/src/backend/app/api/endpoints.py @@ -50,13 +50,19 @@ async def favicon(): class BatchConfigRequest(BaseModel): config: dict switch_ips: List[str] # 支持多个IP + username: str = None # 添加用户名参数 + password: str = None # 添加密码参数 + timeout: int = None @router.post("/batch_apply_config") async def batch_apply_config(request: BatchConfigRequest): results = {} for ip in request.switch_ips: try: - configurator = SwitchConfigurator() + configurator = SwitchConfigurator( + username=request.username, + password=request.password, + timeout=request.timeout ) results[ip] = await configurator.apply_config(ip, request.config) except Exception as e: results[ip] = str(e) @@ -92,6 +98,9 @@ class CommandRequest(BaseModel): class ConfigRequest(BaseModel): config: dict switch_ip: str + username: str = None + password: str = None + timeout: int = None @router.post("/parse_command", response_model=dict) async def parse_command(request: CommandRequest): @@ -115,9 +124,9 @@ async def apply_config(request: ConfigRequest): """ try: configurator = SwitchConfigurator( - username=settings.SWITCH_USERNAME, - password=settings.SWITCH_PASSWORD, - timeout=settings.SWITCH_TIMEOUT + username=request.username, + password=request.password, + timeout=request.timeout ) result = await configurator.safe_apply(request.switch_ip, request.config) return {"success": True, "result": result} @@ -133,16 +142,40 @@ class CLICommandRequest(BaseModel): commands: List[str] # 前端生成的CLI命令列表 is_ensp: bool = False # 是否为eNSP模拟器模式 + # 添加方法从commands中提取凭据 + def extract_credentials(self) -> tuple: + """从commands中提取用户名和密码""" + username = None + password = None + + for cmd in self.commands: + if cmd.startswith("!username="): + username = cmd.split("=")[1] + elif cmd.startswith("!password="): + password = cmd.split("=")[1] + + return username, password + + def get_clean_commands(self) -> List[str]: + """获取去除凭据后的实际命令""" + return [cmd for cmd in self.commands + if not (cmd.startswith("!username=") or cmd.startswith("!password="))] @router.post("/execute_cli_commands", response_model=dict) async def execute_cli_commands(request: CLICommandRequest): """ 执行前端生成的CLI命令 + 支持在commands中嵌入凭据: + !username=admin + !password=cisco123 """ try: + username, password = request.extract_credentials() + clean_commands = request.get_clean_commands() + configurator = SwitchConfigurator( - username=settings.SWITCH_USERNAME, - password=settings.SWITCH_PASSWORD, + username=username, + password=password, timeout=settings.SWITCH_TIMEOUT, ensp_mode=request.is_ensp ) @@ -220,7 +253,7 @@ async def root(): } -# ... 其他路由保持不变 ... + @router.get("/traffic/switch/interfaces", summary="获取交换机的网络接口") async def get_switch_interfaces(switch_ip: str): diff --git a/src/backend/app/api/network_config.py b/src/backend/app/api/network_config.py index edd2371..4ce195c 100644 --- a/src/backend/app/api/network_config.py +++ b/src/backend/app/api/network_config.py @@ -10,6 +10,8 @@ import asyncssh from pydantic import BaseModel from tenacity import retry, stop_after_attempt, wait_exponential +from src.backend.config import settings + # ---------------------- # 数据模型 @@ -44,18 +46,18 @@ class SSHConnectionException(SwitchConfigException): class SwitchConfigurator: def __init__( self, - username: str = "admin", - password: str = "admin", - timeout: int = 10, + username: str = None, + password: str = None, + timeout: int = None, max_workers: int = 5, ensp_mode: bool = False, ensp_port: int = 2000, ensp_command_delay: float = 0.5, **ssh_options ): - self.username = username - self.password = password - self.timeout = timeout + self.username = username if username is not None else settings.SWITCH_USERNAME + self.password = password if password is not None else settings.SWITCH_PASSWORD + self.timeout = timeout if timeout is not None else settings.SWITCH_TIMEOUT self.semaphore = asyncio.Semaphore(max_workers) self.backup_dir = Path("config_backups") self.backup_dir.mkdir(exist_ok=True) diff --git a/src/backend/config.py b/src/backend/config.py index 2e2901c..b5c9863 100644 --- a/src/backend/config.py +++ b/src/backend/config.py @@ -16,6 +16,8 @@ class Settings(BaseSettings): SILICONFLOW_API_URL: str = os.getenv("SILICONFLOW_API_URL", "https://api.siliconflow.cn/v1") # 交换机配置 + SWITCH_USERNAME: str = os.getenv("SWITCH_USERNAME", "admin") + SWITCH_PASSWORD: str = os.getenv("SWITCH_PASSWORD", "admin") SWITCH_TIMEOUT: int = os.getenv("SWITCH_TIMEOUT", 10) # eNSP配置 diff --git a/src/backend/requirements.txt b/src/backend/requirements.txt index 3febf22..fc3d18e 100644 --- a/src/backend/requirements.txt +++ b/src/backend/requirements.txt @@ -1,7 +1,6 @@ fastapi==0.110.0 uvicorn==0.29.0 python-dotenv==1.0.1 -pysnmp pydantic==2.6.4 pydantic-settings==2.2.1 openai==1.93.2