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"
.