Scott Baker | c7325a4 | 2014-05-30 16:06:46 -0700 | [diff] [blame] | 1 | from view_common import * |
Scott Baker | 7807158 | 2015-02-02 16:12:47 -0800 | [diff] [blame] | 2 | from planetstack_analytics import DoPlanetStackAnalytics, PlanetStackAnalytics, RED_LOAD, BLUE_LOAD |
| 3 | |
| 4 | def getCDNContentProviderData(): |
| 5 | cps = [] |
| 6 | for dm_cp in ContentProvider.objects.all(): |
| 7 | cp = {"name": dm_cp.name, |
| 8 | "account": dm_cp.account} |
| 9 | cps.append(cp) |
| 10 | |
| 11 | return cps |
| 12 | |
| 13 | def getCDNOperatorData(randomizeData = False, wait=True): |
| 14 | HPC_SLICE_NAME = "HyperCache" |
| 15 | |
| 16 | bq = PlanetStackAnalytics() |
| 17 | |
| 18 | rows = bq.get_cached_query_results(bq.compose_cached_query(), wait) |
| 19 | |
| 20 | # wait=False on the first time the Dashboard is opened. This means we might |
| 21 | # not have any rows yet. The dashboard code polls every 30 seconds, so it |
| 22 | # will eventually pick them up. |
| 23 | |
| 24 | if rows: |
| 25 | rows = bq.postprocess_results(rows, filter={"event": "hpc_heartbeat"}, maxi=["cpu"], count=["hostname"], computed=["bytes_sent/elapsed"], groupBy=["Time","site"], maxDeltaTime=80) |
| 26 | |
| 27 | # dictionaryize the statistics rows by site name |
| 28 | stats_rows = {} |
| 29 | for row in rows: |
| 30 | stats_rows[row["site"]] = row |
| 31 | else: |
| 32 | stats_rows = {} |
| 33 | |
| 34 | slice = Slice.objects.filter(name=HPC_SLICE_NAME) |
| 35 | if slice: |
| 36 | slice_slivers = list(slice[0].slivers.all()) |
| 37 | else: |
| 38 | slice_slivers = [] |
| 39 | |
| 40 | new_rows = {} |
| 41 | for site in Site.objects.all(): |
| 42 | # compute number of slivers allocated in the data model |
| 43 | allocated_slivers = 0 |
| 44 | for sliver in slice_slivers: |
| 45 | if sliver.node.site == site: |
| 46 | allocated_slivers = allocated_slivers + 1 |
| 47 | |
| 48 | stats_row = stats_rows.get(site.name,{}) |
| 49 | |
| 50 | max_cpu = stats_row.get("max_avg_cpu", stats_row.get("max_cpu",0)) |
| 51 | cpu=float(max_cpu)/100.0 |
| 52 | hotness = max(0.0, ((cpu*RED_LOAD) - BLUE_LOAD)/(RED_LOAD-BLUE_LOAD)) |
| 53 | |
| 54 | try: |
| 55 | lat=float(site.location.latitude) |
| 56 | long=float(site.location.longitude) |
| 57 | except: |
| 58 | lat=0 |
| 59 | long=0 |
| 60 | |
| 61 | # format it to what that CDN Operations View is expecting |
| 62 | new_row = {"lat": lat, |
| 63 | "long": long, |
| 64 | "health": 0, |
| 65 | #"numNodes": int(site.nodes.count()), |
| 66 | "activeHPCSlivers": int(stats_row.get("count_hostname", 0)), # measured number of slivers, from bigquery statistics |
| 67 | "numHPCSlivers": allocated_slivers, # allocated number of slivers, from data model |
| 68 | "siteUrl": str(site.site_url), |
| 69 | "bandwidth": stats_row.get("sum_computed_bytes_sent_div_elapsed",0), |
| 70 | "load": max_cpu, |
| 71 | "hot": float(hotness)} |
| 72 | new_rows[str(site.name)] = new_row |
| 73 | |
| 74 | # get rid of sites with 0 slivers that overlap other sites with >0 slivers |
| 75 | for (k,v) in new_rows.items(): |
| 76 | bad=False |
| 77 | if v["numHPCSlivers"]==0: |
| 78 | for v2 in new_rows.values(): |
| 79 | if (v!=v2) and (v2["numHPCSlivers"]>=0): |
| 80 | d = haversine(v["lat"],v["long"],v2["lat"],v2["long"]) |
| 81 | if d<100: |
| 82 | bad=True |
| 83 | if bad: |
| 84 | del new_rows[k] |
| 85 | |
| 86 | return new_rows |
Scott Baker | c7325a4 | 2014-05-30 16:06:46 -0700 | [diff] [blame] | 87 | |
| 88 | class DashboardSummaryAjaxView(View): |
Scott Baker | 3307ce6 | 2015-02-02 16:23:52 -0800 | [diff] [blame] | 89 | url=r'^hpcsummary/' |
| 90 | |
Scott Baker | c7325a4 | 2014-05-30 16:06:46 -0700 | [diff] [blame] | 91 | def get(self, request, **kwargs): |
| 92 | def avg(x): |
| 93 | if len(x)==0: |
| 94 | return 0 |
| 95 | return float(sum(x))/len(x) |
| 96 | |
| 97 | sites = getCDNOperatorData().values() |
| 98 | |
| 99 | sites = [site for site in sites if site["numHPCSlivers"]>0] |
| 100 | |
| 101 | total_slivers = sum( [site["numHPCSlivers"] for site in sites] ) |
| 102 | total_bandwidth = sum( [site["bandwidth"] for site in sites] ) |
| 103 | average_cpu = int(avg( [site["load"] for site in sites] )) |
| 104 | |
| 105 | result= {"total_slivers": total_slivers, |
| 106 | "total_bandwidth": total_bandwidth, |
| 107 | "average_cpu": average_cpu} |
| 108 | |
Scott Baker | 823b721 | 2014-06-16 10:25:39 -0700 | [diff] [blame] | 109 | return HttpResponse(json.dumps(result), content_type='application/javascript') |
Scott Baker | c7325a4 | 2014-05-30 16:06:46 -0700 | [diff] [blame] | 110 | |
| 111 | class DashboardAddOrRemoveSliverView(View): |
| 112 | # TODO: deprecate this view in favor of using TenantAddOrRemoveSliverView |
| 113 | |
Scott Baker | 3307ce6 | 2015-02-02 16:23:52 -0800 | [diff] [blame] | 114 | url=r'^dashboardaddorremsliver/$' |
| 115 | |
Scott Baker | c7325a4 | 2014-05-30 16:06:46 -0700 | [diff] [blame] | 116 | def post(self, request, *args, **kwargs): |
| 117 | siteName = request.POST.get("site", None) |
| 118 | actionToDo = request.POST.get("actionToDo", "0") |
| 119 | |
| 120 | siteList = [Site.objects.get(name=siteName)] |
| 121 | slice = Slice.objects.get(name="HyperCache") |
| 122 | |
| 123 | if request.user.isReadOnlyUser(): |
| 124 | return HttpResponseForbidden("User is in read-only mode") |
| 125 | |
| 126 | if (actionToDo == "add"): |
| 127 | user_ip = request.GET.get("ip", get_ip(request)) |
Scott Baker | 866c5b3 | 2014-08-29 11:34:00 -0700 | [diff] [blame] | 128 | slice_increase_slivers(request.user, user_ip, siteList, slice, image.objects.all()[0], 1) |
Scott Baker | c7325a4 | 2014-05-30 16:06:46 -0700 | [diff] [blame] | 129 | elif (actionToDo == "rem"): |
| 130 | slice_decrease_slivers(request.user, siteList, slice, 1) |
| 131 | |
| 132 | print '*' * 50 |
| 133 | print 'Ask for site: ' + siteName + ' to ' + actionToDo + ' another HPC Sliver' |
Scott Baker | 823b721 | 2014-06-16 10:25:39 -0700 | [diff] [blame] | 134 | return HttpResponse(json.dumps("Success"), content_type='application/javascript') |
Scott Baker | c7325a4 | 2014-05-30 16:06:46 -0700 | [diff] [blame] | 135 | |
| 136 | class DashboardAjaxView(View): |
Scott Baker | 3307ce6 | 2015-02-02 16:23:52 -0800 | [diff] [blame] | 137 | url = r'^hpcdashboard/' |
Scott Baker | c7325a4 | 2014-05-30 16:06:46 -0700 | [diff] [blame] | 138 | def get(self, request, **kwargs): |
Scott Baker | 823b721 | 2014-06-16 10:25:39 -0700 | [diff] [blame] | 139 | return HttpResponse(json.dumps(getCDNOperatorData(True)), content_type='application/javascript') |