前言
在前期的学习中,我们从一开始对openUBMC懵懵懂懂,到学会如何构建openUBMC产品,想必现在的你很想以openUBMC为基底,在上面打造属于你独一无二的产品吧!
也许你很早之前就已经在openUBMC社区深入学习过新增一个组件和组件开发,并且也在自己终端实际操作过。但由于缺少相关服务器环境,无法观测它如何用于产品,无法感知自己产品的整体情况.
在这里,我们将结合openUBMC社区文档中心,一步步告诉你如何构建属于自己的组件,并如何在产品上查看它。
新增组件
组件初始化
新增组件命令:bingo new -n Hello_openUBMC -t application -l lua

查看新增的组件:ls -l Hello_openUBMC
在新增的组件里面初始git操作,方便后面维护:
cd Hello_openUBMC
git init .
git branch -m main
新增组件业务
想必,您肯定希望在自己组件中实现自己的“奇思妙想”,openUBMC社区提供了一键式的模型生成体系,您只需要遵循其规则添加自己的想法即可。
新增MDS资源对象定义
进入新建的HelloOpenUBMC项目中,打开mds/model.json。在这里添加您想创建的对象(HelloOpenUBMC),以及这个对象挂载的路径(/bmc/kepler/HelloOpenUBMC/${id})、它提供给外界调用的接口(interfaces)、私有属性(properties),更加详细的信息可以参考MDS。
{
"HelloOpenUBMC": {
"path": "/bmc/kepler/HelloOpenUBMC/",
"interfaces": {
"bmc.kepler.OpenUBMC.Community": {
"properties":{
"WelcometoOpenUBMC": {}
}
}
},
"properties": {
"Health": {
"baseType": "U32"
}
}
}
}
模型代码自动生成
充满好奇心的你肯定会问只是在model.json添加自己的资源协作对象的接口和属性就可以直接使用了吗?应该在哪调用呢?
openUBMC社区提供一套基于MDS模型生成的辅助代码,更加的详细信息参考代码自动生成。
如果你这边只是在model.json里面添加内容,在自动生成代码过程中,就会遇到这个问题:
FileNotFoundError: [Errno 2] No such file or directory: '/root/lwm/Hello_openUBMC/temp/lua_codegen/../../temp/opt/bmc/apps/mdb_interface//path/mdb//bmc/kepler/HelloOpenUBMC////HelloOpenUBMC.json'
原因:当组件的MDS对象需要新增interface接口时,需要mdb_interface定义这个interface接口以及属性。
我们可以从两个方面来验证上述的原因:
- 新增的MDS对象只保留私有属性
{
"HelloOpenUBMC": {
"properties": {
"Health": {
"baseType": "U32"
}
}
}
}
执行 bingo gen,此时可以看到是没有报错的,而且也能顺利生成对应自动生成代码
- 在mdb_interface组件中新增Hello_OpenUBMC的对外接口
- 从社区拉起mdb_interface组件
git clone git@gitcode.com:openUBMC/mdb_interface.git
根据openUBMC社区的资源协作接口的说明:开发者需要在mdb_interface组件仓的json/path/路径下新增对象定义文件,根据上述新增的Hello_OpenUBMC组件的MDS对象,需要在mdb_interface做如下修改:
1. 新增json/path/mdb/bmc/kepler/HelloOpenUBMC/HelloOpenUBMC.json对象定义文件
对象定义文件的路径和MDS对象定义的path属性要一致,即json/path/mdb + MDS对象的path
{
"HelloOpenUBMC": {
"path": "/bmc/kepler/HelloOpenUBMC/",
}
在这个路径创建的文件名和类名一致:“HelloOpenUBMC”
总之,在mdb_interface组件仓中新增json/path/mdb/bmc/kepler/HelloOpenUBMC/HelloOpenUBMC.json对象定义文件,内容如下:
{
"HelloOpenUBMC": {
"path": "/bmc/kepler/HelloOpenUBMC/",
"interfaces": [
"bmc.kepler.OpenUBMC.Community"
]
}
}
2. 新增json/intf/mdb/bmc/kepler/OpenUBMC/Community.json接口定义文件
根据openUBMC社区的资源写作接口说明:新增接口的定义存放在mdb_interface组件的json/intf/路径下,主要存放接口的具体方法和属性等信息。接口定义文件的路径要和挂载接口一致:json/intf/ + 新增接口命名转化为路径,如bmc.kepler.OpenUBMC.Community转化为/bmc/kepler/OpenUBMC/Community.json
{
"bmc.kepler.OpenUBMC.Community": {
"properties":{
"WelcometoOpenUBMC": {
"baseType": "String",
"description": "欢迎加入openUBMC社区!"
}
}
}
}
聪明的你肯定会想:那我们是如何将mdb_interface和Hello_OpenUBMC组件相结合,即Hello_OpenUBMC是如何感知mdb_interface的修改呢?
细心的你会发现报错的信息有这么一段话:
'/root/lwm/Hello_openUBMC/temp/lua_codegen/../../temp/opt/bmc/apps/mdb_interface//path/mdb//bmc/kepler/HelloOpenUBMC////HelloOpenUBMC.json'
也就是每次我们自动生成的时候,都会从寻找本地或远程mdb_interface组件的conan包,如何将其存放在temp/opt/bmc/apps/路径下。
那么,Hello_OpenUBMC组件是怎么感知自己要去拉取mdb_interface组件的呢?
原来在我们是用bingo new -n Hello_openUBMC -t application -l lua生成新组件时会自动把依赖组件添加在service.json
{
"name": "Hello_openUBMC",
"type": "application",
"deployConfig": "",
"version": "0.0.1",
"license": "",
"codegen_policy": {
"version": "18"
},
"description": "",
"dependencies": {
"test": [
],
"build": [
{
"conan": "libmc4lua/[>=0.0.1]"
},
{
"conan": "mdb_interface/[>=0.0.1]"
}
]
},
"required": []
}
我们可以看到dependencies里面的build下面具有"conan": "mdb_interface/[>=0.0.1]"这个依赖,也就是在构建/自动生成的时候会默认依赖mdb_interface。
总之,我们需要进行下面三个步骤操作,就可以自动生成代码了:
1. 在mdb_interface组件中构建出包
bingo bulld
2. 将生成的mdb_interface组件的版本号替换Hello_OpenUBMC组件的mdb_interface/[>=0.0.1]
```service.json
{
"name": "Hello_openUBMC",
"type": "application",
"deployConfig": "",
"version": "0.0.1",
"license": "",
"description": "",
"dependencies": {
"test": [
],
"build": [
{
"conan": "libmc4lua/[>=0.0.1]"
},
{
"conan": "mdb_interface/1.90.78@openUBMC.dev/dev"
}
]
},
"required": []
}
3. 在'Hello_OpenUBMC'组件仓中自动生成代码bingo gen
自动生成代码仅仅生成了管理代码,但并没有真正的创建实例。需要在组件的代码中去创建实例对象。
在src/lualib/Hello_openUBMC_app.lua代码中创建实例
local class = require 'mc.class'
local service = require 'Hello_openUBMC.service'
local Hello_openUBMC = class(service)
function Hello_openUBMC:ctor()
end
function Hello_openUBMC:init()
self.super.init(self)
self.hello_openUBMC = self:CreateHelloOpenUBMC(1,function(object)
object.ObjectName = "HelloOpenUBMC_1"
object.WelcometoOpenUBMC = "Welcome to openUBMC"
object.Health = 1
end)
end
return Hello_openUBMC
说明:在这里,我们创建了HelloOpenUBMC_instance这个实例,并对其MDS属性进行赋值。从现在开始,你可以书写属于自己的业务内容。
组件出包
在Hello_OpenUBMC组件中采用bingo build构建出包
bingo build
产品出包
当我们成功完成了组件出包,您会思考我们应该如何将其融入到openUBMC产品呢?看过我们前期两篇教学培训:体验openUBMC和构建openUBMC包的朋友会自然而然地想到openUBMC的manifest仓。是的,您想的没错!和产品相关的内容都是在manifest仓进行的
1. 下载openUBMC社区的manifest(已经有manifest仓的朋友可以跳过)
git clone git@gitcode.com:openUBMC/manifest.git
2. 在build/subsys/rc/hardware.yml(可以放在其他yml里面)添加Hello_OpenUBMC组件
- conan: "Hello_openUBMC/0.0.1@openUBMC.dev/dev"
还需要把mdb_interface的版本也添加进去
3. 在build/product/BMC/openUBMC/manifest.yml中dependency中添加Hello_OpenUBMC组件
4. 构建出包: bingo build -sc qemu
5. 使用python3 build/works/packet/qemu_shells/vemake_1711.py运行qemu
6. ssh登录终端,采用cat /etc/package_info | grep Hello_openUBMC有没有这个组件

7. 查看Hello_openUBMC的资源树
busctl --user tree bmc.kepler.Hello_openUBMC
8. 使用mdbctl查看起来的组件
发现Hello_openUBMC也在里面
但很奇怪的是:你会发现在终端中出现一个Hello_openUBMC组件起不来的刷屏日志
![]()
这需要进一步探究啦~
使用xshell以telnet进去
telnet 127.0.0.1 -p 10023
运行:cat /var/log/app.log | grep Hello
发现报错:
Hello_openUBMC start failed, err: ./opt/bmc/libmc/lualib/mc/mdb/object_manage.lua:102: attempt to call local ‘prop_setting_cb’ (a number value)
然后进一步查看代码,发现Hello_openUBMC_service:CreateHelloOpenUBMC里面只需要传入回调函数
将src/lualib/Hello_openUBMC_app.lua的代码改为:
function Hello_openUBMC:init()
logging:notice("Hello_openUBMC:init start")
self.super.init(self)
self.hello_openUBMC = self:CreateHelloOpenUBMC(function(object)
object.ObjectName = "HelloOpenUBMC_1"
object.WelcometoOpenUBMC = "Welcome to openUBMC"
object.Health = 1
end)
logging:notice("Hello_openUBMC: init end")
end
更加详细的信息可以参考社区文档中的新增一个组件、组件开发、MDS和代码自动生成。
也可以继续关注教学培训篇,后续我们将会讲解和实践更深入的内容!















































