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
7 # http://www.apache.org/licenses/LICENSE-2.0
9 from urllib2 import Request, urlopen, URLError
17 # ----------------------------------------------------------
21 # -----------------------------------------------------------
22 def get_parameter_from_yaml(parameter, file):
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
29 file_yaml = yaml.safe_load(f)
32 for element in parameter.split("."):
33 value = value.get(element)
35 raise ValueError("The parameter %s is not defined in"
36 " reporting.yaml" % parameter)
40 def get_config(parameter):
41 yaml_ = os.environ["CONFIG_REPORTING_YAML"]
42 return get_parameter_from_yaml(parameter, yaml_)
45 # ----------------------------------------------------------
49 # -----------------------------------------------------------
50 def getLogger(module):
51 logFormatter = logging.Formatter("%(asctime)s [" +
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')
58 fileHandler = logging.FileHandler("{0}/{1}".format('.', log_file))
59 fileHandler.setFormatter(logFormatter)
60 logger.addHandler(fileHandler)
62 consoleHandler = logging.StreamHandler()
63 consoleHandler.setFormatter(logFormatter)
64 logger.addHandler(consoleHandler)
65 logger.setLevel(log_level)
69 # ----------------------------------------------------------
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')
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)
93 response = urlopen(request)
95 results = json.loads(k)
97 print('No kittez. Got an error code:', e)
102 def getScenarios(case, installer, version):
105 case = case.getName()
107 # if case is not an object test case, try the string
108 if type(case) == str:
111 raise ValueError("Case cannot be evaluated")
113 period = get_config('general.period')
114 url_base = get_config('testapi.url')
116 url = ("http://" + url_base + "?case=" + case +
117 "&period=" + str(period) + "&installer=" + installer +
118 "&version=" + version)
119 request = Request(url)
122 response = urlopen(request)
124 results = json.loads(k)
125 test_results = results['results']
126 except URLError as e:
127 print('Got an error code:', e)
129 if test_results is not None:
130 test_results.reverse()
132 scenario_results = {}
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...")
146 scenario_results[r['scenario']].append(r)
148 return scenario_results
151 def getScenarioStats(scenario_results):
153 for k, v in scenario_results.iteritems():
154 scenario_stats[k] = len(v)
156 return scenario_stats
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')
164 url = ("http://" + url_base + "?case=scenario_status" +
165 "&installer=" + installer +
166 "&version=" + version + "&period=" + str(period))
167 request = Request(url)
170 response = urlopen(request)
173 results = json.loads(k)
174 test_results = results['results']
175 except URLError as e:
176 print('Got an error code:', e)
178 scenario_results = {}
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)
187 for k, v in scenario_results.items():
188 # scenario_results[k] = v[:LASTEST_TESTS]
191 if element['criteria'] == 'SUCCESS':
195 result_dict[k] = s_list
197 # return scenario_results
201 def getQtipResults(version, installer):
202 period = get_config('qtip.period')
203 url_base = get_config('testapi.url')
205 url = ("http://" + url_base + "?project=qtip" +
206 "&installer=" + installer +
207 "&version=" + version + "&period=" + str(period))
208 request = Request(url)
211 response = urlopen(request)
214 results = json.loads(k)['results']
215 except URLError as e:
216 print('Got an error code:', e)
221 key = '{}/{}'.format(r['pod_name'], r['scenario'])
222 if key not in result_dict.keys():
223 result_dict[key] = []
224 result_dict[key].append(r['details']['score'])
226 # return scenario_results
230 def getNbtestOk(results):
233 for k, v in r.iteritems():
238 print("Cannot retrieve test status")
242 def getResult(testCase, installer, scenario, version):
244 # retrieve raw results
245 results = getApiResults(testCase, installer, scenario, version)
246 # let's concentrate on test results only
247 test_results = results['results']
249 # if results found, analyze them
250 if test_results is not None:
251 test_results.reverse()
253 scenario_results = []
255 # print " ---------------- "
257 # print " ---------------- "
258 # print "nb of results:" + str(len(test_results))
260 for r in test_results:
261 # print r["start_date"]
262 # print r["criteria"]
263 scenario_results.append({r["start_date"]: r["criteria"]})
265 scenario_results.sort()
266 # 4 levels for the results
267 # 3: 4+ consecutive runs passing the success criteria
268 # 2: <4 successful consecutive runs but passing the criteria
269 # 1: close to pass the success criteria
270 # 0: 0% success, not passing
271 # -1: no run available
272 test_result_indicator = 0
273 nbTestOk = getNbtestOk(scenario_results)
275 # print "Nb test OK (last 10 days):"+ str(nbTestOk)
276 # check that we have at least 4 runs
277 if len(scenario_results) < 1:
278 # No results available
279 test_result_indicator = -1
281 test_result_indicator = 0
283 test_result_indicator = 1
285 # Test the last 4 run
286 if (len(scenario_results) > 3):
287 last4runResults = scenario_results[-4:]
288 nbTestOkLast4 = getNbtestOk(last4runResults)
289 # print "Nb test OK (last 4 run):"+ str(nbTestOkLast4)
290 if nbTestOkLast4 > 3:
291 test_result_indicator = 3
293 test_result_indicator = 2
295 test_result_indicator = 2
296 return test_result_indicator
299 def getJenkinsUrl(build_tag):
300 # e.g. jenkins-functest-apex-apex-daily-colorado-daily-colorado-246
302 # jenkins-functest-compass-huawei-pod5-daily-master-136
304 # note it is linked to jenkins format
305 # if this format changes...function to be adapted....
306 url_base = get_config('functest.jenkins_url')
308 build_id = [int(s) for s in build_tag.split("-") if s.isdigit()]
309 url_id = (build_tag[8:-(len(str(build_id[0])) + 1)] +
310 "/" + str(build_id[0]))
311 jenkins_url = url_base + url_id + "/console"
313 print('Impossible to get jenkins url:')
315 if "jenkins-" not in build_tag:
321 def getScenarioPercent(scenario_score, scenario_criteria):
324 score = float(scenario_score) / float(scenario_criteria) * 100
326 print('Impossible to calculate the percentage score')
333 def subfind(given_list, pattern_list):
334 LASTEST_TESTS = get_config('general.nb_iteration_tests_success_criteria')
335 for i in range(len(given_list)):
336 if given_list[i] == pattern_list[0] and \
337 given_list[i:i + LASTEST_TESTS] == pattern_list:
342 def _get_percent(status):
345 return round(float(status) * 100 / 6, 1)
347 return status * 100 / 6
350 def get_percent(four_list, ten_list):
359 LASTEST_TESTS = get_config('general.nb_iteration_tests_success_criteria')
360 if four_score == LASTEST_TESTS:
362 elif subfind(ten_list, [1, 1, 1, 1]):
367 status = four_score + 1
369 return _get_percent(status)
373 status = getScenarioStatus("compass", "master")
374 print("status:++++++++++++++++++++++++")
375 print(json.dumps(status, indent=4))
378 # ----------------------------------------------------------
382 # -----------------------------------------------------------
384 def export_csv(scenario_file_name, installer, version):
386 # generate sub files based on scenario_history.txt
387 scenario_installer_file_name = ("./display/" + version +
388 "/functest/scenario_history_" +
390 scenario_installer_file = open(scenario_installer_file_name, "a")
391 with open(scenario_file_name, "r") as f:
392 scenario_installer_file.write("date,scenario,installer,detail,score\n")
394 if installer in line:
395 scenario_installer_file.write(line)
396 scenario_installer_file.close
399 def generate_csv(scenario_file):
402 # generate sub files based on scenario_history.txt
403 csv_file = scenario_file.replace('txt', 'csv')
404 shutil.copy2(scenario_file, csv_file)
407 def export_pdf(pdf_path, pdf_doc_name):
409 pdfkit.from_file(pdf_path, pdf_doc_name)
411 print("Error but pdf generated anyway...")
413 print("impossible to generate PDF")