定制Redfish multipart上传接口如何创建合法的Redfish task映射

问题描述

Tencent 定制 Redfish multipart 上传接口(POST /redfish/v1/UpdateService/update-multipart)已开发完成,实现在 Tencent/src/lualib/redfish/update_multipart.lua 中作为静态 controller 注册到 Tencent portal_agent。

当前实现:在 update_multipart.luapost() 函数中,直接通过 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 定制分支)
  • 平台:

已知架构

  1. Redfish 标准流程(以 SimpleUpdate 为例):
  • HTTP POST → redfish app 的 load_controller.luaaction_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 信号
  1. 我们的定制流程
  • 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 不匹配)
  1. 跨进程限制
  • 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?

具体子问题:

  1. register_redfish_task 监听 firmware_mgmt 的什么信号?为什么从 Tencent 侧调用 StartUpgrade 时它没有自动创建映射?
  2. 是否可以通过 D-Bus 方式(busctl/gdbus)直接调用 redfish app 内部的 create_new_task?或者是否有其他 D-Bus 接口可以建立 task 映射?
  3. 在 Tencent portal_agent 中是否有办法调用 redfish app 的 task_mgnt 模块?(例如通过 skynet 跨 harbor 通信、MQ、或某种代理机制)
  4. 是否有其他厂商(Baidu/Alibaba/ByteDance)在定制接口中遇到过类似问题?最佳实践是什么?
  5. 如果上述方案都不可行,还有什么推荐的架构方案来实现 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.luapost() 函数中,顺序执行:

  1. 通过 D-Bus 调用 bmc.kepler.TaskService.Taskcreate_task 方法,获得 Redfish task ID。
  2. 存储该 Redfish task ID 与 firmware_mgmt 返回的 task_id 的映射(例如在 Tencent app 的内存中或通过共享 D-Bus 对象)。
  3. 随后调用 client:UpdateServiceUpdateServiceStartUpgrade()(直接传递内部 task_id)。
  4. 在后续的 update_task 或监控过程中,根据 firmware_mgmt 的进度、状态更新对应的 Redfish task 对象。

3. Tencent portal_agent 如何调用 Redfish app 的 task_mgnt 模块?

依据上下文

  • 知识图谱指出 TaskMgmt 是“负责管理异步任务的 D-Bus 服务环境”,并且 TaskMgmt implements Redfish TaskService
  • 文档片段1明确将 create_taskupdate_taskdestroy_task 暴露为 D-Bus 方法。

由于 D-Bus 是系统级通信层,不同 skynet 进程均可通过同一个 D-Bus 总线(system bus 或 session bus)调用。您无需直接调用 Redfish app 内部的 task_mgnt.lua,而是通过 D-Bus 客户端 调用这些标准接口即可。

具体步骤

  1. 在 Tencent app 中通过 busctl 或 lua 的 dbus 库连接到 system bus。
  2. 调用 /bmc/kepler/TaskService 上的 bmc.kepler.TaskService.Task 接口。
  3. 使用 create_task 方法(必须提供合法的 parent_path,可参照已有 ProcessingFlow 配置填入,如 /bmc/kepler/UpdateService)。
  4. 该方法返回的 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.luapost() 函数中,添加对 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 设置 TaskStateCompletedException,并设置合适的 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 标准服务兼容。

接口配置ProcessingFlow的Type是否为Task呢。接口配置可以参考:Redfish接口映射配置指南 | 文档中心 | openUBMC