MDS(Module Description Source)是统一格式的组件模型定义源文件,对组件管理的数据,IPMI进行建模,同时也对组件的扩展和定制能力进行建模,其设计目标是整个系统以及开发工具具有相同的模型基础。 MDS作为系统资源的定义,可以指定组件的功能范围和数据模型,看护业务代码架构的稳定性,是微组件框架的核心。 工程框架基于模型源文件自动生成相关的配置文件和代码,以达到简化组件开发的目的,组件开发人员主要围绕内存对象编写业务逻辑代码。
BMCStudio提供了可视化配置MDS的能力,同时带有MDS的一致性校验功能,推荐使用BMCStudio进行MDS的配置,使用介绍请参考《BMC Studio用户指南》。
组成
组成MDS的文件都在组件仓的/mds
目录下,为了避免整个系统出现多种配置描述语言,MDS也采用json格式
- service.json
描述组件的服务模型,包括名称、版本、依赖等,以及对其他组件APP资源协作接口属性订阅、访问
- model.json
描述组件的数据模型,即类定义,包括类的属性、对象路径、接口等
- ipmi.json
描述组件的IPMI命令模型,包括命令字配置以及请求、响应的数据格式配置
- types.json
该配置文件可选配,用于model中有复杂数据结构场景 描述组件数据模型和IPMI命令模型依赖的数据类型,即类属性、接口属性、接口方法、IPMI命令中的结构体、枚举类型
- schema.json
schema.json文件用于进行字段格式校验等工作,该文件根据model.json自动生成,不需要手动配置
service.json
service.json主要用于定义组件名称和说明信息、组件独立构建和DT测试依赖的其他组件、组件所依赖的协作接口等内容。
配置示例:
{
"name": "app_name",
"type": "application",
"deployConfig": "app.service",
"version" : "1.0.1",
"author" : "",
"license" : "Mulan PSL v2",
"language": "lua",
"description" : "micro-component app",
"codeGenPolicy": {
"version": 3
},
"dependencies": {
"build": [
{
"conan": "liba2/[>1.0.0]"
},
{
"conan": "liba3/[>=1.1.0]"
},
],
"test": [
{
"conan": "lib/1.2.3"
}
]
},
"required": [
{
"path": "*",
"interface": "bmc.kepler.XXXXX"
},
{
"path": "/bmc/kepler/XXXXX",
"interface": "bmc.kepler.XXXXX",
"properties": {}
},
{
"path": "/bmc/kepler/XXXXXX/${Id}",
"interface": "bmc.kepler.XXXX",
"properties": {}
}
]
...
}
字段说明:
name
组件名称,命名采用小写+下划线组合的命名风格,必须与部署态MDS路径/opt/bmc/apps/xxx/mds中xxx命名、代码仓的名称保持一致
type
组件类型,当前的类型有:application、library、tool、command、configuration
deployConfig
组件部署时的配置,当组件类型是application时,组件部署时的配置(当前是systemd的配置文件)
version
组件版本,采用三段式点分式版本号
author
组件的作者,可以是个人,可以是组织/企业名称
license
组件遵循的license,默认是Mulan PSL v2
language
组件的编码语言(如Lua,C,C++),用于生成代码时工具选择对应的模板
description
组件的简要描述,一句话简要描述组件是什么
codeGenPolicy
组件代码生成策略,代码生成工具将基于生成策略指定的版本等信息生成配套的代码
dependencies
表示组件构建或者测试时的依赖,主要是lib库和框架或平台基础组件,可以精确指定和模糊指定版本,版本的语法沿用conan策略,具体可参考《BMC Studio CLI (bingo)》。
1.2.3
:精确指定组件或lib为stable版本1.2.3;[>=1.0.0]
:模糊指定组件或lib是1.0.0以上的stable版本,版本号最大并且最新发布的;[>1.0.0 <1.10.0]
:模糊指定组件或lib的版本范围,版本号在范围限制下最新发布的;
required
该字段主要定义组件对于其他资源写作接口的依赖
注意:若不在此处配置则无法在代码中调用对应的资源
表示组件运行时需要使用的资源协作接口,主要用于生成在组件内部生成接口访问的客户端代码;
interface
:运行时依赖的接口名称path
:运行时依赖的接口所在的对象路径,分为三种描述方式:- 表示不关注接口所在的具体对象路径(ObjectPath)
- 不带动态参数的对象路径,会在运行态进行依赖检查
- 带动态参数的对象路径,会在运行态进行依赖检查
properties
:表示运行时属性依赖,目前支持指定属性的变更信号精准订阅(subscribe)optional
:表示接口依赖的强度,true表示弱依赖,即运行时接口不存在不会影响本组件运行,默认为falsestage
:表示接口满足的阶段,即被依赖的接口必须在什么阶段提供,包括初始化阶段(starting),运行阶段(running),默认为running
model.json
该文件的核心是定义组件的内部资源和对外资源,对应的数据模型定义,数据模型的持久化方式、访问权限等
MDS类和属性部分配置示例:
{
"ClassA": {
"tableName":"t_classa",
"tableLocation":"Local",
"path": "/bmc/kepler/xxx/${Id}",
"privilege": ["UserMgmt", "BasicSetting"],
"interfaces":{
"bmc.kepler.IClassA":{
"privilege": ["SecurityMgmt"],
"properties":{
"PropA1": {
"privilege": {
"read": ["ReadOnly"],
"write": ["ConfigureSelf"],
},
"usage": ["CSR", "PermanentPer"]
},
"PropA2": {
"usage": ["ResetPer"],
"alias": "IClassAPropA1"
}
}
},
"bmc.kepler.IClassAExtend":{
"properties":{
"PropA2": {
"usage": ["PoweroffPer"],
"alias": "IClassAExtendPropA2",
"sensitive": true,
"critical": true
}
},
"methods": {
"Method1" : {
"privilege": ["DiagnoseMgmt"],
}
}
},
"description": "this is a demo"
},
"properties" : {
…
}
},
…
}
字段说明:
持久化配置字段
MDS类支持基于数据库的持久化,类定义中配置tableLocation为Local表示本地持久化,不配或者配置其它取值时为远程持久化,持久化相关的详细说明见Lua编程框架的《持久化》章节
tableName
指定该对象持久化时使用的数据库表名
tableLocation
指定持久化方式为远程持久化还是本地持久化,该字段取值只能为"Local",配置后即指定该对象为本地持久化,若不配置则为远程持久化
ClassA
业务模型定义的MDS类名,使用大驼峰命名风格,如果类的实例化对象需要挂载到D-Bus(即存在path字段),则类名必须与path对应的文件名保持一致(详见MDB语法),如果类的实例化对象不需要挂载到D-Bus(不存在path字段),则类名不做约束,只需要保证唯一即可
path
表示类的接口(interfaces下的内容)挂载到D-Bus上的对象路径
interfaces
表示该类支持的资源协作接口的集合,这些接口在MDB中有详细定义
bmc.kepler.IClassA
对象实现的接口名,必须跟mdb_interface中的接口名称一致
properties
表示需要挂到资源协作接口下的属性的集合,这里只需写出属性名( PropA1,PropA2 …,使用大驼峰命名风格)以及用途(usage),不需要写属性类型以及范围等校验信息,这些信息已经在MDB中有详细定义
usage
表示该属性的用途,可以是多个用途的组合,也可以为空。用途类型有CSR,PermanentPer, PoweroffPer,ResetPer,TemporaryPer,PoweroffPerRetain,ResetPerRetain,TemporaryPerRetain
- 配置CSR说明该字段的值可来源于CSR中配置的值
此外的可选项PermanentPer,PoweroffPer,ResetPer,TemporaryPer,PoweroffPerRetain,ResetPerRetain,TemporaryPerRetain指定该字段的持久化类型,只能选择其中一个进行配置,取值的含义为:
持久化类型 | 描述 |
---|---|
TemporaryPer | 临时持久化(复位丢失,进程重启需要保留的数据) |
TemporaryPerRetain | 临时持久化且对象删除时保留 |
ResetPer | 复位持久化(掉电丢失,复位需要保留的数据) |
ResetPerRetain | 复位持久化且对象删除时保留 |
PoweroffPer | 掉电持久化(恢复出厂设置丢失,掉电需要保留的数据) |
PoweroffPerRetain | 掉电持久化且对象删除时保留 |
PermanentPer | 永久持久化(恢复出厂设置需要保留的数据) |
description
是对Class的注释说明,不参与自动生成代码
alias
属性别名。属性别名用于解决资源协作接口属性与其他资源协作接口属性或私有属性同名冲突的问题,确保可以通过属性(别)表示名访问唯一属性,包括持久化访问、D-Bus对象属性访问等。属性别名存在如下使用约束:
- 只有资源协作接口属性允许配置别名,私有属性禁止配置别名,并且属性别名不能与已有资源协作接口属性名或私有属性名重名
- 当有N个资源协作接口属性同名时,至少需要为其中N-1个资源协作接口属性配置别名(或者全部的N个资源协作接口属性配置别名)
- 对于同时具有usage用途类型包含“CSR”和alias别名配置的属性,需要使用属性别名替代属性名进行CSR配置
- 别名不允许随意变更,否则可能引发兼容性问题
privilege
如示例所示,privilege字段可以配置在对象、接口、属性、方法上,说明如下:
权限类型包括UserMgmt,BasicSetting,KVMMgmt,VMMMgmt,SecurityMgmt,PowerMgmt,DiagnoseMgmt,ReadOnly,ConfigureSelf
当访问者只有ConfigureSelf权限时,但是D-Bus路径、资源协作接口、或者资源协作接口属性/方法没有配置权限,或配置了权限但没有ConfigureSelf权限,框架会报需要修改密码的错误
当多个层级都配置权限时,采用局部继承全局的原则,即实际需要的权限是:
- 资源协作接口属性/方法访问权限(privilege/privilege)组合了 资源协作接口的访问权限(privilege)和 D-Bus路径访问权限(privilege),即多个权限需要同时满足
- 资源协作接口的访问权限(privilege)组合了D-Bus路径访问权限(privilege),即多个权限需要同时满足
权限配置的详细说明如下:
权限名称 | 权限功能 | 可操作项 |
---|---|---|
ReadOnly | 查询功能 | 可以登录以及查看除安全配置、调试诊断、双因素认证、在线用户和常规设置以外的信息 |
BasicSetting | 常规设置 | 服务器带外管理基本配置,如产品信息配置、性能监控配置、告警、事件等功能 |
UserMgmt | 用户配置 | 用户和密码相关的配置,如用户管理、许可证管理、权限管理、恢复出厂设置 |
PowerMgmt | 电源控制 | 电源设置、功率设置、服务器上下电设置 |
SecurityMgmt | 安全配置 | 安全性的查询和配置,如操作日志、安全日志、登录规则、端口服务、一键收集日志 |
DiagnoseMgmt | 调试诊断 | 现场定位、调试操作如传感器模拟、串口重定向记录 |
VMMMgmt | 远程媒体 | 设置VMM通信加密、注销会话、BMA管理 |
KVMMgmt | 远程控制 | 通过HTML5集成远程控制台、Java集成远程控制台、独立远程控制台和VNC客户端访问服务器实时桌面、设置VNC超时时长、键盘布局、VNC密码、登录规则、SSL加密、BMA管理等 |
ConfigureSelf | 配置自身 | 可以配置帐户自身的密码以及管理SSH公钥、SNMPv3加密密码、SNMPv3加密算法和鉴权算法,预置角色默认拥有此权限,自定义角色的配置自身权限可设置 |
sensitive
表示属性是否是敏感数据,如果取值为true,在调试终端查看或一键收集导出时,框架自动完成脱敏处理,默认为false
critical
表示属性是否是关键数据,如果取值为true并且是掉电持久化,在持久化时会实时写入磁盘并完成备份,否则使用周期性备份策略,默认为false
MDS私有类属性部分配置示例:
组件业务代码中可能会使用到一些不需要在资源协作接口中对外暴露的数据模型,但是希望通过微组件框架来管理,从而可以实现框架支持的添加说明、配置持久化,通过CSR进行配置等功能,此时可以使用MDS私有类
{
"ClassA": {
"tableName":"t_classa",
"tableLocation":"Local",
"path":"bmc/kepler/xxx/${Id}",
"interfaces":{
…
},
"properties": {
"PropA4": {
"usage": ["PoweroffPer"],
"baseType": "U32",
"default": 1,
"minimum": 0,
"maximum": 100
},
"PropA5": {
"usage": ["CSR"],
"baseType": "U8[]",
"refInterface":"bmc.kepler.IBlockIO"
},
"PropA6": {
"usage": ["CSR"],
"baseType": "String",
"minLength": 1,
"maxLength": 64,
"pattern": "^(\\([0-9]{3}\\))?[0-9]{3}-[0-9]{4}$"
}
}
},
…
}
字段说明:
properties
表示类的私有属性(不会挂到资源协作接口下,不能与挂到资源协作接口下的属性和属性别名重名),这些属性(PropA4,PropA5 …)需要详细定义;注意这里的properties与interfaces平级
usage
用法与接口属性中的usage字段相同
baseType
表示属性类型,接口属性的类型已被接口定义描述,但是私有属性没有这些描述,需要自行定义
取值有U8,U8[](U8数组),U16, U16[],U32, U32[],U64, U64[],S16,S16[],S32,S32[],S64,S64[],Double,Double[],String,String[],不使用标准schema的type字段指定属性的类型,当types.json中配置有自定义类型时,该字段还可以取值为Array,Struct,Enum,具体请参考types.json部分说明
default
表示属性默认值,根据类型给出即可,""表示空字符串,可选字段,如果没有指定,代码中对于不同类型生成的默认值是0、空字符串、空数据、空字典
类型校验字段
minimum、maximum是针对数字型的属性的取值范围;minLength、maxLength是针对字符串型的属性的长度范围; pattern是针对字符串型的属性的格式要求,使用正则匹配;如需其它类型的数据校验,可参考json-schema官方文档增加类型校验字段
refInterface
属性是引用(CSR中的#语法)其它object的场景,获取这个object下对应interface的method和properity的集合
表示属性需要通过该接口下的方法(Read,Write)获取/设置数据(一般用于关联块读写的器件对象,如EEPROM),或者直接读取该接口下的属性(一般用于关联软件配置类对象,如Component),这里的接口(bmc.kepler.IBlockIO)需要遵循资源协作接口统一定义,并在service.json的require中显性描述出来
types.json
types.json主要是模型中的复杂类型定义,包括结构体、枚举
配置示例:
{
"defs": {
"AaaBbb": {
"MemVar1": {
"baseType": "Boolean"
},
"b2": {
"baseType": "Struct",
"$ref": "#/defs/XxxYyy"
}
},
"XxxYyy": {
"MemVar3": {
"baseType": "S64[]"
},
"MemVar4": {
"baseType": "String"
}
},
"EAbcXyz": {
"EnumVal1" : 1,
"EnumVal2" : 2
}
}
}
字段说明:
- defs为固定字段,表示复杂类型定义的入口
- AaaBbb、 XxxYyy、 EAbcXyz是结构体、枚举类型的名称, MemVar1/MemVar2/MemVar3/MemVar4是结构体成员名称,EnumVal1/EnumVal2是枚举变量名称,使用大驼峰风格
复杂数据类型配置示例(以model.json为例):
{
"ClassDemo": {
"path": "/bmc/kepler/Demo/:Id",
"interfaces" : {},
"properties": {
"a1" : {
"baseType": "Struct",
"$ref": "types.json#/defs/AaaBbb"
},
"a2": {
"baseType": "Array",
"items": {
"baseType": "Struct",
"$ref": "types.json#/defs/AaaBbb"
}
},
"a3" : {
"baseType": "Enum",
"default": "EnumVal1",
"$ref": "types.json#/defs/EAbcXyz"
},
"a4" : {
"baseType": "Struct",
"$ref": "mdb://bmc/demo/IDemo.json#/defs/Struct1"
},
"a5": {
"baseType": "Enum",
"$ref": "mdb://bmc/demo/IDemo.json#/defs/Enum1"
}
}
}
}
字段说明:
baseType取值扩展
除基本类型外,types.json中定义的类型可以通过不同的baseType取值来引用,可选扩展取值如下:
Struct表示该属性的类型是结构体,$ref描述了该结构体定义的位置, types.json#/defs/AaaBbb表示结构体定义是types.json中"defs"这个对象下的AaaBbb
Array表示该属性的类型是数组,数组的成员(items)可以是基本类型,也可以是结构体/枚举,如果是结构体/枚举,则用$ref描述结构体/枚举定义的位置
Enum表示该属性的类型是枚举, default表示该属性的默认值取值(内容必须与枚举定义中的变量名一致), $ref描述了该枚举定义的位置, types.json#/defs/EAbcXyz表示枚举定义是types.json中"defs"这个对象下的EAbcXyz
$ref特殊取值:
mdb://bmc/demo/IDemo.json#/defs/Struct1和mdb://bmc/demo/IDemo.json#/defs/Enum1分别表示引用了资源协作接口描述文件中的结构体定义和枚举定义,该语法同样适用于数组
ipmi.json
配置示例:
{
"package" : "XXIpmiCmds",
"cmds": {
"CmdName1" {
"netfn": "0x0f",
"cmd": "0x0f",
"priority": "Default",
"role" : "Administrator",
"req" : [
{"data": "Iana", "baseType": "U32", "len": "3B", "value": "0xFFFF", "customizedRule": "Manufacturer"},
{"data": "SubCmd", "baseType": "U8", "len": "1B", "value": "0xFF"},
{"data": "Reserved", "baseType": "U8", "len": "4b"},
{"data": "ChannelNum", "baseType": "U8", "len": "4b"},
{"data": "Length", "baseType": "U16", "len": "2B"},
{"data": "Data", "baseType": "U8[]", "len": "Length"},
{"data": "Sign", "baseType": "String", "len": "64B"},
{"data": "Padding", "baseType": "U8[]", "len": "*"}
],
"rsp": [
{"data": "Iana", "baseType": "U32", "len": "3B"}
],
"sysLockedPolicy": "Allowed",
},
"CmdName2": {
}
}
}
字段说明:
package
表示IPMI命令包的名称,采用大驼峰命名风格
cmds
表示IPMI命令定义集合
CmdName1
表示命令的名称,采用大驼峰命名风格,如SetEventReceiver, GetDeviceId,WriteSmbios等,同一个组件内定义的IPMI命令名称不能重复
netfn
表示命令的网络功能码, 16进制形式的数字字符串
cmd
表示命令字,16进制形式的数字字符串
priority
IPMI的路由是通过优先级来进行的,通过配置优先级可以配置IPMI命令的实际处理函数。 该字段用于配置命令的优先级,可选的优先级有Default、OEM、ODM、OBM、EndUser(最终用户定制),运行态的优先级是 Default < OEM < ODM < OBM < EndUser
privilege
表示执行该命令时用户需要的权限,可选的权限有UserMgmt,BasicSetting,KVMMgmt,VMMMgmt,SecurityMgmt,PowerMgmt,DiagnoseMgmt,ReadOnly,ConfigureSelf,支持配置多个,多个时需要同时满足才能执行该命令
req/rsp
表示命令的请求和响应,其内容是数组,采用结构化的描述,req/rsp各个字段:
- data表示req/rsp的字段名称,采用大驼峰命名风格
- baseType表示字段的类型(跟model.json中的用法相同)
- len表示字段的长度(B代表字节,b代表bit位,*代表不定长)
- value表示字段的值(过滤条件)
- 对于变长的数据,如果在整个数据段的中间,则必须有单独字段描述数据的实际长度(参考Length和Data),且数据的len用表示长度的字段名称填充,如果在整个数据段的末尾(参考Padding),则数据的len可以用*填充,类型可以是U8[]或String
- customizedRule表示定制化规则,当前仅支持厂商定制化Manufacturer(请求或响应中的字段将被替换为定制厂商标识)
sysLockedPolicy
表示系统锁定时IPMI命令是否允许执行。可选的配置有Allowed(允许执行)、Forbidden(禁止执行)。可选字段,缺省为Allowed(允许执行)
sensitive
表示请求或响应数据中存在敏感信息,用于IPMI trace等场景对数据进行脱敏处理