Merge branch 'fed4fire' into onelab
[myslice.git] / sla / slicetabsla.py
1 # this somehow is not used anymore - should it not be ?
2 from django.template import RequestContext
3 from django.shortcuts import render_to_response
4 from django.shortcuts import render
5 from django import forms
6
7 from unfold.loginrequired import FreeAccessView
8 from unfold.page import Page
9 from sla.slaclient import restclient
10 from sla.slaclient import wsag_model
11 import wsag_helper
12 from myslice.theme import ThemeView
13 # from sla import SLAPlugin
14 from django.core.urlresolvers import reverse
15 from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
16
17 import slaclient.service.fed4fire.fed4fireservice as fed4fireservice
18 from rest_framework.views import APIView
19 from django.http import HttpResponse
20
21 import json
22 import traceback
23 import re
24 from math import ceil
25 from datetime import datetime
26 from dateutil.relativedelta import relativedelta
27 from dateutil.tz import tzlocal
28 from django.conf import settings
29
30
31 class Rol:
32     CONSUMER = "CONSUMER"
33     PROVIDER = "PROVIDER"
34
35
36 class AgreementsFilter(object):
37     def __init__(self, status=None, provider=None, consumer=None):
38         self.status = status
39         self.provider = provider
40         self.consumer = consumer
41
42     def __repr__(self):
43         return "<AgreementsFilter(status={}, provider={}, consumer={})>".format(
44             self.status, self.provider, self.consumer
45         )
46
47     @staticmethod
48     def _check(expectedvalue, actualvalue):
49         if expectedvalue is None or expectedvalue == '':
50             return True
51         else:
52             return actualvalue == expectedvalue
53
54     def check(self, agreement):
55         """Check if this agreement satisfy the filter.
56
57         The agreement must be previously annotated
58         """
59         guaranteestatus = agreement.guaranteestatus
60         provider = agreement.context.provider
61         consumer = agreement.context.consumer
62         return (
63             AgreementsFilter._check(self.status, guaranteestatus) and
64             AgreementsFilter._check(self.provider, provider) and
65             AgreementsFilter._check(self.consumer, consumer)
66         )
67
68
69 class FilterForm(forms.Form):
70     _attrs = {'class': 'form-control'}
71     exclude = ()
72     status = forms.ChoiceField(
73         choices=[
74             ('', 'All'),
75             (wsag_model.AgreementStatus.StatusEnum.FULFILLED, 'Fulfilled'),
76             (wsag_model.AgreementStatus.StatusEnum.VIOLATED, 'Violated'),
77             (wsag_model.AgreementStatus.StatusEnum.NON_DETERMINED, 'Non determined')],
78         widget=forms.Select(attrs=_attrs),
79         required=False
80     )
81     provider = forms.CharField(
82         widget=forms.TextInput(attrs=_attrs),
83         required=False
84     )
85     consumer = forms.CharField(
86         widget=forms.TextInput(attrs=_attrs),
87         required=False
88     )
89
90
91 class SLAView (FreeAccessView, ThemeView):
92     template_name = 'slice-tab-sla.html'
93
94     def get (self, request, slicename, state=None):
95
96         page=Page(request)
97
98         consumer_id = None
99         agreement_id = None
100         enforcements = {}
101         violations = {}
102         keys = ['provider','agreement','date','status','result','ok']
103         ag_info = []
104
105         filter_ = None
106         form = FilterForm(request.GET)
107         if form.is_valid():
108             filter_ = _get_filter_from_form(form)
109
110         consumer_id = _get_consumer_id(request)
111
112         #agreements = _get_agreements(agreement_id, consumer_id=consumer_id, filter_=filter_)
113         agreements = _get_agreements(agreement_id, slice=slicename)
114
115         for agreement in agreements:
116             row = []
117             provider = agreement.context.provider
118             row.append(provider) # Provider
119             row.append(agreement) # Agreement
120             row.append(agreement.context.time_formatted()) # Date
121
122             enf = _get_enforcement(agreement.agreement_id, provider)
123
124             if enf.enabled == 'true':
125                 row.append('Evaluating') # Status
126                 row.append('') # Result
127                 row('') # Ok
128             else:
129                 if agreement.guaranteestatus == "NON_DETERMINED":
130                     row.append('Provisioned') # Status
131                     row.append('') # Result
132                     row.append('') # Ok
133                 
134                 else:
135                     row.append('Finished') # Status
136
137                     violations_list = _get_agreement_violations(agreement.agreement_id, provider, "GT_Performance")
138                     
139                     if len(violations_list) > 0:
140                         value = '%.2f'%float(violations_list[0].actual_value)
141                         row.append('%d'%(float(value)*100)) # Result
142                     else:
143                         row.append('100') # Result
144
145                     if agreement.guaranteestatus == "VIOLATED":
146                         row.append('false') # Ok
147
148                     if agreement.guaranteestatus == "FULFILLED":
149                         row.append('true') # Ok
150
151             ag_info.append(dict(zip(keys,row)))
152
153         template_env = {}
154        # write something of our own instead
155        # more general variables expected in the template
156         template_env['title'] = 'SLA Agreements'
157         template_env['agreements'] = agreements
158         template_env['username'] = request.user
159         template_env['slicename'] = slicename
160         template_env['enforcements'] = enforcements
161         template_env['last_violation_list'] = violations
162         template_env['ag_info'] = ag_info
163
164
165        # the prelude object in page contains a summary of the requirements() for all plugins
166        # define {js,css}_{files,chunks}
167         prelude_env = page.prelude_env()
168         template_env.update(prelude_env)
169
170         return render_to_response(self.template_name, template_env, context_instance=RequestContext(request))
171
172
173 class AgreementsFilter(object):
174     def __init__(self, status=None, provider=None, consumer=None):
175         self.status = status
176         self.provider = provider
177         self.consumer = consumer
178
179     def __repr__(self):
180         return "<AgreementsFilter(status={}, provider={}, consumer={})>".format(
181             self.status, self.provider, self.consumer
182         )
183
184     @staticmethod
185     def _check(expectedvalue, actualvalue):
186         if expectedvalue is None or expectedvalue == '':
187             return True
188         else:
189             return actualvalue == expectedvalue
190
191     def check(self, agreement):
192         """Check if this agreement satisfy the filter.
193
194         The agreement must be previously annotated
195         """
196         guaranteestatus = agreement.guaranteestatus
197         provider = agreement.context.provider
198         consumer = agreement.context.consumer
199         return (
200             AgreementsFilter._check(self.status, guaranteestatus) and
201             AgreementsFilter._check(self.provider, provider) and
202             AgreementsFilter._check(self.consumer, consumer)
203         )
204
205
206 class ContactForm(forms.Form):
207     subject = forms.CharField(max_length=100)
208     message = forms.CharField()
209     sender = forms.EmailField()
210     cc_myself = forms.BooleanField(required=False)
211
212
213 def _get_agreements_client(path=""):
214     return restclient.Factory.agreements(path)
215
216
217 def _get_violations_client():
218     return restclient.Factory.violations()
219
220 def _get_enforcements_client():
221     return restclient.Factory.enforcements()
222
223 def _get_consumer_id(request):
224     return request.user
225
226
227 def _get_agreement(agreement_id):
228
229     agreements_client = _get_agreements_client()
230     agreement, response = agreements_client.getbyid(agreement_id)
231     return agreement
232
233 def _get_enforcement(agreement_id, testbed):
234
235     enforcements_client = _get_enforcements_client()
236     enforcement, response = enforcements_client.getbyagreement(agreement_id, testbed)
237     return enforcement
238
239 def _get_filter_from_form(form):
240
241     data = form.cleaned_data
242     result = AgreementsFilter(
243         data["status"], data["provider"], data["consumer"])
244     return result
245
246 def agreement_term_violations(request, agreement_id, guarantee_name):
247
248     page = Page(request)
249     prelude_env = page.prelude_env()
250
251     annotator = wsag_helper.AgreementAnnotator()
252     agreement = _get_agreement(agreement_id)
253     violations = _get_agreement_violations(agreement_id, guarantee_name)
254     annotator.annotate_agreement(agreement)
255     
256     slicename = request.POST.get('slicename')
257     
258     paginator = Paginator(violations, 25) # Show 25 violations per page
259     page_num = request.GET.get('page')
260     
261     try:
262         violation_page = paginator.page(page_num)
263     except PageNotAnInteger:
264         # If page is not an integer, deliver first page.
265         violation_page = paginator.page(1)
266     except EmptyPage:
267         # If page is out of range (e.g. 9999), deliver first page.
268         violation_page = paginator.page(1)
269  
270     context = {
271         'agreement_id': agreement_id,
272         'guarantee_term': agreement.guaranteeterms[guarantee_name],
273         'violations': violation_page,
274         'agreement': agreement,
275         'slicename': slicename,
276         'last_violation': violations[-1].actual_value
277     }
278     
279     context.update(prelude_env)
280     
281     return render_to_response ('violations_template.html', context, context_instance=RequestContext(request))
282 #     return render(request, 'violations_template.html', context)
283
284 def agreement_details(request, agreement_id):
285     
286     page = Page(request)
287     prelude_env = page.prelude_env()
288     
289     annotator = wsag_helper.AgreementAnnotator()
290     agreement = _get_agreement(agreement_id)
291     violations = _get_agreement_violations(agreement_id)
292     status = _get_agreement_status(agreement_id)
293     annotator.annotate_agreement(agreement, status, violations)
294
295     violations_by_date = wsag_helper.get_violations_bydate(violations)
296     context = {
297         'agreement_id': agreement_id,
298         'agreement': agreement,
299         'status': status,
300         'violations_by_date': violations_by_date
301     }
302     
303     context.update(prelude_env)
304     
305     return render_to_response ('violations_template.html', context, context_instance=RequestContext(request))
306     #return render(request, 'agreement_detail.html', context)
307
308 def _get_agreement(agreement_id):
309
310     agreements_client = _get_agreements_client()
311     agreement, response = agreements_client.getbyid(agreement_id)
312     return agreement
313
314 def _get_agreements(agreement_id, slice=None, provider_id=None, consumer_id=None, filter_=None):
315
316     agreements_client = _get_agreements_client()
317     if agreement_id is None:
318         if consumer_id is not None:
319             agreements, response = agreements_client.getbyconsumer(consumer_id)
320         elif provider_id is not None:
321             agreements, response = agreements_client.getbyprovider(provider_id)
322         elif slice is not None:
323             agreements_client = _get_agreements_client("slice")
324             agreements, response = agreements_client.getbyslice(slice)
325         else:
326             raise ValueError(
327                 "Invalid values: consumer_id and provider_id are None")
328     else:
329         agreement, response = agreements_client.getbyid(agreement_id)
330         agreements = [agreement]
331
332     annotator = wsag_helper.AgreementAnnotator()
333     for agreement in agreements:
334         id_ = agreement.agreement_id
335         testbed = agreement.context.provider
336         status = _get_agreement_status(id_, testbed)
337         annotator.annotate_agreement(agreement, status)
338
339     if filter_ is not None:
340         print "FILTERING ", repr(filter_)
341         agreements = filter(filter_.check, agreements);
342     else:
343         print "NOT FILTERING"
344     return agreements
345
346
347 def _get_agreements_by_consumer(consumer_id):
348
349     agreements_client = _get_agreements_client()
350     agreements, response = agreements_client.getbyconsumer(consumer_id)
351     return agreements
352
353 def _get_agreement_status(agreement_id, testbed):
354
355     agreements_client = _get_agreements_client()
356     status, response = agreements_client.getstatus(agreement_id, testbed)
357     return status
358
359 def _get_agreement_violations(agreement_id, testbed, term=None):
360
361     violations_client = _get_violations_client()
362     violations, response = violations_client.getbyagreement(agreement_id, testbed, term)
363     return violations
364
365
366 class AgreementSimple(APIView):
367
368     regex = r"[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}"
369
370     def build_response(self, code, text):
371         response = HttpResponse(text, content_type="text/plain", status=code)
372         return response 
373
374     def post(self, request, **kwargs):
375         #import pdb; pdb.set_trace()
376         print "------------------------------------------------1"
377         data = request.POST
378
379         url = settings.SLA_MANAGER_URL
380         c = restclient.Client(url)
381         # for key, value in request.DATA.items(): # jgarcia review this
382         #     data[key] = value
383         
384         # print "---- DATA: ----"
385         # print "Data type: ", type(data)
386         # for key in data:
387         #     print key, data.getlist(key)
388
389         try:
390             # template_id = data['template_id']
391             testbeds = data.getlist("testbeds")
392             user = data["user"]
393             resources = data.getlist("resources")
394             slice_id = data["slice"]
395         except:
396             print "FAIL!"
397             return self.build_response(400, 'Invalid data')
398
399         selected_resources = {}
400
401         now = datetime.now(tzlocal())
402         expiration_time = now + relativedelta(years=1)
403
404         for testbed in testbeds:
405             selected_resources[testbed] = [r for r in resources if testbed in r]
406             template_id = testbed
407             try:
408                 print "Calling createagreementsimplified with template_id:",template_id,"and user:",user
409                 result = fed4fireservice.createagreementsimplified(
410                             template_id, user, expiration_time, selected_resources)
411                 print result
412             except Exception, e:
413                 print traceback.format_exc()
414                 print '%s (%s)' % (e, type(e))
415                 return self.build_response(400, 'Problem creating agreement')
416
417             agreement_id = re.compile(self.regex).search(result.text).group(0)
418          
419             data = '{{ "id": "{}", \
420                       "slice": "{}", \
421                       "testbed": "{}" }}'.format(agreement_id, slice_id, testbed)
422
423             c.post(
424                 "sliver",
425                 data,
426                 headers = {
427                     "content-type": "application/json",
428                     "accept": "application/xml"
429                 }
430             )   
431
432         return self.build_response(200, result)            
433
434 class Testbeds(APIView):
435     def get(self, request, **kwargs):
436         c = restclient.Client("http://157.193.215.125:4001/sla-collector")
437         #url = settings.SLA_MANAGER_URL.replace("/sla","")
438         #c = restclient.Client(url)
439         print "**** URL ******", url
440         SLAtestbeds = c.get("testbeds")
441         # Future work: get SLA description for each testbed
442
443         return HttpResponse(SLAtestbeds.text, content_type="application/json", status=SLAtestbeds.status_code)