From: Felix Date: Tue, 3 Dec 2019 01:39:40 +0000 (+0000) Subject: table on topology views add and start router controller X-Git-Url: https://git.josue.xyz/?p=VSoRC%2F.git;a=commitdiff_plain;h=4ff4cfab60fd88f431c88603d57612fc489dc62f table on topology views add and start router controller --- diff --git a/img/toporouting.png b/img/toporouting.png new file mode 100644 index 0000000..41ac9ef Binary files /dev/null and b/img/toporouting.png differ diff --git a/js/topology/cards.js b/js/topology/cards.js new file mode 100644 index 0000000..04c0606 --- /dev/null +++ b/js/topology/cards.js @@ -0,0 +1,101 @@ +// Copyright (c) 2018 Maen Artimy +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +var BAR_IDX = 1; +var CONTAINER_IDX = 2; + +var cardControl = ( function() { + console.log("cardControl"); + var expand = function(e) { + var size = e.parentElement.parentElement.parentElement.style.width; + if(size==='96%') { // first value of size is "" + e.parentElement.parentElement.parentElement.style.width = '45%'; + } else { + e.parentElement.parentElement.parentElement.style.width = '96%'; + } + //e.classList.toggle("active"); + }; + + var collapse = function(e) { + var c = e.parentElement.parentElement.parentElement.childNodes.item(CONTAINER_IDX); + var disp = c.style.display; + if(disp == "none") { + c.style.display = "block" + } else { + c.style.display = "none"; + } + }; + + return { + expand: expand, + collapse: collapse + } +})(); + +// Generate cards dynamicly based on the template given by local 'html' variable +// and data from the 'views' list. Cards are added to the 'parent' element +// passed as argument. +var generateCards = ( function() { + console.log("generateCards"); + var html = "

{Title}

\ +
\ + \ +

No data to display...

