persistence

版本信息

项目内容
组件版本1.130.10
首发版本openUBMC 26.09
文档作者openUBMC 社区
最后更新2026-09-15
许可证Mulan PSL v2

1. 组件概述

1.1 组件简介

persistence 是 openUBMC 基础框架中的配置与数据持久化组件,负责为业务组件提供远程持久化服务。这里的“远程”不是网络远程,而是指业务组件通过进程间 D-Bus 调用,把内存数据库中的持久化字段交给 persistence 统一写入对应后端;业务读取通常仍直接访问本组件的内存数据库,不在每次查询时访问 persistence。 组件同时包含以下能力:

  1. 统一管理 TemporaryPer、ResetPer、PoweroffPer、PermanentPer 四类数据;
  2. 在业务组件启动时批量读取数据,覆盖或合并 MDS/CSR 预置数据;
  3. 监听 ORM 数据库钩子,把插入、更新和删除转换为持久化事务;
  4. 合并高频事务、抑制写入风暴并支持显式 Flush;
  5. 为 PoweroffPer 提供周期备份、关键属性同步备份、完整性检查和损坏恢复;
  6. 为恢复出厂、平滑复位、一键日志收集和 NAND 写保护提供框架回调;
  7. 动态注册 /bmc/kepler/Global 全局属性,并持久化可观测性 Dashboard 配置。 当前源码保留了独立 persistence.service 文件,但 mds/service.jsondeployConfigframework.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 接口。
TemporaryPerBMC 复位和掉电后均不保留的数据。
ResetPerBMC 复位后保留、掉电后丢失的数据。
PoweroffPer掉电后保留、恢复出厂时通常清除的数据。
PermanentPer恢复出厂后仍保留的数据,当前后端为专用原始设备节点(源码称“字符设备”,非文件系统)。
Retain删除业务对象时仍保留指定持久化字段;显式上下文可要求同时删除。
关键数据 criticalPoweroffPer 属性更新时还要同步写入备份数据库的字段。
敏感数据 sensitive一键日志导出时必须脱敏的字段。
表属主 table owner允许访问某张远程持久化表的 D-Bus 服务名集合。
活动数据 active_data当前有效的持久化记录。
删除标记 deleted_data用于在恢复时删除预置记录的主键墓碑数据。
风暴抑制同一表高频写入达到阈值后,暂停短周期提交并在一分钟大周期统一落盘。
Flush等待客户端异步事务和服务端缓存事务完成并落盘的同步点。

1.5 外部交互边界图

1.5.1 典型数据时序

1.5.2 持久化类型和路径

类型当前源码默认后端保留语义补充说明
TemporaryPer/run/persistence/per_temporary.dbBMC 复位丢失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 管理,实际按原始设备节点访问,不是普通文件系统数据库。
本地 PoweroffLOCAL_POWEROFF_PATH_MINI/persistence.db/data/trust/persistence.local/persistence.db由本组件 ORM 管理ConfigManage.Backup 会复制为 persistence.db

1.5.3 主要服务、对象和接口

用途服务名对象路径接口
远程持久化bmc.kepler.persistence/bmc/kepler/persistencebmc.kepler.persistence
Debug 持久化bmc.kepler.persistence/bmc/kepler/Debug/Persistencebmc.kepler.Persistence
复位回调bmc.kepler.persistence/bmc/kepler/persistence/MicroComponentbmc.kepler.MicroComponent.Reboot
配置备份/恢复bmc.kepler.persistence/bmc/kepler/persistence/MicroComponentbmc.kepler.MicroComponent.ConfigManage
一键日志 Dumpbmc.kepler.persistence/bmc/kepler/persistence/MicroComponentbmc.kepler.MicroComponent.Debug
可观测配置bmc.kepler.persistence/bmc/kepler/Dashboardbmc.kepler.Dashboard.Observability*
全局属性bmc.kepler.persistence/bmc/kepler/Globalglobal*.json 动态定义的 bmc.kepler.Global.*

2. API 使用说明与示例

2.1 通用调用规则

2.1.1 服务与对象检查

bash
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 当前接口目录

