Merge branch 'master' of ssh://git.planet-lab.org/git/plstackapi
authorScott Baker <smbaker@gmail.com>
Wed, 14 May 2014 01:02:21 +0000 (18:02 -0700)
committerScott Baker <smbaker@gmail.com>
Wed, 14 May 2014 01:02:21 +0000 (18:02 -0700)
planetstack/core/plus/views.py
planetstack/templates/admin/dashboard/cdn_nodes.html
planetstack/tests/GetConfiguration.py
planetstack/tests/generate_billing_sample.py

index bee590b..705f4f6 100644 (file)
@@ -243,7 +243,7 @@ def getCDNOperatorData(randomizeData = False, wait=True):
 
     bq = PlanetStackAnalytics()
 
-    rows = bq.get_cached_query_results(bq.compose_latest_query(groupByFields=["%hostname", "event", "%slice"]), wait)      # why did we need %slice ??
+    rows = bq.get_cached_query_results(bq.compose_cached_query(), wait)
 
     # wait=False on the first time the Dashboard is opened. This means we might
     # not have any rows yet. The dashboard code polls every 30 seconds, so it
index cea2f7e..8f4f45a 100644 (file)
@@ -72,8 +72,17 @@ function updateCDNNodeData(data) {
 }
 
 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';
+    var contentProvider = $("#cdn-node-data-slicename").val();
+
+    var filterPart = ""
+    if ((contentProvider!="") && (contentProvider!="all")) {
+         filterPart = "&cp=" + contentProvider
+    }
+
+    var url= '/analytics/bigquery/?event=hpc_heartbeat&sum=@bytes_sent,@bytes_hit,@healthy,@elapsed&computed=@bytes_sent/@elapsed&groupBy=@hostname&cached=hpc&cachedGroupBy=@hostname' + filterPart;
+
     console.log(url);
+
     $.ajax({
     url: url,
     dataType : 'json',
@@ -86,5 +95,14 @@ function updateCDNNodes() {
     setTimeout(updateCDNNodes, 30000);
 }
 
-setTimeout(updateCDNNodes, 5000);
+google.setOnLoadCallback(function () {
+    $('#cdn-node-data-slicename').change(function()
+    {
+        updateCDNNodes();
+    });
+
+    updateCDNNodes();
+});
+
+//setTimeout(updateCDNNodes, 5000);
 </script>
index b3193f4..55d2467 100644 (file)
@@ -10,6 +10,8 @@ os.environ.setdefault("DJANGO_SETTINGS_MODULE", "planetstack.settings")
 from openstack.manager import OpenStackManager
 from core.models import Slice, Sliver, ServiceClass, Reservation, Tag, Network, User, Node, Image, Deployment, Site, NetworkTemplate, NetworkSlice
 
+slice_name_map = {}
+
 def ps_id_to_pl_id(x):
     # Since we don't want the PlanetStack object IDs to conflict with existing
     # PlanetLab object IDs in the CMI, just add 100000 to the PlanetStack object
@@ -20,12 +22,15 @@ def pl_id_to_ps_id(x):
     return x - 100000
 
 def pl_slice_id(slice):
-    if slice.name == "princeton_vcoblitz":
+    if slice.name.startswith("princeton_vcoblitz"):
         # 70 is the slice id of princeton_vcoblitz on vicci
         return 70
     else:
         return ps_id_to_pl_id(slice.id)
 
+def ps_slicename_to_pl_slicename(x):
+    return slice_name_map.get(x,x)
+
 def filter_fields(src, fields):
     dest = {}
     for (key,value) in src.items():
@@ -51,7 +56,7 @@ def GetSlices(filter={}):
                  "slice_tag_ids": [],
                  "peer_id": None,
                  "site_id": ps_id_to_pl_id(ps_slice.site_id),
-                 "name": ps_slice.name}
+                 "name": ps_slicename_to_pl_slicename(ps_slice.name)}
 
                  # creator_person_id, person_ids, expires, created
 
@@ -159,6 +164,22 @@ def GetInterfaces(slicename, node_ids):
                 interfaces.append(interface)
     return interfaces
 
+def find_multi_slicename(orig_slicename):
+    """
+         Because we sometimes have issues deleting a slice in planetstack and
+         creating a new one, allow us to use a prefix match, that way someone
+         can put a version number of the end of the slicename
+    """
+    global slice_name_map
+    slices = Slice.objects.filter()
+    for slice in slices:
+        if slice.name.startswith(orig_slicename):
+            slice_name_map[slice.name] = orig_slicename
+            return slice.name
+
+    return orig_slicename
+
+
 def GetConfiguration(name):
     slicename = name["name"]
     if "node_id" in name:
