点击此处查看详细分析解答
mdb中parent的使用及Port自动上树报错问题分析
问题描述
在使用mdb(Model Data Builder)进行资源建模时,当配置Port对象的parent指向Switch,并利用${parent}/Ports/:ID作为路径进行自动上树时,系统出现以下错误:
"Not match interface, path:${parent}/Ports/Port_9_01010B, interface:bmc.kepler.Switch.Port"
"AddObject Port_9_01010B failed" 并伴随 attempt to index a nil value 错误
这表明对象未能正确创建或属性赋值失败。
parent 在 MDB 中的正确使用方式
在 OpenUBMC 的 Model 架构中,parent 是一种用于定义层级关系的关键机制。它允许子对象继承父对象的上下文信息,特别是路径(path),从而构建清晰的资源树结构。
基本语法
"Port": {
"parent": "Switch",
"path": "${parent}/Ports/:ID",
...
}
parent: 指定父类对象的名称(如 Switch),必须与模型中定义的对象名一致。
${parent}: 是一个模板变量,会被替换为父对象的实际路径。例如,若 Switch 的路径是 /bmc/kepler/Switch/9,则 ${parent}/Ports/:ID 最终展开为 /bmc/kepler/Switch/9/Ports/:ID。
实现原理
- 当通过
CreateSwitch() 创建一个 Switch 实例时,框架会根据其 path 定义生成实际路径,如 /bmc/kepler/Switch/9。
- 所有以该
Switch 为 parent 的子对象(如 Port)将自动继承此路径前缀。
- 子对象通过
:ID 或其他动态参数完成路径的实例化,最终形成完整路径。
报错原因分析
1. 路径拼接异常导致接口不匹配
WARNING: Not match interface, path:${parent}/Ports/Port_9_01010B, interface:bmc.kepler.Switch.Port
- 错误中的路径仍包含未解析的
${parent} 变量,说明变量未被正确展开。
- 正常情况下,
${parent} 应已被替换为具体路径,如 /bmc/kepler/Switch/9。
- 由于路径包含非法字符
${parent},系统无法识别其所属接口,因此提示“interface not match”。
正确路径应为:/bmc/kepler/Switch/9/Ports/Port_9_01010B
当前路径为:${parent}/Ports/Port_9_01010B(变量未解析)
2. 对象初始化失败引发空引用(nil value)
ERROR: AddObject Port_9_01010B failed... attempt to index a nil value
- 因路径解析失败,
Port 对象未能成功注册到资源树。
- 后续属性设置(如
LogicPortId, Enable)尝试对一个不存在的对象操作,导致访问 nil 对象成员而出错。
- 具体堆栈指向
property_mgmt/init.lua:255,正是处理属性赋值的关键位置。
3. 可能的原因总结
| 原因 |
说明 |
parent 定义格式错误 |
使用了 "parent": "Switch(缺少引号闭合)— 此为严重语法错误 |
| 模型解析阶段未处理变量替换 |
框架未在创建对象前展开 ${parent} 模板变量 |
CreateSwitch 回调中未正确设置属性 |
若依赖回调填充路径相关字段,但回调未执行或顺序错误,也会导致路径构建失败 |
| 父对象尚未上树 |
如果 Switch 实例还未完成注册,子对象无法引用其路径 |
解决方案
修正 model.json 中的语法错误
原始配置:
"parent": "Switch
应修正为完整的字符串:
"parent": "Switch"
这是一个致命的 JSON 语法错误,会导致整个模型解析异常。
确保 Switch 对象已成功上树
在调用 CreatePort 之前,确保 Switch 已经完成创建和初始化:
self.switch_model = self:CreateSwitch(LSWMAIN_ID, function(object)
object.ObjectName = "Switch"
-- 确保其他必要属性也被设置
end)
-- 等待 Switch 对象完全注册后再创建 Port
-- 或确保 CSR 自发现流程已完成
手动控制上树流程(推荐用于复杂路径)
如果自动上树存在不确定性,可采用手动上树方式,精确控制路径生成:
local switch_path = "/bmc/kepler/Switch/" .. LSWMAIN_ID
local port_path = switch_path .. "/Ports/" .. port_id
base_service:CreatePort(LSWMAIN_ID, port_id, function(object)
object.LogicPortId = port_id
object.PortName = "Port_" .. port_id
object.Enable = "true"
object.path = port_path -- 显式设置路径
end)
同时在 on_add_object 中返回 false 来禁用 CSR 自动上树:
object_manage.on_add_object(self.bus, function(class_name, object, position)
self.lsw_cfg_mgmt:on_add_object(class_name, object, position)
end, function(object) return false end)
验证路径模板是否被支持
确认当前版本的 mdb 或 bingo 工具链是否支持 ${parent} 模板语法。部分旧版本可能仅支持静态路径或有限变量扩展。
建议查看官方文档或示例仓库验证用法,或改用显式拼接方式规避风险。
参考:正确的 Model 示例
{
"Switch": {
"path": "/bmc/kepler/Switch/:id",
"privilege": ["ConfigureSelf"],
"interfaces": {
"bmc.kepler.Switch.Ops": {
"methods": {
"GetPortsInfo": {
"privilege": ["ReadOnly"],
"req": {},
"rsp": {
"PortInfo": {}
}
}
}
}
}
},
"Port": {
"parent": "Switch",
"path": "${parent}/Ports/:ID",
"tableName": "t_port_attr",
"tableType": "PoweroffPer",
"privilege": ["ConfigureSelf"],
"interfaces": {
"bmc.kepler.Switch.Port": {
"properties": {
"LogicPortId": {
"baseType": "U32",
"usage": ["CSR"],
"primaryKey": true
},
"PortName": {
"baseType": "String",
"usage": ["CSR"],
"primaryKey": true
},
"Enable": {
"baseType": "String",
"usage": ["CSR"]
}
}
}
}
}
}
总结
| 项目 |
建议 |
| 语法检查 |
必须修复 "parent": "Switch 中缺少右引号的问题 |
| 路径展开 |
确保 ${parent} 能被正确解析为父对象路径 |
| 上树时机 |
确保父对象先于子对象完成上树 |
| 容错策略 |
对复杂场景建议采用手动上树 + 显式路径赋值 |
| 调试方法 |
使用 busctl 查看资源树实际路径,验证对象是否存在 |
通过以上修复措施,特别是修正语法错误并确保模型变量正确展开,可以有效解决 Port 自动上树失败的问题。