====== 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 ?
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.
===== - Quick build for dev =====
* https://lists.opendaylight.org/pipermail/mdsal-dev/2017-March/001096.html
*
====== Mininet ======
mn --topo single,3 --mac --switch ovsk,protocols=OpenFlow13 --controller remote,ip=10.10.11.44,port=6653
python:
* https://wiki.opendaylight.org/view/OpenDaylight_OpenFlow_Plugin::Mininet_with_multiple_controllers
===== Mininet CLI =====
h1 ping h2
switch s1,s2 start
Help
Documented commands (type help ):
========================================
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:
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 ======
* https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL:Restconf
* rest sample + websocket: https://github.com/thuydang/bvcRestConfExample1
===== Event Subscription with Rest =====
* https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL:Restconf:Change_event_notification_subscription
* https://github.com/opendaylight/docs/blob/master/manuals/developer-guide/src/main/asciidoc/controller/websocket-notifications.adoc
* https://github.com/BRCDcomm/BVC/wiki/Developing-REST-Applications-on-BVC
==== 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
/a:nodes
CONFIGURATION
BASE
The response has the **Websocket Stream** location:
==== 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
56
==== 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 = ' \
/a:network-topology \
OPERATIONAL \
SUBTREE \
'
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
network-topology
2013-10-21
urn:TBD:params:xml:ns:yang:network-topology
=== 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 '/a:nodes| 61 .then(function(response) {
CONFIGURATIONBASE' | 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 };