merge Amisha's changes
[plstackapi.git] / planetstack / templates / admin / dashboard / welcome.html
1 {% extends "admin/base.html" %}
2 {% load admin_static %}
3
4 {% block content %}
5 <link rel="stylesheet"  href="http://ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.0/css/jquery.dataTables.css">
6 <link rel="stylesheet" type="text/css" href="{% static 'suit/css/suit.css' %}" media="all">
7 <link rel="stylesheet" type="text/css" href="http://ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.0/css/jquery.dataTables_themeroller.css">
8 <link rel="stylesheet" type="text/css" href="{% static 'planetstack.css' %}" media="all">
9 <link rel="stylesheet" href="http://code.jquery.com/ui/1.10.4/themes/smoothness/jquery-ui.css">
10
11 <link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.2/leaflet.css" />
12 <script src="http://cdn.leafletjs.com/leaflet-0.7.2/leaflet.js"></script>
13
14
15 <!-- no need to include jquery here as it's already included by base.html. Including it multiple times will break mtuity statistics. -->
16 <!-- src="http://code.jquery.com/jquery-1.9.1.js" -->
17
18 <script src="http://code.jquery.com/ui/1.10.4/jquery-ui.js"></script>
19 <script src="http://ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.4/jquery.dataTables.min.js"></script>
20 <script type="text/javascript" src="{% static 'log4javascript-1.4.6/log4javascript.js' %}"></script>
21 <script src="{% static 'js/Leaflet.MakiMarkers.js' %}" > </script>
22   
23 <script>
24   $(function() {
25     $( "#hometabs" ).tabs({active: 0, //event: "mouseover"
26       //collapsible: true
27     });
28   });
29 </script>
30 <script>
31
32 function confirmDialog(title,msg) {
33     var dialog = $('<div>'+msg+'</div>');
34     var def = $.Deferred();
35
36     $(dialog).dialog({
37         resizable: false,
38         title: title,
39         autoOpen: true,
40         modal: true,
41         dialogClass: "dashboard-hpc-sliver",
42         buttons: {
43             'OK': function() {
44                 def.resolve();
45                 log.debug("Chose to add a sliver");
46                 $( this ).dialog( "close" );
47             },
48             'Cancel': function() {
49                 def.reject();
50                 $( this ).dialog( "close" );
51             }
52         },
53         close: {
54         }
55     });
56     return def.promise();
57 }
58
59   </script>
60
61 <!-- <div id="hometabs" class="inner-center-column ui-tabs ui-widget ui-widget-content ui-corner-all"> -->
62 <div id="hometabs" >
63   <ul id="suit_form_tabs" class="nav nav-tabs nav-tabs-suit" data-tab-prefix="suit-tab">
64     <li><a href="#tabs-1">Developer View</a></li>
65     <li><a href="#tabs-2">CDN Operations </a></li>
66     <li><a href="#tabs-3">Historical</a></li>
67     <li><a href="#tabs-4">Slice Interactions</a></li>
68     <li><a href="#tabs-5">Tenant</a></li>
69   </ul>
70 <div id="tabs-1">
71 </div>
72 <div id="tabs-2">
73     <div id="HPCDashboard">
74     <h1>CDN Operations View</h1>
75     <span id="hpcSummary">
76         <span class="summary-attr"><b>Active Slivers:</b> <span id="active-slivers-value"> </span> </span>
77         <span class="summary-attr"><b>Overall Throughput:</b> <span id="overall-throughput-value"> </span>  </span>
78         <span class="summary-attr-util"><b>Average CPU Utilization:</b> <span id="cpu-utilization-value"> </span>  </span>
79     </span>
80     <div id="map-us" ></div>
81     <div style="line-height: 30%"><br></div><table border=0><tr>
82     <td>Least Loaded&nbsp;&nbsp;</td>
83     <td bgcolor="#0000FF" width=40>&nbsp;</td>
84     <td bgcolor="#00FFFF" width=40>&nbsp;</td>
85     <td bgcolor="#00FF00" width=40>&nbsp;</td>
86     <td bgcolor="#FFFF00" width=40>&nbsp;</td>
87     <td bgcolor="#FF0000" width=40>&nbsp;</td>
88     <td>&nbsp;&nbsp;Most Loaded</td>
89     </tr></table>
90     </div>
91 </div>
92 <div id="tabs-3">
93 {% include "/opt/planetstack/templates/admin/dashboard/hpc_historical.html" %}
94 </div>
95 <div id="tabs-4">
96 {% include "/opt/planetstack/templates/admin/dashboard/slice_interactions.html" %}
97 </div>
98 <div id="tabs-5">
99 {% include "/opt/planetstack/templates/admin/dashboard/tenant.html" %}
100 </div>
101 </div>
102
103 <div id="confirmNodeAdded" title="Added Node to Site"><p>Added Node to Site</p></div>
104 <div id="confirmNodeRemoved" title="Removed Node from Site"><p>Added Node to Site</p></div>
105 <script>
106 var oTable;
107 var consoleAppender = new log4javascript.BrowserConsoleAppender();
108 var patternLayout = new log4javascript.PatternLayout("%d{HH:mm:ss,SSS} %l{s:l} %-5p - %m{1}%n");
109 consoleAppender.setLayout(patternLayout);
110
111 //var log  = log4javascript.getDefaultLogger();
112 var log  = log4javascript.getRootLogger();
113 log.addAppender(consoleAppender);
114 log.setLevel(log4javascript.Level.ERROR);
115
116 function updateUserSliceTable(){
117     log.debug("Should grab user slice info");
118     jQuery.ajax({
119         async:true,
120         dataType: 'json',
121         url: '/hpcdashuserslices',
122         success: function(data){
123             log.info("Got Data back for User SliceTable");
124             //parseData(data);
125             //createUserSliceTable(data);
126             setTimeout(function () { updateUserSliceTable() }, 5000);
127         },
128         error: function(data){
129             log.debug("COULDNT GET DATA BACK");
130             setTimeout(function () { updateUserSliceTable() }, 5000);
131         }
132     });
133 }
134
135 function createUserSliceTable(data) {
136     log.debug("Creating User Slice Table");
137
138     //Add check for #dynamicusersliceinfo_filter label-> input having focus here
139
140     $('#tabs-1').html( '<table cellpadding="0" cellspacing="0" border="0" class="display" id="dynamicusersliceinfo"></table>' );
141     var actualEntries = [];
142     log.debug(data['userSliceInfo']['rows'][0]['slicename']);
143
144     var rows = data['userSliceInfo']['rows'];
145     for (row in rows) {
146         log.debug(row[0]);
147         slicename = rows[row]['slicename'];
148         sliceid = rows[row]['sliceid'];
149         role = rows[row]['role'];
150         slivercount = rows[row]['slivercount'];
151         sitecount = rows[row]['sitecount'];
152         actualEntries.push(['<a href="http://{{request.get_host}}/admin/core/slice/' + sliceid + '">' + slicename + '</a>',
153                             role, slivercount, sitecount]);
154     }
155     oTable = $('#dynamicusersliceinfo').dataTable( {
156         "bJQueryUI": true,
157         "aaData":  actualEntries ,
158         "bStateSave": true,
159         "aoColumns": [
160             { "sTitle": "Slice" },
161             { "sTitle": "Privilege" , sClass: "alignCenter"},
162             { "sTitle": "Number of Slivers" , sClass: "alignCenter"},
163             { "sTitle": "Number of Sites" , sClass: "alignCenter"},
164         ]
165     } );
166
167     // If the filter had focus, reapply here
168
169     setTimeout(function() {
170        jQuery.ajax({
171            url: '/hpcdashuserslices',
172            dataType: 'json',
173            success: function(data){ createUserSliceTable(data); },
174            complete: function(){ },
175        });
176     },  10000);
177 }
178
179 function initTable(){
180     log.debug("Initializing Table")
181     jQuery.ajax({
182         url: '/hpcdashuserslices',
183         dataType: 'json',
184         success: function(data){ createUserSliceTable(data); },
185         complete: function(){
186         }
187     });
188     updateUserSliceTable();
189 }
190
191
192 initTable();
193
194 $( "#confirmNodeAdded" ).dialog({ autoOpen: false,
195                     modal: true,
196                     buttons: {
197                         Ok: function() {
198                            $( this ).dialog( "close" );
199                         }
200                     }});
201 $( "#confirmNodeRemoved" ).dialog({ autoOpen: false });
202
203 L.Map = L.Map.extend({
204     openPopup: function(popup) {
205         this._popup = popup;
206
207         return this.addLayer(popup).fire('popupopen', {
208             popup: this._popup
209         });
210     }
211 });
212
213
214 //Iterate through data and find the max/min coordinates to include all of our points to start
215 var map = L.map('map-us'); //.setView([0, 0], 1);
216 map.scrollWheelZoom.disable();
217
218 //
219 // Great tiles, but starting to occasionally see 403 errors on certain tiles causing grey out effect
220 //L.tileLayer('http://{s}.tile.cloudmade.com/BC9A493B41014CAABB98F0471D759707/997/256/{z}/{x}/{y}.png', {
221 //
222 // Swapping out cloudmade tiles to openstreetmap - too many grey tiles showing
223 L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
224     maxZoom: 18,
225     attribution: 'Test'
226 }).addTo(map);
227
228 var arrayOfLatLngs = [];
229 var mapData = {{ cdnData|safe }};
230 log.debug( mapData );
231
232 for ( var key in mapData ) {
233     arrayOfLatLngs.push([mapData[key]['lat'],mapData[key]['long']]);
234     log.debug( arrayOfLatLngs );
235
236     mapData[key]['marker'] = L.marker([mapData[key]['lat'], mapData[key]['long']], {icon: getIcon(mapData[key]['numNodes'], mapData[key]['numHPCSlivers'], 0, mapData[key]['hot']) });
237     mapData[key]['marker'].addTo(map).bindPopup(setPopupVals(key, mapData[key]));
238
239 }
240 var bounds = new L.LatLngBounds(arrayOfLatLngs);
241 map.fitBounds(bounds);
242
243 var popup = L.popup();
244
245
246 function setPopupVals (site, siteData) {
247     var retVal = '<span class="SiteDetail"><b>' + site + '</b></span>' + 
248                    '</br><a href="' + siteData['siteUrl'] + '">' + siteData['siteUrl'] + '</a>' + 
249                    '</br><b>HPC Slivers: </b>' + siteData['numHPCSlivers'] + 
250                    '</br><b>Total Nodes: </b>' + siteData['numNodes'] +
251 //                   '</br><b>Hot: </b>' + Math.round(siteData['hot']*100) +
252                    '</br><b>Measured Load: </b>' + siteData['load'] + '%' +
253                    '<span id="addSlivers"></br><a href="#" id="addHPCSliver" data-site="' + site + '" data-availNodes="' + siteData['numNodes'] +'">Add HPC Slivers</a> </span>' +
254                    '<span id="remSlivers"><a href="#" id="remHPCSliver" data-site="' + site + '">Remove HPC Slivers</a> </span>';
255
256    return retVal;
257 }
258
259 $('#map-us').on('click', '#remHPCSliver', function() {
260    
261     $.ajax({
262         url : '/dashboardaddorremsliver/',
263         dataType : 'json',
264         data: {site: $(this).data('site'),
265                actionToDo: "rem",
266                csrfmiddlewaretoken: "{{ csrf_token }}",   // < here 
267                state:"inactive" },
268         type : 'POST',
269         //success: function(response)
270         //{
271          //   alert("Successfully posted request to REMOVE sliver");
272         //},
273         complete:function(){
274             confirmDialog("Info","Removed an HPC Sliver from Site ");
275         },
276         //error:function (xhr, textStatus, thrownError){
277          //   alert("Could not request to remove HPC Sliver");
278         //}
279     });
280 });
281
282 $('#map-us').on('click', '#addHPCSliver', function() {
283    
284     $.ajax({
285         url : '/dashboardaddorremsliver/',
286         dataType : 'json',
287         data: {site: $(this).data('site'),
288                actionToDo: "add",
289                csrfmiddlewaretoken: "{{ csrf_token }}",   // < here 
290                state:"inactive" },
291         type : 'POST',
292         success: function(response)
293         {
294             //alert("Successfully posted request to add sliver");
295         },
296         complete:function()
297         { 
298             confirmDialog("Info","Added an HPC Sliver to Site ");
299         },
300         //error:function (xhr, textStatus, thrownError){
301          //   alert("error doing something");
302         //}
303     });
304   //  confirmDialog("Add HPC Slivers","Add some HPC Slivers to site " + $(this).data('site'));
305 });
306
307 function getIcon(numNodes, numHPCSlivers, currentBW, hot) {
308     //var colorChoices = ["#007FFF", "#0000FF", "#7f00ff", "#FF00FF", "#FF007F", "#FF0000"];
309     var colorChoices = ["#0000FF", "#00FFFF", "#00FF00", "#FFFF00", "#FF0000"];
310
311     var ratio = hot * 100; //(numHPCSlivers/numNodes) * 100;
312     var numColors = colorChoices.length;
313     var colorBands = 100/numColors;
314
315     //Algorithm for color tone should consider the number of available nodes
316     // on the site, and then how much the current dedicated nodes are impacted
317     //var iconColor = 0;
318     var iconColor = colorChoices.length-1;
319     for (colorBand = 0; colorBand < numColors; colorBand ++) {
320         if (ratio < colorBands * colorBand+1) {
321             iconColor = colorBand
322             break;
323         }
324     }
325
326     if (numHPCSlivers < 1) {
327         iconColor = "#7F7F7F";
328     } else {
329         iconColor = colorChoices[iconColor];
330     }
331
332     var icon = L.MakiMarkers.icon({icon: "star-stroked", color: iconColor , size: "s"});
333     return icon;
334 }
335
336 function updateMaps() {
337     log.debug("Attempting to update Maps");
338     $.ajax({
339     url : '/hpcdashboard',
340     dataType : 'json',
341     type : 'GET',
342     success: function(newData)
343     {
344         log.debug("Successfully got data back...");
345         log.debug(newData);
346         log.debug("Still have old data too");
347         log.debug(mapData);
348         updateMapData(newData);
349     }
350 });
351     setTimeout(updateMaps, 30000)
352
353 }
354
355 function updateMapData(newData) {
356     for ( site in newData ) {
357         var isNewSite = false;
358         //check to see if the site is new or not
359         if (site in mapData) {
360             log.debug("Site " + site + " already mapped");
361             //take ownership of marker
362             newData[site]['marker'] = mapData[site]['marker'];
363             delete mapData[site];
364             newData[site]['marker'].setIcon(getIcon(newData[site]['numNodes'], newData[site]['numHPCSlivers'],  0, newData[site]['hot']));
365             // workaround, markers currently don't have a setPopup Content method -- so have to grab object directly
366             newData[site]['marker']._popup.setContent(setPopupVals(site, newData[site]));
367         }
368         else {
369             isNewSite = true;
370             log.debug("New Site detected: " + site);
371             newData[site]['marker'] = L.marker([newData[site]['lat'], newData[site]['long']], 
372                                               {icon: getIcon(newData[site]['numNodes'], newData[site]['numHPCSlivers'],  0, newData[site]['hot']) });
373             newData[site]['marker'].addTo(map).bindPopup(setPopupVals(site, newData[site])); //.openPopup();
374             log.debug("Should have added the new site");
375
376         }
377     }
378
379     // Anything still in data needs to be removed since it is no longer a valid site
380     for (remSite in mapData) {
381         log.warn("Site: " + remSite + " is no longer valid, removing from map");
382         map.removeLayer(data[remSite]['marker']);
383     }
384     mapData = newData;
385 }
386
387 function onMapClick(e) {
388     popup
389     .setLatLng(e.latlng)
390     .setContent("You clicked the map at " + e.latlng.toString())
391     .openOn(map);
392 }
393
394 setTimeout(updateMaps, 5000)
395
396 // from stackexchange
397 function setInnerText (elementId, text) {
398     var element;
399     if (document.getElementById) {
400         element = document.getElementById(elementId);
401     } else if (document.all) {
402         element = document.all[elementId];
403     }
404     if (element) {
405         if (typeof element.textContent != 'undefined') {
406             element.textContent = text;
407         } else if (typeof element.innerText != 'undefined') {
408             element.innerText = text;
409         } else if (typeof element.removeChild != 'undefined') {
410             while (element.hasChildNodes()) {
411                 element.removeChild(element.lastChild);
412             }
413             element.appendChild(document.createTextNode(text)) ;
414         }
415     }
416 }
417
418 function updateLabelData(summaryData) {
419     setInnerText("active-slivers-value", summaryData["total_slivers"]);
420     setInnerText("overall-throughput-value", (summaryData["total_bandwidth"]*8/1024/1024/1024).toFixed(2) + " Gbps");
421     setInnerText("cpu-utilization-value", summaryData["average_cpu"] + "%");
422 }
423
424 function updateLabels() {
425     log.debug("Attempting to update Labels");
426     $.ajax({
427     url : '/hpcsummary',
428     dataType : 'json',
429     type : 'GET',
430     success: function(newData)
431     {
432         updateLabelData(newData);
433     }
434 });
435     setTimeout(updateLabels, 30000)
436
437 }
438
439 setTimeout(updateLabels, 5000)
440                 
441
442 </script>
443 {% endblock %}