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
18 # ----------------------------------------------------------
22 # -----------------------------------------------------------
23 def get_parameter_from_yaml(parameter, file):
25 Returns the value of a given parameter in file.yaml
26 parameter must be given in string format with dots
27 Example: general.openstack.image_name
30 file_yaml = yaml.safe_load(f)
33 for element in parameter.split("."):
34 value = value.get(element)
36 raise ValueError("The parameter %s is not defined in"
37 " reporting.yaml" % parameter)
41 def get_config(parameter):
42 yaml_ = os.environ["CONFIG_REPORTING_YAML"]
43 return get_parameter_from_yaml(parameter, yaml_)
46 # ----------------------------------------------------------
50 # -----------------------------------------------------------
51 def getLogger(module):
52 logFormatter = logging.Formatter("%(asctime)s [" +
54 "] [%(levelname)-5.5s] %(message)s")
55 logger = logging.getLogger()
56 log_file = get_config('general.log.log_file')
57 log_level = get_config('general.log.log_level')
59 fileHandler = logging.FileHandler("{0}/{1}".format('.', log_file))
60 fileHandler.setFormatter(logFormatter)
61 logger.addHandler(fileHandler)
63 consoleHandler = logging.StreamHandler()
64 consoleHandler.setFormatter(logFormatter)
65 logger.addHandler(consoleHandler)
66 logger.setLevel(log_level)
70 # ----------------------------------------------------------
74 # -----------------------------------------------------------
75 def getApiResults(case, installer, scenario, version):
76 results = json.dumps([])
77 # to remove proxy (to be removed at the end for local test only)
78 # proxy_handler = urllib2.ProxyHandler({})
79 # opener = urllib2.build_opener(proxy_handler)
80 # urllib2.install_opener(opener)
81 # url = "http://127.0.0.1:8000/results?case=" + case + \
82 # "&period=30&installer=" + installer
83 period = get_config('general.period')
84 url_base = get_config('testapi.url')
85 nb_tests = get_config('general.nb_iteration_tests_success_criteria')
87 url = ("http://" + url_base + "?case=" + case +
88 "&period=" + str(period) + "&installer=" + installer +
89 "&scenario=" + scenario + "&version=" + version +
90 "&last=" + str(nb_tests))
91 request = Request(url)
94 response = urlopen(request)
96 results = json.loads(k)
98 print('No kittez. Got an error code:', e)
103 def getScenarios(case, installer, version):
106 case = case.getName()
108 # if case is not an object test case, try the string
109 if type(case) == str:
112 raise ValueError("Case cannot be evaluated")
114 period = get_config('general.period')
115 url_base = get_config('testapi.url')
117 url = ("http://" + url_base + "?case=" + case +
118 "&period=" + str(period) + "&installer=" + installer +
119 "&version=" + version)
120 request = Request(url)
123 response = urlopen(request)
125 results = json.loads(k)
126 test_results = results['results']
127 except URLError as e:
128 print('Got an error code:', e)
130 if test_results is not None:
131 test_results.reverse()
133 scenario_results = {}
135 for r in test_results:
136 # Retrieve all the scenarios per installer
137 if not r['scenario'] in scenario_results.keys():
138 scenario_results[r['scenario']] = []
139 # Do we consider results from virtual pods ...
140 # Do we consider results for non HA scenarios...
141 exclude_virtual_pod = get_config('functest.exclude_virtual')
142 exclude_noha = get_config('functest.exclude_noha')
143 if ((exclude_virtual_pod and "virtual" in r['pod_name']) or
144 (exclude_noha and "noha" in r['scenario'])):
145 print("exclude virtual pod results...")
147 scenario_results[r['scenario']].append(r)
149 return scenario_results
152 def getScenarioStats(scenario_results):
154 for k, v in scenario_results.iteritems():
155 scenario_stats[k] = len(v)
157 return scenario_stats
160 # TODO convergence with above function getScenarios
161 def getScenarioStatus(installer, version):
162 period = get_config('general.period')
163 url_base = get_config('testapi.url')
165 url = ("http://" + url_base + "?case=scenario_status" +
166 "&installer=" + installer +
167 "&version=" + version + "&period=" + str(period))
168 request = Request(url)
171 response = urlopen(request)
174 results = json.loads(k)
175 test_results = results['results']
176 except URLError as e:
177 print('Got an error code:', e)
179 scenario_results = {}
181 if test_results is not None:
182 for r in test_results:
183 if r['stop_date'] != 'None' and r['criteria'] is not None:
184 if not r['scenario'] in scenario_results.keys():
185 scenario_results[r['scenario']] = []
186 scenario_results[r['scenario']].append(r)
188 for k, v in scenario_results.items():
189 # scenario_results[k] = v[:LASTEST_TESTS]
192 if element['criteria'] == 'SUCCESS':
196 result_dict[k] = s_list
198 # return scenario_results
202 def getQtipResults(version, installer):
203 period = get_config('qtip.period')
204 url_base = get_config('testapi.url')
206 url = ("http://" + url_base + "?project=qtip" +
207 "&installer=" + installer +
208 "&version=" + version + "&period=" + str(period))
209 request = Request(url)
212 response = urlopen(request)
215 results = json.loads(k)['results']
216 except URLError as e:
217 print('Got an error code:', e)
222 key = '{}/{}'.format(r['pod_name'], r['scenario'])
223 if key not in result_dict.keys():
224 result_dict[key] = []
225 result_dict[key].append(r['details']['score'])
227 # return scenario_results
231 def getNbtestOk(results):
234 for k, v in r.iteritems():
239 print("Cannot retrieve test status")
243 def getResult(testCase, installer, scenario, version):
245 # retrieve raw results
246 results = getApiResults(testCase, installer, scenario, version)
247 # let's concentrate on test results only
248 test_results = results['results']
250 # if results found, analyze them
251 if test_results is not None:
252 test_results.reverse()
254 scenario_results = []
256 # print " ---------------- "
258 # print " ---------------- "
259 # print "nb of results:" + str(len(test_results))
261 for r in test_results:
262 # print r["start_date"]
263 # print r["criteria"]
264 scenario_results.append({r["start_date"]: r["criteria"]})
266 scenario_results.sort()
267 # 4 levels for the results
268 # 3: 4+ consecutive runs passing the success criteria
269 # 2: <4 successful consecutive runs but passing the criteria
270 # 1: close to pass the success criteria
271 # 0: 0% success, not passing
272 # -1: no run available
273 test_result_indicator = 0
274 nbTestOk = getNbtestOk(scenario_results)
276 # print "Nb test OK (last 10 days):"+ str(nbTestOk)
277 # check that we have at least 4 runs
278 if len(scenario_results) < 1:
279 # No results available
280 test_result_indicator = -1
282 test_result_indicator = 0
284 test_result_indicator = 1
286 # Test the last 4 run
287 if (len(scenario_results) > 3):
288 last4runResults = scenario_results[-4:]
289 nbTestOkLast4 = getNbtestOk(last4runResults)
290 # print "Nb test OK (last 4 run):"+ str(nbTestOkLast4)
291 if nbTestOkLast4 > 3:
292 test_result_indicator = 3
294 test_result_indicator = 2
296 test_result_indicator = 2
297 return test_result_indicator
300 def getJenkinsUrl(build_tag):
301 # e.g. jenkins-functest-apex-apex-daily-colorado-daily-colorado-246
303 # jenkins-functest-compass-huawei-pod5-daily-master-136
305 # note it is linked to jenkins format
306 # if this format changes...function to be adapted....
307 url_base = get_config('functest.jenkins_url')
309 build_id = [int(s) for s in build_tag.split("-") if s.isdigit()]
310 url_id = (build_tag[8:-(len(str(build_id[0])) + 1)] +
311 "/" + str(build_id[0]))
312 jenkins_url = url_base + url_id + "/console"
314 print('Impossible to get jenkins url:')
316 if "jenkins-" not in build_tag:
322 def getScenarioPercent(scenario_score, scenario_criteria):
325 score = float(scenario_score) / float(scenario_criteria) * 100
327 print('Impossible to calculate the percentage score')
334 def getFunctestConfig(version=""):
335 config_file = get_config('functest.test_conf') + version
336 response = requests.get(config_file)
337 return yaml.safe_load(response.text)
340 def getArchitectures(scenario_results):
341 supported_arch = ['x86']
342 if (len(scenario_results) > 0):
343 for scenario_result in scenario_results.values():
344 for value in scenario_result:
345 if ("armband" in value['build_tag']):
346 supported_arch.append('aarch64')
347 return supported_arch
348 return supported_arch
351 def filterArchitecture(results, architecture):
352 filtered_results = {}
353 for name, results in results.items():
355 for value in results:
356 if (architecture is "x86"):
357 # drop aarch64 results
358 if ("armband" not in value['build_tag']):
359 filtered_values.append(value)
360 elif(architecture is "aarch64"):
362 if ("armband" in value['build_tag']):
363 filtered_values.append(value)
364 if (len(filtered_values) > 0):
365 filtered_results[name] = filtered_values
366 return filtered_results
372 def subfind(given_list, pattern_list):
373 LASTEST_TESTS = get_config('general.nb_iteration_tests_success_criteria')
374 for i in range(len(given_list)):
375 if given_list[i] == pattern_list[0] and \
376 given_list[i:i + LASTEST_TESTS] == pattern_list:
381 def _get_percent(status):
384 return round(float(status) * 100 / 6, 1)
386 return status * 100 / 6
389 def get_percent(four_list, ten_list):
398 LASTEST_TESTS = get_config('general.nb_iteration_tests_success_criteria')
399 if four_score == LASTEST_TESTS:
401 elif subfind(ten_list, [1, 1, 1, 1]):
406 status = four_score + 1
408 return _get_percent(status)
412 status = getScenarioStatus("compass", "master")
413 print("status:++++++++++++++++++++++++")
414 print(json.dumps(status, indent=4))
417 # ----------------------------------------------------------
421 # -----------------------------------------------------------
423 def export_csv(scenario_file_name, installer, version):
425 # generate sub files based on scenario_history.txt
426 scenario_installer_file_name = ("./display/" + version +
427 "/functest/scenario_history_" +
429 scenario_installer_file = open(scenario_installer_file_name, "a")
430 with open(scenario_file_name, "r") as f:
431 scenario_installer_file.write("date,scenario,installer,detail,score\n")
433 if installer in line:
434 scenario_installer_file.write(line)
435 scenario_installer_file.close
438 def generate_csv(scenario_file):
441 # generate sub files based on scenario_history.txt
442 csv_file = scenario_file.replace('txt', 'csv')
443 shutil.copy2(scenario_file, csv_file)
446 def export_pdf(pdf_path, pdf_doc_name):
448 pdfkit.from_file(pdf_path, pdf_doc_name)
450 print("Error but pdf generated anyway...")
452 print("impossible to generate PDF")