0af60c78a715846f5df1aa8852e09732c6a74cbc
[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, e:
97         print 'No kittez. Got an error code:', e
98
99     return results
100
101
102 def getScenarios(case, installer, version):
103
104     case = case.getName()
105     period = get_config('general.period')
106     url_base = get_config('testapi.url')
107
108     url = ("http://" + url_base + "?case=" + case +
109            "&period=" + str(period) + "&installer=" + installer +
110            "&version=" + version)
111     request = Request(url)
112
113     try:
114         response = urlopen(request)
115         k = response.read()
116         results = json.loads(k)
117         test_results = results['results']
118     except URLError, e:
119         print 'Got an error code:', e
120
121     if test_results is not None:
122         test_results.reverse()
123
124         scenario_results = {}
125
126         for r in test_results:
127             # Retrieve all the scenarios per installer
128             if not r['scenario'] in scenario_results.keys():
129                 scenario_results[r['scenario']] = []
130             scenario_results[r['scenario']].append(r)
131
132     return scenario_results
133
134
135 def getScenarioStats(scenario_results):
136     scenario_stats = {}
137     for k, v in scenario_results.iteritems():
138         scenario_stats[k] = len(v)
139
140     return scenario_stats
141
142
143 # TODO convergence with above function getScenarios
144 def getScenarioStatus(installer, version):
145     period = get_config('general.period')
146     url_base = get_config('testapi.url')
147
148     url = ("http://" + url_base + "?case=scenario_status" +
149            "&installer=" + installer +
150            "&version=" + version + "&period=" + str(period))
151     request = Request(url)
152
153     try:
154         response = urlopen(request)
155         k = response.read()
156         response.close()
157         results = json.loads(k)
158         test_results = results['results']
159     except URLError, e:
160         print 'Got an error code:', e
161
162     scenario_results = {}
163     result_dict = {}
164     if test_results is not None:
165         for r in test_results:
166             if r['stop_date'] != 'None' and r['criteria'] is not None:
167                 if not r['scenario'] in scenario_results.keys():
168                     scenario_results[r['scenario']] = []
169                 scenario_results[r['scenario']].append(r)
170
171         for k, v in scenario_results.items():
172             # scenario_results[k] = v[:LASTEST_TESTS]
173             s_list = []
174             for element in v:
175                 if element['criteria'] == 'SUCCESS':
176                     s_list.append(1)
177                 else:
178                     s_list.append(0)
179             result_dict[k] = s_list
180
181     # return scenario_results
182     return result_dict
183
184
185 def getNbtestOk(results):
186     nb_test_ok = 0
187     for r in results:
188         for k, v in r.iteritems():
189             try:
190                 if "PASS" in v:
191                     nb_test_ok += 1
192             except:
193                 print "Cannot retrieve test status"
194     return nb_test_ok
195
196
197 def getResult(testCase, installer, scenario, version):
198
199     # retrieve raw results
200     results = getApiResults(testCase, installer, scenario, version)
201     # let's concentrate on test results only
202     test_results = results['results']
203
204     # if results found, analyze them
205     if test_results is not None:
206         test_results.reverse()
207
208         scenario_results = []
209
210         # print " ---------------- "
211         # print test_results
212         # print " ---------------- "
213         # print "nb of results:" + str(len(test_results))
214
215         for r in test_results:
216             # print r["start_date"]
217             # print r["criteria"]
218             scenario_results.append({r["start_date"]: r["criteria"]})
219         # sort results
220         scenario_results.sort()
221         # 4 levels for the results
222         # 3: 4+ consecutive runs passing the success criteria
223         # 2: <4 successful consecutive runs but passing the criteria
224         # 1: close to pass the success criteria
225         # 0: 0% success, not passing
226         # -1: no run available
227         test_result_indicator = 0
228         nbTestOk = getNbtestOk(scenario_results)
229
230         # print "Nb test OK (last 10 days):"+ str(nbTestOk)
231         # check that we have at least 4 runs
232         if len(scenario_results) < 1:
233             # No results available
234             test_result_indicator = -1
235         elif nbTestOk < 1:
236             test_result_indicator = 0
237         elif nbTestOk < 2:
238             test_result_indicator = 1
239         else:
240             # Test the last 4 run
241             if (len(scenario_results) > 3):
242                 last4runResults = scenario_results[-4:]
243                 nbTestOkLast4 = getNbtestOk(last4runResults)
244                 # print "Nb test OK (last 4 run):"+ str(nbTestOkLast4)
245                 if nbTestOkLast4 > 3:
246                     test_result_indicator = 3
247                 else:
248                     test_result_indicator = 2
249             else:
250                 test_result_indicator = 2
251     return test_result_indicator
252
253
254 def getJenkinsUrl(build_tag):
255     # e.g. jenkins-functest-apex-apex-daily-colorado-daily-colorado-246
256     # id = 246
257     # note it is linked to jenkins format
258     # if this format changes...function to be adapted....
259     url_base = get_config('functest.jenkins_url')
260     try:
261         build_id = [int(s) for s in build_tag.split("-") if s.isdigit()]
262         jenkins_path = filter(lambda c: not c.isdigit(), build_tag)
263         url_id = jenkins_path[8:-1] + "/" + str(build_id[0])
264         jenkins_url = url_base + url_id + "/console"
265     except:
266         print 'Impossible to get jenkins url:'
267
268     return jenkins_url
269
270
271 def getScenarioPercent(scenario_score, scenario_criteria):
272     score = 0.0
273     try:
274         score = float(scenario_score) / float(scenario_criteria) * 100
275     except:
276         print 'Impossible to calculate the percentage score'
277     return score
278
279
280 # *********
281 # Yardstick
282 # *********
283 def subfind(given_list, pattern_list):
284     LASTEST_TESTS = get_config('general.nb_iteration_tests_success_criteria')
285     for i in range(len(given_list)):
286         if given_list[i] == pattern_list[0] and \
287                 given_list[i:i + LASTEST_TESTS] == pattern_list:
288             return True
289     return False
290
291
292 def _get_percent(status):
293
294     if status * 100 % 6:
295         return round(float(status) * 100 / 6, 1)
296     else:
297         return status * 100 / 6
298
299
300 def get_percent(four_list, ten_list):
301     four_score = 0
302     ten_score = 0
303
304     for v in four_list:
305         four_score += v
306     for v in ten_list:
307         ten_score += v
308
309     LASTEST_TESTS = get_config('general.nb_iteration_tests_success_criteria')
310     if four_score == LASTEST_TESTS:
311         status = 6
312     elif subfind(ten_list, [1, 1, 1, 1]):
313         status = 5
314     elif ten_score == 0:
315         status = 0
316     else:
317         status = four_score + 1
318
319     return _get_percent(status)
320
321
322 def _test():
323     status = getScenarioStatus("compass", "master")
324     print "status:++++++++++++++++++++++++"
325     print json.dumps(status, indent=4)
326
327
328 # ----------------------------------------------------------
329 #
330 #               Export
331 #
332 # -----------------------------------------------------------
333
334 def export_csv(scenario_file_name, installer, version):
335     # csv
336     # generate sub files based on scenario_history.txt
337     scenario_installer_file_name = ("./display/" + version +
338                                     "/functest/scenario_history_" +
339                                     installer + ".csv")
340     scenario_installer_file = open(scenario_installer_file_name, "a")
341     with open(scenario_file_name, "r") as f:
342         scenario_installer_file.write("date,scenario,installer,detail,score\n")
343         for line in f:
344             if installer in line:
345                 scenario_installer_file.write(line)
346         scenario_installer_file.close
347
348
349 def export_pdf(pdf_path, pdf_doc_name):
350     try:
351         pdfkit.from_file(pdf_path, pdf_doc_name)
352     except IOError:
353         print("Error but pdf generated anyway...")
354     except:
355         print("impossible to generate PDF")