方法/属性
主持久化接口BatchReadReadSaveFlush
Debug 接口Debug.ReadDebug.BatchReadDebug.SaveDebug.Flush
DashboardObservability.Enabled、4 个 Traces 属性、2 个 Metrics 属性、2 个 Logs 属性
RebootReboot.PrepareReboot.ActionReboot.Cancel
ConfigManageConfigManage.BackupConfigManage.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.luainclude/persistence/persist_client_lib.lua

参数说明

参数名方向类型描述取值范围
Tables输入as待读取的远程持久化表名列表每项必须是已知 ORM 表名;可为空数组

返回值与异常

返回值/异常含义触发条件处理建议
a{sa{sa{sa{say}}}}每张表包含 active_datadeleted_data,记录值为二进制数组序列化结果正常完成由 PersistClient 解码并合并,不要在 shell 中依赖内部二进制格式
IncorrectSenderInfo调用者不是某张表的属主table_owner.json 对该表有限制且真实 sender 不匹配由正确业务组件调用,或修正属主配置
D-Bus 异常服务未就绪或读取过程失败组件启动窗口、总线或数据库异常PersistClient 当前最多重试 100 次;结合日志判断

应用场景

业务组件启动时一次恢复多张表;定位某组件预置数据为何没有被恢复;核对删除墓碑是否覆盖 CSR/MDS 预置记录。

限制条件

  • 返回值是内部恢复协议,不是面向普通运维用户的稳定 JSON API。
  • 会合并不同持久化后端中同一主键的字段;调用方不能假设字段只来自单个数据库。
  • 读取大表会增加 D-Bus 消息和内存压力,应按组件实际表集合调用。
  • 属主校验使用真实 D-Bus sender;显式的 app 名称不能绕过校验。

调试示例

busctl
bash
busctl --user call bmc.kepler.persistence /bmc/kepler/persistence bmc.kepler.persistence BatchRead 'as' 2 t_demo t_demo_extra

响应形态:

text
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.luainclude/persistence/persist_client_lib.lua

参数说明

参数名方向类型描述取值范围
TableName输入s待读取表名已定义的远程持久化表
AppName输入s调用方组件名称,主要用于统计/兼容建议使用组件服务短名;不能替代真实 sender

返回值与异常

返回值/异常含义触发条件处理建议
a(sa{say})记录数组;每项包含拼接后的主键字符串及字段字典正常完成由 SDK 解码为 Lua 值
IncorrectSenderInfo表属主校验失败真实 sender 不在允许集合由表属主组件调用
空数组表不存在持久化记录或数据为空首次启动、默认值未落盘或已删除结合预置数据与日志判断,不等同于接口失败

应用场景

调试单表恢复;确认某字段是否已经落盘;核对同一主键在不同后端的字段合并结果。

限制条件

  • 只返回活动记录,不单独返回 deleted_data;需要删除墓碑时使用 BatchRead。
  • 第二个字符串不是授权凭据,真实访问控制仍取决于 D-Bus sender。
  • 返回顺序未定义,不应据此比较版本或业务优先级。

调试示例

busctl
bash
busctl --user call bmc.kepler.persistence /bmc/kepler/persistence bmc.kepler.persistence Read 'ss' t_demo persistence-doc

响应形态:

text
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.luasrc/lualib/persistence_transaction.luasrc/lualib/persistence_db_intf.lua

参数说明

参数名方向类型描述取值范围
Operation输入iSQLite 操作码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 调试
lua
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 是框架内部序列化数据。可先核对签名:

bash
busctl --user introspect bmc.kepler.persistence /bmc/kepler/persistence bmc.kepler.persistence

2.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.luasrc/lualib/persistence_task_schedule.luainclude/persistence/persist_client_lib.lua

参数说明

参数名方向类型描述取值范围
AppName输入s发起请求的组件名;当前服务端实现不使用其内容非空组件名为宜

返回值与异常

返回值/异常含义触发条件处理建议
无返回值无待提交事务,或所有当前事务已完成正常执行继续业务流程
调用阻塞/超时提交协程未唤醒或底层 I/O 长时间阻塞数据库锁、设备异常、服务状态异常检查事务/数据库日志,避免并发重复 Flush

应用场景

复位前保证数据落盘;配置操作完成后建立确定同步点;测试中先 Save 再 Read 核验。

