6 from django.views.generic import TemplateView, View
8 from pprint import pprint
10 from core.models import *
11 from operator import attrgetter
12 from django.views.decorators.csrf import csrf_exempt
13 from django.http import HttpResponse, HttpResponseServerError
14 from django.core import urlresolvers
15 from django.contrib.gis.geoip import GeoIP
16 from ipware.ip import get_ip
20 BLESSED_SITES = ["Stanford", "Washington", "Princeton", "GeorgiaTech", "MaxPlanck"]
22 if os.path.exists("/home/smbaker/projects/vicci/cdn/bigquery"):
23 sys.path.append("/home/smbaker/projects/vicci/cdn/bigquery")
25 sys.path.append("/opt/planetstack/hpc_wizard")
27 from planetstack_analytics import DoPlanetStackAnalytics
29 class DashboardWelcomeView(TemplateView):
30 template_name = 'admin/dashboard/welcome.html'
32 def get(self, request, *args, **kwargs):
33 context = self.get_context_data(**kwargs)
34 userDetails = getUserSliceInfo(request.user)
35 #context['site'] = userDetails['site']
37 context['userSliceInfo'] = userDetails['userSliceInfo']
38 context['cdnData'] = userDetails['cdnData']
39 return self.render_to_response(context=context)
41 def getUserSliceInfo(user, tableFormat = False):
44 # // site = Site.objects.filter(id=user.site.id)
46 # // site = Site.objects.filter(name="Princeton")
47 # // userDetails['sitename'] = site[0].name
48 # // userDetails['siteid'] = site[0].id
50 userSliceData = getSliceInfo(user)
52 # pprint("******* GET USER SLICE INFO")
53 userDetails['userSliceInfo'] = userSliceTableFormatter(userSliceData)
55 userDetails['userSliceInfo'] = userSliceData
56 userDetails['cdnData'] = getCDNOperatorData();
57 # pprint( userDetails)
60 class TenantCreateSlice(View):
61 def post(self, request, *args, **kwargs):
62 sliceName = request.POST.get("sliceName", "0")
63 serviceClass = request.POST.get("serviceClass", "0")
64 imageName = request.POST.get("imageName", "0")
65 actionToDo = request.POST.get("actionToDo", "0")
67 if (actionToDo == "add"):
68 serviceClass = ServiceClass.objects.get(name=serviceClass)
69 site = request.user.site
70 #image = Image.objects.get(name=imageName)
71 newSlice = Slice(name=sliceName,serviceClass=serviceClass,site=site,imagePreference=imageName)
76 def getTenantSliceInfo(user, tableFormat = False):
77 tenantSliceDetails = {}
78 tenantSliceData = getTenantInfo(user)
79 tenantServiceClassData = getServiceClassInfo(user)
81 tenantSliceDetails['userSliceInfo'] = userSliceTableFormatter(tenantSliceData)
82 tenantSliceDetails['sliceServiceClass']=userSliceTableFormatter(tenantServiceClassData)
84 tenantSliceDetails['userSliceInfo'] = tenantSliceData
85 tenantSliceDetails['sliceServiceClass']=userSliceTableFormatter(tenantServiceClassData)
86 tenantSliceDetails['image']=userSliceTableFormatter(getImageInfo(user))
87 tenantSliceDetails['network']=userSliceTableFormatter(getNetworkInfo(user))
88 tenantSliceDetails['deploymentSites']=userSliceTableFormatter(getDeploymentSites())
89 tenantSliceDetails['sites'] = userSliceTableFormatter(getTenantSitesInfo());
90 return tenantSliceDetails
93 def getTenantInfo(user):
94 slices =Slice.objects.all()
97 sliceName = Slice.objects.get(id=entry.id).name
98 slice = Slice.objects.get(name=Slice.objects.get(id=entry.id).name)
99 sliceServiceClass = entry.serviceClass.name
100 preferredImage = entry.imagePreference
104 for sliver in slice.slivers.all():
105 numSliver +=sliver.numberCores
106 # sliceSite[sliver.deploymentNetwork.name] =sliceSite.get(sliver.deploymentNetwork.name,0) + 1
107 if sliver.node.site.name in BLESSED_SITES:
108 print "equal",sliver.node.site.name
109 sliceSite[sliver.node.site.name] = sliceSite.get(sliver.node.site.name,0) + 1
110 sliceImage = sliver.image.name
111 userSliceInfo.append({'sliceName': sliceName,'sliceServiceClass': sliceServiceClass,'preferredImage':preferredImage, 'sliceSite':sliceSite,'sliceImage':sliceImage,'numOfSlivers':numSliver})
114 def getTenantSitesInfo():
116 for entry in Site.objects.all():
117 if entry.name in BLESSED_SITES:
118 tenantSiteInfo.append({'siteName':entry.name})
119 return tenantSiteInfo
121 def userSliceTableFormatter(data):
128 def getServiceClassInfo(user):
129 serviceClassList = ServiceClass.objects.all()
131 for entry in serviceClassList:
132 sliceInfo.append({'serviceClass':entry.name})
135 def getImageInfo(user):
136 imageList = Image.objects.all()
138 for imageEntry in imageList:
139 imageInfo.append({'Image':imageEntry.name})
142 def getNetworkInfo(user):
143 #networkList = Network.objects.all()
144 networkList = ['Private Only','Private and Publicly Routable']
146 for networkEntry in networkList:
147 #networkInfo.append({'Network':networkEntry.name})
148 networkInfo.append({'Network':networkEntry})
151 def getDeploymentSites():
152 deploymentList = Deployment.objects.all()
154 for entry in deploymentList:
155 deploymentInfo.append({'DeploymentSite':entry.name})
156 return deploymentInfo
158 def getSliceInfo(user):
159 sliceList = Slice.objects.all()
160 slicePrivs = SlicePrivilege.objects.filter(user=user)
162 for entry in slicePrivs:
164 slicename = Slice.objects.get(id=entry.slice.id).name
165 slice = Slice.objects.get(name=Slice.objects.get(id=entry.slice.id).name)
166 sliverList=Sliver.objects.all()
168 for sliver in slice.slivers.all():
169 #sites_used['deploymentSites'] = sliver.node.deployment.name
170 # sites_used[sliver.image.name] = sliver.image.name
171 sites_used[sliver.node.site.name] = sliver.numberCores
172 sliceid = Slice.objects.get(id=entry.slice.id).id
174 sliverList = Sliver.objects.filter(slice=entry.slice.id)
177 if x.node.site not in siteList:
178 siteList[x.node.site] = 1
179 slivercount = len(sliverList)
180 sitecount = len(siteList)
182 traceback.print_exc()
186 userSliceInfo.append({'slicename': slicename, 'sliceid':sliceid,
187 'sitesUsed':sites_used,
188 'role': SliceRole.objects.get(id=entry.role.id).role,
189 'slivercount': slivercount,
190 'sitecount':sitecount})
194 def getCDNOperatorData(randomizeData = False):
195 return hpc_wizard.get_hpc_wizard().get_sites_for_view()
197 def getPageSummary(request):
198 slice = request.GET.get('slice', None)
199 site = request.GET.get('site', None)
200 node = request.GET.get('node', None)
203 class SimulatorView(View):
204 def get(self, request, **kwargs):
205 sim = json.loads(file("/tmp/simulator.json","r").read())
206 text = "<html><head></head><body>"
207 text += "Iteration: %d<br>" % sim["iteration"]
208 text += "Elapsed since report %d<br><br>" % sim["elapsed_since_report"]
209 text += "<table border=1>"
210 text += "<tr><th>site</th><th>trend</th><th>weight</th><th>bytes_sent</th><th>hot</th></tr>"
211 for site in sim["site_load"].values():
213 text += "<td>%s</td><td>%0.2f</td><td>%0.2f</td><td>%d</td><td>%0.2f</td>" % \
214 (site["name"], site["trend"], site["weight"], site["bytes_sent"], site["load_frac"])
217 text += "</body></html>"
218 return HttpResponse(text)
220 class DashboardUserSiteView(View):
221 def get(self, request, **kwargs):
222 return HttpResponse(json.dumps(getUserSliceInfo(request.user, True)), mimetype='application/javascript')
224 class TenantViewData(View):
225 def get(self, request, **kwargs):
226 return HttpResponse(json.dumps(getTenantSliceInfo(request.user, True)), mimetype='application/javascript')
228 def siteSortKey(site, slice=None, count=None, lat=None, lon=None):
229 # try to pick a site we're already using
230 has_slivers_here=False
232 for sliver in slice.slivers.all():
233 if sliver.node.site.name == site.name:
234 has_slivers_here=True
238 site_lat = site.location.latitude
239 site_lon = site.location.longitude
240 if lat and lon and site_lat and site_lon:
241 site_lat = float(site_lat)
242 site_lon = float(site_lon)
244 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)
245 c = 2 * math.atan2( math.sqrt(a), math.sqrt(1 - a) )
248 return (-has_slivers_here, d)
250 def tenant_pick_sites(user, user_ip=None, slice=None, count=None):
251 """ Returns list of sites, sorted from most favorable to least favorable """
255 client_geo = GeoIP().city(user_ip)
257 lat=float(client_geo["latitude"])
258 lon=float(client_geo["longitude"])
260 print "exception in geo code"
261 traceback.print_exc()
263 sites = Site.objects.all()
264 sites = [x for x in sites if x.name in BLESSED_SITES]
265 sites = sorted(sites, key=functools.partial(siteSortKey, slice=slice, count=count, lat=lat, lon=lon))
269 def tenant_increase_slivers(user, user_ip, siteList, slice, count, noAct=False):
272 # let's compute how many slivers are in use in each node of each site
273 for site in siteList:
274 site.nodeList = list(site.nodes.all())
275 for node in site.nodeList:
277 for sliver in node.slivers.all():
278 if sliver.slice.name == slice.name:
279 node.sliverCount = node.sliverCount +1
281 # Allocate slivers to nodes
282 # for now, assume we want to allocate all slivers from the same site
283 nodes = siteList[0].nodeList
285 # Sort the node list by number of slivers per node, then pick the
286 # node with the least number of slivers.
287 nodes = sorted(nodes, key=attrgetter("sliverCount"))
290 print "adding sliver at node", node.name, "of site", node.site.name
293 sliver = Sliver(name=node.name,
296 image = Image.objects.all()[0],
297 creator = User.objects.get(email=user),
298 deploymentNetwork=node.deployment,
302 node.sliverCount = node.sliverCount + 1
306 sitesChanged[node.site.name] = sitesChanged.get(node.site.name,0) + 1
310 def tenant_decrease_slivers(user, siteList, slice, count, noAct=False):
314 siteNames = [site.name for site in siteList]
318 for sliver in slice.slivers.all():
323 if (not siteNames) or (node.site.name in siteNames):
324 print "deleting sliver", sliver, "at node", node.name, "of site", node.site.name
329 sitesChanged[node.site.name] = sitesChanged.get(node.site.name,0) - 1
333 class TenantAddOrRemoveSliverView(View):
334 """ Add or remove slivers from a Slice
337 siteName - name of site. If not specified, PlanetStack will pick the
339 actionToDo - [add | rem]
340 count - number of slivers to add or remove
341 sliceName - name of slice
342 noAct - if set, no changes will be made to db, but result will still
343 show which sites would have been modified.
346 Dictionary of sites that were modified, and the count of nodes
347 that were added or removed at each site.
349 def post(self, request, *args, **kwargs):
350 siteName = request.POST.get("siteName", None)
351 actionToDo = request.POST.get("actionToDo", None)
352 count = int(request.POST.get("count","0"))
353 sliceName = request.POST.get("slice", None)
354 noAct = request.POST.get("noAct", False)
357 return HttpResponseServerError("No slice name given")
359 slice = Slice.objects.get(name=sliceName)
362 siteList = [Site.objects.get(name=siteName)]
366 if (actionToDo == "add"):
367 user_ip = request.GET.get("ip", get_ip(request))
368 if (siteList is None):
369 siteList = tenant_pick_sites(user, user_ip, slice, count)
371 sitesChanged = tenant_increase_slivers(request.user, user_ip, siteList, slice, count, noAct)
372 elif (actionToDo == "rem"):
373 sitesChanged = tenant_decrease_slivers(request.user, siteList, slice, count, noAct)
375 return HttpResponseServerError("Unknown actionToDo %s" % actionToDo)
377 return HttpResponse(json.dumps(sitesChanged), mimetype='application/javascript')
379 def get(self, request, *args, **kwargs):
380 request.POST = request.GET
381 return self.post(request, *args, **kwargs) # for testing REST in browser
382 #return HttpResponseServerError("GET is not supported")
384 class TenantPickSitesView(View):
385 """ primarily just for testing purposes """
386 def get(self, request, *args, **kwargs):
387 count = request.GET.get("count","0")
388 slice = request.GET.get("slice",None)
390 slice = Slice.objects.get(name=slice)
391 ip = request.GET.get("ip", get_ip(request))
392 sites = tenant_pick_sites(request.user, user_ip=ip, count=0, slice=slice)
393 sites = [x.name for x in sites]
394 return HttpResponse(json.dumps(sites), mimetype='application/javascript')
396 class DashboardSummaryAjaxView(View):
397 def get(self, request, **kwargs):
398 return HttpResponse(json.dumps(hpc_wizard.get_hpc_wizard().get_summary_for_view()), mimetype='application/javascript')
400 class DashboardAddOrRemoveSliverView(View):
401 def post(self, request, *args, **kwargs):
402 siteName = request.POST.get("site", "0")
403 actionToDo = request.POST.get("actionToDo", "0")
405 if (actionToDo == "add"):
406 hpc_wizard.get_hpc_wizard().increase_slivers(siteName, 1)
407 elif (actionToDo == "rem"):
408 hpc_wizard.get_hpc_wizard().decrease_slivers(siteName, 1)
411 print 'Ask for site: ' + siteName + ' to ' + actionToDo + ' another HPC Sliver'
412 return HttpResponse('This is POST request ')
414 class DashboardAjaxView(View):
415 def get(self, request, **kwargs):
416 return HttpResponse(json.dumps(getCDNOperatorData(True)), mimetype='application/javascript')
418 class DashboardAnalyticsAjaxView(View):
419 def get(self, request, name="hello_world", **kwargs):
420 if (name == "hpcSummary"):
421 return HttpResponse(json.dumps(hpc_wizard.get_hpc_wizard().get_summary_for_view()), mimetype='application/javascript')
422 elif (name == "hpcUserSite"):
423 return HttpResponse(json.dumps(getUserSliceInfo(request.user, True)), mimetype='application/javascript')
424 elif (name == "hpcMap"):
425 return HttpResponse(json.dumps(getCDNOperatorData(True)), mimetype='application/javascript')
426 elif (name == "bigquery"):
427 (mimetype, data) = DoPlanetStackAnalytics(request)
428 return HttpResponse(data, mimetype=mimetype)
430 return HttpResponse(json.dumps("Unknown"), mimetype='application/javascript')