问题描述
Tencent 定制 Redfish multipart 上传接口(POST /redfish/v1/UpdateService/update-multipart)已开发完成,实现在 Tencent/src/lualib/redfish/update_multipart.lua 中作为静态 controller 注册到 Tencent portal_agent。
当前实现:在 update_multipart.lua 的 post() 函数中,直接通过 client:UpdateServiceUpdateServiceStartUpgrade() 调用 StartUpgrade,firmware_mgmt 返回 task_id(例如 2906059982),但 Redfish 的 TaskService 中没有对应的 task 映射。
期望:POST 返回 202 Accepted,Location=/redfish/v1/TaskService/Tasks/{RedfishTaskId},且该 ID 在 TaskService 中可查询。
当前返回:直接使用 firmware_mgmt 的 task_id,访问 /redfish/v1/TaskService/Tasks/{id} 时 Redfish 框架通过 ProcessingFlow 调用 GetTaskId(firmware_task_id) 返回 0,导致返回 404。
环境信息
- 软件版本:OpenUBMC(Tencent 定制分支)
- 平台:
已知架构
- Redfish 标准流程(以
SimpleUpdate 为例):
- HTTP POST → redfish app 的
load_controller.lua → action_on_post() 处理
- ProcessingFlow 中
"Type": "Task" 步骤触发 create_new_task()(来自 redfish.protocol.task_mgnt)
create_new_task 在进程内 g_task_rsc_array 中分配槽位,建立 firmware_mgmt task_id ↔ Redfish task_id 映射
- 后续 ProcessingFlow 步骤调用
GetTaskId(firmware_task_id) 返回 Redfish task_id
register_redfish_task 在 redfish app 初始化时 fork 监控线程,监听 firmware_mgmt 的 PropertiesChanged 信号
- 我们的定制流程:
- HTTP POST → Tencent portal_agent → 静态 controller
update_multipart:post()
- 直接调用
client:UpdateServiceUpdateServiceStartUpgrade()(bypass redfish ProcessingFlow)
- 没有经过
action_on_post(),没有调用 create_new_task(),没有建立映射
- 虽然 firmware_mgmt 发出了 PropertiesChanged 信号,但
register_redfish_task 的回调无法正确创建映射(可能是 initiator/context 不匹配)
- 跨进程限制:
- redfish app 和 Tencent app 是不同的 skynet 进程(不同 harbor),无法直接
skynet.call
redfish.protocol.task_mgnt 模块在 Tencent 的 package.path 中不可用
- 动态添加
package.path 后能找到 task_mgnt.lua,但其内部依赖 redfish_utils 等模块仍找不到
- 即使 require 成功,
g_task_rsc_array 是进程内内存,跨进程不可见
请教的问题
在 OpenUBMC 的 Tencent 定制场景下,当 portal_agent(非 redfish app)通过 D-Bus client 直接调用 StartUpgrade 后,如何创建合法的 Redfish task 映射,使得 GetTaskId 能返回正确的 Redfish task ID?
具体子问题:
register_redfish_task 监听 firmware_mgmt 的什么信号?为什么从 Tencent 侧调用 StartUpgrade 时它没有自动创建映射?
- 是否可以通过 D-Bus 方式(busctl/gdbus)直接调用 redfish app 内部的
create_new_task?或者是否有其他 D-Bus 接口可以建立 task 映射?
- 在 Tencent portal_agent 中是否有办法调用 redfish app 的 task_mgnt 模块?(例如通过 skynet 跨 harbor 通信、MQ、或某种代理机制)
- 是否有其他厂商(Baidu/Alibaba/ByteDance)在定制接口中遇到过类似问题?最佳实践是什么?
- 如果上述方案都不可行,还有什么推荐的架构方案来实现 multipart upload 且正确定义 Redfish task?
答案内容由AI生成,仅供参考:
总结**:利用 D-Bus 暴露的 TaskMgmt API(create_task/update_task)是解决跨进程创建 Redfish 任务映射的直接、标准方法。该方案无需依赖进程内内存或 skynet 通信,且与 Redfish 标准服务兼容。
点击此处查看详细分析解答
根据您提供的问题描述和已知的架构背景,结合提供的知识图谱(KG)与文档片段(DC),以下是对各子问题的分析及可行方案建议。
1. register_redfish_task 监听的信号及为何未自动创建映射
依据上下文:知识图谱中提及 task_mgmt.lua 会“记录成功更新运行中的任务并包含进度”,以及 TaskMgmt 负责“创建、更新、销毁任务”。文档片段1(libmcpp)明确指出任务以 D-Bus 对象形式暴露(接口 bmc.kepler.TaskService.Task),外部系统可通过 D-Bus 查询异步任务的执行状态。
在标准流程中,register_redfish_task 会监听 firmware_mgmt 对象的 PropertiesChanged 信号(参见用户问题描述中的已知架构)。该信号由 firmware_mgmt 在升级任务状态变化时发出。但由于您的 Tencent portal_agent 在调用 StartUpgrade 时,并未经过 Redfish app 内部的 action_on_post() 和 ProcessingFlow,因此 register_redfish_task 的回调无法正确关联到 Tencent 侧发起的任务。 换句话说,register_redfish_task 预期调用方来自 Redfish app 自身或其管理的 controller,而 Tencent app 属于不同的 skynet 进程,其发送的 D-Bus 调用可能未被 Redfish app 内的监控线程正确识别(可能缺少 initiator 或上下文信息)。
结论:上下文未提供关于 register_redfish_task 具体过滤条件的详细说明,但可以推断该机制依赖于 Redfish app 内部构建的 g_task_rsc_array 映射表,而 Tencent app 的调用未触发该表的构建。
2. 通过 D-Bus 直接调用 Redfish app 内部的 create_new_task?
关键依据:文档片段1(类型:libmcpp)中列出了 TaskMgmt 的 D-Bus API,包括:
| 方法 |
参数 |
返回 |
说明 |
create_task |
parent_path, timeout_mins 等(可选) |
tuple<result, error, task_id> |
创建任务,返回任务ID |
update_task |
task_id, data(dict) |
UpdateResult |
更新任务属性(Progress/State/Status等) |
destroy_task |
task_id |
void |
销毁任务,释放 D-Bus 对象 |
get_task_obj |
task_id |
task_object* |
获取任务对象指针 |
create_new_task 是 Redfish app 进程内的 lua 函数,并非 D-Bus 接口,无法直接跨进程调用。
- 但 D-Bus 提供了
bmc.kepler.TaskService.Task 接口的 create_task 方法,您可以通过 busctl 或 gdbus 调用它(例如:busctl call bmc.kepler.TaskService /bmc/kepler/TaskService bmc.kepler.TaskService.Task create_task ...)。
- 此调用返回的 task_id 即为 Redfish 标准任务 ID,可将其直接用于 Location 中(如
/redfish/v1/TaskService/Tasks/{task_id})。
- 调用后,该任务对象会发出
PropertiesChanged 信号,能被 register_redfish_task 正确捕获(如果该监听器订阅了该 D-Bus 路径的信号)。
推荐做法:在 update_multipart.lua 的 post() 函数中,顺序执行:
- 通过 D-Bus 调用
bmc.kepler.TaskService.Task 的 create_task 方法,获得 Redfish task ID。
- 存储该 Redfish task ID 与
firmware_mgmt 返回的 task_id 的映射(例如在 Tencent app 的内存中或通过共享 D-Bus 对象)。
- 随后调用
client:UpdateServiceUpdateServiceStartUpgrade()(直接传递内部 task_id)。
- 在后续的
update_task 或监控过程中,根据 firmware_mgmt 的进度、状态更新对应的 Redfish task 对象。
3. Tencent portal_agent 如何调用 Redfish app 的 task_mgnt 模块?
依据上下文:
- 知识图谱指出
TaskMgmt 是“负责管理异步任务的 D-Bus 服务环境”,并且 TaskMgmt implements Redfish TaskService。
- 文档片段1明确将
create_task、update_task、destroy_task 暴露为 D-Bus 方法。
由于 D-Bus 是系统级通信层,不同 skynet 进程均可通过同一个 D-Bus 总线(system bus 或 session bus)调用。您无需直接调用 Redfish app 内部的 task_mgnt.lua,而是通过 D-Bus 客户端 调用这些标准接口即可。
具体步骤:
- 在 Tencent app 中通过
busctl 或 lua 的 dbus 库连接到 system bus。
- 调用
/bmc/kepler/TaskService 上的 bmc.kepler.TaskService.Task 接口。
- 使用
create_task 方法(必须提供合法的 parent_path,可参照已有 ProcessingFlow 配置填入,如 /bmc/kepler/UpdateService)。
- 该方法返回的 task_id 即 Redfish 标准任务 ID。
4. 其他厂商的最佳实践
上下文中没有提及任何其他厂商(Baidu/Alibaba/ByteDance)的实现或最佳实践。因此无法就这部分给出有根据的答案。但根据已知的 OpenUBMC 架构,定制接口通常有两种路线:
- 路线A:尽可能复用现有 ProcessingFlow 映射,避免绕过标准流程。
- 路线B:若必须绕过,则直接通过 D-Bus 调用 TaskMgmt 的 API 来创建/更新任务,保持与 Redfish 标准的兼容性。
您的场景属于路线B,且 create_task D-Bus API 提供了可行路径。
5. 推荐的架构方案(综合上下文)
基于以上分析,给出一个可行的方案流程:
步骤1:在 Tencent portal_agent 中调用 D-Bus 创建 Redfish 任务
在 update_multipart.lua 的 post() 函数中,添加对 bmc.kepler.TaskService.Task.create_task 的调用:
local ret, err, redfish_task_id = dbus.call(
"bmc.kepler.TaskService",
"/bmc/kepler/TaskService",
"bmc.kepler.TaskService.Task",
"create_task",
{ parent_path, ... } -- 根据实际需求提供参数
)
-- 检查 ret, err
得到的 redfish_task_id 即为可供 Redfish TaskService 查询的合法 ID。
步骤2:建立内部映射
在 Tencent app 中保存一个映射表:{ firmware_task_id => redfish_task_id },以便在后续监控进度时调用 update_task 更新 Redfish 任务对象的 Progress/State/Status。
步骤3:返回 202 Accepted
post() 函数响应中设置 HTTP 状态码 202,并在 Location header 中填入:
Location: /redfish/v1/TaskService/Tasks/{redfish_task_id}
步骤4:监控并更新任务
使用 D-Bus 的 get_task_obj 或继续通过 update_task 方法,根据 firmware_mgmt 返回的进度信号不断更新 Redfish 任务属性(百分比、状态、消息)。
步骤5:任务完成时
调用 update_task 设置 TaskState 为 Completed 或 Exception,并设置合适的 Messages 内容(可参考知识图谱中关于 Update_Task 的 Message/State 属性描述)。
需要补充的信息
create_task 方法的具体参数(如 parent_path 的格式)在上下文中未完整给出。建议参考标准 ProcessingFlow 中 Task 类型的配置,例如 /bmc/kepler/UpdateService/TaskService/Tasks/{task_id} 作为父路径。您可能需要查阅 OpenUBMC 的源码或接口定义文件。
- 关于
register_redfish_task 的精确过滤条件,上下文不足,建议在后续开发中通过调试信号来确认。
总结:利用 D-Bus 暴露的 TaskMgmt API(create_task/update_task)是解决跨进程创建 Redfish 任务映射的直接、标准方法。该方案无需依赖进程内内存或 skynet 通信,且与 Redfish 标准服务兼容。
vyasa
(欧文健)
3
接口配置ProcessingFlow的Type是否为Task呢。接口配置可以参考:Redfish接口映射配置指南 | 文档中心 | openUBMC