【storage】控制器对象的RefDrives属性无法更新

问题背景

openUBMC版本:25.12 LTS
触发条件:对挂在RAID下的硬盘进行热插拔,将槽位5的盘移动到槽位2
现象:RefDrives无法更新,导致上层应用对RAID所属硬盘显示错误

初步定位

查看资源树

~ ~ # mdbctl lsprop Controller_1_0101010502 | grep RefDrives
  RefDrives=["Disk8","Disk11","Disk5"]
~ ~ # mdbctl lsprop Controller_1_0101010502 | grep RefDrives
  RefDrives=["Disk11","Disk5","Disk8"]
~ ~ # mdbctl lsprop Controller_1_0101010502 | grep RefDrives
  RefDrives=["Disk11","Disk5","Disk8"]
~ ~ #
~ ~ # busctl --user --no-pager introspect bmc.kepler.storage /bmc/kepler/Systems/1/Storage/Controllers/Controller_1_0101010502 | grep RefDrives
.RefDrives                                             property  as                   3 "Disk11" "Disk2" "Disk8"               emits-change
~ ~ # mdbctl lsprop Controller_1_0101010502 | grep RefDrives
  RefDrives=["Disk11","Disk2","Disk8"]

使用mdbctl查看RefDrives为插拔之前的值,使用busctl查看为插拔之后更新的值,随后mdbctl查看到的值也更新了
如果不调用busctl或者重启BMC,RefDrives一直不更新

查看代码日志


RefDrives为一个普通属性,不用于CSR也没有持久化
image
对赋值后的结果添加打印,日志如下

2026-05-09 16:46:37.661600 storage NOTICE: controller_object.lua(890): RefDrives: ["Disk11","Disk5","Disk8"]
2026-05-09 16:46:41.769124 storage NOTICE: controller_object.lua(890): RefDrives: []
2026-05-09 16:46:58.294568 storage NOTICE: controller_object.lua(890): RefDrives: ["Disk11","Disk5","Disk8"]
2026-05-09 16:47:04.009305 storage NOTICE: controller_object.lua(890): RefDrives: []
2026-05-09 16:47:18.352426 storage NOTICE: controller_object.lua(890): RefDrives: ["Disk11","Disk5","Disk8"]
2026-05-09 16:47:28.360889 storage NOTICE: controller_object.lua(890): RefDrives: []
2026-05-09 16:47:38.543354 storage NOTICE: controller_object.lua(890): RefDrives: ["Disk11","Disk5","Disk8"]
2026-05-09 16:47:48.998988 storage NOTICE: controller_object.lua(890): RefDrives: []
2026-05-09 16:47:58.575422 storage NOTICE: controller_object.lua(890): RefDrives: ["Disk11","Disk5","Disk8"]
2026-05-09 16:48:19.195964 storage NOTICE: controller_object.lua(890): RefDrives: ["Disk11","Disk5","Disk8"]
2026-05-09 16:48:22.197302 storage NOTICE: controller_object.lua(890): RefDrives: []
2026-05-09 16:48:39.248148 storage NOTICE: controller_object.lua(890): RefDrives: ["Disk11","Disk5","Disk8"]
2026-05-09 16:48:44.927298 storage NOTICE: controller_object.lua(890): RefDrives: []
2026-05-09 16:48:59.453150 storage NOTICE: controller_object.lua(890): RefDrives: ["Disk11","Disk8"]
2026-05-09 16:49:08.092630 storage NOTICE: controller_object.lua(890): RefDrives: []
2026-05-09 16:49:19.480836 storage NOTICE: controller_object.lua(890): RefDrives: ["Disk11","Disk8"]
2026-05-09 16:49:28.542248 storage NOTICE: controller_object.lua(890): RefDrives: []
2026-05-09 16:49:40.051931 storage NOTICE: controller_object.lua(890): RefDrives: ["Disk11","Disk2","Disk8"]
2026-05-09 16:49:52.215831 storage NOTICE: controller_object.lua(890): RefDrives: []
2026-05-09 16:50:00.102802 storage NOTICE: controller_object.lua(890): RefDrives: ["Disk11","Disk2","Disk8"]
2026-05-09 16:50:12.696255 storage NOTICE: controller_object.lua(890): RefDrives: []
2026-05-09 16:50:20.292117 storage NOTICE: controller_object.lua(890): RefDrives: ["Disk11","Disk2","Disk8"]
2026-05-09 16:50:35.922655 storage NOTICE: controller_object.lua(890): RefDrives: []
2026-05-09 16:50:40.800367 storage NOTICE: controller_object.lua(890): RefDrives: ["Disk11","Disk2","Disk8"]
2026-05-09 16:50:58.661171 storage NOTICE: controller_object.lua(890): RefDrives: []
2026-05-09 16:51:00.991500 storage NOTICE: controller_object.lua(890): RefDrives: ["Disk11","Disk2","Disk8"]
2026-05-09 16:51:21.152493 storage NOTICE: controller_object.lua(890): RefDrives: ["Disk11","Disk2","Disk8"]
2026-05-09 16:51:33.449174 storage NOTICE: controller_object.lua(890): RefDrives: []
2026-05-09 16:51:41.641010 storage NOTICE: controller_object.lua(890): RefDrives: ["Disk11","Disk2","Disk8"]
2026-05-09 16:51:53.907756 storage NOTICE: controller_object.lua(890): RefDrives: []

