diff --git a/src/backend/.env.txt b/src/backend/.env.txt new file mode 100644 index 0000000..2ce142d --- /dev/null +++ b/src/backend/.env.txt @@ -0,0 +1,11 @@ +# 硅基流动API配置 +SILICONFLOW_API_KEY=sk-mhzuedasunrgdrxfkcxmxgaypgjnxgodvvmrzzdbqrwtkqej +SILICONFLOW_API_URL=https://api.siliconflow.ai/v1 + +# 交换机登录凭证 +SWITCH_USERNAME=admin +SWITCH_PASSWORD=your_switch_password +SWITCH_TIMEOUT=10 + +# 应用设置 +DEBUG=True \ No newline at end of file diff --git a/src/backend/.gitignore b/src/backend/.gitignore index e5effa1..2e78f75 100644 --- a/src/backend/.gitignore +++ b/src/backend/.gitignore @@ -1,7 +1,10 @@ +# Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] *$py.class *.so + +# Python packaging .Python build/ develop-eggs/ @@ -23,6 +26,8 @@ MANIFEST # IDE .idea/ .vscode/ +*.swp +*.swo # Environment .env @@ -34,4 +39,11 @@ env.bak/ venv.bak/ # Logs -*.log \ No newline at end of file +*.log +*.log.* +logs/ + +# Secrets +*.secret +*.key +*.pem \ No newline at end of file diff --git a/src/backend/Dockerfile b/src/backend/Dockerfile index 5fe4682..2da8f24 100644 --- a/src/backend/Dockerfile +++ b/src/backend/Dockerfile @@ -2,14 +2,21 @@ FROM python:3.13-slim WORKDIR /app +# 1. 先复制依赖文件并安装 COPY ./requirements.txt /app/requirements.txt - RUN pip install --no-cache-dir --upgrade -r /app/requirements.txt +# 2. 复制项目代码(排除 .env 和缓存文件) COPY . /app -ENV PYTHONPATH=/app -ENV PORT=8000 -ENV HOST=0.0.0.0 +# 3. 环境变量配置 +ENV PYTHONPATH=/app \ + PORT=8000 \ + HOST=0.0.0.0 -CMD ["uvicorn", "run:app", "--host", "0.0.0.0", "--port", "8000", "--reload"] \ No newline at end of file +# 4. 安全设置 +RUN find /app -name "*.pyc" -delete && \ + find /app -name "__pycache__" -exec rm -rf {} + + +# 5. 启动命令(修正路径) +CMD ["uvicorn", "src.backend.app:app", "--host", "0.0.0.0", "--port", "8000"] \ No newline at end of file diff --git a/src/backend/app/__init__.py b/src/backend/app/__init__.py index ccadf06..3963a5e 100644 --- a/src/backend/app/__init__.py +++ b/src/backend/app/__init__.py @@ -1,8 +1,10 @@ from fastapi import FastAPI -from src.backend.app.api.endpoints import router as api_router +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") def create_app() -> FastAPI: # 设置日志 @@ -18,6 +20,6 @@ def create_app() -> FastAPI: ) # 添加API路由 - app.include_router(api_router, prefix=settings.API_PREFIX) + app.include_router(router, prefix=settings.API_PREFIX) return app \ No newline at end of file diff --git a/src/backend/app/api/__init__.py b/src/backend/app/api/__init__.py index 9b2cbfd..3591b34 100644 --- a/src/backend/app/api/__init__.py +++ b/src/backend/app/api/__init__.py @@ -1,4 +1,7 @@ -from fastapi import APIRouter +from fastapi import APIRouter, FastAPI from .endpoints import router -__all__ = ["router"] \ No newline at end of file +app=FastAPI() +app.include_router(router) + +#__all__ = ["app","router"] \ No newline at end of file diff --git a/src/backend/app/api/endpoints.py b/src/backend/app/api/endpoints.py index 0234d42..8aa16bc 100644 --- a/src/backend/app/api/endpoints.py +++ b/src/backend/app/api/endpoints.py @@ -2,11 +2,35 @@ from fastapi import APIRouter, Depends, HTTPException from typing import Any from pydantic import BaseModel -from src.backend.app.services.ai_services import AIService -from src.backend.app.api.network_config import SwitchConfigurator -from src.backend.config import settings +from ...app.services.ai_services import AIService +from ...app.api.network_config import SwitchConfigurator +from ...config import settings +from ..services.network_scanner import NetworkScanner -router = APIRouter() +router = APIRouter(prefix="/api", tags=["API"]) +scanner = NetworkScanner() + +@router.get("/test") +async def test_endpoint(): + return {"message": "Hello World"} + +@router.get("/scan_network", summary="扫描网络中的交换机") +async def scan_network(subnet: str = "192.168.1.0/24"): + try: + devices = scanner.scan_subnet(subnet) + return { + "success": True, + "devices": devices, + "count": len(devices) + } + except Exception as e: + raise HTTPException(500, f"扫描失败: {str(e)}") + +@router.get("/list_devices", summary="列出已发现的交换机") +async def list_devices(): + return { + "devices": scanner.load_cached_devices() + } class CommandRequest(BaseModel): command: str diff --git a/src/backend/app/services/network_scanner.py b/src/backend/app/services/network_scanner.py new file mode 100644 index 0000000..bf514c5 --- /dev/null +++ b/src/backend/app/services/network_scanner.py @@ -0,0 +1,49 @@ +import nmap +import json +from pathlib import Path +from typing import List, Dict +from ..utils.logger import logger + + +class NetworkScanner: + def __init__(self, cache_path: str = "switch_devices.json"): + self.cache_path = Path(cache_path) + self.nm = nmap.PortScanner() + + def scan_subnet(self, subnet: str = "192.168.1.0/24") -> List[Dict]: + """扫描指定子网的交换机设备""" + logger.info(f"Scanning subnet: {subnet}") + + # 扫描开放22(SSH)或23(Telnet)端口的设备 + self.nm.scan( + hosts=subnet, + arguments="-p 22,23 --open -T4" + ) + + devices = [] + for host in self.nm.all_hosts(): + if self.nm[host].state() == "up": + device = { + "ip": host, + "ports": list(self.nm[host]["tcp"].keys()), + "mac": self.nm[host].get("addresses", {}).get("mac", "unknown") + } + devices.append(device) + logger.debug(f"Found device: {device}") + + self._save_to_cache(devices) + return devices + + def _save_to_cache(self, devices: List[Dict]): + """保存扫描结果到本地文件""" + with open(self.cache_path, "w") as f: + json.dump(devices, f, indent=2) + logger.info(f"Saved {len(devices)} devices to cache") + + def load_cached_devices(self) -> List[Dict]: + """从缓存加载设备列表""" + if not self.cache_path.exists(): + return [] + + with open(self.cache_path) as f: + return json.load(f) \ No newline at end of file diff --git a/src/backend/config.py b/src/backend/config.py index 93590eb..fd68e88 100644 --- a/src/backend/config.py +++ b/src/backend/config.py @@ -1,14 +1,16 @@ +from pydantic_settings import BaseSettings +from dotenv import load_dotenv + +load_dotenv() + import os -from pydantic import BaseSettings - - class Settings(BaseSettings): APP_NAME: str = "AI Network Configurator" DEBUG: bool = True API_PREFIX: str = "/api" # 硅基流动API配置 - SILICONFLOW_API_KEY: str = os.getenv("SILICONFLOW_API_KEY", "") + SILICONFLOW_API_KEY: str = os.getenv("SILICON_API_KEY", "") SILICONFLOW_API_URL: str = os.getenv("SILICONFLOW_API_URL", "https://api.siliconflow.ai/v1") # 交换机配置 diff --git a/src/backend/requirements.txt b/src/backend/requirements.txt index 7f2f48d..7ce79b3 100644 --- a/src/backend/requirements.txt +++ b/src/backend/requirements.txt @@ -4,4 +4,5 @@ python-dotenv==1.0.0 requests==2.28.2 paramiko==3.1.0 pydantic==1.10.7 -loguru==0.7.0 \ No newline at end of file +loguru==0.7.0 +python-nmap==0.7.1 \ No newline at end of file