*openUBMC 支持带外升级自研RAID卡管理的硬盘详细设计说明书*

<table>
    <tr>
        <td>所属SIG组:</td>
        <td>hardware</td>
    </tr>
    <tr>
        <td>落入版本:</td>
        <td>26.03</td>
    </tr>
    <tr>
        <td>设计人员:</td>
        <td>hmh</td>
    </tr>
    <tr>
        <td>日期:</td>
        <td>2026/01/21</td>
    </tr>
</table>


**Copyright © 2026 openUBMC Community**

您对&quot;本文档&quot;的复制，使用，修改及分发受木兰宽松许可证, 第2版协议(以下简称&quot;MulanPSL2&quot;)的约束。
为了方便用户理解，您可以通过访问<https://license.coscl.org.cn/MulanPSL2>了解MulanPSL2的概要 (但不是替代)。
MulanPSL2的完整协议内容您可以访问如下网址获取：<https://license.coscl.org.cn/MulanPSL2>。

**改版记录**

<table>
    <tr>
        <th>日期</th>
        <th>修订版本</th>
        <th>修订描述</th>
        <th>作者</th>
        <th>审核</th>
    </tr>
    <tr>
        <td>2026/01/21</td>
        <td>1.0</td>
        <td>新增支持带外对自研RAID卡管理硬盘进行固件升级</td>
        <td>xxx</td>
        <td>xxx</td>
    </tr>
    <tr>
        <td>2026/01/27</td>
        <td>1.1</td>
        <td>补充硬盘升级进度上报与实现细节（按目标硬盘数量平滑推进）；对齐当前实现的部分异常场景行为描述</td>
        <td>xxx</td>
        <td>xxx</td>
    </tr>
</table>

**List of abbreviations**  **缩略语清单** ：

<table>
    <tr>
        <th>Abbreviations 缩略语</th>
        <th>Full spelling 英文全名</th>
        <th>Chinese explanation 中文解释</th>
    </tr>
    <tr>
        <td>RAID</td>
        <td>Redundant Array of Independent Disks</td>
        <td>独立磁盘冗余阵列</td>
    </tr>
    <tr>
        <td>OOB</td>
        <td>Out-of-band</td>
        <td>带外管理</td>
    </tr>
    <tr>
        <td>UpdateService</td>
        <td>Firmware Update Service</td>
        <td>固件升级服务</td>
    </tr>
</table>

[TOC]

# 1.功能分析
## 1.1 功能背景
<!-- 描述该需求的来源或背景，比如：支撑XXX功能、XXX优化等；以及该需求对用户（含组件）带来什么具体价值，如果没有该需求，对用户（含组件）带来什么损失； -->
当前自研RAID卡管理的硬盘固件升级通常依赖OS侧工具或SP工具，需要重启系统，对业务产生影响、运维成本高、效率低.
本需求通过BMC带外通道提供“自研RAID卡管理硬盘”的固件升级能力，使运维人员可通过北向接口发起升级、查询进度/结果，并与固件管理组件的统一升级框架对齐，提升固件治理的一致性与可维护性。

## 1.2 功能描述
<!-- 描述该需求交付的整体功能，主要实现XXX功能，解决XXX问题，明确方案如何实现 -->
实现对“自研RAID卡管理的硬盘”的带外固件升级能力，覆盖升级准备、升级执行、升级完成及可选的生效等阶段。

方案概述：
1. 复用固件管理组件（firmware_mgmt）升级框架，通过UpdateService信号驱动升级流程（Prepare/Process/Finish/Active）。
2. platform.sr配置新增硬盘固件类型对象`FirmwareComponentInfo_Drive`（ComponentID=34，ComponentIDEx=4294967295，Name=Drive），该对象会通过自发现上报到firmware_mgmt，作为硬盘固件类型标识。
3. 升级包为hpm包，解压后包含`FirmwareX`目录（表示第X个固件）以及`update.cfg`配置文件。firmware_mgmt解析`update.cfg`中的`ComponentID/ComponentIDEx`，匹配到`FirmwareComponentInfo_Drive`后，将其`Name`（即Drive）作为`FirmwareType`作为PrepareSignal参数，同时将`update.cfg`路径一并传递给storage。
4. storage组件作为“硬盘固件升级观察者（observer）”，按`FirmwareType=Drive`识别本信号用于硬盘升级；在Prepare阶段解析`update.cfg`获取`Model`数组（本固件包支持升级的硬盘型号列表），遍历在位硬盘对象，筛选`Model`命中且`RefControllerTypeId`为自研RAID卡管理的硬盘，作为本次升级目标（可为多盘）。
5. storage在Process/Finish阶段对目标硬盘下发升级、上报进度/结果，并在必要时处理生效阶段

## 1.3 功能场景
1) 场景触发条件及对象：运维人员/网管通过Redfish/WEBREST发起硬盘固件升级；或由上层平台系统批量编排升级任务。
2) 使用时间及频度：按版本发布/问题修复节奏进行，可能出现批量升级与维护窗口集中升级。

典型场景：
- 自研RAID卡在位，槽位硬盘可被管理，带外上传升级包后对指定硬盘发起升级，持续上报进度，完成后返回结果。
- 异常场景：包不匹配、目标盘不在位、升级中掉盘、升级中BMC复位/整机AC。

## 1.4 功能列表
<!-- 描述该需求交付的功能列表，内容包括：列出功能详细描述，标题、描述。 -->
| 功能编号 | 功能标题 | 功能描述 |
| ------- | ------- | -------- |
| 1 | 带外硬盘固件升级入口 | 通过UpdateService信号驱动，对自研RAID卡管理硬盘支持带外升级 |
| 2 | 升级状态上报 | 在升级准备/执行/完成/生效阶段上报状态、进度与错误信息 |
| 3 | 目标识别与校验 | 根据请求参数定位目标硬盘，并校验包与目标的匹配关系 |
| 4 | 异常处理与可恢复性 | 覆盖包非法、目标不存在、升级中断、重启/掉电等异常场景 |
| 5 | 北向接口联动 | Redfish/WEBREST展示升级任务与结果，并可查询固件清单信息 |

# 2.功能设计
## 2.1 总体方案分析
<!-- 描述该方案的总体设计（注：相关输出方案可同步刷新到各组件仓） -->
总体采用“升级主题（upgrade_subject）+ 观察者（observer）”的事件分发模式：
1. 固件管理组件通过UpdateService发布升级信号（Prepare/Process/Finish），并可发布Active生效信号。
2. upgrade_subject订阅升级信号并按firmware_type进行分发，调用对应observer的回调方法。
3. platform配置新增`FirmwareComponentInfo_Drive`对象并通过自发现上报到firmware_mgmt，用于将`update.cfg`中的`ComponentID/ComponentIDEx`映射为`FirmwareType=Drive`。
4. firmware_mgmt在Prepare阶段解析hpm包内的`update.cfg`，匹配到`FirmwareComponentInfo_Drive`后，将`FirmwareType=Drive`与`update.cfg`路径作为PrepareSignal参数传递。
5. storage组件实现“硬盘固件升级observer”，并向upgrade_subject注册`firmware_type=Drive`，在回调中完成目标筛选、升级下发及状态回传。

