新增一个组件
更新时间:2025/2/19
在Gitcode上查看源码

openUBMC提供一套完整的开发平台,用户可以基于这个平台,基于自身的业务诉求进行增量开发。

NOTE

组件(Application)是openUBMC架构中最小的功能集合。每一个组件拥有自己的资源、对外的接口。
详细设计请参考《组件开发》

IMPORTANT

为了保证该章节学习的完整性,请确保您已经完成了《构建你的BMC》

新建组件框架

openUBMC CLI支持一键创建新组件,简化组件框架搭建流程。

组件初始化

通过bingo执行新建组件命令,组件名称为my_app,使用openUBMC的Lua SDK作为组件SDK

bash
# 进入到工作目录
cd /home/workspace

# 创建新组件
bingo new -n my_app -t application -l lua

执行完毕后,我们便可以在工作目录下看到一个新的文件夹my_app,其中包括了组件需要的所有基础内容。

bash
> ls -l my_app
total 40
-rw-r--r-- 1 root root    0 Jan 17 07:22 CHANGELOG.md
-rw-r--r-- 1 root root 1273 Jan 17 07:22 CMakeLists.txt
-rw-r--r-- 1 root root  673 Jan 17 07:22 Makefile
-rw-r--r-- 1 root root    0 Jan 17 07:22 README.md
-rw-r--r-- 1 root root  102 Jan 17 07:22 conanfile.py
-rw-r--r-- 1 root root  141 Jan 17 07:22 config.cfg
drwxr-xr-x 2 root root 4096 Jan 17 07:22 mds
-rw-r--r-- 1 root root  624 Jan 17 07:22 permissions.ini
drwxr-xr-x 4 root root 4096 Jan 17 07:22 src
drwxr-xr-x 3 root root 4096 Jan 17 07:22 temp
drwxr-xr-x 4 root root 4096 Jan 17 07:22 test
drwxr-xr-x 3 root root 4096 Jan 17 07:22 user_conf

为了后续方便版本管理,需要进行git初始化

bash
# 进入到my_app项目路径
cd /home/workspace/my_app

# git初始化
git init .

新增MDS资源对象定义

NOTE

MDS(Model Description Source)资源模型描述:
详细设计请参考《MDS》

openUBMC系统中,每个组件都拥有自己的业务资源,通过遵循MDS模型定义,openUBMC即可以完成BMC整体资源的建模,统一系统内的交互规范。同时基于相同的模型基础,openUBMC运行框架简化了组件间的交互逻辑,组件开发人员仅需围绕着自身的资源对象进行业务逻辑代码编写。

首先进入到新建的my_app项目中打开mds/model.json,粘贴以下配置

json
{
    "MyMDSModel": {
        "path": "/bmc/demo/MyMDSModel/${id}",
        "interfaces": {
            "bmc.demo.OpenUBMC.Community": {
                "properties":{
                    "WelcomeMessage": {}
                }
            }
        },
        "properties": {
            "SecretNumber": {
                "baseType": "U32"
            }
        }
    }
}

模型代码生成

NOTE

模型代码生成:
基于MDS模型自动生成辅助代码,简化模型创建、管理、对外交互的编写流程。
详细设计请参考《代码自动生成》

mds/model.json仅定义了资源对象的含义,但并不能直接使用。因此我们需要通过自动生成代码的方式,将模型转换成实际的代码。

通过CLI进行模型代码生成

bash
bingo gen

运行结束后,我们在组件的文件目录中可以看到gen文件夹,里面是基于mds新建的模型生成出来的辅助代码。利用这些代码,我们便可以很轻易地在openUBMC中创建系统资源。具体自动生成的代码含义,以及详细介绍,请参考《代码自动生成》

创建资源对象

自动生成代码仅仅生成了管理代码,但并没有真正的创建实例。因此我们需要在组件的代码中去创建实例对象。

打开src/lualib/my_app_app.lua,粘贴下方代码

lua

local class = require 'mc.class' -- lua开发框架提供的增强类型系统
local c_service = require 'my_app.service' -- 自动生成代码生成的组件基类

local app = class(c_service) -- 创建一个组件类型

function app:ctor() -- 组件的构造函数
end

function app:init() -- 组件的初始化函数
    app.super.init(self) -- 先调用基类的初始化函数
    self.my_mds_model = self:CreateMyMDSModel(1, function(object) -- 创建一个mds对象实例,名字为1
        object.ObjectName = "MyMDSModel_1"  -- 在回调函数中进行对象的属性赋值
        object.WelcomeMessage = "Hello OpenUBMC!"
        object.SecretNumber = 330
    end)
end

return app

openUBMC基于Lua语言创建了一套面对对象编程框架,简化Lua类的创建和管理。

ctor函数即代表类的构造函数,用于创建具体的内存对象实列。

init函数用于初始化对象的属性,会在ctor函数调用后立即调用。

app类是基于openUBMC SDK框架创建的子类,因此可以调用框架的代码进行MDS对象操作。self:CreateMyMdsModel便是基于mds/model.json中定义的对象生成的辅助代码,帮助开发者快速创建对象。