限制条件

  • Flush 会牺牲异步合并带来的性能收益,不应对每次属性更新调用。
  • 它只等待当前已进入客户端和服务端队列的事务,不替代业务层事务边界。
  • 高并发 Flush 可能放大锁竞争;应由组件集中管理同步点。

调试示例

busctl
bash
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_methodsmds/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 镜像)
bash
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 镜像)
bash
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 镜像)
lua
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 镜像)
bash
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.jsongen/class/model.luasrc/lualib/dashboard.lua

参数说明

参数名方向类型描述取值范围
Value输入/输出bEnabled 属性值Boolean;生成模型默认 false

返回值与异常

返回值/异常含义触发条件处理建议
属性值读取成功对象已上树记录当前值
Properties.Set 成功值写入对象并通过本地 ORM 持久化权限和类型合法重读确认
权限/类型异常调用者无 DiagnoseMgmt 或类型不匹配写操作被拒绝使用授权账号和正确签名

应用场景

配置可观测数据的采集和导出策略;验证配置是否在复位后恢复。

限制条件

  • 该属性只提供共享配置,不保证所有采集客户端已正确订阅。
  • 写入后应验证实际日志/指标/追踪客户端是否停止或恢复上报。
  • 本地表为 PoweroffPer,恢复出厂后的保留语义以产品流程为准。

调试示例

busctl
bash
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

读取响应形态:

text
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.jsongen/class/model.luasrc/lualib/dashboard.lua

参数说明

参数名方向类型描述取值范围
Value输入/输出dSamplingRate 属性值Double;生成类型默认值可表现为 0,源码未定义最小值、最大值或比例语义

返回值与异常

返回值/异常含义触发条件处理建议
属性值读取成功对象已上树记录当前值
Properties.Set 成功值写入对象并通过本地 ORM 持久化权限和类型合法重读确认
权限/类型异常调用者无 DiagnoseMgmt 或类型不匹配写操作被拒绝使用授权账号和正确签名

应用场景

配置可观测数据的采集和导出策略;验证配置是否在复位后恢复。

限制条件

  • 当前生成校验仅检查 Double 类型,没有范围约束;不要自行假设必须在 0~1。
  • 需与使用该属性的可观测客户端约定合法区间。

调试示例

busctl
bash
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

读取响应形态:

text
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.jsongen/class/model.luasrc/lualib/dashboard.lua

参数说明

参数名方向类型描述取值范围
Value输入/输出ySamplingPolicy 属性值U8;模型默认 1

返回值与异常

返回值/异常含义触发条件处理建议
属性值读取成功对象已上树记录当前值
Properties.Set 成功值写入对象并通过本地 ORM 持久化权限和类型合法重读确认
权限/类型异常调用者无 DiagnoseMgmt 或类型不匹配写操作被拒绝使用授权账号和正确签名

应用场景

配置可观测数据的采集和导出策略;验证配置是否在复位后恢复。

限制条件

  • 当前源码只校验 U8 类型,不定义 1、2 等编号的业务含义。
  • dashboard.lua 构造函数没有显式从本地数据库复制 SamplingPolicy,因此复位后的恢复行为必须在目标 1.130.9 镜像验证。
  • 不要把未确认的策略编号写入生产环境。

调试示例

busctl
bash
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

读取响应形态:

text
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.jsongen/class/model.luasrc/lualib/dashboard.lua

参数说明

参数名方向类型描述取值范围
Value输入/输出ySamplingLevel 属性值U8;模型默认 2

返回值与异常

返回值/异常含义触发条件处理建议
属性值读取成功对象已上树记录当前值
Properties.Set 成功值写入对象并通过本地 ORM 持久化权限和类型合法重读确认
权限/类型异常调用者无 DiagnoseMgmt 或类型不匹配写操作被拒绝使用授权账号和正确签名

应用场景

配置可观测数据的采集和导出策略;验证配置是否在复位后恢复。

限制条件

  • 当前源码没有给出枚举含义或范围约束。
  • 属性持久化成功不代表消费者支持该级别,需联动验证。

调试示例

busctl
bash
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

读取响应形态:

