Merge branch 'master' of ssh://git.planet-lab.org/git/plstackapi
diff --git a/planetstack/hpc_wizard/bigquery_analytics.py b/planetstack/hpc_wizard/bigquery_analytics.py
index dafb55c..4e375df 100644
--- a/planetstack/hpc_wizard/bigquery_analytics.py
+++ b/planetstack/hpc_wizard/bigquery_analytics.py
@@ -204,6 +204,7 @@
         avg = [x.replace("%","") for x in avg]
         computed = [x.replace("%","") for x in computed]
         maxi = [x.replace("%","") for x in maxi]
+        groupBy = [x.replace("%","") for x in groupBy]
 
         for (k,v) in filter.items():
             rows = self.filter_results(rows, k, v)
diff --git a/planetstack/hpc_wizard/planetstack_analytics.py b/planetstack/hpc_wizard/planetstack_analytics.py
index c0f7ff5..91e4ce1 100644
--- a/planetstack/hpc_wizard/planetstack_analytics.py
+++ b/planetstack/hpc_wizard/planetstack_analytics.py
@@ -247,7 +247,7 @@
         """
 
         if not fieldNames:
-            fieldNames = ["%hostname", "%bytes_sent", "time", "event", "%site", "%elapsed", "%slice", "%cpu"]
+            fieldNames = ["%hostname", "%bytes_sent", "%bytes_hit", "%healthy", "time", "event", "%site", "%elapsed", "%slice", "%cpu"]
 
         fields = ["table1.%s AS %s" % (x,x) for x in fieldNames]
         fields = ", ".join(fields)
@@ -310,6 +310,7 @@
         maxAge = int(req.GET.get("maxAge", 60*60))
 
         cached = req.GET.get("cached", None)
+        cachedGroupBy = self.get_list_from_req(req, "cachedGroupBy", ["doesnotexist"])
 
         q = self.compose_query(slice, site, node, service, event, timeBucket, avg, sum, count, computed, [], groupBy, orderBy, maxAge=maxAge)
 
@@ -386,7 +387,7 @@
                 if event:
                     filter["event"] = event
 
-                result = self.postprocess_results(results, filter=filter, sum=sum, count=count, avg=avg, computed=computed, maxDeltaTime=120, groupBy=["doesnotexist"])
+                result = self.postprocess_results(results, filter=filter, sum=sum, count=count, avg=avg, computed=computed, maxDeltaTime=120, groupBy=cachedGroupBy)
             else:
                 result = self.run_query(q)
 
diff --git a/planetstack/templates/admin/dashboard/cdn_nodes.html b/planetstack/templates/admin/dashboard/cdn_nodes.html
new file mode 100644
index 0000000..9de39ff
--- /dev/null
+++ b/planetstack/templates/admin/dashboard/cdn_nodes.html
@@ -0,0 +1,81 @@
+<div id="tabs-6">
+</div>
+
+<script>
+
+function domain_name_sort(a,b) {
+        parts_a = a.split(".");
+        parts_b = b.split(".");
+        parts_a = parts_a.reverse();
+        parts_b = parts_b.reverse();
+        a = parts_a.join(".");
+        b = parts_b.join(".");
+	return ((a < b) ? -1 : ((a > b) ?  1 : 0));
+}
+
+jQuery.fn.dataTableExt.oSort['domain-name-asc']  = function(a,b) {
+    return domain_name_sort(a,b);
+};
+
+jQuery.fn.dataTableExt.oSort['domain-name-desc']  = function(a,b) {
+    retuirn -domain_name_sort(a,b);
+};
+
+function updateCDNNodeData(data) {
+    $('#tabs-6').html( '<table cellpadding="0" cellspacing="0" border="0" class="display" id="dynamic_cdn_nodes"></table>' );
+    var actualEntries = [];
+
+    var rows = data.rows;
+    for (row in rows) {
+        hostname = rows[row]['hostname'];
+        bytes_sent = rows[row]['sum_bytes_sent'];
+        bytes_hit = rows[row]['sum_bytes_hit'];
+        elapsed = rows[row]['sum_elapsed'];
+        healthy = rows[row]['sum_healthy'];
+
+        if (bytes_sent > 0) {
+            hit_ratio = parseInt( bytes_hit * 100.0 / bytes_sent );
+        } else {
+            hit_ratio = 0;
+        }
+
+        Mbps = parseInt(rows[row]['sum_computed_bytes_sent_div_elapsed'] * 8.0 / 1024.0 / 1024.0);
+
+        if (healthy>0) {
+            healthyStr = "ok";
+        } else {
+            healthyStr = "bad";
+        }
+
+        actualEntries.push([hostname, healthyStr, Mbps, hit_ratio]);
+    }
+    oTable = $('#dynamic_cdn_nodes').dataTable( {
+        "bJQueryUI": true,
+        "aaData":  actualEntries,
+        "bStateSave": true,
+        "aoColumns": [
+            { "sTitle": "Hostname", sType: "domain-name" },
+            { "sTitle": "Healthy" },
+            { "sTitle": "Mbps" , sClass: "alignCenter"},
+            { "sTitle": "Hit Ratio" , sClass: "alignCenter"},
+        ],
+    } );
+}
+
+function updateCDNNodes() {
+    var url= '/analytics/bigquery/?event=hpc_heartbeat&sum=@bytes_sent,@bytes_hit,@healthy,@elapsed&computed=@bytes_sent/@elapsed&groupBy=@hostname&cached=1&cachedGroupBy=@hostname';
+    console.log(url);
+    $.ajax({
+    url: url,
+    dataType : 'json',
+    type : 'GET',
+    success: function(newData)
+    {
+        updateCDNNodeData(newData);
+    }
+});
+    setTimeout(updateCDNNodes, 30000);
+}
+
+setTimeout(updateCDNNodes, 5000);
+</script>