IMPORTANT
为了保证该章节学习的完整性,请确保您已经完成了《扩展对外接口》
BMC作为一款服务器带外管理软件,差异性的硬件适配是bmc最常见的业务场景。openUBMC SDK基于自身多年经验,提供了一系列的硬件适配能力,简化硬件适配的开发流程。
本章节将介绍如何在已有的硬件适配上进行增量开发,用于帮助您理解硬件适配流程。具体的各类硬件适配细节,请参考《开发指南》。
新增一个IPMI Sensor
一个常见的场景便是需要将硬件上的某一个器件的读值,通过IPMI协议中定义的门限传感器呈现给用户。在本章节中,我们将配置一个LM75温度器件,同时配置一个对应的IPMI门限传感器,并呈现至对外接口。
CSR配置
openUBMC采用一种软件描述性语言描述一个硬件的具体信息,这种描述性语言被称之为Component Self-description Record(CSR)。
NOTE
关于CSR的具体介绍,请参考《硬件自描述文件(CSR)》
首先我们先获取CSR仓库:
git clone git@gitcode.com:openUBMC/vpd.git
打开服务机型(vendor/Huawei/Server/Kunpeng/openUBMC)的root.sr
打开后可以发现一系列配置。首先我们需要现在硬件拓扑链路中声明一个LM75器件。
在实际的硬件链路拓扑中,I2c_8总线下地址为0x90
处有一个LM75温感芯片。
在CSR的ManagementTopology
中找到对应的I2c_8
的配置,如果没有I2c_8
,请在ManagementTopology
中粘贴下面的配置(可参考I2c_2
的配置)。
"ManagementTopology": {
...
"I2c_8": {
"Chip": [
"Lm75_DemoSensor"
]
}
...
}
这样CSR中便完成了实际的硬件链路拓扑配置。
同时,在与ManagementTopology
同级的objects
下面定义Lm75器件的具体信息,和两个业务对象:
"Objects": {
...
"Lm75_DemoSensor": {
"OffsetWidth": 1,
"AddrWidth": 1,
"Address": 144
},
"Scanner_GetTemperature": {
"Chip": "#/Lm75_DemoSensor",
"Size": 1,
"Offset": 0,
"Mask": 255,
"Period": 1000
},
"ThresholdSensor_DemoSensor": {
"AssertMask": 29312,
"DeassertMask": 29312,
"ReadingMask": 6168,
"Linearization": 0,
"M": 100,
"RBExp": 224,
"UpperCritical": 48,
"UpperNoncritical": 46,
"PositiveHysteresis": 2,
"NegativeHysteresis": 2,
"OwnerId": 32,
"OwnerLun": 0,
"EntityId": "<=/Entity_DemoSensor.Id",
"EntityInstance": "<=/Entity_DemoSensor.Instance",
"Initialization": 127,
"Capabilities": 104,
"SensorType": 1,
"ReadingType": 1,
"SensorName": "Demo Temperature Sensor",
"Unit": 128,
"BaseUnit": 1,
"ModifierUnit": 0,
"Analog": 1,
"MaximumReading": 127,
"MinimumReading": 128,
"Reading": "<=/Scanner_GetTemperature.Value"
},
"Entity_DemoSensor":{
"Id": 99,
"Name": "Demo Temperature Sensor",
"PowerState": 1,
"Presence": 1,
"Instance": 96
},
...
}
此处我们定义了两个对象,一个是Lm75器件,一个是定期扫描任务Scanner
,一个是IPMI门限传感器的软件对象。 我们通过引用
语法将Scanner和Lm75器件关联起来;通过同步
语法将Scanner的读值同步至ThresholdSensor的读值。
NOTE
具体IPMI传感器的配置,请参考《IPMI Sensor & SEL》
组件构建
由于修改了vpd仓库,因此我们需要对vpd仓库进行重新构建。
为了和之前版本进行区分,我们需要将service.json
中的version
字段进行更新
bingo build --stage=rc
整包构建
找到vpd声明位置,将版本改至对应的构建版本,然后在manifest中再次进行整包构建
bingo build
整包测试
整包升级后,我们可以通过ipmitool进行传感器查询。
> ./ipmitool.exe -H ip -I lanplus -p 623 -U TestUser -P OpenUBMC@123 -C 17 sdr
> Demo Temperature | 28 degrees C | ok
新增硬件资源对象
CSR中的对象定义来源于MDS模型,通过实例化MDS类定义,我们便可以很方便的在对应的设备配置中,将所需要的硬件管理数据配置齐全,然后在组件中对资源对象进行业务逻辑编写。
MDS对象定义
首先我们需要在my_app组件的MDS模型中定义资源类。
打开在《新增一个组件》中创建的my_app
组件的mds/model.json
, 添加下面的模型定义
NOTE
MDS(Model Description Source)资源模型描述:
详细设计请参考《MDS》
{
"MyCSRModel": {
"path": "/bmc/demo/MyCSRModel/${id}",
"interfaces": {
"bmc.demo.OpenUBMC.Reading": {
"properties":{
"TemperatureCelsius": {
"usage": [
"CSR"
]
}
}
}
}
}
}
与普通的组件MDS对象定义不同,这里新增了"usage": ["CSR"]
的声明。这个表示在某个CSR中,存在一个叫做MyCSRModel
的对象,包含TemperatureCelsius
的属性。
CSR对象添加
NOTE
关于硬件自发现的具体设计,请参考《硬件自发现》
在上述的usage
的定义中,可以看到TemperatureCelsius
来源于CSR,因此需要在上述的CSR中定义一个MyCSRModel
,通过硬件自发现将CSR对象分发给my_app
。
"Objects": {
...
"MyCSRModel_DemoSensor": {
"TemperatureCelsius": "<=/Scanner_GetTemperature.Value"
},
...
}
自动生成代码
由于新增了模型定义,我们需要通过自动代码生成辅助代码。在my_app
中执行如下命令:
bingo gen
代码编写
由于MyCSRModel
的实例已经在root.sr中“创建”,因此我们需要等待对象的分发,而非主动去创建。可以通过如下的方法在代码中获取对象的分发。
打开my_app_app.lua
,在app:init()
中添加对象添加回调函数。
local object_manage = require 'mc.mdb.object_manage'
function app:init() -- 组件的初始化函数
app.super.init(self) -- 先调用基类的初始化函数
self.my_mds_model = self:CreateMyMDSModel(1, function(object) -- 创建一个mds对象实例
object.ObjectName = "MyMDSModel_1" -- 在回调函数中进行对象的属性赋值
object.WelcomeMessage = "Hello OpenUBMC!"
object.SecretNumber = 330
end)
self:register_ipmi()
self:register_mds_callback() -- 新增mds方法回调
end
function app:register_mds_callback()
object_manage.on_add_object(self.bus, function(class_name, object, position)
if class_name == 'MyCSRModel' then
self.my_csr_model = object
end
end)
object_manage.on_add_object_complete(self.bus, function(position)
end)
object_manage.on_delete_object(self.bus, function(class_name, object, position)
if self.my_csr_model == object then
self.my_csr_model = nil
end
end)
object_manage.on_delete_object_complete(self.bus, function(position)
end)
end
组件构建
由于修改了my_app
仓库,因此我们需要进行构建。
为了和之前版本进行区分,我们需要将手动将mds目录下的service.json
中的version
字段进行更新,通常会在原有版本号的最后一位上加一。随后再执行组件构建命令。
bingo build --stage=rc
整包构建
在manifest中找到之前my_app声明位置(《新增一个组件》章节中已将该声明放于manifest/build/product/openUBMC/openUBMC/manifest.yml
中),将版本改至对应的构建版本,然后再进行整包构建。
bingo build
整包测试
整包升级后,可以查看资源协作接口对象,
source /etc/profile
busctl --user tree bmc.kepler.my_app
└─/bmc
|─/bmc/demo
| |─/bmc/demo/MyCSRModel
| | └─/bmc/demo/MyCSRModel/MyCSRModel_DemoSensor_01
| └─/bmc/kepler/MyMDSModel
| └─/bmc/kepler/MyMDSModel/1
└─/bmc/kepler
| └─/bmc/kepler/IpmiCmds
| └─/bmc/kepler/IpmiCmds/30
| └─/bmc/kepler/IpmiCmds/30/90
| |─/bmc/kepler/IpmiCmds/30/90/GetSecretNumber
| └─/bmc/kepler/IpmiCmds/30/90/SetSecretNumber
└─/bmc/kepler/my_app
└─/bmc/kepler/my_app/MicroComponent
通过busctl --user tree
我们发现多了一个对象,这个便是CSR中配置的对象。我们可以通过busctl --user introspect
命令对对象进行查看
busctl --user introspect bmc.kepler.my_app /bmc/demo/MyCSRModel/MyCSRModel_DemoSensor_01
NAME TYPE SIGNATURE RESULT/VALUE FLAGS
bmc.kepler.OpenUBMC.Reading interface - - -
.TemperatureCelsius property n 28 emits-change writable
bmc.kepler.Object.Properties interface - - -
.GetAllWithContext method a{ss}s a{sv} -
.GetOptions method a{ss}ss a{ss} -
.GetPropertiesByNames method a{ss}sas a{sv}a{sv} -
.GetPropertiesByOptions method a{ss}sa{ss} as -
.GetWithContext method a{ss}ss v -
.SetWithContext method a{ss}ssv - -
.ClassName property s "MyCSRModel" emits-change
.ObjectIdentifier property (ysss) 0 "1" "" "01" emits-change
.ObjectName property s "MyCSRModel_DemoSensor_01" emits-change
org.freedesktop.DBus.Introspectable interface - - -
.Introspect method - s -
org.freedesktop.DBus.ObjectManager interface - - -
.GetManagedObjects method - a{oa{sa{sv}}} -
org.freedesktop.DBus.Peer interface - - -
.GetMachineId method - s -
.Ping method - - -
org.freedesktop.DBus.Properties interface - - -
.Get method ss v -
.GetAll method s a{sv} -
.Set method ssv - -
.PropertiesChanged signal sa{sv}as - -