装备定制化接入机制介绍
更新时间:2025/12/5
在Gitcode上查看源码

装备定制化简介

定制化目的

装备定制化主要旨在实现以下目标:

  1. 客户个性化配置:在客户下单后,于装备测试阶段,依据客户提供的具体配置信息,对服务器进行个性化定制。例如,设定特定的服务器机型名称、配置 BMC 用户名等。

  2. 故障设备配置清零与恢复:当客户服务器因故障返厂退库时,需彻底清除所有客户相关的配置信息。通过执行不带配置项的定制化脚本,将 BMC 的配置恢复至出厂默认状态。

定制化所处阶段

装备定制化流程部署于生产装备测试流程的最终环节,其在整个生产流程中的位置如下图所示:

openUBMC 装备定制化流程

代码仓介绍

配置装备定制化项与配置导入导出项的仓库相同。
代码仓位置:profile_schema
代码仓目的:schema 文件用于承载组件配置导入导出的数据模型(属性定义 + 取值约束),由于配置导入导出的属性直接面向用户,因此作为组件对外接口的一部分组件在 schema 仓实现数据定义后即可借助配置导入导出统一的校验机制实现对用户数据数据的校验(该能力由 oms 组件实现)。

代码仓结构:

shell
├── CHANGELOG.md         # 记录本仓的变更信息
├── CMakeLists.txt       # 构建配置,主要定义schema的安装路径
├── README.md            # 代码仓说明
├── build.py             # 构建脚本
├── conanfile.py
├── conaninfo.py
├── mds
│   └── service.json     # 主要定义本仓的版本号
├── dist
│   └── permissions.ini  # 构建权限管理文件
├── schema               # 主目录,存放组件的schema文件
│   ├── account.json        # 组件schema文件,以组件名进行命名,每个组件分别定义一个schema
│   ├── bios.json
│   └── ...
└── test                 # 测试目录

定制化流程整体介绍

装备定制化与配置导入导出功能的关系:
装备定制化复用了既有的配置导入导出功能的通道,定制化项同样需要在组件 schema 内增加声明,从而借由导入导出的能力实现定制化项的校验、分发与收集。 定制化数据集合名称:
CustomSettings: 组件定制化数据实例集合。

openUBMC 扩展的关键字:
AttributeType: 定制化时固定配置为 ImportAndExport
CustomDefault: 配置数据默认取值。

openUBMC 的装备定制化根据配置项的性质,分为两类处理流程:

  1. 非敏感信息类定制化项: 直接复用配置导入导出的流程。在此流程中,新增装备定制化所需的配置项,从而实现对这些项的批量设置。
  2. 敏感信息类定制化项: 在定制化脚本中(位于 manifest 仓库的 build/manufacture/customize/function/ 路径下),通过直接调用 IPMI 命令的方式,实现敏感信息项定制。

注:分为敏感信息和非敏感信息主要是为了遵守公司安全要求,避免用户敏感信息泄露,引起红线问题。

敏感信息和非敏感信息项的交互流程如下:

完整的定制化脚本执行流程包含两个核心环节:定制流程校验流程

定制流程负责将配置数据写入 BMC 并使其生效。
定制入口脚本XXX_config.sh校验流程则会在定制完成后,对 BMC 执行复位操作。待 BMC 重启后,重新导出之前设定的定制化项,并与预期设置的值进行比较,以确保定制化操作准确无误。 校验入口脚本XXX_verify.sh

装备定制化的使用

以下为装备定制化功能在实际应用场景的使用步骤。

操作系统下使用装备定制化

  1. 环境准备

    将定制装备包解压至 OS 任意目录路径下,并为脚本文件赋予执行权限:

bash
   chmod +x *.sh
  1. 配置文件创建

    新建 customset.ini 和 serial.ini 文件:

    • customset.ini:存放所有定制化配置参数
    • serial.ini:当前版本为预留文件,请保持内容为空
  2. 配置文件校验

    使用以下命令检查定制项文件格式:

bash
   cat -A customset.ini

重要注意事项:

  • 行尾符必须显示为 $ 符号(Unix/Linux 格式),非 Unix 格式请转为 Unix 格式;

  • 等号=前后不得包含空格字符;

    上述任一格式问题均会导致脚本输出的定制化结果与配置文件内容不一致

  1. 执行定制化流程

    按顺序执行以下操作:

配置应用

bash
./XXX_config.sh customset.ini serial.ini

结果验证

