Merge "Removing SELINUX class from server manifest"
[releng.git] / utils / test / reporting / utils / reporting_utils.py
1 #!/usr/bin/python
2 #
3 # This program and the accompanying materials
4 # are made available under the terms of the Apache License, Version 2.0
5 # which accompanies this distribution, and is available at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 from urllib2 import Request, urlopen, URLError
10 import logging
11 import json
12 import os
13 import pdfkit
14 import yaml
15
16
17 # ----------------------------------------------------------
18 #
19 #               YAML UTILS
20 #
21 # -----------------------------------------------------------
22 def get_parameter_from_yaml(parameter, file):
23     """
24     Returns the value of a given parameter in file.yaml
25     parameter must be given in string format with dots
26     Example: general.openstack.image_name
27     """
28     with open(file) as f:
29         file_yaml = yaml.safe_load(f)
30     f.close()
31     value = file_yaml
32     for element in parameter.split("."):
33         value = value.get(element)
34         if value is None:
35             raise ValueError("The parameter %s is not defined in"
36                              " reporting.yaml" % parameter)
37     return value
38
39
40 def get_config(parameter):
41     yaml_ = os.environ["CONFIG_REPORTING_YAML"]
42     return get_parameter_from_yaml(parameter, yaml_)
43
44
45 # ----------------------------------------------------------
46 #
47 #               LOGGER UTILS
48 #
49 # -----------------------------------------------------------
50 def getLogger(module):
51     logFormatter = logging.Formatter("%(asctime)s [" +
52                                      module +
53                                      "] [%(levelname)-5.5s]  %(message)s")
54     logger = logging.getLogger()
55     log_file = get_config('general.log.log_file')
56     log_level = get_config('general.log.log_level')
57
58     fileHandler = logging.FileHandler("{0}/{1}".format('.', log_file))
59     fileHandler.setFormatter(logFormatter)
60     logger.addHandler(fileHandler)
61
62     consoleHandler = logging.StreamHandler()
63     consoleHandler.setFormatter(logFormatter)
64     logger.addHandler(consoleHandler)
65     logger.setLevel(log_level)
66     return logger
67
68
69 # ----------------------------------------------------------
70 #
71 #               REPORTING UTILS
72 #
73 # -----------------------------------------------------------
74 def getApiResults(case, installer, scenario, version):
75     results = json.dumps([])
76     # to remove proxy (to be removed at the end for local test only)
77     # proxy_handler = urllib2.ProxyHandler({})
78     # opener = urllib2.build_opener(proxy_handler)
79     # urllib2.install_opener(opener)
80     # url = "http://127.0.0.1:8000/results?case=" + case + \
81     #       "&period=30&installer=" + installer
82     period = get_config('general.period')
83     url_base = get_config('testapi.url')
84     nb_tests = get_config('general.nb_iteration_tests_success_criteria')
85
86     url = ("http://" + url_base + "?case=" + case +
87            "&period=" + str(period) + "&installer=" + installer +
88            "&scenario=" + scenario + "&version=" + version +
89            "&last=" + str(nb_tests))
90     request = Request(url)
91
92     try:
93         response = urlopen(request)
94         k = response.read()
95         results = json.loads(k)
96     except URLError as e:
97         print('No kittez. Got an error code:', e)
98
99     return results
100
101
102 def getScenarios(case, installer, version):
103
104     try:
105         case = case.getName()
106     except:
107         # if case is not an object test case, try the string
108         if type(case) == str:
109             case = case
110         else:
111             raise ValueError("Case cannot be evaluated")
112
113     period = get_config('general.period')
114     url_base = get_config('testapi.url')
115
116     url = ("http://" + url_base + "?case=" + case +
117            "&period=" + str(period) + "&installer=" + installer +
118            "&version=" + version)
119     request = Request(url)
120
121     try:
122         response = urlopen(request)
123         k = response.read()
124         results = json.loads(k)
125         test_results = results['results']
126     except URLError as e:
127         print('Got an error code:', e)
128
129     if test_results is not None:
130         test_results.reverse()
131
132         scenario_results = {}
133
134         for r in test_results:
135             # Retrieve all the scenarios per installer
136             if not r['scenario'] in scenario_results.keys():
137                 scenario_results[r['scenario']] = []
138             # Do we consider results from virtual pods ...
139             # Do we consider results for non HA scenarios...
140             exclude_virtual_pod = get_config('functest.exclude_virtual')
141             exclude_noha = get_config('functest.exclude_noha')
142             if ((exclude_virtual_pod and "virtual" in r['pod_name']) or
143                     (exclude_noha and "noha" in r['scenario'])):
144                 print("exclude virtual pod results...")
145             else:
146                 scenario_results[r['scenario']].append(r)
147
148     return scenario_results
149
150
151 def getScenarioStats(scenario_results):
152     scenario_stats = {}
153     for k, v in scenario_results.iteritems():
154         scenario_stats[k] = len(v)
155
156     return scenario_stats
157
158
159 # TODO convergence with above function getScenarios
160 def getScenarioStatus(installer, version):
161     period = get_config('general.period')
162     url_base = get_config('testapi.url')
163
164     url = ("http://" + url_base + "?case=scenario_status" +
165            "&installer=" + installer +
166            "&version=" + version + "&period=" + str(period))
167     request = Request(url)
168
169     try:
170         response = urlopen(request)
171         k = response.read()
172         response.close()
173         results = json.loads(k)
174         test_results = results['results']
175     except URLError as e:
176         print('Got an error code:', e)
177
178     scenario_results = {}
179     result_dict = {}
180     if test_results is not None:
181         for r in test_results:
182             if r['stop_date'] != 'None' and r['criteria'] is not None:
183                 if not r['scenario'] in scenario_results.keys():
184                     scenario_results[r['scenario']] = []
185                 scenario_results[r['scenario']].append(r)
186
187         for k, v in scenario_results.items():
188             # scenario_results[k] = v[:LASTEST_TESTS]
189             s_list = []
190             for element in v:
191                 if element['criteria'] == 'SUCCESS':
192                     s_list.append(1)
193                 else:
194                     s_list.append(0)
195             result_dict[k] = s_list
196
197     # return scenario_results
198     return result_dict
199
200
201 def getNbtestOk(results):
202     nb_test_ok = 0
203     for r in results:
204         for k, v in r.iteritems():
205             try:
206                 if "PASS" in v:
207                     nb_test_ok += 1
208             except:
209                 print("Cannot retrieve test status")
210     return nb_test_ok
211
212
213 def getResult(testCase, installer, scenario, version):
214
215     # retrieve raw results
216     results = getApiResults(testCase, installer, scenario, version)
217     # let's concentrate on test results only
218     test_results = results['results']
219
220     # if results found, analyze them
221     if test_results is not None:
222         test_results.reverse()
223
224         scenario_results = []
225
226         # print " ---------------- "
227         # print test_results
228         # print " ---------------- "
229         # print "nb of results:" + str(len(test_results))
230
231         for r in test_results:
232             # print r["start_date"]
233             # print r["criteria"]
234             scenario_results.append({r["start_date"]: r["criteria"]})
235         # sort results
236         scenario_results.sort()
237         # 4 levels for the results
238         # 3: 4+ consecutive runs passing the success criteria
239         # 2: <4 successful consecutive runs but passing the criteria
240         # 1: close to pass the success criteria
241         # 0: 0% success, not passing
242         # -1: no run available
243         test_result_indicator = 0
244         nbTestOk = getNbtestOk(scenario_results)
245
246         # print "Nb test OK (last 10 days):"+ str(nbTestOk)
247         # check that we have at least 4 runs
248         if len(scenario_results) < 1:
249             # No results available
250             test_result_indicator = -1
251         elif nbTestOk < 1:
252             test_result_indicator = 0
253         elif nbTestOk < 2:
254             test_result_indicator = 1
255         else:
256             # Test the last 4 run
257             if (len(scenario_results) > 3):
258                 last4runResults = scenario_results[-4:]
259                 nbTestOkLast4 = getNbtestOk(last4runResults)
260                 # print "Nb test OK (last 4 run):"+ str(nbTestOkLast4)
261                 if nbTestOkLast4 > 3:
262                     test_result_indicator = 3
263                 else:
264                     test_result_indicator = 2
265             else:
266                 test_result_indicator = 2
267     return test_result_indicator
268
269
270 def getJenkinsUrl(build_tag):
271     # e.g. jenkins-functest-apex-apex-daily-colorado-daily-colorado-246
272     # id = 246
273     # jenkins-functest-compass-huawei-pod5-daily-master-136
274     # id = 136
275     # note it is linked to jenkins format
276     # if this format changes...function to be adapted....
277     url_base = get_config('functest.jenkins_url')
278     try:
279         build_id = [int(s) for s in build_tag.split("-") if s.isdigit()]
280         url_id = (build_tag[8:-(len(str(build_id[0])) + 1)] +
281                   "/" + str(build_id[0]))
282         jenkins_url = url_base + url_id + "/console"
283     except:
284         print('Impossible to get jenkins url:')
285
286     return jenkins_url
287
288
289 def getScenarioPercent(scenario_score, scenario_criteria):
290     score = 0.0
291     try:
292         score = float(scenario_score) / float(scenario_criteria) * 100
293     except:
294         print('Impossible to calculate the percentage score')
295     return score
296
297
298 # *********
299 # Yardstick
300 # *********
301 def subfind(given_list, pattern_list):
302     LASTEST_TESTS = get_config('general.nb_iteration_tests_success_criteria')
303     for i in range(len(given_list)):
304         if given_list[i] == pattern_list[0] and \
305                 given_list[i:i + LASTEST_TESTS] == pattern_list:
306             return True
307     return False
308
309
310 def _get_percent(status):
311
312     if status * 100 % 6:
313         return round(float(status) * 100 / 6, 1)
314     else:
315         return status * 100 / 6
316
317
318 def get_percent(four_list, ten_list):
319     four_score = 0
320     ten_score = 0
321
322     for v in four_list:
323         four_score += v
324     for v in ten_list:
325         ten_score += v
326
327     LASTEST_TESTS = get_config('general.nb_iteration_tests_success_criteria')
328     if four_score == LASTEST_TESTS:
329         status = 6
330     elif subfind(ten_list, [1, 1, 1, 1]):
331         status = 5
332     elif ten_score == 0:
333         status = 0
334     else:
335         status = four_score + 1
336
337     return _get_percent(status)
338
339
340 def _test():
341     status = getScenarioStatus("compass", "master")
342     print("status:++++++++++++++++++++++++")
343     print(json.dumps(status, indent=4))
344
345
346 # ----------------------------------------------------------
347 #
348 #               Export
349 #
350 # -----------------------------------------------------------
351
352 def export_csv(scenario_file_name, installer, version):
353     # csv
354     # generate sub files based on scenario_history.txt
355     scenario_installer_file_name = ("./display/" + version +
356                                     "/functest/scenario_history_" +
357                                     installer + ".csv")
358     scenario_installer_file = open(scenario_installer_file_name, "a")
359     with open(scenario_file_name, "r") as f:
360         scenario_installer_file.write("date,scenario,installer,detail,score\n")
361         for line in f:
362             if installer in line:
363                 scenario_installer_file.write(line)
364         scenario_installer_file.close
365
366
367 def export_pdf(pdf_path, pdf_doc_name):
368     try:
369         pdfkit.from_file(pdf_path, pdf_doc_name)
370     except IOError:
371         print("Error but pdf generated anyway...")
372     except:
373         print("impossible to generate PDF")