[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.sh和verify.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示例如下所示:
{
"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)实现装备定制化项导入导出代码,可参考[配置导入导出]
-- manufacture/customize_config.lua
local m = {}
-- 装备定制化项导入
function m.custom_import(ctx, config)
-- 结合定制化项实现配置导入
...
end
-- 装备定制化项导出,出参config为导出的定制化项,用于进行定制化校验(此时只做示例,实现也可以通过返回值灵活处理)
function m.custom_export(ctx, config)
-- 结合定制化项实现配置导出
...
end
return m3)将装备定制化流程对接到业务导入导出入口处
-- 业务配置导入入口函数
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)
end3.2 含有敏感信息的定制化项开发
3.2.1 定制流程
1)manifest仓的build/manufacture/customize/function路径下增加敏感信息定制脚本,可参考trap_community_config.sh
#!/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
}
main2)build/manufacture/customize/config.sh脚本增加调用,如下所示最后一段代码
#!/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.sh3.2.2 校验流程
1)manifest仓的build/manufacture/customize/function路径下增加敏感信息定制脚本,可参考trap_community_check.sh
#!/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
}
main2)build/manufacture/customize/verify.sh脚本增加调用,如下所示最后一段代码
#!/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.ini 和serial.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目录,存放产品差异化定制项:
# 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
{
"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"
}
}
}
}
}
}
}