Table of Contents
Dlux Dev
Checkout Dlux
git branch -a git checkout -b ima_dlux origin/stable/lithium
Getting Start
Create Dlux App with Archetype
Omit the -DarchetypeVersion for master branch https://github.com/opendaylight/dlux/blob/stable/lithium/archetype/pom.xml. We are using stable lithium, which is of version 0.2.2-SNAPSHOT.
mvn archetype:generate -DarchetypeGroupId=org.opendaylight.dlux -DarchetypeArtifactId=dlux-app -DarchetypeVersion=0.2.2-SNAPSHOT \ -DarchetypeRepository=http://nexus.opendaylight.org/content/repositories/opendaylight.snapshot/ \ -DarchetypeCatalog=http://nexus.opendaylight.org/content/repositories/opendaylight.snapshot/archetype-catalog.xml
Archetype version for current DLUX master is 0.3.0-SNAPSHOT, which points to Beryllium release. For stable lithium SR1, it is 0.2.1-SNAPSHOT.
Respond to the prompts (Please note that artifactId will be used as your application name):
Define value for property 'groupId': : org.opendaylight.dlux.example Define value for property 'artifactId': : exampleApp (Don't use an archetype name with a dash in it. ) Define value for property 'version': 1.0-SNAPSHOT: : 1.0.0-SNAPSHOT Define value for property 'package': org.opendaylight.dlux.example: :
Project Structure
1. Application module contains all of the JS, HTML code and it is packaged as a maven jar.
- Application bundle has a configuration file blueprint.xml, which is read by Karaf container and initiate the deployment of application in DLUX. Application bundle embeds the content of above created Application module jar to make sure browser can access the files. Only Application bundle gets deployed in Karaf.
[fedora@odl_dev IMADluxUI-module]$ tree .
.
|-- pom.xml
|-- src
| `-- main
| `-- resources
| `-- IMADluxUI
| |-- IMADluxUI.controller.js
| |-- IMADluxUI-custom.css
| |-- IMADluxUI.module.js
| |-- IMADluxUI.services.js
| `-- IMADluxUI.tpl.html
`-- target
|-- checkstyle-cachefile
|-- checkstyle-checker.xml
|-- checkstyle-header.txt
|-- checkstyle-result.xml
|-- classes
| `-- IMADluxUI
| |-- IMADluxUI.controller.js
| |-- IMADluxUI-custom.css
| |-- IMADluxUI.module.js
| |-- IMADluxUI.services.js
| `-- IMADluxUI.tpl.html
|-- IMADluxUI-module-1.1.0-SNAPSHOT.jar
|-- IMADluxUI-module-1.1.0-SNAPSHOT-sources.jar
|-- javadoc-bundle-options
| `-- javadoc-options-javadoc-resources.xml
`-- maven-archiver
`-- pom.properties
9 directories, 19 files
[fedora@odl_dev IMADluxUI-bundle]$ tree .
.
|-- pom.xml
|-- src
| `-- main
| `-- resources
| `-- OSGI-INF
| `-- blueprint
| `-- blueprint.xml
`-- target
|-- checkstyle-cachefile
|-- checkstyle-checker.xml
|-- checkstyle-header.txt
|-- checkstyle-result.xml
|-- classes
| |-- IMADluxUI
| | |-- IMADluxUI.controller.js
| | |-- IMADluxUI-custom.css
| | |-- IMADluxUI.module.js
| | |-- IMADluxUI.services.js
| | `-- IMADluxUI.tpl.html
| |-- META-INF
| | `-- MANIFEST.MF
| `-- OSGI-INF
| `-- blueprint
| `-- blueprint.xml
|-- dependency-maven-plugin-markers
| `-- de.dailab.nemo.ima.controller-IMADluxUI-module-jar-1.1.0-SNAPSHOT.marker
|-- generated-resources
| `-- IMADluxUI
| |-- IMADluxUI.controller.js
| |-- IMADluxUI-custom.css
| |-- IMADluxUI.module.js
| |-- IMADluxUI.services.js
| `-- IMADluxUI.tpl.html
|-- IMADluxUI-bundle-1.1.0-SNAPSHOT.jar
|-- IMADluxUI-bundle-1.1.0-SNAPSHOT-sources.jar
`-- javadoc-bundle-options
`-- javadoc-options-javadoc-resources.xml
Add a new Karaf Feature for your application
Go to features module.
Add pom.xml dependency for dluxApp bundle
<dependency> <groupId>de.dailab.nemo.ima.controller</groupId> <artifactId>IMADluxUI-bundle</artifactId> <version>${project.version}</version> </dependency>
Add feature definition in src/main/resources/features.xml
<feature name='ima-controller-dlux-ui' version='${project.version}' description="IMA UI in Opendaylight dlux"> <feature>ima-controller</feature> <feature>odl-dlux-core</feature> <bundle>mvn:de.dailab.nemo.ima.controller/IMADluxUI-bundle/${project.version}</bundle> </feature>
Install Karaf Feature
cd /nfs_data/odl_dev_ws/ima-controller/IMADluxUI mvn clean install [fedora@odl_dev ima-controller]$ rm -rf distribution-karaf/target/assembly/data/* [fedora@odl_dev ima-controller]$ ./distribution-karaf/target/assembly/bin/karaf opendaylight-user@root> feature:repo-add mvn:de.dailab.nemo.ima.controller/features-ima-controller/1.1.0-SNAPSHOT/xml/features opendaylight-user@root>feature:install ima-controller-dlux-ui
Developing with karaf
Watch bundle:
bundle:watch --start de.dailab.nemo.ima.controller # modify angular controller etc. # mvn clean install the IMADluxUI mvn clean install -DskipTests -nsu # Chrome console shows new controller e.g., is loaded
http://karaf.apache.org/manual/latest-3.0.x/developers-guide/developer-commands.html
Mininet
mn --topo tree,depth=2,fanout=8 --mac --switch ovsk,protocols=OpenFlow13 --controller remote,ip=10.10.11.44,port=6633
Next Step - Advance
OSGi Blueprint Bundle
pom.xml
blueprint.xml
Customizing Dlux Karaf Blueprint
OpenDaylight dlux:Create and add a module
Tutorial Workflow
Network Topology GUI with cisco NextUI
Brocade
ODL Restconf
- example:
Required Knowledge
Dlux Developement
For Development: https://wiki.opendaylight.org/view/OpenDaylight_dlux:Lithium_Release_Notes
AngularJS (JavaScript client-side framework, http://www.angularjs.org) Karma (JavaScript Test Runner, http://karma-runner.github.io/) RequireJS (Javascript client-side framework, http://requirejs.org/) Blueprint (To configure new DLUX application, http://aries.apache.org/modules/blueprint.html)
- http://www.sitepoint.com/using-requirejs-angularjs-applications/ <code> AngularJS is the main Application framework- MIT License Restangular module for AngularJS for REST - MIT License AngularJS - UI Router provides “states” and “routing” for the application - MIT License AngularJS - UI Select2 - Provides AngularJS directives for the select2 library - MIT License angularAMD - https://github.com/amdjs/amdjs-api/blob/master/AMD.md Select2 - For making pretty selects - MIT License Select2 Bootstrap CSS - Fixes Select2 CSS to work nicely with Bootstrap3 - MIT License D3 JS - For graphs, topology etc - BSD License Underscore and Underscore String - Diverse utilities - MIT License Bootstrap for styles and so on - Apache License
API dependencies:
NorthBound API's of Controller to expose controller functions to the app Jolokia JMX > JSON Bridge - Apache License
The new UI will only consume NB API's and some external components like Jolokia for JMX parts which is not exposed directly under the NBAPI used for Diagnostics of the controller directly in the Application. </code>
Quick AngularJs + RequireJs
AngularJS + RequireJS Tutorial
- data/workspace/angularjsdevws
git clone angular-seed sudo npm install -g bower
TODO detail on working env
For dummies
RequireJS
RequireJS allow loading of modules, each of which is placed in a separate js-file. Only one main.js needs to be included in index.html. Inside the file, other modules and external libraries are loaded.
Put this single line before the closing body tag in index.html:
<script src="bower_components/requirejs/require.js" data-main="main.js"></script>
Assuming we have the following tree:
js
├── app.js
├── module1.js
├── path/to/
├── module2.js
index.html
The module*.js files contain requirejs module definition.
Load modules
main.js
// Load modules and use them require(['module1', 'path/to/module2'], function(module1ref, module2ref){ // do something with the loaded modules var module1 = new module1ref(), module2 = new module2ref(); console.log(module1.getName() === module2.getModule1Name()); // true });
The require() function takes two arguments: an array of dependencies, and a callback function to execute once all the dependencies are loaded. This callback function takes for parameters the specified dependencies, in their order of apparition in the array. Here, we load module1 and module2, and we pass them to the callback function under the name “module1ref” and “module2ref” respectively.
The parameters passed in the dependency array are the names of the JavaScript files containing the modules, without their extension. They can contain a path, which will be relative to the location of the main.js file.
module1.js
define([], function () {
var returnedModule = function () {
var _name = 'module1 name';
this.getName = function () {
return _name;
}
};
return returnedModule;
});
To create a module, we use the define() function provided by RequireJS. This function, as in the case of the require() function, can specify some dependencies. It has to return something, which will be forwarded to the callback function. Here, we return a function that exposes a getName() method allowing us to to get the” private variable “_name.
module2.js
define(['module1'], function (module1ref) { var module1 = new module1ref(); var returnedModule = function () { this.getModule1Name = function () { return module1.getName(); } }; return returnedModule; });
For this second module, we have declared a dependency on the module1, which becomes available under the name module1ref in the callback function. This module returns a function too, which exposes the getModule1Name() method. We can thus see how we can make use of a dependecy within a module. Of course, you have total freedom on what you do with those dependencies within a module, and I’m sure you will find some way more interesting usages than the one in this exemple!
Loading dependencies that aren’t modules
You will probably soon enough need to load third party libraries that aren’t defined as Require modules, like for example jQuery or underscore.js. For this, James Burke (the author of RequireJS) provides a “shim” system to us.
js/main.js
require.config({ paths: { 'jQuery': 'vendor/jquery-1.9.0.min', 'underscore': 'vendor/underscore-1.9.min' }, shim: { 'jQuery': { exports: '$' }, 'underscore': { exports: '_' } } }); require(['module1', 'path/to/module2', 'jQuery'], function (module1ref, module2ref, $) { // do something with the loaded modules var module1 = new module1ref(), module2 = new module2ref(); console.log(module1.getName() === module2.getModule1Name()); // true console.log('jQuery version:', $.fn.jquery); // 1.9.0 });
In order to use jQuery as a dependency, we must tell RequireJS two things: the path where to find the JavaScript file, and the global variable we wish to get hold of. To do so, we have to provide a configuration object to the config() method of the “require” (or “requirejs”, both are identical) global object. This configuration object defines under its “paths” key the names of the virtual modules, as keys for which the value represents the file we want to load. Under the “shim” key of the configuration object, we use those keys to point to the global variable defined by the library we want to get hold of. It’s this variable that will be returned when we call the module thus defined.
Here again, the “paths” declared are relative to the location of the main.js file and don’t include their .js extension.
Resources
follow:
AngularJS
AngularJS - Modules
Application Module
mainApp.js
var mainApp = angular.module("mainApp", []);
Here we've declared an application mainApp module using angular.module function. We've passed an empty array to it. This array generally contains dependent modules.
Controller Module
studentController.js
mainApp.controller("studentController", function($scope) { $scope.student = { firstName: "Mahesh", lastName: "Parashar", fees:500, subjects:[ {name:'Physics',marks:70}, {name:'Chemistry',marks:80}, {name:'Math',marks:65}, {name:'English',marks:75}, {name:'Hindi',marks:67} ], fullName: function() { var studentObject; studentObject = $scope.student; return studentObject.firstName + " " + studentObject.lastName; } }; });
Here we've declared a controller studentController module using mainApp.controller function.
AngularJS - Services
AngularJS supports the concepts of “Separation of Concerns” using services architecture. Services are javascript functions and are responsible to do a specific tasks only. This makes them an individual entity which is maintainable and testable. Controllers, filters can call them as on requirement basis. Services are normally injected using dependency injection mechanism of AngularJS.
AngularJS provides many inbuilt services for example, $http, $route, $window, $location etc. Each service is responsible for a specific task for example, $http is used to make ajax call to get the server data. $route is used to define the routing information and so on. Inbuilt services are always prefixed with $ symbol.
There are two ways to create a service.
factory service
Using factory method
Using factory method, we first define a factory and then assign method to it.
var mainApp = angular.module(“mainApp”, []); mainApp.factory('MathService', function() {
var factory = {};
factory.multiply = function(a, b) {
return a * b
}
return factory;
});
Using service method
Using service method, we define a service and then assign method to it. We've also injected an already available service to it.
mainApp.service('CalcService', function(MathService){
this.square = function(a) {
return MathService.multiply(a,a);
}
});
Resources
AngularJS + RequireJS
Bootstrap 1
**index.html**
<script src="lib/requirejs/require.js" data-main="js/main.js"></script> </body> </html>
**main.js**
require.config({
// alias libraries paths
paths: {
'domReady': '../lib/requirejs-domready/domReady',
'angular': '../lib/angular/angular'
},
// angular does not support AMD out of the box, put it in a shim
shim: {
'angular': {
exports: 'angular'
}
},
// kick start application
deps: ['./bootstrap']
});
deps: An array of dependencies to load. Useful when require is defined as a config object before require.js is loaded, and you want to specify dependencies to load as soon as require() is defined. Using deps is just like doing a require([]) call, but done as soon as the loader has processed the configuration. It does not block any other require() calls from starting their requests for modules, it is just a way to specify some modules to load asynchronously as part of a config block.
**bootstrap.js**
/**
* bootstraps angular onto the window.document node
*/
define([
'require',
'angular',
'app',
'routes'
], function (require, ng) {
'use strict';
require(['domReady!'], function (document) {
ng.bootstrap(document, ['app']);
});
});
**app.js**
define([
'angular',
'./controllers/index',
'./directives/index',
'./filters/index',
'./services/index'
], function (ng) {
'use strict';
return ng.module('app', [
'app.services',
'app.controllers',
'app.filters',
'app.directives'
]);
});
**routes.js**
define(['./app'], function (app) {
'use strict';
return app.config(['$routeProvider', function ($routeProvider) {
$routeProvider.when('/view1', {
templateUrl: 'partials/partial1.html',
controller: 'MyCtrl1'
});
$routeProvider.when('/view2', {
templateUrl: 'partials/partial2.html',
controller: 'MyCtrl2'
});
$routeProvider.otherwise({
redirectTo: '/view1'
});
}]);
});
**module definition controllers/module.js**
define(['angular'], function (ng) {
'use strict';
return ng.module('app.controllers', []);
});
**module loader (controllers/index.js)**
define([
'./my-ctrl-1',
'./my-ctrl-2'
], function () {});
**module components (controllers/my-ctrl-1.js)**
define(['./module'], function (controllers) {
'use strict';
controllers.controller('MyCtrl1', [function ($scope) {}]);
});
Bootstrap 2
**index.html**
<!-- basic setup -->
<script
data-main="main"
src="local/path/require.js">
</script>
<!-- advanced setup: using public CDN with local file fallback -->
<script data-main="main" src="http://requirejs.org/docs/release/2.1.14/minified/require.js"></script>
<script>window.require || document.write('<script data-main="main" src="local/path/require.js"></script>')</script>
**main.js**
// Configuration Options
require.config({
baseUrl: 'local/path',
// paths: maps ids with paths (no extension)
paths: {
'angular':
['https://code.angularjs.org/1.3.5/angular',
//fallback if CDN location fails
'local/path/angular']
},
// shim: makes external libraries reachable
shim: {
angular: {
exports : 'angular'
}
}
});
// Angular Bootstrap
require(['app', 'services', 'controllers'], function (app) {
// initialisation code defined within app.js
app.init();
});
**app.js**
define(['angular'], function (angular) {
var app = angular.module('myApp', []);
app.init = function () {
angular.bootstrap(document, ['myApp']);
};
return app;
});
**controller.js**
define(['app'], function(app) {
app.controller('MainController', ['$scope', 'Time', function ($scope, Time) {
$scope.time = Time.getTime();
}]);
});
Start Hacking
Angular-seed tutorial: https://github.com/angular/angular-seed/blob/master/README.md
Checkout angular-seed
[dang@dai142 angular-seed]$ git remote --v origin https://github.com/thuydang/angular-seed.git (fetch) origin https://github.com/thuydang/angular-seed.git (push) [dang@dai142 angular-seed]$ git branch master mess_around * requirejs_angularjs
npm install npm start localhost:8000/app/
Start local server:
#-c-1 disable cache node node_modules/http-server/bin/http-server ./app -p 9000 -c-1 http-server -a localhost -p 8000 -c-1
Workflow: Add File, Module, Functions Dependency
main.js
- paths: 'filename': 'path without js'
- shim: 'filename': dependencies, export
app.js
- List filenames in dependency list
- in functions list modules dependency