@@ -166,6 +187,8 @@ def GetConfiguration(name):
     else:
         node_id = 0
 
+    slicename = find_multi_slicename(slicename)
+
     node_sliver_tags = GetTags(slicename, node_id)
 
     slices = GetSlices({"name": slicename})
@@ -215,11 +238,13 @@ def GetConfiguration(name):
             'nodes': nodes}
 
 if __name__ == '__main__':
+    find_multi_slicename("princeton_vcoblitz")  # set up the mapping for princeton_vcoblitz2 -> princeton_vcoblitz
+
     slices = GetSlices()
     nodes = GetNodes()
 
     if ("-d" in sys.argv):
-        config = GetConfiguration({"name": "princeton_coblitz"})
+        config = GetConfiguration({"name": "princeton_vcoblitz"})
         print config
         print slices
         print nodes
index 4fc1374..7fdfbdd 100644 (file)
@@ -1,8 +1,5 @@
 """
-    Basic Sliver Test
-
-    1) Create a slice1
-    2) Create sliver1 on slice1
+    Generates billing sample data
 """
 
 import datetime
@@ -14,6 +11,10 @@ import random
 import sys
 import time
 
+# The granularity at which the charge collection system collects charges. Once
+# per hour makes for a very slow UI, so I upped it to once per 8 hours.
+CHARGE_HOURS = 8
+
 MINUTE_SECONDS = 60
 HOUR_SECONDS = MINUTE_SECONDS * 60
 DAY_SECONDS = HOUR_SECONDS * 24
@@ -86,34 +87,42 @@ def generate_payments(account):
              payment = Payment(account=account, amount=invoice.amount, date=payment_time)
              payment.save()
 
+print "deleting old stuff"
+
 delete_all(Invoice)
 delete_all(Charge)
 delete_all(Payment)
 delete_all(Account)
 delete_all(UsableObject)
 
+print "creating accounts"
+
 for site in Site.objects.all():
     # only create accounts for sites where some slices exist
     if len(site.slices.all()) > 0:
         account = Account(site=site)
         account.save()
 
+print "generating charges"
+
 for slice in Slice.objects.all():
     site = slice.site
     account = site.accounts.all()[0]
     serviceClass =slice.serviceClass
 
-    if not (slice.name in ["DnsRedir", "DnsDemux", "HyperCache"]):
+    if not (slice.name in ["DnsRedir", "DnsDemux", "HyperCache", "Hadoop", "Owl", "Stork", "Syndicate", "test-slice-1", "test-slice-2", "test", "test2"]):
         continue
 
+    print "   generating charges for", slice.name
+
     now = int(time.time())/HOUR_SECONDS*HOUR_SECONDS
 
     charge_kind=None
     for resource in slice.serviceClass.resources.all():
-        if resource.name == "cpu.cores":
+        if resource.name == "numberCores":
             charge_kind = "reservation"
             cost = resource.cost
-        elif (resource.name == "cycles") or (resource.name == "Cycles"):
+        elif (charge_kind==None) and (resource.name == "cycles") or (resource.name == "Cycles"):
             charge_kind = "besteffort"
             cost = resource.cost
 
@@ -121,15 +130,17 @@ for slice in Slice.objects.all():
         print "failed to find resource for", slice.serviceClass
         continue
 
-    for sliver in slice.slivers.all():
+    for sliver in slice.slivers.all()[:4]:    # only do up to 4 slivers; it's way too much data otherwise
         hostname = sliver.node.name
-        for i in range(now-MONTH_SECONDS, now, HOUR_SECONDS):
+        for i in range(now-MONTH_SECONDS, now, CHARGE_HOURS*HOUR_SECONDS):
             if charge_kind == "besteffort":
-                core_hours = random.randint(1,60)/100.0
+                core_hours = random.randint(20,60)/100.0
             else:
                 core_hours = 1
 
-            amount = core_hours * cost
+            core_hours = core_hours * CHARGE_HOURS
+
+            amount = float(core_hours * cost) / 100.0
 
             object = get_usable_object(hostname)
 
@@ -138,6 +149,8 @@ for slice in Slice.objects.all():
             charge = Charge(account=account, slice=slice, kind=charge_kind, state="pending", date=date, object=object, coreHours=core_hours, amount=amount)
             charge.save()
 
+print "doing invoices and payments"
+
 for account in Account.objects.all():
     generate_invoices(account)
     generate_payments(account)