### 2.1.1 方案详细设计
#### 2.1.1.1 方案概述
<!-- 描述该方案的整体实现，内容包括：涉及的关键点，实现策略等 -->
关键点如下：
1. **信号订阅与分发**：upgrade_subject负责订阅UpdateService/FirmwareActive信号并按firmware_type分发，storage仅需注册observer并实现回调。
2. **硬盘固件类型识别**：platform新增`FirmwareComponentInfo_Drive`（ComponentID=34，ComponentIDEx=4294967295，Name=Drive），firmware_mgmt匹配`update.cfg`后将`FirmwareType=Drive`传递给storage，storage以此识别该升级信号为“硬盘升级”。
3. **目标筛选**：storage在Prepare阶段使用入参`update.cfg`路径解析配置，读取`Model`数组（支持升级的硬盘型号列表），遍历在位Drive对象，筛选满足`Drive.Model`命中`Model`数组且`Drive.RefControllerTypeId`为自研RAID卡管理的硬盘，作为本次升级目标（可为多盘）。
3. **升级流程分段**：整体分为**升级阶段**（Prepare/Process/Finish）与**生效阶段**（Active）。升级阶段完成后新固件已写入硬盘但尚未被使用、固件版本不更新；生效阶段完成后硬盘才使用新固件并更新固件版本。
   - Prepare：校验包合法性、权限/属主设置（如需）、解析包元信息、校验目标与包是否匹配、准备控制器/通道资源。
   - Process：下发升级并持续上报进度（Running，进度百分比）。
   - Finish：收尾处理，注册生效对象、持久化待生效列表、释放资源，回传最终结果（**不刷新硬盘版本信息**，版本在生效后更新）。
   - Active（生效阶段）：若升级要求特定生效条件（如掉电生效/重启生效），注册/更新生效策略并处理Active信号；生效完成后硬盘使用新固件并更新固件版本。
4. **状态上报**：升级阶段内通过固件管理组件的状态更新接口回传状态（如Running/Completed/Exception）与进度。
5. **并发与互斥**：目标可能为多块硬盘（Model列表匹配），需限制同一控制器下的并发升级，必要时串行化执行，避免控制器资源竞争。

#### 2.1.1.1.1 升级包结构与关键配置
升级包为hpm包，解压后目录结构如下（示例）：
- `Firmware1/`：表示第1个固件内容目录（可能存在Firmware2/Firmware3等）
- `update.cfg`：升级配置文件，承载固件包适配信息与升级元数据

其中`update.cfg`在本方案中的关键字段：
- `ComponentID`、`ComponentIDEx`：用于firmware_mgmt匹配platform中对应FirmwareComponentInfo对象，并将其`Name`作为`FirmwareType`传递给storage（硬盘场景为Drive）
- `Model`：数组，表示本固件包支持升级的硬盘型号列表；storage通过该列表筛选在位硬盘目标

#### 2.1.1.2 开发视图
<!-- 开发视图面向系统开发及软件管理，描述系统代码结构，构建结构的视图，主要解决系统技术实现和开发的问题，它依托逻辑视图，描述代码、构建结构 -->
```mermaid
classDiagram
    class firmware_mgmt {
        + UpgradePrepareSignal
        + UpgradeProcessSignal
        + UpgradeFinishSignal
        + ActiveProcessSignal
        + PrepareReply()
        + ProcessReply()
        + UpdateUpgradeStatus()
        + ActiveProcessReply()
        + RegisterActiveAction()
        + DeleteActiveAction()
    }

    class storage_drive_fw_upgrade {
        + on_upgrade_prepare()
        + on_upgrade_process()
        + on_upgrade_finish()
        + on_active_process()
        + 配置解析与筛选
        + 目标硬盘筛选
        + 升级任务管理
        + 已升级成功硬盘表
    }

    class storage {
        + Drive对象集合
        + RAID控制器对象集合
        + 目标定位与校验
        + 升级接口调用
        + 生效接口调用
    }

    class bus_monitor_service {
        + on_smbios_status_changed信号
        + OS状态监听
    }

    class fructrl_handle {
        + set_power_off_lock_until_success()
        + 下电锁管理
    }

    class database {
        + UpgradedDrivesPendingActive表
        + 复位持久化存储
    }

    firmware_mgmt --> storage_drive_fw_upgrade : signal subscribe
    storage_drive_fw_upgrade --> firmware_mgmt : reply status update
    storage_drive_fw_upgrade --> storage : depends on
    storage_drive_fw_upgrade --> bus_monitor_service : subscribe OS status
    storage_drive_fw_upgrade --> fructrl_handle : power off lock
    storage_drive_fw_upgrade --> database : persist pending active drives
```

#### 2.1.1.3 运行视图
<!-- 运行视图面向系统运行，描述系统启动过程、运行期交互的视图，主要解决系统运行期交互，描述各可执行交付件在运行期的交互关系 -->
```mermaid
sequenceDiagram
    participant User as User/北向接口
    participant FW as firmware_mgmt(UpdateService)
    participant ST as storage(Drive FW Upgrade)
    participant DB as Database
    participant RAID as 自研RAID控制器
    participant Drive as 目标硬盘
    participant BM as bus_monitor_service
    participant FL as fructrl_handle

    User->>FW: 发起硬盘固件升级(上传hpm包，固件类型Drive)
    FW->>FW: 解压hpm包，获取update.cfg路径与FirmwareX目录
    FW->>FW: 解析update.cfg的ComponentID/ComponentIDEx，匹配FirmwareComponentInfo_Drive(Name=Drive)
    FW->>ST: UpgradePrepareSignal(system_id, firmware_type=Drive, cfg_path, hpm_path, parameters)
    ST->>ST: 检查前置条件(并发控制/OS上电/在位硬盘)
    ST->>FL: 加下电锁(超时600秒)
    ST->>ST: 设置cfg_path和hpm_path文件权限(secbox用户)
    ST->>ST: 解析update.cfg，筛选ComponentID=0x22且ComponentIDEx=0xffffffff的配置项
    ST->>FW: PrepareReply(ret=0/err)

    FW->>ST: UpgradeProcessSignal(system_id, firmware_type, file_path, parameters)
    ST->>ST: 设置file_path文件权限(secbox用户)
    ST->>ST: 解析file_path获取固件名称，从配置中获取对应Model列表
    ST->>ST: 根据Model列表筛选目标硬盘(匹配Model且被自研RAID卡管理)
    ST->>ST: 解压固件包(最大100MB)，获取drive_img.bin
    ST->>FW: UpdateUpgradeStatus(progress=20, state=Running)
    loop 遍历目标硬盘
        ST->>RAID: 下发升级到目标硬盘(Drive)
        ST->>ST: 记录升级成功到内存列表
    end
    ST->>FW: UpdateUpgradeStatus(progress=90, state=Running)
    ST->>FW: ProcessReply(ret=0/err)

    FW->>ST: UpgradeFinishSignal(system_id, firmware_type, parameters)
    ST->>ST: 校验升级成功列表不为空
    ST->>FW: RegisterActiveAction(FirmwareType=Drive, ActiveCondition=None, 掉电持久化)
    ST->>DB: 持久化待生效硬盘列表(去重，复位持久化)
    ST->>FL: 释放下电锁
    ST->>FW: FinishReply(ret=0/err)

    alt 场景1：用户手动触发生效
        User->>FW: 手动触发生效(通过Redfish/WEBREST Active接口)
        FW->>ST: ActiveProcessSignal(system_id, firmware_type=Drive)
        ST->>DB: 读取待生效硬盘列表
        loop 遍历待生效硬盘
            ST->>ST: 检查硬盘在位状态
            ST->>RAID: 执行生效操作
            ST->>ST: 记录生效结果
        end
        ST->>DB: 清空待生效硬盘列表
        ST->>FW: ActiveProcessReply(ret=0/err)
        Note over ST,FW: 无论成功失败都清空表，返回结果
    end

    alt 场景2：OS下电自动生效
        User->>系统: 触发OS关机
        系统->>BM: OS下电事件
        BM->>ST: on_smbios_status_changed信号(status!=SMBIOS_WRITE_FINISH)
        ST->>DB: 清空待生效硬盘列表
        Note over ST: 不删除生效对象，由firmware_mgmt AC场景兜底
        系统->>Drive: 掉电重启，硬盘硬件特性自动完成固件切换
        User->>系统: OS上电
        ST->>RAID: 刷新硬盘版本并验证生效结果
    end

    alt 场景3：AC场景兜底清理
        User->>系统: 整机AC下电/上电
        FW->>FW: 检测AC场景，主动删除FirmwareType=Drive的生效对象
        Note over ST: storage在OS上电时已清空待生效列表(场景2)
        ST->>RAID: 刷新硬盘版本并验证生效结果(硬盘已自动生效)
    end
```

