My Wiki!

Opendaylight Operations

mvn clean install -Dskip
mvn install -DskipTests -DskipIT -nsu

Load karaf feature:

  feature:install odl-mdsal-apidocs odl-netconf-mdsal odl-restconf

Load dlux:

  feature:install odl-dlux-all

Load ovsdb feature:

  feature:install odl-ovsdb-library odl-ovsdb-schema-openvswitch odl-ovsdb-schema-hardwarevtep odl-ovsdb-plugin odl-ovsdb-northbound \
  odl-ovsdb-compatibility-layer odl-ovsdb-ovssfc
  

Load l2switch

  feature:install odl-l2switch-all
  

Now mininet ping work!!

openflowplugin

Following should be installed:

  odl-openflowplugin-southbound odl-openflowplugin-flow-services odl-openflowplugin-nsf-services odl-openflowplugin-nsf-model
  
  feature:install odl-openflowplugin-flow-services-rest

Then the end-to-end tutorials here should work: https://wiki.opendaylight.org/view/OpenDaylight_OpenFlow_Plugin:User_Guide

All in one:

feature:install odl-restconf odl-l2switch-switch odl-mdsal-apidocs odl-dlux-all
feature:install odl-restconf odl-mdsal-apidocs odl-dlux-all

Log

  tail -f distribution/distribution-karaf/target/assembly/data/log/karaf.log
  

dlux

