openUBMC社区的Redfish、CLI、SNMP接口是通过接口映射配置实现,实现业务流程和接口配置的分离。
社区提供的通用接口配置,可以满足绝大部分场景的诉求,但针对部分机型、专有客户场景的定制化诉求难以快速满足。因此接口映射配置需要一种机制支持接口级或属性级的扩展、裁剪、重命名处理,确保差异化代码尽可能最小化。
三层定制能力
openUBMC社区发行版
社区发行版提供的通用基础能力,适用于社区大部份通用场景。
产品商用发行版
提供不同硬件形态的机型相对平台进行差异化定制的能力,按机型产品系列分类,在机型产品合并平台配置和机型定制配置。
客户定制发行版
提供最终用户差异化定制的能力,HPM固件包含所有客户定制内容,按客户分类,在根据定制客户名合并定制配置。
典型场景案例
场景 | 类型 |
---|---|
机架、机柜、管理板的接口差异配置 | 集成对应的openUBMC社区发行版接口组件 |
被社区接纳的OEM Uri | 集成对应的openUBMC社区发行版接口组件 |
智算机型,需要专门XPU运维接口 | 产品商用发行版差异化定制 |
某款无USB功能的机型,移除对应Uri | 产品商用发行版差异化定制 |
Redfish接口需要将OEM厂商名进行替换 | 产品商用发行版批量字段替换 |
SNMP接口的oid需要将OEM oid前缀替换 | 产品商用发行版批量字段替换 |
某客户定制机型,需要特殊字符开头的Web API接口 | 客户专属定制发行版差异化定制 |
某客户定制机型,需要在标准接口中新增某些字段 | 客户专属定制发行版差异化定制 |
接口配置策略
IMPORTANT
虽然目前机制提供了产品定制、客户定制能力,能满足大部分场景使用,但长期可维护性较差。推荐尽可能将定制诉求抽象为特性并寻求社区接纳。
定制配置语法
通用格式
interface_config
目录下的主配置文件为config.json
,其配置格式为:
{
"Uri.Actions": {
"Remove": [],
"Copy": [],
"Rename": []
},
"Property.Actions": [
{
"Target": "./Managers/NICs/NICs.json",
"Uri": "/redfish/v1/Managers/:managerid/NICs",
"Method": "GET",
"Remove": [],
"Modify": {},
"Rename": {}
}
],
"GlobalVariable": {
"OemIdentifier": "openUBMC"
}
}
Uri.Actions
: 接口层级的定制Remove
: 接口裁剪Copy
: 接口拓展Rename
: 接口重命名
Property.Actions
: 属性层级的定制Target
: 目标文件Uri
: 目标UriMethod
: 目标方法Remove
: 属性裁剪Modify
: 属性拓展Rename
: 属性重命名
GlobalVariable
: 批量字段替换的替换关系- 自定义
key
: 被替换的内部变量 - 自定义
value
: 替换为的字符串取值
- 自定义
接口层级定制
接口裁剪 Remove
"Remove": [
{
"Target": "ipmcget/sol.json",
"Uri": "/cli/v1/sol/info",
"Method": ["GET"]
}
]
Remove
为对象数组,每个对象标识裁剪的实例,接口裁剪分四种场景:
裁剪整个目录下所有的接口配置
Target
为待裁剪的目录,Uri
和Method
字段为空裁剪单个文件下接口配置
与场景1类似,不同的是
Target
为文件路径裁剪文件下的指定接口
Target
为文件路径,Uri
指定接口,Method
为空裁剪文件下的指定接口的确定方法
Target
为文件路径,Uri
指定接口,Method
可指定多个方法
NOTE
Target
均采用相对路径的方式,例如cli接口是相对基础配置路径xxx/opt/bmc/apps/cli/interface_config
,下同。
Source
类似,相对定制配置路径。
接口拓展 Copy
"Copy": [
{
"Source": "ipmcset/user.json",
"Target": "ipmcset/user.json"
}
]
Copy
为对象数组,每个对象标识拓展的实例,是将Source
的路径复制到Target
,Source
和Target
可同时为文件或者目录 假设"Source": "aa/bb/cc", "Target": "xx/yy/zz"
,不管是文件还是目录,表征的意义都是将cc
从目录aa/bb
复制到xx/yy
目录,并且重命名为zz
。
接口重命名 Rename
"Rename": [
{
"Target": "ipmcset/dft.json",
"OriginUri": "/cli/v1/maintenance/download",
"NewUri": "/cli/v1/maintenance/download2"
}
]
Rename
为对象数组,每个对象标识重命名的实例,是将Target
路径下的OriginUri
接口重命名为NewUri
,如上述配置,接口变成/cli/v1/maintenance/download2
属性层级定制
"Property.Actions": [
{
"Target": "ipmcget/target.json",
"Uri": "/cli/v1/_/bootdevice",
"Method": "GET",
"Remove": [
"RspBody/BootSourceOverrideTarget"
],
"Modify": {
"RspBody": {
"Version": "${Statements/GetVersion()}"
},
"Statements": {
"GetVersion": {
"Input": "${ProcessingFlow[1]/Destination/Version}",
"Steps": [
{
"Type": "Convert",
"Formula": "StringToNumber"
}
]
}
},
"ProcessingFlow": [
{
"Type": "Property",
"Path": "/bmc/kepler/Systems/1/Bios",
"Interface": "bmc.kepler.Systems.Bios",
"Destination": {
"Version": "Version"
}
}
],
"Rename": {
"Usage": "Instruction"
}
}
}
]
Property.Actions
是对象数组,每个对象表示属性层级定制的实例。Target
、Uri
、Method
用于确认待定制的指定文件、指定接口、指定方法 这里需要特别强调:
- 这里的属性不仅是请求体属性、响应体属性,应该是指待定制的接口JSON对象的属性
- 属性层级的定制应尽可能简单,一眼就能看出变化,复杂的推荐直接使用接口层级定制
属性裁剪 Remove
Remove
是字符串数组,每个元素表征待裁剪的属性,可以是多级属性,用/
分隔,例如RspBody/BootSourceOverrideTarget
,会删除子对象RspBody
的BootSourceOverrideTarget
属性
属性拓展 Modify
Modify
是对象,需要与原接口配置对象做合并,本质是两个JSON对象的合并,策略如下:
- 节点是复杂类型,包括对象、数组,采用追加方式
- 节点是简单类型,采用覆盖方式
- 特殊的
ProcessingFlow
: 对于引用追加的ProcessingFlow
元素时,其下表需要加上原始对象的ProcessingFlow
数组大小(脚本会自动处理,无需配置者处理)
属性重命名 Rename
Rename
是对象,每对key-value
表示待重命名的原属性名和新属性名,原属性名可以是多级属性,一样是/
分隔
定制前后对比
以上述配置为例,假设原接口为:
{
"Resources": [
{
"Uri": "/cli/v1/_/bootdevice",
"Interfaces": [
{
"Type": "GET",
"Description": "Get boot device",
"Usage": "ipmcget -d bootdevice",
"RspBody": {
"BootSourceOverrideTarget": "${ProcessingFlow[1]/Destination/value1}",
"BootSourceOverrideEnabled": "${ProcessingFlow[1]/Destination/value2}"
},
"ProcessingFlow": [
{
"Type": "Property",
"Path": "/bmc/kepler/Systems/1/BootOptions",
"Interface": "bmc.kepler.Systems.BootOptions",
"Destination": {
"BootSourceOverrideTarget": "value1",
"BootSourceOverrideEnabled": "value2"
}
}
],
"Echoes": [
"ipmcget/_bootdevice"
]
}
]
}
]
}
定制后的配置为:
{
"Resources": [
{
"Uri": "/cli/v1/_/bootdevice",
"Interfaces": [
{
"Type": "GET",
"Description": "Get boot device",
"Usage": "ipmcget -d bootdevice",
"RspBody": {
"BootSourceOverrideEnabled": "${ProcessingFlow[1]/Destination/value2}",
"Version": "${Statements/GetVersion()}"
},
"ProcessingFlow": [
{
"Type": "Property",
"Path": "/bmc/kepler/Systems/1/BootOptions",
"Interface": "bmc.kepler.Systems.BootOptions",
"Destination": {
"BootSourceOverrideTarget": "value1",
"BootSourceOverrideEnabled": "value2"
}
},
{
"Type": "Property",
"Path": "/bmc/kepler/Systems/1/Bios",
"Interface": "bmc.kepler.Systems.Bios",
"Destination": {
"Version": "Version"
}
}
],
"Statements": {
"GetVersion": {
"Input": "${ProcessingFlow[1]/Destination/Version}",
"Steps": [
{
"Type": "Convert",
"Formula": "StringToNumber"
}
]
}
},
"Echoes": [
"ipmcget/_bootdevice"
]
}
]
}
]
}
批量字段替换
映射器引入{{var}}
的用法,用两对连续大括号包围的字符串,表示是内部变量。根据在主配置文件config.json
中配置的映射关系,映射器在初始化接口时将这些内部变量替换为指定的字符串(Redfish schema的批量字段替换是在访问接口时)。替换范围包括mapping_config
的JSON配置文件,script和plugins的lua脚本和插件,以及Redfish接口的schema文件。
替换关系配置
在interface_config
目录下的主配置文件config.json
中,有一个GlobalVariable
属性与上述接口/属性层级定制平级,用于表示当前接口的批量字段替换的替换关系。配置参考如下:
"GlobalVariable": {
"OemIdentifier": "openUBMC"
}
该配置即表示将映射器配置中的{{OemIdentifier}}
替换为openUBMC
openUBMC社区发行版、产品商用发行版、客户定制发行版均可配置,其中配置关系为客户定制发行版 > 产品商用发行版 > openUBMC社区发行版。openUBMC社区发行版需要保证所有内部变量有一个默认的替换关系,在构建时,bingo会将openUBMC社区发行版和产品商用发行版的配置合并;接口初始化时,映射器会根据当前定制的客户将客户定制发行版与openUBMC社区发行版/产品商用发行版的配置合并得到最终的替换关系,并对该接口类型的所有映射器配置进行替换。
IMPORTANT
由于批量字段替换在接口/属性层级定制完成后进行,因此接口/属性层级定制的配置中需要设计替换的字段也要使用{{var}}
格式的内部变量表示,确保层级定制后的批量字段替换正常。
当前部分默认配置
以当前openUBMC社区发行版的部分默认配置为例,Redfish接口的部分openUBMC社区发行版配置:
"GlobalVariable": {
"OemIdentifier": "openUBMC"
}
snmp接口的部分openUBMC社区发行版配置:
"GlobalVariable": {
"SnmpOemIdentifier": "2011.2.235.1.1"
}
当前已将存量映射器配置中的Redfish接口的openUBMC
字段整改为{{OemIdentifier}}
,snmp
接口的oid
中的2011.2.235.1.1
替换为{{SnmpOemIdentifier}}
。后续增量开发Redfish接口和snmp接口时需要注意,涉及openUBMC
字样的替换为{{OemIdentifier}}
,snmp
接口的oid
中的2011.2.235.1.1
替换为{{SnmpOemIdentifier}}
。另外开发插件、脚本的lua
代码时注意不要使用带敏感字段的变量名和函数名。
使用注意事项
Redfish接口自身存在厂商名替换机制替换OEM字段,具体是通过BMCSet_RedfishCustomManuName
装备定制化项设置替换的厂商名,生其生效优先级高于多层级定制的批量字段替换功能,同时使用时需要注意厂商替换生效的优先级是:
- 装备定制化阶段(
BMCSet_RedfishCustomManuName
)定制的Manufacturer
优先级最高; - 若
Manufacturer
未定制(为空或openUBMC),次优先级为Customer定制(BMCSet_PackageCustomer
)生效的客户定制发行版配置的config.json
内的OemIdentifier
; - 若客户
Customer
也未定制,则构建openUBMC社区发行版/产品商用发行版配置的config.json
内的OemIdentifier
生效; - 若都未生效,默认使用openUBMC.
多层级定制配置文件获取
openUBMC社区、产品商用层级接口配置文件获取
在manifest下执行个人构建(不加-t
参数或添加-t personal
),生成的接口配置压缩文件在目录output/packet/inner/interface_config
下,解压后获取与环境中运行状态等效的接口配置。 Product文件为构建时指定的产品类型,其他文件为该产品类型下,添加客户定制化后生成的接口配置。