== DLUX === Setup and Run ==== Required Technology Stack * NodeJS (Http Server, http://www.nodejs.org ) * Bower (JavaScript Package Manager, http://bower.io ) * GruntJS (JavaScript Task Runner, http://gruntjs.com ) * AngularJS (JavaScript client-side framework, http://www.angularjs.org ) * Karma (JavaScript Test Runner, http://karma-runner.github.io/ ) * Other AngularJS/Third-party JS libraries ==== Install NodeJS ===== For Windows and Mac without brew: . Go to http://www.nodejs.org . Download and install NodeJS ===== For Mac with brew installed: $ brew update $ brew install node ===== Verify NodeJS is installed: $ npm --version ==== Install required Node libraries Install the following node components using npm. For Mac, you may have to use "sudo" $ sudo npm -g install grunt-cli $ sudo npm -g install bower $ sudo npm -g install karma $ sudo npm -g install karma-cli ==== Get latest DLUX code from git .Anonymous clone $ git clone http://git.opendaylight.org/gerrit/p/dlux.git .If you have a opendaylight.org account $ git clone ssh://@git.opendaylight.org:29418/dlux.git ==== Build the DLUX code ---- $ cd dlux/dlux-web #installs the necessary NodeJS related components for the project - will create a node_modules directory $ sudo npm install #installs necessary components provided by bower $ bower install # update dlux-web with all DLUX static resources for each module by running maven $ mvn clean install # run the unit tests and start karma test runner # this will open up the default browser pointing to karma test running and run the unit tests $ grunt watch ---- Hit Ctrl-C to quit ==== Build DLUX Karaf feature and distribution Once you have installed all necessary modules mentioned above such as nodesjs, bower etc.. You should be able to build the DLUX feature and distribution. Run following command at DLUX home directory +/dlux+. Once successful, It will create DLUX Karaf distribution and DLUX Karaf feature. You can find Karaf distribution at dlux/distribution-dlux. $ mvn clean install ==== Enable DLUX Karaf Feature Get the Opendaylight official helium distribution or use Karaf distribution of DLUX project created above. Unzip the Karaf distribution and go to bin directory of your distribution and run following command to start Karaf. It will start the Karaf console, which may not have any feature installed by default. $ ./karaf Install basic MD-SAL controller features on the Karaf console. I would recommend installing the following features before starting the DLUX feature. L2Switch feature internally enables MD-SAL data broker and openflow plugin service. L2Switch also makes sure that in topology UI, hosts are also visible along with switches. We need the mdsal-apidocs feature for yangUI in DLUX. $ feature:install odl-restconf $ feature:install odl-l2switch-switch $ feature:install odl-mdsal-apidocs Install the AD-SAL features on the Karaf console. $ feature:install odl-adsal-all $ feature:install odl-adsal-northbound Then, install the DLUX feature $ feature:install odl-dlux-core Once done, you should be able to access DLUX UI at http://:8181/dlux/index.html For login, use admin as both the username and the password. Before login, just make sure that MD-SAL features are enabled. you can check what all features are installed by running following command - $ feature:list -i ==== Run standalone DLUX against the controller * Start Karaf distribution with installed MD-SAL and AD-SAL features. * Goto mininet VM and create a topology for the controller Based on where you controller is running, Update baseUrl in file dlux/dlux-web/config/development.json. Back in the DLUX terminal, run $ grunt live Open a browser and go to the URL http://localhost:9000/dlux/index.html This should bring up the DLUX UI and pull data from the controller. Use admin as the username and password to access the UI. === DLUX Modules DLUX modules are the individual features such as nodes, topology etc. Each module has a defined structure and you can find all existing modules under /dlux/modules directory of code. ==== Module Structure * module_folder ** .module.js ** .controller.js ** .services.js ** .directives.js ** .filter.js ** index.tpl.html ** .css ==== Create New Module ===== Define the module First, create an empty file with the module name. Next, we need to surround our module with a define function. This allows RequireJs to see our module.js files. The first argument is an array who contain all the module dependencies. The second is a callback function whose body contain the AngularJs code base. The function parameters correspond with the order of dependencies. Each dependences is injected into a parameter if it is provided. Finally, we return the angular module to be able to inject it as a parameter in our others modules. For each new module, you must have at least those two dependencies : * angularAMD : It's a wrapper arround angularjs to provide an AMD (Asynchronous Module Definition) support. Which is used by RequireJs. For more information click https://github.com/amdjs/amdjs-api/blob/master/AMD.md[here]. * app/core/core.services : This one is mandatory if you want to add content in the navigation menu, the left bar or the top bar. The following are not mandatory, but very often used. * angular-ui-router : A library to provide URL routing * routingConfig : To set the level access to a page define(['angularAMD','app/routingConfig', 'angular-ui-router','app/core/core.services'], function(ng) { var module = angular.module('app.a_module', ['ui.router.state', 'app.core']); // module configuration module.config(function() { [...] }); return module; }); ===== Set the register function If your module is only required by the main application, you will need register your angular components because the app will be already bootstrapped. Otherwise, it won't see your components on the runtime. TIP: If your module is only use by an other module, you don't have to do this step. module.config(function($compileProvider, $controllerProvider, $provide) { module.register = { controller : $controllerProvider.register, directive : $compileProvider.directive, factory : $provide.factory, service : $provide.service }; ===== Set the route The next step is to set up the route for our module. This part is also done in the configuration method of the module. We have to add *$stateProvider* as a parameter. module.config(function($stateProvider) { var access = routingConfig.accessLevels; $stateProvider.state('main.module', { url: 'module', views : { 'content' : { templateUrl: 'src/app/module/module.tpl.html', controller: 'ModuleCtrl' } } }); }); ===== Adding element to the navigation menu To be able to add item to the navigation menu, the module requires the *NavHelperProvider* parameter in the configuration method. This helper has a method to easily add an item to the menu. The first parameter is an id that refers to the level of your menu and the second is a object. var module = angular.module('app.a_module', ['app.core']); module.config(function(NavMenuHelper) { NavMenuHelper.addToMenu('myFirstModule', { "link" : "#/module/index", "active" : "module", "title" : "My First Module", "icon" : "icon-sitemap", "page" : { "title" : "My First Module", "description" : "My first module" } }); }); The ID parameter supports, for now, two levels of depth. So if your ID looks like 'rootNode.childNode', the helper will look for a node named 'rootNode' and it will append the 'childNode' to it. If the root node doesn't exist, it will create it. ===== Link the controller file To include the controller file, we will use the NavHelperProvider. It contain a method who will load the given file. [...] NavHelperProvider.addControllerUrl('/.controller'); The module.js file is now complete. ==== Create the Controllers, factory, directive, etc Creating the controller and other components are similar to the module. * First, add the define method * Second, add the relative path to the module definition * Last, create your methods as you usually do it with angularJs define(['/.module'], function(module) { module.register.controller('ModuleCtrl', function($rootScope, $scope) { }); }); ==== Append to the main file The last thing to do is to add the path of the module definition file and add the name of the angular module. So, edit the file app.module.js as the follows. //----Temporary-------\\ var module = [ [...] '/.js', [...] var e = [ [...] 'a_module', [...] //--------------------\\ === Yang Utils Yang Utils are used by yang UI to perform all CRUD operations. All of these utilities are present in yangutils.services.js file. It has following factories - .Factories * *arrayUtils* – defines functions for working with arrays. * *pathUtils* – defines functions for working with xpath (paths to APIs and subAPIs). It divides xpath string to array of elements, so this array can be later used for search functions. * *syncFact* – provides synchronization between requests to and from ODL when it’s needed. * *custFunct* – it is linked with apiConnector.createCustomFunctionalityApis in yangui controller in yangui.controller.js. That function makes it possible to create some custom function called by the click on button in index.tpl.html. All custom functions are stored in array and linked to specific subAPI. When particular subAPI is expanded and clicked, its inputs (linked root node with its child nodes) are displayed in the bottom part of the page and its buttons with custom functionality are displayed also. * *reqBuilder* – creates object builder = request built from filled inputs on page in JSON format. It is possible with “show preview” button. This request is sent to ODL when button PUT or POST is clicked. * *yinParser* – factory for reading of .xml files of yang models and creating objects hierarchy. Every statement from yang is represented by node. * *nodeWrapper* – adds functions to objects in tree hierarchy created with yinParser. These functions provide functionality for every type of node. * *apiConnector* – the main functionality is filling the main structures and linking them. Structure of APIs and subAPIs which is two level array - first level is filled by main APIs, second level is filled by others sub APIs. Second main structure is array of root nodes, which are objects including root node and its children nodes. Linking these two structures is creating links between every subAPI (second level of APIs array) and its root node, which must be displayed like inputs when subAPI is expanded. * *yangUtils* – some top level functions which are used by yangui controller for creating the main structures.