From 857f987f3c888dfbc8f745a61e684d48135d9730 Mon Sep 17 00:00:00 2001 From: "lei.chen" Date: Wed, 28 Oct 2026 01:46:21 +0000 Subject: [PATCH] =?UTF-8?q?resources:=20XCE=5FRESF=5FBUILTIN=20=E4=BB=8E?= =?UTF-8?q?=E6=9C=AA=E8=A2=AB=E7=BD=AE=E4=BD=8D=20=E2=80=94=20resources.ya?= =?UTF-8?q?ml=20=E5=8A=A0=20builtin:=20true=20=E5=A3=B0=E6=98=8E=E5=BC=8F?= =?UTF-8?q?=E9=94=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit XCE_RESF_BUILTIN (0x01) 在生产链路上从未被任何一层置位:全树只有 types.h 定义、scheduler repl_info.c 显示表、一个测试 fixture 三处引用。worker init_builtin_load_indices()(mem/io/r1m…)、controller add_hostattrs_resvals()/ set_host_slots() 硬编码生产这些资源的值,但定义的 flags 从 YAML→capnp→wire 全程没人打这个位——CLI 的 BUILTIN 列对 mem/io/slots 等恒显 false,与 extlic 等用户资源无法区分。 - resources.schema.json(+xceadmin 打包副本,构建时从 src/configs/schema 同步):加 builtin: boolean 键 - mapping.py:RESOURCE_FLAG_BUILTIN=0x01,_build_resource 映射 builtin:true (与 consumable/release 同模式:缺省/false 不置位) - build.py dump:补渲染 builtin=True;顺手补同样一直缺失的 external=True (此前 EXTERNAL 池 dump 只显示 shared=true) - src/configs/resources.yaml:20 个硬编码生产者资源(slots + 11 load index + 8 host attributes)声明 builtin: true - golden fixture full/expected.bin 相应再生(6696→6856B,diff 恰为 20 行 builtin=True,非 builtin 行 0 差异) 验证:xceadmin 389 测试全绿(dev venv + meson build.dbg 各一遍);t1 实证: 树内 venv 重建 cluster.bin(与 live 逐行比对确认 delta 仅 builtin 20 行)→ config push gen=17 → apiserver 重启拾取(定义 store 只吃 join 时 config push,激活只 re-push scheduler)→ xcecli definition list -l mem/io/slots BUILTIN=true,extlic false、distribution/extlic 值/liccheck 作业 RUN→DONE 全链正常,5 daemon 健康。 Co-Authored-By: Claude Code --- src/configs/resources.yaml | 24 +++++++++++- src/configs/schema/resources.schema.json | 1 + src/xceadmin/src/xceadmin/build.py | 9 +++++ src/xceadmin/src/xcecommon/mapping.py | 22 +++++++---- .../fixtures/full/configs/resources.yaml | 14 +++++++ src/xceadmin/tests/fixtures/full/expected.bin | Bin 6696 -> 6856 bytes src/xceadmin/tests/test_config_dump.py | 26 +++++++++++++ src/xceadmin/tests/test_mapping.py | 35 ++++++++++++++++++ 8 files changed, 122 insertions(+), 9 deletions(-) diff --git a/src/configs/resources.yaml b/src/configs/resources.yaml index 4fc601b2..0c2fbe09 100644 --- a/src/configs/resources.yaml +++ b/src/configs/resources.yaml @@ -5,6 +5,7 @@ resources: type: numeric order: decrease consumable: true + builtin: true description: "job slot count (built-in)" # built-in: dynamic memory load index reported by workers @@ -12,6 +13,7 @@ resources: type: numeric interval: 60 consumable: true + builtin: true order: decrease description: "available memory in bytes (built-in dynamic load index; CLI display converts to a human-readable unit)" @@ -21,6 +23,7 @@ resources: type: numeric interval: 60 consumable: false + builtin: true order: increase description: "1-minute load average (built-in dynamic load index)" @@ -28,6 +31,7 @@ resources: type: numeric interval: 60 consumable: false + builtin: true order: increase description: "15-minute load average (built-in dynamic load index)" @@ -35,6 +39,7 @@ resources: type: numeric interval: 60 consumable: false + builtin: true order: increase description: "15-second load average (built-in dynamic load index)" @@ -42,6 +47,7 @@ resources: type: numeric interval: 60 consumable: false + builtin: true order: increase description: "cpu utilization" @@ -49,6 +55,7 @@ resources: type: numeric interval: 60 consumable: false + builtin: true order: increase description: "page ratio" @@ -56,6 +63,7 @@ resources: type: numeric interval: 60 consumable: false + builtin: true order: increase description: "login count" @@ -63,13 +71,15 @@ resources: type: numeric interval: 60 consumable: false + builtin: true order: increase description: "idle time" - + - name: swp type: numeric interval: 60 consumable: true + builtin: true order: decrease description: "swap size" @@ -77,13 +87,15 @@ resources: type: numeric interval: 60 consumable: false + builtin: true order: increase description: "io rate" - + - name: tmp type: numeric interval: 60 consumable: true + builtin: true order: decrease description: "available tmp disk space in bytes (built-in dynamic load index; CLI display converts to a human-readable unit)" @@ -91,34 +103,42 @@ resources: # controller/worker.c add_hostattrs_resvals() - name: type type: string + builtin: true description: "host OS/arch type (built-in host attribute)" - name: model type: string + builtin: true description: "host hardware model (built-in host attribute)" - name: cpuf type: numeric + builtin: true description: "CPU speed factor (built-in host attribute)" - name: maxcpus type: numeric + builtin: true description: "max CPU count (built-in host attribute)" - name: maxmem type: numeric + builtin: true description: "max memory in bytes (built-in host attribute; CLI display converts to a human-readable unit)" - name: maxswap type: numeric + builtin: true description: "max swap in bytes (built-in host attribute; CLI display converts to a human-readable unit)" - name: maxtmp type: numeric + builtin: true description: "max tmp disk space in bytes (built-in host attribute; CLI display converts to a human-readable unit)" - name: ndisks type: numeric + builtin: true description: "disk count (built-in host attribute)" # dynamic hostbased resource, external load index diff --git a/src/configs/schema/resources.schema.json b/src/configs/schema/resources.schema.json index b11620a4..06515aa0 100644 --- a/src/configs/schema/resources.schema.json +++ b/src/configs/schema/resources.schema.json @@ -12,6 +12,7 @@ "order": { "type": "string", "enum": ["increase", "decrease", "na"] }, "consumable": { "type": "boolean" }, "release": { "type": "boolean" }, + "builtin": { "type": "boolean" }, "description": { "type": "string" }, "resourcemap": { "type": "array", diff --git a/src/xceadmin/src/xceadmin/build.py b/src/xceadmin/src/xceadmin/build.py index edf33494..94799ec1 100644 --- a/src/xceadmin/src/xceadmin/build.py +++ b/src/xceadmin/src/xceadmin/build.py @@ -208,7 +208,9 @@ def _format_resource(r) -> str: ordtype = _RESOURCE_ORDTYPE_NAMES.get(r.ordtype, r.ordtype) consumable = bool(r.flags & mapping.RESOURCE_FLAG_CONSUMABLE) release = bool(r.flags & mapping.RESOURCE_FLAG_RELEASE) + builtin = bool(r.flags & mapping.RESOURCE_FLAG_BUILTIN) shared = bool(r.flags & mapping.RESOURCE_FLAG_SHARED) + external = bool(r.flags & mapping.RESOURCE_FLAG_EXTERNAL) parts = [f"name={r.name}", f"type={valtype}", f"order={ordtype}"] if r.desc: parts.append(f"desc={r.desc!r}") @@ -216,6 +218,13 @@ def _format_resource(r) -> str: parts.append(f"interval={r.interval}") parts.append(f"consumable={consumable}") parts.append(f"release={release}") + # builtin/external change the resource's semantics (whose values count, + # where they come from) -- always visible when set, never shown bare + # false: absent means the plain user-resource default. + if builtin: + parts.append("builtin=True") + if external: + parts.append("external=True") if shared: parts.append("shared=true") if len(r.distributions) > 0: diff --git a/src/xceadmin/src/xcecommon/mapping.py b/src/xceadmin/src/xcecommon/mapping.py index 709de22b..2637a373 100644 --- a/src/xceadmin/src/xcecommon/mapping.py +++ b/src/xceadmin/src/xcecommon/mapping.py @@ -64,12 +64,12 @@ reason -- never a silent drop. ``Resource`` (``resources.yaml``) ``valtype``/``ordtype``/``flags`` ARE mapped from YAML - ``type``/``order``/``consumable``/``release`` -- the encoding is - documented, just not in ``controller.capnp``/design.md: it lives in + ``type``/``order``/``consumable``/``release``/``builtin`` -- the encoding + is documented, just not in ``controller.capnp``/design.md: it lives in ``include/xce/types.h`` (``XCE_VAL_*``, ``xce_order_t``, - ``XCE_RESF_CONSUMABLE``/``XCE_RESF_RELEASE``) and is actively read at - runtime (e.g. ``scheduler.c`` copies these three fields straight out - of the parsed resource). See :data:`RESOURCE_VALTYPE`, + ``XCE_RESF_CONSUMABLE``/``XCE_RESF_RELEASE``/``XCE_RESF_BUILTIN``) and + is actively read at runtime (e.g. ``scheduler.c`` copies these three + fields straight out of the parsed resource). See :data:`RESOURCE_VALTYPE`, :data:`RESOURCE_ORDTYPE`, and the flag constants below for the exact values (also reused by ``xceadmin.build.dump_cluster_config`` to render these int-encoded fields back to their YAML names). ``idx`` and @@ -205,10 +205,16 @@ _XCE_SCALAR_FIELDS: tuple[tuple[str, str], ...] = ( RESOURCE_VALTYPE: dict[str, int] = {"string": 0, "numeric": 1, "boolean": 2} RESOURCE_ORDTYPE: dict[str, int] = {"increase": 0, "decrease": 1, "na": 2} -# resources.yaml ``consumable``/``release`` -> Resource.flags bits, mirroring -# include/xce/types.h's XCE_RESF_CONSUMABLE/XCE_RESF_RELEASE. +# resources.yaml ``consumable``/``release``/``builtin`` -> Resource.flags +# bits, mirroring include/xce/types.h's XCE_RESF_CONSUMABLE/ +# XCE_RESF_RELEASE/XCE_RESF_BUILTIN. RESOURCE_FLAG_CONSUMABLE = 0x80 RESOURCE_FLAG_RELEASE = 0x20 +# XCE_RESF_BUILTIN: the resource's values are produced by hardcoded worker/ +# controller reporters (resource_sync.c's load indices, worker.c's host +# attributes and slots) -- display/accounting code uses it to tell those +# from user-declared resources of the same name space. +RESOURCE_FLAG_BUILTIN = 0x01 # Set together on a resourcemap item whose location is exactly ["all"] # (cluster-wide static shared pool): XCE_RESF_SHARED | XCE_RESF_GLOBAL in @@ -421,6 +427,8 @@ def _build_resource(item: dict, target: "capnp._DynamicStructBuilder") -> None: flags |= RESOURCE_FLAG_CONSUMABLE if item.get("release"): flags |= RESOURCE_FLAG_RELEASE + if item.get("builtin"): + flags |= RESOURCE_FLAG_BUILTIN resourcemap = item.get("resourcemap") or [] if resourcemap: distributions = target.init("distributions", len(resourcemap)) diff --git a/src/xceadmin/tests/fixtures/full/configs/resources.yaml b/src/xceadmin/tests/fixtures/full/configs/resources.yaml index f12b9f82..22be4e85 100644 --- a/src/xceadmin/tests/fixtures/full/configs/resources.yaml +++ b/src/xceadmin/tests/fixtures/full/configs/resources.yaml @@ -12,6 +12,7 @@ resources: type: numeric interval: 60 consumable: false + builtin: true order: decrease description: "available memory in MB (built-in dynamic load index)" @@ -197,3 +198,16 @@ resources: - name: gstring description: string resource type: string + + # external-license-resources: cluster-wide license pool reported by + # the extres daemon (xceesd) -- config declares only the name/shape, + # the free counts come from the daemon's pushes + - name: extlic + description: externally reported license pool + type: numeric + interval: 0 + consumable: true + order: decrease + resourcemap: + - location: + - external diff --git a/src/xceadmin/tests/fixtures/full/expected.bin b/src/xceadmin/tests/fixtures/full/expected.bin index 4d0e67affefbcd51c01f435aa450a330d4958ae4..3fa1e0a7edcbdfb2d9612bc9ff344d68ec5ff30d 100644 GIT binary patch delta 751 zcmZ2sa>A6Afq{V`Vj`=#Ejt?n!&^26hIU2<22)N326+YshEOP7%E`b`&cMJ>$;H4B z&cML%k&A&ro{@neH6_syWI)2iN_F11ObiT03=9k)`qIRY;*%S=S=1OA7#Kj<2BZuL zKV)KHP-0+U0MV-$Cku)j@qw6HP@yD<&|RpJAi9Wg;zu!%nUmK@a83Nj$9I#7fdQl* zL`R`XPJY15!sW!kz;Km`fx!t)a^eCOE-MBGhO}6tL_yjV0vLUm+AjlAqD2N7$UYuOWtS<-(y(pxB zdOLX|v%cV0kW-OFzfS(htS`#S%)o%G7Q|PdT*xgvu|q;o6HQWcav_Vppdm9P&|qfi zPTt6(KRJPwW%3gi8$n5Ci2q=+qLVkW3QuC?nC!zUA{ffdzyNYDi0)!wV2GVu$f_?G z2^9s=AkoCh8(H-Q*Fr7d$jrbni-Cb*CrB;tL8w{~-2_b`tf15}XW~X-QIH-`;DTr_ zMh1qx%nS_Tn@!og*)>utN^&xj85mM4N>YpR5_57Y6^c>|@{3ARQxtMClT-7GQxyvG X^K&M@;8qd#Vn8T_dSr7w?@As357?RX delta 627 zcmX?My26B&fq{X+Wg@G&?QvEHhPiAE4DE~z3{N>27~~lk7+5(Wv??b9LpcKjgC-XP zLpTEi!$K|w26;vXhSZcqLy!S66D!pxD=@Ke8Zj_1oMmEQxHR#j_~ZlJER#K$CHM|9 zF)%1GFff4VRg9B2iW`B2w4g#sV4=wh%q(0W?R%LR7>XDteiQ@i_mSk9_>YfoCldn$ zNIi&-LYLgi#K7Rhz`y{e(IwY1F)&y$Fff2<44o^XIzhA-y3VCgogjJ^K1nUOBnPvE z;9RJgAo>#n1H;P6hRphcAVWZI1koVTjgt$R^+7?#8wCnLC_X!RBeVYG2aGHzqE{z> zWY!ma%EZ8ctoG^TLT2fSJtBgf%%~EalM7k&1qGQQAqF*>fp_vo7JWw1$q!lVMSntl z29x{B#K2%a`6G+?WFJ XCE_RESF_BUILTIN (0x01) OR'd + on top of the other bits: the load indices (mem/io/r1m...) and host + attributes (type/model/maxmem...) are produced by hardcoded worker/ + controller reporters, and the flag tells them apart from user-declared + resources (the CLI's BUILTIN column renders it). Absent/false must + stay 0 -- the same convention as consumable/release. + """ + items = [ + {"name": "mem", "type": "numeric", "interval": 60, + "consumable": True, "builtin": True, "description": "memory"}, + {"name": "mylic", "type": "numeric", "consumable": True, + "builtin": False, "description": "user pool"}, + {"name": "plain", "type": "numeric"}, # builtin absent + ] + mapping.map_list_section(_spec_for("resources"), items, cluster_config) + + r0, r1, r2 = cluster_config.resources + assert r0.flags == 0x80 | 0x01 # CONSUMABLE | BUILTIN + assert r1.flags == 0x80 # explicit false -> no BUILTIN bit + assert r2.flags == 0 # absent -> no BUILTIN bit + + def test_map_list_section_noop_on_empty_or_missing_items(cluster_config): mapping.map_list_section(_spec_for("resources"), [], cluster_config) mapping.map_list_section(_spec_for("resources"), None, cluster_config) @@ -307,6 +330,18 @@ def test_map_list_section_resourcemap_real_repo_configs(cluster_config): for name in ("staticres1", "staticres2", "staticres3", "host_quota"): assert by_name[name].flags & (0x08 | 0x04) == 0 + # builtin:true resources (the worker load indices + host attributes the + # repo config declares) carry XCE_RESF_BUILTIN; user-declared shapes + # (staticres*, extlic) do not. + for name in ("slots", "mem", "r1m", "r15m", "r15s", "ut", "pg", "ls", "it", + "swp", "io", "tmp", "type", "model", "cpuf", "maxcpus", + "maxmem", "maxswap", "maxtmp", "ndisks"): + assert by_name[name].flags & 0x01 == 0x01, f"{name} missing BUILTIN" + for name in ("dynres1", "dynres2", "staticres1", "staticres2", "staticres3", + "staticres4", "res1", "sres1", "bigmem", "strres1", "strres2", + "host_quota", "gstring", "extlic"): + assert by_name[name].flags & 0x01 == 0, f"{name} unexpectedly BUILTIN" + # --------------------------------------------------------------------------- # map_list_section: users.yaml/hosts.yaml -> ugroups/hgroups (named groups)