#### 2.1.1.4 信号回调参数说明
firmware_mgmt触发升级信号时传递的参数说明如下：

**Prepare阶段回调参数**：
- `ctx`：上下文对象
- `system_id`：系统标识
- `firmware_type`：固件类型，对于硬盘固件包为`"Drive"`
- `cfg_path`：`update.cfg`的路径（已解压）
- `hpm_path`：解压前HPM包的路径
- `parameters`：透传参数，后续可能包含对指定硬盘进行升级的扩展信息（如ComponentID/ComponentIDEx等）

**Process阶段回调参数**：
- `file_path`：`FirmwareX`的路径，该路径解压后包含硬盘固件镜像文件

**Finish/Active阶段回调参数**：
- 继承system_id、firmware_type、parameters等通用参数

### 2.1.2 内部依赖分析
<!-- 是否涉及与其他组件接口依赖，如果涉及需要确认当前是否已完成，是否匹配当前需求开发诉求 -->
依赖固件管理组件（firmware_mgmt）：
- UpdateService升级信号（Prepare/Process/Finish）及对应Reply接口，用于驱动升级流程并回传结果。
- UpdateService升级状态更新接口（UpdateUpgradeStatus），用于上报进度、状态与错误信息。
- FirmwareActive生效信号及Reply接口（ActiveProcessSignal、ActiveProcessReply），用于处理手动触发生效场景。
- **RegisterActiveAction接口**：用于注册生效对象（Finish阶段调用），生效对象为掉电持久化。
- **DeleteActiveAction接口**：用于删除生效对象（生效完成后或OS下电时调用），防止重复生效。
- firmware_mgmt在AC场景下主动删除FirmwareType=Drive的生效对象（兜底机制）。

依赖upgrade_subject机制：
- 订阅升级信号并分发至storage observer。
- 按firmware_type映射与分发（特殊固件类型可通过parser扩展）。

依赖platform自发现（FirmwareComponentInfo）：
- 在`vpd/vendor/Huawei/Server/Kunpeng/openUBMC/platform/platform.sr`新增`FirmwareComponentInfo_Drive`对象，示例：
```json
{
  "FirmwareComponentInfo_Drive": {
    "ComponentID": 34,
    "ComponentIDEx": 4294967295,
    "Name": "Drive",
    "RevisionNumber": 0
  }
}
```
- 自发现将该对象上报到firmware_mgmt，用于将`update.cfg`中的`ComponentID/ComponentIDEx`映射到`FirmwareType=Drive`

依赖storage内部能力：
- drive/controller对象管理与索引（用于目标定位）。
- 与自研RAID控制器的管理通道（用于下发升级命令、查询进度/结果、刷新版本、执行生效操作）。
- **已升级成功硬盘表维护机制**：使用数据库表存储已升级成功的硬盘名称（表类型为复位持久化，BMC复位后保留）。
- **OS电源状态监听**：监听OS状态变化信号，用于Prepare前置条件校验（检查SMBIOS状态为完成且电源状态为上电）与OS下电时清理待生效列表。
- **下电锁管理**：通过下电锁管理模块提供的接口管理下电锁，防止升级过程中OS下电。超时时间设置为600秒（10分钟）。

### 2.1.3 外部依赖分析
<!-- 是否涉及与平台SDK的依赖关系 -->
不涉及平台SDK新增依赖。升级包解析/校验如需引入外部工具需评审（本详设默认复用现有能力）。

### 2.1.4 北向接口分析
<!-- 需要分析当前功能是否有以下接口影响，如果有影响，则需要具体的补充影响点。其中注意点如下：
（1）如果有新增IPMI接口，请排查代码中IPMI命令注册的过滤字段，是否完全和IPMI命令的定义一致？
（2）新增一个接口时，需要咨询SIG组是否还有其他的接口受影响 -->
| 特性 | SNMP | CLI | WEB | KVM_VMM | IPMI(RMCP/RMCP+) | HMM | Redfish |
| ---- | ---- | ---- | --- | ------ | ---------------- | --- | ------- |
| 支持带外升级自研RAID卡管理的硬盘 | 不涉及 | 不涉及 | 支持 | 不涉及 | 不涉及 | 不涉及 | 支持 |

**各北向接口详细说明：**
1. **Redfish接口**：
   - 升级入口：`/redfish/v1/UpdateService`
   - 目标选择：选择固件类型为Drive并上传硬盘固件hpm包；目标硬盘由storage在Prepare阶段根据update.cfg的Model列表与在位硬盘自动筛选
   - 状态查询：`/redfish/v1/UpdateService` 或任务/事件记录（以平台实现为准）

2. **WEB接口**：
   - 接口路径：`UI/Rest/BMCSettings/UpdateService`
   - 说明：支持上传固件包、选择目标硬盘并发起升级，展示进度与结果（按UI/REST实现对齐）

