openUBMC社区的SNMP接口采用接口映射配置方案实现,需要将命令配置到json文件中。SNMP接口的接口映射配置文件在rackmount代码仓的snmp路径下。
本篇指导仅介绍SNMP接口独有的配置规则,接口映射配置公共机制可见《接口映射配置》。
接口Uri
Uri的示例如下所示:
"Uri": "/snmp/1.3.6.1.4.1.{{SnmpOemIdentifier}}.0.0.1/Systems/Readwrite"NOTE
{{SnmpOemIdentifier}}为批量字段替换的目标替换字段,实际使用时如默认配置,会加载为2011.2.235.1.1(具体含义和配置方法可见《接口多层级定制》批量字段替换章节)
Uri的格式为:
/snmp/接口Oid/接口名称/接口模式接口Oid 每一个接口Oid要保证是全局唯一的;
接口名称 每一个接口名称可以不是全局唯一的;
接口模式
Readwrite: 支持GET/PATCH操作,可读可写;Readonly: 只支持GET操作,只可读;Setonly: 只支持PATCH或者POST操作,用于只写、导入导出、升级等操作。
数据类型
SNMP协议的数据类型有三大类:通用数据类型、通用结构数据类型和应用数据类型。目前仅涉及SNMP协议的通用数据类型和应用数据类型, 其中涉及的通用数据类型为:
INTEGER: 整型,是-2,147,483,648~2,147,483,647之间的有符号整数,对应的接口映射配置属性数据类型为integer;OCTET STRING: 字符串,对应的接口映射配置属性数据类型为string;OBJECT IDENTIFIER: 对象标识符,一般用于表示告警事件Oid, 对应的接口映射配置属性数据类型为objectId;
涉及的应用数据类型为:
IpAddress: IP地址,对应的接口映射配置属性数据类型为ipAddress.
SNMP接口分为简单接口和Table类型接口,简单接口用于查询和设置单个属性,Table类型接口用于查询和设置集合资源的多个属性。
简单接口
简单接口的配置规则无特殊要求,可参考《接口映射配置》进行配置。
配置示例
{
"Resources": [
{
"Uri": "/snmp/1.3.6.1.4.1.{{SnmpOemIdentifier}}.0.0.1/Systems/Readwrite",
"Interfaces": [
{
"Type": "GET",
"RspBody": {
"Name": "${ProcessingFlow[1]/Destination/Name}"
},
"ProcessingFlow": [
{
"Type": "Property",
"Path": "/bmc/kepler/System",
"Interface": "bmc.kepler.System",
"Destination": {
"Name": "Name"
}
}
]
},
{
"Type": "PATCH",
"ReqBody": {
"Type": "object",
"Required": true,
"Properties": {
"UserName": {
"Type": "string",
"Required": true
}
}
},
"ProcessingFlow": [
{
"Type": "Property",
"Path": "/bmc/kepler/System",
"Interface": "bmc.kepler.System",
"Source": {
"Name": "${ReqBody/Name}"
}
}
]
}
]
}
]
}Table类型接口
Table类型接口用于查询和设置集合资源的多个属性。
配置示例
{
"Resources": [
{
"Uri": "/snmp/1.3.6.1.4.1.{{SnmpOemIdentifier}}.0.0.2/Devices/Readwrite",
"Sequence": [
{
"Name": "Id",
"Type": "integer",
"Access": "Readonly",
"Primary": true
},
{
"Name": "Enabled",
"Type": "integer",
"Access": "Readwrite"
}
],
"Interfaces": [
{
"Type": "GET",
"RspBody": {
"Devices": "${Statements/Devices()}"
},
"Statements": {
"Devices": {
"Input": "${ProcessingFlow[1]/Destination/Devices}",
"Steps": [
{
"Type": "Expand",
"Formula": "1"
}
]
}
},
"ProcessingFlow": [
{
"Type": "List",
"Path": "/bmc/kepler/Devices",
"Destination": {
"Members": "Devices"
}
}
]
},
{
"Type": "PATCH",
"ReqBody": {
"Type": "object",
"Required": true,
"Properties": {
"Id": {
"Type": "integer",
"Required": true
},
"Enabled": {
"Type": "integer"
}
}
},
"ProcessingFlow": [
{
"Type": "Property",
"Path": "/bmc/kepler/Devices/${ReqBody/Id}",
"Interface": "bmc.kepler.Device",
"Source": {
"Enabled": "${ReqBody/Enabled}"
}
}
]
}
]
},
{
"Uri": "/bmc/kepler/Devices/:id",
"Interfaces": [
{
"Type": "GET",
"RspBody": {
"Id": "${Uri/id}",
"Enabled": "${ProcessingFlow[1]/Destination/Enabled}"
},
"ProcessingFlow": [
{
"Type": "Property",
"Path": "/bmc/kepler/Devices/${Uri/Id}",
"Interface": "bmc.kepler.Device",
"Destination": {
"Enabled": "Enabled"
}
}
]
}
]
}
]
}Sequence
Sequence字段用于指示接口中每一个属性的属性名、数据类型和是否为主键。Sequence中至少配置有一个主键,通过Primary字段进行设置。主键的值用于区分不同的子资源,配置示例如下所示:
"Sequence": [
{
"Name": "Id",
"Type": "integer",
"Access": "Readonly",
"Primary": true
},
{
"Name": "Enabled",
"Type": "integer",
"Access": "Readwrite"
}
]上述例子中,Id字段为主键。假设系统有4个device子资源,则SNMP接口返回的Id可为1,2,3,4,用于区分不同的device.
IMPORTANT
配置时务必确保主键取值互不相同,可以用于区分不同的子资源,否则处理时将会因覆盖而获得不可预期的返回。
响应体RspBody
示例如下:
"RspBody": {
"Devices": "${Statements/Devices()}"
}RspBody中只有一个属性,属性值为集合资源数组,其中数组中的每一个元素代表一个子资源。。例如,子资源返回的属性值如下所示:
{
"Id": 1,
"Enabled": 2
}请求体ReqBody
请求体中必须要配置主键,主键可用于接口映射配置中索引对应的子资源;主键的属性名和数据类型要跟Sequence中定义的主键一致;而请求体中的其他属性则可以根据业务的需要自行配置。如下所示:
{
"Type": "PATCH",
"ReqBody": {
"Type": "object",
"Required": true,
"Properties": {
"Id": {
"Type": "integer",
"Required": true
},
"Enabled": {
"Type": "integer"
}
}
},
"ProcessingFlow": [
{
"Type": "Property",
"Path": "/bmc/kepler/Devices/${ReqBody/Id}",
"Interface": "bmc.kepler.Device",
"Source": {
"Enabled": "${ReqBody/Enabled}"
}
}
]
}ReqBody中的Id为主键,属性名和数据类型跟Sequence中定义的一致。
接口错误码
SNMP接口通过错误引擎来定义接口执行失败时返回的SNMP错误码,在mdb_interface代码仓错误类型定义中,为错误类型定义对应SnmpStatusCode来定义错误引擎与SNMP错误码的映射关系。当前错误引擎的大部分错误类型都配置了SnmpStatusCode;若未配置,则SnmpStatusCode默认为5.
如下例中的错误类型定义,当SNMP接口请求处理过程中,业务代码中抛出错误PropertyValueTypeError,则最后收到的SNMP错误码将是SnmpStatusCode定义的7.
"PropertyValueTypeError": {
"Description": "Indicates that a property was given the wrong value type, such as when a number is supplied for a property that requires a string.",
"Message": "The value %1 for the property %2 is of a different type than the property can accept.",
"Severity": "Warning",
"NumberOfArgs": 2,
"ParamTypes": [
"string",
"string"
],
"Resolution": "Correct the value for the property in the request body and resubmit the request if the operation failed.",
"HttpStatusCode": 400,
"IpmiCompletionCode": "0xFF",
"SnmpStatusCode": 7,
"TraceDepth": 0
}SNMP协议的错误码定义
SNMP协议定义了18种错误码,错误码对应表如下:
| 宏定义 | 常量值 | 说明 |
|---|---|---|
SNMP_ERRORSTATUS_NOERROR | 0 | 未发生任何错误 |
SNMP_ERRORSTATUS_TOOBIG | 1 | 无法将请求的 SNMP 操作结果放在单个 SNMP 消息中 |
SNMP_ERRORSTATUS_NOSUCHNAME | 2 | 请求的 SNMP 操作标识了一个未知变量 |
SNMP_ERRORSTATUS_BADVALUE | 3 | 请求的 SNMP 操作尝试更改变量,但它指定了语法或值错误 |
SNMP_ERRORSTATUS_READONLY | 4 | 请求的 SNMP 操作尝试更改不允许更改的变量 |
SNMP_ERRORSTATUS_GENERR | 5 | 在请求的 SNMP 操作期间,出现此处列出的错误以外的错误 |
SNMP_ERRORSTATUS_NOACCESS | 6 | 指定的 SNMP 变量不可访问 |
SNMP_ERRORSTATUS_WRONGTYPE | 7 | 值指定了与变量所需的类型不一致的类型 |
SNMP_ERRORSTATUS_WRONGLENGTH | 8 | 值指定了与变量所需长度不一致的类型 |
SNMP_ERRORSTATUS_WRONGENCODING | 9 | 值包含与字段的 ASN.1 标签不一致的抽象语法表示法(ASN.1)编码 |
SNMP_ERRORSTATUS_WRONGVALUE | 10 | 值不能分配给变量 |
SNMP_ERRORSTATUS_NOCREATION | 11 | 变量不存在,且代理无法创建它 |
SNMP_ERRORSTATUS_INCONSISTENTVALUE | 12 | 该值与其他托管对象的值不一致 |
SNMP_ERRORSTATUS_RESOURCEUNAVAILABLE | 13 | 将值分配给变量需要分配当前不可用的资源 |
SNMP_ERRORSTATUS_COMMITFAILED | 14 | 未发生验证错误,但未更新任何变量 |
SNMP_ERRORSTATUS_UNDOFAILED | 15 | 未发生验证错误。某些变量已更新,因为无法撤消其赋值 |
SNMP_ERRORSTATUS_AUTHORIZATIONERROR | 16 | 发生授权错误 |
SNMP_ERRORSTATUS_NOTWRITABLE | 17 | 变量存在,但代理无法修改它 |
SNMP_ERRORSTATUS_INCONSISTENTNAME | 18 | 变量不存在;代理无法创建它,因为命名对象实例与其他托管对象的值不一致 |
NOTE
后续如果要在mdb_interface代码仓错误类型定义中新增错误类型时,请根据后台业务需要,为新增的错误类型增加SNMP错误码定义(即SnmpStatusCode字段),否则当后台组件返回该种类型错误时,SNMP接口会默认返回SNMP_ERRORSTATUS_GENERR.
SNMPv1错误码映射
SNMPv1版本的错误码只有错误码定义中常量值为0-5的6种,因此使用SNMPv1版本访问SNMP接口时,如果后台组件返回的SNMP错误码不属于上述6种错误码,SNMP接口层会对错误码进行转换。
- 因节点值导致的错误,如错误的值、类型、长度、编码失败、值不一致,转化至
SNMP_ERRORSTATUS_BADVALUE - 因无法获取导致的错误,如节点未创建、鉴权失败、不可写、节点名不一致,转化至
SNMP_ERRORSTATUS_NOSUCHNAME - 因其它不可知错误导致的操作失败,转化至
SNMP_ERRORSTATUS_GENERR
具体的转换规则如下:
| 后台抛出错误码宏定义 | 转换至SNMPv1错误码宏定义 |
|---|---|
| SNMP_ERRORSTATUS_WRONGTYPE | SNMP_ERRORSTATUS_BADVALUE |
| SNMP_ERRORSTATUS_WRONGLENGTH | |
| SNMP_ERRORSTATUS_WRONGENCODING | |
| SNMP_ERRORSTATUS_WRONGVALUE | |
| SNMP_ERRORSTATUS_INCONSISTENTVALUE | |
| SNMP_ERRORSTATUS_NOACCESS | SNMP_ERRORSTATUS_NOSUCHNAME |
| SNMP_ERRORSTATUS_NOCREATION | |
| SNMP_ERRORSTATUS_AUTHORIZATIONERROR | |
| SNMP_ERRORSTATUS_NOTWRITABLE | |
| SNMP_ERRORSTATUS_INCONSISTENTNAME | |
| SNMP_ERRORSTATUS_RESOURCEUNAVAILABLE | SNMP_ERRORSTATUS_GENERR |
| SNMP_ERRORSTATUS_COMMITFAILED | |
| SNMP_ERRORSTATUS_UNDOFAILED |
特有字段说明
SNMP接口存在一些与其它北向接口不一样的配置规则。
SNMPv1v2cSupported字段
用于配置SNMPv1和SNMPv2c版本是否允许访问此SNMP接口,如果没有配置则默认为true(即允许SNMPv1和SNMPv2c版本访问此SNMP接口)。
配置示例:
{
"Resources": [
{
"Uri": "/snmp/1.3.6.1.4.1.{{SnmpOemIdentifier}}.0.0.1/Systems/Readwrite",
"Interfaces": [
{
"Type": "PATCH",
"SNMPv1v2cSupported": false,
"ReqBody": { xxx },
"ProcessingFlow": [
{ xxx }
]
}
]
}
]
}上述示例中,SNMPv1v2cSupported的值被置为false,因此SNMPv1和SNMPv2c版本无法访问此接口。
@Instance字段
对于Table类型接口,接口的Instance值默认与主键值一致,如果要自定义Table类型接口的Instance值,则可以使用@Instance字段进行配置。@Instance字段是一个数组类型,用于支持拥有多个Instance值的SNMP接口。如下所示:
{
"Resources": [
{
"Uri": "/snmp/1.3.6.1.4.1.{{SnmpOemIdentifier}}.7.50/fruPowerDescriptionTable/Readwrite",
"Sequence": [
{
"Name": "fruNum",
"Type": "integer",
"Access": "Readonly",
"Primary": true
},
{
"Name": "fruPowerControl",
"Type": "string",
"Access": "Setonly"
}
],
"Interfaces": [
{
"Type": "GET",
"RspBody": {
"Sequence": [
{
"@Instance": [
1
],
"fruNum": 0,
"fruPowerControl": "write-only"
},
{
"@Instance": [
5
],
"fruNum": 4,
"fruPowerControl": "write-only"
}
]
}
}
]
}
]
}上述接口映射配置配置了一个Table类型SNMP接口的GET类型的接口,主键为fruNum. 当我们walk这个SNMP接口时,会调用这个SNMP接口的GET类型接口,得到如下返回(假设{{SnmpOemIdentifier}}为默认的2011.2.235.1.1):
iso.3.6.1.4.1.2011.2.235.1.1.7.50.1.1.1 = INTEGER: 0
iso.3.6.1.4.1.2011.2.235.1.1.7.50.1.1.5 = INTEGER: 4
iso.3.6.1.4.1.2011.2.235.1.1.7.50.1.2.1 = STRING: "write-only"
iso.3.6.1.4.1.2011.2.235.1.1.7.50.1.2.5 = STRING: "write-only"可以看到,如主键值为0的实例iso.3.6.1.4.1.2011.2.235.1.1.7.50.1.1.1 = INTEGER: 0的Instance值已被配置为1,若没有@Instance字段,这个值将会与主键值保持一致,为0,此时该实例将会是iso.3.6.1.4.1.2011.2.235.1.1.7.50.1.1.0 = INTEGER: 0.
任务机制
有部分SNMP接口也涉及任务机制,当访问该SNMP接口时,后台业务组件会创建一个异步任务来执行相关业务操作。同时,通过其它的SNMP接口可以查询到任务执行的进度和报错信息等。
创建任务
创建任务的配置规则可参考《接口映射配置》。
示例
{
"Uri": "/snmp/1.3.6.1.4.1.{{SnmpOemIdentifier}}.0.0.3/Upgrade/Setonly",
"Interfaces": [
{
"Type": "POST",
"SNMPv1v2cSupported": false,
"ReqBody": {
"Type": "object",
"Required": true,
"Properties": {
"FilePath": {
"Type": "string",
"Required": true
}
}
},
"ProcessingFlow": [
{
"Type": "Task",
"Path": "/bmc/kepler/System",
"Interface": "bmc.kepler.System",
"Name": "StartUpgrade",
"Params": [
"${ReqBody/FilePath}"
],
"Destination": {
"TaskId": "TaskId"
}
}
]
}
]
}查询任务信息
配置映射接口获取任务信息
{
"Uri": "/bmc/kepler/System/TaskService/Tasks/:taskid",
"Interfaces": [
{
"Type": "GET",
"RspBody": {
"Progress": "${ProcessingFlow[1]/Destination/Progress}"
},
"ProcessingFlow": [
{
"Type": "Property",
"Path": "/bmc/kepler/System/TaskService/Tasks/${Uri/taskid}",
"Interface": "bmc.kepler.TaskService.Task",
"Destination": {
"Progress": "Progress"
}
}
]
}
]
}以上述接口配置为示例,示例中的任务Uri为/bmc/kepler/System/TaskService/Tasks/:taskid. 此Uri的前缀/bmc/kepler/System/TaskService/Tasks/要跟资源协作接口的Task路径前缀保持一致。如上述接口对应的资源协作接口的Task路径可以为/bmc/kepler/System/TaskService/Tasks/3545341234
配置查询任务信息接口
{
"Uri": "/snmp/1.3.6.1.4.1.{{SnmpOemIdentifier}}.0.0.5/UpgradeProgress/Readonly",
"Interfaces": [
{
"Type": "GET",
"TaskReferenceUri": [
"/snmp/1.3.6.1.4.1.{{SnmpOemIdentifier}}.42.2/Upgrade/Setonly",
"/snmp/1.3.6.1.4.1.{{SnmpOemIdentifier}}.0.0.4/Reset/Setonly"
],
"RspBody": {
"Progress": "-1"
}
}
]
}TaskReferenceUri字段
TaskReferenceUri字段用于指定此查询任务接口要查询的任务是由哪个Uri所创建的。如示例中
"TaskReferenceUri": [
"/snmp/1.3.6.1.4.1.{{SnmpOemIdentifier}}.42.2/Upgrade/Setonly",
"/snmp/1.3.6.1.4.1.{{SnmpOemIdentifier}}.0.0.4/Reset/Setonly"
]当访问此SNMP接口来查询任务信息时,此接口只会去查询由/snmp/1.3.6.1.4.1.{{SnmpOemIdentifier}}.42.2/Upgrade/Setonly和/snmp/1.3.6.1.4.1.{{SnmpOemIdentifier}}.0.0.4/Reset/Setonly这两个接口所创建的任务信息。如果这两个接口都分别创建了一个任务,则会优先查询最新创建的那个任务的信息。
任务信息的默认值
假设用户还未访问创建任务的接口,但是却去查询任务的信息,则查询任务的接口会返回默认的任务信息。要想定制默认的任务信息,可以通过配置RspBody字段中属性的默认值来实现。如示例中
"RspBody": {
"Progress": "-1"
}RspBody字段中Progress属性的默认值被配置为"-1",因此该接口返回的默认任务信息为"-1".