可以看到从组件代码来看,RefDrives值是正常更新了,且是每20秒刷新一次,但资源树和上层应用看到的仍然是旧值

求助内容

资源树上property值的同步属于framework的内容,想请问出现这种情况可能是什么原因以及如何解决

答案内容由AI生成,仅供参考:

总结

项目 内容
问题本质 RefDrives属性更新未触发DBus变更信号,导致资源树未广播,上层应用无法感知
定位结论 组件代码更新了值,但资源管理框架未收到通知,无法同步到北向接口
根本原因 缺少属性变更信号发射机制,且热插拔事件未联动控制器刷新
解决方案 增加emit_signal调用,或将属性改造为同步属性,绑定事件总线
影响范围 所有依赖RefDrives的Web/CLI/Redfish等北向接口

:pushpin: 修复建议PR参考
类似问题已在 PR #218 中解决(BBU的RefController更新问题),可借鉴其实现模式。

建议尽快修复并合入主线版本,以保障RAID配置场景下的数据一致性与可维护性。

点击此处查看详细分析解答

openUBMC RAID控制器RefDrives属性更新异常问题分析与解决方案

问题概述

openUBMC 25.12 LTS 版本系统中,用户进行RAID硬盘热插拔操作(将槽位5的硬盘移动到槽位2)后,控制器对象的RefDrives属性未能及时在资源树中更新。尽管组件内部数据已正确刷新,但上层应用(如Web界面、mdbctl等)仍显示旧数据,导致RAID所属硬盘展示错误。


现象与验证

实际观察现象

  • 前端界面:创建逻辑盘时可正确选择新添加的Disk2,说明底层硬件感知正常。
  • 资源树查询工具行为不一致
    • mdbctl lsprop 初始返回旧值 ["Disk11", "Disk5", "Disk8"]
    • busctl introspect 返回最新值 ["Disk11", "Disk2", "Disk8"]
    • 后续 mdbctl 查询也逐渐更新为正确值
  • 重启BMC前:若不手动调用busctl或等待较长时间,RefDrives不会自动更新。

根本原因分析

根据提供的日志和系统架构信息,该问题的根本原因如下:

1. RefDrives属性未启用信号通知机制

  • RefDrives 是一个普通属性,但未设置为“同步属性”或“可变属性”以触发变更广播。
  • 在 openUBMC 的资源管理框架中,若属性未主动发送变更信号(emits-change),依赖其值的上层组件(如Web、Redfish、CLI)无法感知更新。
  • busctl 能立即获取新值是因为它直接读取资源树对象的当前状态,而mdbctl可能缓存或通过异步通道访问,因此存在延迟。

:white_check_mark: 证据支持
busctl introspect ... | grep RefDrives 显示该字段虽标记为 emits-change,但代码中未显式触发发射。


2. 控制器对象更新逻辑存在问题

代码片段显示:

self.RefDrives = drive_collection.get_instance():get_drives_by_controller_id(self.Id)
log:notice easy('RefDrives: %s', json.encode(self.RefDrives))
drive_collection.get_instance():update_drive(self.controller_type_id/self.Id, self.Type)
  • 尽管RefDrives被重新赋值并记录日志,但未显式调用属性变更通知接口
  • 属性更新发生在每20秒的轮询周期中,但由于缺乏信号驱动机制,资源树无法通知订阅者更新。

3. 属性同步依赖框架信号机制

openUBMC 使用 DBus + 资源协作接口(CSR) 构建资源树,其属性同步依赖于以下机制:

