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

[toc]

1 装备定制化简介

1.1 定制化目的

装备定制化主要包含如下目的 :

1) 客户下单后,在装备测试阶段根据客户提供的配置实现个性化定制,如服务器机型名称、BMC用户名等;

2) 客户服务器故障返厂退库,需要清除客户配置,执行定制化脚本(不带配置项),使BMC配置恢复默认;

1.2 定制化所处阶段

装备定制化流程位于生产装备测试的最后阶段,如下图所示:

2 oepnUBMC装备定制化流程

2.1 定制化整体流程

主要差异点:

1)OPENUBMC复用了配置导入导出的通道,组件实现装备定制化过程与[配置导入导出]相似;

2)OPENUBMC组件在schema中定制定制化项时,需要增加默认取值CustomDefault,BMC构建时会从组件的schema文件中获取该默认配置,生成整体的默认配置文件default_settings.json;

3)config.shverify.sh时新增了几条装备场景的IPMI命令,用于定制和校验;

2.1.2 OPENUBMC整体交互流程

OPENUBMC装备定制化分为两类:

1)不含敏感信息类定制化项:复用配置导入导出流程,在配置导入导出过程中新增装备定制化项实现定制;

2)含敏感信息类定制化项:在定制化脚本中(manifest仓的build/manufacture/customize/function路径下增加脚本)通过IPMI命令实现敏感信息项定制;

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

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

2.2 定制化详细流程

定制化脚本执行流程分为:定制流程和校验流程。定制时实现配置数据的设置生效;校验时对BMC进行复位,待复位起来后导出之前配置的定制化项,比较定制化项是否与之前设置的值一致。

2.2.1 定制流程

定制入口脚本0502XXX_config.sh

2.2.2 校验流程

校验入口脚本0502XXX_verify.sh

3 组件如何开发定制化

从第二章节介绍可知,OPENUBMC定制化开发区分敏感信息项和非敏感信息项,敏感信息项定制化通过定制化脚本中IPMI命令实现,非敏感信息项定制化通过复用配置导入导出通道实现。

3.1 不含敏感信息的定制化项开发

3.1.1 明确需要实现的定制化项

明确自身组件需要实现的定制化项,分析定制化项在OPENUBMC对应的功能点和实现方式。

3.1.2 profile_schema仓中增加自身组件的定制化项声明

profile_schema仓本身是承载业务场景配置导入导出项的声明和取值约束,由于OPENUBMC装备定制化复用了配置导入导出通道,定制化项也需要在schema文件中增加声明,从而借由配置导入导出的能力实现定制化项的校验、分发和收集。

主要流程:

1)在schema中增加CustomSettings字段声明定制化项,该字段与业务导入导出项保持统一层级;

2)配置定制化项的数据类型,数据类型主要是对应组件资源树上的属性类型,用于设置资源树属性;

3)配置装备定制项属性类型,固定为ImportAndExport;

4)配置装备定制项取值约束,当前已支持的标准schema规则如下:

  • 数据类型:integer、number、string、boolean、array、object、null
  • 字符串长度:minLength、maxLength
  • 正则表达式(字符串):pattern
  • 枚举值:enum
  • 常量值:const
  • 数组长度:minItems、maxItems
  • 属性数量:minProperties、maxProperties
  • 必须属性:required
  • 额外属性:additionalProperties
  • 属性名称:propertyNames
  • 数字的范围:minimum、maximum
  • 排他范围:exclusiveMinimum、exclusiveMaximum
  • 唯一性:uniqueItems 标准schema规则详细解释可参考:https://json-schema.apifox.cn/

5)配置装备定制项默认取值,用于整包构建时生成默认的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": {
                        "BMCSet_XXXX1": {       // 装备定制项名称
                            "type": "number",   // 装备定制项数据类型,对应于ini中定制化项数据类型
                            "AttributeType": "ImportAndExport",  // 装备定制项属性类型,固定为ImportAndExport
                            "enum": [0, 1, 2],  // 装备定制项取值约束
                            "CustomDefault": 1  // 装备定制项默认取值,用于整包构建时生成默认的default_settings.json
                        },
                        "BMCSet_XXXX2": {
                            "type": "number",
                            "AttributeType": "ImportAndExport",
                            "enum": [0, 1, 2],
                            "CustomDefault": 1
                        }
                    }
                }
            }
        }
    }
}

3.1.3 代码实现

1)组件仓的manufacture路径下新增装备定制化代码customize_config.lua(名称任意);