text
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.jsongen/class/model.luasrc/lualib/dashboard.lua

参数说明

参数名方向类型描述取值范围
Value输入/输出uExportIntervalSeconds 属性值U32;dashboard.lua 无记录时运行时回退为 20 秒,但生成模型元数据仍声明 5 秒

返回值与异常

返回值/异常含义触发条件处理建议
属性值读取成功对象已上树记录当前值
Properties.Set 成功值写入对象并通过本地 ORM 持久化权限和类型合法重读确认
权限/类型异常调用者无 DiagnoseMgmt 或类型不匹配写操作被拒绝使用授权账号和正确签名

应用场景

配置可观测数据的采集和导出策略;验证配置是否在复位后恢复。

限制条件

  • 当前源码存在 20 秒与 5 秒两套默认值证据;本文按运行时构造逻辑说明首次上树值,并把差异列为 DE 确认项。
  • 没有最小/最大值约束;过小周期可能增加 CPU、网络和日志压力。

调试示例

busctl
bash
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

读取响应形态:

text
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.jsongen/class/model.luasrc/lualib/dashboard.lua

参数说明

参数名方向类型描述取值范围
Value输入/输出uExportIntervalSeconds 属性值U32;运行时回退为 60 秒,生成模型元数据声明 30 秒

返回值与异常

返回值/异常含义触发条件处理建议
属性值读取成功对象已上树记录当前值
Properties.Set 成功值写入对象并通过本地 ORM 持久化权限和类型合法重读确认
权限/类型异常调用者无 DiagnoseMgmt 或类型不匹配写操作被拒绝使用授权账号和正确签名

应用场景

配置可观测数据的采集和导出策略;验证配置是否在复位后恢复。

限制条件

  • 当前源码存在 60 秒与 30 秒默认值差异,正式契约需维护者确认。
  • 过小周期会增加指标计算和上传压力。

调试示例

busctl
bash
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

读取响应形态:

text
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.jsongen/class/model.luasrc/lualib/dashboard.lua

参数说明

参数名方向类型描述取值范围
Value输入/输出asActivatedMetrics 属性值String[];生成默认值为空数组

返回值与异常

返回值/异常含义触发条件处理建议
属性值读取成功对象已上树记录当前值
Properties.Set 成功值写入对象并通过本地 ORM 持久化权限和类型合法重读确认
权限/类型异常调用者无 DiagnoseMgmt 或类型不匹配写操作被拒绝使用授权账号和正确签名

应用场景

配置可观测数据的采集和导出策略;验证配置是否在复位后恢复。

限制条件

  • 名称有效性由指标消费者决定。
  • 列表过大可能增加采集开销。
  • 设置空数组的实际含义应与消费者确认,不能默认等同于“全部启用”或“全部关闭”。

调试示例

busctl
bash
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

读取响应形态:

text
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.jsongen/class/model.luasrc/lualib/dashboard.lua

参数说明

参数名方向类型描述取值范围
Value输入/输出bEnabled 属性值Boolean;生成默认值 false

返回值与异常

返回值/异常含义触发条件处理建议
属性值读取成功对象已上树记录当前值
Properties.Set 成功值写入对象并通过本地 ORM 持久化权限和类型合法重读确认
权限/类型异常调用者无 DiagnoseMgmt 或类型不匹配写操作被拒绝使用授权账号和正确签名

应用场景

配置可观测数据的采集和导出策略;验证配置是否在复位后恢复。

限制条件

  • 该开关不等同于关闭组件本地运行日志,只影响使用该共享配置的可观测客户端。
  • 写入后要验证消费者是否已订阅属性变化。

调试示例

busctl
bash
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

读取响应形态:

text
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.jsongen/class/model.luasrc/lualib/dashboard.lua

参数说明

参数名方向类型描述取值范围
Value输入/输出uExportIntervalSeconds 属性值U32;运行时回退为 20 秒,生成模型元数据声明 5 秒

返回值与异常

返回值/异常含义触发条件处理建议
属性值读取成功对象已上树记录当前值
Properties.Set 成功值写入对象并通过本地 ORM 持久化权限和类型合法重读确认
权限/类型异常调用者无 DiagnoseMgmt 或类型不匹配写操作被拒绝使用授权账号和正确签名