### 2.1.5 兼容性分析
<!-- 当前的功能对现有在网的功能是否有影响，具体的影响点进行分析之后输出影响分析表格 -->
对于非自研RAID卡管理的硬盘或不支持升级的硬盘，不开放带外升级入口或返回“目标不支持”，不影响现网其他固件升级流程。
对于支持升级的自研RAID卡管理硬盘，新增observer与升级任务管理逻辑，不改变现有硬盘对象管理/告警/盘状态等功能。

### 2.1.6 定制化接口分析
不涉及
### 2.1.7 导入导出分析
<!-- 如果支持导入导出的配置，则需要分析导入导出的schema。 -->
不涉及
### 2.1.8 传感器分析
<!-- 如果需要新增传感器，则需要提前登记和评审新增的传感器要素。新增传感器评审需要上SIG-Interface进行评审 -->
不涉及
### 2.1.9 精准告警事件分析
<!-- 如果需要新增事件，则需要提前登记和评审新增的时间要素 -->
不涉及
### 2.1.10 系统锁定分析
<!-- 对外的接口或者命令是否支持系统锁定 -->
不涉及

### 2.1.11 用例场景分析
<!-- 以表格的形式输出该需求涉及的用例场景 -->

**说明**：硬盘升级整体流程分为**升级**与**生效**两阶段。**升级阶段**（Prepare/Process/Finish）完成后，新固件已写入硬盘但尚未被使用，**固件版本不会立即更新**；只有在**生效阶段**（用户手动触发生效或OS/整机掉电上电后由硬件自动生效）完成后，硬盘才会使用新固件并**更新固件版本**。

| 用例编号 | 用例描述 | 前置条件 |执行步骤 | 预期结果 |
| --- | --- | --- | --- | --- |
| 1 | 自研RAID卡管理硬盘带外升级成功（Model命中） | BMC正常运行；自研RAID卡在位；至少1块在位硬盘满足：Model在升级包update.cfg的Model列表中；准备好匹配的hpm包 | 1.通过WEB/Redfish选择固件类型Drive并上传硬盘固件hpm包；2.发起升级；3.持续查询升级进度；4.等待升级结束（升级阶段完成）；5.查询硬盘固件版本（Revision/FirmwareInventory）；6.触发生效（手动或掉电上电）；7.再次查询硬盘固件版本 | 步骤4完成后升级流程完成，进度到100%，状态为Completed；**此时尚未生效，硬盘仍使用旧固件，固件版本仍为旧版本**；步骤6生效完成后，硬盘使用新固件，固件版本更新为新版本 |
| 2 | 在位硬盘均不命中Model列表导致Prepare失败 | BMC正常运行；自研RAID卡在位；在位硬盘的Model均不在update.cfg的Model数组中 | 1.选择固件类型Drive并上传hpm包；2.发起升级；3.查看返回结果/状态 | Prepare阶段失败并返回“无匹配硬盘型号/目标不存在”；不会进入执行阶段 |
| 3 | 命中Model但非自研RAID卡管理导致Prepare失败 | BMC正常运行；存在硬盘Model命中update.cfg，但其RefControllerTypeId不为自研RAID卡管理 | 1.选择固件类型Drive并上传hpm包；2.发起升级；3.查看返回结果/状态 | Prepare阶段失败并返回“不支持/非自研RAID卡管理硬盘”；不会进入执行阶段 |
| 4 | 升级包ComponentID/ComponentIDEx无法映射到Drive类型 | BMC正常运行；上传的hpm包update.cfg中ComponentID/ComponentIDEx不为(34,4294967295)或未配置对应FirmwareComponentInfo对象 | 1.上传hpm包并发起升级；2.观察FirmwareType与返回结果 | firmware_mgmt无法将该包识别为Drive升级，storage不会收到FirmwareType=Drive的PrepareSignal |
| 5 | 升级过程进度上报正常 | BMC正常运行；自研RAID卡在位；目标硬盘在位；升级包正确 | 1.发起升级；2.循环查询升级状态/进度 | 状态为Running且进度单调推进；最终进入Completed或Exception（仅表示升级阶段结束，不表示固件版本已更新） |
| 6 | 升级过程中拔盘 | BMC正常运行；自研RAID卡在位；目标硬盘在位且已开始升级 | 1.发起升级并确认进入Running；2.拔出目标硬盘；3.查询升级状态 | 升级任务进入Exception并给出错误原因；资源释放；系统盘状态正确更新 |
| 7 | 整机AC下电/上电后的升级行为 | 目标硬盘在位；升级任务Running 或 已完成待生效 | 1.发起升级（若需要生效可停在待生效状态）；2.整机AC下电/上电；3.系统恢复后查询版本与任务状态 | 若AC导致升级中断，则任务失败并可重新发起；若**升级阶段**已完成且处于待生效，AC后进入**生效阶段**，硬盘使用新固件且固件版本可查询到新版本 |
| 8 | OS下电导致升级前置条件不满足 | BMC正常运行；自研RAID卡在位；OS处于下电状态 | 1.选择固件类型Drive并上传hpm包；2.发起升级；3.观察Prepare阶段返回结果 | Prepare阶段返回失败，错误信息为"不满足升级条件：OS下电"；不会进入Process阶段 |
| 9 | 升级过程中拔盘（多盘升级场景） | 自研RAID卡在位；已识别到多个目标硬盘并开始升级 | 1.发起多盘升级并确认Running；2.拔出其中一个目标硬盘；3.持续查询升级状态；4.等待升级结束；5.查询运行日志与最终结果 | 被拔出的硬盘升级失败并记录error日志；其余硬盘继续升级并按各自结果记录成功/失败；整体任务返回失败（存在至少一块升级失败）；**升级阶段**结束后，固件版本尚未更新，需生效后才更新 |
| 10 | 用户手动触发生效 | 硬盘**升级阶段**已完成；storage已维护已升级硬盘表；生效对象已注册（ActiveStatus=Idle） | 1.查询FirmwareActive对象，确认存在Drive类型待生效对象；2.通过Redfish/WEBREST手动触发生效（如POST到Active接口）；3.持续查询生效状态；4.查询硬盘固件版本 | **生效阶段**完成；storage清空已升级硬盘表并删除生效对象；硬盘**开始使用新固件**，固件版本更新为新版本；FirmwareInventory中Version更新 |
| 11 | OS下电自动生效硬盘固件 | 硬盘**升级阶段**已完成；storage已维护已升级硬盘表；生效对象已注册；OS处于上电状态 | 1.查询FirmwareActive对象，确认存在Drive类型待生效对象；2.触发OS正常关机；3.OS完全下电后再上电；4.系统恢复后查询硬盘固件版本与FirmwareActive对象 | OS下电时storage主动删除生效对象并清空已升级硬盘表；OS上电后**生效阶段**由硬件自动完成，硬盘使用新固件，固件版本切换到新版本；FirmwareActive中不再存在Drive待生效对象 |
| 12 | 整机AC后硬盘固件自动生效 | 硬盘**升级阶段**已完成待生效；storage已维护已升级硬盘表；生效对象已注册 | 1.记录升级完成状态与待生效对象；2.对整机进行AC下电；3.对整机进行AC上电；4.系统恢复后查询硬盘固件版本、已升级硬盘表、FirmwareActive对象 | AC后**生效阶段**由硬件自动完成；firmware_mgmt检测AC场景兜底删除Drive生效对象；storage OS上电后感知并清空已升级硬盘表；硬盘使用新固件，固件版本切换到新版本；FirmwareActive中不再存在Drive待生效对象 |
| 13 | 升级过程中OS下电导致任务中断 | 升级任务Running；升级期间已加下电锁（或未加锁） | 1.发起升级并确认Running；2.触发OS下电（如关机命令）；3.BMC感知OS下电事件；4.查询升级任务状态与日志 | storage感知OS下电后释放下电锁（若已加锁）、清理生效对象（若已注册）与已升级硬盘表、标记任务失败并上报Exception |