2)实现装备定制化项导入导出代码,可参考[配置导入导出]

lua
-- manufacture/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

3.2 含有敏感信息的定制化项开发

3.2.1 定制流程

1)manifest仓的build/manufacture/customize/function路径下增加敏感信息定制脚本,可参考trap_community_config.sh

bash
#!/bin/sh
# 设置Trap团体名
set_trap_community_name()
{
	pwd_str=$1
	pwd_info=$(string2hex_with_prefix "$pwd_str")

	# 整个字符串长度
	strlen=`echo ${#pwd_str}`
	# Trap团体名长度为1-32
	if [ $strlen -gt 32 ] || [ $strlen -lt 1 ]; then
		echo_and_save_fail "Length($strlen) of Trap password is too big!"
		error_quit
	fi
	info_len=`printf "%02x" $strlen`
	run_ipmitool_without_echo "raw 0x0C 0x01 0x01 0x10 $pwd_info"
	if [ $? != 0 ] ; then
		echo_and_save_fail "set Trap community name $1 fail!"
		error_quit
	else
		echo_and_save_success "set Trap community name $1 success!"
		return 0
	fi
}

main()
{
	# 获取Trap版本
	getini $CONFIGFILE  BMCSet_TrapVersion
	TrapVersion=$parameter

    # 获取Trap团体名
	getini $CONFIGFILE  BMCSet_TrapCommunityName
	TrapCommunityName=$parameter

	# 设置Trap团体名
	if [ "$TrapVersion" != "" ] && [ "$TrapVersion" != "3" ]; then  # 非SNMPopenUBMC版本才支持
		if [ "$TrapCommunityName" != "" ] ; then
			set_trap_community_name "$TrapCommunityName"
		else
			set_trap_community_name "XXXXX"
		fi
	else
		echo_and_save_success "skip Trap community name set with TrapVersion=$TrapVersion"
	fi
}

main

2)build/manufacture/customize/config.sh脚本增加调用,如下所示最后一段代码

bash
#!/bin/sh
chmod +x *
############################################
# bash script: 定制化配置脚本
# Usage: ./config.sh customset.ini serial.ini 05020VNL
############################################
#把项目编码赋值好
#输入参数
#$1  customset.ini的内容就是BOQ的信息  
#$2 serial.ini的内容就是一个整机条码 
#$3 项目编码 
project_code=$3
VERSIONNAME=$project_code"_version.ini"
BLADE_TYPE=1
CHASSIS_TYPE=0

#每次修改脚本必须修改版本号及readme
version_out()
{
    echo -e "\033[31;1m ############################################ \033[0m"
	echo -e "\033[31;1m # bash script: config.sh                   # \033[0m" 
	echo -e "\033[31;1m # Version:     V1.28                       # \033[0m" 
	echo -e "\033[31;1m ############################################ \033[0m" 
}

#打印版本信息
version_out 

#解压依赖包
tar zxvf function.tar.gz > /dev/null 2>&1

#加载公共脚本
source ./function/common.sh
init_common $1 $2 config

upload_custom_file
if [ $? == 0 ]; then
	customize
fi

# 其他流程
...

# *************[调用对应敏感信息定制]*******************
#定制化SNMP Trap上报告警事件的团体名
source ./function/trap_community_config.sh

3.2.2 校验流程

1)manifest仓的build/manufacture/customize/function路径下增加敏感信息定制脚本,可参考trap_community_check.sh

bash
#!/bin/sh
# 校验Trap团体名
check_trap_community_name()
{
	pwd_str=$1
	pwd_info=$(string2hex_with_prefix "$pwd_str")

	# 整个字符串长度
	strlen=`echo ${#pwd_str}`

	# Trap团体名长度为1-32
	if [ $strlen -gt 32 ] || [ $strlen -lt 1 ]; then
		echo_fail "Length($strlen) of Trap password is too big!"
		echo "Length($strlen) of Trap password is too big!" >> $SAVEFILE
		error_quit
	fi
	info_len=`printf "0x%02x" $strlen`
	run_ipmitool "raw 0x30 0x93 0xdb 0x07 0x00 0x15 0x00 0x15 0x00 0x00 $info_len $pwd_info" "db 07 00"
	if [ $? = 0 ] ; then
		echo_and_save_success "check Trap community name $1 success!"
		return 0
	else
		echo_and_save_fail "check Trap community name $1 fail!"
		error_quit
	fi
}

