7 Required Technology Stack
8 ~~~~~~~~~~~~~~~~~~~~~~~~~
10 - AngularJS (JavaScript client-side framework, http://www.angularjs.org
16 To turn on the DLUX UI, install DLUX core feature via running following
17 command on the Karaf console -
21 feature:install odl-dlux-core
23 The above command will install odl-restconf and DLUX topology
24 application internally, along with core DLUX components. Once this
25 feature is successfully installed, access the UI at
26 http://localhost:8181/index.html. The default credentials for login are
29 All the applications in DLUX are Karaf features. A user can install
30 other dlux applications such as node and yang-ui from Karaf console
31 using commands such as -
35 $ feature:install odl-dlux-node
37 $ feature:install odl-dlux-yangui
42 DLUX modules are the individual features such as nodes and topology.
43 Each module has a defined structure and you can find all existing
45 https://github.com/opendaylight/dlux/tree/stable/boron/modules.
52 - <module\_name>.module.js
54 - <module\_name>.controller.js
56 - <module\_name>.services.js
58 - <module\_name>.directives.js
60 - <module\_name>.filter.js
72 1. Create an empty maven project and create your module folder under
75 2. Create an empty file with pattern <module\_name>.module.js.
77 3. Next, you need to surround the angular module with a define function.
78 This allows RequireJs to see our module.js files. The first argument
79 is an array which contains all the module’s dependencies. The second
80 argument is a callback function, whose body contain the AngularJS
81 code base. The function parameters correspond with the order of
82 dependencies. Each dependency is injected into a parameter, if it is
85 4. Finally, you will return the angular module to be able to inject it
86 as a parameter in others modules.
88 For each new module, you must have at least these two dependencies :
90 - angularAMD : It’s a wrapper around AngularJS to provide an AMD
91 (Asynchronous Module Definition) support, which is used by RequireJs.
92 For more information see the `AMD
93 documentation <https://github.com/amdjs/amdjs-api/blob/master/AMD.md>`__.
95 - app/core/core.services : This one is mandatory, if you want to add
96 content in the navigation menu, the left bar or the top bar.
98 The following are not mandatory, but very often used.
100 - angular-ui-router : A library to provide URL routing.
102 - routingConfig : To set the level access to a page.
104 Your module.js file might look like this:
108 define(['angularAMD','app/routingConfig', 'angular-ui-router','app/core/core.services'], function(ng) {
109 var module = angular.module('app.a_module', ['ui.router.state', 'app.core']);
110 // module configuration
111 module.config(function() {
117 Set the register function
118 ^^^^^^^^^^^^^^^^^^^^^^^^^
120 AngularJS allows lazy registration of a module’s components such as
121 controller, factory etc. Once you will install your application, DLUX
122 will load your module javascript, but not your angular component during
123 bootstrap phase. You have to register your angular components to make
124 sure they are available at the runtime.
126 Here is how to register your module’s component for lazy initialization
131 module.config(function($compileProvider, $controllerProvider, $provide) {
133 controller : $controllerProvider.register,
134 directive : $compileProvider.directive,
135 factory : $provide.factory,
136 service : $provide.service
143 The next step is to set up the route for your module. This part is also
144 done in the configuration method of the module. We have to add
145 **$stateProvider** as a parameter.
149 module.config(function($stateProvider) {
150 var access = routingConfig.accessLevels;
151 $stateProvider.state('main.module', {
155 templateUrl: 'src/app/module/module.tpl.html',
156 controller: 'ModuleCtrl'
162 Adding element to the navigation menu
163 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
165 To be able to add item to the navigation menu, the module requires the
166 **NavHelperProvider** parameter in the configuration method.
167 **addToMenu** method in **NavMenuHelper** helper allows an item addition
172 var module = angular.module('app.a_module', ['app.core']);
173 module.config(function(NavMenuHelper) {
174 NavMenuHelper.addToMenu('myFirstModule', {
175 "link" : "#/module/index",
177 "title" : "My First Module",
178 "icon" : "icon-sitemap",
180 "title" : "My First Module",
181 "description" : "My first module"
186 The first parameter is an ID that refers to the level of your menu and
187 the second is a object. For now, The ID parameter supports two levels of
188 depth. If your ID looks like *rootNode.childNode*, the helper will look
189 for a node named *rootNode* and it will append the *childNode* to it. If
190 the root node doesn’t exist, it will create it.
192 Link the AngularJS module’s controller file
193 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
195 To include the module’s controller file, you can use the
196 NavHelperProvider. It contains a method that will load the given file.
201 NavHelperProvider.addControllerUrl('<path_to_module_folder>/<module_name>.controller');
203 This completes your module.js file.
205 Create the controller, factory, directive, etc
206 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
208 Creating the controller and other components is similar to the module.
210 - First, add the define method.
212 - Second, add the relative path to the module definition.
214 - Last, create your methods as you usually do it with AngularJS.
220 define(['<relative_path_to_module>/<module_name>.module'], function(module) {
221 module.register.controller('ModuleCtrl', function($rootScope, $scope) {
225 Add new application using DLUX modularity
226 -----------------------------------------
228 DLUX works as a Karaf based UI platform, where you can create a new
229 Karaf feature of your UI component and install that UI applications in
230 DLUX using blueprint. This page will help you to create and load a new
231 application for DLUX. You don’t have to add new module in DLUX
234 Add a new OSGi blueprint bundle
235 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
237 The OSGi Blueprint Container specification allows us to use dependency
238 injection in our OSGi environment. Each DLUX application module
239 registers itself via blueprint configuration. Each application will have
240 its own blueprint.xml to place its configuration.
242 1. Create a maven project to place blueprint configuration. For
243 reference, take a look at topology bundle, present at
244 https://github.com/opendaylight/dlux/tree/stable/boron/bundles/topology.
245 All the existing DLUX modules' configurations are available under
246 bundles directory of DLUX code.
248 2. In pom.xml, you have to add a maven plugin to unpack your module code
249 under generated-resources of this project. For reference, you can
250 check pom.xml of dlux/bundles/topology at
251 https://github.com/opendaylight/dlux/tree/stable/boron/bundles/topology.
252 Your bundle will eventually get deployed in Karaf as feature, so your
253 bundle should contain all your module code. If you want to combine
254 module and bundle project, that should not be an issue either.
256 3. Create a blueprint.xml configuration file under
257 src/main/resources/OSGI-INF/blueprint. Below is the content of the
258 blueprint.xml taken from topology bundles’s blueprint.xml. Any new
259 application should create a blueprint.xml in following format -
263 <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
264 <reference id="httpService" availability="mandatory" activation="eager" interface="org.osgi.service.http.HttpService"/>
265 <reference id="loader" availability="mandatory" activation="eager" interface="org.opendaylight.dlux.loader.DluxModuleLoader"/>
267 <bean id="bundle" init-method="initialize" destroy-method="clean" class="org.opendaylight.dlux.loader.DluxModule">
268 <property name="httpService" ref="httpService"/>
269 <property name="loader" ref="loader"/>
270 <property name="moduleName" value="topology "/>
271 <property name="url" value="/src/app/topology"/>
272 <property name="directory" value="/topology"/>
273 <property name="requireJs" value="app/topology/topology.module"/>
274 <property name="angularJs" value="app.topology"/>
275 <property name="cssDependencies">
277 <value>http://yui.yahooapis.com/3.18.1/build/cssreset/cssreset-min.css</value>
278 <value>src/app/topology/topology-custom.css</value>
284 In above configuration, there are two references with id httpService and
285 loader. These two beans will already be initialized by dlux-core, so any
286 new application can use them. Without these two bean references, a new
287 application will not be able to register.
289 Next is the initialization of your application bean, which will be an
290 instance of class org.opendaylight.dlux.loader.DluxModule. There are 5
291 properties that you should provide in this bean besides the references
292 of httpService and loader. Lets talk about those bean properties in
295 **moduleName** : Name of your module. This name should be unique in
298 **url**: This is the url via which RequireJS in DLUX will try to load
299 your module JS/HTML files. Also, this is the url that browser will use
300 to load the static HTML, JS or CSS files. RequireJS in DLUX has a base
301 path of **src**, so all the url should start with /src so RequireJS and
302 the browser can correctly find the files.
304 **directory**: In your bundle’s pom.xml, you unpack your module code.
305 This is the directory where your actual static files will reside. The
306 above mentioned url is registered with httpService, so when browser
307 makes a call to that url, it will be redirected to the directory
308 mentioned here. In the above example, all the topology files are present
309 under /topology directory and the browser/RequireJS can access those
310 files with uri /src/app/topology.
312 **requireJS**: This is the path to your RequireJS module. If you notice
313 closely, you will see the initial path of RequireJS app/topology in the
314 above example matches with the last part of url. This path will be be
315 used by RequireJS. As mentioned above, we have kept **src** as base path
316 in RequireJS, that is the exact reason that url start with /src.
318 **angularJS**: name of your AngularJS module.
320 **cssDependencies**: If the application has any external/internal css
321 dependencies, then those can be added here. If you create your own css
322 files, just point to those css files here. Use the url path that you
323 mentioned above, so the browser can find your css file.
325 OSGi understands blueprint.xml, once you will deploy your bundle in
326 karaf (or you can create a new feature for your application), karaf will
327 read your blueprint.xml and it will try to register your application
328 with dlux. Once successful, if you refresh your dlux UI, you will see
329 your application in left hand navigation bar of dlux.
334 Yang Utils are used by UI to perform all CRUD operations. All of these
335 utilities are present in yangutils.services.js file. It has following
336 AngularJS factories -
338 - **arrayUtils** – defines functions for working with arrays.
340 - **pathUtils** – defines functions for working with xpath (paths to
341 APIs and subAPIs). It divides xpath string to array of elements, so
342 this array can be later used for search functions.
344 - **syncFact** – provides synchronization between requests to and from
345 OpenDaylight when it’s needed.
347 - **custFunct** – it is linked with
348 apiConnector.createCustomFunctionalityApis in yangui controller in
349 yangui.controller.js. That function makes it possible to create some
350 custom function called by the click on button in index.tpl.html. All
351 custom functions are stored in array and linked to specific subAPI.
352 When particular subAPI is expanded and clicked, its inputs (linked
353 root node with its child nodes) are displayed in the bottom part of
354 the page and its buttons with custom functionality are displayed
357 - **reqBuilder** – Builds object in JSON format from input fields of
358 the UI page. **Show Preview** button on Yang UI use this builder.
359 This request is sent to OpenDaylight when button PUT or POST is
362 - **yinParser** – factory for reading .xml files of yang models and
363 creating object hierarchy. Every statement from yang is represented
366 - **nodeWrapper** – adds functions to objects in tree hierarchy created
367 with yinParser. These functions provide functionality for every type
370 - **apiConnector** – the main functionality is filling the main
371 structures and linking them. Structure of APIs and subAPIs which is
372 two level array - first level is filled by main APIs, second level is
373 filled by others sub APIs. Second main structure is array of root
374 nodes, which are objects including root node and its children nodes.
375 Linking these two structures is creating links between every subAPI
376 (second level of APIs array) and its root node, which must be
377 displayed like inputs when subAPI is expanded.
379 - **yangUtils** – some top level functions which are used by yangui
380 controller for creating the main structures.