docs(gaps): re-score 1.6/1.7/1.10 after external-license-resources + elim landed

external-license-resources (E2 Phase 1/2/3) and the elim collector are
merged to working (9b652d93), so the 2026-10-23 audit verdicts change:

- 1.7 external resource: not-found -> implemented (EXTERNAL flag setter,
  xceesd daemon, unsatisfy_ EXTERNAL admission, stale WARN + xceadmin
  extres status, per-project/queue quotas via limit vres, elim script
  collectors in xcecd); remaining gaps listed explicitly (generic dynres
  collector hook, multi-daemon redundancy, merge attribution report
  layer, PR-2 proxy)
- 1.6 resource kinds: flag mapping no longer CONSUMABLE/RELEASE-only
  (breakpoint 2 + BUILTIN + EXTERNAL keys); load index row notes the
  elim collector joins the same push chain
- 1.10 shared resource: [all]+value and [external] shapes are
  end-to-end; host-subset static pools still missing
- N4 annotated: live GC done (breakpoint 3), purge/archive still open
- priority item 5 annotated as mostly done

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
lei.chen 2026-10-29 06:18:07 +00:00
parent d710f56eaa
commit 0dc2bd2145

View file

@ -87,21 +87,47 @@
| 子项 | 判定 | 现状与证据 |
|---|---|---|
| 概念/定义/配置 | ✓ | resources.yaml 全谱系:内置负载指数、host 属性(type/model/cpuf/maxmem/…)、static(shared/hostbased)、dynamic、boolean/string、resourcemap;JSON Schema 校验;join 时按 hostconfig 播种(mark_host_res/add_hostattrs_resvals/set_host_slots,worker.c:232-341)。 |
| resource 种类 | △ | valtype STRING/NUMERIC/BOOLEAN、ordtype INCR/DECR/NA、9 个 flags 齐备(types.h:81-89)。**关键接线断裂:YAML→capnp 映射只映射 CONSUMABLE 和 RELEASE 两个 flag**(mapping.py:194-200)——DYNAMIC/SHARED/GLOBAL/EXTERNAL/BUILTIN 从 YAML 永远置不上;resourcemap 在 build 时被静默丢弃(build.py:38-65 _UNMAPPED_BUT_VALID_ITEM_KEYS,capnp:192-206 目标字段被注释)。ordtype 存了但**无消费者**(排序纯 first-fit,关联 t1 亲和)。 |
| load index | ✓ | **11 个内置指数全部真采集**:r15s/r1m/r15m/ut/pg/ls/it/swp/mem/tmp/io,~15s 周期(resource_sync.c:60-106),实现实在(node_information.c:/proc/loadavg、utmp、MemAvailable、statvfs、diskstats…),推送链完整(resvals→controller opupd.c→RESVALS_DELTA→scheduler core_events.c:1228-1263)。实测 distribution list 有 io/it/ls/mem 值。 |
| static resource | △ | 声明与播种 ✓(hostbased 静态值随 join 落地);但 share 型静态资源的 resourcemap(实例/份额定义)在 build 时被丢(见上),**静态 share 资源实际不工作**。 |
| resource 种类 | △→✓ | valtype STRING/NUMERIC/BOOLEAN、ordtype INCR/DECR/NA、9 个 flags 齐备(types.h:81-89)。~~YAML→capnp 映射只映射 CONSUMABLE 和 RELEASE~~ **断点 ② 已修(2026-10-23)+ BUILTIN 键补链(857f987f)+ EXTERNAL 键(E2,mapping.py:448)**:现 YAML 可置 CONSUMABLE/RELEASE/BUILTIN/SHARED|GLOBAL(location:[all]+value)/SHARED|GLOBAL|EXTERNAL(location:[external])五个语义组;resourcemap→distributions 上 wire(schema distributions/hostBased 取消注释 + 深拷)。仍缺:DYNAMIC flag 无独立 YAML 键(dynamic 形态靠 interval+无 resourcemap 隐式表达)、ordtype 仍无消费者(排序纯 first-fit)。 |
| load index | ✓ | **11 个内置指数全部真采集**:r15s/r1m/r15m/ut/pg/ls/it/swp/mem/tmp/io,~15s 周期(resource_sync.c:60-106),实现实在(node_information.c:/proc/loadavg、utmp、MemAvailable、statvfs、diskstats…),推送链完整(resvals→controller opupd.c→RESVALS_DELTA→scheduler core_events.c:1228-1263)。实测 distribution list 有 io/it/ls/mem 值。**E2 增补(2026-10-28):外部 elim 脚本源可注册进同一条链**(elim.c:595 resource_sync_register_load_index),主机级外部资源与内置指数同一推送通路。 |
| static resource | △→部分✓ | 声明与播种 ✓(hostbased 静态值随 join 落地);~~share 型静态资源的 resourcemap 在 build 时被丢~~ **断点 ② 已修**:`location: [all]`+value 形态置 SHARED\|GLOBAL 并 seed 进 sharedinst(幂等激活热更新容量);**host 子集静态共享池**(dynres2 的多 host 份额形态)仍不工作——distributions 忠实上 wire 但调度器只认 [all] 形态(elastic-shared-resources 仍规划)。 |
---
## 1.7 外部 resource(external resource)
**✗ 缺失。**
> **2026-10-29 复评:✗ → △→✓(license 全局池 + elim 主机级采集两条腿已落地,E2 三阶段完成)。**
> 实现 = `.kiro/specs/external-license-resources/`(design.md §3.5 分阶段),随 merge 9b652d93 进 working。
> 本节原"✗ 缺失"清单的逐项消解见下《E2/elim 完成面对照》。
- XCE_RESF_EXTERNAL(0x10) 定义了但全库无 setter。
- 无 elim 式外挂采集器:worker 没有子进程/脚本采集路径;`resource_sync_register_load_index` 是进程内 C API(给 xcecd 内部代码用),无任何调用方。
- dynres1/dynres2 声明了 interval 但**无采集者**——定义在表里、值永远不会自动出现,只能管理员手工 update_resval 推。
- scaler.yaml(aws-asg/k8s-pool)映射为 hproviders 推给 scheduler,但 **scheduler 零消费者**(而且它是自动扩缩 provider,不是资源采集器)。
- .kiro/specs/custom-resource-reporting 已规划未实施。
**已具备(E2 Phase 1/2/3 + elim,2026-10-27/28/29)**:
- **EXTERNAL flag 全链**:XCE_RESF_EXTERNAL 有声明式 setter(mapping.py `location: [external]` → SHARED|GLOBAL|EXTERNAL 0x1C,mapping.py:448-452);调度准入 EXTERNAL 判式落地(resource.c:176/198 unsatisfy_ `is_external` 两分支:EXTERNAL `total ≥ uncomit + wanted`,跳过 inuse 项——free 值语义,对齐 Slurm GRES/LSLicense 路线而非 LSF bld 归因路线)。
- **独立采集 daemon xceesd**(src/esd/,XCE_TESTING 之外首条 daemon 形采集链):script 采集器(esd_script.c,外部命令 stdout JSON)+ flexlm 接口位(esd.h:22,同一 interface 覆盖 `lmstat -a`);esd.yaml 配置(cyaml schema);join/rejoin/透明重连即全量重推(bug-1978 修复 b471ce31);fail-open 断联策略(esd.c:100-109,保旧值 + stale WARN 升级,`stale_limit` 默认 150s)。
- **wire 零 schema 变更**(复用 RESVALS_DELTA + HostRole `extres`);opupd 守卫"SHARED 即收"(为 elastic-shared 留同一通道)。
- **运维面(Phase 2)**:stale 逐源标记 + WARN 全链;`xceadmin extres status`(本地 status file JSON 渲染,value/age/STALE);resources dump 渲染 `external=True`/`builtin=True`/distributions(build.py:221-227)。
- **策略层(Phase 3)**:per-project/per-queue license 配额 = limit vres 机制复用(ServiceDomain≈queue、DISTRIBUTION≈limit 配额的 LSF 词汇映射);根因修复 bug-1976(controller dispatch 重建丢 allocs_shared → vres 永不计费、global limit 全失效);t1 E2E 三 projA RUN/第 4 PEND/kill 再准入实证。
- **elim 主机级采集(design §3.3b,归 xcecd 不归 esd)**:worker/src/elim.c(656 行)——xcecd.yaml `external_resources:` 脚本源声明 → 子进程采集 → `resource_sync_register_load_index` 接入既有 11 内置指数同一条推送链(elim.c:595);EXTERNAL 记账规则同一套(全局 license 与主机 elim 两条腿同一模型)。
**仍缺(按 design 未做项 + 新边界)**:
- dynres1/dynres2 类**通用 dynamic 资源仍无通用采集钩子**——elim 采集器只覆盖"显式声明 external_resources 的脚本源";任意外部程序报告任意资源名的 LSF elim 全等价物(custom-resource-reporting spec)仍属规划。当前答案是"再写一个 elim 源",不是"自动发现"。
- **multi-daemon 冗余**(Phase 3 原计划项:多 xceesd last-writer-wins)未实现——单 daemon 部署是唯一验证过的形态。
- **手动覆盖 REST**(管理员临时改 free 值)按 design 有意不做。
- **esd 状态只在本机**:`xceadmin extres status` 读 daemon 本地 status file,无远程通道(design 3.6 有意留给 PR-2 proxy,未建 proxy)。
- **merge 归因报告层**(design §3.3c Tier 0-3 + 残差桶闭合):准入免疫已达成(判式只用聚合值),但 Tier1'/Tier2 匹配器、对账 alert 均未实现——多 app 共享同一 license 时账目只能给"我们放行了什么"(limit vres 记账),给不出"他们持有什么"的分解。
- P9 共享池写入权按资源分模式(EXTERNAL=server 赢/无 flag=elastic provisioner 赢)已按此实现,但与 Rongsong 的 §3.6 合并确认仍未做(提请决策项 2/3 未决)。
**原 ✗ 清单其余项不变**:scaler.yaml→hproviders 依旧 scheduler 零消费者(身份是 provider 非采集器,另案);.kiro/specs/custom-resource-reporting 仍规划未实施。
### E2/elim 完成面对照(gaps 原文 → 现状)
| 原 gaps 记载 | 现状 |
|---|---|
| XCE_RESF_EXTERNAL 全库无 setter | ✓ 已接:mapping.py:448 `location: [external]` |
| 无 elim 式外挂采集器 | ✓ 已接:elim.c 脚本采集 + xceesd 全局采集(两条腿) |
| `resource_sync_register_load_index` 无调用方 | ✓ 已接:elim.c:595 |
| dynres 声明 interval 无采集者 | ✗ 仍缺(同上,通用钩子未做) |
| .kiro/specs/custom-resource-reporting 未实施 | ✗ 仍规划(elim 覆盖其"脚本源"形态,非全部) |
---
@ -129,11 +155,12 @@
## 1.10 shared resource
**△ 机制存在,端到端不通。**
> **2026-10-29 复评:机制存在端到端不通 → 集群级([all]+value / [external])形态端到端已通,host 子集形态仍缺。**
- 机制 ✓:SHARED flag 资源进集群级共享池 c->sharedinst(worker.c:65-143 按 flag 路由);调度两段式——先集群级 precheck(sched_alloc_prepare_shared_,alloc_runner.c:73-132,不满足→无主机 PEND 行+PREASON_NO_RESOURCE/LIMIT_GLOBAL)再逐主机检查;snapshot 以 host==NULL 池形态携带恢复(bug-1923)。limit vres(GLOBAL limit)是当前唯一活的生产者。
- 断点 ✗:YAML 映射不置 SHARED flag(mapping.py:194-200)+ resourcemap(LSF 式静态份额/实例定义,如 dynres2 host1:50/host2:50)build 时丢弃 → **静态共享资源(license 类场景)声明得、用不上**;实测 distribution list 只有 hostbased 行,无共享实例行。
- .kiro/specs/elastic-shared-resources、resource-instances 已规划未实施。
- 机制 ✓:SHARED flag 资源进集群级共享池 c->sharedinst(worker.c:65-143 按 flag 路由);调度两段式——先集群级 precheck(sched_alloc_prepare_shared_,alloc_runner.c:73-132,不满足→无主机 PEND 行+PREASON_NO_RESOURCE/LIMIT_GLOBAL)再逐主机检查;snapshot 以 host==NULL 池形态携带恢复(bug-1923)。
- ~~断点 ✗:YAML 不置 SHARED flag + resourcemap build 时丢弃~~ **断点 ② 已修(2026-10-23,见文末)**:`location: [all]`+value 静态共享池(license 类场景的最简形态)声明即用,seed 进 sharedinst 且激活热更新。
- **E2 补全(2026-10-27/28)**:动态侧两个活的生产者——① xceesd 对 `location: [external]` 资源推 free 值(同一 sharedinst 通道,EXTERNAL 判式免 inuse 双扣);② limit vres(GLOBAL limit,Phase 3 扩展到 per-project/per-queue license 配额,bug-1976 修复使记账真正生效)。共享池 PEND reason 带资源名(alloc_runner.c:114 LIMIT_GLOBAL/NO_RESOURCE 判定)。
- **仍缺**:host 子集静态共享池(dynres2 host1:50/host2:50 形态——distributions 上 wire 但调度器零消费者,需 per-host 实例分账,elastic-shared-resources spec 仍规划);sharedinst 手动 update_resval 运维通道未验证;resource-instances spec 仍规划。
---
@ -144,7 +171,7 @@
| N1 | `xce id` 空壳:集群名/状态/管理员全空 | 实测输出 `<>`;handler.go:225 注释 |
| N2 | `queues list` 显示与准入不一致:closed 队列显示 open:active | 实测(close night 后提交被拒、list 仍 open:active) |
| N3 | exit code 不上 job API(REST ExitStatus 死字段) | convert_pure.go:646 无映射;SSE 有 exit_code |
| N4 | done 作业 live 无 GC、无 purge API、无归档:长运行 controller 终态作业内存只增不减 | persist.c:2558 唯一执行点;kvmgr.c:279 del_key=NULL;实测积压一天+ |
| N4 | done 作业 live 无 GC、无 purge API、无归档:长运行 controller 终态作业内存只增不减 | persist.c:2558 唯一执行点;kvmgr.c:279 del_key=NULL;实测积压一天+。**→ 断点 ③ 已修 live GC(2026-10-23,见文末),purge API/归档仍缺** |
| N5 | `jobs peek` 对已结束作业 501 | 实测 GET /jobs/:id/output status 501 |
| N6 | `jobs submit --configfile` 不解析配置行,拼进命令行当作业命令执行 | 实测:job.xce 两行变成 command "queue=short job_name=cfgtest2" |
| N7 | 用户无 CRUD:无 add/delete user、无改密码端点,加人=改 auth.yaml+重启 | routers.go 全量;users 命令族仅角色指派 |
@ -161,14 +188,15 @@
- gaps.md 一~七节(调度/架构/构建)全部继续有效,本文不重复;交叉引用已标注(#3 fairshare、#4 sched_delay、#6/#7/#15 PEND reason、#9 心跳窗、#12 配置传播、#17 执行上下文)。
- .kiro/specs 的空目录(elastic-hosts、controller-job-cleanup、job-dependency、gang-groups、resource-instances、custom-resource-reporting、host-failure-job-recovery、elastic-shared-resources、rbac-persistence、project-* 等)正是本评估所列缺口的"已规划未实施"标记;xce-node-manager 有完整 spec。规划面与管理面缺口高度吻合,说明缺口识别一致,缺的是实施。
- **2026-10-29 更新**:`external-license-resources` 是其中**已实施完成**的一个 spec(E2 Phase 1/2/3 + elim,见 1.7 复评);1.7/1.10/1.6 的相关缺口随之消解(详见 1.7 的对照表)。
## 四、若按用户价值排优先级(供第二步讨论)
1. **配置可达性**:让 config push 真正到达 live scheduler(gaps #12 的一半收益)+ 既有队列编辑热生效——"配了不生效"是管理面最大的信用问题。**→ 已作为断点 ① 修复,见下。**
2. **可见性补齐**(低风险高价值):queues list 状态显示修复(N2)、exit code 上 API(N3)、cluster info 填实(N1)、user/host group 查询端点(N9)、daemon/HA 状态只读命令(ctrlstatus 已有协议只差暴露)。
3. **生命周期补齐**:done 作业 GC+purge 命令(N4)、host 删除流程(elastic-hosts spec 落地)、用户 CRUD(N7)。
3. **生命周期补齐**:done 作业 GC+purge 命令(N4,**GC 部分已作为断点 ③ 修复**,purge/归档仍缺)、host 删除流程(elastic-hosts spec 落地)、用户 CRUD(N7)。
4. **管理动作补齐**:requeue/mig 控制动作(枚举已在、REST 400 挡着)、host 故障作业恢复策略(host-failure-job-recovery spec)。
5. **资源接线**:shared/external resource 的 YAML→capnp 断点(mapping + resourcemap 注释字段)、dynres 采集钩子(custom-resource-reporting spec)。
5. **资源接线**:shared/external resource 的 YAML→capnp 断点(mapping + resourcemap 注释字段)、dynres 采集钩子(custom-resource-reporting spec)。**→ 已大部分完成:断点 ②(SHARED/resourcemap 接线)+ E2(EXTERNAL 全链 + elim 采集 + per-project/queue 策略层,见 1.7);余项 = 通用 dynres 采集钩子、host 子集静态共享池(elastic-shared-resources)。**
---