应用场景

配置可观测数据的采集和导出策略;验证配置是否在复位后恢复。

限制条件

  • 当前源码存在 20 秒与 5 秒默认值差异,需在目标镜像和接口契约中确认。
  • 过小周期可能提高 CPU、网络和服务端压力。

调试示例

busctl
bash
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

读取响应形态:

text
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

返回值与异常

返回值/异常含义触发条件处理建议
0Prepare 完成当前实现无额外动作进入后续复位阶段
D-Bus 异常服务或框架对象异常对象未上树、总线异常终止复位并收集日志

应用场景

系统平滑复位编排,不是普通业务调用。

限制条件

  • 直接调用不会提交事务;真正的数据收尾发生在 Action。
  • 接口返回 0 不代表所有业务组件都已完成保存。
  • 仅在隔离测试机或系统复位框架中调用。

调试示例

busctl(仅隔离测试)
bash
busctl --user call bmc.kepler.persistence /bmc/kepler/persistence/MicroComponent bmc.kepler.MicroComponent.Reboot Prepare 'a{ss}' 1 Initiator docs-persistence

预期响应:

text
i 0

2.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

返回值与异常

返回值/异常含义触发条件处理建议
0Action 流程结束无论 10 次检查内是否看到提交标志,当前实现最终都返回 0必须结合日志确认事务和备份结果
D-Bus/进程异常执行中服务退出或对象失效I/O、数据库或框架异常停止复位链路并保留现场

应用场景

系统平滑复位、AC 掉电准备。

限制条件

  • ⚠️ 直接调用会关闭 persistence 的数据库句柄,可能使后续写入无法落盘;仅在隔离测试机和真实复位编排中执行。
  • 源码最多等待 10 次、每次 0.2 秒检查强制提交标志;即使未观察到标志也会关闭数据库并返回 0。
  • Requestor 字符串影响是否触发备份,不能由普通调用者伪造。
  • 调用后若复位被取消,框架必须调用 Cancel 重新打开数据库。

调试示例

验证建议

不要在仍需继续运行的生产 BMC 手工执行。隔离环境中由复位测试框架调用,并观察:

text
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 确认框架生成的最终签名。

调试示例

目标镜像确认
bash
busctl --user introspect bmc.kepler.persistence /bmc/kepler/persistence/MicroComponent bmc.kepler.MicroComponent.Reboot

由系统复位测试触发 Cancel,预期日志:

text
persistence cancel reboot and reopen db and backup_db

2.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.dbper_poweroff.dbper_poweroff_backup.dbpersistence.db
  • 执行前把 Poweroff journal 切为 DELETE,完成后恢复 WAL;中途异常也会尝试恢复 WAL。
  • 目标目录中的数据库包含业务数据,必须按敏感配置数据保护,不能作为普通日志公开。
  • 任意一个文件复制失败会使整个回调报 InternalError。

调试示例

busctl(仅隔离测试)
bash
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

预期文件:

text
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}恢复选项字典;关键字段为 PreserveConfigPreserveConfig 必须是 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 字符串:

json
{"DataBase":["t_network_config","t_vlan_config"]}

调用示意:

bash
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 已生成,并在下一次启动观察:

text
start recover_preserved_data
recover_preserved_data successfully

2.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.jsonResetPer.jsonPoweroffPer.jsonPermanentPer.jsonmdb_info.log
  • 只导出敏感配置中已定义的表/属性;MDS 未定义属性会被省略。
  • 敏感属性替换为 ******;一旦数据库历史上标记为敏感,即使新配置改为非敏感仍继续脱敏。
  • 一键日志压缩包中的最终相对目录由外部收集框架决定,当前源码只能确认传入输出目录中的文件名。
  • 导出仍可能暴露非敏感业务配置,应按受限日志处理。

调试示例

busctl(测试目录)
bash
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

关键日志:

text
start dumping databases
finished dumping databases, time taken: <ms> ms

3. 组件扩展案例

3.1 扩展能力概述