bash
./XXX_verify.sh customset.ini serial.ini

必须完整执行第 4 步中的两项操作(配置应用与结果验证),方可视为一次完整的定制化流程执行完毕。

非操作系统下使用装备定制化

装备定制化项导入脚本实际调用的是一条 IPMI 命令,也可以不在 OS 下导入定制化项。具体步骤如下:

  1. 新建 customset.ini 文件,可以参考服务器出厂定制化配置,选择需要定制的配置,并写入 customset.ini 文件,如:
ini
BMCSet_MACHINEALIAS=XX
  1. 将 customset.ini 文件上传到 /tmp 目录下;
  2. 发送导入 IPMI 命令:ipmitool raw 0x30 0x90 0x21 0xf0
  3. 查看定制化结果:ipmitool raw 0x30 0x90 0x22 0xef
    返回00,表示进行中
    返回01,表示定制化已完成

定制化开发过程示例

当需要开发新增非敏感信息定制化项,可参考以下开发过程。

明确定制化需求

开发前需明确组件需实现的定制化项清单,并逐一分析各定制化项在 openUBMC 中对应的功能点及实现方式。

声明定制化项

主要流程:

1)添加CustomSettings字段声明: 在 schema 文件中增加CustomSettings字段声明定制化项,该字段与配置导入导出项保持统一层级;
2)定义数据类型: 数据类型需对应组件在资源树上的属性类型,以确保能正确设置目标属性值;
3)指定属性类型: 配置装备定制项属性类型,固定为ImportAndExport
4)配置取值约束: 配置装备定制项取值约束;
5)设置默认取值: 为每个定制化项配置默认值CustomDefault。在系统整包构建阶段,构建工具会解析各组件 schema 文件中的此项声明,并统一生成全局默认配置文件default_settings.json

schema 示例如下所示:

json
{
    "type": "object",
    "properties": {
        "Description": {
            "const": "Configurations of XXX"
        },
        "ConfigData": {
            "type": "object",
            "properties": {
                "XXX": {                          // 配置导入导出项声明
                    "type": "array",
                    "items": {
                        "type": "object",
                        "properties": {
                            "Attribute1": {
                                "type": "number",
                                "AttributeType": "ImportAndExport"
                            },
                            "Attribute2": {
                                "type": "string",
                                "AttributeType": "ImportAndExport",
                                "enum": ["NoAction", "Reset", "PowerOff"]
                            },
                            "Attribute3": {
                                "type": "string",
                                "AttributeType": "ImportAndExport",
                                "enum": ["NoAction", "Reset"]
                            }
                        }
                    }
                },
                "CustomSettings": {             // 装备定制化项声明,固定名称,保持与业务导入导出项同一层级
                    "type": "object",
                    "properties": {
                        "Custom_XXXX1": {       // 装备定制项名称
                            "type": "number",   // 装备定制项数据类型,对应于ini中定制化项数据类型
                            "AttributeType": "ImportAndExport",  // 装备定制项属性类型,固定为ImportAndExport
                            "enum": [0, 1, 2],  // 装备定制项取值约束
                            "CustomDefault": 1  // 装备定制项默认取值,用于整包构建时生成默认的default_settings.json
                        },
                        "Custom_XXXX2": {
                            "type": "string",
                            "AttributeType": "ImportAndExport",
                            "enum": ["on", "off"],
                            "CustomDefault": "on"
                        }
                    }
                }
            }
        }
    }
}

代码实现

1)组件仓新增装备定制化代码customize_config.lua(名称可任意);

2)实现装备定制化项导入导出代码;

lua
-- customize_config.lua
local m = {}

-- 装备定制化项导入
function m.custom_import(ctx, config)
    -- 结合定制化项实现配置导入
    ...
end

-- 装备定制化项导出,出参config为导出的定制化项,用于进行定制化校验(此时只做示例,实现也可以通过返回值灵活处理)
function m.custom_export(ctx, config)
    -- 结合定制化项实现配置导出
    ...
end

return m

3)将装备定制化流程对接到业务导入导出入口处

lua
-- 业务配置导入入口函数
function c_config_mgmt:import(ctx, config_data)
    local cfg = cjson.decode(config_data)
    -- 装备定制化导入流程接入
    local ok, customize_config = pcall(require, 'customize_config')
    if ok and customize_config then
        if cfg.ConfigData.CustomSettings then -- 判断是否存在CustomSettings,如果不存在则不执行装备导入
            customize_config.custom_import(ctx, cfg)
        end
    end

    -- 业务配置导入
    local ok, err = pcall(function ()
        for k, v in pairs(cfg['ConfigData']) do
            if self.config[k] then
                self.config[k]:import(ctx, v)
            end
        end
    end)
    if not ok then
        error(err)
    end
