aboutsummaryrefslogtreecommitdiffstats
path: root/web/nms.gathering.org/nms2/index.html
diff options
context:
space:
mode:
Diffstat (limited to 'web/nms.gathering.org/nms2/index.html')
-rw-r--r--web/nms.gathering.org/nms2/index.html500
1 files changed, 435 insertions, 65 deletions
diff --git a/web/nms.gathering.org/nms2/index.html b/web/nms.gathering.org/nms2/index.html
index a9c33c4..7d49c33 100644
--- a/web/nms.gathering.org/nms2/index.html
+++ b/web/nms.gathering.org/nms2/index.html
@@ -1,68 +1,438 @@
<!DOCTYPE html>
<html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <meta charset="utf-8">
- <title>NMS2</title>
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta name="description" content="">
- <meta name="author" content="">
-
- <link href="css/bootstrap.min.css" rel="stylesheet">
- <link href="css/bootstrap-responsive.min.css" rel="stylesheet">
- <link href="css/slider.css" rel="stylesheet">
- <style type="text/css">
- body {
- padding-top: 60px;
- padding-bottom: 40px;
- }
- .sidebar-nav {
- padding: 9px 0;
- }
-
- </style>
-
- <!-- HTML5 shim, for IE6-8 support of HTML5 elements -->
- <!--[if lt IE 9]>
- <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
- <![endif]-->
-
- <style type="text/css"></style></head>
- <body>
- <div class="navbar navbar-inverse navbar-fixed-top">
- <div class="navbar-inner">
- <div class="container-fluid">
- <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
- <span class="icon-bar">
- </span>
- <span class="icon-bar"></span>
- <span class="icon-bar"></span>
- <span class="icon-bar"></span>
- </a>
- <div class="nav-collapse collapse">
- <p class="navbar-text pull-right" id="speed">Foobar</p>
- <ul class="nav">
- <li class="active"id="nav-param"><a href="#params" onclick="showSwitches()">Show Switches</a></li>
- <li id="nav-home"><a href="#about" onclick="showHome()">About</a></li>
- </ul>
- </div><!--/.nav-collapse -->
- </div>
- </div>
- </div>
-
- <div class="container-fluid">
- <div class="row-fluid">
- <div class="span12">
- <div class="input-append">
- <select onchange="switchChange()" id="switch-list"></select>
- <select onchange="portChange()" id="port-list"></select>
- <input type="text" id="switch-info">
- </div>
- <textarea id="foo" rows=20 cols=80 class="input-block-level"> </textarea>
- </div>
- </div><!--/row-->
- </div><!--/.fluid-container-->
- </div>
- <script src="js/jquery-1.10.2.min.js"></script>
- <script src="js/bootstrap.min.js"></script>
- <script src="js/nms2.js"></script>
- </body>
+ <meta charset="utf-8">
+ <title>NMS2</title>
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="description" content="">
+ <meta name="author" content="">
+
+ <script src="js/jquery-1.10.2.min.js"></script>
+ <!--<script src="http://cdn.jsdelivr.net/qtip2/2.2.1/jquery.qtip.min.js"></script>-->
+
+ <link href="css/bootstrap.min.css" rel="stylesheet">
+ <link href="css/bootstrap-responsive.min.css" rel="stylesheet">
+ <link href="css/slider.css" rel="stylesheet">
+ <!--<link src="http://cdn.jsdelivr.net/qtip2/2.2.1/jquery.qtip.min.css" rel="stylesheet">-->
+ <style type="text/css">
+ body {
+ padding-top: 60px;
+ padding-bottom: 40px;
+ }
+ .sidebar-nav {
+ padding: 9px 0;
+ }
+
+ #canvas {
+ background-image: url('http://nms.tg15.gathering.org/tg15-salkart.png');
+ }
+
+ #tooltip {
+ position: absolute;
+ left: 110px;
+ top: 110px;
+ border: 1px solid #FF0000;
+ }
+ </style>
+
+ <!-- HTML5 shim, for IE6-8 support of HTML5 elements -->
+ <!--[if lt IE 9]>
+ <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
+ <![endif]-->
+
+ <script type="text/javascript">
+ $(document).ready(function() {
+
+ var switches = {};
+ var selectedSwitch = null;
+ var selectedPort = null;
+ var mapSize = null;
+
+ var activeHover = null;
+
+ /* Bind: drop-down::switch-list -> onChange()
+ -------------------------------------------- */
+ $('#switch-list').change(function() {
+ selectedSwitch = $("#switch-list option:selected").text();
+ updatePortList();
+ //sumPorts(selectedSwitch);
+ });
+
+ /* Bind: drop-down::port-list -> onChange();
+ ------------------------------------------- */
+ $('#port-list').change(function() {
+ selectedPort = $("#port-list option:selected").text();
+ showPortdata();
+ });
+
+ $("#canvas").mousemove(function( event ) {
+ var x = event.pageX-$('#canvas').offset().left;
+ var y = event.pageY-$('#canvas').offset().top;
+ jQuery.each(switches, function(_switch, data) {
+ var sx = parseInt(data['x']);
+ var sy = parseInt(data['y']);
+ if (x>=sx && y>=sy && x <= sx+data['width'] && y <= sy+data['height']) {
+ $('#tooltip').css({backgroundColor: '#c2c2c2', bawidth: '100px', height: 'auto', visibility: 'visible', left: x+5, top: y-5});
+ $('#tooltip').html(_switch + '<br>');
+
+ activeHover = _switch;
+ /*
+ $('#tooltip').qtip({ // Grab some elements to apply the tooltip to
+ position: { type: 'absolute'},
+ position: { adjust: { x: 100, y: 100 } },
+ content: {
+ text: 'My common piece of text here'
+ }
+ })
+ */
+ return true;
+ } else { activeHover = null; }
+ });
+ });
+
+ /* ------------ Functions below -------------- */
+
+ function byteCount(bytes) {
+ var units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
+ i = 0;
+ while (bytes > 1024) { bytes = bytes / 1024; i++; }
+ return bytes.toFixed(1) + units[i];
+ }
+
+ function sum(arr) {
+ arr.reduce(
+ function(prev,current){
+ return +(current[1]) + prev;
+ }, 0
+ );
+ }
+
+ function hslToRgb(h, s, l){
+ var r, g, b;
+
+ if(s == 0){
+ r = g = b = l; // achromatic
+ }else{
+ var hue2rgb = function hue2rgb(p, q, t){
+ if(t < 0) t += 1;
+ if(t > 1) t -= 1;
+ if(t < 1/6) return p + (q - p) * 6 * t;
+ if(t < 1/2) return q;
+ if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;
+ return p;
+ }
+
+ var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
+ var p = 2 * l - q;
+ r = hue2rgb(p, q, h + 1/3);
+ g = hue2rgb(p, q, h);
+ b = hue2rgb(p, q, h - 1/3);
+ }
+
+ return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
+ }
+
+ function rgbToHsl(r, g, b){
+ r /= 255, g /= 255, b /= 255;
+ var max = Math.max(r, g, b), min = Math.min(r, g, b);
+ var h, s, l = (max + min) / 2;
+
+ if(max == min){
+ h = s = 0; // achromatic
+ }else{
+ var d = max - min;
+ s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
+ switch(max){
+ case r: h = (g - b) / d + (g < b ? 6 : 0); break;
+ case g: h = (b - r) / d + 2; break;
+ case b: h = (r - g) / d + 4; break;
+ }
+ h /= 6;
+ }
+
+ return [h, s, l];
+ }
+
+ function numberToColorHsl(i) {
+ // as the function expects a value between 0 and 1, and red = 0° and green = 120°
+ // we convert the input to the appropriate hue value
+ var hue = i * 1.2 / 360;
+ // we convert hsl to rgb (saturation 100%, lightness 50%)
+ var rgb = hslToRgb(hue, 1, .5);
+ // we format to css value and return
+ return 'rgb(' + rgb[0] + ',' + rgb[1] + ',' + rgb[2] + ')';
+ }
+
+
+
+ function sumPorts(_switch) {
+ var totalIn = 0;
+ var totalOut = 0;
+ var avgTotalIn = [];
+ var avgTotalOut = [];
+ var foundUplinks = 0;
+
+ if (_switch in switches && 'ports' in switches[_switch] ) {
+ jQuery.each(switches[_switch]['ports'], function(port, portdata) {
+ if ('history' in portdata && $.inArray(port, ['ge-0/0/44', 'ge-0/0/45', 'ge-0/0/46', 'ge-0/0/47']) > -1) {
+ var timeframe = parseInt(portdata['time'])-parseInt(portdata['history']['time']);
+
+ // byte == 1 octett
+ In = (parseInt(portdata['ifhcinoctets']) - parseInt(portdata['history']['ifhcinoctets'])) / timeframe;
+ Out = (parseInt(portdata['ifhcoutoctets']) - parseInt(portdata['history']['ifhcoutoctets'])) / timeframe;
+
+ if (In > 0 || Out > 0) {
+ totalIn += In;
+ avgTotalIn.push(In);
+
+ totalOut += Out;
+ avgTotalOut.push(Out);
+
+ foundUplinks++;
+ }
+ }
+ });
+
+ if (totalIn > 0 && totalOut > 0) {
+ var avgIn = sum(avgTotalIn)/avgTotalIn.length;
+ var avgOut = sum(avgTotalOut)/avgTotalOut.length;
+
+ switches[_switch]['average'] = {IN: avgIn, OUT: avgOut};
+ switches[_switch]['load'] = {IN: totalIn/foundUplinks, OUT: totalOut/foundUplinks};
+ }
+ }
+ }
+
+ function showPortdata() {
+ if(selectedSwitch && selectedPort) {
+ var portdata = switches[selectedSwitch]['ports'][selectedPort];
+ var timeframe = parseInt(portdata['time'])-parseInt(portdata['history']['time']);
+
+ // byte == 1 octett
+ inPerSec = (parseInt(portdata['ifhcinoctets']) - parseInt(portdata['history']['ifhcinoctets'])) / timeframe;
+ outPerSec = (parseInt(portdata['ifhcoutoctets']) - parseInt(portdata['history']['ifhcoutoctets'])) / timeframe;
+
+ $('#switchinfo').val('');
+ $('#switchinfo').val($('#switchinfo').val() + 'IN: ' + byteCount(inPerSec) + '/s\n');
+ $('#switchinfo').val($('#switchinfo').val() + 'Out: ' + byteCount(outPerSec) + '/s\n');
+
+ //jQuery.each(switches[selectedSwitch]['ports'][selectedPort], function(key, val) {
+ // $('#switchinfo').val($('#switchinfo').val() + inPerSec + '\n');
+ //});
+
+ console.log(switches);
+ }
+ }
+
+ function updatePortList() {
+ if(selectedSwitch) {
+ $('#port-list').empty()
+ jQuery.each(switches[selectedSwitch]['ports'], function(port, val) {
+ $('#port-list').append(
+ $('<option></option>').val(port).html(port)
+ );
+ });
+ }
+ }
+
+ function updateSwitchList() {
+ jQuery.each(switches, function(_switch, val) {
+ found = false;
+ $('#switch-list option').each(function(){
+ if (this.value == _switch) {
+ found = true;
+ return false;
+ }
+ });
+
+ if (!found) {
+ $('#switch-list').append(
+ $('<option></option>').val(_switch).html(_switch)
+ );
+ }
+ });
+
+ // var firstItem = $('#switch-list')[0][0].value;
+ selectedSwitch = $("#switch-list option:selected").text();
+
+ updatePortList();
+ selectedPort = $("#port-list option:selected").text();
+
+ showPortdata();
+ }
+
+ Object.size = function(obj) {
+ var size = 0, key;
+ for (key in obj) {
+ if (obj.hasOwnProperty(key)) size++;
+ }
+ return size;
+ };
+
+ function refreshInfra(func) {
+ /* Note:
+ These ajax-requests are chained in their own success
+ because the "inside ajax" can not be run before the predecessor
+ is completed. This is because the nested ajax-calls loops over
+ data that will otherwise not be found.
+ */
+
+ /* Background: Update switchlist
+ ------------------------------- */
+ $.ajax({
+ type: "GET",
+ url: "/switches-json2.pl",
+ dataType: "text",
+ success: function (data, textStatus, jqXHR) {
+ decoded = JSON.parse(data);
+ jQuery.each(decoded['switches'], function(_switch, val) {
+ switches[_switch] = val;
+ switches[_switch]['speed'] = 125000000; // 1Gbit In bytes! BYYYYTE!!! Geez louise!
+ });
+ console.log(switches);
+ /* Background: Update live port-data/port-list
+ --------------------------------------------- */
+ $.ajax({
+ type: "GET",
+ url: "/port-state.pl",
+ dataType: "text",
+ success: function (data, textStatus, jqXHR) {
+ var switchdata = JSON.parse(data);
+ jQuery.each(switchdata, function(_switch, val) {
+ switches[_switch]['ports'] = {};
+
+ jQuery.each(val['ports'], function(port, val) {
+ switches[_switch]['ports'][port] = val;
+ });
+ });
+ /* Background: Update port-history
+ --------------------------------- */
+ $.ajax({
+ type: "GET",
+ url: "/port-state.pl?time=5m",
+ dataType: "text",
+ success: function (data, textStatus, jqXHR) {
+ var switchdata = JSON.parse(data);
+ jQuery.each(switchdata, function(_switch, val) {
+ jQuery.each(val['ports'], function(port, val) {
+ switches[_switch]['ports'][port]['history'] = val;
+ });
+ });
+ if(typeof func != 'undefined')
+ func();
+ }
+ })
+ }
+ });
+ }
+ });
+ }
+
+ function randint(min, max) {
+ return Math.floor(Math.random() * (max - min)) + min;
+ }
+
+ Array.max = function( array ){
+ return Math.max.apply( Math, array );
+ };
+
+ window.addEventListener('resize', resizeCanvas, false);
+
+ function drawMap() {
+ if (Object.size(switches) > 0) {
+ var c = $("#canvas")[0];
+ var ctx = c.getContext("2d");
+ ctx.clearRect(0, 0, c.width, c.height);
+ jQuery.each(switches, function(_switch, data) {
+ sumPorts(_switch);
+ if("load" in switches[_switch]) {
+ var perc = 100.0/parseInt(data['speed']);
+ var throughput = Array.max([switches[_switch]['load']['IN'], switches[_switch]['load']['OUT']]);
+ var percentage = throughput*perc;
+ ctx.fillStyle=numberToColorHsl( 100-percentage );
+ ctx.fillRect(parseInt(data['x']), parseInt(data['y']), data['width'], data['height']);
+ }
+ });
+ if(activeHover) {
+ ctx.beginPath();
+ ctx.moveTo(parseInt(switches[activeHover]['x']), parseInt(switches[activeHover]['y']));
+ ctx.lineTo(switches[activeHover]['width'], switches[activeHover]['height']);
+ ctx.stroke();
+ }
+ }
+ }
+ function resizeCanvas() {
+ canvas.width = mapSize[0];
+ canvas.height = mapSize[1];
+
+ var ref = window.setInterval(function() { drawMap(); }, 50);
+ }
+
+ function init() {
+ var url = $('#canvas').css('background-image').slice(4, -1);
+
+ var bgImg = $('<img />');
+ bgImg.hide();
+ bgImg.bind('load', function()
+ {
+ mapSize = [$(this).width(), $(this).height()];
+ // After we've loaded the map into a hidden <img> to measure the size
+ // we can resize the canvas accordingly. The resize function contains all our draw stuff.
+ resizeCanvas();
+ });
+ $('body').append(bgImg);
+ bgImg.attr('src', url);
+
+ // Fire only once, with a parameter to update the switch-list.
+ // This will flicker the drop-down once but giving us a function
+ // to refresh "infra" in the background retrieving data in real time without affecting the UI.
+ refreshInfra(updateSwitchList);
+ }
+ init();
+
+ });
+ </script>
+
+ <style type="text/css"></style></head>
+ <body>
+ <div class="navbar navbar-inverse navbar-fixed-top">
+ <div class="navbar-inner">
+ <div class="container-fluid">
+ <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
+ <span class="icon-bar">
+ </span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ </a>
+ <div class="nav-collapse collapse">
+ <p class="navbar-text pull-right" id="speed">Foobar</p>
+ <ul class="nav">
+ <li class="active"id="nav-param"><a href="#params" onclick="showSwitches()">Show Switches</a></li>
+ <li id="nav-home"><a href="#about" onclick="showHome()">About</a></li>
+ </ul>
+ </div><!--/.nav-collapse -->
+ </div>
+ </div>
+ </div>
+
+ <div class="container-fluid">
+ <div class="row-fluid">
+ <div class="span12">
+ <div class="input-append">
+ <select id="switch-list"></select>
+ <select id="port-list"></select>
+ <br>
+
+ <!--<textarea id="switchinfo" rows=20 cols=80 class="input-block-level"> </textarea>-->
+ <canvas id="canvas"></canvas>
+ </div>
+ </div><!--/row-->
+ </div><!--/.fluid-container-->
+ </div>
+ <script src="js/bootstrap.min.js"></script>
+ <script src="js/nms2-lib.js"></script>
+ <script src="js/nms2.js"></script>
+
+ <div id="tooltip"></div>
+ </body>
</html>