## 2.2 非功能质量属性设计
### 2.2.1 扩展性分析
<!-- 考虑后续新增类似功能可以很好地扩展 -->
采用upgrade_subject的observer分发机制，后续新增其他“受控设备固件升级”（如RAID、SSD/NVMe等）可通过注册新的firmware_type observer实现复用。
**扩展机制**：
1. **信号分发机制复用**：采用upgrade_subject的observer分发模式，通过FirmwareType路由不同设备类型升级信号（如Drive/RAID/NVMeDirect）。
2. **代码结构建议**：
   - `storage/upgrade/`目录下按设备类型组织（如`drive_upgrade.lua`、`raid_upgrade.lua`、`nvme_mi_upgrade.lua`）。
   - 每个模块实现统一接口（prepare/process/finish/active），由主控模块根据FirmwareType分发。

### 2.2.2 重用性分析
<!-- 是否为通用处理方式、接口，如果是得考虑重用性 -->
UpgradeSubject的信号订阅/分发、状态上报接口为通用机制；storage仅实现目标定位与升级执行逻辑，升级框架能力可复用。

### 2.2.3 可测试性分析
<!-- 此需求如何验证，是否可直接验证，or通过XXX功能覆盖验证，or需要单独怎加测试接口验证 -->
1. 通过WEB/Redfish发起升级验证主流程（Prepare/Process/Finish）与状态上报。
2. 通过构造包不匹配/目标不存在/升级中拔盘等异常验证错误路径。
3. 对并发升级与互斥策略进行场景验证。
4. 对OS复位、BMC复位、整机AC等可靠性场景验证恢复策略。

### 2.2.4 资料分析
<!-- 是否涉及资料修改 -->
需要补充/更新资料：
1) Redfish/WEBREST中“硬盘固件升级”的目标选择参数定义（例如NodeId/槽位/ComponentID等）。  
2) 升级状态字段/错误码说明。  
3) 如涉及固件类型枚举（firmware_type）新增/统一命名，需要同步资料与映射配置。

### 2.2.5 资源使用分析
<!-- 新增线程、内存分配、模型属性名长度是否合理，CPU占用率是否会激增，Flash中新增文件是否合理（频繁读写Flash会大幅缩短emmc寿命）；是否涉及消息队列，如果涉及请检查是否存在某些场景下消息队列会满导致消息丢失，例如大量消息发送到队列且处理消息需要耗费较长时间的场景。 -->
1. 升级流程中使用skynet异步执行，避免阻塞主流程；并发任务数需限制，避免控制器侧压力过大。  
2. 升级包存储与解析由固件管理组件/平台统一处理，本需求不新增频繁Flash写入（按平台现有机制）。  
3. 升级进度上报频率需控制（例如每N%或每T秒），避免消息量过大。  

### 2.2.6 可靠性分析
| 编号 | 场景 | 问题描述 | 可靠性影响 | 建议解决方案/需求 | 备注 |
| --- | --- | --- | --- | --- | --- |
| 1 | OS下电 | 升级依赖OS上电，OS下电时通信中断 | 升级无法进行/中断 | Prepare阶段校验OS电源状态，OS未上电则返回"不满足升级条件"；升级中OS下电则终止任务并释放资源/下电锁 | 已实现 |
| 2 | 目标定位失败 | Model数组与在位硬盘不匹配/硬盘非自研RAID卡管理 | 升级无法开始 | Prepare阶段筛选目标，无匹配则返回明确错误信息 | 已实现 |
| 3 | 包不匹配 | 包与目标介质/型号不兼容 | 误升级风险 | Prepare阶段解析update.cfg并校验匹配关系 | 已实现 |
| 4 | 升级中拔盘（多盘升级） | 升级过程中某硬盘被拔出 | 该硬盘升级失败 | 监听Presence变化，标记该硬盘失败并记录error日志，其余硬盘继续升级，不中断整体任务 | 已实现 |
| 5 | 升级中下电锁失败 | Prepare阶段加下电锁失败 | 升级中可能被下电中断 | 加锁失败则Prepare返回错误，不进入Process阶段 | 已实现 |
| 6 | 升级中OS下电（加锁后） | 虽有下电锁但OS异常下电 | 任务失败/数据一致性风险 | storage通过`on_smbios_status_changed`信号感知OS下电，清空待生效列表；资源清理时释放下电锁 | 已实现 |
| 7 | 升级中控制器异常 | 控制器重置/掉线 | 任务失败/资源泄漏 | 任务超时与异常捕获；释放资源；升级或生效针对硬盘层面都有重试机制 | 已实现 |
| 8 | BMC复位（升级进行中） | 任务上下文丢失，但已升级硬盘表持久化 | 任务中断 | 已升级成功待生效的硬盘只有在给固件管理注册生效对象后才进行复位持久化，该场景复位起来后仍可生效，如果注册生效对象前复位则此次升级失败 | 已实现 |
| 9 | 整机AC（升级进行中） | 系统全断电 | 任务中断 | AC导致任务失败；已升级硬盘表与生效对象持久化保留；firmware_mgmt检测AC场景兜底删除Drive生效对象，storage OS上电后感知并清理表 | 已实现 |
| 10 | 整机AC（升级完成待生效） | AC后硬盘自动生效 | 硬盘固件自动切换 | storage在OS下电时主动删除生效对象与清空表，防止重复生效；firmware_mgmt AC场景兜底删除；OS上电后storage刷新版本验证生效 | 已实现 |
| 11 | 手动生效失败 | 用户触发生效但硬盘生效失败 | 生效不完整 | storage在ActiveProcessSignal回调中执行生效并验证结果，失败则返回错误，待生效列表清除；每个硬盘的生效结果都记录运行日志 | 已实现 |
| 12 | 并发升级 | 在升级过程中，再上传硬盘固件包升级 | 性能/失败率上升 | 若在升级过程中再次升级，则返回失败 | 已实现 |

