# netpilot **Repository Path**: stonejoy/netpilot ## Basic Information - **Project Name**: netpilot - **Description**: 从零自研的网络运维自动化平台:AI 巡检、合规检查、告警闭环、拓扑与大屏,H3C/华为/思科开箱即用 - **Primary Language**: Python - **License**: MIT - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 7 - **Created**: 2026-10-06 - **Last Updated**: 2026-10-06 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # NetPilot — AI 驱动的网络运维自动化平台 > 从零自研的多厂商网络运维自动化平台:SSH/SNMP/Telemetry 采集、AI 巡检、合规检查、事件驱动告警闭环、LLDP 拓扑与监控大屏,让 AI 替你敲命令。 ## ✨ 核心特性 - **多厂商适配**:H3C Comware / 华为 VRP / 思科 IOS,一套抽象层自动识别并适配命令体系 - **AI 巡检**:自然语言描述需求 → AI 生成命令 → 确认下发 → 回显解析汇总入报告 - **合规检查**:只读优先的全面"体检",账号 / 权限 / 基线逐项核验,查完不改一台设备 - **变更工单**:改配置走「提交 → 审批 → 执行 → 回滚」流程,执行前体检高危命令、可选自动备份,高风险工单需管理员执行,申请人不能批自己的单 - **告警闭环**:Syslog / SNMP 指标异常 / 服务器主机指标(超阈值与数据过期离线)/ 交换机遥测指标(CPU / 内存 / 温度 / 接口错包增长 / 推送中断)/ 配置变更 / IP 冲突 / 未规划网段 → 企微 / 钉钉 / 飞书 / 邮件推送 → AI 修复或人工处理 - **AI 助手**:一句话问平台里的数据(回答附「本次参考的数据」,人工一眼能核),单条告警一键出根因分析与排查步骤 - **拓扑与大屏**:SNMP 采集 LLDP 自动生成拓扑,**按分组分区绘制**(同组才连线,跨组邻居只提示不连线),每个分组都有设备/链路明细;「拓扑分析」页把采集结果当图做结构体检(孤立设备 / 单向链路 / 未识别邻居 / 跨分组链路 / 环路 / 数据过期)出风险清单,监控大屏分「网络设备(SNMP)」「服务器健康」「交换机遥测健康」三块 + 设备 CPU/内存历史曲线 + 3D 机房(全屏 / 自动巡检 / 设备图标库) - **遥测与终端**:gRPC dial-out / HTTP 遥测接收解析(深层键名提取设备标识、自动关联设备台账、按「设备+传感器」看最新值),推送入库时自动抽成**结构化指标**(CPU / 内存 / 温度 / 接口错包丢包)驱动告警、大屏、趋势图与报表,并在页面上画成图(健康环形图 / 设备指标趋势 / 接口流量与错包增长排行 / 推送节奏,服务端 SVG 零前端依赖,可按时间范围与设备钻取);SNMP 采集终端与接入交换机关系图 - **无线管理**:SSH 登录无线控制器采集 AP 与在线无线终端,用 LLDP 邻居 / MAC 地址表 自动推断「AP ↔ 接入交换机 + 端口」对应关系,可人工绑定(不被后续采集覆盖) - **服务器监控**:服务器也能网页 SSH 登录(通用 shell,不再下发关分屏这类厂商命令); Windows / Linux 原生二进制 Agent(目标机零依赖)或 SSH 只读探测上报 CPU / 内存 / 磁盘 / 负载 / 运行时长 / 硬件信息,按阈值判健康、留历史趋势;也收 **Categraf**(Prometheus remote write) 的上报——采什么由 Categraf 定,平台只挑这几项落库,认不出的指标如实回清单;健康档直接上监控大屏, 超阈值与「数据过期」自动生成告警中心事件并推送 - **应用监控(全链路)**:登记应用(服务类型 / IP:端口 / 有无 nginx / 是否前后端分离 / 关联服务器), 手动绑定交换机端口,把「服务检查 → 服务器指标 → 交换机端口 → 系统告警 → Syslog」串成一条链路, 一键生成检查项、健康档联动告警中心、监控大屏独立一块展示 - **镜像流量分析**:接入旁路 APM(交换机镜像口 → 会话重组 → L7 解析 → 评分)的导出, 应用健康分 / p99 / 错误率 / 重传进全链路第六段与大屏,采集引擎异常(没流量、丢包、 spill 积压、落地不健康)也能告警;appmap 一键导出 - **多地区与 IPAM**:地区层级归属设备与网段,ARP 对账自动生成地址台账、使用率报告、未规划网段与 IP 冲突告警,闲置地址可预览后回收 - **网页终端**:xterm.js + SSE 的交互式 SSH 终端,多会话并行,敲过的命令逐条留痕可下载; - **堡垒机**:参考 JumpServer 的一期——人→账号→资产的授权、回车前的命令过滤(拦截 / 警告 / 人工复核)、会话录像回放与在线强制断开;二期补上 **RDP 图形桌面**(桥接 guacd,口令只在服务器侧、全程录像、与 SSH 同一条审计链); 交换机与服务器都能连,选中服务器时快捷命令面板自动切成 Linux / Windows 两套 - **数据与安全**:设备密码 / AI Key / 告警密钥统一 Fernet 加密存储;syslog、采集、巡检、日志按保留策略自动清理 - **权限与审计**:只读 / 运维 / 管理员三档角色 + 按地区划数据范围,全站写操作一处拦住;数据增删改与高危动作自动留痕,可筛选、导出 CSV - **运维报表**:日报 / 周报一键聚合 15 类数据,先给一份按严重程度排序的风险清单,可下载 Markdown / JSON / CSV 并推送到值班群 - **只读 REST API**:`/api/v1/` 20 个端点(设备 / 拓扑 / 告警 / 巡检 / 合规 / IPAM / 备份 / 任务…)统一 JSON 信封,令牌绑定账号、权限不超过所属用户、明文只显示一次 - **工程化**:环境变量覆盖配置(密钥 / DEBUG / 监听端口)、空库自动建表、管理员自动初始化;网页与后台服务可拆成两个进程部署,67 个测试脚本一键并行跑在独立库上,`check_production` 一条命令做上线体检 ## 🚀 快速开始 ```bash cd netpilot/h3c_web pip install -r requirements.txt python manage.py migrate # 首次部署或升级后执行(「启动网页.cmd」已自动带上) python manage.py runserver # 或双击仓库根目录「启动网页.cmd」 ``` 浏览器打开 ,默认账号 `admin / admin`(登录后请立即修改密码)。 > 双击「启动网页.cmd」启动时会先执行 `python manage.py migrate --noinput` 再起服务, > 因此拉取新版本后直接双击即可,新增的数据表(如设备图标库)会自动建好; > 手动 `runserver` 时请记得先 migrate,否则涉及新表的页面会报 `no such table`。 ### 跑测试(改完代码怎么验证) **验证一律用 `python run_all_tests.py`(在 `h3c_web/` 下),不要裸跑 `python test_xxx.py`。** 测试脚本默认直连开发库 `db.sqlite3`,而开发库同时被运行中的 dev server 与它的定时任务 写入(SNMP 采集、告警生成都会改数据),裸跑会撞出成片「假失败」;`run_all_tests.py` 把整套测试跑在独立测试库(`test_db.sqlite3`)上并关掉后台线程,结果才可信。 ```bash python run_all_tests.py # 全部 67 个脚本,串行 python run_all_tests.py -j 4 # 并行 4 个(每个 worker 各建独立测试库) python run_all_tests.py test_sflow.py # 只跑指定脚本 ``` CI(GitHub Actions)对所有分支的推送与 PR 自动跑同一套:Django 自检 → 迁移一致性 → 部署体检 → 全量测试脚本 → Go Agent 编译与单测。 ### 代码仓库与推送 仓库配了三个远程:`gitee`(Gitee)、`origin`(内网 Gitea)、`all`(一次推两边): ```bash git push all main # 同时推到 Gitee 与内网 Gitea git push gitee main # 只推 Gitee git push origin main # 只推内网 ``` `main` 的上游仍是 `gitee/main`,裸 `git push` 只推 Gitee;`all` 只配了推送地址, 不要用它 `fetch` / `pull`(拉取请指定 `gitee` 或 `origin`)。 `git push all main` 不会刷新 `gitee/main`、`origin/main` 这两个本地跟踪引用, 推完补一句 `git fetch gitee; git fetch origin`(或 `git fetch --all`),否则 `git status` 会误报「ahead 1」。别写成 `git fetch gitee origin`——那里的 `origin` 会被当成远程上的分支名,直接报 `couldn't find remote ref origin`。 换机器后重建 `all`: ```bash git remote add all git remote set-url --add --push all git remote set-url --add --push all <内网 Gitea 地址> ``` ## 📖 使用手册 以下为完整功能手册(CLI 工具 + 网页管理平台)。 > ⚠️ 声明:本项目仅供实验环境学习交流,所有设备操作默认只读优先,请勿在生产环境执行未经确认的变更。 --- ### H3C 交换机 SSH 指令下发工具 基于 paramiko 的纯 Python 脚本,通过 SSH 连接 H3C(Comware V5 / V7)交换机下发指令。 ## 安装 只需安装一个依赖: ```bash pip install paramiko ``` ## 用法 ```bash # 1. 执行单条 / 多条指令(多条用 ; 分隔) python h3c_ssh.py 192.168.1.1 -u admin -p 123456 -c "display version; display ip interface brief" # 2. 从指令文件批量下发(输出自动保存到当前目录 log.txt) python h3c_ssh.py 192.168.1.1 -u admin -p 123456 -f commands_example.txt # 3. 指定日志文件名 python h3c_ssh.py 192.168.1.1 -u admin -p 123456 -f commands_example.txt -o mylog.txt # 3. 交互模式(不指定指令时默认进入) python h3c_ssh.py 192.168.1.1 -u admin -p 123456 -i # 4. 不写 -p 会交互式提示输入密码(推荐,避免明文出现在命令行) python h3c_ssh.py 192.168.1.1 -u admin -c "display current-configuration" ``` 每次运行会自动把会话和指令记录写入 SQLite(默认 `h3c_logs.db`),不想写库加 `--no-db`。 ## 查询历史记录 ```bash # 列出最近 10 次会话 python h3c_log_query.py # 查看某次会话的全部指令与回显 python h3c_log_query.py -s 3 # 按关键字搜指令(每种指令默认只显示最近一次执行) python h3c_log_query.py -c "display ip" # 显示所有匹配记录,并导出到文件 python h3c_log_query.py -c "display" -a -l 50 -o out.txt # 数据库不是默认文件名时指定 python h3c_log_query.py -d other.db ``` 数据库结构:`sessions` 存会话(时间、目标设备、用户名、状态),`commands` 存每条指令(指令内容、回显、耗时、执行时间)。 ## 网页管理界面(Django) 用浏览器管理设备、下发指令、查看日志,无需命令行。 **启动(二选一):** ```bash # 方式一:双击桌面目录下的「启动网页.cmd」 # 方式二:手动启动 cd h3c_web python manage.py runserver 0.0.0.0:8000 # 浏览器打开 http://127.0.0.1:8000 ``` **登录验证:** 所有页面必须先登录才能访问(浏览器打开后会自动跳到登录页)。 默认账号 `admin` / `admin`,登录后建议立即修改: ```bash # 改密码(控制台) python manage.py changepassword admin # 或登录后访问 http://127.0.0.1:8000/admin/ 管理账号/数据 ``` 登录状态与 Django 管理后台共用,登录一次后 `/admin/` 也可直接进入;右上角可退出登录。 登录后默认是**运维**角色(可采集、可改动),右上角显示当前角色徽章;要给同事开只读账号 或限定可见地区,见下方「用户与权限(RBAC)」。 停止:关闭服务器窗口,或双击「停止网页.cmd」。 **导航与页面结构:** 登录后导航为**左侧分组侧栏**(设备管理 / 网络与备份 / 巡检与合规 / 任务与日志 / 可视化 / 机房管理 / 多地区与IPAM / 系统设置),当前页面在侧栏高亮。**巡检中心**(设备巡检 + AI 巡检)与 **日志中心**(指令日志 + 交换机 syslog 日志)是合并后的单入口:进入后页面顶部有统一的二级 「中心」标签条,点击即可在子页之间切换(各自保留独立地址与操作流程)。每个页面内部 再用**页内二级标签**把内容拆开显示(如设备列表 = 分组管理 / 设备列表 / 操作结果, 设备巡检 = 巡检配置 / 巡检报告 / 历史巡检);各类操作结果出现后自动切到对应标签, 标签切换即时生效、无需刷新。 **侧栏的折叠与滚动位置:** 侧栏入口有三十多个,点一次就是整页跳转,所以两处状态都做了记忆: 点分组标题可**折叠/展开**该组(偏好存在 `localStorage`,长期有效;当前页所在分组始终自动展开, 不会出现"收起后找不到自己在哪");侧栏自身的**滚动位置**存在 `sessionStorage`,跳转后停在原地, 不必每次重新往下找靠下的入口(用 `sessionStorage` 而非 `localStorage`:滚动位置属于"这个标签页 看到哪"的临时状态,多开标签页时不该互相串)。守护见 `test_ui_sidebar.py`。 **页面功能:** | 页面 | 地址 | 功能 | | --- | --- | --- | | 设备列表 | `/` | 查看/编辑/删除已录入的设备,型号/序列号/厂商(H3C/华为/Cisco/其他)一列展示,支持「采集信息」「执行命令」;按分组分组显示,顶部可管理分组(创建/删除/筛选);页内「新增设备」主按钮可直接进入录入表单。设备按**大类 → 类型**分层:网络设备(交换机 / 路由器 / 防火墙 / 无线控制器 / 其他网络设备)与服务器(物理服务器 / 虚拟化服务器)两个标签页,另有「机柜其他设备」标签页登记配线架、理线槽、PDU、KVM 等**机柜配件**(无 IP 与账号,可跨多个 U 位上架),页内「配件型号库」让同款属性一处定义、多件配件重复引用上架(见下方「设备分类层级」) | | 新增设备 | `/device/add/`(从设备列表页按钮进入) | 录入交换机/服务器 IP、账号、**认证方式(口令 / 私钥证书登录)**与密码或私钥(都 Fernet 加密后存入 SQLite),可设置角色(网关/接入)、厂商(H3C/华为/Cisco/其他,留空则 SSH/SNMP 采集时自动识别)、SNMP 社区字(留空继承分组)与端口、所属分组 | | 批量编辑 | `/device/batch-edit/`(从设备列表勾选进入) | 对多台设备批量修改账号/端口/密码/角色/厂商/分组/SNMP 社区字;留空或“保持原样”的字段不动,不影响设备的名称/IP/型号等独有配置 | | 指令执行 | `/device//exec/` | 输入指令立即执行,回显直接显示在页面上,可调超时时间 | | 批量执行 | `/batch/` | 勾选多台设备、输入多条指令,多台并行执行并展示结果;可先按分组筛选,每组可整组全选;自动识别回显中的命令级报错(不认识的命令/参数错误/无权限,Comware/VRP/Cisco 各自特征)并计为失败,成功数如实统计。**下发后指令框与勾选原样保留**,页面仍停在「批量执行」标签页(结果在「执行结果」标签页),可改完再下发一次 | | 一键采集设备(身份+LLDP) | `/`(工具栏按钮) | 一次并行采集**身份信息**(名称/型号/序列号,连接时自动识别真实厂商并写回,即“自动矫正”)与 **LLDP 邻居/接口**(自动回填上联口到「连接接口」并在拓扑上呈现),可选 SSH 或 SNMP;**采集范围三选一**:全部设备 / 按分组(只采所选分组,未分组也可选)/ 按勾选(只采列表勾中的设备,可跨分组,服务器自动跳过);范围之外的设备名称、LLDP 记录与「连接接口」一概不动,回填只按**同分组**设备名推导 | | 一键备份 | `/`(勾选设备后点按钮) | 基于列表勾选,可一键对选中设备并行做配置备份 | | 定时任务 | `/schedule/` | 定时任务:按计划自动执行 采集 / 拓扑采集(LLDP) / 备份 / 批量指令 / 设备巡检 / SNMP 监控采集 / 终端信息采集 / 无线采集 / 主机信息采集 / 合规检查 / AI 巡检 / IPAM 对账与告警 / 数据保留清理 / 运维报表,执行范围支持「全部设备」或「指定分组」(类型下拉直接读模型 choices,新增类型自动出现) | | 巡检中心 · 设备巡检 | `/inspect/` | 只读巡检交换机健康:CPU、内存、STP(生成树)状态与端口统计、接口错误包;生成健康报表,支持 CSV 导出与历史回看(见下方「设备巡检」) | | 巡检中心 · AI 巡检 | `/inspect/ai/` | 用自然语言描述巡检内容,AI 生成只读巡检命令,人工确认后一键并行下发采集回显并自动 AI 结构化解析为指标/表格/问题,先汇总后明细展示;长回显完整落库、按行分页浏览并支持「下载完整回显(.txt)」(`/inspect/ai/echo/<结果id>/`),超预算时按行分段送 AI 解析后合并;可保留历史趋势生成折线图(见下方「AI 巡检」) | | 合规检查 | `/inspect/compliance/` | 内置安全策略逐项合规判定(禁止 Telnet / SSH / SNMP / DHCP Snooping / NTP / 日志中心 / 登录锁定 / 密码强度 / 空闲超时 / 接口安全 / 风暴抑制);一次连接采齐配置回显自动判定,每项违规提供可编辑修复指令,可选 AI 按设备实际违规生成,人工核对后可单条或按设备批量下发(见下方「合规检查」) | | SNMP 监控 | `/monitor/` | 基于 SNMP v2c 采集设备身份与性能:厂商自动矫正、名称/序列号/系统版本写回,CPU/内存进入监控历史并展示每设备迷你趋势图;支持一键对全部或指定分组采集,可接入定时任务周期采集(见下方「SNMP 监控」) | | 网络拓扑 | `/topology/` | **按分组分区**的总线布局拓扑图:每个分组一张独立总线图(网关置顶接入本组总线,接入交换机沿本组总线挂接),分组之间绝不连线;顶部分组筛选(`?g=`,`0`=未分组)可只看一个分组,「分组总览」表 + 「分组详情」标签页给出每组的设备/链路/跨分组/未识别明细;跨分组链路与跨分组重名单独提醒;页内「收集拓扑信息」按钮可**选择 SSH 或 SNMP 采集** LLDP 邻居/接口,只采当前筛选的分组 | | 全链路总览 | `/fulllink/` | **业务链路 × 服务器与网络设备**画在一张图上:应用(web/api/file → 中间件 → 数据库,含人工声明的调用/消息/数据访问依赖边)→ 服务器 → 核心/接入交换机,全部来自库里事实(关联服务器 / 端口绑定 / LLDP / 终端表接入位置);节点与连线按 正常/警告/故障/离线/未采集 五态着色,点节点出详情面板(状态依据/关键指标/最近告警/下钻),滚轮缩放拖拽平移,每 60 秒自动刷新,支持分组筛选(见下方「全链路监控拓扑总览」) | | 堡垒机 | `/bastion/` | **参考 JumpServer 的一期**:资产账号(一机多账号,口令 Fernet 加密只写不读,Windows 域可填)× 授权规则(用户×资产/组×账号×生效时段×来源 IP,enforce 灰度开关)× 命令过滤(**回车前**判定:拦截/警告放行/人工复核,试运行解释器)× 会话审计(SSH+RDP 双协议在线表、管理员强制断开、历史台账含授权拒绝与连接失败、asciicast 录像回放+命令时间线跳转);**RDP 图形桌面**桥接 guacd:服务器侧握手(口令不进浏览器)、SSE/POST 透传、guacd 指令流录像取回回放、命令过滤不适用如实标注(见 docs/12-堡垒机/02) | | 拓扑分析 | `/topology/analysis/` | 把上一次 LLDP 采集结果当成一张图做**结构体检**(支持按分组筛选 `?g=`):设备数/链路数/连通分量/环、孤立设备、汇聚点与度数排行、单向链路、未识别邻居、跨分组链路、设备名重复、角色未设置、离线网关、LLDP 数据过期,按高→低给一份可照做的风险清单,可导出 JSON / CSV / Markdown(见下方「拓扑分析」) | | 终端信息 | `/terminals/` | **SNMP 采集**与 **SSH 采集**两份独立数据(同一 MAC 各一行、互不覆盖,页面可切换对照、提示定位不一致):SNMP 读**网关 ARP 表**(IP↔MAC)+ **交换机 MAC 地址表**(MAC↔端口/VLAN),SSH 登录读 `display/show arp` 与 `mac-address` 回显解析;自动剔除上联口/聚合口去重定位接入端口,支持筛选、CSV 按数据集导出与定时采集(见下方「终端信息」) | | 无线管理 | `/wireless/` | 无线控制器(AC)→ AP → 无线终端三层台账:SSH 采集 AP 与在线终端(H3C / 华为 / 思科命令各自适配),四个标签页分别看 AP、无线终端、「AP ↔ 接入交换机」对应关系与采集登记;支持关键字 / 在线 / 按 AC 筛选、CSV 导入导出、人工登记与绑定接入交换机、清理超期离线终端、重新推断对应关系,可接入定时任务(见下方「无线管理」) | | 遥测数据 | `/telemetry/` | 接收交换机 **telemetry 遥测推送**:gRPC dial-out 采集口(任意服务/方法名,JSON/GPB 编码均解析)+ HTTP JSON 推送 API,自动识别设备标识并关联设备(关联不上可一键「重新匹配设备」),推送入库时自动抽成**结构化指标**(「结构化指标与图形化分析」区块给健康环形图、每台设备健康档与最新值、CPU / 内存 / 温度趋势、接口流量与错包增长排行、推送节奏与数据构成,可按**时间范围**切换、按**设备**钻取,老数据可「补抽指标」,真机还没接上可一键「生成演示数据」预览),支持筛选 / 按「设备+传感器」看最新值 / CSV 导出 / 清理 / 测试数据(见下方「交换机遥测数据」) | | 服务器监控 | `/hosts/` | 物理机 / 虚拟化服务器的健康总览:CPU / 内存 / 磁盘进度条 + 健康档(正常 / 警告 / 严重 / 离线 / 未采集)+ 统计卡,支持关键字 / 健康 / 操作系统筛选;可勾选主机「SSH 一键采集」(只读探测),签发 / 停用 / 吊销 Agent 令牌,页面直接给出 Linux 与 Windows 的安装命令与接口自测命令(见下方「服务器监控与主机 Agent」) | | 主机详情 | `/hosts//` | 单台服务器:最新指标与健康判定依据、CPU / 内存 / 磁盘 / 负载趋势图(可选最近 30~288 个点)、硬件与系统信息(DMI / CIM)、历史明细表、「系统指标」页签(网卡 / 磁盘 / TCP / 进程 / **MySQL 数据库**——对配了 MySQL 登录检查的目标采集 QPS、连接数、慢查询、缓冲池命中率等,Categraf 同口径)、Agent 令牌与安装命令、网页 SSH 登录入口、清空历史 | | 防火墙运维 | `/firewall/` | 华三 SecPath 系列防火墙的**安全策略只读总览**:台数与健康分布(正常 / 数据过期 / 采集失败 / 未采集)、规则与安全域总数,每台给出型号、软件版本、规则数、安全域数、最近采集时间与耗时;可勾选或全选后一键采集(走设备 HTTPS REST API,**只读,不下发配置**);支持**策略调序**(上移/下移)与**对象组编辑**(成员增删改 / 描述)(见下方「防火墙安全策略」)(上移/下移)与**对象组编辑**(成员增删改 / 描述) | 防火墙策略详情 | `/firewall//` | 单台防火墙:设备身份与本次采集(主机名 / 型号 / 版本 / 运行时长 / 桥 MAC / 耗时)、**安全域**(成员接口与 down 提示)、**安全策略规则表**(顺序即设备匹配顺序:动作、启用与有效期、源域→目的域、源/目的地址、服务与应用、命中次数与流量、最近命中时间、描述,可展开看全部匹配维度)、采集历史与失败原因 | | 防火墙编辑 | `/firewall//edit/` | 安全策略规则与对象组的编辑(新增/启停/删除/**调序**规则、新建/删除/改描述组、成员增删**改**):对着采集快照校验 + 载荷与回滚预览,**改动一律生成变更工单**(提交 → 另一位管理员批准 → 执行 → 可回滚),页面不直接下发设备;执行与回滚成功后都会 `save force` 落盘(见下方「防火墙安全策略」) | | Agent 上报 | `/agent/push/` | 主机 Agent 的免登录上报接口:POST JSON,凭请求头 `X-Agent-Token` 认主机,支持数组批量补传,响应回健康判定与阈值;令牌停用 / 过期 / 不存在一律 403(见下方「服务器监控与主机 Agent」) | | 应用管理 | `/apps/` | 业务视角的应用台账与**全链路健康**:应用名 / 服务类型 / IP:端口 / 有无 nginx / 是否前后端分离 / 关联服务器 / 手动绑定的交换机端口;列表按健康档排序并可筛选,详情页把「服务检查 → 服务器指标 → 交换机端口 → 系统告警 → Syslog」五段并排展示,可一键生成检查项(按「监控方式」配 HTTP/HTTPS/TCP/MySQL 探活与探活路径,HTTPS 顺带采集证书剩余天数)、增删端口绑定与依赖声明(见下方「应用管理」) | | 检查清单下发 | `/agent/checks/` | 进程 / 端口 / HTTP 检查清单的免登录接口:GET + 请求头 `X-Agent-Token`,Agent 每 5 分钟拉一次,清单在主机详情页「进程与服务」维护(见下方「服务器监控与主机 Agent」) | | 监控大屏 | `/bigscreen/` | 分五块展示:**网络设备**(总数/在线/离线/网关/接入/未设置角色 + Ping 在线状态 + SNMP CPU/内存与历史曲线)与**服务器健康**(健康分档统计、CPU/内存/磁盘进度条、来源与采集时间、每台走势与服务器平均曲线)、**交换机遥测健康**(健康分档统计、平均 CPU / 内存、最高温度、最需要关注排行)、**应用监控**(应用全链路五段并排 + 分档统计)与**镜像流量(APM)**(引擎状态 + 应用分数排行 + 定界结论),每 60 秒自动刷新,可「立即刷新检测」(Ping + SNMP + 主机体检 + 遥测体检 + 应用体检)(见下方「监控大屏」) | | 大屏设置 | `/bigscreen/settings/` | 统一配置五项监测(Ping / SNMP / 主机体检 / 遥测体检 / 应用体检)的开/关与间隔(分钟)+ **镜像流量接入**(APM 指标地址、控制台地址、采集间隔、是否拉定界结论),展示上次执行时间与采集错误;可「立即执行一次监测(Ping + SNMP + 主机体检 + 遥测体检 + 应用体检 + 镜像流量)」(见下方「监控大屏」) | | 运维驾驶舱 | `/dashboards/` | **多看板 + 组件化**的深色值班看板:四张内置看板(总览驾驶舱 / 网络运行 / 服务器与应用 / 安全与合规)开箱即用,每张看板由 31 个组件自由拼装(设备·告警·任务·服务器·应用·APM·遥测·合规·漏洞·IPAM·备份·终端·无线的指标卡,折线/柱状/环形图,最新告警·最近任务·最近操作·最新日志·离线设备·最近巡检明细),支持增删/调序/调宽度/改标题/配参数(时间窗·条数·分组·指标),按看板设自动刷新秒数、全屏值班、`F` 快捷键;只读展示不采集数据,登录可看、operator 及以上可编辑(见下方「运维驾驶舱」) | | 看板设置 | `/dashboards/settings/` | 看板增删改名、排序、设默认、刷新秒数;当前看板的组件增删/上下移/宽度/标题/参数;看板删光后可一键恢复四张内置看板(见下方「运维驾驶舱」) | | 日志中心 · 指令日志 | `/logs/` | 指令执行历史(含状态/耗时)+ 完整文本日志 `log.txt` 内容 | | 日志中心 · 交换机 syslog 日志 | `/syslog/` | 接收交换机上送的 syslog 告警(UDP 监听),结构化解析后分页展示,支持按设备/级别/关键字/时间筛选与 AI 分析(见下方「交换机 syslog 日志」) | | 告警中心 | `/alerts/` | 平台各处检出的异常汇成一条时间线:按来源 / 级别 / 状态 / 天数 / 关键字筛选,统计卡给出 今日·未处理·推送失败·启用规则数;单条可确认、重试推送、删除,也可清理只保留最近 100 条(见下方「告警中心」);每行「AI 根因」进入 `/alerts//ai/`,先看排障上下文再出根因与排查步骤(见下方「AI 助手」) | | 安全事件 | `/security/` | **安全联动监测**:sFlow 流量特征(触达目的数、SYN/ACK、包长、外联首见、心跳规律)× 交换机 syslog 信号(登录失败/端口安全/ARP 冲突/风暴抑制)按源 IP 联动判定,六条规则(横向移动/端口扫描/暴力破解/ARP 欺骗/新增·心跳外联/流量洪水)产出**带证据链**的安全事件(流样本+日志行+终端台账接入位置);同源同类合并不刷屏,新建/升级按 source=安全联动监测 的告警规则推送;内网范围取自 IPAM,白名单(IP/CIDR)豁免;详情页确认/忽略,处置走命令模板+变更工单(见下方「安全联动监测」) | | 监测设置 | `/security/settings/` | 安全联动监测的开关与节奏(检测间隔/流量滑窗)、六条规则阈值、白名单(IP/CIDR)增删、手动「立即检测一轮」(见下方「安全联动监测」) | | 安全基线 | `/baseline/` | **主机安全基线检查**:内置 16 条基线规则(Linux 10 条 + Windows 6 条:SSH 配置 / 口令策略 / 文件权限 / 内核参数 / UAC / RDP NLA / SMBv1 / 防火墙服务…),可人工编写或 **AI 生成草案**(回填表单人工确认后入库);规则随检查清单下发,Agent v1.9.0 起只做**声明式只读检查**(读文件 / /proc/sys / 注册表 / 服务状态,永不执行平台下发的命令),结果随上报对账为 通过 / 违规 / 无法检查 三态;按主机聚合的违规数告警(来源 `baseline`,指标 `baseline_fail` / `baseline_high`)(见下方「主机安全基线检查」) | | 平台自检 | `/selfcheck/` | 平台自己把 **27 个关键页面 GET 一遍**(只读,不改任何数据):每条断言 HTTP 状态 + 必须出现的区块文本 + 绝不该出现的错误文本(`Traceback`/未渲染的模板标签),超时判警告不判失败;可点「立即自检」或挂成**定时任务**(类型「页面冒烟自检」,批量指令栏填路径可只查指定页),失败按 `source=平台自检` 的告警规则**一轮聚合成一条**推送(见下方「平台自检」) | | 告警规则 | `/alerts/rules/` | 按来源配置判定口径(syslog 级别上限与关键字 / SNMP、主机与遥测指标阈值 / 主机「数据过期」与遥测「推送中断」分钟数 / 接口错包增长条数)、去重间隔与绑定通道,可启用停用、编辑、测试推送 | | 推送通道 | `/alerts/channels/` | 企业微信 / 钉钉 / 飞书机器人 webhook(钉钉、飞书支持加签密钥)与 SMTP 邮件;密钥加密存储、编辑留空即不改,支持测试推送 | | AI 配置 | `/ai/config/` | 保存/切换多家大模型调用配置(DeepSeek、GLM、MiniMax、MiMo、Ollama、自定义),全局唯一“当前”配置,可测试连接;API Key 加密存储 | | AI 助手 | `/assistant/` | 用自然语言问平台里的数据(离线设备、告警集中在哪、IPAM 有没有冲突…),回答只依据库内快照并附「本次参考的数据」,页面给 6 个快捷问题(见下方「AI 助手」) | | 操作审计 | `/audit/` | 平台数据的增删改与高危动作留痕(谁 / 从哪个 IP / 对什么 / 改了什么),按动作·类型·关键字·时间筛选,分页与 CSV 导出,管理员可清理(保留最近 500 条)(见下方「操作审计」) | | 用户与权限 | `/users/` | **仅管理员**:建号、改角色(只读 / 运维 / 管理员)、按地区划数据范围、停用启用、重置密码、删除;带「不能动自己」与「最后一个管理员」保护(见下方「用户与权限(RBAC)」) | | 账号安全 | `/account/mfa/` | **给账号加第二道门(可选)**:顶栏「🔐 账号安全」自助开/关双因子(TOTP):扫码 → 填一个动态码确认才生效 → 一次性给出 10 条备用码;关闭/重置备用码要「当前口令 + 一个验证码」双证。管理员在「用户与权限」页可按账号**重置**(手机丢了时的唯一出口)(见下方「账号双因子(TOTP)」) | | 机房管理 | `/dc/` | 楼栋 → 楼层 → 机房 → 机柜四层位置体系,各层级列表、新增与删除(删上级级联清空下级;删机柜自动解除设备绑定)(见下方「机房管理」) | | 机柜表单 | `/dc/form//`、`/dc/form///` | 新增/编辑楼栋、楼层、机房(含布局行列数)、机柜(型号/U 数)的共用表单页,同名重复会被拒绝 | | 机房详情 | `/dc/room//` | 机柜列表与每柜的 U 位视图(CSS 网格按 U 数展示绑定设备**与机柜配件**,配件按占用 U 数跨格)、设备↔机柜绑定/解绑(校验 U 位 1≤u≤U 数且同柜同 U 不重复)、未绑定设备下拉分配 U 位、只读列出本机房已上架的配件 | | 机柜屏幕布局 | `/dc/room//layout/` | 把机柜摆放到机房的 rows×cols 网格:点击侧栏机柜→空格放置、拖拽换位、转向(0°/90°)、移除,保存时校验越界与同格冲突;网格外圈是**走廊**,UPS / 精密空调 / 配电柜 / 机房大门 / 玻璃门等**基础设施**也在同一页摆放(可旋转 0°/90°/180°/270°、删除、一键生成默认布局),3D 机房按这份数据渲染(见下方「机房管理」) | | 3D 机房 | `/dc/room//3d/` | 按布局用 Three.js 渲染整间机房:机柜 + UPS / 精密空调 / 配电柜 / 墙体 / 玻璃门 / 大门等基础设施;健康状态与「监控大屏」同口径着色(正常 / 偏高 / 严重 / 离线 / 无数据 / 空柜),机柜里的**服务器**改按主机体检口径(CPU / 内存 / 磁盘 + 数据新鲜度),SNMP 与主机指标都没有的网络设备回落到**遥测指标**着色;支持全屏、自动巡检轮播、顶部健康滚动条、点击机柜看全部 U 位详情与设备图标,每 60 秒自动刷新(见下方「机房管理」) | | 3D 机房数据 | `/dc/room//3d/data/` | 3D 页轮询的 JSON 接口:机柜坐标 / 设备与 U 位 / 健康档 / CPU 内存(服务器另带磁盘、主机标记与指标来源时间)/ 图标地址 / 汇总计数(含服务器台数),与页面首次渲染同源 | | 设备图标库 | `/dc/icons/` | 上传/删除自己的设备图标(png / jpg / jpeg / gif / svg / webp,单个 ≤2MB,名称唯一),统计被引用设备数;文件不裸奔在 `/media/`,由登录态视图 `/dc/icons//file/` 输出(见下方「机房管理」) | **设计要点:** - 设备表放在 Django 自带的 SQLite(`h3c_web/db.sqlite3`),密码用项目 `SECRET_KEY` 签名加密存储,数据库里看不到明文。 - syslog 接收服务随 `runserver` 一起自动启动,监听 UDP 端口收交换机日志(默认 `514`,可用环境变量 `H3C_SYSLOG_PORT` 修改,Windows 无管理员权限绑定 514 会失败、 可改用 `1514` 等高端口;`H3C_SYSLOG_DISABLED=1` 可禁用以调试)。识别不了的报文 也整条落入 `raw` 字段,不丢告警。 - AI 的 API Key 保存在 `AIProvider` 表,用 `SECRET_KEY` 派生的密钥 XOR 加密后以 `enc:` 前缀入库(与设备密码同一安全级别:数据库里不是明文,但强度取决于 `SECRET_KEY`,不属于互联网级加密)。 - 执行历史记录(`CommandLog`)只存指令、状态、耗时、错误信息,**不保存回显**, 符合“SQLite 不存回显”的要求;完整回显仅通过网页即时展示并追加写入 `log.txt`。 - 页面复用命令行的核心模块 `h3c_console.py`,登录自动关闭分屏、自动翻页、自动应答 等能力与命令行完全一致。 - 命令行的日志继续写入 `h3c_logs.db`;网页执行时也会把回显追加到页面显示的 `log.txt`(与命令行共用同一份日志文件)。 - 网页执行失败(如设备不可达、超时)不会报 500,会正常渲染并显示错误信息, 同时在历史里记录为 `error`/`timeout`。 - 同一 IP 的设备只能录一条;编辑时密码留空表示不修改。 **设备角色与分组:** - **角色(角色列)**:每台设备可设置「网关交换机」或「接入交换机」,用于网络拓扑 的自动摆放。角色未设置的设备不会出现在拓扑图中,会在拓扑页下方单独列出提示。 - **分组(按大类分开管)**:把设备按机房/楼层/业务等归类。分组分 **网络设备分组**与**服务器分组**两类,一个分组只装同一大类的设备:设备表单的分组 下拉跟着大类联动,跨大类保存会被拒并说清原因;分组管理页也是左右两栏分开列。 分组在设备列表页顶部的「分组管理」中创建和删除(删除分组不影响其中设备, 自动回到“未分组”);**网络设备分组可填 SNMP 社区字,随时可改**(分组胶囊里的 编辑框),服务器分组不用社区字(指标走 SSH 只读探测与 Agent 上报)。胶囊上的 ⇄ 可切换 分组类型,但组里还挂着另一大类的设备时要先把它们挪走;历史混装分组会在胶囊上 如实标出「混入 N 台…」。升级时旧分组自动归类:组内全是服务器的归为服务器分组, 其余(含空组)保持网络设备分组,旧行为不变。新增设备、网段扫描导入、CSV 导入时 都可选择分组。设备列表、批量执行页都按分组分组显示:每组一个表头行(分组名 + 设备数),顶部下拉可按分组筛选(只列当前大类的分组),每组表头带「全选本组」。 - **服务器行只留两个入口**:设备列表里的服务器(物理/虚拟化)不再出现「采集信息 / 执行命令 / 备份 / LLDP 采集」——那是交换机那套流程,对服务器没意义;只保留 **SSH 终端**(打开网页 SSH 终端并自动选中这台)与**服务器监控**(跳到 `/hosts//` 看趋势、硬件与 Agent 令牌),加上通用的编辑/删除。选到「服务器」大类时顶部也不再显示 一键采集与一键备份表单。一键采集、一键 LLDP、一键备份、巡检、AI 巡检、合规检查、 批量执行、变更工单、终端信息采集以及对应的定时任务都会自动跳过服务器(备份会 如实提示跳过了哪几台);直接访问这些单台入口会被拦下并跳到该去的地方。 - **批量编辑**:在设备列表勾选多台设备后点「批量编辑已选设备」,进入批量编辑页, 可只修改**共享字段**——账号、SSH 端口、密码、SNMP 社区字、角色、分组。账号/端口/密码/ SNMP 社区字留空、角色/分组选“保持原样”的设备不修改;设备的名称、IP、型号、序列号、 连接接口等每台设备独有信息一律不动,避免影响各自的其他配置。接口信息以“新增/编辑设备”的 单个录入为准,批量编辑不会触碰。 - **拓扑按分组隔离(硬边界)**:拓扑图**一个分组一张**——网关/接入只在**本分组内** 按 LLDP 认对端连线,别的分组的设备既不会被画进来,也不会被连到本组的总线上; 未分组设备单独成一张图。页面顶部可按分组筛选(`?g=<分组主键>`,`?g=0` 只看未分组), 「分组总览」表逐组给出设备数、网关/接入/未设角色台数、组内链路数、跨分组与未识别 邻居数、已采集 LLDP 台数与最后采集时间;「分组详情」标签页给出每组的设备明细 (角色 / 厂商 / 型号 / 在线 / 连接接口 / 邻居构成「组内/跨组/未识别」/ 最后采集)、 组内链路表、跨分组邻居表与未识别邻居表。**跨分组链路**(对端设备在别的分组)与 **设备名跨分组重复**会在页面顶部单独提醒:前者说明分组划分可能要调整,后者会导致 按名字认对端时误连或漏连。底层数据同样分开:LLDP 邻居记录挂在各自设备下, 拓扑页「收集拓扑信息」、设备列表页「一键采集设备(身份+LLDP)」与定时任务 「拓扑采集(LLDP)」三个采集入口都只作用于**当前分组/任务范围**内的设备, 且「连接接口」回写**只用同一分组内的设备名**推导上联口——跨组同名设备不参与, 不会把 A 组设备的连接接口写成连向 B 组设备的口。 同一套匹配规则(`device_console/topology_groups.py`)被拓扑页、只读 API、拓扑分析、 设备详情与 AI 上下文共用,不会出现「页面一张图、接口另一张图」。 - **网络拓扑(/topology/,总线布局)**:服务端按角色为**每个分组**自动生成 SVG 拓扑图—— **网关交换机排在最上方**,各自垂直连到一条**水平总线**;**接入交换机沿总线下方 垂直挂接**。总线标注所属分组名,盒子内显示设备名/IP/型号/分组名,网关蓝色、接入 绿色,宽度随设备数量 自适应(页面可横向滚动)。**鼠标悬停任意连接线**会浮出提示框,显示该线两端的设备 名称与接口(未采集 LLDP 时接口取“新增/编辑设备”的「连接接口」,如 `GE1/0/2`; 都没有时提示“接口未设置”)。接入线缆的总线侧会显示其**真实上联的网关**及对应接口 (如 `hexin(192.168.56.11)接口 GE1/0/2`,从网关自身的 LLDP 记录反查),网关线缆 的总线侧则列出其下挂的同组接入设备;解析不到已知对端时才回退为“总线/上联 N 台 网关”。悬停总线本身显示其连接了多少台网关/接入。页内 「收集拓扑信息」按钮对**当前筛选范围**(全部分组或所选分组)执行一次 LLDP 采集, 完成后自动刷新拓扑与接口。 按钮旁可**选择采集方式**(默认 SSH): - **SSH 采集**:登录设备解析 LLDP 回显(`display lldp neighbor-information list`, 思科为 `show lldp neighbors detail`),含对端管理地址; - **SNMP 采集**:走标准 **LLDP-MIB(`1.0.8802.1.1.2`,IEEE 802.1AB)** 只读 GET/WALK 远端邻居表(`lldpRemTable`)与本地端口表(`lldpLocPortTable`), 社区字复用「设备 > 分组 > public」解析与各设备的 SNMP 端口(默认 161), 无需 SSH 凭据即可采集;对端名从 `lldpRemSysName` 取、为空回退 `lldpRemChassisId`(MAC 等二进制按十六进制展示),本地接口从 `lldpLocPortId` 映射。SNMP 采集**不提供对端管理地址**(`neighbor_ip` 留空), 拓扑连线只需本地接口与对端名,需管理地址请用 SSH 采集。 - **LLDP 邻居采集(自动回填接口)**:设备列表页有「LLDP采集」单台按钮(走 SSH), 工具栏的「一键采集设备(身份+LLDP)」可按**三种范围**采集邻居与接口 (SSH 或 SNMP 二选一):**全部设备**(当前数据范围内的所有网络设备)、 **按分组**(只采所选分组,`未分组` 也可选;别的分组的名称/型号/序列号、 LLDP 记录与「连接接口」一概不动)、**按勾选**(只采列表里勾中的那几台, 可跨分组勾选,服务器会被自动跳过并提示)。选「按分组」时下拉只列网络设备分组。 拓扑页的「收集拓扑信息」同样可选 SSH 或 SNMP 两种方式, 如上节所述 (SSH 兼容列表表格与 `Port name:` 块两种回显格式;SNMP 兼容上述标准 MIB): 解析邻居关系后写入数据库,每条记录带「采集方式」(`source`:`ssh`/`snmp`, SNMP 采集会整体替换该设备上一次采集(含 SSH)写入的邻居行):设备列表新增 「接口」与「LLDP 邻居」两列展示采集结果;其中**对端是库中已登记设备**的本地 接口会自动写入该设备的「连接接口」(只在**同一分组**内认对端,优先选对端为网关的 那个,作为上联口), 网络拓扑悬停提示随之显示真实接口(多口情况如 `接口 GE1/0/2、GE1/0/3` 顿号连列)。 手填的「连接接口」不会被自动覆盖;设备未启用 LLDP 时解析为空,悬停将回退到 手填值或“接口未设置”。 - **拓扑分析入口**:拓扑页顶部标签条上有「🔍 拓扑分析」,进入 `/topology/analysis/` 对同一批 LLDP 数据做结构体检(见下方「拓扑分析」)。 **多厂商支持(H3C / 华为 / 思科):** - **厂商字段**:每台设备可设置厂商(H3C/华为/Cisco/其他,未设置为空)。厂商决定 SSH 命令集与解析方式:**华为 VRP 与 H3C 命令天然兼容**(沿用全部 `display` 系列); **思科 IOS 全量适配**(`show` 系列命令 + `#` 提示符 + 登录 `terminal length 0` 关分屏 + 惯用回显解析)。三家的采集/巡检/合规/备份/LLDP/批量执行/AI 生成都按厂商 选命令,互不干扰。 - **自动识别与矫正**:连接设备时会先探测一次真实厂商(先 `display version`,认不出 再 `show version`),**识别成功即覆写数据库里的厂商值**——录错厂商也会被自动纠正, 列表里会提示「厂商 旧→新」。对应地,新增/编辑页、批量编辑页的厂商都提供 「保持原样」语义;解析不出个别指标时如实标「未解析/无法检查」,不会误报。 - **导入区分厂商**: - **网段扫描**:保存扫描结果时可选「自动识别厂商」——入库时对每台设备 SSH 逐台探测后写回(较慢),识别失败回退表单里手动选的厂商;不勾选则统一用 表单选的厂商(或留空)。 - **CSV 导入**:CSV 末尾新增可选 `vendor` 列(老文件不带该列依旧兼容), 支持中文别名(H3C/华三、华为、思科/Cisco → 统一归一);导出时厂商列导出中文。 - **合规检查同样适配思科**:判定命令换为 `show` 系列等价命令(`show running-config` + `include`、`show ntp status`、`show spanning-tree` 等),判定规则为思科惯用配置 的独立实现,拿不准的项标「无法检查」;修复指令预填思科写法。H3C/华为设备完全 走原有 H3C 逻辑,零改动。 - **AI 生成/解析带厂商上下文**:对思科设备,AI 生成的巡检/修复命令会被提示用 `show` 系列、不要用 `display/screen-length`;对华为设备提示用 `display` 系列。 **调试用的管理员后台:** 用 `python manage.py createsuperuser` 创建账号后, 登录 `http://127.0.0.1:8000/admin/` 可查看/维护设备与指令历史。 ## 命令模板(配置模板库) 「命令模板」页(`/templates/`)把「初始化配置、接口 VLAN、接口安全策略、RADIUS、ACL」 这类成型的配置做成**带占位符的模板**,选一批设备、逐台填参数,一次生成每台设备各自的 配置命令,导出 TXT / ZIP,或(各台一致时)带入「批量执行」/生成「变更工单」草稿。 - **占位符语法**:`{key}`(主)与 `$key`(兼容外侧 MCP 的 `*.init.tmpl`),`{{`/`}}` 转义; `#!` 开头是模板说明行(渲染、导出、下发都不输出);`#` 开头是普通注释(保留)。 **内置设备变量**免填、按设备自动代入:`device_name` `device_ip` `device_group` `device_vendor` `device_model` `device_serial` `ip_last` `ip_prefix` `today` (后两个按 /24 取)。 - **参数定义**每行一个 `名称=默认值 # 说明`;默认值可再写占位符、按设备逐台展开, 例如 `hostname=SW-{ip_last}` → 三台自动带出 `SW-11/12/13`;没写默认值的算必填。 - **内置模板五条(H3C/Comware,只读,可一键复制后改)**:交换机初始化(命名 + 管理 VLAN/IP + 默认路由 + SSH(关 Telnet)+ SNMP + NTP + 日志中心)、接入端口 VLAN、接入端口安全加固 (边缘端口 + BPDU 保护 + 端口隔离 + 风暴抑制 + 端口安全)、RADIUS 认证、ACL 策略。 模板只写配置类命令,不含 `save` / `write memory`。 - **批量生成**:生成页先按 **IP 关键字 / 厂商 / 分组**筛选设备(可叠加、可一键清除,筛选只影响候选列表),再 行 = 设备、列 = 参数,默认值已按设备展开,逐格改;某列各台相同时用 表头输入框一次覆盖全列;结果区每台一段命令,可导出 **TXT**(合并,每台带 `# 设备名 (IP)` 注释)或 **ZIP**(每台一个 `.cfg`)。还有没填的参数时结果里保留占位符、 标出缺哪些键,并**拦住导出与下发**。 - **与下发路径的衔接**:各台命令**完全一致**时才提供「带入批量执行」(跳批量执行页, 命令与勾选设备已预填,仍需人工确认后执行)与「转变更工单草稿」(按平台审批流程走); 各台不同(含 `{device_name}` 这类设备变量)只能导出——批量执行与工单都是"同一批命令 发给所有设备"的模型。 - **AI 生成模板**:描述需求(可选参考设备带出机型/厂商)→ AI 返回带占位符的草稿 → 回填编辑器人工核对 → 保存后来源标记「AI」。只生成文本、不自动下发; 未配置模型时按钮灰掉并提示先去「AI 配置」。 - **权限与留痕**:查看/生成/导出登录即可(数据范围同全站);新建/编辑/复制/删除/AI 生成 需要运维及以上;模板增删改走操作审计(`command_template`),导出与带入下发另记语义审计。 实现落点:模型 `CommandTemplate`(迁移 0079 + 0080 预置内置模板)、占位符引擎 `device_console/command_templates.py`(解析、内置设备变量、动态默认值、未解析检查、 TXT/ZIP 导出)、页面 `templates/device_console/command_templates.html` 与 `command_template_generate.html`、守护测试 `test_command_template.py`。 ## 配置备份与对比 对设备执行只读配置导出命令(H3C/华为 `display current-configuration`,思科设备 自动改用 `show running-config`),把完整配置保存为备份文件, 备份文件名自带交换机 IP 与时间戳,并支持任意两份备份的逐行对比(difflib)。 **配置漂移告警:** 每次备份成功后自动与**上一份**备份逐行比对(`config_drift`), 有增删就写一条告警(来源「配置变更」)并沿启用的通道推送,正文含新增/删除行数、 两份文件名与最多 30 行差异摘要;同一设备 `CONFIG_ALERT_HOURS`(默认 12 小时)内只告一次, 窗口过了仍有差异会再告一次(正好提醒“变更还没处理”)。首轮备份没有可比对象,不告警。 定时备份任务的结果摘要里也会带上「配置有变更 N 台」,网页「一键备份」的结果里同样带 `drift` 字段;比对失败一律静默,绝不影响备份本身。 **备份文件命名与目录:** ``` backups/backup_<交换机IP>__.cfg 例如: backups/backup_192.168.56.11_20260901_203650.cfg ``` **命令行:** ```bash # 备份设备配置(自动存为 backups/backup__<时间戳>.cfg) python h3c_backup.py backup 192.168.56.11 -u admin -p 12345678 # 列出所有备份(按时间倒序) python h3c_backup.py list # 只看某个 IP 的备份 python h3c_backup.py list --ip 192.168.56.11 # 查看某份备份内容 python h3c_backup.py show backup_192.168.56.11_20260901_203650.cfg # 对比两份备份 python h3c_backup.py diff backup_旧.cfg backup_新.cfg # 对比某个 IP 最近的两份备份(日常巡检最常用) python h3c_backup.py diff 192.168.56.11 # 自定义备份目录 python h3c_backup.py backup 192.168.56.11 -u admin -p 12345678 --dir D:\configs ``` 对比输出中 `-` 开头为删除行、`+` 开头为新增行、`@@` 为差异块,绿色/红色高亮可用 `--color` 开启(需现代终端支持 ANSI)。 **网页(推荐):** | 页面 | 地址 | 功能 | | --- | --- | --- | | 配置备份 | `/backups/` | 设备列表式界面:**备份范围可选「全部 / 按分组 / 按勾选」**,交换机一张表格展示,行内列出该机的**配置文件历史**(查看/下载/与上一版对比) | | 命令模板 | `/templates/` | **配置模板库**:内置 5 条 H3C 模板(初始化 / 接口 VLAN / 接口安全策略 / RADIUS / ACL),也可自建或让 **AI 按需求生成**;模板正文用占位符(`{vlan}` 与 `$community` 两种语法都认,`#!` 开头是说明行不下发),内置设备变量(设备名/IP/分组/厂商/型号/序列号/IP 末段与前三段/日期)按所选设备自动代入,参数默认值可写 `SW-{ip_last}` 这类动态表达式;**生成页**按设备逐台填参数(表头一键批量填充),导出 TXT(合并)或 ZIP(每台一个 .cfg);各台命令一致时可直接**带入批量执行**或**转变更工单草稿**,缺参数会拦住导出(见下方「命令模板」) | | 配置对比 | `/backups/diff/` | 任选两份备份逐行对比,绿=新增 红=删除 彩色显示 | 备份页顶部工具栏提供三选一的**备份范围**(与「一键采集」同一套交互): - **全部**:当前数据范围内的全部网络设备(默认); - **按分组**:只备份所选分组(含「未分组设备」),别的分组一概不动; - **按勾选**:只备份表格里勾选的那几台,**可以跨分组勾选**。 选定后点「开始备份」,对目标设备**并行**执行配置备份并即时展示结果(每台成功/失败、 备份文件、大小)。用 `?g=<分组>` 打开本页可把表格也收窄到该分组,备份完回跳时保留该 筛选,看到的表与刚备份的范围是同一批设备。设备列表里每台设备自身的「备份」按钮仍保留, 单击只备份那一台。 服务器没有 `display current-configuration` 这回事,无论哪种范围都会被自动跳过并提示 (指标请看「服务器监控」,要敲命令请用「网页 SSH 终端」)。范围与勾选**都经数据范围 校验**:勾选列表会与当前账号可见的设备取交集,越权主键即使被提交上来也不会被备份。 **备份历史(交换机表格展示):** `配置备份` 页是一张**统一表格,每台交换机一行**, 该交换机的**配置文件历史直接列在表格行内**(最新在前,**默认折叠只显示最新 2 份**, 超过时点「展开全部」查看所有版本):每份显示 文件名(点击查看)、备份时间、大小, 并带「下载」「与上一版对比」(最早一份显示"最早版本")。表格还含备份份数、最近备份 时间,未录入数据库但有备份的 IP 也会单独成行展示。 **设计要点:** - 备份命令是只读的 `display current-configuration`,不会改动交换机配置。 - 网页备份同样通过共享 SSH 核心 `h3c_console.py` 下发,登录自动关分屏、自动翻页。 - 备份文件在 `h3c_backup.py` 与 Django 网页间完全共用(回车后生成文件的 IP+时间戳 即写入文件名),列表页直接扫描目录解析、按 IP 分组,无需数据库。 - 对比同时支持“同版无差异”判断(输出提示)与真实增删行的彩色差异。 - 网页查看/下载对文件名做了白名单校验,无法通过 URL 读取备份目录以外的文件。 ## 设备批量导入 / 导出 通过 ping + SSH(22) 端口探测自动判定网络设备,支持网段扫描、CSV 导入、CSV 导出。 **判定规则:** ping 可达 且 22 端口开放 → 判定为网络设备。 **网页(推荐):** 导航「批量导入」→ `http://127.0.0.1:8000/import/` - **网段扫描**:输入 CIDR(如 `192.168.56.0/24`),自动并发探测每个 IP, 结果**只列出判定为网络设备的主机**(IP 不通或 22 端口未开放的一律隐藏, 无法勾选),默认勾选并显示 Ping / 22 端口 / 判定结果;**已在设备库中的主机 标注“已添加”**,不显示导入勾选框,避免重复入库, 其余填上账号密码后一键批量入库(密码加密)。最多支持 2048 台,/24 约半分钟; 若一个都没扫到会给出提示。 - **CSV 导入**:下载**导入模板**(⬇ 下载导入模板)后按格式填写再上传,模板为 UTF-8 带 BOM 的 CSV(Excel 可直接打开),带说明注释和示例行,可在开头放 `#` 注释; 导入时同 IP 已存在自动跳过、缺密码跳过、非法行逐行报错; 可选“导入前 ping + 22 端口校验”在结果里显示每台设备的探测情况。 CSV 格式(支持中英文表头,`#` 为注释;`role`/`group`/`vendor` 三列可留空, 行内留空时回落表单里选的“默认分组”): ```csv name,ip,username,password,port,role,group,vendor 核心交换机,192.168.56.11,admin,12345678,22,gateway,总部,H3C 2楼接入,192.168.56.21,admin,12345678,22,接入交换机,教学楼A,华为 ``` `role` 列填 `gateway`/`接入`/`网关` 等即识别为网关交换机,`access`/`接入交换机` 等为接入交换机,其他值视为未设置;`group` 列填分组名,不存在会自动创建; `vendor` 列填 `h3c`/`华三`、`huawei`/`华为`、`cisco`/`思科` 等即归一为对应厂商, 留空表示未设置(SSH 采集时自动识别矫正)。老 CSV(无 `vendor` 列)依旧兼容。 - **CSV 导出**:一键导出全部设备。⚠️ 导出的 CSV 含**明文密码**,请妥善保管, 不要外传。 **命令行 `python h3c_scan.py`:** ```bash # 探测单台主机 python h3c_scan.py probe 192.168.56.11 # 网段扫描(并发,输出在线主机与判定结果) python h3c_scan.py scan 192.168.56.0/24 # 扫描并把判定的网络设备导出为 CSV(供网页导入) python h3c_scan.py scan 192.168.56.0/24 --out found.csv # 校验设备 CSV 文件格式 python h3c_scan.py csvcheck devices.csv ``` 网页导入与命令行共用同一个探测/扫描/CSV 解析模块 `h3c_scan.py`。 ## 设备批量执行(命令) 对多台设备批量下发指令,适合巡检(`display` 类只读指令)、批量查询状态等场景。 **网页:** 导航「批量执行」→ `http://127.0.0.1:8000/batch/` - **勾选设备**:设备按分组分组显示(每组表头带「全选本组」复选,也可全表全选), 顶部下拉可按分组筛选(只列出一个分组的设备),角色列一并展示。 - **输入指令**:多条指令用换行或 `;` 分隔,将按顺序逐条下发。 - **执行方式**:勾选的设备**并行执行**(默认并发 10 台,可在页面上调整“并发设备数”); 每台设备连接一次、内部指令仍按顺序逐条下发;单条超时可调(默认 20 秒)。 设备越多提速越明显:例如 30 台设备各跑 3 条指令,串行约需 30 倍单机耗时, 并行后接近 3~4 批的耗时。 - **结果展示**:按勾选顺序分组展示每条指令的状态(成功/失败)与耗时;成功回显 直接显示在页面下方,同时追加写入 `log.txt`(带设备 IP 前缀,便于区分多台设备)。 - **下发后内容不丢**:点「批量执行」后页面**仍停在「批量执行」标签页**,指令框里的命令与 勾选**原样保留**,可在原内容上改完直接再下发一次;逐台回显在「执行结果(N 台)」标签页, 顶部另有一条提示可直接跳过去。(早期版本提交后会自动切到结果标签页,指令框所在的执行 面板被隐藏,看起来像"刷新一下输入就没了"。) - **入库记录**:每条指令写入执行历史(不含回显),失败的指令标记为 `error`; 设备连接失败时,本批指令全部记为失败并显示原因,不会误报“已下发”。 - ⚠️ 指令对所有勾选的设备生效,请谨慎输入 `reset`、`save`、`delete`、`reboot` 等破坏性指令。设备确认类提问(Y/N)**不会自动应答**,需要确认的指令会等待直到超时, 建议只执行 `display` 等只读指令。 **AI 生成配置:** 批量执行页指令框上方有「AI 生成配置」区块。用自然语言描述想要的 配置(如「创建 vlan 100、101,把端口 GigabitEthernet1/0/1 加入 vlan 100 并配置为 access」),选中目标设备后点击生成,AI 会返回可直接下发的 H3C 命令并**预填回指令框**, 确认无误后再点「批量执行」。生成结果不会自动执行,只做辅助填表。 ## 变更工单(提交 → 审批 → 执行 → 回滚) 「变更工单」页(`/work-orders/`)把「改设备配置」变成一条可追溯的流程: **谁提的、谁批的、改了什么、怎么回滚、结果如何**都存进工单。与「批量执行」页的 分工是:批量执行适合当场敲只读命令,工单适合有审批要求的正式变更。 **状态流转:** ```text 草稿 ──提交──> 待审批 ──批准──> 已批准 ──执行──> 已执行 / 执行失败 ↑ │ │ └────撤回───────┴──驳回──> 已驳回 ─改完再提交─┘ └──回滚──> 已回滚 ``` - **提交 / 撤回**:申请人本人或管理员;被驳回的工单改完可以重新提交。 - **批准 / 驳回**:仅管理员,且**不能审批自己提交的工单**(超级用户例外,提示与审计里 会标注「自批」);**驳回必须写明原因**,申请人好知道改哪儿。 - **执行**:运维及以上;**高风险工单需要管理员执行**。 - **回滚**:只有「已执行 / 执行失败」且填了回滚命令的工单能一键回滚。 **新建 / 编辑**(`/work-orders/add/`、`/work-orders//edit/`):变更标题、变更原因 (为什么改 / 影响面 / 怎么验证)、风险级别(低 / 中 / 高)、计划变更时间、单条命令超时、 是否执行前自动备份;目标设备按分组勾选(**只能选自己数据范围内的设备**,越权的 id 直接 忽略);变更命令与回滚命令都用换行或 `;` 分隔,按顺序逐条下发。只有**草稿与被驳回**的 工单能改,已提交 / 已批准的要先撤回或驳回。 **执行前体检**(详情页实时给出): - **硬错误(不能执行)**:状态不是「已批准」、没有目标设备、变更命令为空、 有设备不在当前账号的数据范围内。 - **警告(可执行,但要人确认)**:没填回滚命令;命中高危命令特征(`reboot`、`save`、 `delete /force`、`format`、`shutdown`、`undo vlan`、改账号密码、删路由或接口 IP、 关 STP、升级镜像…);命令会向设备提 Y/N 确认(平台**不会自动应答**,可能等到超时); 有设备最近监测为离线;提前于计划时间变更;命令超过 50 条或设备超过 50 台 (建议拆单 / 分批)。表单页输入命令时也会即时提示同类风险。 **执行与回滚:** - 开了「执行前自动备份配置」就先并行备份目标设备(复用配置备份那套逻辑,顺带做漂移 检测),备份文件名与成功 / 失败记进工单;**备份失败不阻断变更**,但页面会明确标出 这台没有「变更前」还原点。 - 下发复用「批量执行」的并行 SSH 实现:多台设备并行,单台内部命令按顺序。 - **全部设备成功**才记「已执行」;只要有一台失败就记「执行失败」——部分成功比全失败 更危险,得让人看逐台结果决定继续还是回滚。 - 回滚全部成功 → 「已回滚」;有失败则**保留原状态**并留下回滚结果,提醒人工上设备处理。 - 工单里只存命令文本与状态 / 错误 / 耗时,**不存回显**(回显在「日志中心」与 `log.txt`); 每次执行与回滚都写一条「任务监控」记录(名称形如 `变更工单 #12 …`、 `工单回滚 #12 …`),失败原因可在任务详情里逐台查看。 **列表与筛选**:按状态、关键字(标题 / 变更原因)筛选,可勾「只看我提交的」,每页 20 条; 统计卡给出 总数 / 待审批 / 已批准待执行 / 已执行 / 执行失败 / 我提交的;详情页底部 汇总这张工单的操作审计。 **权限与删除**:只读角色只能查看(写请求由中间件统一拦下);数据范围限定地区的账号只看 得到自己提交的、或目标设备在本地区的工单。删除只允许管理员,或申请人删自己的草稿 / 被驳回工单——已进入执行环节的工单是变更记录,不允许悄悄删掉。所有写操作都记 「操作审计」(对象类型 `change_order`)。 **代码入口**:状态机与执行封装在 `device_console/change_order.py`(`preflight()` 体检、 `transition()` 流转、`execute()` / `rollback()` 下发,命令下发器可注入,单元测试不触网); 工单模型是 `models.ChangeOrder`。 ## 交换机 syslog 日志(syslog 告警接收) 导航「日志中心 · 交换机 syslog 日志」→ `http://127.0.0.1:8000/syslog/`(指令日志与交换机 syslog 日志 共用「日志中心」入口,顶部中心标签条切换)。平台随网页服务启动一个 **UDP syslog 服务**,接收交换机上送的日志并按 RFC3164 / H3C 扩展格式**结构化解析**后入库: 拆出优先级(facility/severity,0-7 对应紧急/严重/危急/错误/警告/通知/信息/调试)、 时间、模块(tag)、H3C 事件名(如 `PROC_CPU`、`IFNET_STATE`)与正文;来源 IP 命中 设备库的报文自动关联到对应设备。 **交换机侧只需要配置 loghost:** ``` info-center enable info-center loghost <平台IP> 514 facility local7 info-center source default channel loghost log level informational ``` (页面底部有完整示例与说明;端口按平台实际监听端口填写。) **页面功能:** - 按设备 / 级别 / 时间范围(近 1/3/7/30 天)/ 关键字筛选,每页 50 条分页展示; 级别以彩色徽章显示,内容超长自动截断(悬停看全文)。 - 每条日志可单独「AI 分析」,也可勾选多条后批量交给 AI 综合分析;分析结果(问题、 根因、影响、处置建议)直接渲染在页面下方,见下方「AI 大模型接入」。 - 删除单条 / 清空全部;顶部实时显示今日数量、告警级(0-4)数量与监听状态 (未监听时显示红色标记,通常是防火墙或端口权限问题)。 **端口与环境变量:** | 变量 | 默认 | 说明 | | --- | --- | --- | | `H3C_SYSLOG_PORT` | `514` | syslog 监听端口。Windows 无管理员权限绑定 514 会失败(页面显示“未运行”),改用高位端口如 `1514` 即可;生产环境以管理员运行可保持 514。 | | `H3C_SYSLOG_DISABLED` | 未设置 | 设为 `1` 禁用 syslog 服务(仅调试用),与服务日志文件同侧记入 `syslog_server.log`。 | ## 告警中心(事件驱动闭环) 「告警中心」(`/alerts/`)把平台各处检出的异常汇成一条时间线,并按规则推送到 企业微信 / 钉钉 / 飞书 / 邮件。**告警来源**共七种: | 来源 | 谁触发 | 判定口径 | | --- | --- | --- | | Syslog 日志 | syslog 接收服务落库后 | 级别 ≤ 规则的「级别上限」(0 紧急 ~ 7 调试),可选关键字命中模块 / 事件 / 内容 | | SNMP 监控指标 | 大屏轮询与「SNMP 监控采集」任务采集后 | CPU / 内存 ≥ 规则阈值 | | 服务器主机指标 | 主机指标一落库就判(Agent 上报 / SSH 采集),「数据过期」由大屏主机体检按间隔判 | CPU / 内存 / 磁盘 ≥ 规则阈值;或「数据过期」超过 N 分钟没有新指标(留空按 30 分钟) | | 交换机遥测指标 | 遥测推送抽出指标后就判(gRPC dial-out / HTTP),「推送中断」由大屏遥测体检按间隔判 | CPU / 内存 ≥ 规则阈值、温度 ≥ 规则摄氏度;「接口错包增长」≥ 规则条数(留空按 1 条);或「遥测中断」超过 N 分钟没有新推送(留空按 30 分钟) | | IPAM 网段对账 | 「ARP 对账」按钮或「IPAM 对账与告警」任务 | ARP 学到但未匹配任何地址段的网段(未规划),同一网段 24 小时内只告一次 | | IPAM IP 冲突 | 同上,或「⚠️ IP 冲突告警」按钮 | 同一 IP 被两个及以上不同 MAC 学到(重复配置 / 私接 / ARP 欺骗) | | 配置变更 | 每次配置备份成功后 | 最新一份与上一份备份逐行比对有增删,同一设备 12 小时内只告一次 | - **规则**(`/alerts/rules/`):按来源配置级别上限 / 关键字 / 指标与阈值 / **去重间隔** (同一规则 + 同一设备在间隔内只告一次),并绑定一个或多个推送通道;可启用停用、编辑、 删除、测试推送。IPAM 与配置变更类告警由平台直接生成、不依赖规则,无规则绑定时兜底 推送到**全部启用通道**。 - **主机指标规则怎么判**(`alerting.evaluate_host_metric` / `evaluate_host_states`): 指标可选 CPU / 内存 / 磁盘(百分比阈值)或**数据过期**(分钟阈值);命中时级别按主机 阈值折算——达到严重线(95%)记 `2 严重`,否则记 `4 警告`,数据过期记 `2 严重`。 两个判定入口共用同一套去重窗口:`host_agent.ingest` 落库后**即时**判阈值, 大屏「主机体检」按间隔做**周期**体检(顺带判数据过期),所以「Agent 刚推上来就告警」 与「机器不推了也能告警」两种情况都覆盖;从没采集过数据的主机不告警(没装 Agent 不等于故障)。判定与推送任何异常都不外抛,绝不影响指标入库。 - **遥测指标规则怎么判**(`alerting.evaluate_telemetry_metrics` / `evaluate_telemetry_states`):指标可选 CPU / 内存(百分比)、温度(摄氏度)、 **接口错包增长**(两次采样之间新增的错包 / 丢包条数)或**遥测中断**(分钟阈值); 命中时级别按遥测阈值折算——达到严重线(CPU / 内存 95%、温度 75℃、错包增长 50 条) 记 `2 严重`,否则记 `4 警告`,推送中断记 `2 严重`。两个判定入口同样共用一套去重 窗口:`telemetry_server.ingest` 抽出指标后**即时**判阈值,大屏「遥测体检」按间隔做 **周期**体检(顺带判推送中断),所以「刚推上来就告警」与「交换机不推了也能告警」 两种情况都覆盖;从没推过遥测的设备不告警(没配 telemetry 订阅不等于故障)。 - **通道**(`/alerts/channels/`):企业微信 / 钉钉 / 飞书机器人 webhook(钉钉、飞书支持 加签密钥),或 SMTP 邮件(SSL/TLS、发件人显示名、多收件人);密钥与密码加密存储, 编辑时留空表示不修改;「测试推送」可当场验证连通性。 - **记录页**:按来源 / 状态(未处理·已确认)/ 天数 / 关键字筛选,最多列 200 条; 单条可**确认**、**重试推送**(重发并写回逐通道结果)、删除,也可一键清理只保留最近 100 条。`push_results` 里存着每个通道的推送结果 JSON,通道或规则后来被删也不影响历史。 - **推送 worker**:告警入队后由后台线程逐通道发送,未随服务启动时会兜底自启; 单条推送异常不影响其他告警。可用 `H3C_ALERTING_DISABLED=1` 关闭推送服务。 ## AI 大模型接入(日志分析 / 批量生成) 平台通过 OpenAI 兼容的 `chat/completions` 接口对接各大模型,用于**分析交换机日志** 与**批量生成配置命令**。支持:DeepSeek、智谱 GLM、MiniMax、MiMo、**Ollama(本地, 免 Key)**,以及任意 OpenAI 兼容的自定义地址。 **AI 配置页**(导航「AI 配置」→ `/ai/config/`): - **新增/编辑**:填配置名称、提供方类型(选择后自动填充官方地址与常用模型,可改)、 模型名称、API 地址、API Key。Key 加密存储、页面不回显;编辑时留空表示不修改。 - **设为当前**:全局同一时刻只有一个“当前”配置(`is_active`),syslog 日志分析、 批量生成都自动使用当前配置——切换厂商只需点一下「设为当前」,下次即生效 (对应需求 7:配置保存后可随时切换复用)。 - **测试连接**:发一条最小对话验证地址/Key/模型是否可用。 - 预设地址与模型: | 类型 | base_url | 默认模型 | | --- | --- | --- | | deepseek | `https://api.deepseek.com/v1` | `deepseek-chat` | | glm | `https://open.bigmodel.cn/api/paas/v4` | `glm-4-flash` | | minimax | `https://api.minimaxi.com/v1` | `MiniMax-Text-01` | | mimo | `https://api.xiaomimimo.com/v1` | `MiMo-7B-RL` | | ollama | `http://127.0.0.1:11434/v1`(本地,无需 Key) | `qwen2.5:7b` | | other | 自定义 | 自定义 | **日志分析:** 在交换机 syslog 日志页勾选一条或多条后点「AI 分析勾选的日志」,平台把结构化 字段(时间、来源、设备、级别、模块/事件、正文)拼成紧凑文本交给当前配置的大模型, 以“H3C 网络运维专家”角色输出:问题告警 / 原因分析 / 影响范围 / 处置建议。调用为 同步阻塞(与批量执行一致),结果直接显示在页面上。 **批量生成配置:** 见上方「设备批量执行 - AI 生成配置」,AI 按所选设备的名称/型号 作上下文生成命令,用户核对后再执行,AI 不直接下发命令。 ## AI 助手(自然语言问数据 + 告警根因分析) 「AI 助手」页(导航「巡检与合规 → AI 助手」→ `/assistant/`)把平台里已经攒下的结构化数据 (设备台账、告警、syslog、巡检、SNMP 监控、合规、IPAM、终端、任务、拓扑、变更工单)压成 一份**紧凑快照**交给大模型归纳。**AI 只负责归纳与推理,不负责提供数据**:所有数字都来自 库里的真实记录,回答下方同时展示「本次参考的数据」,对不对人工一眼能核。 - **提问**:输入一句话即可(最长 2000 字),页面给 6 个快捷问题——整体健康状况与最该立刻 处理的三件事 / 哪些设备离线、可能原因与排查 / 最近 24 小时告警集中在哪些设备和来源 / IPAM 里有没有 IP 冲突或未规划网段 / 哪些设备长期没配置备份或巡检不健康 / 拓扑上有没有孤立设备、单向链路这类结构问题。 - **回答口径**:模型被要求「只用快照里的数据回答」,快照里没有的信息要直说「平台里没有这项 数据,需要先到某个页面采集」,不许编造设备名、IP 或数字;先给结论再给依据,涉及处置动作时 写出具体命令或平台页面路径,并提醒人工确认后再执行。 - **数据范围**:快照跟随登录用户的地区权限生成(`authz.scope_*`),限定地区的账号不会把 越权数据交给模型;默认取最近 24 小时窗口(合规与工单另按 7 天统计),每类明细最多 10 条, 序列化后超过 9000 字符会截断并明确告诉模型「只给了一部分」。 - **打开页面就出一份快照**:不用先提问就能看到「AI 现在能看到什么」,方便判断某个问题问不问得出来。 - **告警根因分析**:告警中心每行的「AI 根因」按钮进入 `/alerts//ai/`——先展示这条告警的 排障上下文(告警本身、设备台账、该设备近期告警与 syslog、最近巡检与 SNMP 指标、合规不通过项、 LLDP 邻居及其在线状态、与上一份备份的配置漂移、最近备份时间、相关变更工单,以及**同期其它 设备的告警数**用来判断是点故障还是面故障),再让模型输出四段:最可能的根因(按可能性排序, 最多 3 条,注明依据是哪条数据)/ 影响范围 / 排查步骤(只读命令优先,如 `display`、`show` 系列)/ 处置与预防建议。页面还给「去建变更工单」的入口,把分析结论落成一次可审批的变更。 - **只读、不触网**:助手只读数据库与已有的备份文件,**不会连设备、不会下发任何命令**; 真要改配置请走「变更工单」。 - **失败不报错页**:没配 AI、问题为空、模型超时或返回异常,都只在页面上给一句提示(快照照常 展示),不会 500;未配置 AI 时页面直接引导去「AI 配置」保存并设为当前。 - **留痕与权限**:每次提问与每次根因分析都写一条操作审计(对象类型 `assistant` / `alert`), 记录问题或告警摘要与失败原因;只读角色可以打开页面看数据,但提问与分析会被全站写操作 拦截挡下。 ## AI Agent(模型自己调工具,多步推理) 「AI 助手」是一次问答:平台先把数据准备好,模型只负责归纳。「AI Agent」页 (导航「巡检与合规 → AI Agent」→ `/agent/`)不一样——**模型自己决定查什么、分几步查**: 它先看一遍可用工具清单,然后一轮一轮地调用工具、读结果、再决定下一步, 最后给出带依据的答复。整条调用链都留在页面上,能一步步核。 好比你问「有哪些设备离线?顺便看看是不是同一台 AC 下的 AP 全掉了」,助手只能拿着平台预生成的 那份快照硬答,Agent 则会自己依次调 `list_devices` → `device_detail` → `query_alerts`, 缺什么补什么。 ### 工具层(18 个内置工具 + 启用知识库后的 `search_knowledge`,`ai_tools.py`) 工具就是「给模型用的函数」,每个工具自己声明参数与说明,模型只能按声明的格式调用: | 工具 | 作用 | | --- | --- | | `platform_overview` | 平台总体概览(设备/告警/巡检/合规/任务/服务器健康计数) | | `list_devices` | 按厂商、状态、分组、关键字筛设备台账(`category=server` 可筛服务器) | | `list_servers` | 受监控服务器列表 + 最新指标 + 健康定级 + 主机检查概览 | | `server_detail` | 单台服务器明细:身份/最新指标/健康原因/逐项检查/趋势 | | `device_detail` | 单台设备的完整台账 + 最近巡检/备份/监控(服务器附 host 块) | | `query_alerts` | 按时间窗、级别、来源查告警 | | `query_syslog` | 按时间窗、级别、关键字查 syslog | | `check_compliance` | 合规检查结果(策略级通过/不通过,**区分「未采集」**) | | `diff_backup` | 设备最近两份配置备份的差异 | | `ipam_status` | IPAM 冲突、闲置 IP、未规划网段与地址段使用率 | | `topology_risks` | 拓扑结构问题(孤立设备、单向链路、LLDP 不一致) | | `terminal_lookup` | 按 MAC/IP/终端名查终端接入信息 | | `task_history` | 任务执行历史(含失败原因) | | `propose_change` | **生成变更工单**(写操作,落成待审批工单,不执行) | | `run_readonly_commands` | **连设备执行只读命令**(见下) | | `recall_memory` | **查平台记忆**(跨会话沉淀的口径/步骤/坑,见下「平台记忆」) | | `remember` | **写一条平台记忆**(写操作,需运维及以上;只记经人确认、以后还用得上的结论) | | `search_knowledge` | **检索运维知识库**(WeKnora,见下)——文档类问题(「怎么操作」「流程是什么」)用它,返回原文片段与来源标题,答复标注出处;未启用知识库时该工具不进清单 | 设计上守五条底线:**只读优先**(写操作只生成工单,绝不下发);**不重复造轮子** (工具内部直接调用平台已有函数,不另写一套解析);**不信任模型**(权限、范围、白名单 都在服务端判,模型说破了天也没用);**不知道就说不知道**(取不到的数据明确标「无法检查」, 绝不猜);**回显不入库**(设备回显只进这次会话的上下文,不落库,需要留痕的看「指令历史」)。 ### 跑一轮 Agent 时它还做了四件事(2026-10-05 起) **① 同轮并发 + 结果缓存**(`ai_agent._execute_calls` / `ai_tools.run_tool`)。模型一轮里 常一次要 3-5 份互不依赖的数据,纯读工具现在并发跑(最多 4 个),串行改并行就是省等待; 同一个查询被问两遍直接复用(`cached: true` 会如实告诉模型"这是复用不是新查的")。 边界很硬:**连设备、建工单、外部 MCP 工具一律串行且不缓存**(有副作用,顺序与预算都要可控)。 缓存只在**一轮会话内**有效,跨会话不复用——避免读到旧状态。 **② 失败后重规划,而不是原地撞墙**。工具失败时,回给模型的消息里附一句明确指令 (换工具/改参数/如实说明缺什么);同一个 (工具, 参数) 本轮已经失败过,第二次调用**直接拦截** 不再真跑——模型最爱干的就是原样重试,拦它既省预算也省超时时间。半途失败的状态会如实 写进步骤表,人工一眼看到它卡在哪。 **③ 自我验证环**(`ai_verify.py`)。模型很擅长把话讲圆,"看起来像结论"不等于"有依据"。 所以每轮答复完,再做一次事后复核,**顺序不能反**: 1. **确定性检查(不花钱、不会错判成通过)**:一次工具都没调、答复里却有具体数字 ("5 台离线")→ 判「缺乏依据」;答复里的 IPv4 必须在本轮任一工具结果里出现过, 没出现过至少降级为「部分一致」并列出可疑 IP; 2. **模型复核**:把「问题 + 答复 + 本轮真实证据摘要」交给模型自己判一致性,要严格 JSON (`consistent` / `partial` / `unsupported` + 理由 + 还缺什么)。 合并规则:**确定性结论只能下调模型给的评价,不能上调**。结果落 `AgentRun.review_status`, 页面上以徽章 + 可展开理由呈现 —— 它只是提醒,**结论该不该信以你看到的证据为准**。 复核本身坏掉(模型超时/返回不解析)退化成「跳过」,绝不把会话弄失败。 **④ 平台记忆(跨会话)**(`agent_memory.py` + `AgentMemory` + `recall_memory`/`remember`)。 模型没有记忆,每轮都是新上下文——「这台设备的 restful https 早就开了」「上次那条告警的根因是 ClickHouse 空转」这类结论每轮都得重问。所以把**经人确认、值得复用的短结论**存下来 (类型:事实/步骤/坑/备注,≤500 字,带标签),每轮开始按关键词挑几条塞进提示词, 并**明确标注"历史沉淀、可能过期、与工具取到的数据冲突时以数据为准"**——记忆是提示不是事实。 检索刻意保守:宁可少注入(漏了模型会自己去查),也不要塞一串过期结论把它带偏。 页面上能增删停用,模型也能主动查;`remember` 要运维及以上角色,**别记凭据、别记一次性查询结果**。 **顺带把用量与成本亮出来了**:以前一轮 Agent 花多少 token、值多少钱,平台一无所知。 现在 `ai_client` 会把接口回的 `usage` 累加(畸形值兜 0,不让统计带崩主流程),落 `AgentRun.prompt_tokens/completion_tokens/llm_calls`,按「AI 配置」里填的**单价**(元/百万 token) 估算费用——没填单价就只统计 token 不折算金额(不猜钱)。「AI 配置」同时多了**单次请求超时**: 本地 Ollama 比云端慢一个量级,调用点写死的超时对它都不合适。 ### MCP 工具桥接(外部工具,`mcp_client.py`) Agent 还能动态接入外部 **MCP server** 的工具(MCP,AI 工具通用协议)。默认指向本机的 network-ops MCP:真机层面的故障体检(`diagnose_device`,SSH 可达 / CPU / 内存 / 接口 / 日志 / 光功率逐项判定)、路径诊断(`diagnose_path`)、批量巡检(`health_check`)、配置备份、 连通性测试,以及本平台只读 API 的查询(`netpilot_*` 系列,读告警 / Syslog / 巡检 / 拓扑 / IPAM)。 于是「平台告警 → 真机体检 → 平台复查收敛」能在一轮 Agent 会话里串起来。 - 桥接工具名带 `mcp_` 前缀,与平台自带 13 个工具并列出现在工具清单里; - 一律受「允许连接设备」授权约束——未授权的会话里模型**看不见**这些工具; - 改配置类工具(`run_config_commands` / `init_device`)**默认不桥接**——那是绕过变更 工单流的旁路;确要开启设 `H3C_MCP_WRITE_TOOLS=1`(仍限运维及以上角色); - server 以 stdio 子进程方式拉起,死亡自动重启、调用失败转 `ok=false` 中文原因, 不影响自带工具;`H3C_MCP_DISABLED=1` 整体关闭,`H3C_MCP_SERVERS_JSON` 可指向 其他 MCP server;零新依赖(自实现 MCP stdio JSON-RPC 客户端)。 ### NetPilot 对外 MCP Server(`netpilot_mcp_server.py`) 反方向同样打通:整个平台可以**封装为一个独立的 MCP server**(stdio,零新依赖, 自实现 initialize/tools/list/tools/call),把平台原生 15 个运维工具原样暴露给任意 MCP 客户端(ZCode / Claude Desktop / …): - 平台数据类:`platform_overview`、`list_devices`、`list_servers`、`server_detail`、 `device_detail`、`query_alerts`、 `query_syslog`、`check_compliance`、`diff_backup`、`ipam_status`、`topology_risks`、 `terminal_lookup`、`task_history`; - 设备操作类:`run_readonly_commands`(白名单守卫的只读命令)、`propose_change` (只产出待审批的变更工单草稿,不下发配置)。 MCP 进程按本机运维管理员构建执行上下文(数据范围全网、预算放宽到 10 台设备/40 条 命令),权限与预算护栏全部复用 ai_tools 既有实现;进程不启动平台后台服务,与网页 共享数据库。ZCode 等客户端的注册示例: ```json { "netpilot": { "type": "stdio", "command": "C:\\Python314\\python.exe", "args": ["C:\\Users\\admin\\Desktop\\vibecoding\\h3c_web\\netpilot_mcp_server.py"], "env": { "PYTHONIOENCODING": "utf-8", "H3C_BACKGROUND": "0" } } } ``` 如此一来,外部 Agent 侧同时拥有两个专职运维工具集:`netpilot`(平台治理运维: 合规/工单/IPAM/拓扑风险/白名单命令)与 `network-ops`(直连设备 SSH 运维: 体检/初始化/备份),平台内置 Agent 又能反向桥接 network-ops——三个入口共享同一套 运维能力,各取所长。 ### 运维知识库(外部 RAG,`weknora_client.py`) 平台自己的数据都是「实时事实」——台账、告警、巡检、合规;**文档类知识**(平台手册、 厂商命令参考、运维规范、复盘记录)原先不在 AI 的查询链路里,模型没地方查「光模块 怎么换」。这一层把外部知识库 **WeKnora**(腾讯开源的知识管理框架)接进来:Agent 多 一个 `search_knowledge` 工具,检索命中的**原文片段 + 来源文档标题**一起回给模型, 答复里标注出处,人工一眼可核。 - **开关与配置在「AI 配置 → 运维知识库」**:填 WeKnora 地址与 API Key(加密存储、 不回显)、可限定知识库 ID(留空 = 该 Key 可见的全部知识库)、调默认返回片段数; 「测试连接」当场发一条真实检索验证连通; - **三处入口,同一套开关**:全站右下角浮层挂件「📚 问知识库」(设备执行页 / 告警 AI 页 / 合规检查页自动带上当前对象作上下文)、独立页 `/knowledge/`、告警根因分析 (按告警内容+厂商型号自动检索,页面多出「知识库处置依据」一块); - **启用与否决定一切入口**:关着的时候挂件、导航与 `search_knowledge` 工具都不出现—— 与「未授权连设备则连设备工具不可见」同一逻辑,不靠模型自觉; - **权限在知识库侧**:给平台一把**只读(`retrieve`)、限定知识库**的 API Key, 平台不做二次过滤;换了 Key 或知识库范围,改一处即可; - **故障不炸会话**:知识库没配 / 服务挂了 / Key 被拒 / 回包畸形,一律转成 `ok=false` 中文原因或「只给检索片段」的降级形态,本轮 Agent 与根因分析照常走完; - **引用随片段走、内容不落库**:命中片段只进本轮上下文(与「回显不入库」同规矩), 挂件的「本次引用」、Agent 的「执行过程」摘要、根因页的「知识库处置依据」都能点开核原文。 部署提示:WeKnora 可以用官方 Docker Compose(**实验室当前形态**:标准版跑在 `10.130.16.33`, 5 个容器 app/frontend/docreader/postgres/redis,API 在 `http://10.130.16.33:8080`、Web 在 `:80`; 向量模型是宿主机 Ollama 的 `bge-m3`,容器经 `host.docker.internal` 访问), 也可以编 **Lite 单二进制**(SQLite + 内存队列,零外部依赖,单机即可跑); 平台侧无额外依赖(客户端就是 `httpx`),换知识库只改「AI 配置 → 运维知识库」一处。 ### 连设备:严白名单,先校验再连接 `run_readonly_commands` 是唯一会碰设备的工具,**默认关闭**——页面上要显式勾选 「允许连接设备」,而且账号必须是有写权限的角色(只读角色连这个工具都看不到)。 勾上之后也仍然受限: - **首词白名单**:只放行 `display` / `show` / `ping` / `ping6` / `tracert` / `traceroute` / `dir`。 - **写操作关键词**:`save`、`reset`、`reboot`、`undo`、`delete`、`format`、`copy`、`tftp`… 出现即拒(按**整词**匹配,所以 `show ip ssh`、`display startup` 这类查询不会被误伤)。 - **禁止字符**:换行、`;`、`&`、反引号、重定向符等一律拒绝(管道符 `|` 例外)。 - **管道只放行过滤**:`| include / exclude / begin / section / count`,最多 2 个管道; `| redirect`、`| tee`、`| append`(会往设备写文件)被挡下。 - **先校后连**:命令在**建立 SSH 连接之前**就全部校验完,一条不合规**整批拒绝**, 绝不下发半截。 - **预算封顶**:单次会话最多 3 台设备、15 条命令、90 秒,单条命令 20 秒超时; 超了直接拒绝并告诉模型为什么。 白名单本身还能**按厂商 / 设备分组 / 设备角色自定义**,见下一节。 ### 命令白名单策略(内置底线 + 管理员自定义,`ai_policy.py`) 白名单的判定逻辑集中在 `ai_policy.py`,分两层:**内置底线**(写死在代码里)和 **自定义策略**(管理员在「安全 → AI 命令策略」页维护,`/ai/policy/`,仅管理员可见)。 判定顺序固定,任一条不过即拒: 1. **内置底线**(`CORE_DENY_WORDS`):进配置视图、落盘、重启、清配置、传文件这类词 (`system-view` / `configure` / `save` / `write` / `copy` / `reboot` / `reset` / `delete` / `format` / `tftp` / `scp` …),**策略与超级管理员总开关都放不开**。 2. **次级底线**(`ESCALATE_DENY_WORDS`):文件改名 / 移动 / 解压这一类 (`rename` / `move` / `mkdir` / `unzip` / `tar` / `patch` …),默认同样拒绝, 只有超级管理员总开关能放开。 3. **内置默认首词白名单**:`display` / `show` / `ping` / `traceroute` / `dir`。 4. **自定义策略**:按下面的动作叠加。 5. **硬校验**:禁止字符、长度、管道段数、管道后必须是过滤关键词—— 不受任何策略影响(它们防的是「一条命令里塞两条命令」,与命令危不危险无关)。 **自定义策略的五个动作**(按 厂商 / 设备分组 / 设备角色 匹配,任一留空 = 不限): | 动作 | 作用 | | --- | --- | | 追加允许的首词 | 放行内置白名单之外的首词,如老 Comware 的 `dis` 缩写、思科的 `join` | | 追加管道过滤词 | 放行内置之外的过滤关键词,如思科的 `\| regexp` | | 追加禁止命令词 | 在底线之上再禁一批词,如「接入层禁止 snmp-agent」 | | 豁免禁止词 | 把某个词从**自定义禁词**里摘回来,**碰不到内置与次级底线** | | 禁止下发任何命令 | 整台设备 / 整个分组一条都不许发,AI 只能查平台数据 | **冲突规则**(`match_policies()`,这是最容易配错、也最要紧的一处): - **收窄类动作(禁止命令词 / 整台禁发)所有命中的策略全部生效,绝不按优先级淘汰。** 两位管理员各加一条禁止时两条都算数——按优先级淘汰一条限制等于把边界悄悄放宽, 而且没人看得出来。 - **放宽类动作(放行首词 / 放过滤词 / 豁免)同动作只留胜出的一组**: 先比「优先级」(数字小的优先),再比「匹配维度更具体」的(填了厂商/分组/角色 的压过全留空的)。放宽需要能写出「全网放行某首词,但核心机房那条不放行」。 - **动作之间取交集**:一条命令要过所有关卡,所以「放行首词」压不过「禁止命令词」。 **两个全局开关**(「AI 命令策略」页): - **整体熔断**(`custom_enabled`):一键让所有自定义策略失效、退回内置底线。 看得见的方向谁都能做——任何管理员都能熔断;**重新打开需要超级用户**。 - **超级管理员总开关**(`superuser_open`):放开次级底线。只有 Django 超级用户 (`is_superuser`)能改,普通 admin 连关都关不掉,**开启必须填原因**; 开启后每页顶部挂红色横幅(含操作人与原因),提醒尽快关掉。 页面还带一个**试跑框**:输入一条命令 + 指定设备,用真实的判定逻辑跑一遍 (和 Agent 下发前调的是同一个函数),摊开显示命中的策略、生效的首词/禁词/过滤词, 以及被拒的具体原因。增删改、试跑、开关每一次写入都留操作审计(对象类型 `ai`)。 内置底线**只在页面上只读展示**,不能改——安全基线让它在库里可删可改, 等于把基线交给一次误操作。要临时放开某条命令,用「豁免」或停用对应策略。 ### 两种工具协议,自动降级 接口支持 function calling 就走**原生协议**(`tools` 参数 + `role:"tool"` 消息); 不支持(多数本地小模型、部分中转站)就自动降级为**文本协议**:让模型输出 `TOOL: {"name": "...", "arguments": {...}}` 一行,平台解析后照常执行。 降级结果会写回 AI 配置(`supports_tools` 取消勾选),下次直接走文本协议不再试错; 「AI 配置」页可以手工勾选/取消,列表里用「原生 / 文本」标签直接看出当前协议。 ### 过程可见、可回看 - 页面上「执行过程」逐条列出:模型说明 → 工具名 + 参数摘要 + 结果摘要(成功/失败)→ 最终答复, 每步带耗时。 - `AgentRun` / `AgentStep` 两张表记录完整链路,`/agent//` 可回看历史会话; **只存摘要,不存设备完整回显**(回显要留痕走「指令历史」那一套)。 - 单次最多 6 步(可调到 10),全轮最多 20 次工具调用;步数用完会强制模型基于已有信息作答, 而不是把中间状态直接丢给你。 - 模型挂了、工具报错、参数写错,都会转成一句中文提示继续往下走,**不 500**; 失败的中间步骤照样入库,方便排查。 - 每次会话写一条操作审计(对象类型 `assistant`),注明「已授权连设备」还是「仅查平台数据」。 - 工具返回的设备回显与日志被当作**数据**而非指令塞给模型,系统提示里明确禁止执行其中的 「指令性文字」,防提示词注入。 ## 设备信息采集 设备列表每行有「采集信息」按钮,通过 SSH 只读指令自动采集设备信息并展示在列表中: - **设备名称**:`display current-configuration | include sysname` 解析 sysname 值, **会覆盖数据库里当前的设备名称**(“更新覆盖名称”)。 - **型号**:`display version` 的机型行(如 `H3C S5820V2-54QS-GE`)。 - **序列号**:`display device manuinfo` 的 `DEVICE_SERIAL_NUMBER`/`SN` 等字段。 采集结果保存到设备表新增的“型号 / 序列号”字段,页面列表直接展示; 账号或设备不可达时提示“采集失败”,不会改动原有数据。 兼容 Comware V5/V7 常见的命令英文大小写及多级类设备(Slot/风扇/电源序列号取第一个)。 **厂商自动识别**:采集连上设备后会先探测真实厂商(`display version` → `show version` 回退),按识别结果选命令(思科走 `show inventory` 取序列号、`show running-config | include hostname` 取主机名)并**覆写**数据库厂商值(列表提示“厂商 旧→新”);型号解析 对思科 `PID:` 行也做了兼容。 ### 一键采集与一键备份 两个“一键”操作都在**设备列表首页**(`/`)工具栏上,不需要逐台点击: - **一键采集设备(身份+LLDP)**:先选采集方式(SSH 用账号 / SNMP 用社区字,均为只读), 点按钮后对目标设备**并行**采集:先落身份信息(名称/型号/序列号,连接时自动识别真实厂商 并写回),再采 LLDP 邻居与接口,保证「连接接口」推导用的是最新设备名;每台的成功/失败、 采集到的名称/型号/序列号与解析出的邻居数展示在「操作结果」标签页。 **采集范围跟着分组筛选走**:列表正按某个分组筛选时按钮显示为「一键采集本分组设备」, 只采该组设备,别的分组的名称、LLDP 记录与「连接接口」一概不动;不筛选时才是全部设备。 名称会覆盖数据库(与逐台采集行为一致);设备越多提速越明显,例如 5 台约 5 秒内完成。 - **一键备份选中设备**:先在列表左侧**勾选**要备份的设备,再点「一键备份已选设备」, 对选中设备**并行**执行配置备份(`display current-configuration`), 结果表格展示每台的备份文件名(可点击查看/下载)或失败原因;与 `/backups/` 页共用同一份备份目录与文件名规则(自带设备 IP 与时间戳)。 两个操作都是并行执行、按勾选/列表顺序显示结果;失败单台不阻塞其余设备。 ## 全局定时任务(调度器) 在「定时任务」页(`/schedule/`)创建任务后,调度器会按计划**自动**执行系统已有功能 (执行范围可选全部设备或指定分组),适合巡检、合规、备份等周期性自动化操作。 定时跑一次与网页上手动点一次,走的是同一套底层函数,结果完全一致。 **任务类型与执行范围:** - **采集设备信息**:并行收集名称/型号/序列号。 - **拓扑采集(LLDP)**:并行 SSH 采集范围内设备的 LLDP 邻居并落库,同时按**同分组** 设备名回填「连接接口」;配合分组范围可让每个分组的拓扑各自保持新鲜, 拓扑分析里的「LLDP 数据过期」风险靠它消掉。 - **配置备份**:并行执行配置备份,备份文件可直接在备份页查看。 - **批量执行指令**:批量下发一组指令(换行或 `;` 分隔多条), 专为 `display` 等巡检类只读指令设计(设备 Y/N 确认**不会自动应答**)。 - **SNMP 监控采集**:并行执行 SNMP 监控采集(身份写回 + CPU/内存入监控历史), 结果与「SNMP 监控」页一致,可周期运行长期积累性能趋势;采集后顺带跑一遍监控指标告警判定。 - **设备巡检 / 终端信息采集**:与「设备巡检」「终端信息」页同一套逻辑,健康度与终端台账 周期入库。 - **合规检查**:对范围内设备跑**全部内置策略**(一次连接采齐配置回显,按厂商分别用 H3C/华为或思科规则判定),批次与逐项结果落库,可在「合规检查」页按批次号回看; 有违规或连接失败即记为失败。 - **AI 巡检**:把「批量指令」输入框当作**自然语言需求**(如“检查 CPU、内存与 STP 状态, 并列出异常端口”),到点由 AI 生成只读命令 → 自动并行下发 → 结构化解析入批次; 需先在「AI 配置」里设好当前模型,未配置时任务直接失败并说明原因。 - **无线采集**:并行 SSH 登录范围内的**无线控制器**(类型 = 网络设备 · 无线控制器) 采集 AP 与在线终端并落库,采完自动重算一遍「AP ↔ 接入交换机」对应关系; 摘要给出 AC 成功台数、AP / 终端总数与在线数,明细逐台记录失败原因。 - **主机信息采集**:并行 SSH 登录范围内的**服务器**(大类 = 服务器,或档案里填了 操作系统)跑一条只读探测命令,把 CPU / 内存 / 磁盘 / 负载 / 运行时长 / 硬件信息 写入主机指标;已装 Agent 的机器由 Agent 自己周期上报,两条通道写同一张表。 - **IPAM 对账与告警**:一次跑完 ARP 对账 + 未规划网段告警 + IP 冲突告警,并统计疑似闲置 地址数(**只统计不自动回收**,回收需人工在页面上确认)。 - **数据保留清理**:立即执行一次保留策略清理(超期 syslog / 采集 / 巡检 / 指令日志 / 告警 / 终端 / 遥测记录与遥测指标、按设备裁剪备份文件、截断过大的文本日志),摘要写入运行详情。 调度器本身每天也会自动跑一次,这个类型用于按需触发或换到别的时间点跑。 - **运维报表**:把「批量指令」输入框当作**报表参数**——写 `daily`(昨天日报)或 `weekly`(上周周报),可追加 `push`(生成后推送到启用的告警通道)与 `ai` (让 AI 写一段点评),如 `daily push ai`;留空或写错都按日报处理。 每个任务创建时可选择**执行范围**:「全部设备」或仅「指定分组」(下拉选择已有分组), 调度器会按执行范围过滤设备后运行;任务列表的「执行范围」列展示具体范围。 **执行计划(两种模式):** - **每 N 分钟**:按设定间隔循环执行(最小 1 分钟)。 - **每天定时**:每天到指定 `HH:MM` 执行一次,已过时间点则顺延到次日。 **页面操作:** 创建 / 启用停用 / 立即运行 / 删除;任务表格展示“执行计划、上次运行 时间与结果、下次执行时间”,每个任务失败原因也会记录在“上次详情”里。任务列表 下方是同页显示的调度器运行日志(`scheduler.log`)。 **运行机制:** - 调度器随 `runserver` 一起自动启动(浏览器打开网页服务即开始调度),每 15 秒 检查一次到期任务;不依赖任务计划程序或 `celery` 等额外组件。 - 任务执行复用网页的并行底层(采集/备份/批量),结果摘要写入 `scheduler.log` (如 `[任务 3] 巡检查询 ok: 批量执行 5 台×1 条:设备全成功 5 台,指令成功 5/5 条`)。 - 同一任务不会重复并发触发;任务执行期间删除或停用不影响已开始的该次执行。 - 机器重启后需重新启动网页服务,调度器才会恢复运行。 - 设置环境变量 `H3C_SCHEDULER_DISABLED=1` 可禁用调度器(仅用于调试/测试)。 ## SNMP 监控 「SNMP 监控」页(`/monitor/`)基于 **SNMP v2c(只读社区字)** 采集设备身份与性能, 不需要 SSH 账号密码,适合无登录凭据或只想旁路观测的场景: - **厂商自动矫正**:优先用 `sysObjectID` 企业号判定(`.1.3.6.1.4.1.9`→Cisco、 `.2011`→华为、`.25506`/`.43`→H3C),识别不到再回退 sysDescr 文本嗅探(与 SSH 版 同款规则);识别成功即覆写数据库厂商值(提示“厂商 旧→新”)。 - **身份采集并写回设备**:`sysName`→设备名称、序列号(ENTITY-MIB 通用链 + 厂商私有 OID 兜底)、`sysDescr`→系统版本(新字段,只写数据库,设备列表不加列)。 - **CPU / 内存采集**:按厂商 OID 候选链只读采集使用率(堆叠多槽取平均), 只写入监控历史表,供页面展示最新值与每台设备的迷你趋势折线图(复用 AI 巡检的 趋势图组件,最近 30 条)。 - **采集入口**:页内「开始采集」按钮可选「全部设备 / 指定分组」一键并行采集; 也可接入「定时任务」选 **SNMP 监控采集** 类型周期执行。 - 设备表单可单独配置每台设备的 **SNMP 社区字**与 **SNMP 端口**(默认 `161`);社区字 **留空 = 跟随所属分组**。「分组管理」里可为每个分组设置默认社区字,采集时按 **设备显式填写 > 所属分组 > 默认 `public`** 的优先级取用;批量编辑页也可一次性 给多台设备统一设置社区字。只读采集、绝不写设备配置;拿不到的项如实标“无法获取”,不误报。 **SNMP OID 表:** | 用途 | OID | 说明 | | --- | --- | --- | | 系统名称 sysName | `1.3.6.1.2.1.1.5.0` | 设备名称 | | 系统描述 sysDescr | `1.3.6.1.2.1.1.1.0` | 品牌 / 型号 / 版本 | | 对象标识 sysObjectID | `1.3.6.1.2.1.1.2.0` | 企业号判定厂商 | | 序列号(通用) | `1.3.6.1.2.1.47.1.1.1.1.11` | ENTITY-MIB entPhysicalSerialNum | | 序列号(H3C) | `1.3.6.1.4.1.25506.2.6.1.1.4.1.3` | hh3cEntityExtSerialNumber | | 序列号(华为) | `1.3.6.1.4.1.2011.2.23.1.1.1.1.23` | hwEntitySerialNumber | | CPU(H3C) | `1.3.6.1.4.1.25506.2.6.1.1.1.1.1.6` | hh3cEntityExtCpuUsage | | CPU(华为 VRP8 / VRP5) | `1.3.6.1.4.1.2011.5.25.31.1.1.1.1.5` / `...10.2.6.1.1.1.1.5` | hwEntityCpuUsage / hwCpuDevUsage | | CPU(Cisco) | `1.3.6.1.4.1.9.9.109.1.1.1.1.8` | cpmCPUTotal5sec(.1 为整机均值) | | 内存(H3C) | `1.3.6.1.4.1.25506.2.6.1.1.1.1.1.7` | hh3cEntityExtMemUsage | | 内存(华为) | `1.3.6.1.4.1.2011.5.25.31.1.1.1.1.13` | hwEntityMemUsage | | 内存(Cisco 池) | `1.3.6.1.4.1.9.9.48.1.1.1.5` / `.6` | 池 used/free → 百分比 | 依赖 `pysnmp-lextudio`(纯 Python SNMP 库,Windows 无需编译原生扩展); 未安装时监控页正常渲染、采集会提示“未安装 SNMP 库”,不会 500。 ## 安全联动监测(sFlow × syslog 内网安全感知) 「安全事件」页(`/security/`)把 sFlow 的「行为」与交换机 syslog 的「设备反应」按**源 IP 联动判定**:流量特征发现可疑、设备日志立即印证 → 带证据链的安全事件。纯读库判定 (不连设备),阈值全部在「监测设置」可调,后台线程每 5 分钟(可调)一轮, `H3C_SECURITY_DISABLED=1` 可整体停用。 - **六条规则**:横向移动(同源触达内网目的数超阈;端口安全/认证日志印证 → 高危)、 端口扫描(多端口 + SYN≫ACK)、暴力破解(登录失败超阈;同源又在扫远程端口 → 高危)、 ARP 欺骗(ARP 冲突日志 + 终端台账多 MAC 印证)、新增/心跳外联(外部目的:端口首见; 固定间隔小包 → 高危)、流量洪水(风暴抑制日志 + 流量超平均倍数)。 - **事件合并**:同 (类别, 源IP) 一条事件——命中次数累加、证据换最新一轮、级别取高; "已确认"的事件再命中会回到"未处理","已忽略"不再打扰。 - **证据链**:详情页展开 判定特征(触达数/端口数/SYN·ACK/间隔抖动)+ sFlow 流样本 (时间/五元组/包长/估算字节)+ syslog 行(设备/模块/事件/内容)+ 终端台账接入位置。 - **推送**:在「告警规则」建 source=安全联动监测 的规则后,事件新建/升级即推送告警中心 (通道复用);无规则只入库展示。 - **基线与白名单**:内网范围 = RFC1918 + IPAM 已规划网段;首次启用第一轮只建外联基线 不报警;白名单(IP/CIDR)豁免授权扫描器/网管机/DNS/NTP/备份服务器。 - **边界**:sFlow 是 1:N 抽样——规模性行为靠流量特征,低速渗透靠 syslog 规则兜底; 日志关键字先按通用+H3C 校准,其它厂商逐步补;平台不自动下发任何处置命令, 封禁/隔离走「命令模板 → 变更工单」。 实现落点:引擎 `device_console/security_monitor.py`,模型 `SecurityConfig / SecurityWhitelist / SecuritySeen / SecurityEvent`(迁移 0081–0083),告警接入 `alerting.evaluate_security`,页面 `security_center.html / security_event_detail.html / security_settings.html`,驾驶舱「安全与合规」看板追加 3 个安全组件,守护测试 `test_security_monitor.py`。 ## 监控大屏 「监控大屏」页(`/bigscreen/`)提供一屏总览,每 60 秒自动刷新: - **设备数量详情**:顶部统计卡把台账分成三块 — **网络设备(SNMP)**、 **服务器(主机监控)**与**交换机遥测(推送)**各自计数,外加在线/离线数、网关/接入/未设置角色计数, 并按分组统计设备数。 - **在线情况**:复用运维工具箱的 Ping 探测逻辑(`h3c_scan.ping_host`,单设备 1.5 秒 超时,绝不抛异常),并发线程池对全部设备逐台 Ping,结果写回 `Device.online` 与 `last_online_at`。 - **CPU / 内存情况**:复用 SNMP 监控采集(`snmp_monitor.collect_all`,内部走 `h3c_snmp.fetch_info` 只读 GET/WALK),结果写入现有 `SnmpMonitorRecord` 历史表, 大屏展示每台设备最新一次的 CPU/内存百分比(<70% 绿、70–90% 橙、≥90% 红)与 最近采集时间,并汇总 SNMP 成功台数与平均 CPU/内存。SNMP 采集只针对**网络设备** (`catalog.supports_snmp`):服务器的指标走下面「服务器健康」那块,对服务器发 SNMP 只会攒一堆失败记录,看着像故障其实是口径不对。 - **历史曲线**:大屏下方「历史趋势」区直接以折线图展示累计的 `SnmpMonitorRecord` 历史 — 每台设备最近 30 条采集的 CPU/内存走势,以及按采集批次聚合各设备的 **平台平均 CPU/内存**曲线(曲线复用 AI 巡检的 `ai_inspect.trend_svg` 零依赖 服务端 SVG 生成,采集不足 2 次时显示“数据不足”)。 - **服务器健康**(有服务器时独立成块):健康分档统计卡(正常 / 警告 / 严重 / 离线 / 未采集,外加 Agent 上报数、SSH 采集数与平均 CPU / 内存),每台服务器一行给出健康档 与判定理由、分类与系统、CPU / 内存 / 磁盘进度条(按 85% / 95% 阈值着色)、数据来源与 采集时间,点主机名进「主机详情」;下方同样有**每台服务器最近 30 条指标的 CPU / 内存 走势**与按分钟聚合的**服务器平均曲线**。这一块只读 `HostMetric`(Agent 上报与 SSH 采集写进来的同一张表),大屏自己不登录服务器。 - **主机体检**:后台监测线程按「大屏设置」的间隔调用 `big_screen.run_host_check()` — 只读库里每台服务器最新一条指标做健康判定,命中「告警规则(来源=服务器主机指标)」 就生成告警中心事件并沿规则通道推送;其中**数据过期**判定只能靠这一步(机器不再上报 时没有任何新数据可判)。「⚡ 立即刷新检测」与设置页的「立即执行一次监测」也会带上它, 提示语给出体检台数、严重 / 警告 / 离线分布与新增告警条数。 - **交换机遥测健康**(有遥测数据时独立成块):设备主动推、平台不发起采集,所以这一 块只读 `TelemetryMetric` — 健康分档统计卡(正常 / 警告 / 严重 / 中断 / 未抽到指标, 外加平均 CPU / 内存、最高温度与指标总条数),「最需要关注」表逐台给出健康档与判定 理由、CPU / 内存进度条(按 85% / 95% 阈值着色)、温度与最后推送时间;逐台趋势图与 接口错包明细在「遥测数据」页看。 - **遥测体检**:后台监测线程按「大屏设置」的间隔调用 `big_screen.run_telemetry_check()` — 只读每台设备最新一批遥测指标做健康判定(阈值 + 接口错包增长 + 推送中断),命中 「告警规则(来源=交换机遥测指标)」就生成告警中心事件并沿规则通道推送;其中 **推送中断**判定只能靠这一步(交换机停推后没有任何新数据可判)。「⚡ 立即刷新检测」 与设置页的「立即执行一次监测」也会带上它,提示语给出体检台数与严重 / 警告 / 中断 分布。 - **应用监控(全链路)**:一块独立的应用视角——按健康档排序列出应用(默认前 8 个), 每行把**服务**(Agent 的端口/HTTP/进程检查)、**服务器**(CPU·内存·磁盘与数据新鲜度)、 **交换机端口**(人工绑定,看设备在线与接口错包)、**系统告警**(关联对象的告警记录)、 **Syslog**(该 IP 最近日志)五段的状态并排显示,鼠标悬停看每段说明; 综合档由五段就高合成,**「未知」是「看不到」而不是故障**(没配检查项、端口没接遥测、 本来就不发日志)。「应用体检」由后台线程按间隔调用 `big_screen.run_app_check()` — 只读库、不连任何设备、不发起探测,命中「告警规则(来源=应用监控)」就生成 告警中心事件。应用与端口绑定在「应用管理」页维护。 **监测开关与间隔在「大屏设置」页(`/bigscreen/settings/`)统一配置**: 「在线监测(Ping)」、「资源监测(SNMP)」、「主机体检」、「遥测体检」与「应用体检」 五项各自的开/关与间隔(1–1440 分钟)独立设置,保存后由随 `runserver` 启动的后台监测线程 按间隔自动执行(首次启动立即执行一次,五项共用一把忙锁、互不叠加);也可点页内按钮 **立即执行一次监测**,或在大屏页点「⚡ 立即刷新检测」。 后台线程默认启用,设置环境变量 `H3C_BIGSCREEN_DISABLED=1` 可禁用(调试用)。 ## 运维驾驶舱 「运维驾驶舱」页(`/dashboards/`)把平台已有的统计与明细**拼成一块深色值班看板**, 和「监控大屏」的分工是:大屏是固定版式的"检测 + 明细"页(含监测开关与执行入口), 驾驶舱是**可自由拼装的只读展示**,看板数量、每张看板放什么、放多大、多快刷新都由页面上定。 **一屏铺满、不用滑动**:驾驶舱高度锁在视口里(加载后按站点头部真实高度精算),组件栅格 每行等分剩余高度——整页高度正好一屏,没有纵向滚动条;图按面板高度等比缩放,明细列表在 **面板内部**滚动。内置看板按 12 栅格 × 3 行挑组件(每行合计正好 12 列),一屏放得下又有 可读性;加更多组件也能容纳(面板变矮,靠缩放/内滚消化)。窄屏(≤1100px)自动退化成 可滚动的流式布局,不把图挤成一条线。 - **多张看板**:顶部标签页切换(地址带 `?board=`,可直接收藏);迁移时预置四张 — 「总览驾驶舱」(默认打开)、「网络运行」、「服务器与应用」、「安全与合规」, 每张看板的组件顺序都按 12 栅格排满整行。 - **31 个组件**,分三类:**指标卡**(设备总览 / 告警总览 / 任务总览 / 服务器健康 / 应用健康 / 镜像流量 / 交换机遥测 / 合规通过率 / 活跃漏洞 / IPAM / 备份覆盖 / 接入终端 / 无线总览)、 **趋势图表**(设备类型分布、厂商分布、告警趋势、告警来源 TOP、告警级别分布、 网络设备与服务器 CPU/内存趋势、服务器资源 TOP、流量 TOP 会话、日志趋势、 任务类型分布、拓扑风险概览)与**明细列表**(最新告警、最近任务、最近操作、最新日志、 离线设备、最近巡检)。 - **点选式编辑**(`/dashboards/settings/`):加组件按分类点一下即加;每行可 `↑ ↓` 调序、 选宽度(1/4~整行)、改标题、配参数(时间窗 6/24/72/168 小时、条数 5/8/10、设备分组、 服务器 TOP 的指标 CPU/内存/磁盘);看板可改名、排序、设默认、单独设刷新秒数(0 = 不自动刷新)、 删除;看板删光后能一键恢复内置四张。 - **值班体验**:一屏铺满不滚动(见上);右上角走时钟;`↻ 刷新` 立刻取数,自动刷新只替换 内容区(不整页白屏);`⛶ 全屏`(或按 `F`)把驾驶舱铺满整屏,可用高度更大、组件更舒展。 - **只读、不采集**:数字全部来自已有采集与后台监测的结果表(SNMP 记录、主机指标、遥测、 sFlow、告警、任务、审计…),看板自己不连设备;单张图至少需要两次采集才画得出来。 - **权限与数据范围**:登录即可看;建/改看板需要运维(operator)及以上权限,浏览者只读且 看不到设置入口;地区受限用户只统计范围内对象(设备/告警/日志/网段/终端的收窄口径与 REST API `/api/v1/summary/` 一致)。看板类增删改都写操作审计。 - **零前端依赖**:图表是服务端渲染的 SVG(`charts.py`,全站换深色主题后默认按深色底配色, 需要浅色可显式传 `theme="light"`),不引入任何前端图表库。 实现落点:注册表与取数 `device_console/dashboards.py`,页面与设置页 `templates/device_console/dashboards.html`、`dashboard_settings.html`(组件局部模板在 `dashboards/` 子目录),模型 `Dashboard` / `DashboardWidget`(迁移 0077 + 0078 预置), 守护测试 `test_dashboards.py`。 ## 拓扑分析(LLDP 结构体检) 「网络拓扑」页画的是按分组分区的示意总线图,排障时真正要问的是**结构问题**。「拓扑分析」页 (`/topology/analysis/`,从「网络拓扑」页顶部标签进入)把上一次 LLDP 采集结果当成一张 无向图,**只读库、不连设备**,算出结构统计、明细清单与一份按严重程度排序的风险清单。 页面顶部可按分组筛选(`?g=<分组主键>`,`?g=0` 只看未分组),导出文件名带上分组后缀。 - **怎么建图**:以设备库里的设备为点,用 LLDP 邻居的**对端名称或管理 IP** 去匹配库内 设备连成边,但**只认同一个分组里的设备**;同一条链路两边都报上来时合并成一条 (无向去重)。对端在别的分组 → 单独进「跨分组链路」(不连线、不计入度数); 库里完全对不上号 → 进「未识别邻居」;只有一边报上来的进「单向链路」。 只看一个分组时,索引仍覆盖数据范围内的全部设备,所以「对端在别的分组」不会被 误判成「未识别邻居」。 - **统计卡**:设备数 / 链路数 / LLDP 邻居总数、网关与接入台数、孤立设备数、汇聚点数、 连通分量数与其中成环的个数、单向链路数、未识别邻居数、跨分组链路数、角色未设置数、离线网关数、 最大度数、过期记录数,以及**最早 / 最近一次采集时间**。 - **明细清单**(每类最多列 20 条,其余只给计数): - **孤立设备**:一个已知邻居都没有——没采到 LLDP、真的没连线,或对端设备未纳管; - **汇聚点 / 度数排行**:邻居数 ≥ 3 算汇聚点,度数排行告诉你「谁挂了最多东西」; - **单向链路**:只有一边报上来,通常是对端没开 LLDP,或采集时漏了一台设备; - **未识别邻居**:对端在设备库里对不上号(未纳管的交换机、服务器网卡,或设备名与库里不一致); - **跨分组链路**:对端设备在库里、但属于别的分组——两端分组与接口都列出来, 便于判断是分组划分要调整还是确实存在跨组互联; - **设备名重复**:同一个设备名在库里出现多次(标出是否跨分组)。拓扑按名字认对端, 重名会误连或漏连,建议改名或让设备把对端管理地址报全; - **连通分量**:设备被分成几块互不相连的部分,每块给出点数 / 边数 / 是否成环与前几个 设备名;**边数 ≥ 点数即判定该分量存在环**(双上联冗余正常会有环,需确认 STP 已开启); 连通性风险按**分组内部**判定(分组隔离后「整张图不连通」是常态,只有某个分组里 既有链路、又有互相连不上的设备时才算问题); - **LLDP 数据过期**:超过 7 天没更新的邻居记录,并附最早一条的采集时间; - **角色未设置 / 离线网关**:没设角色的设备拓扑总线图画不出来;网关离线会让下挂接入整片失联。 - **风险清单**:上面这些按「高 → 中 → 低」排序成一份可直接照做的清单——高:没有任何 LLDP 数据(提示先去采集)、网关交换机离线、孤立设备超过半数;中:孤立设备、单向链路、 未识别邻居、跨分组链路、设备名重复、拓扑存在环路;低:拓扑不连通(分组内部)、 LLDP 数据过期、设备未设置角色。规则都是 「有数据才提示」:一条 LLDP 都没有时只会提示去采集,不会把所有设备都说成孤立点。 - **导出**:`?format=json`(完整结果,给第三方系统或 AI 用)、`?format=csv`(类别 / 级别 / 对象 / IP / 说明,UTF-8 带 BOM,Excel 直接打开不乱码)、`?format=md`(可直接贴进值班群 或周报的 Markdown)。 - **数据范围**:跟随登录用户的地区权限(`authz.scope_devices`),限定地区的账号只看到自己那片网; 再叠加分组筛选时,`scope.group` 会标出本次体检的分组,`scope.unrestricted` 相应变为 false。 - **同一份结果多处复用**:页面、三种导出与「AI 助手」的平台快照用的是同一个 `topology_analysis.analyze()`,不会出现「页面上一个数、AI 说另一个数」。 ## 设备分类层级(网络设备 / 服务器 / 机柜其他设备) 设备不再是「一堆交换机」,而是按**大类 → 类型**两层管理,机柜里没有 IP 的东西单独一层: | 大类 | 类型(`Device.kind` / `RackAccessory.kind`) | 说明 | | --- | --- | --- | | 网络设备 | 交换机(默认)、路由器、防火墙、无线控制器、其他网络设备 | 有 IP 与 SSH / SNMP 账号,参与采集、巡检、备份、合规、拓扑 | | 服务器 | 物理服务器、虚拟化服务器 | 有 IP 与 SSH 账号,可网页 SSH 登录、被 Agent / SSH 探测监控(见「服务器监控与主机 Agent」) | | 机柜其他设备 | 配线架、理线槽、机柜 PDU、KVM/控制台、其他 | 记在 `RackAccessory` 表,没有 IP 与账号,只占机柜 U 位、只做资产与 3D 展示;属性可从**配件型号库**(`AccessorySpec`)引用 | - **历史数据零影响**:`category` 默认 `network`、`kind` 默认 `switch`,老库里所有设备 自动就是「网络设备 · 交换机」,既有采集 / 巡检 / 备份 / 拓扑流程一行都不用改。 - **设备列表页**按大类分标签(网络设备 / 服务器 / 机柜其他设备),每个标签内再按类型 给出数量与筛选 chips;「类型」列直接显示中文标签,机柜配件在同一页用表单增删改 (选机柜 + 起始 U + 占用 U 数,冲突即拒绝保存),属性可从页内「配件型号库」引用。 - **设备表单**里大类与类型是联动下拉(选了「服务器」就只列物理 / 虚拟化服务器), 另有「操作系统」字段(Linux / Windows / 其他),填了它即使是网络设备也会按通用 shell 连接(见 `device_console/device_catalog.py` 的 `uses_generic_shell`)。 - **能力判定集中在一处**:`device_catalog.py` 只有常量与纯函数(不查库), 页面、CSV 导入、采集编排与测试都复用它——`is_server` / `is_network` / `is_wireless_controller` / `supports_ssh` / `supports_snmp` / `uses_generic_shell`; CSV 导入的「大类 / 类型 / 操作系统」列支持中英文别名归一(如「物理机」「VM」 「防火墙」「无线AC」都能认)。 - **U 位视图与 3D**:`device_catalog.u_rows()` 把设备与配件合成一张按 U 排列的表 (`(u, 设备, 配件, 跨U数)`),机房详情页与 3D 机房都基于它渲染,配件跨 U 时 被盖住的格位显示为空;`u_conflict()` 是设备与配件共用的唯一冲突判据。 - **配件型号库(属性一处定义、可重复引用上架)**:配线架 / 理线槽这类东西往往一次 上架十几件、属性完全一样,逐件重填既慢又容易填错。「设备列表 → 机柜其他设备」 标签页下方的**配件型号库**(`AccessorySpec` 表)把 型号名称 + 类型 + 型号 + 端口数 + 默认占用 U 数 + 图标 + 备注 只存一份(**同名型号只能有一份**,否则引用 就没有单一出处);上架配件时在「引用型号」里选它即自动带出全部属性,仍可单件 覆盖(覆盖只作用于这件配件,不会写回型号)。型号库里**不含机柜与 U 位**——那些 属于每一件实物,所以「重复引用」=多件实物共用同一份属性、各占各的 U 位, 而不是一件实物被上架两次;配件行另有「复制上架」(带出这件的属性,换机柜 / U 位 再登记一件同款)与「存为型号」(把已有配件的属性收进型号库)两个快捷入口。 配件列表的「引用型号」列会标出每件配件引用的型号名(未引用显示「手工登记」), 型号库表格则显示每个型号「被引用」多少件。 - **改型号后一键同步**:型号属性改了,点「同步」把新属性推给所有引用它的配件 (**不动**名称、机柜与 U 位;某件配件改了占用 U 数会越顶或撞到别的东西时, 该件只同步其余属性、占用保持原样,并在提示里列出是哪几件)。删除型号只**解除 引用**(外键 `SET_NULL`),已上架的实物一条都不会少、U 位照旧。型号的增删改与 同步都进「操作审计」(对象类型 `dc`)。 - **同柜同名拦截**:一件实物只占一个 U 位,同一机柜内配件名称重复就是重复录入, 保存时直接拒绝并提示用「-2」这类后缀区分;不同机柜允许同名(是两件实物)。 ## 机房管理 「机房管理」页(`/dc/`)提供四层位置体系的增删改查与设备 U 位绑定: - **楼栋 → 楼层 → 机房 → 机柜**:每层可新增/编辑/删除(删除上层级会计数联动、 删除机房级联删除其中机柜,删除机柜自动解除设备绑定);机柜可跨 U 位高度配置 (默认 42U),每间机房定义摆放网格尺寸(默认 6 行 × 8 列)。 - **同一机房内机柜名称唯一**:楼栋 / 楼层 / 机房 / 基础设施早就有重名拦截,机柜这一层 此前漏了——同机房两个同名机柜会让 U 位视图、3D 机房与「设备 / 配件归属」都分不清 是哪一柜。现在「机房管理」页的快捷新增与机柜表单(含改名、换机房)都会拦,数据库 也补了唯一约束 `uniq_rack_room_name`(不同机房之间仍允许同名)。老库里已有的重名 机柜会在升级时自动改成「原名-2 / 原名-3」(id 小的保留原名),迁移输出里逐条列出 改名清单;改名只动名称,设备与配件绑定(走外键 id)、U 位、平面布局坐标都不受影响。 - **U 位绑定**:在机房详情页(`/dc/room//`)把未绑定设备放入某机柜的某个 U 位 (1=最底层,须在 1–u_units 之间且同柜同 U 不重复);机柜内以折叠式 U 位视图按 编号从高到低展示已绑设备(按在线状态着色),也可在「设备表单」里直接选择 所属机柜与 U 位,或一键解绑。 - **机柜配件也占 U 位**:配线架 / 理线槽 / 机柜 PDU / KVM 这些没有 IP 与账号的东西 记在 `RackAccessory` 表(类型 + 名称 + 机柜 + 起始 U + 占用 U 数),在 「设备列表 → 机柜其他设备」标签页登记与维护,与设备共用同一套 U 位冲突校验 (同柜同 U 被设备或别的配件占了就拒绝保存);机房详情页的 U 位视图、3D 机房的 U 位详情都会把它们画出来(配件按跨 U 数占格)。配件不参与 SSH / SNMP 采集、 巡检与备份,只用于机房 U 位展示与资产统计。同款配件(如一整柜的配线架)可在页内 「配件型号库」把属性定义一次、再被任意机柜任意 U 位的配件重复引用上架,同一机柜内 名称不允许重复,详见「设备分类层级」。 - **机柜屏幕布局**:机房详情页点「机柜屏幕布局」进入 2D 网格编辑器 (`/dc/room//layout/`)—— 侧边列出未摆放机柜,点击选中后点网格空位放置, 也可直接拖拽已摆放机柜换位;每柜可切换朝向(0°/90°),「保存布局」把 `机柜 id → 行列 + 朝向` 提交回本页(越界/同格冲突会被拒绝)。 - **基础设施位置可编辑**:机柜网格外圈多出一格**走廊**(坐标范围 `x ∈ [-1, cols]`、`y ∈ [-1, rows]`,外圈即走廊),UPS 电源 / 精密空调 / 配电柜 / 机房大门 / 玻璃门 / 其他设施在左侧「基础设施」面板里选类型 → 点走廊格子放下, 每块可旋转朝向(0°/90°/180°/270°)、删除,也可「按机房尺寸生成默认布局」一键铺好; 保存时机柜布局与基础设施布局一起提交(存在 `RoomInfra` 表,门类会自动吸附到墙面)。 3D 机房完全按这份数据渲染,门的位置还决定前墙 / 左墙的开洞位置;机房还没摆机柜时 3D 页会用内置预设(`preset`)先给出一个可看的场景。 - **3D 机房展示**(`/dc/room//3d/`):Three.js 渲染(`three.min.js` 已随仓库 内置,离线可用),按机柜屏幕布局自动生成,机柜网格四周留出走廊摆放基础设施: - **场景与基础设施**:防静电地砖地面、四面半透明墙体(前墙开玻璃门洞、左墙开 大门洞)、顶部灯带、投影光照与雾效;**UPS ×2、精密空调 ×3(风扇持续转动)、 配电柜(黄黑警示条 + 空开)、玻璃门(双开钢化玻璃 + 拉手)、机房大门 (双开金属门 + 安全出口指示)、机柜上方桥架**;鼠标悬停任意基础设施可看用途 说明,点击机柜弹出摘要气泡。 - **全屏**:右上角「⛶ 全屏」(或按 `F`)把整个 3D 舞台 + 右侧信息栏铺满屏幕, 当机房大屏用;再点一次或 `Esc` 退出,切换后自动重算画布尺寸与相机比例。 - **健康状态(与监控大屏同口径)**:网络设备取 `Device.online`(Ping 监测)+ **最新一条** `SnmpMonitorRecord`;CPU/内存 ≥90% 判「严重」、≥70% 判「偏高」、 设备离线判「离线」、在线但没有采集记录判「无数据」。机柜里的**服务器** (大类=服务器,或档案里填了操作系统)改取**最新一条** `HostMetric`,按 `host_agent.health()` 的主机体检口径判档——CPU / 内存 / 磁盘阈值 + 每核负载 + 超过 30 分钟没有新数据判「离线」(`crit` 对应 3D 的「严重」),没有主机指标时 仍回落到 SNMP,所以服务器不跑 SNMP 也不会整柜显示「无数据」。机柜取其中 **最差档**,没绑设备为「空机柜」。机柜顶部灯条、地面健康光晕、U 位贴片、 机柜列表圆点与汇总卡片统一配色(汇总里另有「服务器(主机监控)」台数), 严重/离线机柜的光晕呼吸闪烁;设备范围跟随登录用户的 数据权限(`authz.scope_devices`)。 - **动态播放(自动巡检)**:点「▶ 自动巡检」后每 6 秒切到下一个机柜——镜头推到 该机柜正面、右侧同步展开它的 U 位详情、底部字幕显示「巡检 3/6 · A03(42U)· 设备 4 台 / 在线 3 · 健康 正常」;顶部滚动条持续滚过全部机柜的设备数 / 在线数 / 资源峰值(CPU / 内存 / 磁盘取最高)/ 健康档,并先给一行机房汇总。 鼠标一拖拽就接管视角并停止巡检; 另有「🔄 环绕旋转」只转镜头不换机柜。快捷键:`F` 全屏、`空格` 巡检、`R` 复位。 - **点击机柜看全部 U 位**:右侧「机柜 U 位详情」从最高 U 到 U1 逐格列出—— 有设备的 U 位显示**设备图标**、名称、IP / 型号、CPU 与内存进度条、健康标签, 服务器再多一条**磁盘**进度条、名称前的「主机」小标与指标来源 / 采集时间 (Agent 上报 / SSH 采集);空 U 位显示为灰色占位格;绑了机柜但没填 U 位的 设备在列表末尾单独提示。 - **数据刷新**:页面每 60 秒拉一次 `/dc/room//3d/data/`(也可点「⟳ 立即刷新」), 只重算颜色与面板文字、不重建 3D 场景;右上角显示「更新于 hh:mm:ss」, 失败时提示「刷新失败」而不打断展示。 - **设备图标库**(`/dc/icons/`):上传自己的设备图片(png / jpg / jpeg / gif / svg / webp, 单个 ≤2MB、名称唯一,建议正方形透明底),在「设备表单 → 设备图标」里为设备选用, 3D 机房的 U 位详情即按图标展示,未选图标的设备用健康色块占位。删除图标会同时删掉 磁盘文件,引用它的设备自动变为「无图标」(外键 `SET_NULL`,不会连带删设备)。 上传内容不经静态目录直出,而由登录态视图 `/dc/icons//file/` 输出(未登录不放行); 上传/删除写入操作审计(对象类型 `device_icon`),只读角色(viewer)被中间件拦成 403。 ## 设备巡检 「巡检中心 · 设备巡检」页(`/inspect/`)通过 SSH 登录交换机,用**只读指令**(`display` 系列) 采集健康指标并生成报表。支持**手动巡检**、**历史批次回看**与**定时任务**三种入口, 巡检历史保存在数据库,可导出 CSV(UTF-8 带 BOM,Excel 直接打开中文不乱码)。 **巡检内容(每台设备一次连接,顺序执行):** | 指标 | 指令 | 说明 | | --- | --- | --- | | CPU 使用率 | `display cpu-usage`(解析不出自动回退 `display cpu`) | 兼容 V7 百分比句式、V5 `CPU busy rate`、V7 槽位表 | | 内存使用率 | `display memory` | V7 `FreeRatio`(空闲比例→换算已用)、V5 `Used Memory Rate` | | STP 状态 | `display stp` + `display stp brief` | 启停状态、模式(MSTP/RSTP/STP)、转发/阻塞端口数 | | 接口错误包 | `display interface` | 按接口统计 input/output errors 与 drops,只列出有错误的接口 | **思科设备**自动改走 `show` 系列等价命令:`show processes cpu`(解析 `CPU utilization for five seconds: N%`)、`show processes memory`(解析 `Processor Pool Total/Used`)、`show spanning-tree`(协议模式与 FWD/BLK 端口 按 `\bFWD\b` 等词计数)、`show interfaces`;解析不到的字段标「未解析」,不报错。 **健康判定:** CPU/内存 ≥80% 提示“偏高”(warn),≥90% 判定**不健康**; STP 未启用、存在错误包的接口判定不健康;解析不出个别指标时如实标注“未解析” (不影响整体巡检结果)。每台设备给出「健康 / 异常 / 连接失败」结论与问题清单。 **报表与历史:** 巡检结果按“批次”归档(同一次巡检共用批次号),页面默认展示 最近一次,也可在「历史巡检」列表按批次回看任意一次;「导出 CSV」可下载当前批次 或指定批次报表(列:设备 / IP / 巡检时间 / CPU% / 内存% / STP 状态 / STP 模式 / 转发端口 / 阻塞端口 / 错误接口数 / 错误包总数 / 健康 / 问题)。 **定时巡检:** 在「定时任务」页选择任务类型「设备巡检」即可按计划周期巡检 (每 N 分钟或每天定时),执行结果摘要写入 `scheduler.log` (如 `巡检 5 台:健康 5 台`)。巡检只读不改配置,可放心定时执行。 ## 自定义巡检与解析规则库(自升级) 解析能力的沉淀从**日常 AI 巡检**开始,无需先手工建巡检项: 1. 你在「AI 巡检」页说"帮我做一次 STP 的巡检"→ AI 生成命令 → 确认下发 → AI 解析; 2. 解析完成时**自动蒸馏**:把本批次尚无规则的 (厂商×命令) 逐条蒸出「可复用解析规则 + 健康判定」,并在原样本上**自校验**——回放结果与 AI 自己的解析不一致的规则一律拒绝 入库(同一份回显被拒过会记缓存,不再重复浪费 AI);无法沉淀规则的自由文本也会如实标注; 3. 页面横幅显示「解析规则沉淀:N 个 厂商×命令 组合,已入规则库 M 条」,并提示 **把这次巡检保存为自定义巡检项**(名称/标识可改,命令按批次内厂商自动落键); 4. 保存后到「自定义巡检」页即可立即执行,或建 `自定义巡检` 类型定时任务定时跑—— 之后同样的命令走规则库**纯代码解析**:毫秒级、零 AI 成本、结果可回归; 5. 设备固件升级导致格式变化 → 规则连续失败 3 次自动停用 → 回退 AI 重新蒸馏。 **命令自动修正(AI 巡检与自定义巡检共用)**:分两层—— - **命令预检(事前)**:正式下发前,先在每厂商一台代表设备上试跑整份命令清单, 报错命令连同设备回显(含 ? 帮助与 ^ 位置指示)交给 AI 修正,逐条过只读白名单 后替换进清单并**复测**,循环到全部通过(最多 3 轮)才正式巡检——AI 第一轮修错 了也能被下一轮复测抓住再修。修正常被 AI 巡检解析成「命令报错」的误报由此消除。 - **逐台兜底(事后)**:个别设备型号差异导致的运行时报错,把「失败命令 + 设备 报错回显」交给 AI 修正、过白名单后原路重试一次。 两层的成功修正都沉淀到命令修正库(`CommandFix`):同厂商同样的坏命令下次执行前 直接替换——第一次报错,之后不再报错也不再花 AI。修正后仍报错会如实标注,绝不掩盖; 每轮修正命令必须逐条通过 ai_policy 只读白名单(内置底线),自动修正绝不可能成为 写操作的旁门。命令级报错只出现在回显的 [错误] 行里,不再被误标成「连接失败」。 「自定义巡检」(导航「巡检与合规 → 自定义巡检」)也支持完全手工创建巡检项 (每项 = 厂商命令集 + 设备范围);「解析规则库」页可查看每条规则的正则与留存样本、 命中/失败计数,可停用/启用/删除——AI 打底,人可兜底。内置「OSPF 状态巡检」 (邻居应全部 Full)与 6 条已真机校准的 CPU/内存种子规则,列表页一键初始化。 ## AI 巡检 「巡检中心 · AI 巡检」页(`/inspect/ai/`)把“需要看什么”用自然语言描述出来,由 AI 生成具体的 巡检命令,人工确认后下发,再用 AI 把回显解析成结构化数据——适合固定巡检(CPU/内存/STP) 覆盖不到的自定义检查项(如光纤接口收发光功率、风扇状态、电源冗余、BGP 邻居等)。 使用「AI 配置」中当前激活的模型,调用 `ai_client.chat`(OpenAI 兼容接口),无新依赖。 **完整流程(页面按步骤操作):** 1. **① AI 生成巡检命令**:填写自然语言需求(如“查看各接口收发光功率和错误”)、 勾选设备(分组筛选+全选本组,同批量执行页),可选勾选「生成表格数据」「保留历史 趋势」→ 提交后 AI 生成**只读 display 查询命令**回填命令框。 若 AI 生成的命令包含非 `display` 开头的指令,页面会黄色提醒“非只读”要求谨慎核对。 思科设备在 AI 提示中已约束只生成 `show` 系列(`show` 开头在白名单内,可正常下发)。 2. **② 确认并下发(自动 AI 解析)**:人工核对/编辑命令后点击一次即可——按设备**并行** 下发采集(并发可设,每台设备内部命令顺序执行,复用批量执行底层,写入 `log.txt` 与指令历史),采集完成会自动调用 AI 把每台回显逐台解析为结构化数据 (小并发 ≤3;未配置可用 AI 模型时仅完成下发并提示,配置好后可点「重新解析」补解析)。 连接失败在页面上明确标注。 3. **③ 结果展示(先汇总后明细)**:卡片顶部先展示「汇总信息」——整批的状态计数 (健康/异常/未评定/解析失败/连接失败)+ 每台设备的概览表(状态、AI 概述、指标数、 表格、问题数),下方再逐台展开详情:健康徽章、AI 概述、指标 KV 表(带 ok/warn/error 状态)、可选明细表格、问题清单与原始回显。 4. **重新解析与历史趋势**:解析失败/连接失败可点「重新解析」(仅重调 AI,不重新下发, 覆盖旧结果);勾选了「保留历史趋势」时,每个数值指标会按历次巡检取值绘制 **折线图**(服务器端 SVG 生成、零依赖,含 min/max/avg 统计),不足 2 次时提示 “历史数据不足”。 **结构化解析的 JSON 约定(AI 严格按此输出,页面容错清洗):** ```json { "healthy": true, "summary": "一句话总体情况(中文)", "metrics": [{"key": "cpu", "name": "CPU使用率", "value": 12, "unit": "%", "status": "ok"}], "table": {"columns": ["接口", "输入错误"], "rows": [["GE1/0/1", "2"]]}, "issues": ["问题描述"] } ``` **注意事项:** - **只读安全**:AI 生成的命令应为 `display` 查询类;非只读命令会提醒。建议人工核对 命令列表后再下发,不要下发 reset / save / shutdown 等写操作命令。 - **长回显不丢内容**:单台设备的合并回显**完整落库**(默认不截断,需要控制库体积时设 `H3C_AI_INSPECT_KEEP_CHARS`,被截断时回显尾部会有明确标记)。回显超过送 AI 的 预算(`H3C_AI_PARSE_INPUT_CHARS`,默认 24000 字符)时,按**行边界**切成多段分别 解析再把结果合并(指标按 key 去重、表格按同结构拼接、问题去重),最多解析 `H3C_AI_PARSE_MAX_SEGMENTS` 段(默认 6);未能覆盖的内容会在问题清单里如实说明 “未送 AI”,不会被悄悄丢掉。页面上长回显按行分页浏览,并可「下载完整回显(.txt)」 拿到全文。 - **token 消耗**:生成命令 1 次 + 每台设备解析 1 次调用(随确认下发自动进行); 回显超预算时按段数成倍增加;解析异常可点「重新解析」重试(会再次消耗 token)。 - **趋势图要点**:只有 `value` 为数值的指标才参与画图,且同一指标的 `key` 在各次巡检中 需保持稳定(AI 提示已约束),否则无法串成一条趋势线。 - **历史管理**:批次与结果全部入库,可回看、可删除(删除级联清理回显与解析结果)。 ## 合规检查 「合规检查」页(`/inspect/compliance/`)按**内置安全加固策略**对交换机配置逐项判定 合规,对不合规项给出修复指令,可选 AI 按设备实际违规生成,人工核对后可按设备批量 下发(调用批量命令底层)。全程零新依赖,规则判定为本地纯函数,AI 只用于生成修复指令。 **思科设备自动改用 `show` 系列等价命令与独立判定规则**(见上「多厂商支持」)。 **检查流程(页面按步骤操作):** 1. **① 执行合规检查**:先选**判定依据**,再勾选设备(分组筛选+全选本组)与策略 (默认全选)→ 平台把所选策略的判定命令**去重合并**,按选定的依据判定每条策略归属 「通过 / 违规 / 无法检查」,结果入库(命令不支持或采集失败记为“无法检查”,不误判合规)。 两种判定依据: - **在线采集**(默认):对每台设备**一次 SSH 连接采齐**全部只读 `display` 类命令, 不动设备配置;结论反映设备**当前运行状态**。 - **配置文件**:直接读**已备份的配置文件**判定,**完全不连设备**,速度快、可用于 设备不可达或不想登录的场景。原理是:内置策略里 `display current-configuration | include X` 读的就是**运行配置**,而备份文件正是 `display current-configuration` 的完整回显——按同一关键字过滤出的行与在线回显**等价**,因此判定复用同一套规则, **配置类策略的结论与在线检查完全一致**(有专门的测试锁住这条等价性)。 离线扫描如实标注边界:**备份文件里只有配置、没有运行态**,所以「时钟是否已同步」 (`display ntp status`)、「端口安全运行时状态」(`display port-security`)这类策略 会记为**「无法检查」**并提示改用在线采集;NTP 是否**配置了服务器**属于配置事实, 仍能明确判定。每台设备取**最新一份**备份,结论里标注依据的备份文件名;**没有备份 文件的设备**记为「无法检查」并引导先去「配置备份」页备份一次——绝不用别的设备或 旧日期文件顶替。历史记录里每批都标注本批用的是哪种依据。 2. **结果汇总与矩阵**:顶部徽章展示整批「共 N 项 / 通过 / 违规 / 无法检查 / 待修复」, 设备×策略矩阵表用 ✓ / ✗ / · 一眼看出哪台设备哪项不合规;下方按设备展开每条策略的 判定结论与关键回显。 3. **修复指令**:每条违规项预填**静态修复指令**(文本框可编辑;个别需要设备上下文的 如接口名、NTP/日志服务器地址以 `# 请替换` 占位提示)。可点「AI 生成修复指令」让 AI 按该设备该项的**实际违规回显**生成修复命令(需先在「AI 配置」设为当前模型),也可点 「AI 生成全部修复指令」整批生成(跳过已修复项);AI 只生成不执行,人工核对后下发。 4. **下发修复(批量命令)**:单条点「下发修复」,或点「下发全部修复指令(批量)」—— 平台把该批次所有待修复项**按设备聚合**,每台设备**一次连接顺序执行多条修复命令** (多台设备并行),逐条写入指令历史与 `log.txt`;连接失败的设备保持“待修复”便于重新 下发,已修复项自动跳过。`#` / `!` 注释行与行内注释(` # xxx`)在下发时自动忽略。 **内置策略(11 项):** | 策略 | 判定依据 | 修复要点 | | --- | --- | --- | | 禁止 Telnet | `display telnet server status` 为 Disabled | `undo telnet server enable` | | 启用 SSH 远程管理 | `display ssh server status` 为 Enabled | `ssh server enable` | | SNMP 禁止默认团体字 | `include snmp-agent community` 中无 public/private | 删除默认团体字并配置强团体字 | | DHCP Snooping | 全局 `dhcp snooping enable`(建议上联口 trust) | `dhcp snooping enable` + 上联口 `dhcp snooping trust` | | NTP 时间同步 | 配置了 NTP 服务器且时钟已同步(`synchronized`,按词边界判定) | `ntp-service unicast-server <服务器地址>` | | 日志中心 | 配置了 `info-center loghost` | `info-center enable` + `info-center loghost <服务器地址>` | | 登录失败锁定 | `password-control login-attempt` 已配置 | `password-control login-attempt 5 exceed lock-time 5` | | 密码最小长度 | `password-control length ≥8` | `password-control length 8` | | 空闲会话超时 | 未被 `undo idle-timeout` 禁用且 ≤10 分钟 | `line vty 0 63` + `idle-timeout 5 0` | | 接口安全(端口安全) | `display port-security` 全局 Enabled | `port-security enable` | | 接口风暴抑制 | 配置了 `storm-suppress broadcast` | 接入/上联接口配置 `storm-suppress broadcast 2000` | **注意事项:** - 检查本身只下发只读 `display` 命令,**不修改设备**;修复指令需人工确认后才下发 (批量下发前请核对接口名、服务器地址等占位内容)。 - AI 生成修复指令会消耗 token(单条 1 次调用;批量生成按违规项数调用),要求先配置 并激活「AI 配置」里的模型,未配置时页面会给出提示。 - 历史批次入库可回看 / 删除(级联清理全部判定与修复指令)。 ## 运维工具箱 网页内「🧰 运维工具箱」提供 7 个免登录设备即可使用的日常工具(登录后左侧菜单 「网络与备份 → 运维工具箱」): | 工具 | 说明 | | --- | --- | | Ping | 调系统 `ping` 命令(Windows `-n`/Unix `-c`),可设次数与超时 | | 路由跟踪 | 调系统 `tracert`(Windows)/ `traceroute`(Unix),关闭反解加速 | | TCP 端口探测(tcping) | 原生 socket 循环连 TCP 端口,统计成功数与最小/平均/最大时延 | | UDP 探测(udping) | UDP connect + 发包,收到 ICMP 回显即主机可达,超时判不可达 | | Telnet 探测 | TCP 连 + 读登录横幅(自动过滤 IAC 控制字节),确认端口是否提供 Telnet 服务 | | SNMP 团体名验证 | 用团体字读取交换机身份与性能:名称(sysName)、型号、系统版本、序列号、CPU、内存,复用 SNMP 监控的采集逻辑 | | 子网掩码计算器 | 同时支持 IPv4 / IPv6:输入 `地址/CIDR`、`地址+前缀长度` 或 `地址+点分掩码`,输出网络地址、广播地址、地址总数、可用主机数与首末地址、是否私网 | **安全与边界:** - 探测目标**只接受 IP 字面量**(IPv4 / IPv6,不支持域名),统一经 `ipaddress` 严格校验, 串命令注入字符(`; / | & ` $ < > ' "` 等)一律拒绝。 - 系统命令(ping/tracert)一律参数列表 + `shell=False` + 隐藏窗口执行,外层超时兜底。 - 数值参数严格限幅:次数 1-20、端口 1-65535、超时 1-30s、跳数 1-30;SNMP 团体名 ≤128 字符且仅允许可打印字符。 - 全部工具**只读探测/计算**:不落库、不写设备、不触发任何配置变更。 - SNMP 验证暂仅支持 IPv4(与监控采集一致),IPv6 地址会给出友好提示而非报错。 ## 常用参数 | 参数 | 说明 | | --- | --- | | `host` | 交换机 IP / 主机名(必填) | | `-u` | SSH 用户名,默认 `admin` | | `-p` | SSH 密码,不填则运行中提示输入 | | `--port` | SSH 端口,默认 22 | | `-k` | SSH 私钥文件路径(与密码二选一) | | `-c` | 要执行的指令,可重复使用,多条用 `;` 分隔 | | `-f` | 指令文件,每行一条,`#` 开头为注释 | | `-o` | 日志/回显保存文件,默认 `log.txt`(追加写入,含时间戳会话头) | | `-d` | SQLite 数据库文件,默认 `h3c_logs.db` | | `--no-db` | 本次不写入 SQLite 数据库 | | `-i` | 指令执行完后进入交互模式 | | `-t` | 单条指令等待回显超时秒数,默认 15 | | `-y` | 自动应答 Y/N 确认(会发 `y`,危险操作勿开) | | `-v` | 显示连接、发送等过程信息 | ## 设计说明 - 登录后自动执行 `screen-length disable` 关闭分屏,即使失败,脚本也会 识别 `---- More ----` 自动发空格翻页,长回显不会被截断。 - 回显按“出现下一个提示符(如 ``、`[H3C]`、`[H3C-GigabitEthernet1/0/1]`)”判读结束, 对 `save` 之类执行较慢的指令也能等待到结果。 - Windows 下自动把控制台输出切到 UTF-8,避免中文回显乱码。 - **注意**:`-y` 会把 `[Y/N]` 确认自动答 `y`,涉及 `reset`、`reboot` 等危险操作时 不要使用,请改用交互模式手动确认。 ## 终端信息(SNMP / SSH 两种采集,两份独立数据) 「终端信息」页(`/terminals/`)生成"哪个终端接在哪台接入交换机的哪个端口"。终端信息有 **两份互相独立的数据集**,来自两种采集方式,页面上用数据集切换按钮分别查看、互相对照: | 数据集 | 采集方式 | 内容 | 适用 | | --- | --- | --- | --- | | **SNMP 采集**(`source=snmp`) | SNMP v2c 只读 | 网关 ARP 表 + 全部交换机 MAC 地址表 | 轻量、不用登录设备;但依赖设备实现相关 MIB,部分设备表项不全 | | **SSH 采集**(`source=ssh`) | SSH 登录读回显 | `display/show arp` + `display/show mac-address` 文本解析 | 回显最权威、表项最全;代价是要登录设备(账号权限与并发需留意) | 两种来源**同一个 MAC 各占一行、互不覆盖**:SNMP 采到的和 SSH 采到的分开存放,采其中一种 不会动到另一种(陈旧记录清理也严格限定在本来源内)。页面顶部显示各自条数,若两边定位结果 不一致会给出「N 个 MAC 两边定位不一致」提示,行内「另一份数据」列直接列出同 MAC 在另一份 数据里的交换机/端口并标「不一致」,便于当场比对。**统计口径按 MAC 去重**(同一台终端在两份 数据里只算一台),CSV 导出文件名带数据集标识(`terminals_snmp_*.csv` / `terminals_ssh_*.csv`)。 **采集入口:** 页面上选**采集方式**(SNMP / SSH)与**采集范围**(全部设备 / 按分组,含 「未分组设备」),点「开始采集终端」。采集范围同样经数据范围校验、自动跳过服务器;采集 完成后自动跳回对应数据集。采集动作写入任务监控(类型「终端采集」,方式记录为 snmp 或 ssh)。 **关联去重规则(两种来源完全一致,只写一套):** 1. 先剔除「上联口」表项:上联口 = 拓扑采集的「连接接口」(`Device.topo_port`)∪ LLDP 记录过的本地端口 ∪ 名称匹配聚合/Trunk 模式(Bridge-Aggregation/Eth-Trunk/Port-Channel/Trunk 等)的端口;端口名比较会展开常见缩写(GE1/0/48 ≡ GigabitEthernet1/0/48)。 2. 剩余表项唯一 → 定位到该交换机该端口;剩余多条(终端漫游/双归属)→ 标记「多交换机命中」,取设备 IP+端口排序第一条,条数写入备注。 3. 表项全部在上联/聚合口 → 未定位(备注说明);只有 ARP 没有 MAC 表项(终端关机/未直连交换机)→ 记录 IP、标「未定位」;只有 MAC 没有 ARP → 记录 MAC、IP 留空。 4. **交换机互联推断(没采拓扑时的兜底)**:ARP 里 IP 与设备 IP 对得上的 MAC 是交换机自身的 管理 MAC——它出现在 A 的哪个口,说明该口下联 B(A→B 的互联口),自动并入上联口剔除集合; 若某终端 MAC 只出现在这类互联口上,则按互联关系把终端归属到下联那台交换机(端口留空、 备注写明推断依据),避免把下联交换机下面的终端错记在上联交换机上。 5. **交换机自身的管理 MAC 不计入终端**:它们只用于推断互联关系,不会出现在终端列表里 (否则每台交换机自己都会变成一条「终端」)。 **SNMP 采集细节(MIB):** | 对象 | MIB | 内容 | | --- | --- | --- | | 网关交换机(角色=网关;未设置角色则全部设备) | IP-MIB `ipNetToMediaPhysAddress` | ARP 表:IP ↔ MAC,VLAN 从 VLAN 接口名(Vlan-interface10/Vlanif10/Vlan10)推断 | | 全部交换机 | Q-BRIDGE-MIB `dot1qTpFdbTable` | MAC 地址表:MAC ↔ 桥端口/VLAN,仅取动态学习(learned)条目;桥端口经 `dot1dBasePortIfIndex` 映射为 ifIndex,再经 `ifName`(回退 `ifDescr`)转接口名;VLAN 由 `dot1qVlanFdbTable` 建立 fdbId→VLAN 映射(映射不到回退 fdbId,H3C/华为普遍 fdbId 即 VLAN) | **SSH 采集细节:** 命令映射见 `h3c_vendor.py` 的 `arp_table` / `mac_table`(H3C/华为 `display arp` / `display mac-address`,思科 `show ip arp` / `show mac address-table`)。 回显按「逐行定位 MAC 词元」解析,兼容三种列序:H3C(MAC VLAN State Port)、华为 (MAC VLAN Port Type)、思科(VLAN MAC Type Ports)。ARP 解析会**区分 VLAN 与老化时间**: H3C 的 MAC 后一列是 VLAN,华为同位置是 `Expire(M)` 老化分钟数(华为该命令不回 VLAN), 据此只把"数字后面紧跟接口名"的那列认作 VLAN,取不到就留空——错标 VLAN 比留空更有害。 **落库与展示:** `TerminalEntry` 按 (MAC, 来源) 唯一(同一 MAC 两份数据各一行,upsert 更新不重复建行),统计卡展示当前数据集的 记录数/已定位/已知 IP/多命中;支持按关键字(MAC/IP/端口)、接入交换机、分组、定位状态筛选与 CSV 导出(带 BOM,Excel 直接打开,含「来源」列)。 **陈旧记录清理:** 一次全网采集(所有设备都成功)结束后,本次全网都没再看到的**本来源** 记录会被删除(归属在未扫描设备名下、或本就未定位的行保留),页面不会继续展示上一次的错误 归属;任一设备采集失败时不清理,防止误删。两份数据各自清理,绝不影响对方。 **人工绑定:** 定位不到或定位有误时,行内「修正」可直接把终端绑定到指定交换机/端口 (来源标「人工」,写入操作审计);人工绑定的行**不会被后续采集覆盖**,点「解除」交回 **绑定前的那份数据**(SSH 采来的行解除后回到 SSH 数据集,不会跑到 SNMP 那一份里)。 适合设备不开放 MAC 表、或终端接在 Hub/无线 AP 后面等采集看不到的场景。 **定时采集:** 定时任务类型「终端信息采集」,支持全部设备/指定分组,按 SNMP 方式采集; 建议与拓扑采集(填充上联口)配合使用以提高定位准确度。 **MAC 表 CLI 兜底(SNMP 采集内部):** 若 SNMP 请求正常但 FDB 表为空(部分设备/模拟器不实现 BRIDGE/Q-BRIDGE 子树),SNMP 采集会自动改用 SSH 下发 `display mac-address` 兜底,结果仍归入 **SNMP 数据集**(这是 SNMP 采集的补足手段,不是 SSH 采集)。任务详情中每台设备的 `mac_source` 标明本轮 MAC 表来自 `snmp` 还是 `cli`。 **注意:** 设备需开启 SNMP 且社区字正确;SNMP 与 CLI 兜底都拿不到 MAC 表时,终端只能记录 ARP 中的 IP↔MAC 并标「未定位」——任务详情中该设备 `MAC=0` 即此情形。 ## 无线管理(AC / AP / 无线终端) 「无线管理」页(`/wireless/`)把无线网络当三层台账管:**无线控制器(AC)→ AP → 在线无线终端**,再加一层「AP ↔ 接入交换机」的物理对应关系。前提是把 AC 在「设备列表」 里的类型设为**网络设备 · 无线控制器**并填好 SSH 账号。 **采集命令按厂商自动选**(`h3c_web/device_console/wireless.py`): | 厂商 | AP 列表 | 无线终端 | | --- | --- | --- | | H3C Comware | `display wlan ap all` | `display wlan client all`(块状回显也能解析) | | 华为 VRP | `display ap all` | `display station all` | | 思科 IOS | `show ap summary` | `show client summary` | | 厂商未知 | 先按 H3C 试,解析不到再依次回落 | 同左 | - **宽容解析**:定宽表格按「分隔线分组 + 表头列位对齐」切列(表头对不上就退到最近的列起点), 解析不出的字段如实留空、状态原文照存,绝不猜、绝不误报。 - **落库口径**:AP 先按(控制器, 名称)认亲,改了名字再按 MAC 认亲,都认不上才新增; 本轮没出现的 AP / 终端标记为**离线**而不是删除(历史可追溯);有终端回显时按在线终端数 回填 AP 的「在线终端」列;无线终端按 MAC 全局唯一,重复采集在原行更新。 - **对应关系推断**:优先用接入交换机的 **LLDP 邻居**(邻居名 = AP 名),其次用「终端信息」 里的 **MAC 地址表**(AP 的管理 MAC 本身就是一条终端记录),来源分别标记 `lldp` / `mac`; **人工绑定(`manual`)永远不会被自动推断覆盖**,解绑后可点「重新推断对应关系」重算。 - **页面**:四个标签(无线 AP / 无线终端 / AP ↔ 接入交换机 / 采集与登记);顶部统计卡给出 AC 数、AP 总数与在线离线、无线终端数与在线数、已关联接入交换机数、SSID 数; 支持关键字 / 在线状态 / 按 AC 筛选与分页(每页 100 条);AP 列表可导出 CSV,导入时 中英文表头别名都认(按 IP 关联控制器与交换机);可人工登记 / 编辑 / 删除 AP、 人工绑定或解绑接入交换机、清理超期离线终端。 - **权限与定时**:写操作统一走角色校验(只读角色 403);「定时任务」可选**无线采集**类型 周期跑,任务监控里逐台记录成功状态、AP 数与失败原因。 - **测试**:`h3c_web/test_wireless.py`(解析 / 落库 / 对应关系推断 / 采集编排 / 页面与 POST / 定时任务),全程用假 SSH 客户端,不碰真设备。 ## 交换机遥测数据(telemetry 接收、解析与指标化) 「遥测数据」页(`/telemetry/`)接收交换机主动推送的遥测订阅数据(push 模式, 区别于 SNMP/SSH 的拉取模式),两条接收通道: **① gRPC dial-out 采集口**(随网页服务自动启动,默认端口 `50051`,可用环境变量 `H3C_TELEMETRY_PORT` 修改): - **不依赖厂商 proto 文件**:gRPC 侧注册通用处理器,任意服务/方法名均按 「客户端流 → 单响应」接收(H3C `GRPCTelemetry/rpcTelemetry` 与华为 `TelemetryService/TelemetryReport` 的 dial-out 形态都兼容); - **报文无 schema 通用解析**:按 protobuf 线格式解析出字段树;其中携带 JSON 载荷的字段(设备侧 `encoding json` 时的 data_json)完整解析为 JSON; 二进制 GPB 载荷递归解析成「字段号→值」的通用树供人工比对(需要字段语义 请对照厂商 proto 定义); - 交换机侧配置参考(H3C Comware V7,各版本语法略有差异): ``` telemetry destination-group DG1 ipv4-address <平台IP> port 50051 grpc sensor-group SG1 sensor path ifmgr/statistics refresh-interval 10 subscription SUB1 sensor-group SG1 sample-interval 10 destination-group DG1 encoding json ``` > **先确认设备支不支持 dial-out**:`telemetry` 这条命令在不同 Comware 版本里含义并不一样—— > 有的版本只有 IFA(`apply` / `flow-group` / `ifa` / `mod` / `stream`),**没有** > `destination-group` / `sensor-group` / `subscription`,也没有 `grpc` 命令,这类设备配不出遥测订阅 > (实测 H3C V9850-256H、Comware 7.1.070 R7643P02 就是这种:`telemetry ?` 只列 IFA 相关子命令, > `grpc ?` 直接报 `% Wrong parameter found at '^' position.`)。在设备上敲 `telemetry ?` 与 `grpc ?` > 一看便知。不支持时两条替代路径:① 用平台的 **SNMP 采集**(设备管理里填只读社区字即可, > CPU / 内存照样进监控大屏、3D 机房着色、运维报表与告警);② 用下面的 HTTP 推送口,让探针/脚本代推。 **② HTTP JSON 推送 API**:`POST /telemetry/push/`(免登录,设备/探针直接推): ```bash curl -X POST http://<平台IP>:8000/telemetry/push/ -H "Content-Type: application/json" -d '{"node_id_str":"192.168.56.11","sensor_path":"ifmgr/statistics","InOctets":123456}' ``` 设置环境变量 `H3C_TELEMETRY_TOKEN` 后,推送需带头 `X-Telemetry-Token`。 **解析与落库:** 从 JSON 载荷的常见键名(node_id/node_id_str/device_name、 sensor_path/proto_path、subscription_id 等)提取设备标识与传感器路径,键名搜索 **逐层下钻**(最多 6 层,数组只探前 8 个元素;同层先比键名再往下走,所以浅层的值 优先命中),标识藏在 `telemetry` 子对象或 `data.ifmgr.statistics.Interface[0]` 里也认得出来。设备关联依次尝试:**标识就是已登记的 IP → 设备名精确 → 设备名忽略 大小写 → 标识里夹着的 IP**(`10.1.1.1:50051`、`slot=1;ip=10.1.1.1` 这类形态); 匹配不上也照样落库(`device` 留空),事后用页面上的「重新匹配设备」批量回填—— 设备是后登记或改过名时的补救。每条推送一行 `TelemetryRecord`(解析数据 + 原始报文截断留档,坏报文不丢不崩)。 **页面与运维:** 统计卡(总条数 / 设备数 / 近 1 小时 / gRPC·HTTP 分布 / **未关联设备**,一条聚合 SQL 出全部数字);**「最新值」区块**按「设备标识 + 传感器路径」聚合,直接给每组的当前值、推送条数与最后接收时间,不用在周期推送的 流水里翻;按标识 / 通道 / 关键字 / 时间 / **只看未匹配**筛选,单条数据与原始报文 展开查看,**导出 CSV**(跟随当前筛选,最多 5000 条),写入测试数据, **重新匹配设备**,清理(按 id 阈值分批删、保留最近 2000 条,不再把 data/raw 大文本整条读进内存);关键字搜索没给时间范围时自动按保留期兜一层,避免大文本 `LIKE` 全表扫把页面拖慢。保留策略默认 14 天(`H3C_TELEMETRY_KEEP_DAYS` 可调) 且总量上限 2 万条,由每日数据清理任务执行。依赖 `grpcio`(未安装时 gRPC 通道 降级关闭,HTTP 通道不受影响)。 **指标化(把推送变成能判定的数值):** 原始 JSON 是给人溯源看的——键名各厂商各叫各的 (H3C `CpuUsage`、华为 `MemoryUtilization`、思科 `cpu-utilization`…),层级也不统一, 没法直接比阈值、画趋势。所以每条推送入库时都会再由 `telemetry_metrics.extract()` 走一 遍:按**键名别名表**归一成 `TelemetryMetric` 行(设备 + 指标 + 实例 + 数值 + 单位 + 时间),接口类指标另带 `label`(接口名 / 索引)区分实例,设备级指标 `label` 留空。 抽取遵循全项目的第一原则——**宽容解析,绝不误报**:认得的键才抽,认不得的原样留在 `TelemetryRecord` 里;方向不明(分不清 in / out)的计数器宁可丢掉也不猜。支持的指标: CPU / 内存 / 温度、接口进出字节、接口进出错包与丢包、电源与风扇状态、其他数值。 | 指标 | 警告 | 严重 | | --- | --- | --- | | CPU / 内存使用率 | ≥ 85% | ≥ 95% | | 温度 | ≥ 65℃ | ≥ 75℃ | | 接口错包 / 丢包增长(两次采样的差值) | ≥ 1 条 | ≥ 50 条 | | 数据新鲜度 | — | 超过 30 分钟没有新推送判**中断** | 从没推过数据 → **未采集**;数据太旧 → **中断**(比阈值问题更要紧,先判)。判定口径刻意 与「服务器监控」(`host_agent`)保持一致,读起来是同一套心智模型;计数器被清零(设备 重启)按 0 处理,不会重启后刷出一片假告警。 **一份指标喂四处**:告警中心(来源=交换机遥测指标)、监控大屏「交换机遥测健康」块与 「遥测体检」、3D 机房着色兜底(SNMP 与主机指标都没有的网络设备)、运维报表「交换机 遥测」一节,全部只读这张表,不再各自解析 JSON;另有只读接口 `/api/v1/telemetry-metrics/` (支持 `device` / `metric` / `label` / `node` / `latest` / `hours`)。 **页面「结构化指标与图形化分析」区块**:统计卡(有遥测数据的设备数 / 健康分档 / 平均 CPU·内存 / 最高温度 / 指标总条数)+ 每台设备一行(健康档与判定理由、最新指标值、接口计数器条数、最后推送时间) + 一整套图。图表全部由服务端直接生成 SVG(`device_console/charts.py`:折线 / 迷你走势 / 横向与纵向 柱状 / 环形图,**零前端依赖**,每个数据点带 `` 悬停可见数值,画不出来的一律返回 `None`、 页面显示「数据不足」而不是空白图),时间范围 `?hours=`(1 / 3 / 6 / 12 / 24 / 72 / 168 小时,默认 6, 非法值回落默认)与设备钻取 `?dev=` 都在 URL 上,跟着筛选、分页与 CSV 导出一起传: | 图 | 内容 | 数据口径 | | --- | --- | --- | | 健康环形图 | 正常 / 警告 / 严重 / 中断 / 未抽到指标的设备台数占比,中心写设备总数 | `health_summary()` | | 设备指标趋势 | 每台一张 CPU / 内存 / 温度三线图,带「警告 85」「严重 95」阈值参考线(最多 6 台) | `device_history()`,每张最多 40 个点 | | 接口流量 | 入方向速率 Top 10 排行 + 前 3 个接口的进 / 出方向曲线(单位自动换成 K/M/G bps) | `interface_rates()`:进出字节计数器的差值 ÷ 采样间隔 × 8 | | 错包 / 丢包增长 | Top 10 排行,达严重线的标红 | `counter_growth()`:窗口内首末两次采样之差,计数器清零按 0 | | 推送节奏 | 时间桶柱状图(≤6 小时分 12 桶,否则 24 桶),整段为 0 就是设备侧订阅断了 | `push_histogram()` | | 指标 / 传感器分布 | 各指标类型条数、各传感器路径推送条数,看订阅到底推了些什么 | `metric_distribution()` / `sensor_distribution()` | | 表格迷你走势 | 每台设备一行的 CPU / 内存 sparkline(末点按阈值变色)+「看这台」一键钻取 | `charts.sparkline()` | **演示数据**:真机还没接上(或像上面那种压根不支持 dial-out)时,图形化区块只会显示「数据不足」, 看不出效果——「🎬 生成演示数据」按 10 分钟一个点回溯 6 小时造出 36 个采样点(设备级 CPU / 内存 / 温度 + 两个接口的字节与错包计数器,计数器单调累加),走的是与真实推送**完全相同**的入库链路 (`telemetry_server.ingest_dict` → 抽指标 → 回填接收/采集时刻),所以看到的图就是真数据的样子; 数值刻意压在告警阈值以下、错包只在中段增长,不会误触发告警与通知。订阅名固定 `netpilot-demo`, 「🧹 清除演示数据」按它精确删除(先删指标再删记录、分批删),不碰真实推送。 **补抽指标**:指标化上线前攒下的老推送、或改过键名别名表之后,用页面上的「🧮 补抽指标」 回扫历史(一次最多 2000 条,已抽过的不重复);指标要挂到已登记设备上才能比阈值、上大屏, 关联不上时先用「重新匹配设备」回填。 **裁剪**:指标保留 14 天、总量上限 6 万条(一条推送能抽出几十行指标,涨得比原始记录更 快),由每日数据清理任务执行(摘要里的「遥测指标」项),每入库 500 次也会顺手裁一次。 **推送口的边界:** HTTP 顶层是数组时**按条拆开逐条入库**(此前是整包塞成一条、 设备标识也提不出来),一次最多 500 条,超出返回 400;请求体上限与 gRPC 一致 (2MB),超限返回 **413** 而不是抛异常变成 500;令牌校验改用常量时间比较。 gRPC 侧限制并发 RPC 数(32)与收发消息大小,接入设备再多也不会吃满线程池。 **测试**:`h3c_web/test_telemetry.py`(线格式解析 / 深层键名提取 / 设备关联 / HTTP 推送 边界 / 页面与 CSV 导出)、`h3c_web/test_telemetry_metrics.py`(键名别名归一 / 落库与 裁剪 / 计数器增量 / 健康判定 / 告警与大屏体检 / 报表与 API / 图表出图与数据口径(速率换算、 计数器清零、窗口过滤、分布与节奏)/ 演示数据生成与清除 / 页面图形化渲染与钻取), 全程用假报文,不碰真设备。 ## 网页 SSH 终端(交互式会话) 登录后访问 **http://127.0.0.1:8000/terminal/**,像本地 SecureCRT 一样直接对 交换机敲命令:进入 `system-view` 改配置、按空格翻页、Y/N 确认、Ctrl+C 中断、 Ctrl+Z / Ctrl+D 退出配置视图均可实时生效。 - **一屏布局**:终端区自动占满视口剩余高度(xterm.js 按容器实时 fit,窗口缩放、 侧栏折叠都会重算行列),滚动条为暗色细条;快捷命令与操作提示放在终端右侧 面板,窄屏自动落到终端下方。 - **交互方式**:下拉选设备点「连接」即建 SSH 会话;支持一次开多条连接 (类似 SecureCRT 多标签),并发上限 20;空闲 10 分钟无交互且无页面挂着会自动断开。 - **回显推送**:页面用 SSE(`/terminal/<sid>/stream/`)实时拿设备回显,输入用 POST base64 字节流(`/terminal/<sid>/input/`)写入通道——UTF-8/GBK 与 Ctrl+C、方向键等控制序列均原样转发;断线重连时自动回放会话缓冲,不丢历史。 - **快捷命令**:右侧命令面板按「信息查看(只读)/ 配置操作(写设备)」分组, 版本 / CPU / 内存 / 接口摘要 / LLDP 邻居 / 当前配置等一键下发,按钮上同时标出真实命令。 - **技术实现**:不用 Django Channels / WebSocket,保持纯 WSGI——SSE 长连接 + POST 输入;会话为内存态(`device_console/device_terminal.py`),重启即回收, 不留库;前端 xterm.js 渲染终端(静态资源固化在 `static/.../vendor/xterm/`, 内网可用)。 - **安全提示**:本页操作实时生效(包括写配置),页面上方有明确红字警示; 回显不入库,但敲过的每条命令都会留痕,见下节「终端操作日志」。 ## 终端操作日志(网页 SSH 会话留痕) 「终端操作日志」页(`/terminal/logs/`)留存每一次网页终端会话敲过的命令,用于事后追溯 「谁、在哪台设备上、什么时候、做了什么」。 - **记录内容**:设备、操作人、开始/结束时间、时长、命令条数、逐条命令(带时间戳), 状态分「正常结束 / 异常断开」。**只记命令文本、不记回显**——回显可在会话进行中点终端页 的「💾 保存日志」下载(会话断开后该实时接口返回 410,此后只能从本页下载留档)。 - **命令采集规则**:以回车/换行提交一行,Ctrl+C / Ctrl+D 也会提交当前行;方向键等其余 控制字符不计入命令,避免翻页、行编辑动作被记成乱码。 - **落库时机**:会话销毁时写入 `TerminalLog`(主动断开、空闲超时回收、服务停机均会落库), 落库失败不阻塞会话回收。 - **页面能力**:按状态与设备名称/IP 关键字筛选,每页 30 条;概览卡给出 总数 / 正常 / 异常; 详情页看逐条命令;单条可下载 `.txt`;「🗑 清理旧日志」保留最近 200 条。 - **自动裁剪**:列表页每次打开会把超出 2000 条的最老记录直接删掉,防止长期堆积。 ## 服务器监控与主机 Agent 「服务器监控」页(`/hosts/`,导航在「巡检与合规」组)盯的是**服务器**:物理服务器与 虚拟化服务器的 CPU / 内存 / 磁盘 / 负载 / 运行时长 / 硬件信息。前提是先在「设备列表」把 大类设为**服务器**(或档案里填了操作系统)并填好 SSH 账号与端口。数据有三条通道, **写同一张表 `HostMetric`**,页面上看起来完全一致,只是每行标明来源是「Agent 上报」、 「Categraf 上报」还是「SSH 采集」。 **① Agent 上报(推荐:数据最全、频率可控、不占用 SSH 会话)** - **Go 原生二进制,目标机零依赖**:Agent 是 Go 写的单文件程序(源码在仓库根目录 `agent/`),用 `CGO_ENABLED=0` 静态交叉编译出各平台产物,**Linux / Windows 直接 跑二进制,不需要 Python、也不需要装任何依赖**——这是相比上一代 Python 版最大的 变化:过去主机要先装好 Python 3(EOL 发行版还要换归档源)才能跑,现在没有这道坎。 Linux 读 `/proc`(stat / meminfo / loadavg / uptime)与 `/sys/class/dmi/id`, Windows 用 Win32 API(`GetSystemTimes` / `GlobalMemoryStatusEx`)+ 注册表;全程 **只读**,单个字段采不到就留空,不影响其余字段上报。运行形态对齐 Zabbix Agent: Linux 装 systemd 服务、Windows 装原生 Windows 服务,**常驻**周期上报。 编译产物随本仓库一起放在静态目录,按 `os/arch` 命名: `netpilot-agent-linux-amd64` / `netpilot-agent-linux-arm64` / `netpilot-agent-windows-amd64.exe`,页面上可直接下载;要重新编译(或加新架构)跑 `bash agent/build.sh`,产物会落回静态目录。 - **参数**:`--url`(`/agent/push/` 全地址)、`--token`、`--interval`(默认 300 秒)、 `--once`(只上报一次就退出)、`--print`(只打印采集结果自检、不上报)、`--timeout`、 `--insecure`(自签证书)、`--version`;仅 Windows 另有 `--install-service` / `--uninstall-service`(注册 / 卸载原生 Windows 服务)。也可用环境变量 `NETPILOT_URL` / `NETPILOT_TOKEN` / `NETPILOT_INTERVAL` 代替命令行参数。上报失败按 指数退避重试(最多退到 10 倍间隔),平台重启期间不会疯狂重试。 - **一键安装**:页面「Agent 接入与令牌」按主机操作系统直接给出可粘贴的命令。 `<平台地址>` 默认跟着当前访问地址走,不写死 IP;但**用浏览器从本机 `127.0.0.1` / `localhost` 打开平台时,远端主机是连不上这个地址的**(Agent 装不上 最常见的原因),页面会自动换成平台的局域网地址,并在命令上方提示已替换、列出本机 其余网卡地址供手动挑选;也可以用环境变量 `H3C_PLATFORM_BASE_URL` 把平台地址固定 下来(优先级最高,多网卡或走了反向代理时建议直接配这个)。 Linux(root 执行,`curl` 与 `wget` 二选一——最小安装的系统常常只有其中一个): ```bash curl -fsSL http://<平台地址>/static/device_console/agent/install_linux.sh -o /tmp/netpilot-install.sh # 机器上没有 curl 就用 wget: wget -qO /tmp/netpilot-install.sh http://<平台地址>/static/device_console/agent/install_linux.sh sh /tmp/netpilot-install.sh http://<平台地址> <令牌> 300 ``` 安装脚本按 `uname -m` 挑对应架构的二进制、跑一次 `--print` 自检、再装 systemd 服务, 任何一步失败都会把原因打印出来;装完 `journalctl -u netpilot-agent -n 20 --no-pager` 里应该能看到一行「上报成功 CPU … → HTTP 200 ok=True health=ok」,同时页面上这台主机的 来源会从「SSH 采集」变成「Agent 上报」。 装成 systemd 服务 `netpilot-agent`(二进制落到 `/usr/local/bin/netpilot-agent`, 机器没有 systemd 时打印等价的 `nohup` 命令),用 `systemctl status netpilot-agent`、 `journalctl -u netpilot-agent` 看状态与日志。Windows(管理员执行): ```bat powershell -NoProfile -Command "Invoke-WebRequest -UseBasicParsing http://<平台地址>/static/device_console/agent/install_windows.cmd -OutFile $env:TEMP\netpilot-install.cmd" %TEMP%\netpilot-install.cmd http://<平台地址> <令牌> 300 ``` 二进制落到 `C:\NetPilot\netpilot-agent.exe` 并注册为**原生 Windows 服务** `NetPilotAgent`(开机自启、常驻上报,不再是每 5 分钟跑一次的计划任务),用 `sc query NetPilotAgent` 查状态、`netpilot-agent.exe --uninstall-service` 卸载。 - **令牌**:一台主机一把(也可给不同用途签多把),明文前缀 `npa_`,库里只存 SHA-256 摘要、页面只留前 12 位供辨认,**明文只在签发那一刻显示一次**(请立刻复制保存)。 签发后跳到主机详情页,**顶部黄色横幅直接给出明文 + 一键复制**,并自动切到 「Agent 与令牌」标签页(安装命令里已把令牌填好);万一先回到 `/hosts/` 列表页, Agent 标签页顶部同样会显示一次。刷新页面即消失,忘了只能吊销重签。 可选有效期(永久 / 30 天 / 90 天 / 一年),支持**停用**(Agent 立刻推不上来, 但不用重装,比吊销温和)、**启用**与**吊销**;签发 / 停用 / 吊销都写操作审计。 - **上报接口 `POST /agent/push/`**:免登录、`@csrf_exempt`,凭请求头 `X-Agent-Token` 认主机;请求体可以是单个对象,也可以是**数组**(补传历史点时用)。字段非常宽容: 缺字段按 0 / 空处理、不会 400;内存与磁盘既可以只给百分比(`mem` / `disk`), 也可以只给总量与已用量(`mem_total_mb` / `mem_used_mb`,平台自己折算);采集时刻 `ts` 认 epoch 秒 / 毫秒 / ISO 字符串(不合法就落服务器时间)。响应回一份健康判定 与阈值,Agent 可以在本机日志里直接提示「CPU 超过阈值」。非 POST → 405; 令牌缺失 / 不存在 / 已停用 / 已过期 → 403;请求体不是合法 JSON → 400。 每次成功上报还会更新令牌的「最近使用 / 最近来源 / 上报次数」(限流写库,60 秒内不重复更新)。 **② SSH 采集(没装 Agent 的机器,一键补齐同样的字段)** - 在「主机列表」勾选主机(不勾就是全部)点「🖥️ SSH 采集勾选的主机」,平台用服务器 档案里的账号并行登录(最多 8 台同时,单机超时 15 秒;模块默认 25 秒)跑一条**只读** 探测命令,从回显里解析出 CPU / 内存 / 磁盘 / 负载 / 运行时长 / 系统与硬件信息。 - **回显解析按行首匹配**:探测命令统一输出 `NPM|key=value` 形式的行 (`h3c_web/device_console/host_agent.py`),这样在满是登录横幅与命令回显的终端文本里 也能一眼捞出结果,且**不会被命令回显本身误认成数据**;解析不到的字段如实留空,绝不猜。 - Linux 用 `/proc/stat` 两次采样算 CPU 使用率、`free -m`、`df -Pk /`、`/proc/loadavg`、 `/proc/uptime` 与 `/sys/class/dmi/id/*`;Windows 把 PowerShell 脚本转 base64 走 `-EncodedCommand`(绕开引号转义),用 CIM 取 `Win32_OperatingSystem` / `Win32_ComputerSystem` / `Win32_Processor` / `Win32_LogicalDisk` / `Win32_BIOS` 等。 - **系统类型没填会自动试**:档案里 `os_type` 为空时先按 Linux 试,一条数据都没解析到 再按 Windows 试(探测命令都是只读的,试错没有副作用),试出来后**回填设备档案**, 下次不用再试。 - 采集过程记进「任务监控」(类型 `host` 主机信息采集),逐台留成功状态、系统类型与 失败原因;「定时任务」也可以选**主机信息采集**类型按分组周期跑。 - **服务器只认证书登录也行**:设备档案的「认证方式」选**私钥(证书)**并粘贴私钥 (OpenSSH / PEM 的 ed25519 / ecdsa / rsa,自带口令就填「私钥口令」),SSH 采集、 一键备份、网页 SSH 终端、堡垒机会话**全部**改走证书登录。保存时平台会当场解析这把 私钥(格式/完整性/口令错都直接报错),并把**指纹**(与 `ssh-keygen -lf` 同口径)与 **公钥整行**显示在编辑页,复制到目标机 `~/.ssh/authorized_keys` 即可; 私钥**只存密文、绝不回显**,也不进 CSV 导出与操作审计(见下方「服务器证书登录」)。 **③ Categraf 上报(可选:采集项更全,平台只挑要用的几项落库)** - **为什么支持它**:Categraf(夜莺 Nightingale 配套的开源采集器,单二进制、自带上百个 input 插件:磁盘 IO、网络、进程、中间件、数据库…)很多环境里已经在跑。它对外**只有 Prometheus remote write 一种输出**(snappy 压缩的 protobuf),所以平台单开了一个接收口 `POST /agent/categraf-write/`——不用为了接它再搭一套 Prometheus / VictoriaMetrics, 也不用在目标机再装一个 Agent。 - **配置**:目标机装好 Categraf 后,`conf/config.toml` 里改两处就能推上来(页面 「Agent 接入与令牌 → ⑤ Categraf 接入」与主机详情页都给出填好地址与令牌的片段): ```toml [global] interval = 60 # 平台推荐值,见下;Categraf 自己的默认是 15 秒 [heartbeat] enable = false # 不接夜莺时关掉,否则目标机日志里全是连接失败 [[writers]] url = "http://<平台地址>/agent/categraf-write/" headers = ["X-Agent-Token", "<令牌>"] timeout = 5000 ``` 令牌与 Agent 通道**同一把**(Categraf 的 `headers` 支持自定义请求头,正好用来带 `X-Agent-Token`),页面上的签发 / 停用 / 吊销流程完全通用。接之前建议先在目标机跑一次 `categraf --test`(只打印采集结果、不上报),确认采到的指标名。 **采集间隔别照抄 Categraf 的默认 15 秒**:平台不是时序库,每台主机只留最近 500 条快照 (`host_agent.METRIC_KEEP`),15 秒一次约 2 小时就滚完,60 秒一次约 8 小时, 内置 Agent 默认更是 300 秒;要更实时就调小,代价是趋势图能回看的窗口同步变短。 真要长期存 15 秒粒度的原始数据,请把 writer 指向 VictoriaMetrics / 夜莺。 - **平台只挑要用的几项**:一批报文(默认 15 秒一次、一次可能几百条序列)只落**一条** `HostMetric` 快照,取 CPU(整机汇总值优先,只有每核时取平均,或按空闲率反推)、内存 (百分比优先,或按总量 / 可用量换算)、磁盘(根分区优先,没有根分区就取最满的挂载点)、 负载、运行时长、核数,以及主机名 / 系统版本 / 内核(来自 `agent_hostname` 全局标签与 `system_info` 序列)。**其余指标一律忽略**(磁盘 IO、网络、进程、中间件…),不会把原始 时序灌进 SQLite——Categraf 的定位是「比内置 Agent 采得全」,平台的定位仍是「只留该告警的 那几项 + 台账 + 告警闭环」。要长期存全量时序请把 Categraf 的 writer 指向 VictoriaMetrics / 夜莺,平台这边保持现状。 - **认不出就如实说,不猜**:响应回一份 `matched`(认出来的平台字段)与 `ignored` (没认出来的指标名清单)加一句 `hint`;一条都没认出来时**不落库**(不写一条全 0 的快照让 页面误以为「CPU 0% 正常」),只回 `ok=false` 与排查提示。对不上通常只是版本或 input 配置 差异,在 `device_console/categraf.py` 的 `FIELD_ALIASES` 里补一行别名即可(指标名以 `categraf --test` 实测为准)。 - **接口行为**:非 POST → 405;令牌缺失 / 停用 / 过期 → 403;`Content-Encoding` 不是 snappy → 415;snappy 或 protobuf 解不开 → 400(带具体原因);请求体超 2 MB → 413; 空报文或全认不出 → 200 + `ok=false`。落库后**走与 Agent 完全相同的链路**:来源显示 「Categraf 上报」、健康判定、阈值告警(落库即触发)、数据过期告警、监控大屏、运维报表、 3D 机房着色全部通用。响应里还会带上 Categraf 自报的主机 IP(`system_info` 标签), 与令牌绑定的设备对不上时一眼能看出「令牌签给了另一台机器」。 - **零新依赖**:snappy 与 protobuf 各手写了一个最小解码器 (`device_console/categraf.py`,合计百来行)——不引 python-snappy(Windows 上要装 C 库), 也不引 protobuf 运行时(只为解一个固定 schema 不值当)。两个解码器对畸形数据一律抛 ValueError 由视图转 400,绝不 500;解压后长度、时序条数都有上限,防压缩炸弹。 **④ 进程与服务检查(Agent 的 checks 模块:nginx 还在吗、自研二进制还在跑吗)** CPU / 内存 / 磁盘只能说明「机器活着」,说明不了「服务还在」——这一层补的就是后者。 - **三类检查**:`process`(进程,匹配口径与 `pgrep -f` 一致:**命令行子串**,可再填一个 排除词把脚本自身 / grep 排掉;Windows 侧同样按命令行匹配,见下)、`port`(TCP 连通, 写端口默认探 `127.0.0.1`,也可写 `host:port`)、`http`(GET 一个 URL,状态码 < 400 算可用, 4xx/5xx 记不可用并带上状态码——「端口通」不等于「服务能用」,502 必须能看出来)。 - **期望清单在平台侧**(主机详情页「进程与服务」标签页):判「进程不在了」的前提是平台 知道「应该有 nginx」,所以清单放平台、Agent 每 5 分钟拉一次(`GET /agent/checks/`, 同一把令牌),**改检查项不用登机器**。Agent 只报事实、不自己下结论——阈值与期望值都在 平台侧,改完不用重装 Agent。 - **结果随指标一起上报**(`/agent/push/` 的 `checks` 字段),不额外发请求、不额外开端口。 聚合口径:`instances` 匹配到的进程数、`cpu` 各进程之和(多核可超 100%,看的是这个服务 总共吃多少 CPU)、`mem_mb` 各进程常驻内存之和、`uptime_s` 运行最久那个实例的存活秒数 (主进程重启了这里会掉下来,一眼能看出「它刚重启过」)。 - **四态,只有「不在」告警**:`正常` / `不在`(Agent 明确报了 down)/ `未支持`(这一类检查 在采集端根本做不到)/ `未上报`(清单刚加还没被拉走、或结果超过 30 分钟没更新)。 后两者**都不告警**——采不到不等于服务挂了;主机整机失联由既有的「数据过期判离线」 (来源=服务器主机指标)负责,否则一次 Agent 停机就会刷出一屏假故障。 - **告警口径**(告警中心 → 规则,来源选**进程与服务检查**):「进程/服务不在」固定记严重; 「进程实例数不足」(少于检查项配的期望值)固定记严重;「进程重启」按**运行时长回退**判定 (uptime 单调递增,回退即重启过;阈值是「最小回退秒数」,留空按 0)——上次运行时长不足 60 秒的回退不报,那是它自己刚起来;「进程 CPU 使用率(%)」「进程内存(MB)」 按阈值判定,达到阈值 1.5 倍记严重、否则记警告。去重沿用规则的 `interval_minutes`。 - **离线 / 自检**:`--checks /path/checks.json` 用本机 JSON 清单(离线部署、或平台还没配时 手工验证),文件里写 `{"checks":[...]}` 或直接给数组都认;`--print` 会把检查结果一起打印, 所以「装了但没配检查项」也能在目标机上先跑通再上平台。`NETPILOT_CHECKS_URL` 可覆盖清单 地址(上报地址走了自定义路径时用)。 - **Windows 也支持进程检查**(v1.3.0 起),口径与 Linux 有一处已知差别,实现上是 「命令行 + 映像全路径 + 映像名」三者合一做**大小写不敏感**子串匹配——Windows 没有 `/proc`,命令行要读目标进程的 PEB,跨用户 / 高权限进程可能只有受限权限读不到命令行, 这时仍按映像名匹配(不误报「不在」),但清单里若写的是「exe + 参数」这种只有命令行 才含的串就可能漏判——所以判定为「不在」时会带一句「另有 N 个进程命令行读不到 (权限不足)」,让人知道这次扫描不完整。装成 Windows 服务(LocalSystem)时几乎 都能读到;前台以普通用户手动跑 `--print` 时会看到这个提示。 **阈值与健康判定**(`host_agent.health()`,页面与上报接口共用同一套口径): | 指标 | 警告 | 严重 | | --- | --- | --- | | CPU / 内存 / 磁盘使用率 | ≥ 85% | ≥ 95% | | 1 分钟负载 | ≥ 1.5 × 核数 | — | | 数据新鲜度 | 超过 10 分钟未更新就提示 | 超过 30 分钟无新数据判**离线** | 还没有任何数据 → **未采集**;数据太旧 → **离线**(比阈值问题更要紧,先判)。 每台主机只保留最近 **500** 条历史,超出自动裁剪,不用担心库越长越大。 **接进监控大屏与告警中心**:大屏的「服务器健康」块直接读这张表(分档统计 + 进度条 + 每台走势 + 服务器平均曲线),后台「主机体检」按「大屏设置」的间隔做只读判定;命中 「告警规则(来源=**服务器主机指标**)」即生成告警中心事件并沿规则通道推送。阈值判定 在指标**落库那一刻**就触发(Agent 上报与 SSH 采集都算),「数据过期」由主机体检发现 (机器不再上报也能告警);从没采集过数据的主机不告警。规则配置、级别折算与去重口径 见「告警中心」。 **接进运维报表与 3D 机房**:日报 / 周报多出「服务器与主机健康」一节(见「运维报表」), 主机资源严重不足 / 偏高、监控数据过期、本周期缺指标都会进报表开头的风险清单;3D 机房里 上架的服务器同样按这套口径着色,U 位详情给出 CPU / 内存 / 磁盘三条进度条与指标来源、 采集时间。两处都只读 `HostMetric`——出报表、刷机房都不会去连主机。 **系统指标(网卡 / 磁盘 IO / TCP 连接 / 进程)**:`HostMetric` 是一台机一条扁平快照, 网卡、磁盘、连接数这些**多实例、且多为累计计数器**的量放不进它,于是 Agent 在同一个 上报 payload 里另带 `ifaces / disks / tcp / proc` 子结构,平台落成 `HostPoint` (设备 + 类别 + 指标 + 实例 + 数值 + 单位 + 是否计数器 + 时刻,见 `device_console/host_points.py`): | 类别 | 指标 | 采集来源 | | --- | --- | --- | | 网络接口 | 每张网卡进出字节 / 包 / 错包 / 丢包 | Linux `/proc/net/dev`;Windows `GetIfTable2`(64 位计数器、友好名,过滤层/环回/隧道伪接口不报) | | 磁盘 IO | 每块整盘读写字节点数 / 次数 / IO 耗时 | Linux `/proc/diskstats`(分区与 loop 已剔除);Windows `IOCTL_DISK_PERFORMANCE`(按物理盘,标签带盘符如 `PhysicalDrive0 (C:)`) | | TCP 连接 | 各状态连接数 + 总数 | Linux `/proc/net/tcp(6)`;Windows `GetExtendedTcpTable` | | 进程 | 进程总数 / 运行中 / 阻塞 / 线程数 | Linux 扫 `/proc/*/status`;Windows `NtQuerySystemInformation`(总数 / 线程数 / 运行中三项,见下) | - **计数器看增量**:速率与「错包增长」用相邻两点的差值除以时间差(`rates()` / `error_growth()`),计数器被清零(主机重启)按 0 处理,不会刷出负速率或假告警。 - **两个平台的进程口径**(v1.4.0 起 Windows 从"只有总数"补齐到三项):`proc_total` 与 `proc_threads` 两边语义完全一致;`proc_running` 在 Linux 是 R 态进程数,在 Windows 是 **「有就绪/运行线程的进程数」**——Windows 没有按进程的运行态,用线程调度态(就绪 + 运行) 按进程归并,回答的仍是同一个问题「现在有几个进程想占 CPU」。`proc_blocked` **只在 Linux 报**: D 态(不可中断睡眠,通常卡在磁盘 IO)在 Windows 没有对应物,硬凑一个只会比出误导性的数—— 页面按"有哪个字段显示哪个"渲染,Windows 主机这一格就是不出现,不是 0。 数据结构(`SYSTEM_PROCESS_INFORMATION` 的字段偏移)按 x64 写死,32 位 Windows 只报进程总数; 解析出的数字与工具快照的线程数在测试里交叉验证(两条完全不同的通路必须对得上, 对不上说明 Windows 版本改了布局——那时宁可少报,也不拿错位的字节当状态数)。 - **负载(load1)两个平台也是同一套口径**:Linux 直接读 `/proc/loadavg`(内核维护的指数加权 移动平均);Windows 没有内核 loadavg,**Agent 自己按同一套算法采**——每 5 秒(对齐内核 `LOAD_FREQ`)取一次运行队列(就绪 + 运行态线程数),按 1 分钟时间常数做 EWMA,冷启动第一份 上报就以首次采样初始化(不是从 0 爬升,避免刚装完 Agent 报出一个假的 0 负载)。 **空闲任务(PID 0,System Idle Process)整条不计**:它每个核占一个线程、线程态恒为「运行」, 算进运行队列会让空闲机负载凭空抬高一个"核数"——Linux 的 loadavg 同样不计 idle 任务 (swapper 连 `/proc` 条目都没有)。所以 Windows 主机的「1 分钟负载 ≥ 每核 1.5」告警是真会触发的, 不再是恒 0 的死指标;采样链路断开超过 1 分钟就如实报"没有负载数据",不拿老值充当现在。 - **展示**:主机详情页新增「系统指标」标签页——网卡 / 磁盘当前速率与错包、TCP 与进程 当前值,以及网络吞吐、磁盘读写、连接数、进程数四张趋势图;监控大屏「服务器健康」块 多了「平均 TCP 连接 / 网卡错包(累计)」与逐台「连接 / 错包」列;运维报表 「服务器与主机健康」一节多了系统指标覆盖率、TCP / 进程平均与峰值、以及 「网卡错包 / 丢包增长最多」排行。 - **告警**:`host` 来源新增两个指标——`net_errors`(窗口内每张网卡错包 + 丢包的最大 增量 ≥ 阈值)与 `tcp_conn`(TCP 连接总数 ≥ 阈值),落库即判、共用既有去重窗口。 - **裁剪**:每个(设备 · 类别 · 指标 · 实例)序列只保留最近 300 个点,由 `host_points.prune()`(每日数据保留清理任务也会跑)执行。 - **Categraf 与 Agent 的关系**:平台保留 Categraf(Prometheus remote write)接收口, 但**部署上统一推荐 Agent**——Categraf 采出的丰富指标平台目前只消费 CPU/内存/磁盘等 少数几项,其余会被忽略;核心主机指标已由 Agent 直接采集,无需再装 Categraf。 **数据库监控(MySQL)已对齐 Categraf mysql 插件的核心能力**:Agent v1.10.0 起对 MySQL 登录检查的目标顺带采 SHOW GLOBAL STATUS 白名单指标,平台现算 QPS、缓冲池 命中率等(见 docs/05-监控/10-数据库监控与QPS.md)。 - **测试**:`h3c_web/test_host_points.py`(归一 / 落库与裁剪 / 速率与增量 / 上报接口 / 页面 / 告警)。 **页面** - `/hosts/`:统计卡(服务器数 / 正常 / 警告 / 严重 / 离线 / 未采集 / Agent 上报 / Categraf 上报 / SSH 采集 / 历史数据点)+ 两个标签页(主机列表、Agent 接入与令牌, 后者含 Categraf 配置片段);主机行给出 CPU / 内存 / 磁盘进度条、健康档与判定依据、系统与分类、数据来源、采集时间、 **服务检查概览(如 3/4,有不在的标红、有未上报的标黄)**、Agent 版本、历史点数与令牌状态; 支持关键字(名称 / IP / 主机名 / 系统 / Agent 版本)、 健康档、操作系统三种筛选(筛选只影响列表,不影响统计卡)。 - `/hosts/<id>/`:五个标签页(趋势 / 硬件与系统 / 历史明细 / **进程与服务** / Agent 与令牌)—— 最新指标与健康判定依据、CPU / 内存 / 磁盘 / 负载趋势图(可选最近 30 / 60 / 120 / 288 个点,默认 60)、DMI / CIM 硬件与系统信息、历史明细表、检查项配置与结果(新增 / 编辑 / 停用 / 删除,含实例数、进程 CPU 与内存、运行时长、HTTP 状态码、未上报原因)、 令牌签发与安装命令(含 Categraf 配置片段)、网页 SSH 登录入口、清空这台主机的历史指标。 - 写操作(SSH 采集 / 签发 / 停用 / 吊销 / 清空)统一走角色校验,只读角色返回 403。 **网页 SSH 登录服务器**:网页终端(`/terminal/`)对服务器走**通用 shell**——不再下发 `screen-length disable` 这类厂商初始化命令(服务器没有这些命令,下发只会在终端里留下 一行报错),提示符按 `~$` / `~#` / `PS C:\>` 识别;右侧快捷命令面板会随选中的设备自动 切换成 **Linux**(`uname -a` / `uptime` / `top` / `free -h` / `df -hP` / `lscpu` / `ip -br addr` / `systemctl --failed` / `journalctl` / `dmesg`)或 **Windows PowerShell** (系统信息 / CPU 前 10 进程 / 磁盘剩余 / 异常服务 / 系统事件日志)两套。从「服务器监控」 点「🔌 SSH 登录」会带 `?device=<id>` 跳到终端页并预选这台机器;交换机等网络设备的 终端行为完全不变。 **测试**:`h3c_web/test_hosts.py`(payload 宽容化 / 落库与历史裁剪 / 健康判定 / 探测命令与回显解析 / SSH 采集编排与系统类型回填 / 令牌签发与鉴权 / 上报接口 / 页面与 POST 动作 / 定时任务),SSH 部分全程用假客户端,不碰真机器。 `h3c_web/test_categraf.py` 覆盖 Categraf 通道:snappy 与 protobuf 两个解码器 (含重叠拷贝、负时间戳、NaN、越界与畸形数据)、指标挑选(cpu-total 优先、磁盘根分区 优先、总量量级兜底、干扰指标进 ignored)、接收端点各状态码与「全认不出不落库」、 落库即触发告警、页面配置片段——测试里的 remote write 报文由测试自己按协议拼出来 (literal-only 的合法 snappy + 最小编码的 protobuf),不需要真装 Categraf。 `h3c_web/test_process_checks.py` 覆盖进程与服务检查:结果归一化(认不出的状态归 「未上报」而不是「不在」)、四态判定、期望清单汇总、清单下发接口(含「拉清单不计入 上报次数」)、带 checks 的上报通道、四类告警与去重、页面与增删改停四个动作、 只读角色被拦;Go 侧另有 `agent/checks_test.go` 与 `agent/checks_linux_test.go` (清单过滤与限量、端口 / HTTP 检查、/proc 解析、拿测试进程自身做进程匹配), CI 里 `go test ./...` 一起跑。 ## 服务器安全巡检(Linux) 巡检中心 →「服务器巡检」(`/inspect/server/`):用 SSH(口令或证书)登录 Linux 服务器跑**只读命令**, 按**身份认证 / 暴露面收敛 / 文件权限 / 入侵痕迹 / 系统基线**五个维度出 19 条结论—— 空口令账户、长期未用账号、`PermitRootLogin`、sudo 与 NOPASSWD、`last`/`lastb` 登录审计、 监听端口与绑定范围(telnet/ftp/rpcbind、数据库绑 0.0.0.0)、自启服务、防火墙默认策略、 `/etc/shadow` 权限、全局可写目录、**账户清单跨轮基线比对**(新增后门账户点名)、 高 CPU 可疑进程、对外连接清单、定时任务可疑痕迹、临时目录隐藏文件、日志服务与轮转、 发行版 EOL 与待装更新。 结论四态:**通过 / 违规 / 警告 / 无法检查**——读不到(非 root 看 /etc/shadow、btmp、iptables) 如实记「无法检查」,**绝不拿读不到当通过**。每轮记录存原始回显,可点「**AI 安全分析**」 把回显分段喂给模型产出概述与问题清单(AI 是提醒,处置以人工核实为准)。可挂定时任务 (类型「服务器安全巡检」)。Windows 服务器不在本页(走安全基线的 Agent 规则)。 ## 防火墙安全策略 「防火墙运维」页(`/firewall/`,导航在「监控与可观测」组、紧跟服务器监控)看的是**华三 SecPath 系列防火墙的安全策略**:平台用 HTTPS **REST API**(Comware 7 的 `/api/v1/SecurityPolicies`)读回 规则、安全域与命中计数,**只读**——不下发、不删除、不改动设备上的任何配置。 **设备侧准备**(执行一次即可,不需要开 SSH / SNMP): ``` system-view ip https enable restful https enable # 账号:服务类型要带 http https,角色 network-admin local-user admin class manage service-type http https ssh authorization-attribute user-role network-admin return save force ``` **台账**:到「设备列表」把设备大类选**防火墙**(类型=防火墙、厂商=H3C)并填好账号密码。 「防火墙」是设备管理里的独立类别(标签页 `网络设备 / 防火墙 / 服务器`,三者互斥计数), 但**落库口径仍是「网络设备 + 类型=防火墙」**——这样 SNMP 采集、大屏计数、AI 设备清单这些 只认「网络设备 / 服务器」两类的流程不会把防火墙漏掉。设备列表里防火墙行有「防火墙运维」入口。 **采集到什么**:`Device/Base`(主机名 / 型号 / 软件版本 / 运行时长 / 桥 MAC)、 `GetRules` + `IPv4Rules`/`IPv6Rules`(规则与匹配条件、命中次数与流量、最近命中时间、描述、规则组); 两条规则来源按 **(类型, 规则 ID) 合并**,只在一边出现的规则也照常展示。另外读 `SecurityZone/Zones` + `Interfaces`(安全域成员,接口名按 `Ifmgr/Interfaces` 的 IfIndex 换算成 `GE1/0/1`)与接口 up/down。 **页面**:总览页给台数、健康分布(正常 / 数据过期 / 采集失败 / 未采集)与规则/安全域总数; 详情页给设备身份、**安全域**(**接口 down 单列**——它会让该域的策略整片失效)、**安全策略规则表** (顺序即设备上的匹配顺序,每行显示动作 / 启用 / 有效期 / 源域→目的域 / 源目的地址 / 服务应用 / 命中计数与流量 / 最近命中 / 描述,可展开看全部匹配维度;某维度为空即设备上「不限制」,页面显示「任意」) 与采集历史。每台保留最近 10 次采集,采集成功的批次会把厂商 / 型号 / 版本**回写设备档案**。 **边界**:采集路径只用 GET(登录走 `POST /api/v1/tokens`),PUT/DELETE **只在变更工单批准之后的 执行器里用**;页面只读库,采集是 POST 动作(需「运维」及以上角色,只读角色被拦)并在任务监控留痕 (类型=防火墙策略采集、方式=REST API)。 **编辑能力**:详情页「✏️ 编辑策略 / 对象组」(`/firewall/<id>/edit/`)能新增/启停/删除**调序** 安全策略规则、新建/删除/**改描述**对象组、增删**改**组成员(三类组都行:IPv4 地址 / 服务 / 端口);**新建组可以当场填成员**(「初始成员」一行一个:`10.1.0.0/24`、`10.1.0.1-10.1.0.9`、`10.1.0.5`,服务组 `tcp/80-90`、`udp/53`、`icmp/8/0`,端口组 `80-90`),不用先建空组再回头加。 改动**一律生成变更工单**(提交 → 另一位管理员批准 → 执行 → 可回滚,平台规矩是不能自批), 页面本身不下发设备。提交前对着最近一次采集的快照校验(安全域/服务组必须真存在、IP 与掩码合法、 ID 与组名不冲突),并给出「将下发载荷 + 回滚载荷」的预览页——**CLI 载荷会显示要下发的命令原文**。 载荷按序下发、**某步失败即停**(半执行状态如实写进工单,由人决定继续或回滚)。执行与回滚成功后都经 SSH 发 `save force` 把配置落盘(REST 只改运行配置,不落盘的话设备一重启就回到改动前)。 几条实机得来的口径(都固化在代码与测试里): - **调序走 CLI**:设备 REST 没有顺序接口,命令是 `security-policy ip` 视图下的 `move rule name A {before|after} name B`(两个 `name` 都不能省,实测语法)。规则表把设备上的 匹配顺序存成显式序号展示;**调序风险标为高**(挪错位置等于改流量走向),默认规则不允许调序。 - **改成员 = 删旧加新**:设备对对象成员不支持 PUT(405)、同 ID 重复 POST 也 409,所以 「改成员」按「删掉旧成员 + 用原 ID 加回新值」下发;旧值回滚用采集时存的设备原始行。 - **中文描述按 GBK 发**:设备 CLI 按本地字符集解释字节,UTF-8 发中文会存成乱码 (实测踩过),CLI 载荷带 charset、执行器照它编码。 - **REST 客户端按设备共享**:设备对并发 REST 会话有上限,密集采集/执行曾把会话打满、 连登录都 401(看起来像密码错);现在按 (host, 账号) 复用同一个客户端与 token。 策略变更比对与合规判定仍是后续的事。 更多细节(实测口径、常见问题、数据模型)见 [docs/05-监控/12-防火墙安全策略.md](docs/05-监控/12-防火墙安全策略.md)。 ## 应用管理(应用监控:全链路) 「应用管理」页(`/apps/`,导航在「巡检与合规」组、紧跟服务器监控)登记的是**业务视角**: 一个「应用」= 一台服务器上的一个对外服务(IP:端口),以及它在网络侧的落点。 - **应用档案**:应用名(唯一)、**服务类型**(Web 站点 / API 后端 / 数据库 / 中间件 / 文件存储 / 其他)、服务 IP 与端口(**同一 IP:端口 只能登记一个应用**)、 **有 nginx**(勾了会一并检查 nginx 进程)、**前后端分离**(一般要挂两个交换机端口)、 **关联服务器**(取这台机器的 CPU / 内存 / 磁盘与检查项结果)、启用开关、备注。 - **手动关联交换机端口**:一条应用可挂多个端口(默认最多 8 个),选交换机 + 端口名 + 用途 (接入 / 上联 / 其他)。端口下拉是**采集到过的接口**(LLDP 本地接口 + 遥测指标实例), 也可以手工填设备上还没采到的名字。这张绑定表**只由页面维护,采集链路不写它**, 所以人工绑定不会被后续采集覆盖(与终端信息里的人工绑定同一口径)。 **全链路健康:五段拼出来的一个档位**(`app_monitor.link_health`,不落库——存下来就会过期, 而且必然与告警判定出现两套口径): | 段 | 数据来源 | 判定 | | --- | --- | --- | | ① 服务 | 该应用名下检查项的最新结果(Agent 的 checks) | 有 down → 严重;有未上报/未支持 → 未知;全 ok → 正常 | | ② 服务器 | 关联主机最新指标与数据新鲜度 | 按主机阈值判;**数据过期降一档记警告**(看不到 ≠ 确定挂了) | | ③ 交换机端口 | 绑定端口的 **SNMP 接口快照**(`ifOperStatus` / 带宽计数器 / 错包,随「SNMP 监控」采集一起采);没有快照时回退到该端口遥测的错包/丢包 | 交换机离线 → 严重;**端口不在 up → 严重**(link down 与 dormant/模块不在位分别写明);**被人工关闭(admin down)→ 警告**;带宽利用率 ≥ 80% → 警告;窗口内错包增长 → 警告;两路都没数据 → 未知 | | ④ 系统告警 | 关联对象(服务器 + 绑定交换机)最近 120 分钟的告警中心记录 | 有严重级(severity ≤ 2)→ 严重;有其它 → 警告 | | ⑤ Syslog | 该应用 IP 与服务器 IP 最近 30 分钟的日志 | 有严重级日志 → 警告;没有日志 → 正常(不发日志不是故障) | **综合口径:就高合成,且「未知」不算故障** —— 任一段严重 → 严重;否则警告 → 警告; 否则未知 → 未知;全绿才正常。这条口径是刻意的:没配检查项、端口没接遥测、日志本来就不发, 都是**看不到**而不是**坏了**;把它们判成故障,运维第二天就会把告警静音,整套监控也就废了。 **③ 端口段的接口数据是怎么来的**(`snmp_monitor` + `h3c_snmp.fetch_interface_stats`): SNMP 监控采集时**顺带采该设备上被应用绑定过的那些接口**(只采点名的口,不做全表 walk—— 一台 48 口交换机全采一遍是 48 行/周期,而绝大多数端口没人关心),存 `SnmpInterfaceRecord` 快照(运营状态 / 管理状态 / 链路速率 / 收发字节 / 错包 / 计数器位宽)。 速率与错包增长按相邻两点算:**计数器回退(设备重启)或 32 位计数器绕回时那一向显示「—」 而不是 0**(显示 0 会被读成"没流量"),两向都不可信时明确写「本轮速率不可用」。 端口名支持精确 / 缩写(`GE1/0/1` ↔ `GigabitEthernet1/0/1`)/ 唯一后缀三种匹配; 设备上没有这个接口时如实报「设备上没有这些接口」,而不是静默当成 0。 每个接口保留最近 500 条快照,超期由每日保留清理删除。 - **一键生成检查项**:详情页按应用配置在关联服务器上建好 `app:<应用名>:port`(端口检查)、 `app:<应用名>:http`(Web / API / 文件服务生成)、`app:<应用名>:nginx`(勾了 nginx 才生成), 幂等(已存在就跳过)。检查项挂在应用名下(`HostCheck.application`),Agent 下一个采集周期 自动拉取执行——**应用监控的"服务段"就是这些检查项的结果**。 - **联动告警中心**:告警规则新增来源「**应用监控**」、指标「**应用健康档(0正常/1警告/2严重)**」, 口径仍是「≥ 阈值」——想要"严重才报"填 2,"有警告就报"填 1。**未知档记 0 所以不告警**。 命中即生成告警中心事件(严重档记严重级别),沿用规则的 `interval_minutes` 去重; 同一个应用不重复告警,但**共享服务器/交换机上的严重告警会让同机其他应用也升档**—— 这是全链路口径的必然结果(关联对象的告警算在自己头上)。体检由大屏「应用体检」按间隔执行 (只读库,不连任何设备、不发起探测)。 - **监控大屏**:「应用监控(全链路)」独立一块:分档统计 + 按健康档排序的前 8 个应用, 每行把五段各自的状态并排显示(悬停看每段说明),一眼看出"是哪一段出问题", 而不是只知道"这个应用不健康"。大屏设置页可配应用体检的开关与间隔(默认 5 分钟)。 - **数据范围与权限**:应用跟随关联服务器的地区(未关联服务器的应用对限定范围的用户不可见, 与终端信息同一口径);增删改要求「运维」及以上角色,只读角色可看结果不能改; 应用与端口绑定的增删改都写操作审计。 - **页面**:`/apps/` 列表(统计卡 + 关键字/服务类型/健康档筛选)、`/apps/add/` 与 `/apps/<id>/edit/` 表单、`/apps/<id>/` 详情(五段链路卡片 + 检查项 + 端口绑定增删 + 最近告警与日志)、删除(端口绑定一并删,**它名下的检查项保留在服务器上**,只解除关联)。 - **测试**:`h3c_web/test_apps.py`(90 项断言:模型约束、五段各自的四态口径、综合就高、 一键生成检查项的幂等与类型分支、端口候选来源、汇总排序与 top 截断、告警命中/去重/ 未知不告警、页面增删改查、数据范围、只读角色、大屏区块与设置项)。 ## 镜像流量分析监测(APM 旁路接入) 旁路分析侧是**独立项目**(交换机镜像口 → 会话重组 → L7 解析 → 评分,需要 Linux + 镜像口 + root,不在本平台里);本平台**只读拉取**它的结论,接进应用全链路、监控大屏 与告警中心——不去改它的配置(它的写接口要令牌、改完还要重启采集)。 **接入配置**(「大屏设置 → 镜像流量接入」,保存后由后台监测线程按间隔采集): - **指标地址**:APM 的 Prometheus 文本导出(默认 `http://<主机>:9400`),平台按间隔 GET `/metrics` 并解析(纯文本解析,零新依赖); - **控制台地址**(可空):APM 自托管控制台(默认 `127.0.0.1:9500`,建议开成内网可达), 用于详情页深链到「应用详情 / 问题定界 / 引擎健康」; - **拉取故障定界结论**:按应用拉 `/api/v1/fault-window` 的一句话归因(如「服务端处理慢 (TTFB 352ms)」),走 ClickHouse、较重,可关; - 采集失败**不抛异常**:错误写进配置行的 `last_error`,页面与提示语如实显示"连不上 APM"。 **拉两类数据,两种口径**: | 类别 | 指标 | 用途 | | --- | --- | --- | | 应用指标 | `apm_app_score` / `latency_p50_ms` / `latency_p99_ms` / `calls_total` / `error_calls_total` / `conns_total` / `conn_fail_total` / `conn_reset_total` / `retrans_total` / `zero_window_total` / `bytes_total` | 落 `ApmAppMetric`(按应用裁剪历史),进应用链路第六段、大屏、告警 | | 引擎指标 | `apm_capture_packets/drops`、`apm_xdp_drops`、`apm_spill_*`、`apm_sink_ch_healthy`、`apm_flowstore_healthy`、`apm_store_segments`、`apm_flowstat_*`、`apm_port_messages_total{port,state}` | 落 `ApmEngineMetric`,判断"镜像到底有没有在好好采" | **累计值 vs 本周期值(这一节最容易看错,务必分清)**:APM 导出的 `apm_app_calls_total` / `_error_calls_total` / `_conns_total` / `_conn_fail_total` / `_retrans_total` / `_zero_window_total` / `_bytes_total` 是**自它进程启动以来的累计计数器**(重启即归零), 只有 `apm_app_score` 与 `latency_p50/p99_ms` 是 APM 自己的聚合窗口值(默认 10 秒)。 所以平台**存原始累计值,在读取时按相邻两次采集的增量算「本周期」值**(`interval_stats()`): - 页面与告警里的「错误率」是**本周期错误率** = Δ错误 / Δ调用(`MIN_CALLS_FOR_RATE = 20`, 样本不足时这一条不判、页面写「样本不足未判」,绝不拿累计比冒充当前状态—— 累计比会让一次历史错误长期挂红(误报),APM 重启归零后又瞬间「痊愈」(漏报)); - 应用详情页四个数字卡片标的是「**本周期**调用/错误、重传/零窗口、会话/建连失败」, 并另给一行「自 APM 启动累计」;健康分 / p50 / p99 则标「APM 窗口」; - 首个采样点、APM 重启后的第一点(计数器回退)都算「增量不可用」,相关规则不判。 **「没有应用数据」区分三种原因,都不算应用故障**(平台「拿不准就标未知」的老规矩): 1. **镜像没有业务流量** → 两次采样的收帧计数不增长 → 引擎异常「镜像口没有流量」; 2. **有流但没有解析出调用** → 流记录在涨而会话层调用不涨 → 引擎异常「检查端口白名单 / appmap / 协议开关」(这是最容易踩的坑); 3. **APM 没在跑 / 连不上** → 整次采集失败,`last_error` 如实记录。 只有背景流量(有帧无流记录)时**不报异常**,只给一句「镜像上只有背景流量,还没有业务流量」; 首次采样(只有一个点)不下结论,等下一个采样点——避免拿单点数据误报。 **接进应用全链路(第六段「镜像流量」)**:应用详情页的全链路健康多一段「镜像流量」 (健康分 / 错误率 / p99 / 定界结论),综合口径不变(就高合成、**未知不算故障**); 接入没启用时这一段不出现,链路仍是五段。 - **应用 ↔ APM 应用名**:应用表单新增「APM 应用名」字段(下拉是 APM 里出现过的应用名), 两边名字不一致时手工指定,留空则按应用名匹配; - **appmap 导出**:应用列表页「⬇ 导出 appmap」把登记的应用导出成 APM 的 `appmap.entries` 片段(`cidr: IP/32` + `ports` + `app`),人工粘贴进它的 `collector.yaml`——**平台不写 APM 的配置**,一步人工确认反而更可控; - **告警规则**新增来源「镜像流量(APM)」,五个指标:`apm_score`(应用健康分, **低于**阈值告警——方向与其余指标相反,低于阈值一半记严重)、`apm_err_rate`(本周期错误率 %, Δ错误/Δ调用;样本不足或首个采样点不判)、`apm_p99`(p99 延迟 ms,APM 窗口值)、 `apm_retrans`(**本周期新增**重传次数)、`apm_engine` (引擎异常,**不看阈值**,配了规则就报,内容写明是哪一条问题)。去重沿用 `interval_minutes`;**没有应用数据不告警**(未知不报故障)。 - **三段定界进应用详情**(v1.6 起):应用详情的「镜像流量」卡片多一张表——该应用最近 60 分钟按 p99 倒序的接口/语句排行,每行给出 **TTFB / TXFER / GAP** 三段 p99 与 **判读结论**(谁的问题:服务端处理慢 / 链路丢包 / 客户端思考时间…,规则与 APM 控制台 同源),回答的是"慢在哪一段"。走 APM 的 `/api/v1/segments`(ClickHouse),**按需拉一次** (只在打开页面时拉,不在体检周期里拉),受「拉取故障定界结论」开关控制;拿不到就只有 一行说明,不影响其余数据。另补一个「报文归档(pcap 取证)」深链。 - **报表新增「应用与镜像流量」版块**:总体情况多一行「应用全链路(严重 / 警告)」; 正文新增第七章——应用分档、需要关注的应用(带判定依据)、镜像流量引擎状态与应用分档 (健康分 / p99 / **本周期错误率**);风险清单多四条:应用全链路严重(高)、 应用有警告(低)、镜像流量采集引擎异常(高)、镜像流量侧应用异常 / 拉取失败(中)。 全部只读库,不会去连 APM 或翻 ClickHouse 明细。AI 点评的输入里也带上了这一版块。 - **监控大屏**新增「镜像流量(APM 旁路分析)」独立一块:引擎状态徽标 + 分档统计 + 累计收帧 / spill 待重放 + 应用分数排行(健康分 / p50·p99 / 本周期调用 / 错误率 / 重传 / 建连失败 / 定界结论)+ 到 APM 引擎页的深链。 - **测试**:`h3c_web/test_apm.py`(Prometheus 文本解析含 NaN/脏值/转义引号、归一化、 落库与裁剪、健康分三档与错误率/p99 抬档、数据过期→未知、引擎五类问题与"首次采样不下 结论""只有背景流量不误报"、告警方向与级别、采集成功/失败、链路第六段的出现与消失、 页面与 appmap 导出、只读角色)。 **当前环境实况**(192.168.255.131 上跑着 APM,镜像口 `ens224`):引擎健康、pcap 归档 在滚,但**镜像上还没有业务流量**(只有背景噪声),所以应用级指标是空的——先在 EVE-NG 里把业务网段的镜像配到 `ens224`,应用分数才有数据;在那之前平台会如实显示「未知」, 不会编造健康度。 ## 多地区管理(Region) 「地区管理」页(`/regions/`)维护一套可父子嵌套的地区层级(如 华北 → 北京一区)。 设备与 IP 地址段都能归属地区,从而按地区分别统计与筛选。 - **层级列表**:按「排序 + id」展开成缩进树,每行显示归属设备数与地址段数; 支持新增(`/regions/add/`)、编辑(`/regions/<id>/edit/`)、删除。 - **字段**:地区名称(全局唯一)、上级地区(留空即顶级)、排序(1–9999)、备注。 - **校验**:名称必填且不可重名;编辑时上级不能选自身或自己的子地区(会被忽略并归为顶级)。 - **删除规则**:仍有子地区时拒绝删除,需先处理子地区;删除成功后自动解除该地区下设备与 地址段的归属(置空),**不**级联删除设备或地址段;删除上级后其子地区自动提升为顶级。 - **筛选语义**:选中某地区时,统计范围包含它的**全部子地区**;未绑定地区的设备/终端 只在「全部地区」视图里出现。 - **设备归属**:设备新增/编辑表单(`/device/add/`、`/device/<id>/edit/`)已有「所属地区」 下拉(含层级缩进,可留空为未归属);地址段表单同样可选地区。批量编辑与 CSV 导入暂不含 地区列,需要时经 `/admin/` 调整。 - **与权限的关系**:地区本身只做归属与筛选;一旦给账号划了「数据范围」(见下方 「用户与权限(RBAC)」),设备、终端与地址段就只在这些地区(含子地区)内可见。 ## IP 地址段管理(IPAM) 「IP 地址段(IPAM)」页(`/ipam/`)管理网段规划,并以网关 ARP 采集结果为事实来源做地址对账, 回答「每个网段用了多少、哪些网段压根没规划」。 **数据来源**:「终端信息」采集落库的 `TerminalEntry`(网关交换机 ARP 表,一条终端一行, `ip` 字段逗号分隔该终端学到的全部 IP)。IPAM 只做计算与落库,自身不发任何网络请求, 所以**先在「终端信息」页采集(或配好定时采集)再看 IPAM**,数据才有意义。 - **地址段列表**:每行显示 网段 / 地区 / 名称·用途 / 可用容量 / 已用(ARP) / 已用(库) / 使用率 / 状态;概览卡给出 地址段总数、ARP 学得地址数、已用地址(线上)、可用容量、 未规划网段数;支持地区筛选,每页 20 条。 - 可用容量:IPv4 去掉网络号与广播地址(/24 记 254),IPv6 全算。 - 已用(ARP) 是本轮 ARP 实时学到、落在该网段内的地址数;已用(库) 是地址表里状态为 「已用」的行数;使用率按 已用(ARP) ÷ 可用容量 计算,上限 100%。 - **新增 / 编辑地址段**(`/ipam/subnet/add/`、`/ipam/subnet/<id>/edit/`):CIDR 必填且全局 唯一(自动规范化,如 `192.168.56.1/24` 存为 `192.168.56.0/24`);另可填 地区、名称、 用途(办公网络 / 设备管理 / 服务器 / 无线网络 / 物联网·终端 / 其他)、网关地址、VLAN、 状态(规划中 / 在用 / 停用)、备注。 - **批量导入**(`/ipam/import/`):粘贴多行文本,每行一个网段,格式 `网段 [名称] [用途] [网关] [VLAN]`,用 Tab / 多空格 / 逗号分隔,仅第一个字段必填, `#` 开头为注释;可统一指定归属地区。已存在的网段自动跳过,结果分别列出 新增 / 跳过 / 失败(带行号与原因)。 - **地址段详情**(`/ipam/subnet/<id>/`):地址级台账。地址行 = 库内 `IpAddress` ∪ ARP 实时见到的地址(库里没有的以「已用(ARP)」只读行补上),按 IP 升序排列;可新增地址 (默认「预留」,越界或重复会被拦截)、逐行改状态(空闲 / 已用 / 预留)与用途/备注、 删除单行;页面同时给出容量、已用、空闲、使用率与 ARP 实时已用数。 - **🔄 ARP 对账**:把本轮 ARP 学到的 IP 对入 IPAM——命中已规划网段的地址,库里没有就 新建为「已用」,已存在则刷新「最后发现」,原状态为「空闲」的自动改「已用」;对不上的 计入「未规划」。**不回收地址**(历史占用保留,避免终端临时离线就被判成空闲)。 对账动作写入「任务监控」(类型「终端采集」、名称「IPAM ARP 对账」),全部命中记成功、 存在未规划地址记部分成功,详情里带完整统计。 - **🔔 未规划网段告警**:对 ARP 学到但未匹配任何地址段的网段生成告警(来源 「IPAM 网段对账」、级别「错误」),内容含网段、终端数与最多 8 个地址预览,入「告警中心」 并沿启用的通道推送;同一网段 24 小时内只告一次(去重窗口见 `ipam.UNPLANNED_ALERT_HOURS`),窗口内重复点击会提示「没有新增」。 - **⚠️ IP 冲突检测**:同一 IPv4 被**两个及以上不同 MAC** 学到即判为冲突(重复配置静态 IP、 私接设备或 ARP 欺骗)。页面统计卡给出冲突数,下方列出 冲突 IP / 所属网段 / MAC 数 / 逐条命中位置(MAC · 设备 端口 · VLAN);点「⚠️ IP 冲突告警」为每个冲突 IP 生成一条 告警(来源「IPAM IP 冲突」、级别「严重」),同一 IP `ipam.CONFLICT_ALERT_HOURS` (默认 24 小时)内只告一次。「ARP 对账」按钮会顺带跑一遍冲突告警。 - **♻️ 闲置地址回收**:台账里标记「已用」但连续 N 天(默认 30,可调 1–3650)没在 ARP 中 出现的地址视为闲置。页面先给统计数,填天数点「预览闲置地址」(`?reclaim=1&days=N`) 列出 网段 / 地址 / MAC / 闲置天数 / 用途备注,确认后一键回收为「空闲」并清掉 MAC。 **预留(reserved)与空闲地址一律不动**,本轮 ARP 仍见到的地址也不动;回收动作写操作审计。 定时任务「IPAM 对账与告警」只统计闲置数量,不自动回收。 - **删除地址段**:级联删除其下全部地址明细。 ## IP 使用详情(基于 ARP 的网段使用报告) 「IP 使用详情」页(`/ip/usage/`)是面向「先看现状」的报告页,**不需要事先规划地址段**: 它把 ARP 学到的全部 IP 直接归并成网段展示。 - **网段归并规则**:优先命中 IPAM 中状态为「规划中 / 在用」的地址段;命中不了则按 `/24` 兜底成网段并标记「未规划」。因此同一份 ARP 数据,规划过的按规划口径统计,没规划的也看得见。 - **表格**:网段 / 归属地区 / 状态(已规划·未规划)/ 容量 / 已用 / 使用率 / 地址明细 (该网段学到的 IP 列表);已规划网段排在前面,未规划网段的容量按 /24 记 254。 概览卡给出 网段总数、已规划网段、未规划网段、学得终端地址、覆盖容量。 - **地区筛选**:与 IPAM 一致(含子地区);未绑定设备的终端只在「全部地区」下出现。 - **🔄 ARP 对账 / 🔔 未规划网段告警**:与地址段列表页同一套逻辑,可在本页直接触发。 - **一键规划**:页底「未规划网段」清单列出每个网段的终端数与地址预览,点「一键规划」 跳转到新增地址段表单并预填该 CIDR。 - **导出 CSV**:`/ip/usage/?export=csv`,列为 网段 / 归属地区 / 状态 / 容量 / 已用 / 使用率% / IP 明细,UTF-8 带 BOM(Excel 直接打开不乱码),文件名带时间戳。 ## 服务器证书(私钥)登录 Linux 服务器普遍禁用口令登录、只认公钥。平台的设备档案里,「认证方式」可以在 **口令**与**私钥(证书登录)**之间选——选了私钥之后,**所有需要 SSH 的地方**(主机信息 采集、网络设备的采集与配置备份、网页 SSH 终端、堡垒机会话、RDP 中继主机编排、录像取回) 统一改走证书,不用逐处配置。 - **粘私钥就够,不用先导出公钥**:保存时平台当场解析(`h3c_console.load_private_key`), 格式不认识、粘贴不完整(缺 `-----END`)、有口令没填、口令错,都会在表单上直接报错并 说明怎么改;坏密钥不会被存进库。 - **编辑页会给公钥与指纹**:指纹口径与 `ssh-keygen -lf` 完全一致(`SHA256:…`,可直接与 目标机比对),公钥整行可一键复制进 `~/.ssh/authorized_keys`。 - **私钥只存密文**:与设备口令同一套 Fernet 加密(`crypto.encrypt_secret`);页面永不回显 (留空 = 不修改),操作审计的字段排除表里也有它俩,CSV 导出只带「认证方式」一列、 **不带私钥**——CSV 会被随手转发,口令能改、私钥不能。 - **选了私钥就不回退口令**:证书登录按证书判成败(`pkey` 单独用,不给口令兜底), 这样「连不上」一定是证书链路的问题,而不是被口令掩盖成「偶尔能连、偶尔不能」。 要口令兜底就把认证方式切回口令——两种方式都在档案里,随时可切。 - **连不上会说清是哪一种**:公钥没部署(`authorized_keys`)、目标机不允许公钥登录 (`sshd` 的 `PubkeyAuthentication`)、私钥口令错,提示各不相同;公钥没上机时 sshd 常常不回明确错误、表现为**超时**,提示里也会点明这种可能(实机踩过)。 - **换平台密钥不锁死**:私钥密文由 `SECRET_KEY`/`H3C_CRYPTO_KEY` 派生,换密钥后解不开, 编辑页会直接提示「已存的私钥解不开,请重新粘贴」;重新粘贴即可,设备档案其它字段不受影响。 - **实现上只有一处判凭据**:`device_console/ssh_creds.py` 是「这台设备用口令还是私钥」的 唯一出处(`client_kwargs` / `make_client` / `raw_client`),加第三种方式时只改这里, 不会出现「某些页面能连、某些不能」的静默偏差。 ## 用户与权限(RBAC) 「用户与权限」页(`/users/`,**仅管理员可见**)管账号的角色与数据范围。角色存在 `UserProfile`(一个用户一条,按需自动创建),**超级用户恒为管理员**,不看本表。 | 角色 | 能做什么 | | --- | --- | | 只读 viewer | 只能看:页面照常打开,任何写操作(POST/PUT/PATCH/DELETE)被拦成 403 | | 运维 operator | 日常运维全开:采集 / 巡检 / 合规 / 备份 / 改设备与网段 / 批量执行 / 网页终端改配置 | | 管理员 admin | 运维的全部,外加管账号与角色、划数据范围、清理审计与日志 | - **默认角色**:新账号默认「运维」——与引入 RBAC 之前「登录即可操作」的行为一致,升级后 不会集体失去写权限;要收紧用环境变量 `H3C_DEFAULT_ROLE=viewer|operator|admin` 改默认值。 - **只读拦截在一处兜住全站**:`middleware.RoleMiddleware` 对非安全方法统一判定,不给上百个 视图逐个加装饰器(免得漏);管理员专属页另用 `authz.admin_required` 细分。豁免路径: `/login`、`/logout`、`/admin/`(Django 自带 is_staff 校验)、`/telemetry/push` (设备侧免登录推送)、`/api/`(走自己的鉴权)。 - **数据范围(按地区)**:给账号勾选地区后,设备、终端、地址段只在这些地区**含子地区**内 可见,留空即不限;未绑定地区的设备在限定范围时不可见。所有「列设备 / 列网段 / 列终端」 的查询统一走 `authz.scope_devices() / scope_subnets() / scope_terminals()`, 页面与 CSV 导出口径一致。 - **页面提示**:右上角显示角色徽章;只读账号额外挂「只读模式」标记;导航里的 「用户与权限」只对管理员出现,权限不足时统一渲染 403 说明页(当前角色 / 所需角色)。 - **防自锁保护**:不能改自己的角色、不能停用或删除自己;降级 / 停用 / 删除前都会校验 「是否还有其他启用的管理员」,不让平台失去最后一个管理员。给超级用户改角色只影响展示, 实际权限仍是管理员(审计里会标注)。 - **账号操作**:建号(用户名 / 密码 ≥6 位 / 姓名 / 邮箱 / 角色 / 备注 / 数据范围)、 改角色、改数据范围、停用与启用、重置密码、删除;重名与过短密码会被拒,每个动作都写审计。 - **代码里判权限**:`authz.role_of(user)` / `can_write(user)` / `is_admin(user)`; 视图加 `@authz.write_required` 或 `@authz.admin_required`; 需要自己返回拒绝页时用 `authz.denied_response(request, authz.ROLE_ADMIN)`。 ## 账号双因子(TOTP) 口令是**一道**门,双因子是第二道门:开了之后,登录要多给一个验证器 App 上每 30 秒 变一次的 6 位码。**这是可选项**——管理员不强制,谁觉得自己的账号值钱就自己开: 顶栏「🔐 账号安全」(`/account/mfa/`)里三分钟搞定,只读账号也能开。 为什么用 TOTP 而不是短信:平台是内网自建,没有短信通道,也不该为登录去外部服务发码。 验证器用任意标准 App 都行(Google / Microsoft Authenticator、1Password、微信小程序 「腾讯身份验证器」),服务器与手机各自按时间算同一个码,不联外网。 - **绑定三步**:点「开始绑定验证器」→ 扫码(扫不了手抄密钥)→ 把 App 上出现的 6 位码 填回来确认。**没确认不生效**:只扫码不验证,就会出现「扫完没存住」的糊涂状态。 - **10 条备用码**:确认后一次性显示(页面只显示这一次),手机丢了或验证器时间不对时 代替动态码登录;**用一条少一条**,登录后到本页可重新生成(要双证:口令 + 一个验证码)。 - **登录变成两步**:口令过了**还不算登录**,页面跳到 `/login/mfa/` 要码;待验证状态 5 分钟 有效,连续错 5 次锁 5 分钟;同一个码 30 秒内不认第二次;允许 ±30 秒时钟偏差 (手机与服务器差几十秒是常态)。 - **绕不过去**:`MFAEnforceMiddleware` 统一兜住那些「只看 `user.is_authenticated`」的路子 ——Django 自带的 `/admin/login/`、API 的会话鉴权、开启双因子之前就存在的浏览器会话; 没有「已完成第二步」标记的会话会被降级成待验证(带上原地址,验完落回原页面), 会话里不留任何半登录痕迹。 - **换密钥不锁死人**:TOTP 密钥用 Fernet 加密存(`UserProfile.mfa_secret`),换 `SECRET_KEY`/`H3C_CRYPTO_KEY` 后动态码必然失效——**备用码刻意不依赖 SECRET_KEY** (每账号随机盐 + SHA-256 存摘要),这时它仍是入口:用备用码登录 → 重新绑定。 - **手机和备用码都丢了**:找管理员在「用户与权限」页点「重置双因子」。重置后回到只有口令, 密钥与备用码作废,动作写审计。上线体检里也有一项「双因子覆盖」看管理员开没开(只报建议)。 ## 操作审计(ChangeLog) 「操作审计」页(`/audit/`)回答「谁、从哪个 IP、对什么对象、做了什么改动」,与 「指令日志」(网页下发的每条命令)、「终端操作日志」(网页终端会话)互补。 - **自动留痕**:模型层信号(`audit_signals`)监听白名单模型的增删改——设备、设备分组、 地区、IP 地址段、告警规则与通道、AI 配置、定时任务、大屏设置、机房四层 (楼栋 / 楼层 / 机房 / 机柜)。采集、监控、日志类高频写入的表**不跟踪**,避免噪音。 - **记什么**:动作(新增 / 修改 / 删除 / 执行 / 账号 / 其它)、对象类型与标识、对象名称、 详情(修改时逐字段列「旧 → 新」,最多 40 个字段)、操作人(`username` 冗余存一份, 账号被删后仍能追溯)、来源 IP(优先 `X-Forwarded-For` 首段)、时间。 - **不记什么**:主键、时间戳、密码 / API Key / SMTP 密码等密文字段,以及机器回写字段 (设备 `online`/`last_online_at`/`model`/`serial`,任务 `last_run_at`/`last_status` 等); 跟踪字段没有实际变化时也不写,同值保存不留噪音。 - **高危动作显式记**:网页终端开会话、单设备执行命令、批量执行、变更工单的提交 / 批准 / 驳回 / 执行 / 回滚 / 删除、清理任务 / syslog / 终端日志、账号管理动作、 AI 助手提问与告警根因分析,都在视图里显式调 `authz.audit_request()` 补一条。 - **后台线程**:调度器、采集、大屏轮询不走中间件,操作人记为「系统」。 - **页面能力**:按动作 / 对象类型 / 关键字(操作人、对象名、详情)/ 起止日期筛选,每页 50 条; 顶部统计卡给出 总条数、今日、删除动作、账号动作;`?export=csv` 导出(UTF-8 带 BOM, Excel 直接打开不乱码);管理员可「清理」,保留最近 500 条。 - **兜底与开关**:写审计失败一律静默(审计不该把业务操作搞崩);排查问题或极端写入压力下 可设 `H3C_AUDIT_DISABLED=1` 完全关闭。 ## 平台自检(页面冒烟巡检) 「平台自检」页(`/selfcheck/`,导航「巡检与安全 → 🩺 平台自检」)让**平台自己点一遍关键页面**。 **为什么需要它**:76 个测试脚本跑在**独立测试库**上,验证的是**代码逻辑**;而"用户打不开页面" 绝大多数是**真实数据 + 真实配置**触发的——模板里除零、空列表渲染、迁移没跑、某台设备的回显 把解析器噎住、后台任务写坏一行数据。这类问题测试可以全绿、线上却是 500。2026-10-05 就实发过两次: 一次是分支被切走导致安全基线与堡垒机页面集体 404,一次是模板注释被当正文渲染到页面上 (`{# #}` 写成多行)—— 都是"没人去点页面就发现不了"。 每条检查断言三件事:**HTTP 状态码**、**必须出现的区块文本**(`expect`)、**绝不该出现的文本** (`Traceback` / `服务器错误` / 没渲染出去的 `{{` `{%`)。**只看状态码是最常见的假绿**——模板报错被吞、 区块没渲染、被中间件挡到登录页,HTTP 都还是 200。`expect` 只写骨架级稳定文本(标题、区块名), 不写业务数据;超过 8 秒判「警告」不改判失败(真实库首屏偏慢是体验问题)。 实现是**本进程内**用 Django 的测试 Client 直接调视图:不依赖 8000 有没有起、不占端口, 生产 waitress 下同样能跑;只 GET 不改数据。结果落 `PageSmokeRun`/`PageSmokeResult`, 页面上看最近一轮逐页明细与历史,同时留档在任务监控里。 ## 后台服务与测试 **后台服务可与网页拆开部署**:定时调度、syslog 接收、遥测接收、大屏轮询、告警推送都是 进程内 daemon 线程,由 `device_console/background.py` 的注册表统一决定「哪些该在本进程启动」 ——过去只在 `runserver` 里起,换 waitress / gunicorn 部署会静默失效(网页正常但服务不跑)。 ```bash cd h3c_web python manage.py netpilot_worker --list # 只看会启动哪些服务 python manage.py netpilot_worker # 后台服务常驻(生产推荐) python manage.py netpilot_worker --only scheduler,syslog_server waitress-serve --listen=:8000 h3c_web.wsgi:application # 网页另起一个进程 ``` - 开发期照旧 `python manage.py runserver`(网页 + 后台一体);autoreload 的父进程只监听 文件变化,服务只在子进程启动,避免调度器 / syslog 各起两份。 - `H3C_BACKGROUND=1` 任何命令都强制启动,`=0` 强制不启动(调试 / 测试用); `migrate`、`shell` 与独立测试脚本默认不启动。 - 单个服务仍可关:`H3C_SCHEDULER_DISABLED` / `H3C_SYSLOG_DISABLED` / `H3C_TELEMETRY_DISABLED` / `H3C_SFLOW_DISABLED` / `H3C_BIGSCREEN_DISABLED` / `H3C_ALERTING_DISABLED` / `H3C_SECURITY_DISABLED`。 - 换库不改代码:`H3C_DB_NAME=/path/to/other.sqlite3`(测试隔离与多实例并存用)。 **跑测试**:`h3c_web/test_*.py` 是 67 个可独立运行的脚本(`exit 0` = 全部通过), 统一入口默认跑在**独立测试库**上,不碰开发库 `db.sqlite3`: ```bash cd h3c_web python run_all_tests.py # 全部脚本,串行 python run_all_tests.py -j 4 # 并行 4 个(同一个库同一时刻只跑一个脚本) python run_all_tests.py test_ipam.py # 只跑指定脚本(可多个) python run_all_tests.py -v --keep # 失败打印完整输出,并保留测试库供排查 python run_all_tests.py --dev-db # 直接跑在开发库上(旧行为) ``` 这些脚本大多是「建数据 → 断言 → 清理」的写法且直连数据库,所以并行时按测试库加锁: 两个脚本共用一个库并发跑会互删数据,出现随机假失败。子进程统一注入 `PYTHONIOENCODING=utf-8`(Windows 控制台默认 GBK,打印 `✔` 会抛编码异常)与 `H3C_BACKGROUND=0`。仓库带 GitHub Actions 工作流 `.github/workflows/ci.yml`,推送与 PR 自动跑「Django 自检 → 迁移一致性 → 部署体检 → 全量测试脚本」。 ## 运维报表(日报 / 周报) 「运维报表」页(`/reports/`)把平台里已有的数据——采集 / 巡检 / 监控 / 主机指标 / 遥测指标 / 合规 / 备份 / 告警 / syslog / IPAM / 终端 / 任务 / 审计——按天或按周聚合成一份 可存档、可推送的报告,回答「昨天(上周)网络到底怎么样、现在最该处理什么」。 **只读聚合,不触网**:所有数字都来自库里已有的记录,生成报表不会去连设备, 所以随时可以重复生成,也不会因为设备离线而卡住。 **统计区间**:日报=昨天一整天,周报=上周一到上周日(按服务器本地时区);页面上 也可以填开始 / 结束日期出自定义区间的报告(类型记为「自定义」,两个日期必须同时填, 填反了会自动交换)。 **报表内容**(详情页 `/reports/<id>/`): - **风险清单**:值班先看这一段就够。按 高 / 中 / 低 排序,规则是「有数据才提示」, 不会凭空造风险——定时任务超期未执行、设备离线、IP 地址冲突、告警未处理、 配置备份缺失或过期、配置发生变更、未规划网段、合规检查不通过、巡检发现异常、 主机资源严重不足、主机资源偏高、主机监控数据过期、服务器缺少主机指标、 交换机遥测指标严重、交换机遥测指标偏高、遥测推送中断、接口错包 / 丢包在涨、 任务执行失败、疑似闲置地址、终端归属歧义、本周期没有任何采集与巡检、 没有可用推送通道,共 23 条判定规则。 - **11 个版块**:总体情况、可用性与设备、告警与日志、巡检与监控、 **服务器与主机健康**、**交换机遥测**、合规检查、配置备份、IPAM 地址管理、 终端接入、任务与平台改动。每块都是「一句话摘要 + 明细表格」,排行榜取前 10 条、 明细最多列 20 条(其余只给计数),避免报表变成日志堆。 - **服务器与主机健康**(`reports._sec_hosts()`):与「服务器监控」页同一口径 (受监控范围=`host_agent.server_filter()`,判档=`host_agent.health()`)—— 受监控台数、健康分档(严重 / 警告 / 离线 / 未采集 / 正常)、Agent 与 SSH 各自台数、 CPU / 内存 / 磁盘的「当前平均」与「本周期峰值」、本周期指标条数与上报覆盖率; 再列三张明细表:需要关注的主机(含判定依据)、资源占用最高的主机、本周期一条 指标都没上报的主机。「当前健康」看每台主机最新一条指标,「本周期」只统计落在 报表区间内的指标,两者分开算,所以昨天的日报也能反映此刻的健康状况。 没有纳入监控的服务器时,这一节只留一句「怎么纳入」的引导,不编数字。 - **交换机遥测**(`reports._sec_telemetry()`):与「遥测数据」页同一口径 (`telemetry_metrics.health_summary()`)——有遥测数据的设备数、健康分档(严重 / 警告 / 中断 / 未采集 / 正常)、CPU / 内存的「当前平均」与「本周期峰值」、最高温度、 本周期指标条数与原始推送条数、上报设备覆盖率,再按指标类型给出条数分布;另有两张 明细表:需要关注的设备(含判定依据)与本周期**接口错包 / 丢包增长最多**的接口 (计数器取两次采样的差值)。「当前健康」看每台设备最新一批指标,「本周期」只统计 落在报表区间内的指标,两者分开算。没有遥测数据时只留一句「怎么配 telemetry 订阅」 的引导,不编数字。 - **AI 点评**:勾选「AI 点评」后,把关键汇总数据(不含逐条明细)交给当前 AI 提供方 写一段不超过 300 字的中文点评;没配 AI 或调用失败都不影响出报表,只在提示里说明原因。 **页面操作**: - **生成**:选类型(日报 / 周报)或填自定义区间,可选归属地区(含子地区)、 是否同时推送、是否要 AI 点评;生成后直接跳到详情页。 - **推送**:复用「告警中心 → 推送通道」里**已启用**的通道(企业微信 / 钉钉 / 飞书 / 邮件 / 自定义 webhook),正文超过 3500 字自动截断并补一句「完整报表见平台 #编号」; 逐通道的成功 / 失败原因记在报表里,列表页直接能看到推送状态。 - **下载**:`/reports/<id>/download/` 默认下载 Markdown 原文;`?format=json` 下载 完整聚合数据(供二次加工或对接报表平台);`?format=csv` 只下载风险清单。 文本一律 UTF-8 带 BOM,Excel / 记事本打开不乱码。 - **筛选与清理**:列表支持按类型、报表覆盖区间(起止日期)与标题关键字筛选, 每页 20 条;「清理旧报表」保留最近 200 份(仅管理员)。 **权限与审计**:报表按登录用户的**数据范围**聚合——只划了几个地区的账号,生成的报表 里就只有它看得到的设备与网段。生成 / 推送 / 删除 / 清理都写「操作审计」(对象类型 `report`),只读角色由中间件直接拦下。 **代码入口**:聚合逻辑在 `device_console/reports.py`——`build_data()` 只算不入库(预览、 测试用它)、`generate()` 算完入库并可选推送 / AI 点评、`to_markdown()` 出正文、 `build_risks()` 出风险清单;报表模型是 `models.ReportRecord`。 ## 只读 REST API(/api/v1) 给监控大屏、值班脚本、第三方平台取数用。**只读**:所有端点只接受 GET(其它方法返回 405),不暴露任何改设备、下发命令、删数据的能力——写操作仍走网页,那里有角色拦截、 二次确认与操作审计。 ### 令牌 令牌在「系统设置 → API 令牌」页签发(仅管理员可见),绑定一个平台账号: - **权限不超过所属账号**:返回的数据范围与该账号在网页上能看到的一致(复用同一套 地区数据范围);账号被停用、降权或删除,令牌立刻跟着失效。 - **明文只显示一次**:库里只存 SHA-256 摘要,页面只留前 12 位用于辨认;忘了就重新 签发一把。可随时停用 / 启用 / 吊销,页面上能看到调用次数、最近使用时间与来源 IP。 - 给外部系统建议单独建一个「只读」账号再签发令牌,并设置过期时间(默认建议 90 天)。 三种带令牌的写法任选其一(也支持已登录的浏览器会话直接打开看 JSON): ```bash curl -H "Authorization: Bearer np_xxx" http://127.0.0.1:8000/api/v1/summary/ curl -H "X-Api-Token: np_xxx" http://127.0.0.1:8000/api/v1/devices/ curl "http://127.0.0.1:8000/api/v1/alerts/?token=np_xxx&hours=24" ``` ```python import requests HEADERS = {"Authorization": "Bearer np_xxx"} BASE = "http://127.0.0.1:8000/api/v1" offline = requests.get(f"{BASE}/devices/", params={"online": 0, "limit": 200}, headers=HEADERS, timeout=15).json() print(offline["count"], [d["ip"] for d in offline["results"]]) ``` ### 端点 `GET /api/v1/` 返回索引(身份、限制、全部端点与说明),可以自助发现,不用翻文档。 | 端点 | 说明 | 主要参数 | | --- | --- | --- | | `/api/v1/` | 索引:身份 / 角色 / 数据范围 / 端点清单 | — | | `/api/v1/summary/` | 平台总览计数:设备、告警、syslog、IPAM、终端、巡检、合规通过率、任务、备份覆盖 | — | | `/api/v1/regions/` | 地区树(平铺 + `parent_id` / `depth`) | — | | `/api/v1/devices/` | 设备列表 | `q` `region` `group` `vendor` `role` `online` `ordering` | | `/api/v1/devices/<id>/` | 设备详情:最近巡检 / 监控 / 合规 / AI 巡检 + 告警计数与最近 5 条 + 备份清单 + LLDP 邻居 + 终端与 syslog 计数 | — | | `/api/v1/topology/` | LLDP 拓扑:`nodes` + `links`(只在同分组内成立)+ 未识别邻居 + `cross_group_neighbors`(对端在别的分组)+ 结构统计(孤立点 / 度数 / 网关数 / 分组清单)+ `scope.group` | `group`(分组主键或**完整**分组名,`0`=未分组;认不出的分组名返回空结果而不是全库数据) | | `/api/v1/alerts/` | 告警记录 | `source` `severity` `status` `device_ip` `q` `hours` | | `/api/v1/syslog/` | syslog 日志 | `severity` `device_ip` `tag` `q` `hours` | | `/api/v1/inspections/` | 巡检记录 | `device` `healthy` `run_id` `hours` | | `/api/v1/compliance/` | 合规检查结果 | `run` `device` `policy` `ok` `hours` | | `/api/v1/monitor/` | SNMP 监控采集记录(CPU / 内存) | `device` `hours` | | `/api/v1/telemetry/` | 遥测数据 | `node` `device` `sensor_path` `unmatched` `hours` | | `/api/v1/telemetry-metrics/` | 遥测指标(从推送里抽出的结构化数值,计数器类带 `counter` 标记,增量由调用方自己算) | `device` `metric` `label` `node` `latest` `hours` | | `/api/v1/terminals/` | 终端信息(ARP + MAC 表关联结果) | `device` `vlan` `q` `ambiguous` `hours` | | `/api/v1/subnets/` | IPAM 地址段与使用率 | `region` `status` `purpose` `vlan` `q` `usage` | | `/api/v1/subnets/<id>/` | 地址段详情与地址明细(含 ARP 实时见到但未入库的地址) | `status` `q` | | `/api/v1/ip-addresses/` | IPAM 地址明细 | `subnet` `status` `device` `q` | | `/api/v1/backups/` | 配置备份文件清单(只读元数据) | `ip` | | `/api/v1/tasks/` | 任务监控记录 | `task_type` `status` `trigger` `q` `hours` | | `/api/v1/audit/` | 操作审计(**仅管理员令牌**,其它返回 403) | `action` `username` `object_type` `q` `hours` | ### 约定 - **信封**:列表统一返回 `{"count": N, "limit": L, "offset": O, "next_offset": O|null, "results": [...]}`;`count` 是过滤后的总数,翻到最后一页时 `next_offset` 为 `null`。 错误统一返回 `{"error": "说明", "code": "错误码"}` + 对应 HTTP 状态码 (`401 unauthorized` / `403 forbidden` / `404 not_found` / `405 method_not_allowed` / `500 server_error`)。 - **分页**:`?limit=100&offset=0`,`limit` 默认 100、上限 500。 - **时间窗**:`?hours=24`,传负数(`hours=-1`)表示不限时间;各端点默认窗口见上表说明。 - **排序**:设备列表支持 `?ordering=ip`/`-updated_at`(可排序字段:`id` `ip` `name` `online` `vendor` `role` `updated_at` `last_online_at`)。 - **过滤取值**:`region` / `group` / `device` 都同时接受 id 与名称(IP)片段, 地区命中后自动包含其所有子地区。 - **不外泄凭据**:响应里刻意不含设备登录名与密码、SNMP 社区字、AI Key、告警 webhook 密钥,也不含备份文件的服务器绝对路径;设备详情只用 `credential_set` / `snmp_community_set` 这样的布尔值说明「有没有配」。 - 实现见 `h3c_web/device_console/api.py`,令牌模型见 `models.ApiToken`; 鉴权装饰器 `api_get` 统一做「只读校验 + 令牌鉴权 + 异常兜底」,视图内部一律用 `authz.scope_*` 收窄数据范围。 ## 上线部署体检 平台是内网工具,默认配置偏开发态(`DEBUG=1`、示例 `SECRET_KEY`、`admin/admin`)。 真要放到生产环境跑,先用体检命令过一遍——它只读、不触网、不写库,把「能不能上线」 拆成 21 项可自动判定的检查,给出 `OK / WARN / FAIL` 三级结论: ```bash cd h3c_web python manage.py check_production # 逐项体检;有 FAIL 时退出码 1 python manage.py check_production --json # 机器可读输出(CI / 巡检脚本用) python manage.py check_production --strict # WARN 也算不通过 python manage.py check_production --list # 列出所有检查项 key python manage.py check_production --only debug,secret_key,backups ``` 输出示例(开发态直接跑,就能看到该改的地方): ```text [FAIL] 调试模式 DEBUG 开着:报错页会泄露路径与配置,上线前设 H3C_DEBUG=0 [FAIL] SECRET_KEY 还在用 Django 示例默认 SECRET_KEY:设 H3C_SECRET_KEY 换掉 [FAIL] 管理员口令 管理员仍是弱口令:admin(=admin),上线前必须改 [WARN] 密文密钥 未设 H3C_CRYPTO_KEY:设备密码等密文由 SECRET_KEY 派生… [OK] 备份覆盖 5 台设备全部有备份 体检完成:21 项,通过 12,建议处理 5,必须处理 4 ``` 检查项覆盖五类问题,新增检查只要往 `device_console/deploy_check.py` 的 `CHECKS` 里加一个 `_c_xxx(ctx)` 函数: | 分类 | 检查项 | 说明 | | --- | --- | --- | | 基础配置 | `debug` `secret_key` `crypto_key` `allowed_hosts` `cookie_flags` `static` | DEBUG 是否关闭、密钥是否还是示例值、密文密钥是否与 SECRET_KEY 解耦、Host 白名单、HTTPS Cookie 加固、静态文件托管 | | 账号权限 | `admin_account` `default_role` | 超级用户是否存在、是否仍是 `admin/admin` 一类弱口令、新用户默认角色是否过大 | | 数据库 | `migrations` `model_changes` | 有没有未执行的迁移、模型改了却没生成迁移文件 | | 容量与备份 | `disk` `logs` `retention` `backups` `backup_coverage` | 磁盘余量、日志文件是否异常增长、保留策略是否合理、最新备份多久前、哪些设备压根没备份 | | 服务链路 | `background` `scheduler` `alerting` `devices` `telemetry_token` `ai` | 后台服务是否在跑、定时任务有没有超期未执行、告警规则有没有可用推送通道、设备台账与凭据、遥测推送口是否有令牌、AI 服务商是否可用 | - 退出码:有 `FAIL` → `1`(`--strict` 时 `WARN` 也算),检查项名写错 → `2`, 可直接串在发布流水线里当门禁。 - 建议上线前把这些环境变量配上:`H3C_DEBUG=0`、`H3C_SECRET_KEY`、`H3C_CRYPTO_KEY`、 `H3C_ALLOWED_HOSTS`、`H3C_TELEMETRY_TOKEN`,并把网页与后台拆成两个进程 (`waitress-serve` + `netpilot_worker`)。 - 改完 `SECRET_KEY` 前先看 `H3C_CRYPTO_KEY`:没设独立密文密钥时,旧的设备密码密文 会解不开。