Skip to content

About

A website for huawei server running status

Resources

Stars

0 stars

Watchers

0 watching

Forks

 
 

Repository files navigation

华为服务器资源监控平台

嘉庚创新实验室共享计算资源(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 技能

后端服务

auth_server.py — 认证与账号管理服务

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

accounts 表字段(v5)

列名 类型 说明
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,历史数据不动

Schema 迁移历史

版本 变更 迁移脚本
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 数据采集流程

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: 按作业开始日统计(跨天作业只计在开始日)

图表 JSON 格式

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:local

entrypoint.local.sh 启动流程:

  1. 启动 crond(后台)
  2. 初始化数据库(首次)或运行迁移脚本(v3 → v4 → v5)
  3. 创建管理员账号(从环境变量)
  4. 启动 auth_server.py(后台,127.0.0.1:28790)
  5. 启动 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 发布

# 构建并上传到 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

Claude Code 技能(手动备用)

容器内 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 历史引用(不影响构建运行)

相关文档

About

A website for huawei server running status

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages