====== Dlux Dev ======
* https://wiki.opendaylight.org/view/OpenDaylight_dlux:Getting_started
* https://wiki.opendaylight.org/view/OpenDaylight_dlux:Setup_and_Run
* https://wiki.opendaylight.org/view/OpenDaylight_dlux:Add_new_application
* https://wiki.opendaylight.org/view/OpenDaylight_dlux:Create_and_add_a_module
===== Checkout Dlux =====
git branch -a
git checkout -b ima_dlux origin/stable/lithium
===== Getting Start =====
* https://wiki.opendaylight.org/view/OpenDaylight_dlux:Add_new_application
===== Create Dlux App with Archetype =====
* https://wiki.opendaylight.org/view/OpenDaylight_DLUX:Create_application_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.
2. 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
de.dailab.nemo.ima.controller
IMADluxUI-bundle
${project.version}
Add feature definition in src/main/resources/features.xml
ima-controller
odl-dlux-core
mvn:de.dailab.nemo.ima.controller/IMADluxUI-bundle/${project.version}
==== 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 =====
* https://wiki.opendaylight.org/view/OpenDaylight_DLUX:Setup_and_Run
===== OpenDaylight dlux:Create and add a module =====
* https://wiki.opendaylight.org/view/OpenDaylight_dlux:Create_and_add_a_module
===== Tutorial Workflow =====
====== Network Topology GUI with cisco NextUI ======
* https://github.com/CiscoDevNet/opendaylight-sample-apps/tree/master/next-odl-integration
* http://community.brocade.com/t5/DevNet-Documents/Video-How-to-Write-RESTCONF-Application-For-OpenFlow-Device/ta-p/70635
* https://developer.cisco.com/site/devnetlabs/bgp/
* https://fredhsu.wordpress.com/2013/06/04/making-a-topology-graph-with-opendaylight-rest-api-python-and-javascript/
* https://developer.cisco.com/site/neXt/learn/
===== Brocade =====
* https://github.com/BRCDcomm/BVC/wiki/RESTCONF-Developer-Resources
===== ODL Restconf =====
* https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL:Restconf:Change_event_notification_subscription
* https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL:MD-SAL_Document_Review:RESTCONF
* https://github.com/opendaylight/docs/blob/master/manuals/developer-guide/src/main/asciidoc/controller/websocket-notifications.adoc
* example:
* http://www.packetdesign.com/blog/pce-topology-notifications-with-opendaylight-helium
* http://sdnhub.org/tutorials/onos/
*
====== 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/
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.
===== Quick AngularJs + RequireJs =====
====== AngularJS + RequireJS Tutorial ======
* data/workspace/angularjs_dev_ws
git clone angular-seed
sudo npm install -g bower
===== TODO detail on working env =====
===== For dummies =====
* http://anthonypigeot.com/javascript-workflow-for-dummies-scopes-and-variables/
* http://anthonypigeot.com/javascript-wokflow-for-dummies-require-js/
===== 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:
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 ====
* http://briantford.com/blog/huuuuuge-angular-apps
* http://cliffmeyers.com/blog/2013/4/21/code-organization-angularjs-javascript
follow:
* https://www.startersquad.com/blog/angularjs-requirejs/
* http://www.ringabell.org/en/un-simple-guide-pour-debuter-avec-requirejs/
* https://medium.com/angularjs-meetup-south-london/angular-using-requirejs-amd-528358208f84
===== 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 ====
* http://www.tutorialspoint.com/angularjs/angularjs_modules.htm
===== AngularJS + RequireJS =====
https://medium.com/angularjs-meetup-south-london/angular-using-requirejs-amd-528358208f84
==== Bootstrap 1 ====
* https://www.startersquad.com/blog/angularjs-requirejs/
==== **index.html** ====