ONOS project started using BUCK from 1.7.0 humming bird release. Buck is a build tool developed by Facebook,
and supports highly parallel and incremental builds. To build ONOS, we simply need to run the buck build onos
command.
Ever since ONOS migrated to buck, there has been lot of requests on how to utilize BUCK to build ONOS apps.
If you have already written apps on top of ONOS, you might be aware of onos-create-app
utility, which utilizes maven archetypes to generate pom.xml
and other related files.
For more information on how to write ONOS app based on old maven process, please refer my earlier post ONOS Application Tutorial - PortStatistics Application
In this post, I’m going to explain how to write an ONOS app based on BUCK build system.
onos-create-app
utility, lets you place your app’s source in any path. This is because, onos-create-app
follows mvn
based approach, where all the dependencies will be expressed as mvn targets. These can be either fetched from internet or can be fetched from your ~/.m2
repo.
Eventhough ONOS has migrated to BUCK, onos-create-app
still uses old mvn style targets. BUCK support isn’t added yet.
In-order to create apps based on buck, you will have to place your apps under onos/apps
subtree for the build script to locate your source.
In-order to get our hands dirty with buck, let create a sample CLI application. As explained above, we need to place our app inside onos/apps
tree. Lets name our app as failedintentsanalyze
and the path now looks like onos/apps/failedintentsanalyze
.
Most JAVA projects will be organized as main
and test
dirs, where actual logic will be under main
and UT / IT logic will be placed under test
. Java files will be placed under main\java
, property files, XML files etc will be placed under main\resources
and web\gui related files will be placed under main\web
.
If you are looking for detailed steps on how to write a CLI app on top of ONOS, I suggest reading through CLI and Service Tutorial from ONOS wiki. Once done, read-on…
Ok so in-order to have a custom command in ONOS, all we need to do, is to extend AbstractShellCommand
class and override execute()
method. So lets just have a sample command implemented like below
Next important step, is to let karaf know that, this command exists. This is done via XML config in a filed named shell-config.xml
as follows.
This shell-config.xml
should be placed under onos/apps/failedintentsanalyzer/src/main/resources/OSGI-INF/blueprint
path.
buck
Okay now are raedy to cook the app using buck
. Just like how ant
has Makefile
, maven
has pom.xml
, buck
uses BUCK files to understand what needs to be cooked.
BUCK
fileSo let us start writing a very simple BUCK
file as follows.
Best way to read BUCK
file is to read from bottom. At the bottom, we just create an onos app with a bucklet
named onos_app()
. We are naming the app, category, url, description etc. This is analogus to following in pom.xml
.
Note : For curious people like, you can take look at all available bucklets
under ~/onos/bucklets/onos.bucklet
.
ONOS apps are essentially karaf
features, which are installed / un-installed / activated / deactivated in karaf runtime. All karaf features are essentially osgi-jars
. When you build a jar
using javac
, someone has to convert normal jar
to osgi-jar
. In case of mvn
based builds, maven-bundle-plugin
takes the responsiblity of packaging OAR
to osgi-jar
. Incase of buck jars
, there exists osgi_jar
bucklet, which mimics the functionality of maven-bundle-plugin
.
As an application developer, all you need to do, is to notify buck to use osgi_jar()
bucklet. If you want to include test targets, then feel free to use another similar bucklet osgi_jar_with_tests
.
If you look at the args, that we have passed for osgi_jar
bucklets, deps = COMPILE_DEPS
instructs buck
to use all the targets specified in COMPILE_DEPS
during compile time. Obviously, we will be needing core libs, cli deps ( since our app is essentially extending ONOS’ cli ) and karaf console dependencies.
If your app needs to do something with GUI / REST, all you need to do is to just add '//lib:javax.ws.rs-api', '//utils/rest:onlab-rest',
to list of deps and then you are done. Yeah… it is as simple as that.
One of the important feature of buck is its ability to understand JAVA. It also enforce you to specify any transitive dependency explicitly. Though this is kind of extra work ( as opposed to automatic dependency injection techniques ), it saves lot of unknowns.
Assume a scenario, where-in we are adding a runtime dependency to our app. For example, let us add ConnectPointCompleter
bean to our command as follows
The ConnectPointCompleter
object is part of onos-cli
library and a reference to this object will be made during runtime, when our app is activated. Incase of mvn
, bundleplugin will be able to scan through the shell-config.xml
file to determine if there are dependencies in there that the bundle needs to import, but with buck
it is not looking at the XML files. It is now the responsiblity of the developer to explicitly specify run-time dependencies. With ONOS bucklets, this is rather simple one-line change.
The ConnectPointCompleter
class is available in org.onosproject.cli.net
package. So just go-ahead and add that as import_packages
directive in your BUCK
file as follows.
Note : The default *
simply gives you all of your compile time dependencies, by adding the cli one you are telling the OSGI runtime to load it even though there is no explicit dependency.
We are almost there. We have assembled all that are needed to cook our app under buck
. Last step is to tie our app, with master list of all buck
targets, so that oru apps gets built, installed automatically when building ONOS. This step is super-easy.
All we need to do, is to locate modules.defs
under ONOS root and add an entry to our app under ONOS_APPS
section as follows
Note : Pay attention to onos-apps-failedintentsanalyzer-oar
naming convention. The pattern is onos-apps-<appname>-oar
.
We need to ensure that our app is located in onos\apps\<appname>\
Alright.. we are ready to go. Just hit tools/build/onos-buck run onos-local -- clean
which would instruct buck
to build entire ONOS source tree, create a package and run it instantly. Since our app is already inside onos source tree, as a bonus, our app will be automatically installed in ONOS. There is no need for an extra step of onos-app localhost install app.oar
.
You are free to just activate your app using app activate <package>.<classname>
If you are wondering where buck outputs are maintained, take a look at onos/buck-out/bin/apps
path.
I hope this post would have provided you enough inputs on getting started with your ONOS app development using BUCK. Feel free to fire in any questions / comments / clarifications and I would be happy to help.
Cya!!!