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 along with core DLUX components. Once this
24 feature is successfully installed, access the UI at
25 http://localhost:8181/index.html. The default credentials for login are
26 admin/admin. After successful login you'll see empty page.
27 For applications, continue with DluxApps project.
32 DLUX modules are the individual features such as nodes and topology.
33 Each module has a defined structure and you can find all existing
35 https://github.com/opendaylight/dlux/tree/stable/boron/modules.
42 - <module\_name>.module.js
44 - <module\_name>.controller.js
46 - <module\_name>.services.js
48 - <module\_name>.directives.js
50 - <module\_name>.filter.js
62 1. Create an empty maven project and create your module folder under
65 2. Create an empty file with pattern <module\_name>.module.js.
67 3. Next, you need to surround the angular module with a define function.
68 This allows RequireJs to see our module.js files. The first argument
69 is an array which contains all the module’s dependencies. The second
70 argument is a callback function, whose body contain the AngularJS
71 code base. The function parameters correspond with the order of
72 dependencies. Each dependency is injected into a parameter, if it is
75 4. Finally, you will return the angular module to be able to inject it
76 as a parameter in others modules.
78 For each new module, you must have at least these two dependencies :
80 - angularAMD : It’s a wrapper around AngularJS to provide an AMD
81 (Asynchronous Module Definition) support, which is used by RequireJs.
82 For more information see the `AMD
83 documentation <https://github.com/amdjs/amdjs-api/blob/master/AMD.md>`__.
85 - app/core/core.services : This one is mandatory, if you want to add
86 content in the navigation menu, the left bar or the top bar.
88 The following are not mandatory, but very often used.
90 - angular-ui-router : A library to provide URL routing.
92 - routingConfig : To set the level access to a page.
94 Your module.js file might look like this:
98 define(['angularAMD','app/routingConfig', 'angular-ui-router','app/core/core.services'], function(ng) {
99 var module = angular.module('app.a_module', ['ui.router.state', 'app.core']);
100 // module configuration
101 module.config(function() {
107 Set the register function
108 ^^^^^^^^^^^^^^^^^^^^^^^^^
110 AngularJS allows lazy registration of a module’s components such as
111 controller, factory etc. Once you will install your application, DLUX
112 will load your module javascript, but not your angular component during
113 bootstrap phase. You have to register your angular components to make
114 sure they are available at the runtime.
116 Here is how to register your module’s component for lazy initialization
121 module.config(function($compileProvider, $controllerProvider, $provide) {
123 controller : $controllerProvider.register,
124 directive : $compileProvider.directive,
125 factory : $provide.factory,
126 service : $provide.service
133 The next step is to set up the route for your module. This part is also
134 done in the configuration method of the module. We have to add
135 **$stateProvider** as a parameter.
139 module.config(function($stateProvider) {
140 var access = routingConfig.accessLevels;
141 $stateProvider.state('main.module', {
145 templateUrl: 'src/app/module/module.tpl.html',
146 controller: 'ModuleCtrl'
152 Adding element to the navigation menu
153 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
155 To be able to add item to the navigation menu, the module requires the
156 **NavHelperProvider** parameter in the configuration method.
157 **addToMenu** method in **NavMenuHelper** helper allows an item addition
162 var module = angular.module('app.a_module', ['app.core']);
163 module.config(function(NavMenuHelper) {
164 NavMenuHelper.addToMenu('myFirstModule', {
165 "link" : "#/module/index",
167 "title" : "My First Module",
168 "icon" : "icon-sitemap",
170 "title" : "My First Module",
171 "description" : "My first module"
176 The first parameter is an ID that refers to the level of your menu and
177 the second is a object. For now, The ID parameter supports two levels of
178 depth. If your ID looks like *rootNode.childNode*, the helper will look
179 for a node named *rootNode* and it will append the *childNode* to it. If
180 the root node doesn’t exist, it will create it.
182 Link the AngularJS module’s controller file
183 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
185 To include the module’s controller file, you can use the
186 NavHelperProvider. It contains a method that will load the given file.
191 NavHelperProvider.addControllerUrl('<path_to_module_folder>/<module_name>.controller');
193 This completes your module.js file.
195 Create the controller, factory, directive, etc
196 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
198 Creating the controller and other components is similar to the module.
200 - First, add the define method.
202 - Second, add the relative path to the module definition.
204 - Last, create your methods as you usually do it with AngularJS.
210 define(['<relative_path_to_module>/<module_name>.module'], function(module) {
211 module.register.controller('ModuleCtrl', function($rootScope, $scope) {
215 Add new application using DLUX modularity
216 -----------------------------------------
218 DLUX works as a Karaf based UI platform, where you can create a new
219 Karaf feature of your UI component and install that UI applications in
220 DLUX using blueprint. This page will help you to create and load a new
221 application for DLUX. You don’t have to add new module in DLUX
224 Add a new OSGi blueprint bundle
225 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
227 The OSGi Blueprint Container specification allows us to use dependency
228 injection in our OSGi environment. Each DLUX application module
229 registers itself via blueprint configuration. Each application will have
230 its own blueprint.xml to place its configuration.
232 1. Create a maven project to place blueprint configuration. For
233 reference, take a look at topology bundle, present at
234 https://github.com/opendaylight/dlux/tree/stable/boron/bundles/topology.
235 All the existing DLUX modules' configurations are available under
236 bundles directory of DLUX code.
238 2. In pom.xml, you have to add a maven plugin to unpack your module code
239 under generated-resources of this project. For reference, you can
240 check pom.xml of dlux/bundles/topology at
241 https://github.com/opendaylight/dlux/tree/stable/boron/bundles/topology.
242 Your bundle will eventually get deployed in Karaf as feature, so your
243 bundle should contain all your module code. If you want to combine
244 module and bundle project, that should not be an issue either.
246 3. Create a blueprint.xml configuration file under
247 src/main/resources/OSGI-INF/blueprint. Below is the content of the
248 blueprint.xml taken from topology bundles’s blueprint.xml. Any new
249 application should create a blueprint.xml in following format -
253 <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
254 <reference id="httpService" availability="mandatory" activation="eager" interface="org.osgi.service.http.HttpService"/>
255 <reference id="loader" availability="mandatory" activation="eager" interface="org.opendaylight.dlux.loader.DluxModuleLoader"/>
257 <bean id="bundle" init-method="initialize" destroy-method="clean" class="org.opendaylight.dlux.loader.DluxModule">
258 <property name="httpService" ref="httpService"/>
259 <property name="loader" ref="loader"/>
260 <property name="moduleName" value="topology "/>
261 <property name="url" value="/src/app/topology"/>
262 <property name="directory" value="/topology"/>
263 <property name="requireJs" value="app/topology/topology.module"/>
264 <property name="angularJs" value="app.topology"/>
265 <property name="cssDependencies">
267 <value>http://yui.yahooapis.com/3.18.1/build/cssreset/cssreset-min.css</value>
268 <value>src/app/topology/topology-custom.css</value>
274 In above configuration, there are two references with id httpService and
275 loader. These two beans will already be initialized by dlux-core, so any
276 new application can use them. Without these two bean references, a new
277 application will not be able to register.
279 Next is the initialization of your application bean, which will be an
280 instance of class org.opendaylight.dlux.loader.DluxModule. There are 5
281 properties that you should provide in this bean besides the references
282 of httpService and loader. Lets talk about those bean properties in
285 **moduleName** : Name of your module. This name should be unique in
288 **url**: This is the url via which RequireJS in DLUX will try to load
289 your module JS/HTML files. Also, this is the url that browser will use
290 to load the static HTML, JS or CSS files. RequireJS in DLUX has a base
291 path of **src**, so all the url should start with /src so RequireJS and
292 the browser can correctly find the files.
294 **directory**: In your bundle’s pom.xml, you unpack your module code.
295 This is the directory where your actual static files will reside. The
296 above mentioned url is registered with httpService, so when browser
297 makes a call to that url, it will be redirected to the directory
298 mentioned here. In the above example, all the topology files are present
299 under /topology directory and the browser/RequireJS can access those
300 files with uri /src/app/topology.
302 **requireJS**: This is the path to your RequireJS module. If you notice
303 closely, you will see the initial path of RequireJS app/topology in the
304 above example matches with the last part of url. This path will be be
305 used by RequireJS. As mentioned above, we have kept **src** as base path
306 in RequireJS, that is the exact reason that url start with /src.
308 **angularJS**: name of your AngularJS module.
310 **cssDependencies**: If the application has any external/internal css
311 dependencies, then those can be added here. If you create your own css
312 files, just point to those css files here. Use the url path that you
313 mentioned above, so the browser can find your css file.
315 OSGi understands blueprint.xml, once you will deploy your bundle in
316 karaf (or you can create a new feature for your application), karaf will
317 read your blueprint.xml and it will try to register your application
318 with dlux. Once successful, if you refresh your dlux UI, you will see
319 your application in left hand navigation bar of dlux.
324 Yang Utils are used by UI to perform all CRUD operations. All of these
325 utilities are present in yangutils.services.js file. It has following
326 AngularJS factories -
328 - **arrayUtils** – defines functions for working with arrays.
330 - **pathUtils** – defines functions for working with xpath (paths to
331 APIs and subAPIs). It divides xpath string to array of elements, so
332 this array can be later used for search functions.
334 - **syncFact** – provides synchronization between requests to and from
335 OpenDaylight when it’s needed.
337 - **custFunct** – it is linked with
338 apiConnector.createCustomFunctionalityApis in yangui controller in
339 yangui.controller.js. That function makes it possible to create some
340 custom function called by the click on button in index.tpl.html. All
341 custom functions are stored in array and linked to specific subAPI.
342 When particular subAPI is expanded and clicked, its inputs (linked
343 root node with its child nodes) are displayed in the bottom part of
344 the page and its buttons with custom functionality are displayed
347 - **reqBuilder** – Builds object in JSON format from input fields of
348 the UI page. **Show Preview** button on Yang UI use this builder.
349 This request is sent to OpenDaylight when button PUT or POST is
352 - **yinParser** – factory for reading .xml files of yang models and
353 creating object hierarchy. Every statement from yang is represented
356 - **nodeWrapper** – adds functions to objects in tree hierarchy created
357 with yinParser. These functions provide functionality for every type
360 - **apiConnector** – the main functionality is filling the main
361 structures and linking them. Structure of APIs and subAPIs which is
362 two level array - first level is filled by main APIs, second level is
363 filled by others sub APIs. Second main structure is array of root
364 nodes, which are objects including root node and its children nodes.
365 Linking these two structures is creating links between every subAPI
366 (second level of APIs array) and its root node, which must be
367 displayed like inputs when subAPI is expanded.
369 - **yangUtils** – some top level functions which are used by yangui
370 controller for creating the main structures.