前一集中,我們聊了 entity-manager 裡的 Probe:它負責「找到」一顆 FRU 並確認它是什麼身份:Motherboard?PSU?NIC?還是 DC-SCM?
但 Probe 只是第一步。真正把整台機器的拓撲「長」出來、讓每位板子都有自己的家與自己的名字,是在 Probe 之後的流程: updateSystemConfiguration() → naming → postToDbus()。
今天我們來認真深掘這件事:entity-manager 是怎麼把「一顆 FRU」變成 D-Bus 上那棵美麗的 Inventory Tree? 更重要的是,它是怎麼保證 重開機之後,板子不會突然改名、index 不會亂跳?
為什麼 Inventory 名稱的穩定性這麼重要?
OpenBMC 是一個高度動態的系統,不像 BIOS 那樣有一套固定的 enumeration 流程。以下是日常會遇到的「不穩定性」:
- FRU EEPROM 回應慢一點,第一次掃描抓不到
- I²C 仲裁有 delay,bus 掃描順序亂掉
- 多顆 NIC / PSU 同時存在時,誰先被掃到完全不一定
- DC-SCM / CPU board 有時候後上電,會比 Motherboard 晚出現
- MCTP endpoint 每次 enumeration 都可能不同順序
如果 entity-manager 直接依照「掃描順序」命名 Inventory:
第一次開機:
nic0, nic1
第二次開機(順序反了):
nic1, nic0
光是這件事,就足以讓:
- Redfish
- dbus-sensors
- PLDM stack
- BIOS inventory 匹配
- 上層管理平台(Meta、Google、Microsoft)
管理起來相當困擾~
所以 entity-manager 的核心理念很簡單:
「不論硬體什麼時候出現、不論順序怎麼變,我都希望知道你是誰,並且讓你一直叫同一個名字。」
這就是接下來四個工具登場的原因:
- getRecordName()
- usedNames
- indexes
- generateDeviceName()
getRecordName():找出一顆 FRU 的「指紋」
entity-manager 第一個要解決的問題是:我怎麼知道這顆 FRU 跟上次那顆是同一顆?掃描順序不能信、mapper 回傳順序不能信、DBus event 出現順序更不能信。唯一穩定的,只有裝置自己的屬性,也就是 FRU EEPROM 裡的:
- Serial Number
- Part Number
- Product Name
- Manufacturer
- BOARD_、PRODUCT_、CHASSIS_* 等欄位
getRecordName() 會:
- 把這些 D-Bus 上的 FruDevice 屬性做 hash
- 加上 Probe 自己的名稱
- 得到一個「唯一」又「穩定」的 key
像這樣:
Yosemite5_MB_f0ab3291這樣 entity-manager 就算在下一次開機時:
- Motherboard 比 DC-SCM 晚出現
- NIC 比 PSU 先被掃到
- bus 掃描順序不同
它仍然能靠 recordName 知道:「喔,我認得你,上次就是這顆 MB。」這是所有穩定命名邏輯的基礎。
usedNames 與 indexes:名字不該跳號,也不能撞名
當 entity-manager 確定「你是誰」之後,下一步就是:
那你該叫什麼名字?
這裡有兩個目標:
- 舊的 FRU 保持原本名字
- 新的 FRU 要有合適的 index、不撞名、不跳號
於是就需要兩個資料結構:
- usedNames:這一輪已經分配出去的名稱
- indexes:這一輪可用的 index 清單(像 {0,1,2,3,...})
流程大概是:
Step 1:先處理舊的、有記錄的 FRU
如果 recordName 在 systemConfiguration 或 lastJson 裡存在:「你之前叫 'Yosemite5 MB',那現在我就讓你繼續叫那個名字。」於是 indexes 裡那個 index(假設是 0)會被移除。避免被後來的新 FRU 占走。
Step 2:剩下的是新 FRU(第一次看到)
entity-manager 會依序從 indexes 裡拿出一個 index,比如:
indexes = {0,1,2}
新裝置 → 拿 0 → 剩 {1,2}
然後這個 index 會交給 generateDeviceName() 去生成名稱。這也是為什麼:
- 多顆 NIC 永遠是 nic0、nic1
- 多顆 PSU 永遠是 psu0、psu1
- 無論順序怎麼變,index 都穩定不跳
generateDeviceName():把模板變成真正的名稱
看過 JSON 的人一定熟悉:
"Name": "Y5 NIC {index}"
或:
"Name": "$PRODUCT_PRODUCT_NAME $BOARD_SERIAL_NUMBER"
entity-manager 會在這裡做三件事:
- 把
$FIELD換成 FruDevice 上的真實值 - 把
{index}或$index替換成剛剛選出來的 index - 如果名稱撞名(例如 OM 沒設好 FRU,兩顆 PSU 一模一樣),
就會自動加上後綴避免衝突
所以最終你會得到穩定的:
Yosemite5 MB
Y5 NIC 0
Y5 NIC 1
PSU 0
PSU 1
即使硬體順序每天都變,它們還是會「叫同一個名字」。
FRU 資料是怎麼被寫進 Inventory Decorator 的?(填空題)
這也是很多人第一次看 entity-manager 時的疑惑:「JSON 裡那些 Decorator 值,是誰填進去的?」
例如:
"xyz.openbmc_project.Inventory.Decorator.Asset": {
"Manufacturer": "$BOARD_MANUFACTURER",
"Model": "$BOARD_PRODUCT_NAME",
"SerialNumber": "$BOARD_SERIAL_NUMBER"
}
這些 $FIELD 其實都會被 templateCharReplace() 替換成 FRU 裡的值。
像:
$BOARD_MANUFACTURER → Wiwynn
$BOARD_SERIAL_NUMBER → WNC-1234-5678
它就像是在做「自動填空」。而因為 entity-manager 用的是 FRU 上的 D-Bus 屬性,也確保了這些 Inventory 資料是:
- 一致的
- 可信賴的
- 可以對應到真實硬體
把整個系統變成一棵樹:Associations + Exposes
最後,entity-manager 會利用:
- JSON 的 Association
- Exposes 裡定義的子節點
- Probe 的匹配結果
建出一棵階層式的 Inventory Tree。
例如:
/system/chassis
/motherboard
/dc-scm0
/cpu-board0
/cpu-board1
/nic0
/nic1
/psu0
/psu1
如果 JSON 有:
"Associations": [
{ "Forward": "chassis", "Backward": "contained_by", "From": "Motherboard" }
]
entity-manager 會建立對應的關聯:
Motherboard → contained_by → chassisCPU board、NIC、PSU 都會透過類似機制被擺在正確的位置。
最終的動作:postToDbus() → 真正建立 Inventory
一旦 naming / Decorator 填寫 / Associations 都準備好了:
publishNewConfiguration()
→ postToDbus()
entity-manager 會正式把整台系統「發佈」到 D-Bus:你會看到:
/xyz/openbmc_project/inventory/system/chassis/motherboard
/xyz/openbmc_project/inventory/system/chassis/nic0
/xyz/openbmc_project/inventory/system/chassis/psu1
每個節點都帶有:
- xyz.openbmc_project.Inventory.Item
- xyz.openbmc_project.Inventory.Decorator.Asset
- xyz.openbmc_project.Inventory.Decorator.AssetTag
- xyz.openbmc_project.Association.Definitions
上層服務(Redfish、dbus-sensors、PLDM)就能順利讀取整台機器的拓撲。
總結:entity-manager 命名不亂跳的四大基石
把整段邏輯濃縮後,你會得到一個非常清楚的流程:
- getRecordName:找到 FRU 的「指紋」(不會因順序變動)
- usedNames / indexes:分配穩定、連續、不撞名的 index
- generateDeviceName:用模板生出人類看的懂的名稱
- systemConfiguration:把所有結果寫入這一輪掃描總表
這串邏輯讓 OpenBMC 在每次開機時,仍能呈現:可靠且一致,可對應真實硬體的系統拓樸。





















