Scott Baker | 9416013 | 2014-05-18 18:49:20 -0700 | [diff] [blame] | 1 | <div id="HPCDashboard"> |
| 2 | <h1>CDN Operations View</h1> |
| 3 | <span id="hpcSummary"> |
| 4 | <span class="summary-attr"><b>Allocated Slivers:</b> <span id="active-slivers-value"> </span> </span> |
| 5 | <span class="summary-attr"><b>CDN Bandwidth:</b> <span id="overall-throughput-value"> </span> </span> |
| 6 | <span class="summary-attr-util"><b>CDN Load:</b> <span id="cpu-utilization-value"> </span> </span> |
| 7 | </span> |
| 8 | <div id="map-us" ></div> |
| 9 | <div style="line-height: 30%"><br></div><table border=0><tr> |
| 10 | <td>Least Loaded </td> |
| 11 | <td bgcolor="#0000FF" width=40> </td> |
| 12 | <td bgcolor="#00FFFF" width=40> </td> |
| 13 | <td bgcolor="#00FF00" width=40> </td> |
| 14 | <td bgcolor="#FFFF00" width=40> </td> |
| 15 | <td bgcolor="#FF0000" width=40> </td> |
| 16 | <td> Most Loaded</td> |
| 17 | </tr></table> |
| 18 | </div> |
| 19 | |
Scott Baker | f70a791 | 2014-05-19 10:37:53 -0700 | [diff] [blame] | 20 | <div id="confirmNodeAdded" title="Added Node to Site"><p>Added Node to Site</p></div> |
| 21 | <div id="confirmNodeRemoved" title="Removed Node from Site"><p>Added Node to Site</p></div> |
| 22 | |
Scott Baker | 9416013 | 2014-05-18 18:49:20 -0700 | [diff] [blame] | 23 | <script> |
| 24 | $( "#confirmNodeAdded" ).dialog({ autoOpen: false, |
| 25 | modal: true, |
| 26 | buttons: { |
| 27 | Ok: function() { |
| 28 | $( this ).dialog( "close" ); |
| 29 | } |
| 30 | }}); |
| 31 | $( "#confirmNodeRemoved" ).dialog({ autoOpen: false }); |
| 32 | |
| 33 | L.Map = L.Map.extend({ |
| 34 | openPopup: function(popup) { |
| 35 | this._popup = popup; |
| 36 | |
| 37 | return this.addLayer(popup).fire('popupopen', { |
| 38 | popup: this._popup |
| 39 | }); |
| 40 | } |
| 41 | }); |
| 42 | |
| 43 | |
| 44 | //Iterate through data and find the max/min coordinates to include all of our points to start |
| 45 | var map = L.map('map-us'); //.setView([0, 0], 1); |
| 46 | map.scrollWheelZoom.disable(); |
| 47 | |
| 48 | // |
| 49 | // Great tiles, but starting to occasionally see 403 errors on certain tiles causing grey out effect |
| 50 | //L.tileLayer('http://{s}.tile.cloudmade.com/BC9A493B41014CAABB98F0471D759707/997/256/{z}/{x}/{y}.png', { |
| 51 | // |
| 52 | // Swapping out cloudmade tiles to openstreetmap - too many grey tiles showing |
| 53 | L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { |
| 54 | maxZoom: 18, |
| 55 | attribution: 'Test' |
| 56 | }).addTo(map); |
| 57 | |
| 58 | var arrayOfLatLngs = []; |
| 59 | var mapData = {{ cdnData|safe }}; |
| 60 | log.debug( mapData ); |
| 61 | |
| 62 | for ( var key in mapData ) { |
| 63 | arrayOfLatLngs.push([mapData[key]['lat'],mapData[key]['long']]); |
| 64 | log.debug( arrayOfLatLngs ); |
| 65 | |
| 66 | mapData[key]['marker'] = L.marker([mapData[key]['lat'], mapData[key]['long']], {icon: getIcon(mapData[key]['numNodes'], mapData[key]['numHPCSlivers'], 0, mapData[key]['hot']) }); |
| 67 | mapData[key]['marker'].addTo(map).bindPopup(setPopupVals(key, mapData[key])); |
| 68 | |
| 69 | } |
| 70 | var bounds = new L.LatLngBounds(arrayOfLatLngs); |
| 71 | map.fitBounds(bounds); |
| 72 | |
| 73 | var popup = L.popup(); |
| 74 | |
| 75 | |
| 76 | function setPopupVals (site, siteData) { |
| 77 | var retVal = '<span class="SiteDetail"><b>' + site + '</b></span>' + |
| 78 | '</br><a href="' + siteData['siteUrl'] + '">' + siteData['siteUrl'] + '</a>' + |
| 79 | '</br><b>HPC Slivers: </b>' + siteData['numHPCSlivers'] + |
| 80 | '</br><b>Total Nodes: </b>' + siteData['numNodes'] + |
| 81 | // '</br><b>Hot: </b>' + Math.round(siteData['hot']*100) + |
| 82 | '</br><b>Measured Load: </b>' + siteData['load'] + '%' + |
| 83 | '<span id="addSlivers"></br><a href="#" id="addHPCSliver" data-site="' + site + '" data-availNodes="' + siteData['numNodes'] +'">Add HPC Slivers</a> </span>' + |
| 84 | '<span id="remSlivers"><a href="#" id="remHPCSliver" data-site="' + site + '">Remove HPC Slivers</a> </span>'; |
| 85 | |
| 86 | return retVal; |
| 87 | } |
| 88 | |
| 89 | $('#map-us').on('click', '#remHPCSliver', function() { |
| 90 | |
| 91 | $.ajax({ |
| 92 | url : '/dashboardaddorremsliver/', |
| 93 | dataType : 'json', |
| 94 | data: {site: $(this).data('site'), |
| 95 | actionToDo: "rem", |
| 96 | csrfmiddlewaretoken: "{{ csrf_token }}", // < here |
| 97 | state:"inactive" }, |
| 98 | type : 'POST', |
Scott Baker | d927d66 | 2014-05-22 09:29:06 -0700 | [diff] [blame^] | 99 | success:function(){ |
Scott Baker | 9416013 | 2014-05-18 18:49:20 -0700 | [diff] [blame] | 100 | confirmDialog("Info","Removed an HPC Sliver from Site "); |
| 101 | }, |
Scott Baker | d927d66 | 2014-05-22 09:29:06 -0700 | [diff] [blame^] | 102 | error:function (xhr, textStatus, thrownError){ |
| 103 | errorDialog("Error", textStatus + " " + xhr.responseText); |
| 104 | } |
Scott Baker | 9416013 | 2014-05-18 18:49:20 -0700 | [diff] [blame] | 105 | }); |
| 106 | }); |
| 107 | |
| 108 | $('#map-us').on('click', '#addHPCSliver', function() { |
| 109 | |
| 110 | $.ajax({ |
| 111 | url : '/dashboardaddorremsliver/', |
| 112 | dataType : 'json', |
| 113 | data: {site: $(this).data('site'), |
| 114 | actionToDo: "add", |
| 115 | csrfmiddlewaretoken: "{{ csrf_token }}", // < here |
| 116 | state:"inactive" }, |
| 117 | type : 'POST', |
| 118 | success: function(response) |
| 119 | { |
Scott Baker | 9416013 | 2014-05-18 18:49:20 -0700 | [diff] [blame] | 120 | confirmDialog("Info","Added an HPC Sliver to Site "); |
| 121 | }, |
Scott Baker | d927d66 | 2014-05-22 09:29:06 -0700 | [diff] [blame^] | 122 | error:function (xhr, textStatus, thrownError){ |
| 123 | errorDialog("Error", textStatus + " " + xhr.responseText); |
| 124 | } |
Scott Baker | 9416013 | 2014-05-18 18:49:20 -0700 | [diff] [blame] | 125 | }); |
Scott Baker | 9416013 | 2014-05-18 18:49:20 -0700 | [diff] [blame] | 126 | }); |
| 127 | |
| 128 | function getIcon(numNodes, numHPCSlivers, currentBW, hot) { |
| 129 | //var colorChoices = ["#007FFF", "#0000FF", "#7f00ff", "#FF00FF", "#FF007F", "#FF0000"]; |
| 130 | var colorChoices = ["#0000FF", "#00FFFF", "#00FF00", "#FFFF00", "#FF0000"]; |
| 131 | |
| 132 | var ratio = hot * 100; //(numHPCSlivers/numNodes) * 100; |
| 133 | var numColors = colorChoices.length; |
| 134 | var colorBands = 100/numColors; |
| 135 | |
| 136 | //Algorithm for color tone should consider the number of available nodes |
| 137 | // on the site, and then how much the current dedicated nodes are impacted |
| 138 | //var iconColor = 0; |
| 139 | var iconColor = colorChoices.length-1; |
| 140 | for (colorBand = 0; colorBand < numColors; colorBand ++) { |
| 141 | if (ratio < colorBands * colorBand+1) { |
| 142 | iconColor = colorBand |
| 143 | break; |
| 144 | } |
| 145 | } |
| 146 | |
| 147 | if (numHPCSlivers < 1) { |
| 148 | iconColor = "#7F7F7F"; |
| 149 | } else { |
| 150 | iconColor = colorChoices[iconColor]; |
| 151 | } |
| 152 | |
| 153 | var icon = L.MakiMarkers.icon({icon: "star-stroked", color: iconColor , size: "s"}); |
| 154 | return icon; |
| 155 | } |
| 156 | |
| 157 | function updateMaps() { |
| 158 | log.debug("Attempting to update Maps"); |
| 159 | $.ajax({ |
| 160 | url : '/hpcdashboard', |
| 161 | dataType : 'json', |
| 162 | type : 'GET', |
| 163 | success: function(newData) |
| 164 | { |
| 165 | log.debug("Successfully got data back..."); |
| 166 | log.debug(newData); |
| 167 | log.debug("Still have old data too"); |
| 168 | log.debug(mapData); |
| 169 | updateMapData(newData); |
| 170 | } |
| 171 | }); |
| 172 | setTimeout(updateMaps, 30000) |
| 173 | |
| 174 | } |
| 175 | |
| 176 | function updateMapData(newData) { |
| 177 | for ( site in newData ) { |
| 178 | var isNewSite = false; |
| 179 | //check to see if the site is new or not |
| 180 | if (site in mapData) { |
| 181 | log.debug("Site " + site + " already mapped"); |
| 182 | //take ownership of marker |
| 183 | newData[site]['marker'] = mapData[site]['marker']; |
| 184 | delete mapData[site]; |
| 185 | newData[site]['marker'].setIcon(getIcon(newData[site]['numNodes'], newData[site]['numHPCSlivers'], 0, newData[site]['hot'])); |
| 186 | // workaround, markers currently don't have a setPopup Content method -- so have to grab object directly |
| 187 | newData[site]['marker']._popup.setContent(setPopupVals(site, newData[site])); |
| 188 | } |
| 189 | else { |
| 190 | isNewSite = true; |
| 191 | log.debug("New Site detected: " + site); |
| 192 | newData[site]['marker'] = L.marker([newData[site]['lat'], newData[site]['long']], |
| 193 | {icon: getIcon(newData[site]['numNodes'], newData[site]['numHPCSlivers'], 0, newData[site]['hot']) }); |
| 194 | newData[site]['marker'].addTo(map).bindPopup(setPopupVals(site, newData[site])); //.openPopup(); |
| 195 | log.debug("Should have added the new site"); |
| 196 | |
| 197 | } |
| 198 | } |
| 199 | |
| 200 | // Anything still in data needs to be removed since it is no longer a valid site |
| 201 | for (remSite in mapData) { |
| 202 | log.warn("Site: " + remSite + " is no longer valid, removing from map"); |
| 203 | map.removeLayer(data[remSite]['marker']); |
| 204 | } |
| 205 | mapData = newData; |
| 206 | } |
| 207 | |
| 208 | function onMapClick(e) { |
| 209 | popup |
| 210 | .setLatLng(e.latlng) |
| 211 | .setContent("You clicked the map at " + e.latlng.toString()) |
| 212 | .openOn(map); |
| 213 | } |
| 214 | |
| 215 | setTimeout(updateMaps, 5000) |
| 216 | |
| 217 | // from stackexchange |
| 218 | function setInnerText (elementId, text) { |
| 219 | var element; |
| 220 | if (document.getElementById) { |
| 221 | element = document.getElementById(elementId); |
| 222 | } else if (document.all) { |
| 223 | element = document.all[elementId]; |
| 224 | } |
| 225 | if (element) { |
| 226 | if (typeof element.textContent != 'undefined') { |
| 227 | element.textContent = text; |
| 228 | } else if (typeof element.innerText != 'undefined') { |
| 229 | element.innerText = text; |
| 230 | } else if (typeof element.removeChild != 'undefined') { |
| 231 | while (element.hasChildNodes()) { |
| 232 | element.removeChild(element.lastChild); |
| 233 | } |
| 234 | element.appendChild(document.createTextNode(text)) ; |
| 235 | } |
| 236 | } |
| 237 | } |
| 238 | |
| 239 | function updateLabelData(summaryData) { |
| 240 | setInnerText("active-slivers-value", summaryData["total_slivers"]); |
| 241 | setInnerText("overall-throughput-value", (summaryData["total_bandwidth"]*8/1024/1024/1024).toFixed(2) + " Gbps"); |
| 242 | setInnerText("cpu-utilization-value", summaryData["average_cpu"] + "%"); |
| 243 | } |
| 244 | |
| 245 | function updateLabels() { |
| 246 | log.debug("Attempting to update Labels"); |
| 247 | $.ajax({ |
| 248 | url : '/hpcsummary', |
| 249 | dataType : 'json', |
| 250 | type : 'GET', |
| 251 | success: function(newData) |
| 252 | { |
| 253 | updateLabelData(newData); |
| 254 | } |
| 255 | }); |
| 256 | setTimeout(updateLabels, 30000) |
| 257 | |
| 258 | } |
| 259 | |
| 260 | setTimeout(updateLabels, 5000) |
| 261 | |
| 262 | |
| 263 | </script> |