karaf> http:list | grep -i dlux
271 | DluxLoaderIndexServlet | ServletModel-33   | Deployed    | /index.html                  | [/index.html/*]                                             
271 | ResourceServlet        | /dlux             | Deployed    | /                            | [/]                 

ip:8080/index.html

netstat -ntlp 
karaf>http:info

ip:8181/explorer/index.html

Karaf Development

  opendaylight-user@root>info

Set Log Level

  log:set debug org.opendaylight.ovsdb.openstack.netvirt.impl.NeutronL3Adapter
  log:set TRACE org.opendaylight.controller.networkconfig.neutron
  log:set debug org.opendaylight.ovsdb  
  
* http://os-tech.blogspot.de/2011/07/karaf-logging-overview.html
  log:set DEBUG org.opendaylight.openflowplugin.learningswitch.multi.LearningSwitchManagerMultiImpl 
  
  karaf@root> log:set LEVEL mypackage.subpackage

This will set the logging for that specific package to whatever the level you provide.

In Karaf 3.x, you can also filter for a specific package using the following command:

karaf@root> log:get mypackage.subpackage

Add Feature Repo

  feature:repo-add <url or short name> ?<version>
  feature:repo-all mvn:
  repo-add mvn:de.dailab.nemo.dmm/features-dmm/1.0.0-SNAPSHOT/xml/features
  feature:install dmm-task-all

Auto Import New Bundle

dev:watch is replaced by bundle:watch

or system:property

bundle:list | grep bundle
xx abdc

Karaf 3.0:

With this command you can define maven url’s which are be observed by Karaf after you have installed a bundle.

bundle:install -s mvn:ch.dropbit.test/cxf-rest-test/0.0.1-SNAPSHOT
bundle:watch mvn:ch.dropbit.test/cxf-rest-test/0.0.1-SNAPSHOT

Afterwards each maven build (mvn clean install) triggers a cxf-rest-test bundle reload. If you want to remove an observation use something like:

bundle:watch --remove mvn:ch.dropbit.test/cxf-rest-test/0.0.1-SNAPSHOT


bundle:watch mvn:groupid/artifactID/version

It will actually monitor all bundles that have a location matching mvn:* that have '-SNAPSHOT' in their url.

Debug Features

Show feature dependency:

  feature:info feature_name
Description:
  OpenDaylight :: isco-controller :: main
Feature has no configuration
Feature has no configuration files
Feature depends on:
  odl-mdsal-broker 1.4.1-Boron-SR1
  odl-mdsal-models 0.9.1-Boron-SR1
Feature contains followed bundles:
  mvn:com.gtarc.isco.network.controller/isco-controller-main/0.1.0
Feature has no conditionals.

1. Quick build for dev

Mininet

  mn --topo single,3 --mac --switch ovsk,protocols=OpenFlow13 --controller remote,ip=10.10.11.44,port=6653
  

python:

Mininet CLI

h1 ping h2
switch s1,s2 start

Help

Documented commands (type help <topic>):
========================================
EOF    gterm  iperfudp  nodes        pingpair      py      switch
dpctl  help   link      noecho       pingpairfull  quit    time  
dump   intfs  links     pingall      ports         sh      x     
exit   iperf  net       pingallfull  px            source  xterm 

You may also send a command to a node using:
  <node> command {args}
For example:
  mininet> h1 ifconfig

The interpreter automatically substitutes IP addresses
for node names when a node is the first arg, so commands
like
  mininet> h2 ping h3
should work.

Some character-oriented interactive commands require
noecho:
  mininet> noecho h2 vi foo.py
However, starting up an xterm/gterm is generally better:
  mininet> xterm h2

ODL Rest

Event Subscription with Rest

Create Subscription from Postman

POST /restconf/operations/sal-remote:create-data-change-event-subscription HTTP/1.1
Host: 192.168.201.43:8080
Authorization: Basic YWRtaW46YWRtaW4=
Content-Type: application/xml
Accept: application/xml
Cache-Control: no-cache

<input xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote">
  <path xmlns:a="urn:opendaylight:inventory">/a:nodes</path>
  <datastore xmlns="urn:sal:restconf:event:subscription">CONFIGURATION</datastore>
  <scope xmlns="urn:sal:restconf:event:subscription">BASE</scope>  
</input>

The response has the Websocket Stream location:

<output 
    xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote">
    <stream-name>opendaylight-inventory:nodes/datastore=CONFIGURATION/scope=BASE</stream-name>
</output>

Request a Socket to the Stream

GET /restconf/streams/stream/opendaylight-inventory:nodes/datastore=CONFIGURATION/scope=BASE HTTP/1.1
Host: 192.168.201.43:8080
Authorization: Basic YWRtaW46YWRtaW4=
Content-Type: application/xml
Accept: application/xml
Cache-Control: no-cache

The Stream socket is contained in Response header:

Content-Length → 0
Location → ws://192.168.201.43:8185/opendaylight-inventory:nodes/datastore=CONFIGURATION/scope=BASE
Server → Jetty(8.1.14.v20131031)

Open Connection to the Stream with a Websocket Client (java, chrome plugin)

Using the socket returned above:

 ws://192.168.201.43:8185/opendaylight-inventory:nodes/datastore=CONFIGURATION/scope=BASE

Make Some Changes to the Nodes Database

POST /restconf/config HTTP/1.1
Host: 192.168.201.43:8080
Authorization: Basic YWRtaW46YWRtaW4=
Content-Type: application/xml
Accept: application/xml
Cache-Control: no-cache

<nodes xmlns="urn:opendaylight:inventory">
  <node>
    <id>56</id>
  </node>
</nodes>

Sample notification websocket with Restangular

Note: network topology path

Request the Stream:

We request the stream from the controller by making a POST HTTP request to the data change subscription URL for OpenDaylight:

url = baseURL + 'operations/sal-remote:create-data-change-event-subscription'
headers = ...
payload = '<input xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote"> \
               <path xmlns:a="urn:TBD:params:xml:ns:yang:network-topology">/a:network-topology</path> \
               <datastore xmlns="urn:sal:restconf:event:subscription">OPERATIONAL</datastore> \
               <scope xmlns="urn:sal:restconf:event:subscription">SUBTREE</scope> \
           </input>'

responseData = requests.post( url, data=payload, headers-headers, auth=... )
streamName = responseData.text

Look the path up in Restconf service:

http://192.168.201.43:8181/restconf/modules

<module>
<name>network-topology</name>
<revision>2013-10-21</revision>
<namespace>urn:TBD:params:xml:ns:yang:network-topology</namespace>
</module>

Writing Angluar Service

Service:

   IMADluxUIApp.register.factory('OdlWebsocketSvc', function(ImaTopologyRestangular, $q, $rootScope, E| 54                                                                                                      
    NV) {                                                                                                | 55         /**                                                                                          
 96         // We return this object to anything injecting our service                                   | 56          *  Handle Websocket for Topology Update                                                     
 97     var svc = {                                                                                      | 57          */                                                                                          
 98       getOldStream: function() {                                                                     | 58         var streamName;                                                                              
 99         return ImaTopologyRestangular.one('restconf').customPOST(                                    | 59         var wsUrl;                                                                                   
100             '<input xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote"><path xmlns:| 60         OdlWebsocketSvc.getOldStream()                                                               
    a="urn:opendaylight:inventory">/a:nodes</path><datastore xmlns="urn:sal:restconf:event:subscription">| 61           .then(function(response) {                                                                 
    CONFIGURATION</datastore><scope xmlns="urn:sal:restconf:event:subscription">BASE</scope></input>'    | 62             streamName = response.data.output['stream-name'];                                        
101             , // body, data                                                                          | 63             //console.log("Got stream-name: ", response.output);                                     
102             'operations/sal-remote:create-data-change-event-subscription', // path                   | 64             console.log("Got stream-name: ", response.data.output['stream-name']);                   
103             {}, // custom param                                                                      | 65                                                                                                      
104             {                                                                                        | 66             // subscribeToStream                                                                     
105               //'Authorization': 'Basic ' + btoa('{admin}:{admin}'),                                 | 67             OdlWebsocketSvc.subscribeToStream(streamName)                                            
106               "Content-Type": "application/xml"                                                      | 68               .then(function(response) {                                                             
107               //"Access-Control-Allow-Methods": "POST, GET, PUT, DELETE, OPTIONS"                    | 69                 wsUrl = response.headers('Location');
108             } // custom header                                                                       | 70                 console.log("Got 200: ", wsUrl);
109             );                                                                                       | 71                                                                                                      
110       },                                                                                             | 72                 // open Websocket
111       subscribeToStream: function(streamName) {                                                      | 73                 //OdlWebsocketSvc.openWebsocket(wsUrl)
112         return ImaTopologyRestangular.one('restconf').customGET(                                     | 74                 
113             'streams/stream/opendaylight-inventory:nodes/datastore=CONFIGURATION/scope=BASE', // path| 75               }, function() {console.log("subscribeToStream: There was an error");
114             {}, // custom param                                                                      | 76               }); //--
115             {                                                                                        | 77           }, function() {
116               //'Authorization': 'Basic ' + btoa('{admin}:{admin}'),                                 | 78             console.log("There was an error");
117               "Content-Type": "application/xml"                                                      | 79           });
118               //"Access-Control-Allow-Methods": "POST, GET, PUT, DELETE, OPTIONS"                    | 80           
119             } // custom header                                                                       | 81           
120             );                                                                                       | 82       /*--*/                                                                                         
121       },                                                                                             | 83       
122       openWebsocket: function(wsUrl) {                                                               | 84       /*
123         svc.ws = new WebSocket(wsUrl);                                                               | 85         $scope.line = {
124         svc.ws.onopen = function(){                                                                  | 86           labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
125           console.log("Socket has been opened!");                                                    | 87           series: ['Series A', 'Series B'],
126         };                                                                                           | 88           data: [
127       },                                                                                             | 89             [65, 59, 80, 81, 56, 55, 40],
128       socketNotificationListener: function() {                                                       | 90             [28, 48, 40, 19, 86, 27, 90]
129         return svc.data;                                                                             | 91           ],
130       },                                                                                             | 92           onClick: function (points, evt) {
131       ws: null                                                                                       | 93             console.log(points, evt);
132                                                                                                      | 94           }
133     };                                                                                               | 95         };

Navigation