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

性能建议

  1. 使用缓存: 对于频繁查询的路径,启用 get_path 的缓存功能
  2. 批量查询: 使用 get_sub_objects 批量获取对象,而不是逐个查询
  3. 限制深度: 在 get_sub_objects 和 get_sub_paths 中合理设置深度参数
  4. 分页查询: 对于大量数据,使用 get_sub_paths_paging 进行分页
  5. 权限检查: 在操作前进行权限验证,避免不必要的操作

最佳实践

  • ✅ 在 RESTful API 处理函数中,先通过 privilege.validate 验证权限,再使用 mdb_service 执行查询操作
  • ✅ 对频繁查询的固定路径启用 get_path 缓存,并合理设置 set_max_cache_size 避免内存浪费
  • ❌ 不要在同一个请求处理中混用 mdb_service 和直接 DBus 调用,应统一通过 MDB 模块访问以利于维护
  • ❌ 不要在生产环境禁用缓存并进行深度无限的对象树遍历,会导致极高的 DBus 调用开销

相关文档