persistence 的主要扩展方式不是编写服务端插件,而是由业务组件通过 MDS、生成的 ORM、PersistClient 和少量产品配置接入:

  1. 在业务组件 mds/model.json 中定义表、主键和持久化字段;
  2. 通过 MDS 代码生成得到 ORM 表和字段元数据;
  3. 组件启动时创建 PersistClient,先恢复持久化数据,再注册数据库 hook;
  4. 通过普通 ORM insert/update/delete 自动触发远程持久化;
  5. 按需配置 table_owner、CSR 恢复策略、Retain、critical、sensitive;
  6. 产品可通过 global*.json 动态注册全局属性;
  7. 可观测客户端通过 Dashboard 属性共享采集策略。

3.2 扩展点说明

3.2.1 MDS 类级字段

字段是否必需含义注意事项
tableNameORM 数据库表名建议使用稳定的 t_ 前缀名称;改名等同于新表,需要迁移策略。
tableType可选类级默认持久化类型TemporaryPerResetPerPoweroffPerPermanentPer
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删除对象时默认行为
TemporaryPerprotect_temporary删除字段并写墓碑
ResetPerprotect_reset删除字段并写墓碑
PoweroffPerprotect_power_off删除字段并写墓碑
PermanentPerprotect_permanent删除字段并写墓碑
TemporaryPerRetainprotect_temporary_retain保留字段
ResetPerRetainprotect_reset_retain保留字段
PoweroffPerRetainprotect_power_off_retain保留字段

3.3 二次开发指导

步骤一:在业务组件 MDS 中定义持久化表

json
{
  "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 表:

lua
local db = open_local_db(...)
local DemoConfig = db.DemoConfig

不要直接手工编辑生成文件;修改 MDS 后重新生成,并把生成差异纳入代码评审。

步骤三:创建并初始化 PersistClient

lua
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() 的顺序为:

  1. ping persistence 服务;
  2. BatchRead 所有 ORM 表;
  3. 合并持久化数据、预置数据和删除墓碑;
  4. 恢复内存数据库;
  5. 注册 insert/update/delete hook。 若组件需要在恢复时补字段或丢弃不兼容记录,可以实现:
lua
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 操作

lua
-- 插入
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 未设置时,服务端尝试读取:

text
/opt/bmc/apps/persistence/mds/table_owner.json

示例:

json
{
  "t_demo_config": ["demo"],
  "t_shared_config": ["demo", "config_mgmt"]
}

服务端会扩展为:

text
bmc.kepler.demo
bmc.kepler.config_mgmt

注意:

  • 不配置某张表时,当前实现默认允许所有 sender;敏感表应显式配置属主。
  • 组件改名、服务名改名和表迁移必须同步更新该文件。
  • Debug.Read/BatchRead 可绕过属主检查,Debug 镜像必须受控。

步骤六:正确使用 Retain

普通删除会保留 *_retain 字段。如果恢复出厂或安全清理要求连 Retain 一起删除,应由受控调用链设置:

lua
local context = require 'mc.context'
-- 具体上下文创建/恢复方法由业务框架统一封装
ctx.delete_retain_data = 'true'

PersistClient 会在发送前去除 _retain 后缀,使服务端执行真正删除。不要在普通业务删除中随意设置该上下文。

步骤七:扩展全局属性

文件选择顺序:

  1. 环境变量 GLOBAL_FILE_PATH
  2. /opt/bmc/conf/global/global_<product_id>.json
  3. /opt/bmc/conf/global/global.json。 最小示例:
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
          }
        }
      }
    }
  }
}

当前解析器支持的基础类型:

text
Boolean, String, Binary,
S8, U8, S16, U16, S32, U32, S64, U64, Double

支持的 usage:

text
PermanentPer, PoweroffPer, ResetPer, TemporaryPer,
PoweroffPerRetain, ResetPerRetain, TemporaryPerRetain, Memory

不支持的 baseType、default 类型不匹配、未知 privilege 或非法 usage 会跳过对应属性并打印 parse global prop model failed 警告。全局属性统一上树到 /bmc/kepler/Global,远程持久化表固定使用 t_global,主键形态为 Id:<domain>