### 2.2.7 安全性分析
| 安全合规项 | 是否涉及 | 现有的防护措施 |
| --- | --- | --- |
| 访问控制（通道、文件权限、用户权限、查询权限、配置权限、接口权限） | 涉及 | 复用UpdateService权限体系；升级包/配置文件权限按平台策略处理 |
| 敏感数据 | 不涉及 |  |
| 日志（操作日志、维护日志、安全日志、运行日志） | 涉及 | 记录发起升级、目标、版本、结果与错误原因 |
| 文档 | 涉及 | 补充北向接口资料与错误码说明 |
| 加密及算法 | 不涉及 |  |
| 新增关键资源（密钥、证书、关键配置）备份、恢复 | 不涉及 |  |
| 新增对外接口入参校验 | 涉及 | 参数合法性校验、目标权限/存在性校验、包匹配校验 |
| 新增开源及三方软件引入 | 不涉及 |  |

# 3.功能实现
<!-- 通过表格、流程图、简明文字描述提供，力求容易看懂、容易实现，详细描述细节。 -->
## 3.1 支持带外升级自研RAID卡管理的硬盘
### 3.1.1 功能实现设计
整体实现沿用"upgrade_subject订阅/分发 + observer实现回调"的框架，并补充Drive固件类型识别、目标筛选与生效机制逻辑：

**1. 固件类型识别与observer注册**：
- platform新增`FirmwareComponentInfo_Drive`（ComponentID=34/0x22，ComponentIDEx=4294967295/0xffffffff，Name=Drive）并自发现上报到firmware_mgmt，使firmware_mgmt可将硬盘hpm包识别为`FirmwareType=Drive`。
- storage在初始化阶段直接订阅UpdateService和FirmwareActive信号，实现硬盘固件升级observer（`firmware_type=Drive`）。订阅的信号包括：Prepare信号、Process信号、Finish信号、Active信号，以及OS下电状态变化信号。

**2. Prepare阶段（前置条件与目标筛选）**：
- **并发控制**：校验是否已有升级任务在进行中，防止并发调用导致资源冲突。
- **OS上电状态校验**：升级依赖OS上电与RAID卡通信，需校验OS电源状态（SMBIOS状态为完成且电源状态为上电），不满足则返回错误。
- **在位硬盘校验**：校验是否有在位硬盘且被RAID卡管理（控制器ID有效），无有效硬盘则返回错误。
- **配置解析与筛选**：解析update.cfg配置文件，筛选出硬盘固件类型的配置项（ComponentID=0x22且ComponentIDEx=0xffffffff），保存配置信息供后续阶段使用。
- **文件权限设置**：设置升级包相关文件（update.cfg和hpm包）的属主为secbox用户（UID=104，GID=104），确保升级过程中文件访问权限正确。
- **下电锁保护**：加下电锁防止升级过程中OS下电导致通信中断，超时时间设置为600秒（10分钟），加锁失败则返回错误。
- **异步处理**：异步执行准备逻辑，解析配置信息，回传PrepareReply并上报Running状态。

**3. Process阶段（升级下发与异常处理）**：
- **配置校验**：校验Prepare阶段解析的配置信息不为空，否则返回错误并清理资源。
- **文件权限设置**：设置固件文件路径的属主为secbox用户，确保升级过程中文件访问权限正确。
- **目标筛选**：解析固件文件路径获取固件名称，根据固件名称从配置中获取对应的Model列表，重新筛选目标硬盘（匹配Model且被自研RAID卡管理）。
- **固件解压**：解压固件包获取硬盘固件镜像文件，最大解压限制100MB，防止解压文件过大。
- **升级执行**：遍历目标硬盘，对每个硬盘执行升级操作：
  - 检查硬盘在位状态，不在位则记录错误日志并跳过该硬盘。
  - 通过RAID控制器接口下发升级命令（传入控制器ID、设备ID和固件文件路径）。
  - 升级成功则记录到成功列表，并记录运行日志。
  - 升级失败则记录错误日志，但继续处理其他硬盘，不中断整体任务。
- **进度上报**：上报升级进度（初始20%，完成90%），状态为Running。
- **结果判断**：所有目标硬盘都成功升级才返回成功，有任何失败则返回失败（但不中断其他硬盘处理）。
- **异步处理**：异步执行升级逻辑，回传ProcessReply。

**4. Finish阶段（生效注册与资源清理）**：
- **成功列表校验**：校验升级成功的硬盘列表不为空，否则返回错误。
- **注册生效对象**：调用firmware_mgmt的RegisterActiveAction接口注册生效对象，生效对象属性包括：
  - FirmwareId：'Drive'（与固件类型一致，用于标识硬盘固件升级）
  - FirmwareType：'Drive'（硬盘固件类型）
  - ActiveCondition：'ResetTargetDevice'（通过重置目标硬盘触发生效）
  - ActiveMode：'None'
  - ActiveStatus：'Idle'（待生效状态）
  - 所有升级成功硬盘共用该生效对象，掉电持久化。
- **持久化待生效列表**：将升级成功的硬盘名称持久化到数据库表中（表类型为复位持久化），支持BMC重启后恢复。
- **版本与生效说明**：硬盘升级分为**升级**与**生效**两阶段；本阶段仅完成升级阶段的收尾与生效对象注册，**不刷新固件版本**。新固件已写入硬盘但尚未被使用，固件版本需在**生效阶段**（用户手动触发生效或OS/整机掉电上电后自动生效）完成后才会更新。
- **资源清理**：异步执行完成逻辑，无论成功失败都释放资源（包括下电锁、清空内存状态），回传FinishReply。

**5. Active阶段（生效机制）**：
- **场景1：用户手动触发生效** — storage在Active信号回调中从数据库读取待生效硬盘列表，对每个硬盘执行生效操作，全部成功与否都会则清空待生效列表，返回固件管理成功或失败都会取消注册生效对象。
- **场景2：OS下电/AC自动生效** — storage监听OS下电事件，主动清空待生效列表；firmware_mgmt检测AC场景兜底删除生效对象；硬盘硬件特性自动完成固件切换。

**6. OS下电/AC异常处理**：
- **OS下电感知**：通过OS状态变化信号感知OS下电，清空数据库中的待生效列表，防止重复生效。
- **资源清理**：统一释放下电锁、清空内存中的升级状态，确保资源不泄漏。
- **持久化保护**：已升级硬盘表与生效对象复位持久化，固件管理的生效对象（掉电持久化），BMC复位后保留，保证触发生效。

### 3.1.2 功能详细设计
#### 3.1.2.1 observer注册与信号分发
1. storage在`drive_upgrade:init()`函数中直接订阅UpdateService和FirmwareActive信号：
   - `client:SubscribeUpdateServiceUpdateServiceUpgradePrepareSignal`：订阅Prepare信号
   - `client:SubscribeUpdateServiceUpdateServiceUpgradeProcessSignal`：订阅Process信号
   - `client:SubscribeUpdateServiceUpdateServiceUpgradeFinishSignal`：订阅Finish信号
   - `client:SubscribeFirmwareActiveFirmwareActiveActiveProcessSignal`：订阅Active信号
   - `bus_monitor_service.get_instance().on_smbios_status_changed:on`：订阅OS下电事件