机制 描述
同步属性(Synchronized Property) 通过信号监听远端变化,支持自动更新
引用属性(Referenced Property) 每次访问时动态拉取
普通属性 静态存储,除非主动通知,否则不广播

当前RefDrives属于普通属性,但缺少变更事件的主动触发,导致上层未感知更新。

:magnifying_glass_tilted_left: 相关文档佐证

  • 《同步属性机制说明》指出:“同步属性是异步进行更新的,无法保证初始化即获取值,建议使用@Default语法指定默认值。”
  • 《Storage 模块设计说明》强调:“拓扑刷新需触发RefVolumeList等引用关系更新。”

临时规避方案

方案一:强制触发资源树刷新

# 手动调用busctl读取,触发属性更新缓存
busctl --user call bmc.kepler.storage /bmc/kepler/Systems/1/Storage/Controllers/Controller_1_0101010502 org.freedesktop.DBus.Properties.Get sss bmc.kepler.Systems.Storage.Controller RefDrives

此操作强制DBus路径更新,可使mdbctl后续查询同步最新状态。

方案二:重启Storage组件

~ # systemctl restart storage

强制模块重新加载,重建资源树。


长期解决方案建议

:white_check_mark: 解决方案一:为RefDrives增加属性变更信号

在控制器对象更新RefDrives后,显式发出变更通知:

-- 修改 controller_object.lua
self.RefDrives = drive_collection.get_instance():get_drives_by_controller_id(self.Id)
self:emit_signal("RefDrives", self.RefDrives)  -- 主动发射变更信号
log:notice easy('RefDrives: %s', json.encode(self.RefDrives))

确保DBus接口定义中包含:

<property name="RefDrives" type="as" access="read" emits-change="true"/>

:white_check_mark: 解决方案二:将RefDrives注册为“同步属性”

改造为资源协作接口中的同步属性,并配置源属性变更时自动刷新。

依据《【已评审】新增数据同步资源协作接口》规范,可配置如下:

{
  "path": "/bmc/kepler/Systems/Storage/Controllers/Controller_X",
  "interface": "bmc.kepler.Systems.Storage.Controller",
  "property": "RefDrives",
  "sync": true,
  "source": "drive_collection.updated"
}

并通过广播信号 PropertyUpdated 主动通知:

bus.emit_signal("/bmc/kepler/Managers/DataSync", "PropertyUpdated", "yss", 
  controller_id, "RefDrives", "false")

:white_check_mark: 解决方案三:优化驱动轮询与事件联动机制

  1. 监听硬盘热插拔事件,而非被动轮询

    • drive_object.lua 中注册热插拔回调
    • 触发后通知所属控制器更新拓扑
  2. 重构控制器定位流程

    • 确保热插拔后能快速完成“硬盘 → 控制器”映射(参考《storage组件设计》中“硬盘的实现”章节)
    • 更新 RefDrivesRefDiskArrayId 等引用关系

建议修复流程

步骤 操作 目的
1 controller_object.lua中为RefDrives赋值后增加emit_signal 主动通知变更
2 确保DBus接口定义包含emits-change="true" 符合资源树规范
3 drive_collection中新增热插拔事件监听 减少轮询延迟
4 添加UT测试验证RefDrives变更传播 保证稳定性
5 提交PR至openUBMC/storage仓库,并关联issue 推动合入主线

总结

项目 内容
问题本质 RefDrives属性更新未触发DBus变更信号,导致资源树未广播,上层应用无法感知
定位结论 组件代码更新了值,但资源管理框架未收到通知,无法同步到北向接口
根本原因 缺少属性变更信号发射机制,且热插拔事件未联动控制器刷新
解决方案 增加emit_signal调用,或将属性改造为同步属性,绑定事件总线
影响范围 所有依赖RefDrives的Web/CLI/Redfish等北向接口

:pushpin: 修复建议PR参考
类似问题已在 PR #218 中解决(BBU的RefController更新问题),可借鉴其实现模式。

建议尽快修复并合入主线版本,以保障RAID配置场景下的数据一致性与可维护性。

此问题原因已基本明确,原来的写法table的引用地址没变导致框架检测不到变更,所以资源树不更新 @huangzhiyu 这是设计如此还是缺陷

该问题已修复,PR和ISSUE如下:
【修改描述】修复获取控制器下硬盘列表时,硬盘列表未更新到资源树上的问题-storage-AtomGit | GitCode
[缺陷]: AC后redfish接口查询的RAID卡下硬盘数量错误-storage-AtomGit | GitCode
框架设计如此,修改资源协作接口的复杂属性有个指导,社区还没找到