步骤八:验证扩展

  1. 构建并升级 Debug 测试镜像;
  2. 检查 bmc.kepler.persistence 和业务组件 D-Bus 服务;
  3. 首次启动读取业务属性,确认 MDS 默认值;
  4. 修改一个非默认值,调用 PersistClient.flush;
  5. 使用主 Read/BatchRead 从业务组件上下文确认远端记录;
  6. 复位 BMC,确认各持久化类型按预期保留或丢失;
  7. 删除对象,确认 active_data 和 deleted_data;
  8. 对 Retain 分别验证普通删除和 delete_retain_data=true
  9. 执行一键日志收集,确认敏感字段脱敏;
  10. 触发数据库备份和损坏恢复测试时,只在可恢复的隔离环境操作。

注意事项

  • 不要直接修改 SQLite 表或 Permanent 原始设备节点;业务数据必须通过 ORM/PersistClient 修改。
  • MDS 主键、表名和字段名一旦发布,应视为持久化兼容契约。
  • 变更字段类型、持久化等级或默认值时,要设计升级、回退和墓碑兼容测试。
  • critical 会增加每次写入备份数据库的 I/O,只用于真正关键的 PoweroffPer 字段。
  • sensitive 的历史标记会持久化;后续改为 false 也可能继续脱敏,这是安全优先行为。
  • Flush、备份和 Dump 都可能产生 I/O 峰值,性能测试要覆盖并发业务写入。

4. 日志说明

4.1 一键日志收集

当前源码能直接确认 Dump 回调在框架传入目录生成:

文件名内容说明
TemporaryPer.jsonTemporaryPer 活动数据,按表和记录重组;敏感字段脱敏。
ResetPer.jsonResetPer 活动数据。
PoweroffPer.jsonPoweroffPer 活动数据。
PermanentPer.jsonPermanentPer 活动数据。
mdb_info.log持久化写入数据量和写入次数统计,按日期、表和组件汇总。
源码不能单独确定它们在 openUBMC 26.2.0 最终一键日志 ZIP 中的相对目录。README 给出过 dump_info/AppDump/persistence/,但正式发布前必须以目标镜像实际收集结果为准。

4.2 运行日志位置

日志/文件源码证据与用途
/var/log/framework/persistence.logdist/config.cfg 声明的组件 logger。实际产品可能汇聚到 framework.log。
/var/log/framework.logdeployConfig 为 framework.service 时的主要框架日志候选;以目标日志路由为准。
/var/log/operation.logConfigManage.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 failedERROR客户端启动恢复失败检查 persistence 服务、属主和数据库
persist app read/save failed, table owner mismatchERROR真实 D-Bus sender 不是表属主核对 table_owner 和服务名
appname(...) save table(...) fail as db files size overrunERRORSave 因数据库超限被静默丢弃立即处理容量;修复后重新触发业务写入
the database size exceeds the upper limit...RUNNING/WARN本地或远程数据库超过上限,存在拒绝服务风险收集分区、数据库大小和写入热点
the database size and persistence service are restored to normalRUNNING/WARN超限状态解除验证此前丢弃的数据是否需要补写
A storm occurs in table ...WARN某表一分钟内短周期提交达到阈值找高频写入源;检查是否把周期数据误设为持久化
database integrity check failedERRORSQLite quick_check 失败禁止直接覆盖;按主库→备份→recover 流程处理
database file in the primary partition ... copy it from the backup partitionWARN/RUNNING主库缺失或损坏,尝试备份恢复检查备份完整性和数据时效
failed to recover from backup databaseWARN新旧备份都不可用保留损坏库,评估 SQLite recover 和业务重建
database per_poweroff.db backup successfulNOTICEPoweroff 周期/触发备份成功核对备份文件时间和 quick_check
persist save failed for backup databaseERROR关键字段主库成功、备库失败立即修复备份区;主调用可能仍显示成功
finish force commit transactions before rebootNOTICE复位前强制提交完成与 Action/关闭数据库日志成对确认
received flash write protection signalNOTICENAND 写保护开启,服务等待 5 秒后强制提交关注后续 finish to commit all transactions
start/finished dumping databasesNOTICE一键导出开始/结束检查五个输出文件和耗时
parse global prop model failedWARN/ERROR全局属性配置中的类型、默认值、usage 或权限非法按接口/属性名修复配置
fetch Dashboard database data failedERROR本地 Dashboard 表读取失败检查本地 persistence.db 和模型兼容

