MDB Lua API
概述
MDB Lua API 提供了 MDB Service 和 Privilege 模块的 Lua 绑定,使 Lua 脚本能够方便地访问 BMC 的 MDB 服务和进行权限验证。
加载模块
local lmdb = require('lmdb')
模块包含两个子模块:
lmdb.mdb_service: MDB 服务接口lmdb.privilege: 权限验证接口
主要特性
- 对象查询: 通过
mdb_service子模块查询和管理 DBus 对象,支持深度控制、分页和缓存 - 权限验证: 通过
privilege子模块进行位掩码权限验证,支持 8 种预定义权限级别 - 服务发现: 自动查找 DBus 服务名称、获取接口所有者、验证路径有效性
- 缓存管理: 内置 LRU 缓存机制,支持路径缓存、缓存大小控制和手动清除
- 权限组合: 配合
bit库实现多个权限的按位或组合,灵活控制访问级别
子模块文档
MDB Service
MDB Service 模块提供了与 BMC MDB 服务(bmc.kepler.maca)通信的接口,包括:
- 对象查询接口(get_object, get_sub_objects, get_sub_paths, get_parent_objects)
- 服务查询接口(get_service_name, get_service_names)
- 路径查询接口(get_path, get_interface_owners, is_valid_path, get_sub_paths_paging)
- 类和对象接口(get_classes, get_object_list, get_object_owner, get_matched_objects, get_traced_object)
- 缓存管理接口(clear_cache, set_max_cache_size, get_max_cache_size, get_cache_size)
详细文档: MDB Service Lua API
Privilege
Privilege 模块提供了权限验证功能,包括:
- 权限常量(ReadOnly, DiagnoseMgmt, SecurityMgmt, BasicSetting, UserMgmt, PowerMgmt, VMMMgmt, KVMMgmt, ConfigureSelf)
- 认证状态常量(NoAuth, AuthRequired)
- 权限验证函数(validate, get_privilege_str)
详细文档: MDB Privilege Lua API
快速开始
示例 1: 查询对象路径
local ldbus = require('ldbus')
local lmdb = require('lmdb')
-- 创建 DBus 连接
local conn = ldbus.blocking.open_system()
-- 查询网络接口路径(使用缓存)
local path = lmdb.mdb_service.get_path(
conn:get_raw(),
"xyz.openbmc_project.Network.EthernetInterface",
'{"InterfaceName": "eth0"}',
false, -- 不忽略大小写
true -- 启用缓存
)
print("网络接口路径:", path)
conn:close()
示例 2: 权限验证
local lmdb = require('lmdb')
-- 验证用户管理权限
local ok, err = pcall(function()
lmdb.privilege.validate(lmdb.privilege.UserMgmt)
end)
if ok then
print("权限验证成功,可以执行用户管理操作")
else
print("权限验证失败:", err)
end
示例 3: 获取子对象
local ldbus = require('ldbus')
local lmdb = require('lmdb')
local conn = ldbus.blocking.open_system()
-- 获取所有子对象
local objects = lmdb.mdb_service.get_sub_objects(
conn:get_raw(),
"/redfish/v1/Systems",
1,
{"xyz.openbmc_project.Inventory.Item"}
)
-- 遍历对象
for path, obj in pairs(objects) do
print("路径:", path)
for key, value in pairs(obj) do
print(" " .. key .. ":", value)
end
end
conn:close()
模块结构
lmdb
├── mdb_service -- MDB 服务接口
│ ├── get_object()
│ ├── get_sub_objects()
│ ├── get_sub_paths()
│ ├── get_parent_objects()
│ ├── get_service_name()
│ ├── get_service_names()
│ ├── get_path()
│ ├── get_interface_owners()
│ ├── is_valid_path()
│ ├── get_sub_paths_paging()
│ ├── get_classes()
│ ├── get_object_list()
│ ├── get_object_owner()
│ ├── get_matched_objects()
│ ├── get_traced_object()
│ ├── clear_cache()
│ ├── set_max_cache_size()
│ ├── get_max_cache_size()
│ └── get_cache_size()
│
└── privilege -- 权限验证接口
├── ReadOnly -- 常量
├── DiagnoseMgmt -- 常量
├── SecurityMgmt -- 常量
├── BasicSetting -- 常量
├── UserMgmt -- 常量
├── PowerMgmt -- 常量
├── VMMMgmt -- 常量
├── KVMMgmt -- 常量
├── ConfigureSelf -- 常量
├── NoAuth -- 常量
├── AuthRequired -- 常量
├── get_privilege_str()
└── validate()
使用场景
RESTful API 开发
local lmdb = require('lmdb')
function handle_get_user(user_id)
-- 验证只读权限
lmdb.privilege.validate(lmdb.privilege.ReadOnly)
-- 查询用户路径
local path = lmdb.mdb_service.get_path(
conn:get_raw(),
"xyz.openbmc_project.User.Manager",
string.format('{"UserId": "%s"}', user_id),
false,
true
)
-- 获取用户对象
local user = lmdb.mdb_service.get_object(
conn:get_raw(),
path,
{"xyz.openbmc_project.User.Attributes"}
)
return user
end
function handle_delete_user(user_id)
-- 验证用户管理权限
lmdb.privilege.validate(lmdb.privilege.UserMgmt)
-- 执行删除操作
-- ...
end
系统监控
local lmdb = require('lmdb')
function monitor_system()
local conn = ldbus.blocking.open_system()
-- 获取所有传感器
local sensors = lmdb.mdb_service.get_interface_owners(
conn:get_raw(),
"xyz.openbmc_project.Sensor.Value"
)
-- 读取传感器值
for _, path in ipairs(sensors) do
local obj = lmdb.mdb_service.get_object(
conn:get_raw(),
path,
{"xyz.openbmc_project.Sensor.Value"}
)
print(string.format("%s: %s", path, obj.Value))
end
conn:close()
end
配置管理
local lmdb = require('lmdb')
function update_system_config(config_data)
-- 验证基础设置权限
lmdb.privilege.validate(lmdb.privilege.BasicSetting)
-- 查询配置对象路径
local path = lmdb.mdb_service.get_path(
conn:get_raw(),
"xyz.openbmc_project.Network.SystemConfiguration",
'{}',
false,
true
)
if path then
-- 更新配置
-- ...
print("配置更新成功")
else
print("未找到配置对象")
end
end
错误处理
所有函数在失败时都会抛出 Lua 错误,建议使用 pcall 进行错误捕获:
local ok, result = pcall(function()
return lmdb.mdb_service.get_path(
conn:get_raw(),
interface,
filter,
false,
true
)
end)
if ok then
print("查询成功:", result)
else
print("查询失败:", result)
end
性能建议
- 使用缓存: 对于频繁查询的路径,启用
get_path的缓存功能 - 批量查询: 使用
get_sub_objects批量获取对象,而不是逐个查询 - 限制深度: 在
get_sub_objects和get_sub_paths中合理设置深度参数 - 分页查询: 对于大量数据,使用
get_sub_paths_paging进行分页 - 权限检查: 在操作前进行权限验证,避免不必要的操作
最佳实践
- ✅ 在 RESTful API 处理函数中,先通过
privilege.validate验证权限,再使用mdb_service执行查询操作 - ✅ 对频繁查询的固定路径启用
get_path缓存,并合理设置set_max_cache_size避免内存浪费 - ❌ 不要在同一个请求处理中混用
mdb_service和直接 DBus 调用,应统一通过 MDB 模块访问以利于维护 - ❌ 不要在生产环境禁用缓存并进行深度无限的对象树遍历,会导致极高的 DBus 调用开销