end

-- 业务配置导出入口函数
function c_config_mgmt:export(ctx)
    local cfg = {}
    cfg.ConfigData = {}

    -- 装备定制化导出流程接入
    local ok, customize_config = pcall(require, 'customize_config')
    if ok and customize_config then
        customize_config.custom_export(ctx, cfg)
    end

    -- 业务配置导出
    local ok, err = pcall(function ()
        for k, v in pairs(self.config) do
            cfg.ConfigData[k] = v:export()
        end
    end)
    if not ok then
        error(err)
    end
    return cjson.encode(cfg)
end

机型差异化定制

主要场景

  • 产品 A 的某个属性存在不同的默认值,需要支持产品 A 配置不同的默认值。

  • 产品 B 存在独有的定制项,需要支持产品 B 配置定制项及其默认值。

差异化定制方案

profile_schema仓中定义通用定制项(与机型无关),在vpd仓定义差异化定制项,处理流程如下:

  1. vpd仓对应的产品目录下配置自身差异化的定制属性;
  2. 构建时从profile_schema仓和vpd仓获取对应的 schema 文件;
  3. 将产品差异化 schema 配置整合到对应的 schema 文件中;
  4. 基于整合后的 schema 文件生成默认配置default_settings.json

vpd仓对应产品目录下增加schema目录,存放产品差异化定制项:

shell
# vpd代码仓目录结构规划
├── CHANGELOG.md
├── Makefile
├── build.py
├── conanfile.py
├── conaninfo.py
├── mds
├── permissions.ini
└── vendor                  # 厂家信息:服务器厂家、组件厂家等
    ├── Aspeed
   └── bmc_soc
       ├── ast2500
       └── ast2600
    ├── Huawei
   ├── BMCSoC
   └── hi1711                  
   ├── Nic
   ├── Raid
   ├── Server
   ├── Ascend
   ├── Kunpeng
   ├── BM320
   ├── PSR             
   ├── platform        
   ├── profile.txt     
   ├── redfish         
   ├── schema          # 产品的装备定制化存在差异性配置时(默认值、属性)
   └── web_backend     
   └── Nic                 
       └── Lom
   ├── Pangea
   ├── TCE
   └── public
   ├── Ssd
   └── TianChi
    ├── Intel
   ├── Nic
   └── Raid
    ├── Mellanox
    └── Nvidia

参考vendor/Huawei/Server/Kunpeng/TaiShan200_DA123C/schema/bmc_network.json

json
{
    "type": "object",
    "properties": {
        "Description": {
            "const": "Configurations of bmc_network"
        },
        "ConfigData": {
            "type": "object",
            "properties": {
                "CustomSettings":{
                    "type": "object",
                    "properties": {
                        "BMCSet_RackInner_SubNet": {
                            "type": "string",
                            "Import": false,
                            "AttributeType": "ImportAndExport",
                            "CustomDefault": "172.31.0.0"
                        },
                        "BMCSet_RackInner_VLAN_ID": {
                            "type": "integer",
                            "Import": false,
                            "AttributeType": "ImportAndExport",
                            "CustomDefault": 702,
                            "minimum": 1,
                            "maximum": 4094
                        },
                        "BMCSet_Maint_IPv4": {
                            "type": "string",
                            "Import": false,
                            "AttributeType": "ImportAndExport",
                            "CustomDefault": "192.168.240.100"
                        },
                        "BMCSet_Maint_SubnetMask": {
                            "type": "string",
                            "Import": false,
                            "AttributeType": "ImportAndExport",
                            "CustomDefault": "255.255.255.0"
                        }
                    }
                }
            }
        }
    }
}

常见问题

  1. 装备定制化如何使用?

    可参考装备定制化的使用章节。

  2. 在不进入 OS 的情况下,能否执行装备定制化? 可以,可参考非操作系统下使用装备定制化章节。

  3. default_settings.json 文件在哪里查看?

    以 S920X20 机型为例,可在编译环境 manifest/temp/build_S920X20_debug_dev/buildimg/rtos_with_driver/rootfs/opt/bmc/profile_schema/custom 目录下查看。BMC 系统下可在 /opt/bmc/profile_schema/custom 目录下查看。