2. storage实现硬盘固件升级observer的回调方法：
   - `on_upgrade_prepare`：处理Prepare阶段
   - `on_upgrade_process`：处理Process阶段
   - `on_upgrade_finish`：处理Finish阶段
   - `on_active_process`：处理Active阶段
3. 在回调方法中通过`is_drive_firmware(firmware_type)`函数识别是否为硬盘升级信号（`firmware_type == 'Drive'`），否则直接返回。

#### 3.1.2.2 Prepare阶段：前置条件与目标校验
Prepare阶段需完成以下前置条件校验、目标筛选与资源准备（以硬盘升级为例）：

**1. 信号识别**：校验`firmware_type == 'Drive'`，否则认为不是硬盘升级信号直接返回或交由其他observer处理。  

**2. 前置条件校验**：
- **并发控制**：检查是否已有升级任务在进行中，若已在升级中则返回错误，防止并发调用导致资源冲突。
- **在位硬盘检查**：检查是否有在位硬盘且被RAID卡管理（控制器ID有效），无有效硬盘则返回错误。
- **OS上电依赖**：硬盘固件升级依赖OS上电状态（与带内RAID卡通信正常），OS下电不满足升级条件。Prepare阶段需校验OS电源状态：
  - 检查SMBIOS状态是否为完成状态
  - 检查电源状态是否为上电状态
  - 若不满足则返回错误"不满足升级条件：OS下电"。
- **参数合法性校验**：校验system_id、cfg_path(update.cfg路径)、hpm_path等必填参数存在且可访问。  

**3. 解析update.cfg**：
- 根据cfg_path读取update.cfg配置文件。
- 筛选配置项：只保留ComponentID为0x22且ComponentIDEx为0xffffffff的配置项（硬盘固件配置），删除不符合条件的配置项。
- 将筛选后的配置保存到内存中（以固件名称为key，配置对象为value），供Process阶段使用。
- 注意：Prepare阶段不进行目标硬盘筛选，目标筛选在Process阶段根据具体固件名称和Model列表进行。  

**4. 文件权限设置**：
- 设置update.cfg文件权限的属主为secbox用户（UID=104，GID=104），确保升级过程中文件访问权限正确。
- 设置hpm包文件权限的属主为secbox用户（UID=104，GID=104）。
- 权限设置失败则清理资源并返回错误。

**5. 异步执行准备逻辑**：
- 异步执行准备逻辑，避免阻塞主流程。
- 在异步函数中解析update.cfg并保存配置信息。
- 执行完成后回传PrepareReply（成功或失败）。  

**6. 资源准备与下电保护**：
- 按控制器维度锁定升级互斥资源，准备升级通道。  
- **下电锁机制**：升级期间通过下电锁接口加下电锁，防止升级过程中OS下电导致通信中断。下电锁超时时间设置为600秒（10分钟），加锁失败则Prepare返回错误。升级完成后（成功或失败）在资源清理时自动解锁。

**7. 回传PrepareReply与状态上报**：Prepare成功则上报Running并进入Process；失败则返回错误码与明确原因（如"OS下电"/"无匹配目标硬盘"/"目标非自研RAID卡管理"）。

#### 3.1.2.3 Process阶段：下发升级与异常处理
**1. 下发升级**：
- **配置校验**：校验Prepare阶段解析的配置信息不为空，否则返回错误并清理资源。
- **文件权限设置**：设置固件文件路径的属主为secbox用户（UID=104，GID=104），确保升级过程中文件访问权限正确。
- **目标筛选**：解析固件文件路径获取固件目录和固件名称，根据固件名称从配置中获取对应的Model列表，重新筛选目标硬盘（匹配Model且被自研RAID卡管理），支持Process阶段动态匹配。
- **固件解压**：解压固件包获取硬盘固件镜像文件，最大解压限制100MB，防止解压文件过大。
- **升级执行**：遍历目标硬盘，对每个硬盘执行升级操作：
  - 检查硬盘在位状态，不在位则记录运行日志（error级别）并跳过该硬盘。
  - 通过RAID控制器接口下发升级命令（传入控制器ID、设备ID和固件文件路径）。
  - 升级成功则记录到成功列表，并记录运行日志（info级别）。
  - 升级失败则记录错误日志和运行日志（error级别），但继续处理其他硬盘，不中断整体任务。
- 当前实现为串行处理，后续可按策略支持并发或限并发。

**2. 进度监控与上报**：
- 上报初始进度：在开始处理升级包（解压前）固定上报一次进度20%，状态为Running，表示已进入升级执行阶段。
- 进度平滑推进：在遍历目标硬盘、依次执行升级时，将20%~90%这一进度区间按“目标硬盘个数”线性切分；每完成一块硬盘（无论成功或失败），都会在该区间内更新一次进度，使多盘场景下进度条更平滑。
- 最后一块硬盘完成后，对应进度接近或等于90%，状态仍为Running，由后续Finish/Active阶段补齐整体任务状态。
- 进度上报通过固件管理组件的状态更新接口，参数包括：
  - progress：0~100（Process阶段主要在20%~90%之间线性推进）
  - state：'Running'
  - message：阶段说明

**3. 异常处理（拔盘场景）**：
- **升级过程中拔盘**：监听Drive对象的Presence属性变化，若升级中某硬盘被拔出：
  - 标记该硬盘升级失败，记录运行日志（error级别），说明原因为"升级中拔盘"。
  - 其余目标硬盘继续升级，不中断整体任务。
  - 在Process或Finish阶段汇总结果时，明确哪些硬盘成功、哪些失败及原因。

**4. Process阶段结束后回传ProcessReply**：
- **结果判断**：若所有目标硬盘都成功升级，返回成功；若有任何硬盘升级失败（包括部分失败或全部失败），返回失败，但不会中断其他硬盘的升级流程。
- **日志记录**：每个硬盘的升级结果都会记录详细的运行日志，包括成功和失败信息，便于问题定位和追踪。

**5. 升级对业务影响说明**：
- 硬盘固件升级过程中对业务几乎无影响（带内通道升级，盘仍可响应IO）。

#### 3.1.2.4 Finish阶段：生效注册、维护表更新与资源清理
**1. 释放资源**：释放互斥资源/恢复通道；统一释放下电锁（解锁超时时间10秒），清空内存中的升级状态，确保资源不泄漏。  

**2. 版本与生效说明**：硬盘升级分为**升级阶段**与**生效阶段**。Finish阶段仅完成升级阶段收尾，**不刷新固件版本**，仅维护待生效列表；固件版本需在**生效阶段**（手动触发生效或掉电上电自动生效）完成后才会更新。  

**3. 维护已升级成功硬盘表**：
- storage在内部维护一张"已升级成功的硬盘表"，存储在数据库中（表类型为复位持久化，BMC复位后数据保留）。
- 表结构：主键为硬盘名称（String类型），存储成功升级的硬盘名称。
- 在Process阶段，每成功升级一个硬盘，立即将该硬盘名称记录到内存列表中。
- 在Finish阶段，将内存列表中的硬盘名称持久化到数据库表中（通过硬盘名称字段去重，避免重复插入）。

