fix for tenant view
[plstackapi.git] / planetstack / core / plus / views.py
1 #views.py
2 import functools
3 import math
4 import os
5 import sys
6 from django.views.generic import TemplateView, View
7 import datetime
8 from pprint import pprint
9 import json
10 from syndicate.models import *
11 from core.models import *
12 from hpc.models import ContentProvider
13 from operator import attrgetter
14 from django import template
15 from django.views.decorators.csrf import csrf_exempt
16 from django.http import HttpResponse, HttpResponseServerError
17 from django.core import urlresolvers
18 from django.contrib.gis.geoip import GeoIP
19 from ipware.ip import get_ip
20 import traceback
21 import socket
22
23 BLESSED_SITES = ["Stanford", "Washington", "Princeton", "GeorgiaTech", "MaxPlanck"]
24
25 if os.path.exists("/home/smbaker/projects/vicci/cdn/bigquery"):
26     sys.path.append("/home/smbaker/projects/vicci/cdn/bigquery")
27 else:
28     sys.path.append("/opt/planetstack/hpc_wizard")
29 import hpc_wizard
30 from planetstack_analytics import DoPlanetStackAnalytics, PlanetStackAnalytics, RED_LOAD, BLUE_LOAD
31
32 class DashboardWelcomeView(TemplateView):
33     template_name = 'admin/dashboard/welcome.html'
34
35     def get(self, request, *args, **kwargs):
36         context = self.get_context_data(**kwargs)
37         userDetails = getUserSliceInfo(request.user)
38         #context['site'] = userDetails['site']
39
40         context['userSliceInfo'] = userDetails['userSliceInfo']
41         context['cdnData'] = userDetails['cdnData']
42         context['cdnContentProviders'] = userDetails['cdnContentProviders']
43         return self.render_to_response(context=context)
44
45 class DashboardView(TemplateView):
46     head_template = r"""{% extends "admin/dashboard/dashboard_base.html" %}
47        {% load admin_static %}
48        {% block content %}
49     """
50
51     tail_template = r"{% endblock %}"
52
53     def get(self, request, name="hpc_historical", *args, **kwargs):
54         context = self.get_context_data(**kwargs)
55
56         head_template = self.head_template
57         tail_template = self.tail_template
58
59         if (name=="tenant"):
60             # quick fix for tenant view
61             head_template = head_template + '<div id="tabs-5"></div>'
62
63
64         t = template.Template(head_template + open("/opt/planetstack/templates/admin/dashboard/%s.html" % name, "r").read() + self.tail_template)
65
66         userDetails = getUserSliceInfo(request.user)
67         #context['site'] = userDetails['site']
68
69         context['userSliceInfo'] = userDetails['userSliceInfo']
70         context['cdnData'] = userDetails['cdnData']
71         context['cdnContentProviders'] = userDetails['cdnContentProviders']
72
73         response_kwargs = {}
74         response_kwargs.setdefault('content_type', self.content_type)
75         return self.response_class(\r
76             request = request,\r
77             template = t,\r
78             context = context,\r
79             **response_kwargs)
80
81 def getUserSliceInfo(user, tableFormat = False):
82         userDetails = {}
83
84         userSliceData = getSliceInfo(user)
85         if (tableFormat):
86 #            pprint("*******      GET USER SLICE INFO")
87             userDetails['userSliceInfo'] = userSliceTableFormatter(userSliceData)
88         else:
89             userDetails['userSliceInfo'] = userSliceData
90         userDetails['cdnData'] = getCDNOperatorData(wait=False)
91         userDetails['cdnContentProviders'] = getCDNContentProviderData()
92         return userDetails
93
94 class TenantCreateSlice(View):
95     def post(self, request, *args, **kwargs):
96         sliceName = request.POST.get("sliceName", "0")
97         serviceClass = request.POST.get("serviceClass", "0")
98         imageName = request.POST.get("imageName", "0")
99         actionToDo = request.POST.get("actionToDo", "0")
100         #network = request.POST.get("network","0")
101         mountDataSets = request.POST.get("mountDataSets","0")
102         if (actionToDo == "add"):
103            serviceClass = ServiceClass.objects.get(name=serviceClass)
104            site = request.user.site
105            image = Image.objects.get(name=imageName)
106            newSlice = Slice(name=sliceName,serviceClass=serviceClass,site=site,imagePreference=image,mountDataSets=mountDataSets)
107            newSlice.save()
108         return HttpResponse("Slice created")
109
110 class TenantUpdateSlice(View):
111     def post(self, request, *args, **kwargs):\r
112         sliceName = request.POST.get("sliceName", "0")\r
113         serviceClass = request.POST.get("serviceClass", "0")\r
114         imageName = request.POST.get("imageName", "0")\r
115         actionToDo = request.POST.get("actionToDo", "0")\r
116         #network = request.POST.get("network","0")\r
117         dataSet = request.POST.get("dataSet","0")\r
118         slice = Slice.objects.all()\r
119         for entry in slice:\r
120                 serviceClass = ServiceClass.objects.get(name=serviceClass)\r
121                 if(entry.name==sliceName):\r
122                          if (actionToDo == "update"):\r
123                                 setattr(entry,'serviceClass',serviceClass)\r
124                                 setattr(entry,'imagePreference',imageName)\r
125                                 #setattr(entry,'network',network)\r
126                                 setattr(entry,'mountDataSets',dataSet)\r
127                                 entry.save()\r
128                                 break\r
129         return HttpResponse("Slice updated")\r
130 \r
131 def getTenantSliceInfo(user, tableFormat = False):
132     tenantSliceDetails = {}
133     tenantSliceData = getTenantInfo(user)
134     tenantServiceClassData = getServiceClassInfo(user)
135     if (tableFormat):
136        tenantSliceDetails['userSliceInfo'] = userSliceTableFormatter(tenantSliceData)
137        tenantSliceDetails['sliceServiceClass']=userSliceTableFormatter(tenantServiceClassData)
138     else:
139        tenantSliceDetails['userSliceInfo'] = tenantSliceData
140     tenantSliceDetails['sliceServiceClass']=userSliceTableFormatter(tenantServiceClassData)
141     tenantSliceDetails['image']=userSliceTableFormatter(getImageInfo(user))
142     #tenantSliceDetails['network']=userSliceTableFormatter(getNetworkInfo(user))
143     tenantSliceDetails['deploymentSites']=userSliceTableFormatter(getDeploymentSites())
144     tenantSliceDetails['sites'] = userSliceTableFormatter(getTenantSitesInfo())
145     tenantSliceDetails['mountDataSets'] = userSliceTableFormatter(getMountDataSets())
146     tenantSliceDetails['publicKey'] = getPublicKey(user)
147     return tenantSliceDetails
148
149 def getTenantInfo(user):
150     slices =Slice.objects.all()
151     userSliceInfo = []
152     for entry in slices:
153        sliceName = Slice.objects.get(id=entry.id).name
154        slice = Slice.objects.get(name=Slice.objects.get(id=entry.id).name)
155        sliceServiceClass = entry.serviceClass.name
156        preferredImage =  entry.imagePreference
157        sliceDataSet = entry.mountDataSets
158        #sliceNetwork = entry.network
159        numSliver = 0
160        sliceImage=""
161        sliceSite = {}
162        sliceNode = {}
163        sliceInstance= {}
164        for sliver in slice.slivers.all():
165             if sliver.node.site.name in BLESSED_SITES:
166                 sliceSite[sliver.node.site.name] = sliceSite.get(sliver.node.site.name,0) + 1
167                 sliceImage = sliver.image.name
168                 sliceNode[str(sliver)] = sliver.node.name
169        numSliver = sum(sliceSite.values())
170        numSites = len(sliceSite)
171        userSliceInfo.append({'sliceName': sliceName,'sliceServiceClass': sliceServiceClass,'preferredImage':preferredImage,'numOfSites':numSites, 'sliceSite':sliceSite,'sliceImage':sliceImage,'numOfSlivers':numSliver,'sliceDataSet':sliceDataSet,'instanceNodePair':sliceNode})
172     return userSliceInfo
173
174 def getTenantSitesInfo():
175         tenantSiteInfo=[]
176         for entry in Site.objects.all():
177             if entry.name in BLESSED_SITES:
178                  tenantSiteInfo.append({'siteName':entry.name})
179         return tenantSiteInfo
180
181 def userSliceTableFormatter(data):
182 #    pprint(data)
183     formattedData = {
184                      'rows' : data
185                     }
186     return formattedData
187
188 def getPublicKey(user):
189         users=User.objects.all()\r
190         for key in users:\r
191                 if (str(key.email)==str(user)):\r
192                         sshKey = key.public_key\r
193         return sshKey
194
195 def getServiceClassInfo(user):
196     serviceClassList = ServiceClass.objects.all()
197     sliceInfo = []
198     for entry in serviceClassList:
199           sliceInfo.append({'serviceClass':entry.name})
200     return sliceInfo
201
202 def getImageInfo(user):
203     imageList = Image.objects.all()
204     #imageList = ['Fedora 16 LXC rev 1.3','Hadoop','MPI']
205     imageInfo = []
206     for imageEntry in imageList:
207           imageInfo.append({'Image':imageEntry.name})
208           #imageInfo.append({'Image':imageEntry})
209     return imageInfo
210
211 def createPrivateVolume(user, sliceName):
212     caps = Volume.CAP_READ_DATA | Volume.CAP_WRITE_DATA | Volume.CAP_HOST_DATA
213     getattr(Volume.default_gateway_caps,"read data") | \
214            getattr(Volume.default_gateway_caps,"write data") | \
215            getattr(Volume.default_gateway_caps,"host files")
216     v = Volume(name="private_" + sliceName, owner_id=user, description="private volume for %s" % sliceName, blocksize=61440, private=True, archive=False, default_gateway_caps = caps)
217     v.save()
218
219 SYNDICATE_REPLICATE_PORTNUM = 1025
220
221 def get_free_port():
222     inuse={}
223     inuse[SYNDICATE_REPLICATE_PORTNUM] = True
224     for vs in VolumeSlice.objects.all():
225         inuse[vs.peer_portnum]=True
226         inuse[vs.replicate_portnum]=True
227     for network in Network.objects.all():
228         network_ports = [x.strip() for x in network.ports.split(",")]
229         for network_port in network_ports:
230             try:
231                 inuse[int(network_port)] = True
232             except:
233                 # in case someone has put a malformed port number in the list
234                 pass
235     for i in range(1025, 65535):
236         if not inuse.get(i,False):
237             return i
238     return False
239
240 def mountVolume(sliceName, volumeName, readWrite):
241     slice = Slice.objects.get(name=sliceName)
242     volume = Volume.objects.get(name=volumeName)
243     # choose some unused port numbers
244     flags = Volume.CAP_READ_DATA
245     if readWrite:
246         flags = flags | Volume.CAP_WRITE_DATA
247     vs = VolumeSlice(volume_id = volume, slice_id = slice, gateway_caps=flags, peer_portnum = get_free_port(), replicate_portnum = SYNDICATE_REPLICATE_PORTNUM)
248     vs.save()
249
250 def hasPrivateVolume(sliceName):
251      slice = Slice.objects.get(name=sliceName)
252      for vs in VolumeSlice.objects.filter(slice_id=slice):
253          if vs.volume_id.private:
254              return True
255      return False
256
257 def getMountDataSets():
258         dataSetInfo=[]\r
259         for volume in Volume.objects.all():\r
260             if not volume.private:\r
261                 dataSetInfo.append({'DataSet': volume.name})\r
262 \r
263         return dataSetInfo
264
265 def getNetworkInfo(user):
266    #networkList = Network.objects.all()
267     networkList = ['Private Only','Private and Publicly Routable']
268     networkInfo = []
269     for networkEntry in networkList:
270           #networkInfo.append({'Network':networkEntry.name})
271           networkInfo.append({'Network':networkEntry})
272     return networkInfo
273
274 def getDeploymentSites():
275     deploymentList = Deployment.objects.all()
276     deploymentInfo = []
277     for entry in deploymentList:
278         deploymentInfo.append({'DeploymentSite':entry.name})
279     return deploymentInfo
280
281 def getSliceInfo(user):
282     sliceList = Slice.objects.all()
283     slicePrivs = SlicePrivilege.objects.filter(user=user)
284     userSliceInfo = []
285     for entry in slicePrivs:
286
287         slicename = Slice.objects.get(id=entry.slice.id).name
288         slice = Slice.objects.get(name=Slice.objects.get(id=entry.slice.id).name)
289         sliverList=Sliver.objects.all()
290         sites_used = {}
291         for sliver in slice.slivers.all():
292              #sites_used['deploymentSites'] = sliver.node.deployment.name
293              # sites_used[sliver.image.name] = sliver.image.name
294              sites_used[sliver.node.site.name] = sliver.numberCores
295         sliceid = Slice.objects.get(id=entry.slice.id).id
296         try:
297             sliverList = Sliver.objects.filter(slice=entry.slice.id)
298             siteList = {}
299             for x in sliverList:
300                if x.node.site not in siteList:
301                   siteList[x.node.site] = 1
302             slivercount = len(sliverList)
303             sitecount = len(siteList)
304         except:
305             traceback.print_exc()
306             slivercount = 0
307             sitecount = 0
308
309         userSliceInfo.append({'slicename': slicename, 'sliceid':sliceid,
310                               'sitesUsed':sites_used,
311                               'role': SliceRole.objects.get(id=entry.role.id).role,
312                               'slivercount': slivercount,
313                               'sitecount':sitecount})
314
315     return userSliceInfo
316
317 def getCDNContentProviderData():
318     cps = []
319     for dm_cp in ContentProvider.objects.all():
320         cp = {"name": dm_cp.name,
321               "account": dm_cp.account}
322         cps.append(cp)
323
324     return cps
325
326 def getCDNOperatorData(randomizeData = False, wait=True):
327     HPC_SLICE_NAME = "HyperCache"
328
329     bq = PlanetStackAnalytics()
330
331     rows = bq.get_cached_query_results(bq.compose_cached_query(), wait)
332
333     # wait=False on the first time the Dashboard is opened. This means we might
334     # not have any rows yet. The dashboard code polls every 30 seconds, so it
335     # will eventually pick them up.
336
337     if rows:
338         rows = bq.postprocess_results(rows, filter={"event": "hpc_heartbeat"}, maxi=["cpu"], count=["hostname"], computed=["bytes_sent/elapsed"], groupBy=["Time","site"], maxDeltaTime=80)
339
340         # dictionaryize the statistics rows by site name
341         stats_rows = {}
342         for row in rows:
343             stats_rows[row["site"]] = row
344     else:
345         stats_rows = {}
346
347     slice = Slice.objects.filter(name=HPC_SLICE_NAME)
348     if slice:
349         slice_slivers = list(slice[0].slivers.all())
350     else:
351         slice_slivers = []
352
353     new_rows = {}
354     for site in Site.objects.all():
355         # compute number of slivers allocated in the data model
356         allocated_slivers = 0
357         for sliver in slice_slivers:
358             if sliver.node.site == site:
359                 allocated_slivers = allocated_slivers + 1
360
361         stats_row = stats_rows.get(site.name,{})
362
363         max_cpu = stats_row.get("max_avg_cpu", stats_row.get("max_cpu",0))
364         cpu=float(max_cpu)/100.0
365         hotness = max(0.0, ((cpu*RED_LOAD) - BLUE_LOAD)/(RED_LOAD-BLUE_LOAD))
366
367         # format it to what that CDN Operations View is expecting
368         new_row = {"lat": float(site.location.longitude),
369                "long": float(site.location.longitude),
370                "lat": float(site.location.latitude),
371                "health": 0,
372                "numNodes": int(site.nodes.count()),
373                "activeHPCSlivers": int(stats_row.get("count_hostname", 0)),     # measured number of slivers, from bigquery statistics
374                "numHPCSlivers": allocated_slivers,                              # allocated number of slivers, from data model
375                "siteUrl": str(site.site_url),
376                "bandwidth": stats_row.get("sum_computed_bytes_sent_div_elapsed",0),
377                "load": max_cpu,
378                "hot": float(hotness)}
379         new_rows[str(site.name)] = new_row
380
381     # get rid of sites with 0 slivers that overlap other sites with >0 slivers
382     for (k,v) in new_rows.items():
383         bad=False
384         if v["numHPCSlivers"]==0:
385             for v2 in new_rows.values():
386                 if (v!=v2) and (v2["numHPCSlivers"]>=0):
387                     d = haversine(v["lat"],v["long"],v2["lat"],v2["long"])
388                     if d<100:
389                          bad=True
390             if bad:
391                 del new_rows[k]
392
393     return new_rows
394
395 def getPageSummary(request):
396     slice = request.GET.get('slice', None)
397     site = request.GET.get('site', None)
398     node = request.GET.get('node', None)
399
400 class SimulatorView(View):
401     def get(self, request, **kwargs):
402         sim = json.loads(file("/tmp/simulator.json","r").read())
403         text = "<html><head></head><body>"
404         text += "Iteration: %d<br>" % sim["iteration"]
405         text += "Elapsed since report %d<br><br>" % sim["elapsed_since_report"]
406         text += "<table border=1>"
407         text += "<tr><th>site</th><th>trend</th><th>weight</th><th>bytes_sent</th><th>hot</th></tr>"
408         for site in sim["site_load"].values():
409             text += "<tr>"
410             text += "<td>%s</td><td>%0.2f</td><td>%0.2f</td><td>%d</td><td>%0.2f</td>" % \
411                         (site["name"], site["trend"], site["weight"], site["bytes_sent"], site["load_frac"])
412             text += "</tr>"
413         text += "</table>"
414         text += "</body></html>"
415         return HttpResponse(text)
416
417 class DashboardUserSiteView(View):
418     def get(self, request, **kwargs):
419         return HttpResponse(json.dumps(getUserSliceInfo(request.user, True)), mimetype='application/javascript')
420
421 class TenantViewData(View):
422     def get(self, request, **kwargs):
423         return HttpResponse(json.dumps(getTenantSliceInfo(request.user, True)), mimetype='application/javascript')
424
425 def haversine(site_lat, site_lon, lat, lon):
426     d=0
427     if lat and lon and site_lat and site_lon:
428         site_lat = float(site_lat)
429         site_lon = float(site_lon)
430         lat = float(lat)
431         lon = float(lon)
432         R = 6378.1
433         a = math.sin( math.radians((lat - site_lat)/2.0) )**2 + math.cos( math.radians(lat) )*math.cos( math.radians(site_lat) )*(math.sin( math.radians((lon - site_lon)/2.0 ) )**2)
434         c = 2 * math.atan2( math.sqrt(a), math.sqrt(1 - a) )
435         d = R * c
436
437     return d
438
439 def siteSortKey(site, slice=None, count=None, lat=None, lon=None):
440     # try to pick a site we're already using
441     has_slivers_here=False
442     if slice:
443         for sliver in slice.slivers.all():
444             if sliver.node.site.name == site.name:
445                 has_slivers_here=True
446
447     # Haversine method
448     d = haversine(site.location.latitude, site.location.longitude, lat, lon)
449
450     return (-has_slivers_here, d)
451
452 def tenant_pick_sites(user, user_ip=None, slice=None, count=None):
453     """ Returns list of sites, sorted from most favorable to least favorable """
454     lat=None
455     lon=None
456     try:
457         client_geo = GeoIP().city(user_ip)
458         if client_geo:
459             lat=float(client_geo["latitude"])
460             lon=float(client_geo["longitude"])
461     except:
462         print "exception in geo code"
463         traceback.print_exc()
464
465     sites = Site.objects.all()
466     sites = [x for x in sites if x.name in BLESSED_SITES]
467     sites = sorted(sites, key=functools.partial(siteSortKey, slice=slice, count=count, lat=lat, lon=lon))
468
469     return sites
470
471 def slice_increase_slivers(user, user_ip, siteList, slice, count, noAct=False):
472     sitesChanged = {}
473
474     # let's compute how many slivers are in use in each node of each site
475     for site in siteList:
476         site.nodeList = list(site.nodes.all())
477         for node in site.nodeList:
478             node.sliverCount = 0
479             for sliver in node.slivers.all():
480                  if sliver.slice.id == slice.id:
481                      node.sliverCount = node.sliverCount + 1
482
483     # Allocate slivers to nodes
484     # for now, assume we want to allocate all slivers from the same site
485     nodes = siteList[0].nodeList
486     while (count>0):
487         # Sort the node list by number of slivers per node, then pick the
488         # node with the least number of slivers.
489         nodes = sorted(nodes, key=attrgetter("sliverCount"))
490         node = nodes[0]
491
492         print "adding sliver at node", node.name, "of site", node.site.name
493
494         if not noAct:
495             sliver = Sliver(name=node.name,
496                         slice=slice,
497                         node=node,
498                         image = Image.objects.all()[0],
499                         creator = User.objects.get(email=user),
500                         deploymentNetwork=node.deployment,
501                         numberCores =1 )
502             sliver.save()
503
504         node.sliverCount = node.sliverCount + 1
505
506         count = count - 1
507
508         sitesChanged[node.site.name] = sitesChanged.get(node.site.name,0) + 1
509
510     return sitesChanged
511
512 def slice_decrease_slivers(user, siteList, slice, count, noAct=False):
513     sitesChanged = {}
514     sliverList ={}
515     if siteList:
516         siteNames = [site.name for site in siteList]
517     else:
518         siteNames = None
519
520     for sliver in slice.slivers.all():
521         if(not siteNames) or (sliver.node.site.name in siteNames):\r
522                 node = sliver.node\r
523                 sliverList[sliver.name]=node.name
524
525     for key in sliverList:
526         if count>0:
527             sliver = Sliver.objects.filter(name=key)[0]\r
528             sliver.delete()\r
529             print "deleting sliver",sliverList[key],"at node",sliver.node.name\r
530             count=count-1\r
531             sitesChanged[sliver.node.site.name] = sitesChanged.get(sliver.node.site.name,0) - 1\r
532 \r
533     return sitesChanged
534
535 class TenantDeleteSliceView(View):
536         def post(self,request):\r
537                 sliceName = request.POST.get("sliceName",None)\r
538                 slice = Slice.objects.get(name=sliceName)\r
539                 #print slice, slice.id\r
540                 sliceToDel=Slice(name=sliceName, id=slice.id)\r
541                 sliceToDel.delete()
542                 return HttpResponse("Slice deleted")
543
544 class TenantAddOrRemoveSliverView(View):
545     """ Add or remove slivers from a Slice
546
547         Arguments:
548             siteName - name of site. If not specified, PlanetStack will pick the
549                        best site.,
550             actionToDo - [add | rem]
551             count - number of slivers to add or remove
552             sliceName - name of slice
553             noAct - if set, no changes will be made to db, but result will still
554                     show which sites would have been modified.
555
556         Returns:
557             Dictionary of sites that were modified, and the count of nodes
558             that were added or removed at each site.
559     """
560     def post(self, request, *args, **kwargs):
561         siteName = request.POST.get("siteName", None)
562         actionToDo = request.POST.get("actionToDo", None)
563         count = int(request.POST.get("count","0"))
564         sliceName = request.POST.get("slice", None)
565         noAct = request.POST.get("noAct", False)
566
567         if not sliceName:
568             return HttpResponseServerError("No slice name given")
569
570         slice = Slice.objects.get(name=sliceName)
571
572         if siteName:
573             siteList = [Site.objects.get(name=siteName)]
574         else:
575             siteList = None
576
577         if (actionToDo == "add"):
578             user_ip = request.GET.get("ip", get_ip(request))
579             if (siteList is None):
580                 siteList = tenant_pick_sites(user, user_ip, slice, count)
581
582             sitesChanged = slice_increase_slivers(request.user, user_ip, siteList, slice, count, noAct)
583         elif (actionToDo == "rem"):
584             sitesChanged = slice_decrease_slivers(request.user, siteList, slice, count, noAct)
585         else:
586             return HttpResponseServerError("Unknown actionToDo %s" % actionToDo)
587
588         return HttpResponse(json.dumps(sitesChanged), mimetype='application/javascript')
589
590     def get(self, request, *args, **kwargs):
591         request.POST = request.GET
592         return self.post(request, *args, **kwargs)  # for testing REST in browser
593         #return HttpResponseServerError("GET is not supported")
594
595 class TenantPickSitesView(View):
596     """ primarily just for testing purposes """
597     def get(self, request, *args, **kwargs):
598         count = request.GET.get("count","0")
599         slice = request.GET.get("slice",None)
600         if slice:
601             slice = Slice.objects.get(name=slice)
602         ip = request.GET.get("ip", get_ip(request))
603         sites = tenant_pick_sites(request.user, user_ip=ip, count=0, slice=slice)
604         sites = [x.name for x in sites]
605         return HttpResponse(json.dumps(sites), mimetype='application/javascript')
606
607 class DashboardSummaryAjaxView(View):
608     def get(self, request, **kwargs):
609         def avg(x):
610             if len(x)==0:
611                 return 0
612             return float(sum(x))/len(x)
613
614         sites = getCDNOperatorData().values()
615
616         sites = [site for site in sites if site["numHPCSlivers"]>0]
617
618         total_slivers = sum( [site["numHPCSlivers"] for site in sites] )
619         total_bandwidth = sum( [site["bandwidth"] for site in sites] )
620         average_cpu = int(avg( [site["load"] for site in sites] ))
621
622         result= {"total_slivers": total_slivers,
623                 "total_bandwidth": total_bandwidth,
624                 "average_cpu": average_cpu}
625
626         return HttpResponse(json.dumps(result), mimetype='application/javascript')
627
628 class DashboardAddOrRemoveSliverView(View):
629     # TODO: deprecate this view in favor of using TenantAddOrRemoveSliverView
630
631     def post(self, request, *args, **kwargs):
632         siteName = request.POST.get("site", None)
633         actionToDo = request.POST.get("actionToDo", "0")
634
635         siteList = [Site.objects.get(name=siteName)]
636         slice = Slice.objects.get(name="HyperCache")
637
638         if (actionToDo == "add"):
639             user_ip = request.GET.get("ip", get_ip(request))
640             slice_increase_slivers(request.user, user_ip, siteList, slice, 1)
641         elif (actionToDo == "rem"):
642             slice_decrease_slivers(request.user, siteList, slice, 1)
643
644         print '*' * 50
645         print 'Ask for site: ' + siteName + ' to ' + actionToDo + ' another HPC Sliver'
646         return HttpResponse('This is POST request ')
647
648 class DashboardAjaxView(View):
649     def get(self, request, **kwargs):
650         return HttpResponse(json.dumps(getCDNOperatorData(True)), mimetype='application/javascript')
651
652 class DashboardAnalyticsAjaxView(View):
653     def get(self, request, name="hello_world", **kwargs):
654         if (name == "hpcSummary"):
655             return HttpResponse(json.dumps(hpc_wizard.get_hpc_wizard().get_summary_for_view()), mimetype='application/javascript')
656         elif (name == "hpcUserSite"):
657             return HttpResponse(json.dumps(getUserSliceInfo(request.user, True)), mimetype='application/javascript')
658         elif (name == "hpcMap"):
659             return HttpResponse(json.dumps(getCDNOperatorData(True)), mimetype='application/javascript')
660         elif (name == "bigquery"):
661             (mimetype, data) = DoPlanetStackAnalytics(request)
662             return HttpResponse(data, mimetype=mimetype)
663         else:
664             return HttpResponse(json.dumps("Unknown"), mimetype='application/javascript')
665