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 if os.path.exists("/home/smbaker/projects/vicci/cdn/bigquery"):
21 sys.path.append("/home/smbaker/projects/vicci/cdn/bigquery")
23 sys.path.append("/opt/planetstack/hpc_wizard")
25 from planetstack_analytics import DoPlanetStackAnalytics
27 class DashboardWelcomeView(TemplateView):
28 template_name = 'admin/dashboard/welcome.html'
30 def get(self, request, *args, **kwargs):
31 context = self.get_context_data(**kwargs)
32 userDetails = getUserSliceInfo(request.user)
33 #context['site'] = userDetails['site']
35 context['userSliceInfo'] = userDetails['userSliceInfo']
36 context['cdnData'] = userDetails['cdnData']
37 return self.render_to_response(context=context)
39 def getUserSliceInfo(user, tableFormat = False):
42 # // site = Site.objects.filter(id=user.site.id)
44 # // site = Site.objects.filter(name="Princeton")
45 # // userDetails['sitename'] = site[0].name
46 # // userDetails['siteid'] = site[0].id
48 userSliceData = getSliceInfo(user)
50 # pprint("******* GET USER SLICE INFO")
51 userDetails['userSliceInfo'] = userSliceTableFormatter(userSliceData)
53 userDetails['userSliceInfo'] = userSliceData
54 userDetails['cdnData'] = getCDNOperatorData();
55 # pprint( userDetails)
58 class TenantCreateSlice(View):
59 def post(self, request, *args, **kwargs):
60 sliceName = request.POST.get("sliceName", "0")
61 serviceClass = request.POST.get("serviceClass", "0")
62 imageName = request.POST.get("imageName", "0")
63 actionToDo = request.POST.get("actionToDo", "0")
65 if (actionToDo == "add"):
66 serviceClass = ServiceClass.objects.get(name=serviceClass)
67 site = request.user.site
68 #image = Image.objects.get(name=imageName)
69 newSlice = Slice(name=sliceName,serviceClass=serviceClass,site=site,imagePreference=imageName)
74 def getTenantSliceInfo(user, tableFormat = False):
75 tenantSliceDetails = {}
76 tenantSliceData = getTenantInfo(user)
77 tenantServiceClassData = getServiceClassInfo(user)
79 tenantSliceDetails['userSliceInfo'] = userSliceTableFormatter(tenantSliceData)
80 tenantSliceDetails['sliceServiceClass']=userSliceTableFormatter(tenantServiceClassData)
82 tenantSliceDetails['userSliceInfo'] = tenantSliceData
83 tenantSliceDetails['sliceServiceClass']=userSliceTableFormatter(tenantServiceClassData)
84 tenantSliceDetails['image']=userSliceTableFormatter(getImageInfo(user))
85 tenantSliceDetails['network']=userSliceTableFormatter(getNetworkInfo(user))
86 tenantSliceDetails['deploymentSites']=userSliceTableFormatter(getDeploymentSites())
87 tenantSliceDetails['sites'] = userSliceTableFormatter(getTenantSitesInfo());
88 return tenantSliceDetails
91 def getTenantInfo(user):
92 slices =Slice.objects.all()
95 sliceName = Slice.objects.get(id=entry.id).name
96 slice = Slice.objects.get(name=Slice.objects.get(id=entry.id).name)
97 sliceServiceClass = entry.serviceClass.name
98 preferredImage = entry.imagePreference
102 for sliver in slice.slivers.all():
103 numSliver +=sliver.numberCores
104 # sliceSite[sliver.deploymentNetwork.name] =sliceSite.get(sliver.deploymentNetwork.name,0) + 1
105 sliceSite[sliver.node.site.name] = sliceSite.get(sliver.node.site.name,0) + 1
106 sliceImage = sliver.image.name
107 userSliceInfo.append({'sliceName': sliceName,'sliceServiceClass': sliceServiceClass,'preferredImage':preferredImage, 'sliceSite':sliceSite,'sliceImage':sliceImage,'numOfSlivers':numSliver})
110 def getTenantSitesInfo():
112 for entry in Site.objects.all():
113 tenantSiteInfo.append({'siteName':entry.name})
114 return tenantSiteInfo
116 def userSliceTableFormatter(data):
123 def getServiceClassInfo(user):
124 serviceClassList = ServiceClass.objects.all()
126 for entry in serviceClassList:
127 sliceInfo.append({'serviceClass':entry.name})
130 def getImageInfo(user):
131 imageList = Image.objects.all()
133 for imageEntry in imageList:
134 imageInfo.append({'Image':imageEntry.name})
137 def getNetworkInfo(user):
138 #networkList = Network.objects.all()
139 networkList = ['Private Only','Private and Publicly Routable']
141 for networkEntry in networkList:
142 #networkInfo.append({'Network':networkEntry.name})
143 networkInfo.append({'Network':networkEntry})
146 def getDeploymentSites():
147 deploymentList = Deployment.objects.all()
149 for entry in deploymentList:
150 deploymentInfo.append({'DeploymentSite':entry.name})
151 return deploymentInfo
153 def getSliceInfo(user):
154 sliceList = Slice.objects.all()
155 slicePrivs = SlicePrivilege.objects.filter(user=user)
157 for entry in slicePrivs:
159 slicename = Slice.objects.get(id=entry.slice.id).name
160 slice = Slice.objects.get(name=Slice.objects.get(id=entry.slice.id).name)
161 sliverList=Sliver.objects.all()
163 for sliver in slice.slivers.all():
164 #sites_used['deploymentSites'] = sliver.node.deployment.name
165 # sites_used[sliver.image.name] = sliver.image.name
166 sites_used[sliver.node.site.name] = sliver.numberCores
167 sliceid = Slice.objects.get(id=entry.slice.id).id
169 sliverList = Sliver.objects.filter(slice=entry.slice.id)
172 if x.node.site not in siteList:
173 siteList[x.node.site] = 1
174 slivercount = len(sliverList)
175 sitecount = len(siteList)
177 traceback.print_exc()
181 userSliceInfo.append({'slicename': slicename, 'sliceid':sliceid,
182 'sitesUsed':sites_used,
183 'role': SliceRole.objects.get(id=entry.role.id).role,
184 'slivercount': slivercount,
185 'sitecount':sitecount})
189 def getCDNOperatorData(randomizeData = False):
190 return hpc_wizard.get_hpc_wizard().get_sites_for_view()
192 def getPageSummary(request):
193 slice = request.GET.get('slice', None)
194 site = request.GET.get('site', None)
195 node = request.GET.get('node', None)
198 class SimulatorView(View):
199 def get(self, request, **kwargs):
200 sim = json.loads(file("/tmp/simulator.json","r").read())
201 text = "<html><head></head><body>"
202 text += "Iteration: %d<br>" % sim["iteration"]
203 text += "Elapsed since report %d<br><br>" % sim["elapsed_since_report"]
204 text += "<table border=1>"
205 text += "<tr><th>site</th><th>trend</th><th>weight</th><th>bytes_sent</th><th>hot</th></tr>"
206 for site in sim["site_load"].values():
208 text += "<td>%s</td><td>%0.2f</td><td>%0.2f</td><td>%d</td><td>%0.2f</td>" % \
209 (site["name"], site["trend"], site["weight"], site["bytes_sent"], site["load_frac"])
212 text += "</body></html>"
213 return HttpResponse(text)
215 class DashboardUserSiteView(View):
216 def get(self, request, **kwargs):
217 return HttpResponse(json.dumps(getUserSliceInfo(request.user, True)), mimetype='application/javascript')
219 class TenantViewData(View):
220 def get(self, request, **kwargs):
221 return HttpResponse(json.dumps(getTenantSliceInfo(request.user, True)), mimetype='application/javascript')
223 ALLOWED_TENANT_SITES = ["Stanford", "Washington", "Princeton", "GeorgiaTech", "MaxPlanck"]
225 def siteSortKey(site, slice=None, count=None, lat=None, lon=None):
226 # try to pick a site we're already using
227 has_slivers_here=False
229 for sliver in slice.slivers.all():
230 if sliver.node.site.name == site.name:
231 has_slivers_here=True
235 site_lat = site.location.latitude
236 site_lon = site.location.longitude
237 if lat and lon and site_lat and site_lon:
238 site_lat = float(site_lat)
239 site_lon = float(site_lon)
241 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)
242 c = 2 * math.atan2( math.sqrt(a), math.sqrt(1 - a) )
245 return (-has_slivers_here, d)
247 def tenant_pick_sites(user, user_ip=None, slice=None, count=None):
248 """ Returns list of sites, sorted from most favorable to least favorable """
252 client_geo = GeoIP().city(user_ip)
254 lat=float(client_geo["latitude"])
255 lon=float(client_geo["longitude"])
257 print "exception in geo code"
258 traceback.print_exc()
260 sites = Site.objects.all()
261 sites = [x for x in sites if x.name in ALLOWED_TENANT_SITES]
262 sites = sorted(sites, key=functools.partial(siteSortKey, slice=slice, count=count, lat=lat, lon=lon))
266 def tenant_increase_slivers(user, user_ip, siteList, slice, count, noAct=False):
269 # let's compute how many slivers are in use in each node of each site
270 for site in siteList:
271 site.nodeList = list(site.nodes.all())
272 for node in site.nodeList:
274 for sliver in node.slivers.all():
275 if sliver.slice.name == slice.name:
276 node.sliverCount = node.sliverCount +1
278 # Allocate slivers to nodes
279 # for now, assume we want to allocate all slivers from the same site
280 nodes = siteList[0].nodeList
282 # Sort the node list by number of slivers per node, then pick the
283 # node with the least number of slivers.
284 nodes = sorted(nodes, key=attrgetter("sliverCount"))
287 print "adding sliver at node", node.name, "of site", node.site.name
290 sliver = Sliver(name=node.name,
293 image = Image.objects.all()[0],
294 creator = User.objects.get(email=user),
295 deploymentNetwork=node.deployment,
299 node.sliverCount = node.sliverCount + 1
303 sitesChanged[node.site.name] = sitesChanged.get(node.site.name,0) + 1
307 def tenant_decrease_slivers(user, siteList, slice, count, noAct=False):
311 siteNames = [site.name for site in siteList]
315 for sliver in slice.slivers.all():
320 if (not siteNames) or (node.site.name in siteNames):
321 print "deleting sliver", sliver, "at node", node.name, "of site", node.site.name
326 sitesChanged[node.site.name] = sitesChanged.get(node.site.name,0) - 1
330 class TenantAddOrRemoveSliverView(View):
331 """ Add or remove slivers from a Slice
334 siteName - name of site. If not specified, PlanetStack will pick the
336 actionToDo - [add | rem]
337 count - number of slivers to add or remove
338 sliceName - name of slice
339 noAct - if set, no changes will be made to db
342 Dictionary of sites that were modified, and the count of nodes
343 that were added or removed at each site.
345 def post(self, request, *args, **kwargs):
346 siteName = request.POST.get("siteName", None)
347 actionToDo = request.POST.get("actionToDo", None)
348 count = int(request.POST.get("count","0"))
349 sliceName = request.POST.get("slice", None)
350 noAct = request.POST.get("noAct", False)
353 return HttpResponseServerError("No slice name given")
355 slice = Slice.objects.get(name=sliceName)
358 siteList = [Site.objects.get(name=siteName)]
362 if (actionToDo == "add"):
363 user_ip = request.GET.get("ip", get_ip(request))
364 if (siteList is None):
365 siteList = tenant_pick_sites(user, user_ip, slice, count)
367 sitesChanged = tenant_increase_slivers(request.user, user_ip, siteList, slice, count, noAct)
368 elif (actionToDo == "rem"):
369 sitesChanged = tenant_decrease_slivers(request.user, siteList, slice, count, noAct)
371 return HttpResponseServerError("Unknown actionToDo %s" % actionToDo)
373 return HttpResponse(json.dumps(sitesChanged), mimetype='application/javascript')
375 def get(self, request, *args, **kwargs):
376 request.POST = request.GET
377 return self.post(request, *args, **kwargs) # for testing REST in browser
378 #return HttpResponseServerError("GET is not supported")
380 class TenantPickSitesView(View):
381 """ primarily just for testing purposes """
382 def get(self, request, *args, **kwargs):
383 count = request.GET.get("count","0")
384 slice = request.GET.get("slice",None)
386 slice = Slice.objects.get(name=slice)
387 ip = request.GET.get("ip", get_ip(request))
388 sites = tenant_pick_sites(request.user, user_ip=ip, count=0, slice=slice)
389 sites = [x.name for x in sites]
390 return HttpResponse(json.dumps(sites), mimetype='application/javascript')
392 class DashboardSummaryAjaxView(View):
393 def get(self, request, **kwargs):
394 return HttpResponse(json.dumps(hpc_wizard.get_hpc_wizard().get_summary_for_view()), mimetype='application/javascript')
396 class DashboardAddOrRemoveSliverView(View):
397 def post(self, request, *args, **kwargs):
398 siteName = request.POST.get("site", "0")
399 actionToDo = request.POST.get("actionToDo", "0")
401 if (actionToDo == "add"):
402 hpc_wizard.get_hpc_wizard().increase_slivers(siteName, 1)
403 elif (actionToDo == "rem"):
404 hpc_wizard.get_hpc_wizard().decrease_slivers(siteName, 1)
407 print 'Ask for site: ' + siteName + ' to ' + actionToDo + ' another HPC Sliver'
408 return HttpResponse('This is POST request ')
410 class DashboardAjaxView(View):
411 def get(self, request, **kwargs):
412 return HttpResponse(json.dumps(getCDNOperatorData(True)), mimetype='application/javascript')
414 class DashboardAnalyticsAjaxView(View):
415 def get(self, request, name="hello_world", **kwargs):
416 if (name == "hpcSummary"):
417 return HttpResponse(json.dumps(hpc_wizard.get_hpc_wizard().get_summary_for_view()), mimetype='application/javascript')
418 elif (name == "hpcUserSite"):
419 return HttpResponse(json.dumps(getUserSliceInfo(request.user, True)), mimetype='application/javascript')
420 elif (name == "hpcMap"):
421 return HttpResponse(json.dumps(getCDNOperatorData(True)), mimetype='application/javascript')
422 elif (name == "bigquery"):
423 (mimetype, data) = DoPlanetStackAnalytics(request)
424 return HttpResponse(data, mimetype=mimetype)
426 return HttpResponse(json.dumps("Unknown"), mimetype='application/javascript')