Create an App
更新时间: 2026/06/26
在Gitcode上查看源码

openUBMC offers a complete development platform that you can build on incrementally, tailoring it to your own business needs.

NOTE

An app (application) is the smallest functional unit in the openUBMC architecture. Each app owns its own resources and exposes its own interfaces.
For the detailed design, see App Development.

IMPORTANT

To get the most out of this chapter, make sure you've already completed Build Your Own BMC.

Scaffold a New App

The openUBMC CLI can scaffold a new app in a single command, taking the boilerplate out of setting up an app's structure.

Initialize the App

Use Bingo to create a new app named my_app, with openUBMC's Lua SDK as the app SDK:

bash
# Enter the working directory
cd /home/workspace

# Create the new app
bingo new -n my_app -t application -l lua

Once it finishes, you'll find a new my_app folder in the working directory containing everything an app needs to get started.

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

To make version control easier down the line, initialize a git repository:

bash
# Enter the my_app project directory
cd /home/workspace/my_app

# Initialize git
git init .

Define an MDS Resource Object

NOTE

MDS (Model Description Source) describes the resource model.
For the detailed design, see MDS.

In openUBMC, every app owns its own business resources. By defining them against the MDS model, openUBMC can model the BMC's resources as a whole and enforce a consistent interaction contract across the system. Because everything shares the same modeling foundation, the openUBMC runtime also handles the inter-app interaction logic for you—as an app developer, you only need to write business logic around your own resource objects.

Open mds/model.json in your new my_app project and paste in the following configuration:

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

Generate Model Code

NOTE

Model code generation:
Auto-generates helper code from the MDS model, so you write far less boilerplate to create, manage, and expose your model.
For the detailed design, see Code Generation.

mds/model.json only defines what the resource object means—it isn't usable on its own. To turn the model into code you can actually call, we generate that code automatically.

Generate Model Code from the CLI

bash
bingo gen

When it finishes, a gen folder appears in your app directory, holding the helper code generated from the model you defined under mds. With this code, creating system resources in openUBMC becomes straightforward. For what the generated code does and a full walkthrough, see Code Generation.

Create a Resource Object

Code generation only produces the management scaffolding—it doesn't actually create any instances. For that, we create the instance object ourselves in the app's code.

Open src/lualib/my_app_app.lua and paste in the code below:

lua

local class = require 'mc.class' -- Enhanced type system provided by the Lua development framework
local c_service = require 'my_app.service' -- App base class produced by code generation

local app = class(c_service) -- Create an app class

function app:ctor() -- The app's constructor
end

function app:init() -- The app's initialization function
    app.super.init(self) -- Call the base class initializer first
    self.my_mds_model = self:CreateMyMDSModel(1, function(object) -- Create an MDS object instance named "1"
        object.ObjectName = "MyMDSModel_1"  -- Assign the object's properties inside the callback
        object.WelcomeMessage = "Hello OpenUBMC!"
        object.SecretNumber = 330
    end)
end

return app

openUBMC builds an object-oriented programming framework on top of Lua to simplify creating and managing Lua classes.

The ctor function is the class constructor; it creates the concrete in-memory object instance.

The init function initializes the object's properties and runs immediately after ctor.

The app class is a subclass built on the openUBMC SDK framework, so it can call into the framework to work with MDS objects. self:CreateMyMDSModel is the helper code generated from the object defined in mds/model.json, letting you create objects quickly.

For more on the app SDK framework, see App Development.

Build the App

With the code written, we want to test it on a real device, which means packaging the my_app app into a BMC build.

openUBMC has a two-tier build system—app-level builds and product-level builds—and uses Conan, a well-established open-source package manager, to manage app build packages.

So we build the app first, then build the full image.

bash
bingo build --stage=stable

On a successful build, you'll see my_app/0.0.1@openubmc/stable printed repeatedly—this is the build tag for version 0.0.1 of my_app. From here on, anywhere we refer to this app's build artifact, we use this tag to point to it.

This is a local build, so the artifact is only cached on your machine. You can find where it's stored with:

bash
> conan cache path my_app/0.0.1@openubmc/stable

NOTE

For app builds and a rundown of each file in an app, see BMC Studio CLI (bingo).

Build the Full Image

Because we just created a new app, the current manifest doesn't include it yet.

So the first step is to add the app to the manifest's component list.

First, locate the definition file for the product:

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 defines the product's basic information, including exactly which apps it bundles.

Open manifest.yml and add my_app under dependencies::

yaml
dependencies:
  - conan: "my_app/0.0.1@openubmc/stable"

NOTE

For what manifest.yml means and how the product repository is defined, see Product Build.

Once it's added, build the full image the same way as before:

bash
bingo build

When the build finishes, you'll find the package in manifest/output.

Test the Full Build

After upgrading with the full image, we can inspect the app we just added. openUBMC is D-Bus compatible, so we can query it with the standard D-Bus command-line tools.

Query via the D-Bus Interface

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

The busctl --user tree command lists the resource paths exposed by the my_app app—and they match exactly the path we defined in mds/model.json. In D-Bus, a resource path represents a resource object, so this path is our MDS object. We can inspect the object with 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    -                     -

You can see the bmc.demo.OpenUBMC.Community MDB interface (resource collaboration interface) and, under it, the WelcomeMessage property—exactly what we defined in mds/model.json. In this demo we defined bmc.demo.OpenUBMC.Community as our MDB interface; to change its properties or add an interface of your own, see MDS.

Sharp-eyed readers will notice that our other property, SecretNumber, isn't shown here. That's because it isn't declared in the MDB interface, so it can't be accessed from outside. We call this a private property of the MDS object: internal data that belongs to the app alone—other apps can neither see it nor read it from outside. To add a private property (like SecretNumber here), just add it directly; there's no need to declare it in the MDB interface.

Query with the mdbctl Tool

Beyond the native D-Bus tools, openUBMC provides another mature object-query tool: mdbctl. It queries more from the angle of MDS objects.

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

As before, mdbctl can only see data exposed through the MDB interface; private properties don't show up.