\ +
"; + + // + + var run = function(views, parent) { + console.log("generateCards.run"); + var doc = document.getElementById(parent); + doc.innerHTML = ""; + for (var idx in views) { + var d = document.createElement("div"); + d.id = views[idx].id; + d.classList.add("card"); + var card = html.replace("{Title}", views[idx].dsc); + d.innerHTML = card; + doc.appendChild(d); + } + }; + + /*var loadModules = function(views) { + for (var idx in views) { + if(views[idx].call) { + var card = document.getElementById(views[idx].id); + var container = card.childNodes.item(CONTAINER_IDX) + + var myModule = new BaseModule(views[idx].cmd); + myModule.callback = views[idx].call; + myModule.run(container); + } + } + };*/ + + return { + run: run + } +})(); + +var views = [ +{id:"mSwitch", cmd:"/listswitch", dsc:"Open V Switch ID(s)", call:dpList, ref:true}, +{id:"mTableStats", cmd:"/tablestatus?tablestat=", dsc:"Table stats", call:dpTable, ref:true}, +{id:"mPortDesc", cmd:"/portsdesc?portdesc=", dsc:"Port Desc", call:dpTable, ref:true}, +{id:"mPorts", cmd:"/portsstat?portstat=", dsc:"Ports stats", call:dpTable, ref:true}, +//{id:"mTableFeature", cmd:"/data?tablefeature=", dsc:"Table Features", call:dpTable, ref:true}, +//{id:"mQueueStats", cmd:"/data?queuestat=", dsc:"Queue Stats", call:dpTable, ref:true}, +//{id:"mQueueConfig", cmd:"/data?queueconfig=", dsc:"Queue Configuration", call:dpTable, ref:true}, +//{id:"mMeters", cmd:"/data?meterstat=", dsc:"Meter stats", call:dpTable, ref:true} +]; diff --git a/js/topology/main.js b/js/topology/main.js new file mode 100644 index 0000000..de882e5 --- /dev/null +++ b/js/topology/main.js @@ -0,0 +1,94 @@ +// Copyright (c) 2018 Maen Artimy +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * All global objects are here. + * + **/ +var myGlobalObject = (function () { + console.log("myGlobalObject"); + var dpid = 1; //current datapath (switch) ID + var myMasterURL = ""; //"http://localhost:8080"; + + // returns full url for the command sent to the SDN controller + var url = function(command) { + var cmd = command.replace("",dpid); //dpidStr(dpid)); + return myMasterURL + cmd; + }; + + // sends asynchronous request to the SDN controller + function httpGetAsync(command, callback, element) { + //console.log("httpGetAsync"); + var COMPLETE = 4; + var OK = 200; + var NOTFOUND = 404; + var UNAVAILABLE = 503; + // this script is for sending a GET request to a server + var xmlHttp = new XMLHttpRequest(); + xmlHttp.onreadystatechange = function() { + if (xmlHttp.readyState == COMPLETE) { + if(xmlHttp.status == OK) { + callback(xmlHttp.responseText, element); + } else { + console.log(xmlHttp.status); + } + } + } + xmlHttp.open("GET", url(command), true); // true for asynchronous + xmlHttp.send(null); + } + + function httpPostAsync(command, parm, callback, element) { + //console.log("httpPostAsync"); + var COMPLETE = 4; + var OK = 200; + var NOTFOUND = 404; + var UNAVAILABLE = 503; + // this script is for sending a GET request to a server + var xmlHttp = new XMLHttpRequest(); + xmlHttp.onreadystatechange = function() { + if (xmlHttp.readyState == COMPLETE) { + if(xmlHttp.status == OK) { + callback(xmlHttp.responseText, element); + } else { + console.log(xmlHttp.status); + } + } + } + xmlHttp.open("POST", url(command), true); // true for asynchronous + //xmlHttp.setRequestHeader("Content-Type", "application/json"); + xmlHttp.setRequestHeader("Content-Type", "plain/text"); + xmlHttp.send(parm); + } + + function dpidStr(dpid) { + return ("000000000000000" + dpid.toString(16)).substr(-16); + } + + function setDPID(str) { + dpid = parseInt(str); + } + + function getDPID() { + return dpid; + } + + // these are the public objects + return { + dpid: getDPID, + setDPID: setDPID, + httpGetAsync: httpGetAsync, + httpPostAsync: httpPostAsync, + } +})(); diff --git a/js/topology/mainmenu.js b/js/topology/mainmenu.js new file mode 100644 index 0000000..8296288 --- /dev/null +++ b/js/topology/mainmenu.js @@ -0,0 +1,58 @@ +// Copyright (c) 2018 Maen Artimy +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +$(function () { + var path = window.location.pathname; + var url = window.location.href; + + var menu = '' + +/*
\ + Flow Control \ + \ +
\*/ + + //var logo = '
'; + + var hashtag = url.lastIndexOf('#') + var slash = url.lastIndexOf('/') + 1 + var filename = hashtag < 0 ? url.substring(slash) : url.substring(slash, hashtag); + + $('#menu').html(menu); + var $link = $('a[href="' + filename + '"]'); + $link.addClass("active"); + $link.parent().show(); + + $(".topmenu").click(function() { + //$("#myLinks").show(); + $("#myLinks").animate({height: "toggle"}, 120); + }) + + +}); diff --git a/js/topology/modules.js b/js/topology/modules.js new file mode 100644 index 0000000..4d05772 --- /dev/null +++ b/js/topology/modules.js @@ -0,0 +1,252 @@ +// Copyright (c) 2018 Maen Artimy +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * Definition of modules. + * + **/ + +// Makes a GET request to the controller +function BaseModule(command) { + var cmd = command; + var go = myGlobalObject; + + var run = function(element) { + go.httpGetAsync(cmd, this.callback, element); + }; + + var callback = function(jsondata, element) { + console.log(element); + } + + return { + callback: callback, + run: run + } +} + +// Makes a POST request to the controller +function BasePostModule(command) { + var cmd = command; + var go = myGlobalObject; + var idx; + var parm = ""; + + var dpInFilter = function (e, x) { + idx = x; + e.innerHTML ="Filter: "; + }; + + var run = function(element) { + go.httpPostAsync(cmd, this.param, this.callback, element); + }; + + var callback = function(jsondata, element) { + console.log(element); + } + + return { + idx: this.idx, + param: this.param, + dpInFilter: dpInFilter, + callback: callback, + run: run + } +} + +function hc(myString) { + return myString.replace("_"," ").replace(/\b\w/g, l => l.toUpperCase()) +} + +// Populates the Switch ID card +var dpList = function (jsondata, element) { + var switches = JSON.parse(jsondata); + var found = false; + + //var html = ""; + element.innerHTML = ""; + var ul = document.createElement("ul"); + ul.setAttribute("id", "swlist"); + for(var s in switches) { + var num = +switches[s]; //("000000000000000" + switches[s].toString(16)).substr(-16); + //html += num + "
"; + + var li = document.createElement("li"); + li.innerHTML = num; + if(switches[s] === myGlobalObject.dpid()) { + li.classList.add("selected"); + found = true; + } + li.addEventListener("click", clickMe); + ul.appendChild(li); + } + element.appendChild(ul); + //element.innerHTML = html; + if (!found && document.getElementById("swlist").firstChild) { + var name = document.getElementById("swlist").firstChild.innerHTML + myGlobalObject.setDPID(name) + moduleManager.loadModules(views); + } +}; + +var dpStruct = function (jsondata, element) { + var jsonobj = JSON.parse(jsondata); + if(!jsonobj) return; + var switchName = Object.keys(jsonobj); + var struct = jsonobj[switchName]; + var html = ""; + for(var key in struct) { + html += hc(key) + " : " + struct[key] + "
"; + } + element.innerHTML = html; +}; + +var dpTable = function (jsondata, element) { + var dispObj = function(obj) { + // JSON to string? + var str = ""; + if(Array.isArray(obj)) { + for(var item in obj) { + if(obj[item] instanceof Object) { + + } else { + str += obj[item].replace(":","=") + "
"; + } + } + return str; + } else { + var allKeys = Object.keys(obj); + for(var key in allKeys) { + str += allKeys[key] + " = " + obj[allKeys[key]] + "
"; + } + } + return str; + }; + + var jsonobj = JSON.parse(jsondata); + if(!jsonobj) return; + + var switchName = Object.keys(jsonobj); + + // extract the flows + var rows = jsonobj[switchName]; + + // get the headers + var col = []; + for (var c in rows[0]) { + col.push(c); + } + col.sort(); // A, B, C, ... + col.reverse(); // ..., C, B, A + + // CREATE DYNAMIC TABLE. + var table = document.createElement("table"); + //table.classList.add("fixed_headers"); + + // CREATE HTML TABLE HEADER ROW USING THE EXTRACTED HEADERS ABOVE. + var tr = table.insertRow(-1); // TABLE ROW. + for (var i = 0; i < col.length; i++) { + var th = document.createElement("th"); // TABLE HEADER. + th.innerHTML = col[i].replace("_","
"); + tr.appendChild(th); + } + + // ADD JSON DATA TO THE TABLE AS ROWS. + for (var i = 0; i < rows.length; i++) { + tr = table.insertRow(-1); + for (var j = 0; j < col.length; j++) { + var tabCell = tr.insertCell(-1); + + if(typeof rows[i][col[j]] === 'object') { + //tabCell.innerHTML = dispObj(rows[i][col[j]]); + tabCell.innerHTML = JSON.stringify(rows[i][col[j]]); + } else { + tabCell.innerHTML = rows[i][col[j]]; + } + } + } + element.innerHTML = ""; + table.align = "center"; + element.appendChild(table); +} + +// Populate the cards with data +var moduleManager = (function () { + var time = 15000; //10 sec + var myViews = []; + + var loadModules = function(views) { + myViews.length = 0; // it is supposed to be the best way to clear an array + self.clearInterval(); + + for (var idx in views) { + if(views[idx].call) { + var card = document.getElementById(views[idx].id); + var container = card.childNodes.item(CONTAINER_IDX); + + var myModule; + if(views[idx].post) { + myModule = new BasePostModule(views[idx].cmd); + var bar = card.childNodes.item(BAR_IDX); + myModule.dpInFilter(bar, idx); + } else { + myModule = new BaseModule(views[idx].cmd); + } + myModule.callback = views[idx].call; + myModule.run(container); + views[idx].module = myModule; // we need this to refresh + views[idx].container = container; // we need this to refresh + + if(views[idx].ref) { // refresh is required + myViews.push(views[idx]); + }; + } + } + //myViews = views; + }; + + var refreshModules = function() { + for (var idx in myViews) { + myViews[idx].module.run(myViews[idx].container); + } + } + + var interval = self.setInterval(refreshModules,time); + + var setInterval = function(newtime) { + time = newtime; + interval = self.setInterval(loadModules,time); + } + + var getInterval = function() { + console.log(time); + } + + return { + setInterval: setInterval, + loadModules: loadModules + } +})(); + +function clickMe(e) { + //console.log(e); + myGlobalObject.setDPID(e.currentTarget.innerHTML); + moduleManager.loadModules(views); +} + +function mainFilterFunc(element, idx) { + var str = element.getElementsByClassName("filterInput")[0].value; + views[idx].module.param = str; + views[idx].module.run(views[idx].container); +} diff --git a/js/topology/topology.js b/js/topology/topology.js index 45040e1..ebd33a0 100644 --- a/js/topology/topology.js +++ b/js/topology/topology.js @@ -294,22 +294,18 @@ $(function () { // La funcion jsonget fue creada para sustituir el metodo json de D3 function jsonget() { - let xhr = new XMLHttpRequest(); xhr.open('GET', "/gettopo" , true); //console.log(xhr); //para ver en la consola xhr.onload = function() { if (xhr.status == 200) { //can use this.status instead //console.log(xhr.responseText);// para ver en la consola - - listTopology(JSON.parse(xhr.responseText)); plotGraph(toGraph(JSON.parse(xhr.responseText))); } } xhr.send(); } - - jsonget(); + jsonget(); diff --git a/npm-debug.log b/npm-debug.log index 54b150b..a2cfa34 100644 --- a/npm-debug.log +++ b/npm-debug.log @@ -8,7 +8,7 @@ 7 verbose unsafe-perm in lifecycle true 8 info web@1.0.0 Failed to exec start script 9 error web@1.0.0 start: `node src/index.js` -9 error Exit status 143 +9 error Exit status 1 10 error Failed at the web@1.0.0 start script. 10 error This is most likely a problem with the web package, 10 error not with npm itself. diff --git a/partials/header.ejs b/partials/header.ejs index 9d98aa5..d7e6f35 100644 --- a/partials/header.ejs +++ b/partials/header.ejs @@ -7,13 +7,14 @@
diff --git a/src/routes/index.js b/src/routes/index.js index 0084754..d9abe2e 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -4,6 +4,7 @@ const { const router = new Router(); + //renders de las paginas web router.get("/", (req, res) => { res.render("index") @@ -40,6 +41,18 @@ router.get('/free', (req, res) => { }); }); +router.post('/flowdel', (req, res) => { + var sys = require('sys') + var exec = require('child_process').exec; + var child; + var flow = JSON.stringify(req.body); + child = exec("curl -X POST -d "+req.body+"localhost:8080/flowdel", function(error, stdout, stderr) { + console.log(stdout); + console.log(req.body); + res.send(req.body); + }); +}); + router.get('/mpstat', (req, res) => { var sys = require('sys') @@ -51,7 +64,6 @@ router.get('/mpstat', (req, res) => { }); }); - router.get('/ifstat', (req, res) => { var sys = require('sys') var exec = require('child_process').exec; @@ -66,8 +78,8 @@ router.get('/showtemp', (req, res) => { var sys = require('sys') var exec = require('child_process').exec; var child; - child = exec("cd /home/pi/scripts && ./gettemp.sh", function(error, stdout, stderr) { - console.log("show temp"); + child = exec("cd /home/pi/scripts && (./multissh.sh \"$(echo $(cat geteverything.sh))\" |grep -v rpi | sort -n -t . -k 1,1 -k 2,2 -k 3,3 -k 4,4)", function(error, stdout, stderr) { + console.log("show temp");//this was modified res.send(stdout); }); }); @@ -178,16 +190,26 @@ router.get('/getvsorcdata', (req, res) => { console.log("getting vsorc data"); res.send(stdout+"^"+isVsorcUP); }); - }); router.get('/getcontrollerdata', (req, res) => { var sys = require('sys') var exec = require('child_process').exec; var child; + var child2; + child2 = exec("ps aux | grep python | grep ryu | grep -v grep |awk {'print $2'}", function(error, stdout, stderr) { + console.log(stdout); + console.log("view status controller"); + if (stdout === ""){ + isControllerUP = false; + }else { + isControllerUP = true; + } + }); child = exec("cd /home/pi/scripts && cat controllerout 2>/dev/null", function(error, stdout, stderr) { console.log("getting controller data"); - res.send(stdout+"^"+isControllerUP); + res.send(stdout+"^"+isControllerUP);//Send controller data and UP or DOWN separate by ^ }); + }); router.get('/listswitch', (req, res) => { var sys = require('sys') @@ -199,15 +221,17 @@ router.get('/listswitch', (req, res) => { let value = ''; try { value = JSON.parse(stdout) + res.send(value); } catch(error) { - console.error(error); + //console.error(error); console.log("no response from server"); // expected output: ReferenceError: nonExistentFunction is not defined // Note - error messages will vary depending on browser + res.send("No response from server"); } - res.send(value); + }); }); @@ -225,6 +249,76 @@ router.get('/status', (req, res) => { }); }); +router.get('/tablestatus', (req, res) => { + var sys = require('sys') + var exec = require('child_process').exec; + var child; + console.log(req.query); + child = exec("curl \"localhost:8080/data?tablestat="+req.query.tablestat+"\"", function(error, stdout, stderr) { + console.log("table status"); + console.log(stdout); + let value = ''; + try { + value = JSON.parse(stdout) + res.send(value); + } + catch(error) { + //console.error(error); + console.log("no response from server"); + // expected output: ReferenceError: nonExistentFunction is not defined + // Note - error messages will vary depending on browser + let er = "No response from server"; + res.send(JSON.stringify(er)); + } + }); +}); + +router.get('/portsdesc', (req, res) => { + var sys = require('sys') + var exec = require('child_process').exec; + var child; + console.log(req.query); + child = exec("curl \"localhost:8080/data?portdesc="+req.query.portdesc+"\"", function(error, stdout, stderr) { + console.log("port desc"); + let value = ''; + try { + value = JSON.parse(stdout) + res.send(value); + } + catch(error) { + //console.error(error); + console.log("no response from server"); + // expected output: ReferenceError: nonExistentFunction is not defined + // Note - error messages will vary depending on browser + let er = "No response from server"; + res.send(JSON.stringify(er)); + } + }); +}); + +router.get('/portsstat', (req, res) => { + var sys = require('sys') + var exec = require('child_process').exec; + var child; + console.log(req.query); + child = exec("curl \"localhost:8080/data?portstat="+req.query.portstat+"\"", function(error, stdout, stderr) { + console.log("port status"); + console.log(stdout); + let value = ''; + try { + value = JSON.parse(stdout) + res.send(value); + } + catch(error) { + //console.error(error); + console.log("no response from server"); + // expected output: ReferenceError: nonExistentFunction is not defined + // Note - error messages will vary depending on browser + let er = "No response from server"; + res.send(JSON.stringify(er)); + } + }); +}); router.get('/startcontroller', (req, res) => { isControllerUP = true; @@ -239,6 +333,17 @@ router.get('/startcontroller', (req, res) => { }); }); +router.get('/startcontrollerrouter', (req, res) => { + isControllerUP = true; + var sys = require('sys') + var exec = require('child_process').exec; + var child; + child = exec("cd /home/pi/scripts && touch controllerout && ./ryurouter.sh > controllerout 2>&1 &", function(error, stdout, stderr) { + console.log("controller REST Router started"); + res.send(stdout); + }); +}); + router.get('/stopcontroller', (req, res) => { isControllerUP = false; var sys = require('sys') @@ -320,7 +425,7 @@ router.get('/stopvsorc', (req,res) =>{ //antes, en ves de echo exit > fifo, estaba sudo kill $(ps aux | grep GRE| grep sudo|awk {'print $2'}) console.log("Exiting..."); - child2 = exec("cd /home/pi/scripts && echo exit > fifo && rm fifo", function(error, stdout, stderr) { + child2 = exec("cd /home/pi/scripts && echo exit > fifo && rm fifo && sudo killall tail", function(error, stdout, stderr) { console.log(stdout); payload+="killed\n\n"+stdout; }); diff --git a/src/views/access.ejs b/src/views/access.ejs index 578847b..06b901e 100644 --- a/src/views/access.ejs +++ b/src/views/access.ejs @@ -27,7 +27,14 @@ <%include ../../partials/header%>
- +

Topologia para practica de Routing

+ +

+ Esta practica consiste en crear una topologia como la mostrada en esta imagen, asi como las + direcciones IP de los hosts y enrutamiento estatico, de modo que exista conectividad entre las redes de h1 y h2 como de h3 y h2, + pero no de las redes de h1 a h3. + Para esto, utiliza la API rest_router del controlador RYU. +