Skip to content

DesiredState 参考

DesiredState 是「单节点应运行什么」的完整声明式输入,schema 版本 v1。本目录是其字段的单一事实源。

源码在 packages/dn42_schemas/dn42_schemas/desired_state.py(顶层、跨字段校验、normalize 钩子)、network.pyrouting.pydns.pyruntime.pyenums.py,示例见 testing.py

分册

文档内容
节点与接口 specNodeSpecInterfaceSpecWireGuardPeerSpec
Runtime specRouterRuntimeSpec 及其全部嵌套:服务、卷、健康检查、构建、端口、underlay、RPKI、Dockerfile
BIRD 与路由 specBird2ConfigSpecBgpSessionSpecBfdSpec、内部拓扑、large community、RouteLocalPrefSpec
DNS specDnsSpecDnsZoneSpecDnsRecordSpecDnsForwardSpec
Normalize 钩子四个 normalize 钩子(派生 / 注入 / 剥离)、TemplateSetSpec、枚举、完整示例

相关:DB 事实如何变成本对象见 materialize 写入路径;地址的源 / 派生 / 副本分类见 地址模型


StrictModel 不变量

本包所有 schema 对象继承 StrictModeldn42_schemas/base.py):

  • extra="forbid"——拒绝任何未知字段。控制面与 agent 之间的任何隐式协议漂移都会在解析期直接报错,而不是被静默忽略。这也是锁步升级纪律的由来。
  • frozen=True——模型不可变。唯一受控豁口是 validate_references 里 normalize 钩子用 object.__setattr__ 回写 runtime / interfaces / bird;其它任何地方都按不可变对象使用。
  • canonical_json()——稳定可复算的 JSON(排序键、紧凑分隔符、ensure_ascii=False),使控制面与 agent 在不同进程对同一对象算出一致的字节序列。
  • canonical_sha256()——上述 canonical JSON 的 SHA-256 十六进制摘要,用于哈希门控与内容寻址。

顶层字段

源码 desired_state.py

字段类型必填说明
schema_versionLiteral["v1"]否(默认 "v1"schema 版本号;当前只接受 v1
generationintge=1期望状态世代号,通常由控制面递增
nodeNodeSpec节点身份、ASN、前缀、loopback、link-local
runtimeRouterRuntimeSpecruntime 部署:underlay、Dockerfile、RPKI、服务列表、WG 端口范围
birdBird2ConfigSpec否(默认空配置)BIRD 2 模板的高层配置
interfaceslist[InterfaceSpec]否(默认 []节点应创建的接口
bgp_sessionslist[BgpSessionSpec]否(默认 []节点应建立的 BGP 会话
dnsDnsSpec | None否(默认 None本地 DNS 服务配置;None 表示不生成 DNS
templatesTemplateSetSpec否(默认值)渲染时选用的模板集版本

validate_referencesmodel_validator(mode="after"))在解析后跑跨字段校验并执行 normalize 钩子。


跨字段校验规则

DesiredState.validate_references 按顺序执行:

  1. 接口名唯一——interfaces[*].name 不得重复。
  2. BGP 会话名唯一——bgp_sessions[*].name 不得重复。
  3. BGP 会话引用的接口须存在——每个非空 session.interface 必须出现在 interfaces 的名集合里。
  4. 每 WG 接口单一外部远端 ASN——对 enabled 且非内部的会话,按 interface 聚合 remote_asn;同一接口出现多个外部 ASN 即报错。
  5. 内部拓扑须包含本节点——若 bird.internal_topology 存在,node.node_id 必须属于 routers + private_nodes

嵌套模型自身的校验在解析期已生效,关键的几条:

模型校验
NodeSpecloopback_ipv4 ∈ ipv4_prefixesloopback_ipv6 ∈ ipv6_prefixes;前缀走 DN42 网络校验;link_local 须为合法 fe80::/10
InterfaceSpec名 ≤15 字符;wireguard 接口须有 private_key_ref字面私钥)与 wireguard_peer,非 wireguard 不得有 wireguard_peer
BgpSessionSpecneighbor / zone / interface 一致性;IPv6 link-local 邻居须给 %zone 或显式 interface
InternalTopologySpecrouters / private_nodes / igp_adjacencies 引用的节点都须在 hosts
RouterRuntimeSpecruntime.md 的服务校验
UnderlayNetworkSpecipv6_subnet 设了就必须有 ipv6_gateway
PortPublishSpec / WireGuardPortRangeSpec端口范围一致性与上界校验
DnsZoneSpec有内联 records 时须同时给 primary_nsadmin_email