====== 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: opendaylight-inventory:nodes/datastore=CONFIGURATION/scope=BASE ==== 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 };