嘉庚创新实验室共享计算资源(HPC/NPU)的使用量监控、计费统计与账号管理平台。
校内访问地址:http://10.26.15.53:18788
| 模块 | 功能 | 状态 |
|---|---|---|
| HPC 用量监控 | 每日自动采集 Slurm sacct 作业记录,按用户/按天计算核时(core-hours) | ✅ 已上线 |
| 可视化图表 | 堆叠柱状图展示每日核时分布,排行榜展示用户用量排名 | ✅ 已上线 |
| 计费数据库 | SQLite 存储全历史 HPC 核时数据,支持按日期范围查询与按计费组聚合 | ✅ 已上线 |
| 用户认证 | 注册/登录/登出,PBKDF2-SHA256 密码哈希,Session Cookie,登录失败锁定 | ✅ 已上线 |
| 账号管理 | 用户自助申请 HPC/NPU 账号、停用/启用、凭证查看;管理员管理所有账号 | ✅ 已上线 |
| 角色权限 | admin(全量查看 + 用户管理) / user(个人页面 + 自助管理) | ✅ 已上线 |
| 管理后台 | 用户列表、角色设置、密码重置、账号停用/启用/凭证重置 | ✅ 已上线 |
| 核时统计 | 个人统计页(日期筛选 + 按账号明细)+ 管理员统计页(全员排行 + 按组聚合) | ✅ 已上线 |
| 审计日志 | 所有敏感操作(登录、管理操作)写入 audit_log | ✅ 已上线 |
| NPU 用量采集 | Ascend 卡时统计 | ⏳ 规划中 |
| HTTPS | TLS 加密传输 | ⏳ 待部署 |
| 计费报表导出 | 月度/季度账单导出 | ⏳ 规划中 |
单容器部署,基于 nginx:alpine,容器内运行三个核心进程:
┌─────────────────────────────────────────────────────────┐
│ Docker Container │
│ (nginx:alpine, --network host) │
│ │
│ ┌──────────┐ ┌──────────────┐ ┌─────────────────┐ │
│ │ nginx │ │ crond │ │ auth_server.py │ │
│ │ :18788 │ │ 03:00 daily │ │ 127.0.0.1:28790│ │
│ │ │ │ │ │ │ │
│ │ 静态HTML │ │ update- │ │ 认证/注册/ │ │
│ │ /api/auth│──→│ slurm.sh │ │ 账号管理/统计 │ │
│ │ 反代 │ │ │ │ │ API 服务 │ │
│ └──────────┘ └────┼─────────┘ └─────────────────┘ │
│ │ │
│ ┌────────────────┼────────────────┐ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ collect_slurm aggregate_hpc init_db.py │
│ .py .py (首次/迁移) │
│ │ │ │
│ ▼ ▼ │
│ slurm_daily hpc_daily 表 │
│ .json (SQLite) │
│ (图表数据) (计费数据) │
│ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ /opt/db-data/usage.sqlite (SQLite WAL, schema v5)│ │
│ │ /usr/share/nginx/html/data/slurm_daily.json │ │
│ └──────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
│ │
│ SSH + sacct │ HTTP :18788
▼ ▼
┌──────────────┐ ┌──────────────┐
│ HPC 集群 │ │ 浏览器用户 │
│ 172.16.12.2 │ │ admin / user │
│ (Slurm) │ │ │
└──────────────┘ └──────────────┘
| 进程 | 端口 | 职责 |
|---|---|---|
| nginx | 18788 (host) | 提供静态 HTML 页面,反向代理 /api/auth/ 到 auth_server |
| crond | — | 每日 03:00 (Asia/Shanghai) 执行 update-slurm.sh 采集 HPC 数据 |
| auth_server.py | 28790 (localhost) | Python stdlib HTTP 服务,处理认证、注册、账号管理与统计查询 |
浏览器 ──→ nginx :18788
├── /api/auth/* ──→ proxy_pass ──→ auth_server.py :28790
├── /data/*.json ──→ 静态文件 (图表数据)
└── /*.html ──→ 静态文件 (前端页面)
| 层 | 技术 | 说明 |
|---|---|---|
| 运行时 | nginx:alpine + Python 3 (stdlib) | 单容器,无框架依赖 |
| 后端 | Python stdlib HTTP server | http.server.ThreadingHTTPServer,无 Flask/Django |
| 密码安全 | PBKDF2-SHA256, 200,000 次迭代 | stdlib hashlib.pbkdf2_hmac,无外部依赖 |
| 前端 | 原生 HTML + JavaScript + Chart.js | 无构建步骤,HTML 直接复制到 nginx 根目录 |
| 数据库 | SQLite (WAL 模式, schema v5) | 单文件,/opt/db-data/usage.sqlite |
| 数据采集 | SSH + sacct (Slurm) | SSH 密钥认证远程执行 sacct -P 获取作业记录 |
| 部署 | Docker 单阶段构建 | Dockerfile.local,--network host 模式 |
| 进程管理 | tini | PID 1 僵尸进程回收 |
huawei-report/
├── README.md # 本文件
├── REQUIREMENTS.md # 需求与设计文档
├── Dockerfile.local # 单阶段构建镜像(推荐)
├── entrypoint.local.sh # 容器入口脚本
├── gen_mock_data.py # 伪数据生成脚本(开发测试用)
├── secrets.env.example # 密码模板(HPC + admin)
├── .gitignore
├── .dockerignore
│
├── web/ # 前端页面 + 后端服务
│ ├── nginx.conf # nginx 配置(监听 18788,反代 /api/auth/)
│ ├── crontab # 定时任务:每日 03:00 采集 HPC
│ ├── common.js # 前端公共 JS(API 调用、认证守卫、登出)
│ ├── index.html # 首页:总览图表
│ ├── login.html # 登录页
│ ├── register.html # 注册页(可选申请 HPC/NPU 账号)
│ ├── profile.html # 个人页:账号信息 + 凭证管理
│ ├── admin.html # 管理后台:用户列表 + 账号管理
│ ├── stats.html # 个人核时统计
│ ├── stats-admin.html # 管理员核时统计
│ ├── dashboard.html # 管理员仪表盘
│ ├── 404.html # 404 页面
│ ├── Dockerfile # 旧版标准镜像(HTML 需 bind-mount)
│ ├── Dockerfile.migrate # 旧版自包含镜像(HTML 内置)
│ ├── docker-compose.yml # Docker Compose 编排配置
│ ├── .env.example # Compose 环境变量模板
│ └── scripts/
│ ├── entrypoint.sh # 旧版容器入口
│ ├── update-slurm.sh # 每日 sacct 采集 + JSON/DB 更新
│ ├── collect_slurm.py # sacct 解析:按用户/按天核时 → JSON
│ └── auth_server.py # 认证 + 注册 + 账号管理 + 统计 API 服务
│
├── db/ # 数据库工具(打包进镜像)
│ ├── schema.sql # SQLite schema v5
│ ├── init_db.py # 数据库初始化 + sacct 用户自动 seed
│ ├── backfill_hpc.sh # 首次部署:180 天历史回填
│ ├── aggregate_hpc.py # HPC 数据聚合:sacct → hpc_daily UPSERT
│ ├── admin_bootstrap.py # 管理员账号初始化(从环境变量)
│ ├── migrate_v3.py # v2→v3 迁移:accounts 增加 credential 列
│ ├── migrate_v4.py # v3→v4 迁移:accounts 增加 status 列
│ └── migrate_v5.py # v4→v5 迁移:accounts 扩展(hpc_account, npu_account)
│
├── docs/ # 开发文档
│ ├── PRD-Frontend-Rebuild.md # 前端重建产品需求文档
│ ├── SPEC-Frontend-Rebuild.md # 前端重建技术规格
│ ├── tech-stack-selection.md # 技术栈选型分析
│ ├── decisions/ # 架构决策记录
│ ├── design-system/ # 设计系统(Design tokens + 规范)
│ └── phase2/ # 前端重建接口设计文档
│
├── skill/ # Claude Code 技能(手动备用)
│ ├── SKILL.md # 技能声明
│ ├── run.sh # 编排脚本
│ ├── collect_slurm.py # sacct 解析(与 web/scripts 版本一致)
│ ├── pull-sacct.exp # expect 脚本:ssh hpc 采集
│ └── push-json.exp # expect 脚本:scp 推送 JSON
│
└── deploy/ # 部署辅助
├── remote-setup.sh # 服务器端容器启动脚本
├── export-image.sh # 构建自包含镜像并导出 tar.gz
├── start-container.sh # 从导出镜像启动容器
├── release-image.sh # 构建并上传到 GitHub Release
└── install-skill.sh # 本地安装 Claude Code 技能
Python stdlib HTTP 服务(无框架依赖),监听 127.0.0.1:28790,nginx 反代 /api/auth/ 到此端口。
安全机制:
| 机制 | 实现 |
|---|---|
| 密码哈希 | PBKDF2-SHA256,200,000 次迭代,16 字节随机 salt |
| Session | 32 字节随机 token,HttpOnly Cookie,24 小时 TTL |
| 登录保护 | 5 次失败锁定 15 分钟,恒定时间失败响应(防用户名枚举) |
| 请求限制 | POST body 上限 8KB |
| 审计日志 | 所有敏感操作写入 audit_log 表 |
API 端点:
| 方法 | 路径 | 功能 | 权限 |
|---|---|---|---|
| POST | /api/auth/login |
用户登录 | 公开 |
| POST | /api/auth/logout |
用户登出 | 公开 |
| POST | /api/auth/register |
用户注册(创建 group + person + auth_user) | 公开 |
| GET | /api/auth/check |
检查登录状态 | 公开 |
| GET | /api/auth/profile |
获取个人信息 + 账号列表 + HPC 用量 | 登录用户 |
| GET | /api/auth/stats/hpc |
个人 HPC 核时统计(支持日期范围) | 登录用户 |
| POST | /api/auth/apply-account |
申请新 HPC/NPU 账号 | 登录用户 |
| POST | /api/auth/suspend-account |
停用自己的账号 | 登录用户 |
| POST | /api/auth/activate-account |
重新启用自己的账号 | 登录用户 |
| GET | /api/auth/health |
健康检查 | 公开 |
| GET | /api/auth/admin/users |
用户列表(含 HPC 用量汇总) | admin |
| GET | /api/auth/admin/users/:id |
用户详情(含账号 + HPC 用量) | admin |
| POST | /api/auth/admin/users/:id/reset-password |
重置用户密码 | admin |
| POST | /api/auth/admin/users/:id/set-role |
设置用户角色 | admin |
| POST | /api/auth/admin/accounts/:id/suspend |
停用用户账号 | admin |
| POST | /api/auth/admin/accounts/:id/activate |
启用用户账号 | admin |
| POST | /api/auth/admin/accounts/:id/reset-credential |
重置账号凭证 | admin |
| GET | /api/auth/admin/stats/hpc |
全员 HPC 核时排行(支持日期范围) | admin |
| GET | /api/auth/admin/stats/hpc/by-group |
按计费组聚合的 HPC 核时统计 | admin |
统计查询支持日期范围参数:
?start=YYYY-MM-DD&end=YYYY-MM-DD,默认最近 30 天。
| 脚本 | 用途 | 数据源 | 触发方式 |
|---|---|---|---|
update-slurm.sh |
编排 HPC 采集全流程 | SSH → sacct | crond 03:00 |
collect_slurm.py |
sacct 解析 → 图表 JSON | sacct TSV | update-slurm.sh 调用 |
aggregate_hpc.py |
sacct 聚合入库 | sacct TSV → hpc_daily |
update-slurm.sh 调用 |
backfill_hpc.sh |
HPC 历史回填(180 天) | sacct via SSH | 首次部署手动执行 |
SQLite 单文件(WAL 模式),路径 /opt/db-data/usage.sqlite,schema 版本 v5。
| 表名 | 用途 | 关键字段 |
|---|---|---|
schema_version |
Schema 版本追踪 | version, applied_at |
groups |
计费组(单人组 is_individual=1) |
name, is_individual |
person |
自然人,关联一个组 | name, email, role, group_id |
accounts |
人员 × 系统(HPC/NPU) × 账号名 + 凭证 + 状态 | system, account_name, credential, status |
hpc_daily |
HPC 每日核时 | date, account_name, core_hours, job_count |
auth_user |
登录账号 | username, password_hash, failed_attempts, locked_until |
auth_session |
登录会话 | token, person_id, expires_at |
audit_log |
操作审计日志 | ts, person_id, action, target |
| 列名 | 类型 | 说明 |
|---|---|---|
id |
INTEGER PK | 自增主键 |
person_id |
INTEGER FK | 关联 person |
system |
TEXT | hpc / npu |
account_name |
TEXT | 账号名(UNIQUE(system, account_name)) |
credential |
TEXT | HPC/NPU 密码(v3 新增) |
status |
TEXT | active / suspended / pending_review(v4 新增) |
hpc_account |
TEXT | HPC 集群登录名(v5 新增) |
npu_account |
TEXT | NPU 集群登录名(v5 新增) |
created_at |
TEXT | 创建时间 |
- per-system 分表:HPC/NPU 指标不同,各自独立表,类型清晰、索引可单独优化
- hpc_daily.account_name 不是外键:新用户出现在 sacct 时直接落库,管理员事后补映射
- groups + person 分离:个人转入正式组时只改
person.group_id,历史数据不动
| 版本 | 变更 | 迁移脚本 |
|---|---|---|
| v1 | 基础表:groups, person, accounts, hpc_daily | schema.sql |
| v2 | 认证表:auth_user, auth_session, audit_log | schema.sql |
| v3 | accounts 增加 credential 列 |
migrate_v3.py |
| v4 | accounts 增加 status 列 |
migrate_v4.py |
| v5 | accounts 扩展(hpc_account, npu_account) | migrate_v5.py |
所有迁移脚本均为幂等(可安全重复运行),entrypoint.sh 启动时自动按顺序执行。
原生 HTML + JavaScript + Chart.js(web/ 目录),共 9 个页面:
| 页面 | 功能 | 权限 |
|---|---|---|
index.html |
总览页:统计指标 + 堆叠柱状图 + 排行榜 | 公开 |
login.html |
登录页(admin → 仪表盘,user → 个人页) | 公开 |
register.html |
注册页(可选申请 HPC/NPU 账号) | 公开 |
profile.html |
个人页:账号信息 + 凭证管理 | 登录用户 |
stats.html |
个人核时统计:日期范围筛选 + 按账号明细 | 登录用户 |
dashboard.html |
管理员仪表盘:用户用量详情 + 排行榜 | 仅 admin |
stats-admin.html |
管理员核时统计:全员排行 + 按计费组聚合 | 仅 admin |
admin.html |
管理后台:用户列表 + 账号管理 + 角色设置 | 仅 admin |
404.html |
404 页面 | 公开 |
common.js 提供公共工具:API 调用封装 (api())、认证守卫 (requireAuth() / requireAdmin())、登出处理 (handleLogout())。
| 角色 | 可访问页面 | 可执行操作 |
|---|---|---|
| admin | 全部页面 | 查看所有用户用量、管理用户与账号、设置角色、重置密码/凭证 |
| user | index, login, register, profile, stats | 查看个人用量、申请/停用/启用自己的账号、查看凭证 |
| 匿名 | index, login, register | 查看总览图表、注册/登录 |
注册流程:
register.html → POST /api/auth/register
├── 创建个人组 (is_individual=1)
├── 创建 person 记录
├── 创建 auth_user (PBKDF2 哈希)
└── (可选) 创建 HPC/NPU 账号 → accounts 表
账号管理:
profile.html → POST /api/auth/apply-account (申请新账号)
→ POST /api/auth/suspend-account (停用自己的账号)
→ POST /api/auth/activate-account (启用已停用的账号)
管理员操作:
admin.html → POST /api/auth/admin/users/:id/reset-password
→ POST /api/auth/admin/users/:id/set-role
→ POST /api/auth/admin/accounts/:id/suspend
→ POST /api/auth/admin/accounts/:id/activate
→ POST /api/auth/admin/accounts/:id/reset-credential
HPC (172.16.12.2, Slurm)
│ ssh -i $HPC_SSH_KEY → sacct -P (最近 30 天作业记录)
│
│ sacct 输出字段:
│ User | Account | JobID | State | CPUTimeRAW | Start | End | AllocCPUS | Elapsed
│
▼
原始 TSV 数据
│
├──→ collect_slurm.py ──→ slurm_daily.json (前端图表, 30天滚动窗口)
│ 路径: /usr/share/nginx/html/data/
│ 原子写入: .tmp → mv
│
└──→ aggregate_hpc.py ──→ hpc_daily 表 (SQLite, 全历史计费)
路径: /opt/db-data/usage.sqlite
UPSERT: date + account_name 联合主键
幂等: 重新运行不累积重复值
调度: crond 每天 03:00 (Asia/Shanghai)
首次部署: backfill_hpc.sh 一次性拉 180 天 sacct
按"用户 × 天"分桶计算核时(core-hours)。对跨天作业,按天切分时间段:
作业: Start=2026-08-01T22:00, End=2026-08-02T03:00, AllocCPUS=16
→ 08-01: 16 核 × 2 小时 = 32.0 core-hours
→ 08-02: 16 核 × 3 小时 = 48.0 core-hours
RUNNING 作业: End 字段为 Unknown,按当前时间处理
job_count: 按作业开始日统计(跨天作业只计在开始日)
slurm_daily.json 供前端 Chart.js 渲染堆叠柱状图和排行榜:
{
"range": { "start": "2026-07-05", "end": "2026-08-03", "days": 30 },
"users": ["alice", "bob"],
"dates": ["2026-07-05", "2026-07-06"],
"core_hours": { "alice": [0.0, 1.2], "bob": [3.5, 0.0] },
"totals_per_day": [3.5, 1.2],
"totals_per_user": { "alice": 12.3, "bob": 45.6 }
}- Docker 已安装在华为服务器(10.26.15.53)
- 可 SSH 访问 HPC(10.26.15.51 / 内网 172.16.12.2)
- 容器使用
--network host模式(Docker 默认 bridge 无法路由 172.16.12.x)
使用 Dockerfile.local 构建,将静态 HTML 页面和后端脚本打包进 nginx 镜像:
# 1. 构建镜像
docker build -f Dockerfile.local -t huawei-reports-web:local .
# 2. 运行容器
docker run -d --name huawei-reports-web --network host --restart unless-stopped \
-e ADMIN_EMAIL=admin@example.com \
-e ADMIN_PASSWORD=Huawei2024Admin \
-v /home/liangzhu/huawei-db:/opt/db-data \
-v /home/liangzhu/huawei-reports/data:/usr/share/nginx/html/data \
-v /path/to/id_ed25519:/opt/ssh/id_ed25519:ro \
huawei-reports-web:localentrypoint.local.sh 启动流程:
- 启动 crond(后台)
- 初始化数据库(首次)或运行迁移脚本(v3 → v4 → v5)
- 创建管理员账号(从环境变量)
- 启动 auth_server.py(后台,127.0.0.1:28790)
- 启动 nginx(前台,阻塞)
使用 web/Dockerfile.migrate 构建自包含镜像,导出为 tar.gz 传到服务器:
# 1. 构建 + 导出
bash deploy/export-image.sh
# 产出: huawei-reports-web.tar.gz (~40MB)
# 2. 传输到服务器
scp huawei-reports-web.tar.gz liangzhu@10.26.15.53:/home/liangzhu/
# 3. 在服务器上加载 + 启动
ssh liangzhu@10.26.15.53
docker load < huawei-reports-web.tar.gz
ADMIN_EMAIL=admin@example.com ADMIN_PASSWORD=Huawei2024Admin \
SSH_KEY=~/.ssh/id_ed25519 \
bash deploy/start-container.sh# 构建并上传到 GitHub Release
bash deploy/release-image.sh [VERSION_TAG]
# 默认 tag: latest;也可指定版本号如 v5
# 在目标服务器下载
gh release download latest --repo zleung9/huawei-report| 宿主机路径 | 容器路径 | 用途 |
|---|---|---|
/home/liangzhu/huawei-db/ |
/opt/db-data |
SQLite 数据库(rw) |
/home/liangzhu/huawei-reports/data/ |
/usr/share/nginx/html/data |
JSON 图表数据(rw) |
| 变量 | 说明 | 默认值 |
|---|---|---|
HPC_HOST |
HPC 头节点地址 | 172.16.12.2 |
HPC_USER |
HPC SSH 用户 | zhangjie |
HPC_SSH_KEY |
SSH 私钥路径(容器内) | /opt/ssh/id_ed25519 |
DAYS |
sacct 采集窗口(天) | 30 |
DB_PATH |
SQLite 数据库路径 | /opt/db-data/usage.sqlite |
OUT_DIR |
图表 JSON 输出目录 | /usr/share/nginx/html/data |
ADMIN_EMAIL |
管理员邮箱 | admin@example.com |
ADMIN_PASSWORD |
管理员密码 | Huawei2024Admin |
UPDATE_CRON |
自定义 cron 表达式 | 0 3 * * * |
生产环境请务必修改
ADMIN_PASSWORD默认值。
gen_mock_data.py 可生成完整的测试数据(SQLite + JSON),无需连接真实 HPC:
# 生成到指定路径
python3 gen_mock_data.py --db /tmp/test/usage.sqlite --out /tmp/test/data/slurm_daily.json
# 直接注入运行中的容器
python3 gen_mock_data.py --container huawei-reports-web# 构建镜像
docker build -f Dockerfile.local -t huawei-reports-web:local .
# 使用伪数据启动(无需 HPC 连接)
docker run -d --name huawei-reports-dev -p 18788:18788 \
-e ADMIN_EMAIL=admin@test.local \
-e ADMIN_PASSWORD=admin123 \
-v huawei-db-test:/opt/db-data \
-v huawei-html-data-test:/usr/share/nginx/html/data \
huawei-reports-web:local
# 注入伪数据
python3 gen_mock_data.py --container huawei-reports-dev
# 访问 http://localhost:18788容器内 crond 已接管自动更新。本地 Claude Code 技能(skill/ 目录)作为手动备用:
# 直接运行采集
bash skill/run.sh
DAYS=60 bash skill/run.sh # 自定义时间窗口- claw → hpc TCP:22 经 10.26.15.51 被防火墙拦截:Ping 通(NAT),但 SSH 超时。使用内网 IP
172.16.12.2(hpc 和 claw 均在 172.16.12.0/24) - 容器需要
--network host:Docker 默认 bridge 无法路由到 172.16.12.x 网络,因此 nginx 直接监听 18788 端口(无端口映射)
- HPC 每日核时统计图表
- SQLite 使用量数据库 + HPC 历史回填(180 天)
- 登录认证系统(PBKDF2-SHA256 + Session Token + 登录锁定)
- 每日自动采集(容器内 crond 03:00)
- 用户注册 + HPC/NPU 账号申请
- 角色路由(admin → 仪表盘,user → 个人页)
- 个人页凭证管理(密码显示/隐藏/复制)
- 账号自助管理(申请/停用/启用)
- 管理后台(用户管理 + 账号管理 + 角色设置 + 密码重置)
- HPC 核时统计页(个人 + 管理员,支持日期范围筛选)
- 按计费组聚合统计
- 自包含 Docker 镜像(Dockerfile.migrate)
- Schema v3→v4→v5 迁移(credential / status / hpc_account / npu_account)
- 单阶段 Docker 构建(Dockerfile.local,前端 HTML + 后端打包一体化)
- 伪数据生成工具(gen_mock_data.py)
- NPU 用量采集(待 NPU 资源管理方案确定)
- HTTPS 部署(登录系统上线前需先部署 TLS)
- 计费报表导出(月度/季度账单)
- 服务器上的
docker-compose v2.4.1与 Docker 29.2.1 API 不兼容,使用docker run代替 - 密码存储在本地
secrets.env(已 gitignore),未来迁移至 SSH 密钥认证 - 当前为 HTTP(端口 18788),登录系统上线前需要先部署 HTTPS
docs/下tech-stack-selection.md和SPEC-Frontend-Rebuild.md仍保留 Vue 历史引用(不影响构建运行)
- REQUIREMENTS.md — 完整需求与设计文档(含登录系统方案对比、计费模型等)
- docs/PRD-Frontend-Rebuild.md — 前端重建产品需求文档
- docs/SPEC-Frontend-Rebuild.md — 前端重建技术规格
- docs/tech-stack-selection.md — 技术栈选型分析
- docs/design-system/DESIGN-SYSTEM.md — 设计系统规范