persistence
版本信息
| 项目 | 内容 |
|---|---|
| 组件版本 | 1.130.10 |
| 首发版本 | openUBMC 26.09 |
| 文档作者 | openUBMC 社区 |
| 最后更新 | 2026-09-15 |
| 许可证 | Mulan PSL v2 |
1. 组件概述
1.1 组件简介
persistence 是 openUBMC 基础框架中的配置与数据持久化组件,负责为业务组件提供远程持久化服务。这里的“远程”不是网络远程,而是指业务组件通过进程间 D-Bus 调用,把内存数据库中的持久化字段交给 persistence 统一写入对应后端;业务读取通常仍直接访问本组件的内存数据库,不在每次查询时访问 persistence。 组件同时包含以下能力:
- 统一管理 TemporaryPer、ResetPer、PoweroffPer、PermanentPer 四类数据;
- 在业务组件启动时批量读取数据,覆盖或合并 MDS/CSR 预置数据;
- 监听 ORM 数据库钩子,把插入、更新和删除转换为持久化事务;
- 合并高频事务、抑制写入风暴并支持显式 Flush;
- 为 PoweroffPer 提供周期备份、关键属性同步备份、完整性检查和损坏恢复;
- 为恢复出厂、平滑复位、一键日志收集和 NAND 写保护提供框架回调;
- 动态注册
/bmc/kepler/Global全局属性,并持久化可观测性 Dashboard 配置。 当前源码保留了独立persistence.service文件,但mds/service.json的deployConfig为framework.service,CHANGELOG 也记录 1.27.9 已将 persistence 进程合并进 framework 以降低内存。因此目标产品到底以独立单元还是 framework 内子服务运行,必须以产品 Manifest 和实际镜像为准。
1.2 解决什么问题
没有统一持久化机制时,每个业务组件都需要重复处理数据库路径、掉电等级、字段兼容、事务落盘、备份恢复、敏感数据脱敏和复位时序,容易造成实现分散和数据损坏。persistence 将这些共性能力下沉到框架:
- 业务开发者只需在 MDS 中标记持久化类型并使用 ORM 操作;
- 同一记录的不同字段可以分别放入不同持久化后端;
- 字段新增、删除和预置数据变化可以按字段粒度兼容;
- 高频写入先合并再落盘,降低 Flash 写放大;
- 关键掉电数据可同步写入备份数据库;
- 一键日志收集导出脱敏后的持久化数据和写入统计,便于定位问题。
1.3 核心功能
- 四级持久化:按数据在复位、掉电、恢复出厂后的保留要求选择存储后端。
- 客户端自动接入:PersistClient 恢复数据并注册内存数据库 insert/update/delete hook。
- 事务合并与风暴抑制:普通表约每 0.1 秒提交;一分钟内超过阈值的表延迟到大周期批量提交。
- 掉电数据库保护:完整性检查、备份区恢复、SQLite recover、关键字段同步备份。
- 配置备份与保留恢复:配合 ConfigManage 备份数据库,并在恢复出厂时保留指定表。
- 复位协同:平滑复位前等待客户端同步、强制提交事务、必要时备份并关闭数据库。
- 敏感信息保护:一键导出时仅输出 MDS 已定义字段,敏感值替换为
******。 - 全局属性与可观测配置:动态上树全局属性,持久化 Dashboard 的日志、指标和追踪配置。
1.4 关键术语表
| 术语 | 解释 |
|---|---|
| 远程持久化 | 业务组件通过 D-Bus 调用 persistence 服务端统一落盘;与组件自己管理的本地持久化相对。 |
| 本地持久化 | 由业务组件的 libmc4lua ORM 直接管理本组件数据库,不经过 persistence 主 D-Bus 接口。 |
| TemporaryPer | BMC 复位和掉电后均不保留的数据。 |
| ResetPer | BMC 复位后保留、掉电后丢失的数据。 |
| PoweroffPer | 掉电后保留、恢复出厂时通常清除的数据。 |
| PermanentPer | 恢复出厂后仍保留的数据,当前后端为专用原始设备节点(源码称“字符设备”,非文件系统)。 |
| Retain | 删除业务对象时仍保留指定持久化字段;显式上下文可要求同时删除。 |
| 关键数据 critical | PoweroffPer 属性更新时还要同步写入备份数据库的字段。 |
| 敏感数据 sensitive | 一键日志导出时必须脱敏的字段。 |
| 表属主 table owner | 允许访问某张远程持久化表的 D-Bus 服务名集合。 |
| 活动数据 active_data | 当前有效的持久化记录。 |
| 删除标记 deleted_data | 用于在恢复时删除预置记录的主键墓碑数据。 |
| 风暴抑制 | 同一表高频写入达到阈值后,暂停短周期提交并在一分钟大周期统一落盘。 |
| Flush | 等待客户端异步事务和服务端缓存事务完成并落盘的同步点。 |
1.5 外部交互边界图
1.5.1 典型数据时序
1.5.2 持久化类型和路径
| 类型 | 当前源码默认后端 | 保留语义 | 补充说明 |
|---|---|---|---|
| TemporaryPer | /run/persistence/per_temporary.db | BMC 复位丢失 | SQLite;服务启动时确保目录存在。 |
| ResetPer | /opt/bmc/pram/persistence/per_reset.db | 复位保留,掉电丢失 | SQLite;DELETE journal。 |
| PoweroffPer | /data/trust/persistence/per_poweroff.db | 掉电保留,恢复出厂通常清除 | SQLite;实体环境优先 WAL,备份路径为 /data/backup/persistence/per_poweroff.db。 |
| PermanentPer | /dev/mmcblk0p8 | 恢复出厂仍保留 | 源码/README 称“字符设备”;由 persist_driver 管理,实际按原始设备节点访问,不是普通文件系统数据库。 |
| 本地 Poweroff | LOCAL_POWEROFF_PATH_MINI/persistence.db 或 /data/trust/persistence.local/persistence.db | 由本组件 ORM 管理 | ConfigManage.Backup 会复制为 persistence.db。 |
1.5.3 主要服务、对象和接口
| 用途 | 服务名 | 对象路径 | 接口 |
|---|---|---|---|
| 远程持久化 | bmc.kepler.persistence | /bmc/kepler/persistence | bmc.kepler.persistence |
| Debug 持久化 | bmc.kepler.persistence | /bmc/kepler/Debug/Persistence | bmc.kepler.Persistence |
| 复位回调 | bmc.kepler.persistence | /bmc/kepler/persistence/MicroComponent | bmc.kepler.MicroComponent.Reboot |
| 配置备份/恢复 | bmc.kepler.persistence | /bmc/kepler/persistence/MicroComponent | bmc.kepler.MicroComponent.ConfigManage |
| 一键日志 Dump | bmc.kepler.persistence | /bmc/kepler/persistence/MicroComponent | bmc.kepler.MicroComponent.Debug |
| 可观测配置 | bmc.kepler.persistence | /bmc/kepler/Dashboard | bmc.kepler.Dashboard.Observability* |
| 全局属性 | bmc.kepler.persistence | /bmc/kepler/Global | 由 global*.json 动态定义的 bmc.kepler.Global.* |
2. API 使用说明与示例
2.1 通用调用规则
2.1.1 服务与对象检查
busctl --user list | grep -F bmc.kepler.persistence
busctl --user tree bmc.kepler.persistence
busctl --user introspect bmc.kepler.persistence /bmc/kepler/persistence
busctl --user introspect bmc.kepler.persistence /bmc/kepler/Dashboard若产品把 persistence 合并到 framework.service,不要仅以 persistence.service 是否 active 判断组件状态;应同时检查 D-Bus 名称、对象树和 framework 日志。
2.1.2 Context 和调用者身份
- 主接口通过
register_method_with_sender获取真实 D-Bus sender,调用方不能用显式字符串伪造表属主。 - Debug、Reboot、ConfigManage 和 Dump 的显式首参数通常为
a{ss}Context。 - 测试示例使用最小 Context:
1 Initiator docs-persistence;真正北向调用还可能由框架注入 Requestor、Privilege、Auth 等字段。 - 表属主配置把组件短名扩展为
bmc.kepler.<component>;不匹配时抛出IncorrectSenderInfo。
2.1.3 D-Bus 参数记法
s/i/u/y/d/b:String、S32、U32、U8、Double、Boolean;ay:二进制数组。persistence 使用它承载经过框架序列化的数据值,不等同于可直接手写的字符串;a(say):由“属性名 + 二进制数组值”组成的结构数组;a{sa{say}}:字符串到“属性名 + 二进制数组值”字典的嵌套字典;a{ss}:字符串字典;as:字符串数组。
2.1.4 风险等级
| 等级 | 范围 | 要求 |
|---|---|---|
| 低 | Read、BatchRead、属性读取、introspect | 可在测试环境执行;避免高频遍历大表。 |
| 中 | Flush、Dashboard 属性写入、Dump | 先记录原值;Dump 目录应受控;关注阻塞与磁盘占用。 |
| 高 | Save、Debug.Save、Reboot、ConfigManage | 仅由业务框架或隔离测试执行;备份数据并准备恢复路径。 |
2.1.5 当前接口目录
| 组 | 方法/属性 |
|---|---|
| 主持久化接口 | BatchRead、Read、Save、Flush |
| Debug 接口 | Debug.Read、Debug.BatchRead、Debug.Save、Debug.Flush |
| Dashboard | Observability.Enabled、4 个 Traces 属性、2 个 Metrics 属性、2 个 Logs 属性 |
| Reboot | Reboot.Prepare、Reboot.Action、Reboot.Cancel |
| ConfigManage | ConfigManage.Backup、ConfigManage.Recover |
| 一键日志 | Debug.Dump |
2.2 BatchRead
功能说明
按表名批量读取远程持久化数据,同时返回当前有效记录和删除墓碑。PersistClient 启动恢复阶段优先使用该接口,避免逐表多次往返。
| 属性 | 内容 |
|---|---|
| 服务名 | bmc.kepler.persistence |
| 对象路径 | /bmc/kepler/persistence |
| 接口名 | bmc.kepler.persistence |
| D-Bus 签名 | as → a{sa{sa{sa{say}}}} |
| 权限 | 由主服务接口和 D-Bus sender 共同约束;表属主不匹配时拒绝 |
| 首发版本 | openUBMC 26.09 |
| 可用构建 | Release、Debug |
| 风险等级 | 低 |
| 废弃状态 | 正常可用 |
| 源码依据 | src/lualib/persistence_app.lua、include/persistence/persist_client_lib.lua |
参数说明
| 参数名 | 方向 | 类型 | 描述 | 取值范围 |
|---|---|---|---|---|
| Tables | 输入 | as | 待读取的远程持久化表名列表 | 每项必须是已知 ORM 表名;可为空数组 |
返回值与异常
| 返回值/异常 | 含义 | 触发条件 | 处理建议 |
|---|---|---|---|
| a{sa{sa{sa{say}}}} | 每张表包含 active_data 和 deleted_data,记录值为二进制数组序列化结果 | 正常完成 | 由 PersistClient 解码并合并,不要在 shell 中依赖内部二进制格式 |
| IncorrectSenderInfo | 调用者不是某张表的属主 | table_owner.json 对该表有限制且真实 sender 不匹配 | 由正确业务组件调用,或修正属主配置 |
| D-Bus 异常 | 服务未就绪或读取过程失败 | 组件启动窗口、总线或数据库异常 | PersistClient 当前最多重试 100 次;结合日志判断 |
应用场景
业务组件启动时一次恢复多张表;定位某组件预置数据为何没有被恢复;核对删除墓碑是否覆盖 CSR/MDS 预置记录。
限制条件
- 返回值是内部恢复协议,不是面向普通运维用户的稳定 JSON API。
- 会合并不同持久化后端中同一主键的字段;调用方不能假设字段只来自单个数据库。
- 读取大表会增加 D-Bus 消息和内存压力,应按组件实际表集合调用。
- 属主校验使用真实 D-Bus sender;显式的 app 名称不能绕过校验。
调试示例
busctl
busctl --user call bmc.kepler.persistence /bmc/kepler/persistence bmc.kepler.persistence BatchRead 'as' 2 t_demo t_demo_extra响应形态:
a{sa{sa{sa{say}}}} 2
"t_demo" ... "active_data" ... "deleted_data" ...
"t_demo_extra" ...ay 中是框架序列化值。人工判断重点是表名、主键和 active/deleted 两个分组;业务恢复应使用 PersistClient。
2.3 Read
功能说明
读取一张表的所有活动持久化记录。服务端会把 Temporary、Reset、Poweroff 和 Permanent 后端中同一主键的字段合并为完整记录。
| 属性 | 内容 |
|---|---|
| 服务名 | bmc.kepler.persistence |
| 对象路径 | /bmc/kepler/persistence |
| 接口名 | bmc.kepler.persistence |
| D-Bus 签名 | ss → a(sa{say}) |
| 权限 | 由主服务接口和 D-Bus sender 共同约束;表属主不匹配时拒绝 |
| 首发版本 | openUBMC 26.09 |
| 可用构建 | Release、Debug |
| 风险等级 | 低 |
| 废弃状态 | 正常可用 |
| 源码依据 | src/lualib/persistence_app.lua、include/persistence/persist_client_lib.lua |
参数说明
| 参数名 | 方向 | 类型 | 描述 | 取值范围 |
|---|---|---|---|---|
| TableName | 输入 | s | 待读取表名 | 已定义的远程持久化表 |
| AppName | 输入 | s | 调用方组件名称,主要用于统计/兼容 | 建议使用组件服务短名;不能替代真实 sender |
返回值与异常
| 返回值/异常 | 含义 | 触发条件 | 处理建议 |
|---|---|---|---|
| a(sa{say}) | 记录数组;每项包含拼接后的主键字符串及字段字典 | 正常完成 | 由 SDK 解码为 Lua 值 |
| IncorrectSenderInfo | 表属主校验失败 | 真实 sender 不在允许集合 | 由表属主组件调用 |
| 空数组 | 表不存在持久化记录或数据为空 | 首次启动、默认值未落盘或已删除 | 结合预置数据与日志判断,不等同于接口失败 |
应用场景
调试单表恢复;确认某字段是否已经落盘;核对同一主键在不同后端的字段合并结果。
限制条件
- 只返回活动记录,不单独返回 deleted_data;需要删除墓碑时使用 BatchRead。
- 第二个字符串不是授权凭据,真实访问控制仍取决于 D-Bus sender。
- 返回顺序未定义,不应据此比较版本或业务优先级。
调试示例
busctl
busctl --user call bmc.kepler.persistence /bmc/kepler/persistence bmc.kepler.persistence Read 'ss' t_demo persistence-doc响应形态:
a(sa{say}) <记录数> "Id:1" <字段数> "Id" <ay...> "Name" <ay...> ...输出为空时先确认该表是否只包含默认值。客户端会主动跳过“首次出现且全部为默认值”的记录。
2.4 Save
功能说明
提交一条插入、更新或删除事务。服务端按每个字段的 persist_type 把同一记录拆分到不同后端,并由事务调度器合并、限流和落盘。
| 属性 | 内容 |
|---|---|
| 服务名 | bmc.kepler.persistence |
| 对象路径 | /bmc/kepler/persistence |
| 接口名 | bmc.kepler.persistence |
| D-Bus 签名 | isa(say)a{sa{say}}s → void |
| 权限 | 真实 D-Bus sender 必须匹配 table_owner;通常仅供 PersistClient 调用 |
| 首发版本 | openUBMC 26.09 |
| 可用构建 | Release、Debug |
| 风险等级 | 高 |
| 废弃状态 | 正常可用 |
| 源码依据 | src/lualib/persistence_app.lua、src/lualib/persistence_transaction.lua、src/lualib/persistence_db_intf.lua |
参数说明
| 参数名 | 方向 | 类型 | 描述 | 取值范围 |
|---|---|---|---|---|
| Operation | 输入 | i | SQLite 操作码 | INSERT=18,UPDATE=23,DELETE=9 |
| TableName | 输入 | s | 目标表名 | 已定义并由调用组件拥有的远程表 |
| PrimaryKey | 输入 | a(say) | 主键字段和值数组 | 至少应包含完整主键;值由框架序列化为 ay |
| PersistParams | 输入 | a{sa{say}} | 字段到 {value, persist_type, critical...} 的映射 | persist_type 使用 protect_* 或 *_retain |
| AppName | 输入 | s | 统计中的组件名 | 使用实际组件名称 |
返回值与异常
| 返回值/异常 | 含义 | 触发条件 | 处理建议 |
|---|---|---|---|
| 无返回值 | 事务已进入服务端缓存或被当前策略忽略 | 正常返回 | 需要落盘同步点时随后调用 Flush |
| IncorrectSenderInfo | 表属主不匹配 | 真实 sender 不在 table_owner 允许集合 | 禁止伪造,修正组件/配置 |
| 静默丢弃并记错误日志 | 远程数据库已超限 | db_check 判定目标后端超过上限 | 处理容量告警后重新发起业务操作;不能只看 D-Bus 调用成功 |
| 日志中的 per_save failed | 数据库写入重试后仍失败 | 锁、I/O、数据库损坏或设备异常 | 收集主/备数据库状态和 framework 日志 |
应用场景
由 ORM hook 自动保存业务对象;为不同字段选择不同掉电等级;删除对象时记录墓碑;关键掉电字段同步备份。
限制条件
- 不建议人工构造
ay。其编码由 libmc4lua/sd-bus 框架负责,手写 busctl 参数很容易造成类型或端序错误。 - Save 正常返回只代表已接收/缓存;服务端后续提交失败需要通过日志、Read 和 Flush 验证。
- 数据库超限分支当前会记错误日志后直接返回,不抛 D-Bus 异常。自动化测试必须检查结果而不是只检查退出码。
- DELETE 遇到 Retain 字段时默认保留;只有上下文
delete_retain_data=true才会删除保留字段。 - 关键字段备份写失败时主数据库已成功写入,接口仍按成功处理并记录错误。
调试示例
推荐:通过 PersistClient/BasicClient 调试
local sqlite3 = require 'lsqlite3'
local per_client = require 'persistence.basic_client'
per_client:call(bus, 'Save', 'isa(say)a{sa{say}}s',
sqlite3.UPDATE,
't_demo',
{{'Id', 1}},
{
Name = {value = 'node-1', persist_type = 'protect_power_off'},
Count = {value = 7, persist_type = 'protect_reset'},
Token = {value = 'masked', persist_type = 'protect_power_off', critical = 1}
},
'demo')随后执行 Flush,再用 Read/BatchRead 核对。原始 busctl call Save 不作为公开可复制示例,因为 ay 是框架内部序列化数据。可先核对签名:
busctl --user introspect bmc.kepler.persistence /bmc/kepler/persistence bmc.kepler.persistence2.5 Flush
功能说明
强制服务端提交当前缓存事务,并等待当前提交完成。PersistClient.flush 还会先刷新本地 ORM hook,并等待客户端侧异步事务结束。
| 属性 | 内容 |
|---|---|
| 服务名 | bmc.kepler.persistence |
| 对象路径 | /bmc/kepler/persistence |
| 接口名 | bmc.kepler.persistence |
| D-Bus 签名 | s → void |
| 权限 | 主服务可调用;建议仅由业务组件在明确同步点使用 |
| 首发版本 | openUBMC 26.09 |
| 可用构建 | Release、Debug |
| 风险等级 | 中 |
| 废弃状态 | 正常可用 |
| 源码依据 | src/lualib/persistence_app.lua、src/lualib/persistence_task_schedule.lua、include/persistence/persist_client_lib.lua |
参数说明
| 参数名 | 方向 | 类型 | 描述 | 取值范围 |
|---|---|---|---|---|
| AppName | 输入 | s | 发起请求的组件名;当前服务端实现不使用其内容 | 非空组件名为宜 |
返回值与异常
| 返回值/异常 | 含义 | 触发条件 | 处理建议 |
|---|---|---|---|
| 无返回值 | 无待提交事务,或所有当前事务已完成 | 正常执行 | 继续业务流程 |
| 调用阻塞/超时 | 提交协程未唤醒或底层 I/O 长时间阻塞 | 数据库锁、设备异常、服务状态异常 | 检查事务/数据库日志,避免并发重复 Flush |
应用场景
复位前保证数据落盘;配置操作完成后建立确定同步点;测试中先 Save 再 Read 核验。
限制条件
- Flush 会牺牲异步合并带来的性能收益,不应对每次属性更新调用。
- 它只等待当前已进入客户端和服务端队列的事务,不替代业务层事务边界。
- 高并发 Flush 可能放大锁竞争;应由组件集中管理同步点。
调试示例
busctl
busctl --user call bmc.kepler.persistence /bmc/kepler/persistence bmc.kepler.persistence Flush 's' demo成功时无 D-Bus 返回正文。随后用 Read 或业务属性确认预期值。
2.6 Debug.Read
功能说明
Debug 构建中的单表读取接口。它绕过主接口的 table_owner 检查,用于维护者在隔离环境读取任意表。
| 属性 | 内容 |
|---|---|
| 服务名 | bmc.kepler.persistence |
| 对象路径 | /bmc/kepler/Debug/Persistence |
| 接口名 | bmc.kepler.Persistence |
| D-Bus 签名 | a{ss}ss → a(sa{say}) |
| 权限 | MDS 标注 ReadOnly;仅 Debug 构建注册 |
| 首发版本 | openUBMC 26.09 |
| 可用构建 | 仅 Debug/非 Release 构建 |
| 风险等级 | 中 |
| 废弃状态 | 正常可用 |
| 源码依据 | src/lualib/persistence_app.lua:init_debug_methods、mds/debug/model.json |
参数说明
| 参数名 | 方向 | 类型 | 描述 | 取值范围 |
|---|---|---|---|---|
| Context | 输入 | a{ss} | 调试调用上下文 | 至少保留可审计 Initiator |
| TableName | 输入 | s | 目标表名 | 任意已存在/已知表 |
| AppName | 输入 | s | 统计组件名占位 | 非授权字段 |
返回值与异常
| 返回值/异常 | 含义 | 触发条件 | 处理建议 |
|---|---|---|---|
| a(sa{say}) | 与主 Read 相同的活动记录数组 | 正常完成 | 按内部序列化格式解码 |
| D-Bus 异常 | Debug 对象未注册 | Release 构建或对象上树失败 | 不要在生产镜像依赖 Debug API |
应用场景
维护者在无法使用业务 sender 的隔离调试镜像中读取持久化记录。
限制条件
- 绕过表属主校验,数据可见范围更大,不能作为生产业务接口。
- MDS 权限标记为 ReadOnly 不代表返回数据不敏感;Dump 的脱敏规则不会自动应用到 Read。
- Release 构建不会注册该对象。
调试示例
busctl(仅 Debug 镜像)
busctl --user call bmc.kepler.persistence /bmc/kepler/Debug/Persistence bmc.kepler.Persistence Read 'a{ss}ss' 1 Initiator docs-persistence t_demo docs-persistence响应结构与主 Read 相同。调试完成后清理终端记录和导出文件。
2.7 Debug.BatchRead
功能说明
Debug 构建中的批量读取接口,绕过 table_owner 检查并返回活动数据和删除墓碑。
| 属性 | 内容 |
|---|---|
| 服务名 | bmc.kepler.persistence |
| 对象路径 | /bmc/kepler/Debug/Persistence |
| 接口名 | bmc.kepler.Persistence |
| D-Bus 签名 | a{ss}as → a{sa{sa{sa{say}}}} |
| 权限 | MDS 标注 ReadOnly;仅 Debug 构建注册 |
| 首发版本 | openUBMC 26.09 |
| 可用构建 | 仅 Debug/非 Release 构建 |
| 风险等级 | 中 |
| 废弃状态 | 正常可用 |
| 源码依据 | src/lualib/persistence_app.lua:init_debug_methods |
参数说明
| 参数名 | 方向 | 类型 | 描述 | 取值范围 |
|---|---|---|---|---|
| Context | 输入 | a{ss} | 调试上下文 | 建议包含 Initiator |
| Tables | 输入 | as | 表名列表 | 控制表数量,避免一次读取全部业务数据 |
返回值与异常
| 返回值/异常 | 含义 | 触发条件 | 处理建议 |
|---|---|---|---|
| 嵌套字典 | 每表 active_data/deleted_data | 正常完成 | 仅在受控环境解析 |
| D-Bus 异常 | 对象不存在或读取失败 | Release 构建、服务异常 | 回到主接口或 Debug 镜像 |
应用场景
一次核对多个相关表的恢复数据和墓碑;排查 CSR 预置对象为何被删除。
限制条件
- 绕过属主校验,禁止作为普通组件依赖。
- 返回可能包含敏感原值;不要把原始响应直接附到公开问题单。
- 大批量读取会增加内存和 D-Bus 消息压力。
调试示例
busctl(仅 Debug 镜像)
busctl --user call bmc.kepler.persistence /bmc/kepler/Debug/Persistence bmc.kepler.Persistence BatchRead 'a{ss}as' 1 Initiator docs-persistence 2 t_demo t_demo_extra响应结构与主 BatchRead 相同。
2.8 Debug.Save
功能说明
Debug 构建中的写入接口。它通过 Debug 对象暴露 Save,但最终仍进入主 per_save 流程;源码处理函数接收真实 sender,并执行 table_owner 校验。
| 属性 | 内容 |
|---|---|
| 服务名 | bmc.kepler.persistence |
| 对象路径 | /bmc/kepler/Debug/Persistence |
| 接口名 | bmc.kepler.Persistence |
| D-Bus 签名 | a{ss}isa(say)a{sa{say}}s → void |
| 权限 | MDS 标注 ReadOnly,但方法实际可修改数据;仅 Debug 构建注册 |
| 首发版本 | openUBMC 26.09 |
| 可用构建 | 仅 Debug/非 Release 构建 |
| 风险等级 | 高 |
| 废弃状态 | 正常可用 |
| 源码依据 | src/lualib/persistence_app.lua:init_debug_methods |
参数说明
| 参数名 | 方向 | 类型 | 描述 | 取值范围 |
|---|---|---|---|---|
| Context | 输入 | a{ss} | 调试上下文 | 必须可审计 |
| Operation | 输入 | i | 操作码 | 18/23/9 |
| TableName | 输入 | s | 表名 | 受 table_owner 约束 |
| PrimaryKey | 输入 | a(say) | 主键 | 完整主键 |
| PersistParams | 输入 | a{sa{say}} | 持久化字段 | 合法 protect_* 类型 |
| AppName | 输入 | s | 组件名 | 实际组件名称 |
返回值与异常
| 返回值/异常 | 含义 | 触发条件 | 处理建议 |
|---|---|---|---|
| 无返回值 | 进入缓存或被策略丢弃 | 正常返回 | 必须 Flush+Read 验证 |
| IncorrectSenderInfo | 真实 sender 不是表属主 | 属主限制生效 | 由正确服务调用 |
| 日志错误 | 数据库超限/写入失败 | 容量或 I/O 异常 | 不要只看 D-Bus 成功 |
应用场景
维护者在 Debug 镜像复现保存路径、数据类型和事务合并问题。
限制条件
- 接口的 MDS 权限元数据为 ReadOnly,但方法具有写副作用;正式文档按实际行为将其视为高风险接口。
- 不能绕过 table_owner;Debug.Read 与 Debug.BatchRead 才明确绕过检查。
- 禁止在生产设备构造任意持久化记录。
- 原始 ay 仍应由框架客户端编码。
调试示例
Lua 调试(仅 Debug 镜像)
local context = require 'mc.context'
local sqlite3 = require 'lsqlite3'
local ctx = context.new('docs', 'Admin', '127.0.0.1')
bus:call('bmc.kepler.persistence',
'/bmc/kepler/Debug/Persistence',
'bmc.kepler.Persistence',
'Save', 'a{ss}isa(say)a{sa{say}}s',
ctx, sqlite3.UPDATE, 't_demo', {{'Id', 1}},
{Name = {value = 'debug', persist_type = 'protect_power_off'}},
'demo')随后调用 Debug.Flush,并用 Debug.Read 读取。
2.9 Debug.Flush
功能说明
Debug 构建中的显式落盘接口,行为与主 Flush 相同,只是多一个 Context 参数。
| 属性 | 内容 |
|---|---|
| 服务名 | bmc.kepler.persistence |
| 对象路径 | /bmc/kepler/Debug/Persistence |
| 接口名 | bmc.kepler.Persistence |
| D-Bus 签名 | a{ss}s → void |
| 权限 | MDS 标注 ReadOnly;仅 Debug 构建注册 |
| 首发版本 | openUBMC 26.09 |
| 可用构建 | 仅 Debug/非 Release 构建 |
| 风险等级 | 中 |
| 废弃状态 | 正常可用 |
| 源码依据 | src/lualib/persistence_app.lua:init_debug_methods |
参数说明
| 参数名 | 方向 | 类型 | 描述 | 取值范围 |
|---|---|---|---|---|
| Context | 输入 | a{ss} | 调试上下文 | 建议包含 Initiator |
| AppName | 输入 | s | 组件名占位 | 非空字符串 |
返回值与异常
| 返回值/异常 | 含义 | 触发条件 | 处理建议 |
|---|---|---|---|
| 无返回值 | 当前缓存事务完成或无事务 | 正常 | 继续验证 |
| 阻塞/异常 | 数据库或调度异常 | I/O、锁、服务退出 | 检查日志 |
应用场景
与 Debug.Save 配套建立同步点;复现普通 Flush 在 Debug 镜像中的行为。
限制条件
- 仅 Debug 构建。
- 不要在高频循环中调用。
- 成功返回仍应通过读取或业务状态核验。
调试示例
busctl(仅 Debug 镜像)
busctl --user call bmc.kepler.persistence /bmc/kepler/Debug/Persistence bmc.kepler.Persistence Flush 'a{ss}s' 1 Initiator docs-persistence demo成功时无正文。
2.10 Dashboard.Observability.Enabled
功能说明
控制系统可观测功能总开关。属性变化写入 persistence 自身的本地 Poweroff 数据库。
| 属性 | 内容 |
|---|---|
| 服务名 | bmc.kepler.persistence |
| 对象路径 | /bmc/kepler/Dashboard |
| 接口名 | bmc.kepler.Dashboard.Observability |
| D-Bus 签名 | 属性 Enabled:b(read/write) |
| 权限 | 读取 ReadOnly;写入 DiagnoseMgmt |
| 首发版本 | openUBMC 26.09 |
| 可用构建 | Release、Debug(对象是否裁剪需目标镜像确认) |
| 风险等级 | 中 |
| 废弃状态 | 正常可用 |
| 源码依据 | mds/model.json、gen/class/model.lua、src/lualib/dashboard.lua |
参数说明
| 参数名 | 方向 | 类型 | 描述 | 取值范围 |
|---|---|---|---|---|
| Value | 输入/输出 | b | Enabled 属性值 | Boolean;生成模型默认 false |
返回值与异常
| 返回值/异常 | 含义 | 触发条件 | 处理建议 |
|---|---|---|---|
| 属性值 | 读取成功 | 对象已上树 | 记录当前值 |
| Properties.Set 成功 | 值写入对象并通过本地 ORM 持久化 | 权限和类型合法 | 重读确认 |
| 权限/类型异常 | 调用者无 DiagnoseMgmt 或类型不匹配 | 写操作被拒绝 | 使用授权账号和正确签名 |
应用场景
配置可观测数据的采集和导出策略;验证配置是否在复位后恢复。
限制条件
- 该属性只提供共享配置,不保证所有采集客户端已正确订阅。
- 写入后应验证实际日志/指标/追踪客户端是否停止或恢复上报。
- 本地表为 PoweroffPer,恢复出厂后的保留语义以产品流程为准。
调试示例
busctl
busctl --user get-property bmc.kepler.persistence /bmc/kepler/Dashboard bmc.kepler.Dashboard.Observability Enabled
busctl --user set-property bmc.kepler.persistence /bmc/kepler/Dashboard bmc.kepler.Dashboard.Observability Enabled 'b' true读取响应形态:
b true写入前记录原值,验证完成后恢复。
2.11 Dashboard.Traces.SamplingRate
功能说明
配置追踪采样率。当前 persistence 只负责存储和上树,具体数值语义由追踪消费者解释。
| 属性 | 内容 |
|---|---|
| 服务名 | bmc.kepler.persistence |
| 对象路径 | /bmc/kepler/Dashboard |
| 接口名 | bmc.kepler.Dashboard.Observability.Traces |
| D-Bus 签名 | 属性 SamplingRate:d(read/write) |
| 权限 | 读取 ReadOnly;写入 DiagnoseMgmt |
| 首发版本 | openUBMC 26.09 |
| 可用构建 | Release、Debug(对象是否裁剪需目标镜像确认) |
| 风险等级 | 中 |
| 废弃状态 | 正常可用 |
| 源码依据 | mds/model.json、gen/class/model.lua、src/lualib/dashboard.lua |
参数说明
| 参数名 | 方向 | 类型 | 描述 | 取值范围 |
|---|---|---|---|---|
| Value | 输入/输出 | d | SamplingRate 属性值 | Double;生成类型默认值可表现为 0,源码未定义最小值、最大值或比例语义 |
返回值与异常
| 返回值/异常 | 含义 | 触发条件 | 处理建议 |
|---|---|---|---|
| 属性值 | 读取成功 | 对象已上树 | 记录当前值 |
| Properties.Set 成功 | 值写入对象并通过本地 ORM 持久化 | 权限和类型合法 | 重读确认 |
| 权限/类型异常 | 调用者无 DiagnoseMgmt 或类型不匹配 | 写操作被拒绝 | 使用授权账号和正确签名 |
应用场景
配置可观测数据的采集和导出策略;验证配置是否在复位后恢复。
限制条件
- 当前生成校验仅检查 Double 类型,没有范围约束;不要自行假设必须在 0~1。
- 需与使用该属性的可观测客户端约定合法区间。
调试示例
busctl
busctl --user get-property bmc.kepler.persistence /bmc/kepler/Dashboard bmc.kepler.Dashboard.Observability.Traces SamplingRate
busctl --user set-property bmc.kepler.persistence /bmc/kepler/Dashboard bmc.kepler.Dashboard.Observability.Traces SamplingRate 'd' 0.5读取响应形态:
d 0.5写入前记录原值,验证完成后恢复。
2.12 Dashboard.Traces.SamplingPolicy
功能说明
配置追踪采样策略编号。模型默认值为 1,但当前源码没有枚举表。
| 属性 | 内容 |
|---|---|
| 服务名 | bmc.kepler.persistence |
| 对象路径 | /bmc/kepler/Dashboard |
| 接口名 | bmc.kepler.Dashboard.Observability.Traces |
| D-Bus 签名 | 属性 SamplingPolicy:y(read/write) |
| 权限 | 读取 ReadOnly;写入 DiagnoseMgmt |
| 首发版本 | openUBMC 26.09 |
| 可用构建 | Release、Debug(对象是否裁剪需目标镜像确认) |
| 风险等级 | 中 |
| 废弃状态 | 正常可用 |
| 源码依据 | mds/model.json、gen/class/model.lua、src/lualib/dashboard.lua |
参数说明
| 参数名 | 方向 | 类型 | 描述 | 取值范围 |
|---|---|---|---|---|
| Value | 输入/输出 | y | SamplingPolicy 属性值 | U8;模型默认 1 |
返回值与异常
| 返回值/异常 | 含义 | 触发条件 | 处理建议 |
|---|---|---|---|
| 属性值 | 读取成功 | 对象已上树 | 记录当前值 |
| Properties.Set 成功 | 值写入对象并通过本地 ORM 持久化 | 权限和类型合法 | 重读确认 |
| 权限/类型异常 | 调用者无 DiagnoseMgmt 或类型不匹配 | 写操作被拒绝 | 使用授权账号和正确签名 |
应用场景
配置可观测数据的采集和导出策略;验证配置是否在复位后恢复。
限制条件
- 当前源码只校验 U8 类型,不定义 1、2 等编号的业务含义。
dashboard.lua构造函数没有显式从本地数据库复制SamplingPolicy,因此复位后的恢复行为必须在目标 1.130.9 镜像验证。- 不要把未确认的策略编号写入生产环境。
调试示例
busctl
busctl --user get-property bmc.kepler.persistence /bmc/kepler/Dashboard bmc.kepler.Dashboard.Observability.Traces SamplingPolicy
busctl --user set-property bmc.kepler.persistence /bmc/kepler/Dashboard bmc.kepler.Dashboard.Observability.Traces SamplingPolicy 'y' 1读取响应形态:
y 1写入前记录原值,验证完成后恢复。
2.13 Dashboard.Traces.SamplingLevel
功能说明
配置追踪采样级别编号。模型默认值为 2。
| 属性 | 内容 |
|---|---|
| 服务名 | bmc.kepler.persistence |
| 对象路径 | /bmc/kepler/Dashboard |
| 接口名 | bmc.kepler.Dashboard.Observability.Traces |
| D-Bus 签名 | 属性 SamplingLevel:y(read/write) |
| 权限 | 读取 ReadOnly;写入 DiagnoseMgmt |
| 首发版本 | openUBMC 26.09 |
| 可用构建 | Release、Debug(对象是否裁剪需目标镜像确认) |
| 风险等级 | 中 |
| 废弃状态 | 正常可用 |
| 源码依据 | mds/model.json、gen/class/model.lua、src/lualib/dashboard.lua |
参数说明
| 参数名 | 方向 | 类型 | 描述 | 取值范围 |
|---|---|---|---|---|
| Value | 输入/输出 | y | SamplingLevel 属性值 | U8;模型默认 2 |
返回值与异常
| 返回值/异常 | 含义 | 触发条件 | 处理建议 |
|---|---|---|---|
| 属性值 | 读取成功 | 对象已上树 | 记录当前值 |
| Properties.Set 成功 | 值写入对象并通过本地 ORM 持久化 | 权限和类型合法 | 重读确认 |
| 权限/类型异常 | 调用者无 DiagnoseMgmt 或类型不匹配 | 写操作被拒绝 | 使用授权账号和正确签名 |
应用场景
配置可观测数据的采集和导出策略;验证配置是否在复位后恢复。
限制条件
- 当前源码没有给出枚举含义或范围约束。
- 属性持久化成功不代表消费者支持该级别,需联动验证。
调试示例
busctl
busctl --user get-property bmc.kepler.persistence /bmc/kepler/Dashboard bmc.kepler.Dashboard.Observability.Traces SamplingLevel
busctl --user set-property bmc.kepler.persistence /bmc/kepler/Dashboard bmc.kepler.Dashboard.Observability.Traces SamplingLevel 'y' 2读取响应形态:
y 2写入前记录原值,验证完成后恢复。
2.14 Dashboard.Traces.ExportIntervalSeconds
功能说明
配置追踪数据导出周期。
| 属性 | 内容 |
|---|---|
| 服务名 | bmc.kepler.persistence |
| 对象路径 | /bmc/kepler/Dashboard |
| 接口名 | bmc.kepler.Dashboard.Observability.Traces |
| D-Bus 签名 | 属性 ExportIntervalSeconds:u(read/write) |
| 权限 | 读取 ReadOnly;写入 DiagnoseMgmt |
| 首发版本 | openUBMC 26.09 |
| 可用构建 | Release、Debug(对象是否裁剪需目标镜像确认) |
| 风险等级 | 中 |
| 废弃状态 | 正常可用 |
| 源码依据 | mds/model.json、gen/class/model.lua、src/lualib/dashboard.lua |
参数说明
| 参数名 | 方向 | 类型 | 描述 | 取值范围 |
|---|---|---|---|---|
| Value | 输入/输出 | u | ExportIntervalSeconds 属性值 | U32;dashboard.lua 无记录时运行时回退为 20 秒,但生成模型元数据仍声明 5 秒 |
返回值与异常
| 返回值/异常 | 含义 | 触发条件 | 处理建议 |
|---|---|---|---|
| 属性值 | 读取成功 | 对象已上树 | 记录当前值 |
| Properties.Set 成功 | 值写入对象并通过本地 ORM 持久化 | 权限和类型合法 | 重读确认 |
| 权限/类型异常 | 调用者无 DiagnoseMgmt 或类型不匹配 | 写操作被拒绝 | 使用授权账号和正确签名 |
应用场景
配置可观测数据的采集和导出策略;验证配置是否在复位后恢复。
限制条件
- 当前源码存在 20 秒与 5 秒两套默认值证据;本文按运行时构造逻辑说明首次上树值,并把差异列为 DE 确认项。
- 没有最小/最大值约束;过小周期可能增加 CPU、网络和日志压力。
调试示例
busctl
busctl --user get-property bmc.kepler.persistence /bmc/kepler/Dashboard bmc.kepler.Dashboard.Observability.Traces ExportIntervalSeconds
busctl --user set-property bmc.kepler.persistence /bmc/kepler/Dashboard bmc.kepler.Dashboard.Observability.Traces ExportIntervalSeconds 'u' 20读取响应形态:
u 20写入前记录原值,验证完成后恢复。
2.15 Dashboard.Metrics.ExportIntervalSeconds
功能说明
配置指标数据导出周期。
| 属性 | 内容 |
|---|---|
| 服务名 | bmc.kepler.persistence |
| 对象路径 | /bmc/kepler/Dashboard |
| 接口名 | bmc.kepler.Dashboard.Observability.Metrics |
| D-Bus 签名 | 属性 ExportIntervalSeconds:u(read/write) |
| 权限 | 读取 ReadOnly;写入 DiagnoseMgmt |
| 首发版本 | openUBMC 26.09 |
| 可用构建 | Release、Debug(对象是否裁剪需目标镜像确认) |
| 风险等级 | 中 |
| 废弃状态 | 正常可用 |
| 源码依据 | mds/model.json、gen/class/model.lua、src/lualib/dashboard.lua |
参数说明
| 参数名 | 方向 | 类型 | 描述 | 取值范围 |
|---|---|---|---|---|
| Value | 输入/输出 | u | ExportIntervalSeconds 属性值 | U32;运行时回退为 60 秒,生成模型元数据声明 30 秒 |
返回值与异常
| 返回值/异常 | 含义 | 触发条件 | 处理建议 |
|---|---|---|---|
| 属性值 | 读取成功 | 对象已上树 | 记录当前值 |
| Properties.Set 成功 | 值写入对象并通过本地 ORM 持久化 | 权限和类型合法 | 重读确认 |
| 权限/类型异常 | 调用者无 DiagnoseMgmt 或类型不匹配 | 写操作被拒绝 | 使用授权账号和正确签名 |
应用场景
配置可观测数据的采集和导出策略;验证配置是否在复位后恢复。
限制条件
- 当前源码存在 60 秒与 30 秒默认值差异,正式契约需维护者确认。
- 过小周期会增加指标计算和上传压力。
调试示例
busctl
busctl --user get-property bmc.kepler.persistence /bmc/kepler/Dashboard bmc.kepler.Dashboard.Observability.Metrics ExportIntervalSeconds
busctl --user set-property bmc.kepler.persistence /bmc/kepler/Dashboard bmc.kepler.Dashboard.Observability.Metrics ExportIntervalSeconds 'u' 60读取响应形态:
u 60写入前记录原值,验证完成后恢复。
2.16 Dashboard.Metrics.ActivatedMetrics
功能说明
配置需要启用的指标名称集合。persistence 不校验这些名称是否被采集端实现。
| 属性 | 内容 |
|---|---|
| 服务名 | bmc.kepler.persistence |
| 对象路径 | /bmc/kepler/Dashboard |
| 接口名 | bmc.kepler.Dashboard.Observability.Metrics |
| D-Bus 签名 | 属性 ActivatedMetrics:as(read/write) |
| 权限 | 读取 ReadOnly;写入 DiagnoseMgmt |
| 首发版本 | openUBMC 26.09 |
| 可用构建 | Release、Debug(对象是否裁剪需目标镜像确认) |
| 风险等级 | 中 |
| 废弃状态 | 正常可用 |
| 源码依据 | mds/model.json、gen/class/model.lua、src/lualib/dashboard.lua |
参数说明
| 参数名 | 方向 | 类型 | 描述 | 取值范围 |
|---|---|---|---|---|
| Value | 输入/输出 | as | ActivatedMetrics 属性值 | String[];生成默认值为空数组 |
返回值与异常
| 返回值/异常 | 含义 | 触发条件 | 处理建议 |
|---|---|---|---|
| 属性值 | 读取成功 | 对象已上树 | 记录当前值 |
| Properties.Set 成功 | 值写入对象并通过本地 ORM 持久化 | 权限和类型合法 | 重读确认 |
| 权限/类型异常 | 调用者无 DiagnoseMgmt 或类型不匹配 | 写操作被拒绝 | 使用授权账号和正确签名 |
应用场景
配置可观测数据的采集和导出策略;验证配置是否在复位后恢复。
限制条件
- 名称有效性由指标消费者决定。
- 列表过大可能增加采集开销。
- 设置空数组的实际含义应与消费者确认,不能默认等同于“全部启用”或“全部关闭”。
调试示例
busctl
busctl --user get-property bmc.kepler.persistence /bmc/kepler/Dashboard bmc.kepler.Dashboard.Observability.Metrics ActivatedMetrics
busctl --user set-property bmc.kepler.persistence /bmc/kepler/Dashboard bmc.kepler.Dashboard.Observability.Metrics ActivatedMetrics 'as' 2 cpu.usage memory.usage读取响应形态:
as 2 "cpu.usage" "memory.usage"写入前记录原值,验证完成后恢复。
2.17 Dashboard.Logs.Enabled
功能说明
控制日志可观测采集/上报开关。
| 属性 | 内容 |
|---|---|
| 服务名 | bmc.kepler.persistence |
| 对象路径 | /bmc/kepler/Dashboard |
| 接口名 | bmc.kepler.Dashboard.Observability.Logs |
| D-Bus 签名 | 属性 Enabled:b(read/write) |
| 权限 | 读取 ReadOnly;写入 DiagnoseMgmt |
| 首发版本 | openUBMC 26.09 |
| 可用构建 | Release、Debug(对象是否裁剪需目标镜像确认) |
| 风险等级 | 中 |
| 废弃状态 | 正常可用 |
| 源码依据 | mds/model.json、gen/class/model.lua、src/lualib/dashboard.lua |
参数说明
| 参数名 | 方向 | 类型 | 描述 | 取值范围 |
|---|---|---|---|---|
| Value | 输入/输出 | b | Enabled 属性值 | Boolean;生成默认值 false |
返回值与异常
| 返回值/异常 | 含义 | 触发条件 | 处理建议 |
|---|---|---|---|
| 属性值 | 读取成功 | 对象已上树 | 记录当前值 |
| Properties.Set 成功 | 值写入对象并通过本地 ORM 持久化 | 权限和类型合法 | 重读确认 |
| 权限/类型异常 | 调用者无 DiagnoseMgmt 或类型不匹配 | 写操作被拒绝 | 使用授权账号和正确签名 |
应用场景
配置可观测数据的采集和导出策略;验证配置是否在复位后恢复。
限制条件
- 该开关不等同于关闭组件本地运行日志,只影响使用该共享配置的可观测客户端。
- 写入后要验证消费者是否已订阅属性变化。
调试示例
busctl
busctl --user get-property bmc.kepler.persistence /bmc/kepler/Dashboard bmc.kepler.Dashboard.Observability.Logs Enabled
busctl --user set-property bmc.kepler.persistence /bmc/kepler/Dashboard bmc.kepler.Dashboard.Observability.Logs Enabled 'b' true读取响应形态:
b true写入前记录原值,验证完成后恢复。
2.18 Dashboard.Logs.ExportIntervalSeconds
功能说明
配置可观测日志批量导出周期。
| 属性 | 内容 |
|---|---|
| 服务名 | bmc.kepler.persistence |
| 对象路径 | /bmc/kepler/Dashboard |
| 接口名 | bmc.kepler.Dashboard.Observability.Logs |
| D-Bus 签名 | 属性 ExportIntervalSeconds:u(read/write) |
| 权限 | 读取 ReadOnly;写入 DiagnoseMgmt |
| 首发版本 | openUBMC 26.09 |
| 可用构建 | Release、Debug(对象是否裁剪需目标镜像确认) |
| 风险等级 | 中 |
| 废弃状态 | 正常可用 |
| 源码依据 | mds/model.json、gen/class/model.lua、src/lualib/dashboard.lua |
参数说明
| 参数名 | 方向 | 类型 | 描述 | 取值范围 |
|---|---|---|---|---|
| Value | 输入/输出 | u | ExportIntervalSeconds 属性值 | U32;运行时回退为 20 秒,生成模型元数据声明 5 秒 |
返回值与异常
| 返回值/异常 | 含义 | 触发条件 | 处理建议 |
|---|---|---|---|
| 属性值 | 读取成功 | 对象已上树 | 记录当前值 |
| Properties.Set 成功 | 值写入对象并通过本地 ORM 持久化 | 权限和类型合法 | 重读确认 |
| 权限/类型异常 | 调用者无 DiagnoseMgmt 或类型不匹配 | 写操作被拒绝 | 使用授权账号和正确签名 |
应用场景
配置可观测数据的采集和导出策略;验证配置是否在复位后恢复。
限制条件
- 当前源码存在 20 秒与 5 秒默认值差异,需在目标镜像和接口契约中确认。
- 过小周期可能提高 CPU、网络和服务端压力。
调试示例
busctl
busctl --user get-property bmc.kepler.persistence /bmc/kepler/Dashboard bmc.kepler.Dashboard.Observability.Logs ExportIntervalSeconds
busctl --user set-property bmc.kepler.persistence /bmc/kepler/Dashboard bmc.kepler.Dashboard.Observability.Logs ExportIntervalSeconds 'u' 20读取响应形态:
u 20写入前记录原值,验证完成后恢复。
2.19 Reboot.Prepare
功能说明
由微组件复位框架在平滑复位 Prepare 阶段调用。当前 persistence 只记录“无需额外准备”,并返回 0。
| 属性 | 内容 |
|---|---|
| 服务名 | bmc.kepler.persistence |
| 对象路径 | /bmc/kepler/persistence/MicroComponent |
| 接口名 | bmc.kepler.MicroComponent.Reboot |
| D-Bus 签名 | a{ss} → i |
| 权限 | 由 MicroComponent 框架定义;仅系统复位编排者调用 |
| 首发版本 | openUBMC 26.09 |
| 可用构建 | Release、Debug |
| 风险等级 | 高 |
| 废弃状态 | 正常可用 |
| 源码依据 | src/lualib/persistence_app.lua:on_reboot_prepare、集成测试 test_persistence.lua |
参数说明
| 参数名 | 方向 | 类型 | 描述 | 取值范围 |
|---|---|---|---|---|
| Context | 输入 | a{ss} | 复位上下文 | 由框架生成;可含 Requestor |
返回值与异常
| 返回值/异常 | 含义 | 触发条件 | 处理建议 |
|---|---|---|---|
| 0 | Prepare 完成 | 当前实现无额外动作 | 进入后续复位阶段 |
| D-Bus 异常 | 服务或框架对象异常 | 对象未上树、总线异常 | 终止复位并收集日志 |
应用场景
系统平滑复位编排,不是普通业务调用。
限制条件
- 直接调用不会提交事务;真正的数据收尾发生在 Action。
- 接口返回 0 不代表所有业务组件都已完成保存。
- 仅在隔离测试机或系统复位框架中调用。
调试示例
busctl(仅隔离测试)
busctl --user call bmc.kepler.persistence /bmc/kepler/persistence/MicroComponent bmc.kepler.MicroComponent.Reboot Prepare 'a{ss}' 1 Initiator docs-persistence预期响应:
i 02.20 Reboot.Action
功能说明
在平滑复位 Action 阶段执行持久化收尾:等待 5 秒供业务组件同步数据,触发强制提交;当 Requestor 为 bmc.kepler.fructrl 时备份 Poweroff 数据库;把 Poweroff journal 切换为 DELETE;等待提交标志并关闭三个 SQLite 数据库。
| 属性 | 内容 |
|---|---|
| 服务名 | bmc.kepler.persistence |
| 对象路径 | /bmc/kepler/persistence/MicroComponent |
| 接口名 | bmc.kepler.MicroComponent.Reboot |
| D-Bus 签名 | a{ss} → i |
| 权限 | 由 MicroComponent 框架定义;仅系统复位编排者调用 |
| 首发版本 | openUBMC 26.09 |
| 可用构建 | Release、Debug |
| 风险等级 | 高 |
| 废弃状态 | 正常可用 |
| 源码依据 | src/lualib/persistence_app.lua:on_reboot_action |
参数说明
| 参数名 | 方向 | 类型 | 描述 | 取值范围 |
|---|---|---|---|---|
| Context | 输入 | a{ss} | 复位上下文;Requestor 影响是否执行 Poweroff 备份 | 系统生成;AC 场景源码识别 bmc.kepler.fructrl |
返回值与异常
| 返回值/异常 | 含义 | 触发条件 | 处理建议 |
|---|---|---|---|
| 0 | Action 流程结束 | 无论 10 次检查内是否看到提交标志,当前实现最终都返回 0 | 必须结合日志确认事务和备份结果 |
| D-Bus/进程异常 | 执行中服务退出或对象失效 | I/O、数据库或框架异常 | 停止复位链路并保留现场 |
应用场景
系统平滑复位、AC 掉电准备。
限制条件
- ⚠️ 直接调用会关闭 persistence 的数据库句柄,可能使后续写入无法落盘;仅在隔离测试机和真实复位编排中执行。
- 源码最多等待 10 次、每次 0.2 秒检查强制提交标志;即使未观察到标志也会关闭数据库并返回 0。
- Requestor 字符串影响是否触发备份,不能由普通调用者伪造。
- 调用后若复位被取消,框架必须调用 Cancel 重新打开数据库。
调试示例
验证建议
不要在仍需继续运行的生产 BMC 手工执行。隔离环境中由复位测试框架调用,并观察:
finish force commit transactions before reboot
persistence has finish action for reboot <n>
persistence has closed db and backup_db集成测试使用 a{ss} Context 并断言返回 i 0。
2.21 Reboot.Cancel
功能说明
在复位流程取消时重新打开 Poweroff、Reset、Temporary 主数据库和 Poweroff 备份数据库,并清除强制提交完成标志。
| 属性 | 内容 |
|---|---|
| 服务名 | bmc.kepler.persistence |
| 对象路径 | /bmc/kepler/persistence/MicroComponent |
| 接口名 | bmc.kepler.MicroComponent.Reboot |
| D-Bus 签名 | a{ss} → void(按框架回调形态推断,目标 introspect 需确认) |
| 权限 | 由 MicroComponent 框架定义 |
| 首发版本 | openUBMC 26.09 |
| 可用构建 | Release、Debug |
| 风险等级 | 高 |
| 废弃状态 | 正常可用 |
| 源码依据 | src/lualib/persistence_app.lua:on_reboot_cancel;接口签名由外部 libmc4lua 框架提供 |
参数说明
| 参数名 | 方向 | 类型 | 描述 | 取值范围 |
|---|---|---|---|---|
| Context | 输入 | a{ss} | 复位取消上下文 | 由框架生成 |
返回值与异常
| 返回值/异常 | 含义 | 触发条件 | 处理建议 |
|---|---|---|---|
| 无返回值 | 数据库重新打开并重置状态 | 正常 | 恢复业务写入 |
| 日志错误 | 主/备数据库重新打开失败 | 文件、权限、数据库损坏 | 不要继续业务,检查数据库状态 |
应用场景
Prepare/Action 之后系统决定取消复位时恢复 persistence 服务。
限制条件
- 必须与 Action 的关闭动作成对使用。
- 当前源码没有显式返回码;是否完全恢复要通过日志、Read/Save/Flush 验证。
- 目标镜像需用
busctl introspect确认框架生成的最终签名。
调试示例
目标镜像确认
busctl --user introspect bmc.kepler.persistence /bmc/kepler/persistence/MicroComponent bmc.kepler.MicroComponent.Reboot由系统复位测试触发 Cancel,预期日志:
persistence cancel reboot and reopen db and backup_db2.22 ConfigManage.Backup
功能说明
把制造默认配置/还原点所需的持久化数据库复制到调用方指定目录。当前复制 Reset 主库、Poweroff 主库、Poweroff 备库和 persistence 本地数据库。
| 属性 | 内容 |
|---|---|
| 服务名 | bmc.kepler.persistence |
| 对象路径 | /bmc/kepler/persistence/MicroComponent |
| 接口名 | bmc.kepler.MicroComponent.ConfigManage |
| D-Bus 签名 | a{ss}s → void(框架方法;源码回调内部返回文件列表) |
| 权限 | 由 ConfigManage 框架定义;仅配置管理流程调用 |
| 首发版本 | openUBMC 26.09 |
| 可用构建 | Release、Debug |
| 风险等级 | 高 |
| 废弃状态 | 正常可用 |
| 源码依据 | src/lualib/persistence_config_manage.lua:backup_cb、集成测试 |
参数说明
| 参数名 | 方向 | 类型 | 描述 | 取值范围 |
|---|---|---|---|---|
| Context | 输入 | a{ss} | 操作上下文,用于操作日志 | 由配置管理框架生成 |
| Destination | 输入 | s | 已存在的目标目录 | 必须是目录;调用方负责容量和访问控制 |
返回值与异常
| 返回值/异常 | 含义 | 触发条件 | 处理建议 |
|---|---|---|---|
| 无 D-Bus 业务返回 | 四个文件复制完成 | 正常 | 检查目标目录文件和操作日志 |
| InvalidValue | 目标路径不是目录 | 路径不存在或为文件 | 创建受控目录后重试 |
| InternalError | 任意源文件复制失败 | 源文件缺失、权限、空间或 I/O 异常 | 检查具体 Backup <name> ... failed 日志 |
应用场景
生成制造默认配置、系统还原点或升级前备份。
限制条件
- 不会备份 TemporaryPer 和 PermanentPer。
- 输出文件固定为
per_reset.db、per_poweroff.db、per_poweroff_backup.db、persistence.db。 - 执行前把 Poweroff journal 切为 DELETE,完成后恢复 WAL;中途异常也会尝试恢复 WAL。
- 目标目录中的数据库包含业务数据,必须按敏感配置数据保护,不能作为普通日志公开。
- 任意一个文件复制失败会使整个回调报 InternalError。
调试示例
busctl(仅隔离测试)
install -d -m 700 /tmp/persistence-backup
busctl --user call bmc.kepler.persistence /bmc/kepler/persistence/MicroComponent bmc.kepler.MicroComponent.ConfigManage Backup 'a{ss}s' 1 Initiator docs-persistence /tmp/persistence-backup
ls -l /tmp/persistence-backup预期文件:
per_reset.db
per_poweroff.db
per_poweroff_backup.db
persistence.db验证后安全删除测试目录。
2.23 ConfigManage.Recover
功能说明
在恢复出厂流程前,把指定表的 ResetPer 和 PoweroffPer 数据复制到临时 preserved.db;persistence 下次启动时把这些数据写回主库并删除临时数据库。
| 属性 | 内容 |
|---|---|
| 服务名 | bmc.kepler.persistence |
| 对象路径 | /bmc/kepler/persistence/MicroComponent |
| 接口名 | bmc.kepler.MicroComponent.ConfigManage |
| D-Bus 签名 | a{ss}a{ss} → void |
| 权限 | 由 ConfigManage 框架定义;仅恢复出厂编排调用 |
| 首发版本 | openUBMC 26.09 |
| 可用构建 | Release、Debug |
| 风险等级 | 高 |
| 废弃状态 | 正常可用 |
| 源码依据 | src/lualib/persistence_config_manage.lua:recover_cb、集成测试 |
参数说明
| 参数名 | 方向 | 类型 | 描述 | 取值范围 |
|---|---|---|---|---|
| Context | 输入 | a{ss} | 操作上下文 | 由框架生成 |
| Options | 输入 | a{ss} | 恢复选项字典;关键字段为 PreserveConfig | PreserveConfig 必须是 JSON 字符串,内含 DataBase 字符串数组 |
返回值与异常
| 返回值/异常 | 含义 | 触发条件 | 处理建议 |
|---|---|---|---|
| 无 D-Bus 业务返回 | 回调已处理 | 正常或配置为空 | 必须检查 preserved.db 和下次启动恢复日志 |
| 内部 false/无保留文件 | PreserveConfig 缺失、不是字符串、JSON 非法或无 DataBase 数组 | 输入不合法 | 当前回调未必转换为 D-Bus 异常,调用方必须验证结果 |
| 日志错误 | 创建目录、打开数据库或写入失败 | 路径/空间/数据库异常 | 停止恢复出厂并收集日志 |
应用场景
恢复出厂时保留网络配置或产品明确列出的少量数据库表。
限制条件
- 只从 ResetPer 和 PoweroffPer 复制指定表;Temporary、Permanent 和本地 persistence.db 不在该逻辑中。
- 临时数据库路径为
/data/trust/opt/bmc/persistence/preserved.db。 - 表名来自调用方 JSON,必须使用经过评审的白名单,避免意外保留账号或安全配置。
- 恢复发生在 persistence 下次启动;调用成功当下主数据库不会立即改变。
- 非法 PreserveConfig 当前可能只记录日志/返回 false,北向流程不能仅以 D-Bus 无异常判断成功。
调试示例
busctl(仅隔离测试)
PreserveConfig 的值本身是 JSON 字符串:
{"DataBase":["t_network_config","t_vlan_config"]}调用示意:
PRESERVE='{"DataBase":["t_network_config","t_vlan_config"]}'
busctl --user call bmc.kepler.persistence /bmc/kepler/persistence/MicroComponent bmc.kepler.MicroComponent.ConfigManage Recover 'a{ss}a{ss}' 1 Initiator docs-persistence 1 PreserveConfig "$PRESERVE"之后确认 preserved.db 已生成,并在下一次启动观察:
start recover_preserved_data
recover_preserved_data successfully2.24 Debug.Dump
功能说明
由一键日志框架调用,把四类持久化数据按表重组为 JSON,并把写入数据量/次数统计追加到 mdb_info.log。导出时应用敏感字段过滤。
| 属性 | 内容 |
|---|---|
| 服务名 | bmc.kepler.persistence |
| 对象路径 | /bmc/kepler/persistence/MicroComponent |
| 接口名 | bmc.kepler.MicroComponent.Debug |
| D-Bus 签名 | a{ss}s → void |
| 权限 | 由 MicroComponent Debug 框架定义;通常由一键日志收集器调用 |
| 首发版本 | openUBMC 26.09 |
| 可用构建 | Release、Debug(框架是否暴露手工调用需目标镜像确认) |
| 风险等级 | 中 |
| 废弃状态 | 正常可用 |
| 源码依据 | src/lualib/persistence_dump.lua、集成测试 |
参数说明
| 参数名 | 方向 | 类型 | 描述 | 取值范围 |
|---|---|---|---|---|
| Context | 输入 | a{ss} | 收集上下文 | 由一键日志框架生成 |
| OutputDir | 输入 | s | 组件输出目录 | 必须存在、可写且属于本次受控收集任务 |
返回值与异常
| 返回值/异常 | 含义 | 触发条件 | 处理建议 |
|---|---|---|---|
| 无返回值 | 导出流程结束 | 正常 | 检查五个输出文件和日志 |
| 局部失败日志 | 某一持久化类型或统计文件导出失败 | 数据库、sqlite3、路径或权限异常 | 根据 dump <type> data failed 定位;其他文件可能仍已生成 |
应用场景
一键日志收集、持久化恢复问题取证、写入热点分析。
限制条件
- 导出文件为
TemporaryPer.json、ResetPer.json、PoweroffPer.json、PermanentPer.json、mdb_info.log。 - 只导出敏感配置中已定义的表/属性;MDS 未定义属性会被省略。
- 敏感属性替换为
******;一旦数据库历史上标记为敏感,即使新配置改为非敏感仍继续脱敏。 - 一键日志压缩包中的最终相对目录由外部收集框架决定,当前源码只能确认传入输出目录中的文件名。
- 导出仍可能暴露非敏感业务配置,应按受限日志处理。
调试示例
busctl(测试目录)
install -d -m 700 /tmp/persistence-dump
busctl --user call bmc.kepler.persistence /bmc/kepler/persistence/MicroComponent bmc.kepler.MicroComponent.Debug Dump 'a{ss}s' 1 Initiator docs-persistence /tmp/persistence-dump
ls -l /tmp/persistence-dump关键日志:
start dumping databases
finished dumping databases, time taken: <ms> ms3. 组件扩展案例
3.1 扩展能力概述
persistence 的主要扩展方式不是编写服务端插件,而是由业务组件通过 MDS、生成的 ORM、PersistClient 和少量产品配置接入:
- 在业务组件
mds/model.json中定义表、主键和持久化字段; - 通过 MDS 代码生成得到 ORM 表和字段元数据;
- 组件启动时创建 PersistClient,先恢复持久化数据,再注册数据库 hook;
- 通过普通 ORM insert/update/delete 自动触发远程持久化;
- 按需配置 table_owner、CSR 恢复策略、Retain、critical、sensitive;
- 产品可通过
global*.json动态注册全局属性; - 可观测客户端通过 Dashboard 属性共享采集策略。
3.2 扩展点说明
3.2.1 MDS 类级字段
| 字段 | 是否必需 | 含义 | 注意事项 |
|---|---|---|---|
tableName | 是 | ORM 数据库表名 | 建议使用稳定的 t_ 前缀名称;改名等同于新表,需要迁移策略。 |
tableType | 可选 | 类级默认持久化类型 | TemporaryPer、ResetPer、PoweroffPer、PermanentPer。 |
tableLocation | 可选 | Local 表示本地持久化 | 未指定通常走远程;Local 不支持 PermanentPer。 |
path | 资源对象需要 | MDB 对象路径 | 与持久化主键设计相互独立。 |
3.2.2 MDS 属性级字段
| 字段 | 作用 | 关键规则 |
|---|---|---|
usage | 属性级持久化类型 | 属性级配置优先于类级 tableType;可使用 PoweroffPerRetain 等 Retain 形式。 |
primaryKey | 主键标记 | 至少一个持久化主键;复合主键按稳定顺序拼接为 name:value,...。 |
uniqueKey | 唯一键 | 主键默认唯一;用于 ORM 查询和兼容恢复。 |
baseType | 数据类型 | 客户端据此做类型、bit 长度或字符串长度校验。 |
default | 默认值 | 首次出现且全部持久化字段都等于默认值时,客户端可能不落盘。 |
notAllowNull | 非空约束 | INSERT 时缺失非空持久化字段会被客户端拒绝。 |
sensitive | 一键导出脱敏 | 导出值替换为 ******。 |
critical | 关键掉电数据 | 仅 PoweroffPer 触发同步写备份数据库。 |
3.2.3 持久化 usage 与服务端类型
| MDS usage | 服务端 persist_type | 删除对象时默认行为 |
|---|---|---|
TemporaryPer | protect_temporary | 删除字段并写墓碑 |
ResetPer | protect_reset | 删除字段并写墓碑 |
PoweroffPer | protect_power_off | 删除字段并写墓碑 |
PermanentPer | protect_permanent | 删除字段并写墓碑 |
TemporaryPerRetain | protect_temporary_retain | 保留字段 |
ResetPerRetain | protect_reset_retain | 保留字段 |
PoweroffPerRetain | protect_power_off_retain | 保留字段 |
3.3 二次开发指导
步骤一:在业务组件 MDS 中定义持久化表
{
"DemoConfig": {
"tableName": "t_demo_config",
"tableType": "PoweroffPer",
"path": "/bmc/kepler/DemoConfig/${Id}",
"properties": {
"Id": {
"baseType": "U32",
"primaryKey": true,
"readOnly": true
},
"Name": {
"baseType": "String",
"default": "",
"maxLength": 64,
"sensitive": false
},
"BootCount": {
"baseType": "U32",
"usage": ["ResetPer"],
"default": 0
},
"Secret": {
"baseType": "String",
"usage": ["PoweroffPer"],
"sensitive": true,
"critical": true,
"notAllowNull": true
},
"FactoryToken": {
"baseType": "String",
"usage": ["PoweroffPerRetain"]
}
}
}
}设计检查:
Id在所有版本中保持相同类型和语义;Secret不使用默认空值掩盖缺失输入;- 只有真正需要同步备份的数据使用
critical; FactoryToken是否应在对象删除时保留,必须通过安全评审。
步骤二:生成 ORM 代码并初始化数据库
MDS 生成后,组件会得到类似以下 ORM 表:
local db = open_local_db(...)
local DemoConfig = db.DemoConfig不要直接手工编辑生成文件;修改 MDS 后重新生成,并把生成差异纳入代码评审。
步骤三:创建并初始化 PersistClient
local PersistClient = require 'persistence.persist_client_lib'
-- service 为当前业务组件服务对象,需包含稳定的 service.name
self.persist = PersistClient.new(self.bus, self.db, self, {
-- CSR 参与恢复的表可以标记为“只恢复预置主键对应数据”
t_demo_config = false
})
self.persist:init()init() 的顺序为:
- ping persistence 服务;
- BatchRead 所有 ORM 表;
- 合并持久化数据、预置数据和删除墓碑;
- 恢复内存数据库;
- 注册 insert/update/delete hook。 若组件需要在恢复时补字段或丢弃不兼容记录,可以实现:
function service:recover_db(table_name, row)
if table_name == 't_demo_config' and row.Name == nil then
row.Name = ''
end
return true
end当前客户端通过 pcall 调用该回调;回调异常会记录日志,开发者必须为版本迁移编写单元测试。
步骤四:使用普通 ORM 操作
-- 插入
self.db:insert(self.db.DemoConfig):value({
Id = 1,
Name = 'demo',
BootCount = 1,
Secret = 'private'
}):exec()
-- 更新
self.db:update(self.db.DemoConfig):value({
BootCount = 2
}):where(self.db.DemoConfig.Id:eq(1)):exec()
-- 删除
self.db:delete(self.db.DemoConfig):where({Id = 1}):exec()
-- 只有在明确同步点调用
self.persist:flush()PersistClient 会自动过滤以下情况:
- 表没有任何持久化字段;
- 当前上下文是 Override;
- 当前上下文设置 NonPersist;
- 本次变化不包含持久化字段且主键未变化;
- 新记录所有持久化字段均为默认值且远端没有历史记录;
- 新值与客户端缓存中的持久化值完全相同。
步骤五:配置 table_owner
TABLE_OWNER_PATH 未设置时,服务端尝试读取:
/opt/bmc/apps/persistence/mds/table_owner.json示例:
{
"t_demo_config": ["demo"],
"t_shared_config": ["demo", "config_mgmt"]
}服务端会扩展为:
bmc.kepler.demo
bmc.kepler.config_mgmt注意:
- 不配置某张表时,当前实现默认允许所有 sender;敏感表应显式配置属主。
- 组件改名、服务名改名和表迁移必须同步更新该文件。
- Debug.Read/BatchRead 可绕过属主检查,Debug 镜像必须受控。
步骤六:正确使用 Retain
普通删除会保留 *_retain 字段。如果恢复出厂或安全清理要求连 Retain 一起删除,应由受控调用链设置:
local context = require 'mc.context'
-- 具体上下文创建/恢复方法由业务框架统一封装
ctx.delete_retain_data = 'true'PersistClient 会在发送前去除 _retain 后缀,使服务端执行真正删除。不要在普通业务删除中随意设置该上下文。
步骤七:扩展全局属性
文件选择顺序:
- 环境变量
GLOBAL_FILE_PATH; /opt/bmc/conf/global/global_<product_id>.json;/opt/bmc/conf/global/global.json。 最小示例:
{
"GlobalDemo": {
"tableName": "t_global",
"tableType": "KV",
"tableLocation": "Remote",
"path": "/bmc/kepler/Global",
"privilege": ["ReadOnly"],
"interfaces": {
"bmc.kepler.Global.Demo": {
"privilege": ["BasicSetting"],
"properties": {
"FeatureEnabled": {
"baseType": "Boolean",
"default": false,
"usage": ["PoweroffPer"]
},
"RetryCount": {
"baseType": "U32",
"default": 3,
"minimum": 0,
"maximum": 10,
"usage": ["ResetPer"]
},
"Endpoint": {
"baseType": "String",
"default": "local",
"minLength": 1,
"maxLength": 64,
"pattern": "^[A-Za-z0-9._-]+$",
"usage": ["PoweroffPer"],
"sensitive": false
}
}
}
}
}
}当前解析器支持的基础类型:
Boolean, String, Binary,
S8, U8, S16, U16, S32, U32, S64, U64, Double支持的 usage:
PermanentPer, PoweroffPer, ResetPer, TemporaryPer,
PoweroffPerRetain, ResetPerRetain, TemporaryPerRetain, Memory不支持的 baseType、default 类型不匹配、未知 privilege 或非法 usage 会跳过对应属性并打印 parse global prop model failed 警告。全局属性统一上树到 /bmc/kepler/Global,远程持久化表固定使用 t_global,主键形态为 Id:<domain>。
步骤八:验证扩展
- 构建并升级 Debug 测试镜像;
- 检查
bmc.kepler.persistence和业务组件 D-Bus 服务; - 首次启动读取业务属性,确认 MDS 默认值;
- 修改一个非默认值,调用 PersistClient.flush;
- 使用主 Read/BatchRead 从业务组件上下文确认远端记录;
- 复位 BMC,确认各持久化类型按预期保留或丢失;
- 删除对象,确认 active_data 和 deleted_data;
- 对 Retain 分别验证普通删除和
delete_retain_data=true; - 执行一键日志收集,确认敏感字段脱敏;
- 触发数据库备份和损坏恢复测试时,只在可恢复的隔离环境操作。
注意事项
- 不要直接修改 SQLite 表或 Permanent 原始设备节点;业务数据必须通过 ORM/PersistClient 修改。
- MDS 主键、表名和字段名一旦发布,应视为持久化兼容契约。
- 变更字段类型、持久化等级或默认值时,要设计升级、回退和墓碑兼容测试。
critical会增加每次写入备份数据库的 I/O,只用于真正关键的 PoweroffPer 字段。sensitive的历史标记会持久化;后续改为 false 也可能继续脱敏,这是安全优先行为。- Flush、备份和 Dump 都可能产生 I/O 峰值,性能测试要覆盖并发业务写入。
4. 日志说明
4.1 一键日志收集
当前源码能直接确认 Dump 回调在框架传入目录生成:
| 文件名 | 内容说明 |
|---|---|
TemporaryPer.json | TemporaryPer 活动数据,按表和记录重组;敏感字段脱敏。 |
ResetPer.json | ResetPer 活动数据。 |
PoweroffPer.json | PoweroffPer 活动数据。 |
PermanentPer.json | PermanentPer 活动数据。 |
mdb_info.log | 持久化写入数据量和写入次数统计,按日期、表和组件汇总。 |
源码不能单独确定它们在 openUBMC 26.2.0 最终一键日志 ZIP 中的相对目录。README 给出过 dump_info/AppDump/persistence/,但正式发布前必须以目标镜像实际收集结果为准。 |
4.2 运行日志位置
| 日志/文件 | 源码证据与用途 |
|---|---|
/var/log/framework/persistence.log | dist/config.cfg 声明的组件 logger。实际产品可能汇聚到 framework.log。 |
/var/log/framework.log | deployConfig 为 framework.service 时的主要框架日志候选;以目标日志路由为准。 |
/var/log/operation.log | ConfigManage.Backup 使用统一操作日志接口记录成功/失败;物理路径由平台 logger 配置决定。 |
/var/log/running.log | 数据库超限和恢复使用 running log;物理路径由平台配置决定。 |
/data/var/damaged_database/ | Debug 构建可保存损坏的主数据库副本,文件名包含版本发布日期。 |
4.3 关键日志信息
| 日志片段 | 级别 | 含义解读 | 建议处理动作 |
|---|---|---|---|
persist client init completed, time taken: ... | NOTICE | 客户端恢复并注册 hook 完成 | 建立启动耗时基线;过长时检查 BatchRead 和表数量 |
persist client recover from db failed, call read_by_tables failed | ERROR | 客户端启动恢复失败 | 检查 persistence 服务、属主和数据库 |
persist app read/save failed, table owner mismatch | ERROR | 真实 D-Bus sender 不是表属主 | 核对 table_owner 和服务名 |
appname(...) save table(...) fail as db files size overrun | ERROR | Save 因数据库超限被静默丢弃 | 立即处理容量;修复后重新触发业务写入 |
the database size exceeds the upper limit... | RUNNING/WARN | 本地或远程数据库超过上限,存在拒绝服务风险 | 收集分区、数据库大小和写入热点 |
the database size and persistence service are restored to normal | RUNNING/WARN | 超限状态解除 | 验证此前丢弃的数据是否需要补写 |
A storm occurs in table ... | WARN | 某表一分钟内短周期提交达到阈值 | 找高频写入源;检查是否把周期数据误设为持久化 |
database integrity check failed | ERROR | SQLite quick_check 失败 | 禁止直接覆盖;按主库→备份→recover 流程处理 |
database file in the primary partition ... copy it from the backup partition | WARN/RUNNING | 主库缺失或损坏,尝试备份恢复 | 检查备份完整性和数据时效 |
failed to recover from backup database | WARN | 新旧备份都不可用 | 保留损坏库,评估 SQLite recover 和业务重建 |
database per_poweroff.db backup successful | NOTICE | Poweroff 周期/触发备份成功 | 核对备份文件时间和 quick_check |
persist save failed for backup database | ERROR | 关键字段主库成功、备库失败 | 立即修复备份区;主调用可能仍显示成功 |
finish force commit transactions before reboot | NOTICE | 复位前强制提交完成 | 与 Action/关闭数据库日志成对确认 |
received flash write protection signal | NOTICE | NAND 写保护开启,服务等待 5 秒后强制提交 | 关注后续 finish to commit all transactions |
start/finished dumping databases | NOTICE | 一键导出开始/结束 | 检查五个输出文件和耗时 |
parse global prop model failed | WARN/ERROR | 全局属性配置中的类型、默认值、usage 或权限非法 | 按接口/属性名修复配置 |
fetch Dashboard database data failed | ERROR | 本地 Dashboard 表读取失败 | 检查本地 persistence.db 和模型兼容 |
4.4 日志与数据安全
- 主 Read/Debug.Read 返回的是原始持久化值,不自动脱敏。
- 只有 Dump 路径会按敏感配置过滤和替换
******。 - Debug 构建保存的损坏数据库可能包含敏感原值,目录必须受限访问并及时清理。
- 不要把整个数据库、Read 响应或未审查的一键日志上传到公开社区。
- 故障单优先提供日志片段、表名、主键哈希、数据库大小、quick_check 结果和时间线。
5. 问题定界指南
5.1 分层定界原则
按以下顺序判断,避免一开始就修改数据库:
- 部署层:实际由
framework.service还是persistence.service承载; - D-Bus 层:服务名、对象和接口是否上树;
- 客户端层:PersistClient 是否完成 init、恢复和 hook 注册;
- 模型层:表名、主键、usage、default、Local/Remote 是否正确;
- 授权层:table_owner 与真实 D-Bus sender 是否匹配;
- 调度层:事务是否被默认值过滤、上下文跳过、风暴抑制或等待 Flush;
- 存储层:数据库大小、完整性、journal、主备文件和 Permanent 设备;
- 生命周期层:复位、掉电、恢复出厂语义是否与持久化类型一致;
- 导出层:一键收集框架是否实际调用 Dump、输出目录是否可写。
5.2 典型问题定界
| 现象描述 | 是否为 persistence 问题 | 判断依据 | 关键证据收集方法 |
|---|---|---|---|
bmc.kepler.persistence 不存在 | 可能是部署/框架问题 | framework 未启动、依赖失败或组件初始化失败 | systemctl、busctl list/tree、framework 日志 |
| 业务属性修改后立即读取正常,复位后恢复旧值 | 高概率为持久化链路问题 | 内存 DB 正常但 Save/Flush/落盘失败或被过滤 | 客户端日志、BatchRead、数据库 mtime、Flush 结果 |
| Read 返回 IncorrectSenderInfo | 配置/调用者问题 | table_owner 不允许真实 sender | table_owner.json、服务名、错误日志 |
| Save 调用成功但没有数据 | 可能是策略或容量问题 | 默认值过滤、NonPersist/Override、超限静默丢弃、异步未 Flush | 相关日志、上下文、BatchRead、容量告警 |
| 同一表延迟约一分钟才落盘 | 通常是风暴抑制 | 出现 A storm occurs in table | 统计该表写入频率和调用栈 |
| Poweroff 主库损坏后数据变旧 | 可能是预期恢复行为 | 服务优先从较旧备份恢复 | 主/备 quick_check、mtime、恢复日志 |
| 关键字段主库有新值、备份没有 | persistence 备份异常 | 关键字段备库写失败仍返回成功 | persist save failed for backup database、两库只读查询 |
| 恢复出厂后应保留表却丢失 | ConfigManage/编排问题 | PreserveConfig 非法、表名未加入、preserved.db 未恢复 | Recover 入参、preserved.db、启动恢复日志 |
| Dashboard 写入后复位不一致 | 当前源码差异需重点验证 | 默认值 20/60/20 与模型 5/30/5;SamplingPolicy 未显式恢复 | 属性前后值、本地表、dashboard 日志 |
| 一键日志没有 JSON 文件 | Dump/收集框架问题 | Debug.Dump 未调用、输出目录或 sqlite3 失败 | 收集器日志、dump 开始/结束日志、输出目录 |
| PermanentPer 读取失败 | 设备/驱动问题 | /dev/mmcblk0p8 不可用、格式或锁异常 | 设备节点、驱动日志、只读状态;不要用文件工具覆盖 |
| 数据类型非法但业务无异常 | 客户端校验丢弃 | validate 只记日志并 return | Data validation failed 日志和 ORM 输入 |
5.3 错误与状态速查表
| 错误/状态 | 含义 | 可能原因 | 排查建议 |
|---|---|---|---|
IncorrectSenderInfo | 表属主校验失败 | 服务改名、配置遗漏、直接 shell 调用受限表 | 从真实业务组件调用;更新 table_owner |
InvalidValue(filepath) | Backup 目标不是目录 | 路径不存在或是普通文件 | 创建权限 0700 的目录 |
InternalError | Backup 复制任一文件失败 | 源文件缺失、空间不足、权限/I/O | 查 Backup <name> 错误日志 |
Data validation failed: require not null | INSERT 缺少非空持久化字段 | MDS 与业务输入不一致 | 补值或修正 notAllowNull |
Data validation failed: type mismatch | BOOLEAN/INTEGER/REAL 类型不合法 | 字符串数字、非整数、Boolean 非 0/1 | 在 ORM 边界转换类型 |
Data validation failed: max length exceeded | 字符串长度或整数 bit 长度超限 | MDS maxLength 太小或输入异常 | 修正数据和模型,评估兼容性 |
db files size overrun | 数据库超限,Save 被丢弃 | 高频写入、无清理、分区不足 | 先止写、统计热点、扩容/清理后补写 |
A storm occurs in table | 表写入风暴 | 周期采样值每次落盘、无变化过滤失效 | 降频、改 Memory/Temporary、只保存必要状态 |
database integrity check failed | SQLite 损坏 | 掉电、存储介质或旧临时文件不匹配 | 保留现场,按自动恢复链路分析 |
backup database ... damaged and not open | 备份不可用 | 备份文件损坏且重新备份失败 | 修复备份分区,确认主库完整性后重建备份 |
the transaction cache is dirty | 新一轮开始仍有旧事务 | 调度/提交异常 | 收集线程、锁、前序错误和复现压力 |
5.4 开启调试日志
优先使用平台标准日志级别工具,不要直接修改源码常量。若目标镜像提供 mdbctl:
$ mdbctl
% attach persistence
% dloglevel是否支持动态设置、具体命令和输出取决于目标 SDK。正式发布前应在 26.2.0 Debug 镜像验证,并记录恢复原日志级别的命令。
5.5 最小复现与证据收集
5.5.1 无破坏性基础检查
busctl --user list | grep -F bmc.kepler.persistence
busctl --user tree bmc.kepler.persistence
busctl --user introspect bmc.kepler.persistence /bmc/kepler/persistence
systemctl status framework.service --no-pager
systemctl status persistence.service --no-pager || true
ls -lh /run/persistence/per_temporary.db /opt/bmc/pram/persistence/per_reset.db /data/trust/persistence/per_poweroff.db /data/backup/persistence/per_poweroff.db 2>/dev/null5.5.2 SQLite 只读检查
/usr/sbin/sqlite3 -readonly /data/trust/persistence/per_poweroff.db 'PRAGMA quick_check; PRAGMA journal_mode; SELECT count(*) FROM persist_table;'
/usr/sbin/sqlite3 -readonly /data/backup/persistence/per_poweroff.db 'PRAGMA quick_check; SELECT count(*) FROM persist_table;'禁止在故障现场执行 UPDATE、DELETE、VACUUM、REINDEX、journal_mode 切换或直接复制覆盖主库。
5.5.3 单表业务复现
- 选择不含敏感数据的测试表和主键;
- 记录修改前业务值;
- 通过业务组件 ORM 修改为非默认值;
- 调用组件 PersistClient.flush;
- 从同一业务组件上下文调用 Read/BatchRead;
- 复位 BMC,确认值恢复;
- 恢复原值并再次 Flush;
- 收集时间窗口内 persistence/framework 日志。
5.5.4 风暴复现
仅在测试环境对单一测试表连续产生超过 30 个短周期提交,预期出现:
A storm occurs in table <table>随后该表进入延迟队列,在一分钟大周期或显式 Flush/复位强制提交时统一处理。测试结束后确认数据库大小和写入统计没有异常增长。
5.5.5 备份恢复测试
数据库损坏实验必须使用可重刷、可恢复的隔离镜像,并保留原始主库和备份库副本。验收点:
- 主库缺失时从
/data/backup恢复; - 主库损坏时先尝试头修复,再优先备份恢复,最后 SQLite recover;
- Debug 镜像保留损坏库副本;
- 恢复后的业务数据时效符合备份周期;
- 新主库和备份库 quick_check 均为
ok。
6. 常见问题解答
Q1:persistence 是“远程网络服务”吗?
- 问题描述:文档把它称为远程持久化,容易误解为跨 BMC 网络服务。
- 一句话答案:不是;这里的远程是相对于本组件本地数据库而言,指通过 D-Bus 进行进程间持久化。
- 根因说明:业务组件内存数据库和 persistence 服务端不在同一个直接 ORM 存储边界。
- 解决方案:业务查询仍访问本组件内存 DB,持久化恢复和写入通过 PersistClient 完成。
- 适用版本:当前 1.130.9 及随附 CHANGELOG 可追溯版本。
Q2:为什么修改属性后 Read 立即看不到?
- 问题描述:ORM 修改成功,但服务端 Read 仍返回旧值。
- 一句话答案:写入是异步合并的;在需要确定同步点时调用 PersistClient.flush。
- 根因说明:客户端和服务端都有事务/协程缓存,普通表约 0.1 秒调度,风暴表可能延迟更久。
- 解决方案:只在测试、复位前或明确配置完成点调用 flush,再读取验证。
- 规避方案:不要把远端 Read 用作每次业务写入后的同步确认机制。
- 适用版本:1.130.9。
Q3:为什么 Save 没报错但数据没有保存?
- 问题描述:D-Bus 调用成功,复位后数据仍丢失。
- 一句话答案:Save 可能被默认值/上下文策略过滤,也可能在数据库超限时被静默丢弃。
- 根因说明:客户端优化会跳过无变化和全默认值;服务端超限分支只记录错误并 return。
- 解决方案:检查
persistent data is the default value...、db files size overrun、Override/NonPersist 上下文和 Flush。 - 规避方案:自动化验证同时检查日志、BatchRead 和复位后业务值,不只检查退出码。
- 适用版本:1.130.9。
Q4:为什么直接在 shell 调 Read 得到 IncorrectSenderInfo?
- 问题描述:busctl 的签名正确但表读取被拒绝。
- 一句话答案:该表配置了属主,shell 调用的真实 D-Bus sender 不是允许的组件服务。
- 根因说明:table_owner 校验使用总线 sender,第二个 AppName 字符串不能伪造授权。
- 解决方案:从真实业务组件调用;调试镜像可在受控条件下使用 Debug.Read。
- 规避方案:为测试表单独设计属主和测试组件,不放宽生产敏感表。
- 适用版本:自 1.27.3 可追溯。
Q5:不配置 table_owner 会怎样?
- 问题描述:新表没有出现在 table_owner.json。
- 一句话答案:当前实现对未配置表默认允许访问,安全敏感表不应依赖该默认行为。
- 根因说明:
match_table_owner在没有该表节点时直接返回 true。 - 解决方案:为所有需要隔离的表显式列出组件短名,并覆盖服务改名测试。
- 规避方案:在 CI 中比较 MDS 远程持久化表和 table_owner 的覆盖率。
- 适用版本:1.130.9。