Merge branch 'onelab' of https://github.com/onelab-eu/myslice into onelab
[myslice.git] / sla / slicetabsla.py
1 from __future__ import print_function
2
3 # this somehow is not used anymore - should it not be ?
4 import ast
5 from datetime import datetime
6 import json
7 import pytz
8 from django.template import RequestContext
9 from django.shortcuts import render_to_response
10 from django.shortcuts import render
11 from django import forms
12 import re
13
14 from unfold.loginrequired import LoginRequiredView, FreeAccessView
15 from unfold.page import Page
16 from sla.slaclient import restclient
17 from sla.slaclient import wsag_model
18 import wsag_helper
19 from myslice.theme import ThemeView
20 # from sla import SLAPlugin
21 from django.core.urlresolvers import reverse
22 from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
23
24 import slaclient.service.fed4fire.fed4fireservice as fed4fireservice
25 from django.http import HttpResponse
26
27 from myslice.settings import logger, SLA_COLLECTOR_URL
28
29 class SLAView(FreeAccessView, ThemeView):
30     template_name = 'slice-tab-sla.html'
31
32     def get(self, request, slicename):
33
34         page = Page(request)
35
36         agreement_id = None
37         enforcements = {}
38         violations = {}
39         keys = ['provider', 'agreement',
40                 'date', 'status', 'result',
41                 'ok', 'slivers']
42         ag_info = []
43
44         agreements = _get_agreements_by_slice(slicename)
45
46         for agreement in agreements:
47             row = []
48             provider = agreement.context.provider
49             row.append(provider)  # Provider
50             row.append(agreement)  # Agreement
51             row.append(agreement.context.time_formatted())  # Date
52
53             enf = _get_enforcement(agreement.agreement_id, provider)
54
55             if enf.enabled == 'true':
56                 row.append('Evaluating')  # Status
57                 row.append('')  # Result
58                 row.append('')  # Ok
59             else:
60                 if agreement.guaranteestatus == "NON_DETERMINED":
61                     row.append('Provisioned')  # Status
62                     row.append('')  # Result
63                     row.append('')  # Ok
64
65                 else:
66                     row.append('Finished')  # Status
67
68                     violations_list = _get_agreement_violations(agreement.agreement_id, provider, "GT_Performance")
69
70                     if len(violations_list) > 0:
71                         value = '%.2f' % float(violations_list[0].actual_value)
72                         row.append('%d' % (float(value) * 100))  # Result
73                     else:
74                         row.append('100')  # Result
75
76                     if agreement.guaranteestatus == "VIOLATED":
77                         row.append('false')  # Ok
78
79                     if agreement.guaranteestatus == "FULFILLED":
80                         row.append('true')  # Ok
81
82             for _, terms in agreement.guaranteeterms.items():
83                 try:
84                     s = ast.literal_eval(terms.scopes[0].scope.lstrip())
85                     logger.debug('SLA scope: {}'.format(s))
86                     row.append(s)
87                     break
88                 except Exception as e:
89                     logger.debug("SLA EXCEPTION: {}".format(e.message))
90
91             ag_info.append(dict(zip(keys, row)))
92
93         template_env = {}
94         # write something of our own instead
95         # more general variables expected in the template
96         template_env['title'] = 'SLA Agreements'
97         template_env['agreements'] = agreements
98         template_env['username'] = request.user
99         template_env['slicename'] = slicename
100         template_env['enforcements'] = enforcements
101         template_env['last_violation_list'] = violations
102         template_env['ag_info'] = ag_info
103
104         # the prelude object in page contains a summary of the requirements() for all plugins
105         # define {js,css}_{files,chunks}
106         prelude_env = page.prelude_env()
107         template_env.update(prelude_env)
108
109         return render_to_response(self.template_name, template_env, context_instance=RequestContext(request))
110
111
112 def _get_agreements_client():
113     return restclient.Factory.agreements()
114
115
116 def _get_violations_client():
117     return restclient.Factory.violations()
118
119
120 def _get_enforcements_client():
121     return restclient.Factory.enforcements()
122
123
124 def _get_consumer_id(request):
125     return request.user
126
127
128 def _get_agreement(agreement_id):
129     agreements_client = _get_agreements_client()
130     agreement, response = agreements_client.getbyid(agreement_id)
131     return agreement
132
133
134 def _get_enforcement(agreement_id, testbed):
135     enforcements_client = _get_enforcements_client()
136     enforcement, response = enforcements_client.getbyagreement(agreement_id, testbed)
137     return enforcement
138
139
140 def agreement_term_violations(request, agreement_id, guarantee_name):
141     page = Page(request)
142     prelude_env = page.prelude_env()
143
144     annotator = wsag_helper.AgreementAnnotator()
145     agreement = _get_agreement(agreement_id)
146     violations = _get_agreement_violations(agreement_id, guarantee_name)
147     annotator.annotate_agreement(agreement)
148
149     slicename = request.POST.get('slicename')
150
151     paginator = Paginator(violations, 25)  # Show 25 violations per page
152     page_num = request.GET.get('page')
153
154     try:
155         violation_page = paginator.page(page_num)
156     except PageNotAnInteger:
157         # If page is not an integer, deliver first page.
158         violation_page = paginator.page(1)
159     except EmptyPage:
160         # If page is out of range (e.g. 9999), deliver first page.
161         violation_page = paginator.page(1)
162
163     context = {
164         'agreement_id': agreement_id,
165         'guarantee_term': agreement.guaranteeterms[guarantee_name],
166         'violations': violation_page,
167         'agreement': agreement,
168         'slicename': slicename,
169         'last_violation': violations[-1].actual_value
170     }
171
172     context.update(prelude_env)
173
174     return render_to_response('violations_template.html', context, context_instance=RequestContext(request))
175
176
177 # TODO Change function to class
178 def agreement_details(request, agreement_id):
179     page = Page(request)
180     prelude_env = page.prelude_env()
181
182     annotator = wsag_helper.AgreementAnnotator()
183     agreement = _get_agreement(agreement_id)
184     violations = _get_agreement_violations(agreement_id)
185     status = _get_agreement_status(agreement_id)
186     annotator.annotate_agreement(agreement, status, violations)
187
188     violations_by_date = wsag_helper.get_violations_bydate(violations)
189     context = {
190         'agreement_id': agreement_id,
191         'agreement': agreement,
192         'status': status,
193         'violations_by_date': violations_by_date
194     }
195
196     context.update(prelude_env)
197
198     return render_to_response('violations_template.html', context, context_instance=RequestContext(request))
199     #return render(request, 'agreement_detail.html', context)
200
201
202 def _get_agreements_by_slice(slice):
203     agreements_client = _get_agreements_client()
204     agreements, response = agreements_client.getbyslice(slice)
205
206     annotator = wsag_helper.AgreementAnnotator()
207     for agreement in agreements:
208         id_ = agreement.agreement_id
209         testbed = agreement.context.provider
210         status = _get_agreement_status(id_, testbed)
211         annotator.annotate_agreement(agreement, status)
212
213     return agreements
214
215
216 def _get_agreement_status(agreement_id, testbed):
217     agreements_client = _get_agreements_client()
218     status, response = agreements_client.getstatus(agreement_id, testbed)
219     return status
220
221
222 def _get_agreement_violations(agreement_id, testbed, term=None):
223     violations_client = _get_violations_client()
224     violations, response = violations_client.getbyagreement(agreement_id, testbed, term)
225     return violations
226
227
228 class Testbeds(FreeAccessView, ThemeView):
229     def get(self, request, *args, **kwargs):
230         c = restclient.Client(SLA_COLLECTOR_URL)
231         #url = settings.SLA_MANAGER_URL.replace("/sla","")
232         #c = restclient.Client(url)
233         # print "**** URL ******", url
234         SLAtestbeds = c.get("testbeds/")
235         # Future work: get SLA description for each testbed
236
237         return HttpResponse(SLAtestbeds.text, content_type="application/json", status=SLAtestbeds.status_code)
238
239
240 class AgreementTemplates(FreeAccessView, ThemeView):
241     def get(self, request, *args, **kwargs):
242         c = restclient.Templates(SLA_COLLECTOR_URL)
243         testbed = kwargs.get('testbed', None)
244
245         templates, response = c.getall(testbed)
246         service_level_objectives = []
247
248         for template in templates:
249             service_level_objectives.append(
250                 [v.servicelevelobjective for v in template.guaranteeterms.values()])
251
252         return HttpResponse(service_level_objectives, content_type="application/json", status=response.status_code)
253
254 class CreateAgreement(LoginRequiredView, ThemeView):
255     def post(self, request, *args, **kwargs):
256
257         c = restclient.Client(SLA_COLLECTOR_URL)
258         data = request.POST.copy()
259
260         testbed_urn_regex = r"\+(.*?)\+"
261         pattern = re.compile(testbed_urn_regex)
262         testbed_urn = pattern.search(data["SLIVER_INFO_AGGREGATE_URN"]).group(1)
263
264         # Fix for django QueryDict list parameters
265         slivers = data.getlist("SLIVER_INFO_URN[]")
266         data["SLIVER_INFO_URN"] = slivers
267         del data["SLIVER_INFO_URN[]"]
268
269         # Timestamp to ISO date + timezone
270         tstmp = data["SLIVER_INFO_EXPIRATION"]
271         dt = datetime.fromtimestamp(float(tstmp))
272         # gmt_2 = pytz.timezone("Etc/GMT-2")
273         # dlocal = gmt_2.localize(dt).isoformat()
274         dlocal = dt.isoformat() + "CET"
275         data["SLIVER_INFO_EXPIRATION"] = dlocal
276
277         # logger.debug("SLA Agreement parameters: {}".format(data.dict()))
278         # import pdb; pdb.set_trace()
279
280         try:
281             response = c.post("agreementslist/", data=json.dumps(data),
282                               headers={"accept": "application/json",
283                                  "content-type": "application/json"})
284         except Exception as e:
285             # import traceback, sys
286             #
287             # traceback.print_exc(file=sys.stdout)
288             logger.debug("SLA Error: CreateAgreement {}".format(e.message))
289
290         return HttpResponse(response.text, status=response.status_code)