4.4 日志与数据安全

  • 主 Read/Debug.Read 返回的是原始持久化值,不自动脱敏。
  • 只有 Dump 路径会按敏感配置过滤和替换 ******
  • Debug 构建保存的损坏数据库可能包含敏感原值,目录必须受限访问并及时清理。
  • 不要把整个数据库、Read 响应或未审查的一键日志上传到公开社区。
  • 故障单优先提供日志片段、表名、主键哈希、数据库大小、quick_check 结果和时间线。

5. 问题定界指南

5.1 分层定界原则

按以下顺序判断,避免一开始就修改数据库:

  1. 部署层:实际由 framework.service 还是 persistence.service 承载;
  2. D-Bus 层:服务名、对象和接口是否上树;
  3. 客户端层:PersistClient 是否完成 init、恢复和 hook 注册;
  4. 模型层:表名、主键、usage、default、Local/Remote 是否正确;
  5. 授权层:table_owner 与真实 D-Bus sender 是否匹配;
  6. 调度层:事务是否被默认值过滤、上下文跳过、风暴抑制或等待 Flush;
  7. 存储层:数据库大小、完整性、journal、主备文件和 Permanent 设备;
  8. 生命周期层:复位、掉电、恢复出厂语义是否与持久化类型一致;
  9. 导出层:一键收集框架是否实际调用 Dump、输出目录是否可写。

5.2 典型问题定界

现象描述是否为 persistence 问题判断依据关键证据收集方法
bmc.kepler.persistence 不存在可能是部署/框架问题framework 未启动、依赖失败或组件初始化失败systemctl、busctl list/tree、framework 日志
业务属性修改后立即读取正常,复位后恢复旧值高概率为持久化链路问题内存 DB 正常但 Save/Flush/落盘失败或被过滤客户端日志、BatchRead、数据库 mtime、Flush 结果
Read 返回 IncorrectSenderInfo配置/调用者问题table_owner 不允许真实 sendertable_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 只记日志并 returnData validation failed 日志和 ORM 输入

5.3 错误与状态速查表

错误/状态含义可能原因排查建议
IncorrectSenderInfo表属主校验失败服务改名、配置遗漏、直接 shell 调用受限表从真实业务组件调用;更新 table_owner
InvalidValue(filepath)Backup 目标不是目录路径不存在或是普通文件创建权限 0700 的目录
InternalErrorBackup 复制任一文件失败源文件缺失、空间不足、权限/I/OBackup <name> 错误日志
Data validation failed: require not nullINSERT 缺少非空持久化字段MDS 与业务输入不一致补值或修正 notAllowNull
Data validation failed: type mismatchBOOLEAN/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 failedSQLite 损坏掉电、存储介质或旧临时文件不匹配保留现场,按自动恢复链路分析
backup database ... damaged and not open备份不可用备份文件损坏且重新备份失败修复备份分区,确认主库完整性后重建备份
the transaction cache is dirty新一轮开始仍有旧事务调度/提交异常收集线程、锁、前序错误和复现压力

5.4 开启调试日志

优先使用平台标准日志级别工具,不要直接修改源码常量。若目标镜像提供 mdbctl:

bash
$ mdbctl
% attach persistence
% dloglevel

是否支持动态设置、具体命令和输出取决于目标 SDK。正式发布前应在 26.2.0 Debug 镜像验证,并记录恢复原日志级别的命令。

5.5 最小复现与证据收集

5.5.1 无破坏性基础检查

bash
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/null

5.5.2 SQLite 只读检查

bash
/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 单表业务复现

  1. 选择不含敏感数据的测试表和主键;
  2. 记录修改前业务值;
  3. 通过业务组件 ORM 修改为非默认值;
  4. 调用组件 PersistClient.flush;
  5. 从同一业务组件上下文调用 Read/BatchRead;
  6. 复位 BMC,确认值恢复;
  7. 恢复原值并再次 Flush;
  8. 收集时间窗口内 persistence/framework 日志。

5.5.4 风暴复现

仅在测试环境对单一测试表连续产生超过 30 个短周期提交,预期出现:

text
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。