**4. 注册生效对象**：
- **成功列表校验**：校验升级成功的硬盘列表不为空，否则返回错误。
- **注册生效对象**：调用firmware_mgmt提供的RegisterActiveAction接口注册生效对象，该生效对象为所有升级成功的硬盘共用（FirmwareType=Drive）。
- **生效对象属性**：
  - FirmwareId：'Drive'（与固件类型一致，用于标识硬盘固件升级）
  - FirmwareType：'Drive'（硬盘固件类型）
  - ActiveCondition：'ResetTargetDevice'（表示由用户触发重启目标设备生效）
  - ActiveMode：'None'
  - ActiveStatus：'Idle'（待生效状态）
- 该生效对象为**掉电持久化**（AC断电后恢复仍存在，直到被删除或生效完成）。
- 注册失败则返回错误，成功则继续持久化待生效列表。

**5. 上报最终状态与资源清理**：
- 异步执行完成逻辑，无论成功失败都调用`clear_drive_upgrade_resource`释放资源（包括下电锁、清空内存状态）。
- 回传FinishReply，附带错误原因（如失败）及成功/失败硬盘统计信息。

#### 3.1.2.5 Active阶段：生效机制与场景
硬盘固件升级存在"待生效"阶段，生效分为两种场景：

**场景1：用户手动触发生效**
- **触发方式**：用户通过北向接口手动触发生效（如Redfish Active接口）。
- **firmware_mgmt动作**：发布ActiveProcessSignal，携带firmware_type=Drive。
- **storage处理**：
  1. 从数据库读取待生效硬盘列表（支持BMC重启后恢复）。
  2. 校验待生效列表不为空，否则返回错误。
  3. 遍历待生效硬盘列表，对每个硬盘：
     - 从记录中获取硬盘名称。
     - 通过硬盘集合获取硬盘对象。
     - 检查硬盘是否存在，不存在则记录错误日志和运行日志（error级别）并跳过。
     - 检查硬盘是否在位，不在位则记录错误日志和运行日志（error级别）并跳过。
     - 通过RAID控制器接口执行生效操作（使用RAID管理命令激活硬盘固件）。
     - 记录每个硬盘的生效结果（成功/失败）和运行日志（info/error级别）。
  4. 判断生效结果：
     - 若所有硬盘生效成功，清空数据库中的待生效列表，返回成功。
     - 若有任何硬盘生效失败，清空数据库中的待生效列表，返回失败。
  5. 异步执行生效逻辑，回传ActiveProcessReply。

**场景2：系统下电再上电或系统复位自动生效**
- **触发方式**：OS下电再上电（AC或正常关机重启），硬盘自动完成固件生效（硬件特性）。
- **storage处理**：
  1. **感知OS下电**：storage监听OS状态变化信号，当OS下电或未就绪时，触发清理逻辑。
  2. **主动清理待生效列表**：在OS下电事件回调中，清空数据库中的待生效列表（通过truncate操作），防止重复生效。
  3. **firmware_mgmt AC场景自动清理**：firmware_mgmt检测到AC场景（整机掉电上电），主动删除FirmwareType为Drive的生效对象，作为兜底机制。
  4. **版本刷新**：系统重启后，storage重新查询硬盘固件版本并更新到FirmwareInfo（如已注册），验证生效结果。

**场景对比**：
| 场景 | 触发方式 | 生效执行者 | 清理时机 | 备注 |
| --- | --- | --- | --- | --- |
| 手动触发生效 | 用户通过北向接口触发 | storage在Active信号回调中执行生效（通过RAID控制器接口） | 全部成功时storage清空待生效列表 | 需等待生效结果，部分失败不清空表 |
| 自动生效 | OS下电再上电/系统复位 | 硬盘硬件特性自动生效 | OS下电时storage主动清空待生效列表；AC时firmware_mgmt兜底删除生效对象 | 防止重复生效 |

### 3.1.3 开发者测试
#### 3.1.3.1 单元测试
<!-- UT，主要是功能单元测试，测试对象是功能单元接口。UT测试设计要从黑盒（功能）角度设计，从输入(I)、处理（B）、预期输出（O）的角度进行用例分析设计，测试覆盖率仅作为反馈，用于分析哪些功能场景没有覆盖到，从而指导测试设计优化并补充测试用例 -->

| 组件名  | 用例类型 | 测试用例描述 | 用例名称 | 预置条件 | 操作步骤 | 预期结果 |
| ------- | -------- | ------------ | -------- | -------- | -------- | -------- |
| Storage | UT | observer注册成功 | test_register_drive_upgrade_observer | 打桩upgrade_subject | 1.初始化storage升级模块<br>2.验证调用register_upgrade_observer | observer已注册到指定firmware_type |
| Storage | UT | Prepare阶段目标定位失败 | test_prepare_target_not_found | 打桩drive集合查询 | 1.构造参数指向不存在目标<br>2.调用on_upgrade_prepare | PrepareReply返回失败，错误信息明确 |
| Storage | UT | Prepare阶段包不匹配失败 | test_prepare_pkg_not_match | 打桩包解析/匹配逻辑 | 1.构造不匹配包元信息<br>2.调用on_upgrade_prepare | PrepareReply返回失败，不进入Process |
| Storage | UT | Process阶段进度上报 | test_process_progress_update | 打桩控制器进度查询 | 1.调用on_upgrade_process<br>2.模拟进度变化 | UpdateUpgradeStatus按策略被调用，进度正确推进 |
| Storage | UT | Finish阶段不刷新版本仅注册生效 | test_finish_no_version_refresh | 打桩client与reset_local_db | 1.设置upgraded_drives_success<br>2.调用on_upgrade_finish | FinishReply成功，仅注册生效对象与持久化待生效列表，不刷新固件版本 |
| Storage | UT | 生效完成后版本刷新 | test_active_then_version_refresh | 打桩sml.pd_active_firmware与版本查询 | 1.构造待生效记录<br>2.调用on_active_process<br>3.模拟版本查询返回新版本 | 生效流程完成，固件版本更新/清单更新正确 |
| Storage | UT | 升级中拔盘异常 | test_process_drive_removed | 打桩Presence变化 | 1.升级Running<br>2.模拟拔盘 | 任务进入Exception并释放资源 |

#### 3.1.3.2 集成测试
<!-- IT，主要是组件/模块内的集成测试，测试对象是模块/组件接口。IT测试设计将模块/组件当作黑盒测试，IT测试用例中禁止对组件/模块内部代码打桩，如果确实有少量场景难以构造，可以考虑在测试框架中统一打桩并提供接口供测试用例调用构造场景。
说明：API测试属于IT，其测试对象是微服务接口。
PCST，是指PC上的服务集成测试，测试对象是功能需求。PCST测试设计，要覆盖正常功能、异常功能和交叉功能，采用灰盒 -->
不涉及