组件SDK框架更多细节请参考此章节。《组件开发》

组件构建

代码写完后,我们需要在真实环境上测试一下我们写的代码。因此需要将my_app组件打包到BMC版本中。

openUBMC拥有组件级构建产品级构建的两层构建体系,利用业界成熟的开源软件Conan进行组件构建包的管理。

因此需要先将组件构建后,再进行整包构建。

bash
bingo build --stage=rc

构建成功后,我们可以看到打印了许多my_app/0.0.1@openUBMC.release/rc的文字,这个就是my_app版本0.0.1的构建标签。后续在任何和组件构建产物相关的地方,我们都会使用此标签来指向这次的组件构建包。

本次构建只是本地构建,构建产物也仅缓存在本地文件,可以在/root/.conan/data中查询:

bash
> ls /root/.conan/data/my_app
0.0.1

从conan远程仓缓存的组件构建包也会存在/root/.conan/data中,需要时可以在此处查看。

NOTE

组件构建以及组件中各文件的介绍,请参考《BMC Studio CLI (bingo)》

整包构建

由于我们新建了一个组件,当前的manifest中并不包含这个新组件。

所以第一步,我们需要将组件添加至manifest组件列表中。

首先我们需要找到产品对应的定义文件:

bash
> cd /home/workspace/manifest
> ls build/product/
ca  BMC
> ls build/product/BMC
openUBMC
> ls build/product/BMC/openUBMC
archive.ini  manifest.yml  permissions.ini  rootfs  update_ext4.cfg  version.xml

manifest/build/product/BMC/openUBMC/manifest.yml便是定义产品的基础信息,包括具体包括的组件。

打开manifest.yml,在dependencies:下面添加my_app

yaml
dependencies:
  - conan: "my_app/0.0.1@openUBMC.release/rc"

NOTE

manifest.yml的具体含义,以及产品仓的定义。请参考《产品构建》

添加完成后,我们便可以按照之前的方式进行整包构建。

bash
bingo build

构建完成后,便可在manifest/output中查看构建包。

整包测试

整包升级后,我们便可以查看我们新增的组件了。openUBMC兼容D-Bus协议,因此我们可以使用D-Bus标准的命令行工具即可查询。

D-Bus接口查询

bash
source /etc/profile
busctl --user tree bmc.kepler.my_app
bash
└─/bmc
  |─/bmc/demo
  | └─/bmc/demo/MyMDSModel
  |   └─/bmc/demo/MyMDSModel/1
  └─/bmc/kepler
    └─/bmc/kepler/my_app
      └─/bmc/kepler/my_app/MicroComponent

通过busctl --user tree这个命令,便可以查询到组件my_app提供的资源路径。这个路径正好是我们在mds/model.json中定义的路径。在D-Bus协议中,一个资源路径即代表一个资源对象,因此这个路径也便是我们的mds对象。我们可以通过busctl --user introspect命令对对象进行查看

bash
busctl --user introspect bmc.kepler.my_app /bmc/demo/MyMDSModel/1
log
NAME                                TYPE      SIGNATURE   RESULT/VALUE          FLAGS
bmc.demo.OpenUBMC.Community         interface -           -                     -
.GetRepoURL                         method    a{ss}u      s                     -
.WelcomeMessage                     property  s           "Hello OpenUBMC!"     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           "MyMDSModel"          emits-change
.ObjectIdentifier                   property  (ysss)      1 "" "" ""            emits-change
.ObjectName                         property  s           "MyMDSModel_1"        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    -                     -

我们可以看到bmc.demo.openUBMC.Community这个资源协作接口,以及下面的属性WelcomeMessage。这些也恰好是我们在mds/model.json中定义的。在本演示中,我们一再资源协作接口中定义了bmc.demo.OpenUBMC.Community接口,如果您想要修改该接口下的属性或者新增一个属于您的专属接口,请参考《MDS》

细心的读者可以发现,此处并没有显示我们的另一个属性,也就是SecretNumber。这是因为它并没有在资源协作接口中定义,因此也无法被外部获取。我们称这种属性为mds对象的私有属性,属于组件自己的内部数据,其他组件无法感知,也无法从外部获取。如果需要添加私有属性(例如本案例中的SecretNumber),可以直接进行添加,无需在资源协作接口中定义。

mdbctl工具查询

除了D-Bus本身的工具,openUBMC也提供了另一套成熟的对象查询工具:mdbctl。这个命令更多是基于MDS对象维度进行查询。

bash
mdbctl lsprop MyMDSModel_1
log
bmc.demo.OpenUBMC.Community
  WelcomeMessage="Hello OpenUBMC!"
bmc.kepler.Object.Properties
  ClassName="MyMDSModel"
  ObjectIdentifier=[0,"","",""]
  ObjectName="MyMdsSModel_1"

同样,mdbctl也只能查到资源协作接口暴露的数据,私有属性无法查询。