145 lines
10 KiB
Markdown
145 lines
10 KiB
Markdown
# 云端服务与控制台开发说明
|
||
|
||
更新:2026-11-09。当前交付是第一阶段本地可运行版本。Vue 控制台通过真实 HTTP 调用 Go API,账号、授权、设备、任务和审计保存在 PostgreSQL;演示 VM 的电源操作由明确标记的演示计算适配执行。本文件主要描述演示开发环境;随后已接通[独立真实环境](cloud-live-integration.md),控制台端口 5182、设备 HTTPS 8443。
|
||
|
||
## 启动
|
||
|
||
### Windows 本机开发
|
||
|
||
需要 Node.js 22.12+、Go 1.25+、Docker Desktop。仓库根目录执行:
|
||
|
||
```powershell
|
||
.\tools\start-cloud-dev.ps1
|
||
```
|
||
|
||
已安装前端依赖时可加 `-SkipInstall`。脚本启动专用 PostgreSQL 容器,编译并启动本机 API,再启动 Vite。默认控制台地址 `http://127.0.0.1:5180`,API 地址 `http://127.0.0.1:8088`,数据库仅映射本机 `55438`。可用 `-ApiPort` 和 `-ConsolePort` 改开发端口。不会停止其他占用端口的程序。
|
||
|
||
演示账号 `admin`、`operator`、`viewer`,统一演示密码 `Demo@2026`。对应超级管理员、运维、只读角色,仅 `VDI_MODE=demo` 会创建这些账号。首次数据库初始化后,重新启动保留业务数据。
|
||
|
||
进程 PID 和日志在忽略提交的 `.local/` 中。关闭本机开发进程时根据 `.local/cloud-dev.json` 确认 PID 和命令路径,只停止本次启动的 API 与 Vite。数据库可通过 `docker compose -f deploy/compose.dev.yml stop postgres` 停止;不删除卷即可保留数据。
|
||
|
||
### 全容器开发
|
||
|
||
与本机模式二选一,避免占用同一端口:
|
||
|
||
```powershell
|
||
docker compose -f deploy/compose.dev.yml up --build -d
|
||
```
|
||
|
||
控制台仍是 `http://127.0.0.1:5180`。Nginx 代理同源 `/api` 到 Go 服务,PostgreSQL 使用命名卷。该 compose 是开发演示配置,不是客户生产部署包。
|
||
|
||
端口被其他开发进程占用时,可先设置 `$env:VDI_CONSOLE_PORT='5181'`、`$env:VDI_API_PORT='8089'` 再执行 compose。当前本机验收使用该端口组合,预览地址为 `http://127.0.0.1:5181`。
|
||
|
||
### 仅前端模拟
|
||
|
||
```powershell
|
||
cd console
|
||
npm ci
|
||
$env:VITE_API_MODE='mock'
|
||
npm run dev
|
||
```
|
||
|
||
MSW 在浏览器层模拟 HTTP,只有开发构建允许启用,不需要 Go 或数据库。模拟操作不控制真实资源,刷新页面会重置模拟业务数据。正常的 `api` 模式不注册模拟 Worker。
|
||
|
||
## 当前可用范围
|
||
|
||
| 模块 | 当前实现 |
|
||
| --- | --- |
|
||
| 登录 | bcrypt 密码校验、JWT、服务端会话记录、退出撤销、刷新页面恢复、三角色服务端授权 |
|
||
| 总览 | 终端在线、VM 电源、实际画面就绪连接、异常任务;连接预约单独记录 |
|
||
| 计算资源 | 节点列表;配置 PVE 后每 30 秒同步节点/已纳管 VM,显示同步时间与过期标记 |
|
||
| 桌面 | 演示桌面;发现 PVE VM、纳管、查看详情、开机/正常关机/重启;PVE UPID 跟踪 |
|
||
| 终端 | 管理员登记、一次性激活、设备独立令牌、心跳、桌面授权列表、命令领取与回执 |
|
||
| 授权 | 创建最终使用者、每设备关联一位使用者、每使用者多个桌面、停用和撤销后阻止新连接 |
|
||
| 任务 | 持久化排队/执行/成功/失败/结果未确认、请求去重、同对象任务互斥、最终回执审计 |
|
||
| 连接契约 | 短期单次票据、终端隔离、消费时重新校验授权、同桌面活动占用检查 |
|
||
|
||
当前连接票据仅授权并返回 Moonlight 端点与参数;终端仍需既有 Sunshine 配对。消费票据登记连接预约,不证明串流已建立;现场 Qt 已上报实际画面就绪与进程结束事件,详情见真实接入说明。不要把 `credentialMode=existing-pairing` 当作免配对认证。
|
||
|
||
本轮将 API 入口与基础业务模块放在一个可运行的 Go 网关进程中,数据库和 Proxmox client 独立封装。原方案的七个服务职责继续作为后续拆分边界;当前尚未交付七个独立部署的服务。MQTT 总线、Rust Agent、VictoriaMetrics 指标接入、模板发放、桌面池、GPU 绑定、OTA、AD/LDAP 尚未完成;Qt 适配现已实际部署。控制台仅显示已接通的第一阶段功能。
|
||
|
||
## 真实 Proxmox 接入
|
||
|
||
使用新的独立数据库,按 `platform/.env.example` 注入配置。正式模式要求至少 32 字符的 JWT 密钥、管理员账号和至少 12 字符的初始密码。管理员环境变量仅在账号首次创建时生效,不会在每次启动时覆盖已有密码。数据库记录初始化模式,拒绝直接混用演示与正式数据库。
|
||
|
||
```text
|
||
VDI_MODE=production
|
||
DATABASE_URL=postgres://.../vdi?sslmode=require
|
||
VDI_JWT_SECRET=...
|
||
VDI_ADMIN_USERNAME=...
|
||
VDI_ADMIN_PASSWORD=...
|
||
PVE_URL=https://pve.example.internal:8006
|
||
PVE_TOKEN_ID=vdi@pve!console
|
||
PVE_TOKEN_SECRET=...
|
||
PVE_CA_FILE=/run/secrets/pve-ca.pem
|
||
```
|
||
|
||
PVE 凭据由后端持有,前端和终端不会接收;证书校验始终开启。PVE_URL 只填 HTTPS origin,不附 `/api2/json`。由运维给 API Token 配置实际需要的节点/VM/存储查询和 VM 电源操作权限。本轮不自动修改 PVE 账号、ACL、VM 或主机配置。
|
||
|
||
启动后到“计算资源”手动同步;再到“桌面管理”选择“纳管已有 VM”。纳管仅登记已存在的 VM,不改 VM 配置。连接地址可在纳管表单填写。首次真实接入应使用专门测试 VM 核验 API 版本、证书、任务结果和关机行为,再对业务 VM 开放操作。
|
||
|
||
正式环境的 HTTPS 入口、运维凭据轮换、账号维护、登录限流、独立数据库迁移流程与备份恢复仍属于部署产品化工作;当前 compose 不作生产就绪声明。
|
||
|
||
## 设备接口联调
|
||
|
||
接口契约在 `docs/openapi/platform.v1.json`,API 根路径 `/api/v1`。控制台通过生成的类型和统一请求适配调用接口,页面不拼接 API 地址。
|
||
|
||
1. 管理员在终端页登记 SN,取得仅显示一次的 `activationSecret`。
|
||
2. 终端 `POST /terminal/register` 提交 SN、activationSecret、agentVersion,取得设备令牌;激活密钥随即作废。
|
||
3. 设备以独立 `Authorization: Bearer <device-token>` 发送心跳、拉配置和获取授权桌面。
|
||
4. 管理员创建用户并关联终端、勾选多个桌面;设备再次请求 `/terminal/desktops` 即获得更新列表。
|
||
5. 设备轮询 `GET /terminal/commands` 领取命令,执行后 `POST /terminal/commands/{id}/ack` 报告 success/failed。没有回执的命令约两分钟后显示结果未确认;不会自动重放。
|
||
6. 申请 `/terminal/connect-ticket`,再用 `/terminal/connect-ticket/consume` 单次消费;消费时再次检查授权与桌面占用。之后仍使用已有 Moonlight/Sunshine 配对。
|
||
|
||
`tools/platform-terminal-simulator.py --sn <SN>` 可在本机演示平台注册、发心跳和读取授权桌面。激活密钥通过交互输入或 `VDI_DEVICE_ACTIVATION_SECRET` 传入;模拟器对所有设备操作回失败,避免假装执行了重启或日志收集。它不是可部署的 Rust Agent。
|
||
|
||
当前 HTTPS 轮询是 MQTT 接入前的可验证通道;没有声称已提供消息总线。终端令牌的撤销/重新激活、配置热更新将继续扩展契约;Qt 串流事件、固定命令执行和诊断日志上传已在真实环境接通。
|
||
|
||
## 检查命令
|
||
|
||
```powershell
|
||
cd console
|
||
npm run lint
|
||
npm run typecheck
|
||
npm run test
|
||
npm run build
|
||
npm run test:e2e
|
||
npm run api:generate
|
||
```
|
||
|
||
E2E 使用已经启动的本机平台,只允许对 `/healthz` 返回 demo 模式的服务运行;Windows 默认使用已安装的 Edge。其他环境使用 `npx playwright install chromium` 准备测试浏览器。`VDI_E2E_URL` 可覆盖测试地址。测试会创建演示用户和待激活终端、切换演示 VM 电源,不会操作真实 PVE。
|
||
|
||
```powershell
|
||
cd platform
|
||
go test ./...
|
||
go vet ./...
|
||
```
|
||
|
||
数据库集成测试需要 `VDI_TEST_DATABASE_URL` 指向**专用可清空测试数据库**。测试会清空该数据库内平台表,不要指向开发业务库或生产库。
|
||
|
||
```powershell
|
||
docker exec vdi-cloud-dev-postgres-1 psql -U vdi -d postgres -c 'CREATE DATABASE vdi_test'
|
||
$env:VDI_TEST_DATABASE_URL='postgres://vdi:vdi-local-demo@127.0.0.1:55438/vdi_test?sslmode=disable'
|
||
go test ./...
|
||
```
|
||
|
||
后端测试覆盖服务端 RBAC、JWT 退出失效、幂等任务、授权变更事务回滚、设备隔离、一次性票据、回执和超时;PVE client 使用本地测试服务器验证 TLS 和 UPID,不向现场 PVE 发送请求。
|
||
|
||
## 本轮验收记录(2026-11-09)
|
||
|
||
- Go 单元测试、专用 PostgreSQL 集成测试和 `go vet` 通过;包含模式隔离、重启后撤权保留、PVE 明确失败与提交结果未确认的区分。
|
||
- 前端 ESLint、TypeScript、3 项登录状态单元测试和生产构建通过。
|
||
- 容器版 `http://127.0.0.1:5181` 的 7 项 Playwright 用例全部通过:登录失败/恢复/退出、桌面命令最终结果、用户多桌面授权持久化、终端激活信息、两种权限角色、空列表/异常/401。
|
||
- 单独启动 MSW 模式,验证模拟登录和授权页导航;检查 1440px 桌面及 390px 窄屏。
|
||
- 页面截图:[总览](evidence/cloud-console-20261109/overview.png)、[桌面管理](evidence/cloud-console-20261109/desktops.png)、[窄屏](evidence/cloud-console-20261109/narrow.png)。页面主题集中在 `console/src/styles/tokens.css`,可交给 UI 同事继续调整。
|
||
- Node 依赖完整审计为 0 项已知漏洞。Vitest 已更新;TypeScript ESLint 的 minimatch 子依赖定向覆盖至 11.0.1+,静态检查通过。
|
||
- Docker API/控制台镜像构建并启动,数据库保留卷内已有业务数据。未向现场 PVE 或盒子发送操作。
|
||
|
||
## 数据与执行边界
|
||
|
||
- 在线按最近 90 秒心跳计算;FPS/RTT 缺失为 null,不填 0。PVE 电源状态与 VM 内连接服务状态分开。
|
||
- 任务成功必须有计算适配结果或设备回执。提交后发生通信异常时保留“结果未确认”,由管理员核对实际状态,不自动重试。
|
||
- 桌面“重启”只用 PVE reboot;未将硬重启 reset 冒充“还原镜像”。
|
||
- 当前任务和审计列表展示最近 1000 条,完整记录仍存 PostgreSQL;长期检索和归档后续扩展。
|
||
- 凭据不写入审计;设备上报的自由文本不直接放入公开任务结果。
|