main()
{
	# 获取Trap版本
	getini $CONFIGFILE  BMCSet_TrapVersion
	TrapVersion=$parameter

    # 获取Trap团体名
	getini $CONFIGFILE  BMCSet_TrapCommunityName
	TrapCommunityName=$parameter

	# 校验Trap团体名是否定制化成功
	if [ "$TrapVersion" != "" ] && [ "$TrapVersion" != "3" ]; then  # 非SNMPopenUBMC版本才支持
		if [ "$TrapCommunityName" != "" ] ; then
			check_trap_community_name "$TrapCommunityName"
		else
			check_trap_community_name "XXXXX"
		fi
	else
		echo_and_save_success "skip Trap community name check with TrapVersion=$TrapVersion"
	fi
}

main

2)build/manufacture/customize/verify.sh脚本增加调用,如下所示最后一段代码

bash
#!/bin/sh
chmod +x *
############################################
# bash script: 定制化功能定制检测脚本
# Usage: ./verify.sh customset.ini serial.ini 05020VNL
############################################
#赋值项目编码
project_code=$3

VERSIONNAME=$project_code"_version.ini"

#解压依赖包
tar zxvf function.tar.gz > /dev/null 2>&1

#加载公共脚本
source ./function/common.sh

#检查并等待定制完成
check_custom_completd

#复位BMC
reset_bmc

init_common $1 $2 verify

#下发校验请求
start_verify

#等待校验完成
check_verify_completd

#检查并等待校验完成
get_custom_result

#定制化电子标签信息
source ./function/assets_check.sh

# *************[调用对应敏感信息校验]*******************
#校验SNMP Trap上报告警事件的团体名定制化结果
source ./function/trap_community_check.sh

#其他流程
...

4 装备定制化测试标准动作

1) 将定装备包解压到OS任意路径下,赋予脚本执行权限chmod +x *.sh

2) 新建customset.iniserial.ini文件:

​ a)customset.ini放入定制化配置;

​ b)serial.ini目前为预留文件,保持为空即可;

3) cat -A customset.ini检查定制项文件,注意事项:

​ a)行尾符必须为$(Unix格式),非Unix格式请转为Unix格式;

​ b)=号前后不能有空格;

​ c)以上两个问题都会导致脚本打印的定制化结果与配置文件不一致;

4) 执行./XXX_config.sh customset.ini serial.ini,开始定制化

5) 执行./XXX_verify.sh customset.ini serial.ini,进行定制化校验

6) 以上步骤4-5操作必须执行完成,才能算跑完一次定制化(如果一直跑config是肯定会失败的,此类问题不需要定位)

注意

1、本地或者OS侧用取的包升级BMC到对应版本

2、确保OS发行版本与装备包中driver.tar.gz对应,即driver.tar.gz里面体现了支持的OS版本,

1)泰山支持的OS:centos82、euler2sp5、euler2sp8

2)X86支持的OS:suse11sp1、suse11sp3、suse12sp0、suse12sp2、suse15

[root@localhost BC83SMMAA035.02.00.02]# ls -al driver
total 4
drwxr-xr-x 13 root root  196 Jun 27  2022 .
drwxr-xr-x  5 root root 4096 Sep 23 20:11 ..
drwxr-xr-x  2 root root   78 Jun 27  2022 centos82
drwxr-xr-x  3 root root  102 Jun 27  2022 euler2sp5
drwxr-xr-x  3 root root  102 Jun 27  2022 euler2sp8
drwxr-xr-x  2 root root  156 Jun 27  2022 PaxHeaders.93190
drwxr-xr-x  3 root root  102 Jun 27  2022 suse11sp1
drwxr-xr-x  3 root root  102 Jun 27  2022 suse11sp3
drwxr-xr-x  3 root root  102 Jun 27  2022 suse12sp0
drwxr-xr-x  3 root root  102 Jun 27  2022 suse12sp2
drwxr-xr-x  3 root root  102 Jun 27  2022 suse15
drwxr-xr-x  3 root root  102 Jun 27  2022 suse15sp1
drwxr-xr-x  3 root root  102 Jun 27  2022 suse15sp2

5 机型差异化定制

5.1 主要场景

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

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

5.2 差异化定制方案

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          # 产品的装备定制化存在差异性配置时(默认值、属性),在此目录定义差异化的schema文件,构建时会综合profile_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"
                        }
                    }
                }
            }
        }
    }
}