104 lines
5.1 KiB
Markdown
104 lines
5.1 KiB
Markdown
# FlashOps — 存储实验室无人值守执行层
|
||
|
||
> 固件回归测试的**控制平面**:把一条真实 SOP 变成可执行、可恢复、可取证的状态机,
|
||
> 让工程师不必通宵值守。
|
||
|
||
**命名是临时的。** `FlashOps` 只是后端代号,控制台目前仍显示 `STORAGE LABOS`;
|
||
商标与最终品牌确认后,需要统一后端常量、控制台标题和文档。
|
||
|
||
---
|
||
|
||
## 当前可运行基线
|
||
|
||
现在已有一条**无需硬件即可端到端跑通**的真实纵向链路:
|
||
|
||
```
|
||
建任务 → 六项安全预检 → 资源加锁 → N 次模拟循环
|
||
→ 注入 Agent 心跳丢失 → L1/L2 失败 → L3 带外 Reset 恢复
|
||
→ 从循环检查点续跑 → Evidence Bundle 打包 → 前端实时可见
|
||
```
|
||
|
||
全程使用内置模拟 DUT、测试主机与带外控制器,一条命令即可完成。当前实现重点是
|
||
事件溯源写路径、安全门禁、状态转移、恢复记录和可复现演示;独立 Host Agent
|
||
已经完成注册、token 与心跳最小链路,但步骤租约、真实硬件适配器、失败聚类执行逻辑
|
||
与完整权限体系仍是后续工作,不在此基线中伪装完成。
|
||
|
||
---
|
||
|
||
## 快速开始
|
||
|
||
前置:Python 3.9+。**不需要 Node 或 Docker。**
|
||
|
||
```bash
|
||
make setup # 建 venv、装依赖、建库、灌种子数据
|
||
make demo # 跑一条 8 轮模拟回归(含故障注入、恢复与证据包)
|
||
make dev # 起控制平面与控制台 :8000
|
||
make dev-agent # 注册独立 Host Agent 并发送一次心跳
|
||
make test # 控制平面 + Agent + API 端到端测试
|
||
```
|
||
|
||
`make demo` 结束会打印 Run ID 与 Evidence Bundle 路径;`make dev` 后打开
|
||
<http://localhost:8000/console/Tasks.dc.html>,运行预检并创建任务,再进入“实时运行”
|
||
即可看到同一条 Run 的事件时间线。API 文档在 <http://localhost:8000/docs>。
|
||
|
||
---
|
||
|
||
## 仓库结构
|
||
|
||
```
|
||
flashops/
|
||
├─ docs/ 架构与规范(先读这里)
|
||
│ ├─ architecture.md 五层架构 → 代码目录的逐层映射
|
||
│ ├─ domain-model.md 7 个核心领域对象 → 数据库表
|
||
│ ├─ state-machine.md Run/Step 状态机、恢复阶梯、检查点语义
|
||
│ ├─ adapter-sdk.md 工具适配器契约(产品扩张的关键边界)
|
||
│ ├─ workflow-spec.md SOP → YAML 工作流的 schema
|
||
│ └─ decisions/ ADR:为什么这么选,以及什么时候该推翻
|
||
├─ services/
|
||
│ ├─ control-plane/ FastAPI 控制平面(事件、安全、模拟执行、证据)
|
||
│ └─ host-agent/ 独立拉模式 Agent(注册、凭据、心跳)
|
||
├─ ../前端UI八页面完成/ 控制台原型;由 FastAPI 挂载到 /console
|
||
├─ docker-compose.yml 目标生产拓扑草案(尚未作为发布物验收)
|
||
└─ Makefile
|
||
```
|
||
|
||
---
|
||
|
||
## 三条必须守住的架构红线
|
||
|
||
写后续代码时,这三条一旦破了,返工成本最高:
|
||
|
||
1. **控制面与数据面分离**——任务状态的唯一真相在控制平面数据库,测试主机本地只有缓存。
|
||
Agent 挂了、主机重装了,Run 状态不丢。
|
||
|
||
2. **事件溯源**——所有状态变化以 append-only 事件写入 `run_events`,
|
||
当前状态是事件的投影而非独立真相。时间线、审计、复现全部由此派生。
|
||
*禁止*绕过 `events/recorder.py` 直接 UPDATE Run 状态。
|
||
|
||
3. **安全默认拒绝**——当前序列号、破坏性授权、系统盘、固件型号、Host 与 OOB
|
||
任一不满足即在 `safety/` 层拒绝。真实 Agent 接入前还必须补签名命令模板,
|
||
保证 Agent 只执行控制平面批准的动作。
|
||
|
||
---
|
||
|
||
## 当前状态与下一步
|
||
|
||
| 能力 | 状态 | 说明 |
|
||
|---|---|---|
|
||
| 14 张持久化表 | ✅ 已落地 | SQLite 建表与种子数据可重复执行 |
|
||
| Run 事件溯源 | ✅ 已落地 | 状态只能经 `events/recorder.py` 投影 |
|
||
| Run 状态转移 | ✅ 已落地 | 纯函数转移表,终态不可恢复 |
|
||
| 六项安全门禁 | ✅ 已落地 | 序列号、破坏性授权、系统盘、固件、Host、OOB |
|
||
| L1–L5 恢复决策 | ✅ 已落地 | 纯函数;演示链路实际执行 L1–L3 |
|
||
| 循环检查点续跑 | ✅ 模拟落地 | 循环边界保存,恢复后续跑 |
|
||
| Evidence Bundle | ✅ 最小实现 | `manifest.json` + `events.ndjson`,完整率 100% |
|
||
| 控制台 | 🟨 部分接入 | 任务中心与实时运行接 API;其余页面仍为静态样例 |
|
||
| 独立 Host Agent | 🟨 部分落地 | 注册、token 摘要、心跳、主机探针与 15s/30s 状态老化已实现;Step 租约待实现 |
|
||
| 真实 nvme-cli 与 OOB | ⬜ 待实现 | 需要可牺牲 DUT 与 JetKVM/PDU |
|
||
| 失败签名执行与聚类 | ⬜ 待实现 | 数据表已定义,服务逻辑未接入 |
|
||
| 多工位调度、认证与权限 | ⬜ 待实现 | 进入真实实验室前必须补齐 |
|
||
|
||
下一步建议实现 Step 租约、ACK、续租、完成上报与幂等事件,再把内置模拟执行器迁到
|
||
独立 Agent;完成这层后再接真实 `nvme-cli` 与 JetKVM,才能保证硬件接入不绕过
|
||
控制面安全规则。
|