3 # jose.lausuch@ericsson.com
4 # valentin.boucher@orange.com
5 # All rights reserved. This program and the accompanying materials
6 # are made available under the terms of the Apache License, Version 2.0
7 # which accompanies this distribution, and is available at
8 # http://www.apache.org/licenses/LICENSE-2.0
19 from datetime import datetime as dt
26 import functest.utils.functest_logger as ft_logger
28 logger = ft_logger.Logger("functest_utils").getLogger()
31 # ----------------------------------------------------------
35 # -----------------------------------------------------------
36 def check_internet_connectivity(url='http://www.opnfv.org/'):
38 Check if there is access to the internet
41 urllib2.urlopen(url, timeout=5)
43 except urllib2.URLError:
47 def download_url(url, dest_path):
49 Download a file to a destination path given a URL
51 name = url.rsplit('/')[-1]
52 dest = dest_path + "/" + name
54 response = urllib2.urlopen(url)
55 except (urllib2.HTTPError, urllib2.URLError):
58 with open(dest, 'wb') as f:
59 shutil.copyfileobj(response, f)
63 # ----------------------------------------------------------
67 # -----------------------------------------------------------
68 def get_git_branch(repo_path):
72 repo = Repo(repo_path)
73 branch = repo.active_branch
77 def get_installer_type():
79 Get installer type (fuel, apex, joid, compass)
82 installer = os.environ['INSTALLER_TYPE']
84 logger.error("Impossible to retrieve the installer type")
85 installer = "Unknown_installer"
95 scenario = os.environ['DEPLOY_SCENARIO']
97 logger.error("Impossible to retrieve the scenario")
98 scenario = "Unknown_scenario"
107 # Use the build tag to retrieve the version
108 # By default version is unknown
109 # if launched through CI the build tag has the following format
110 # jenkins-<project>-<installer>-<pod>-<job>-<branch>-<id>
111 # e.g. jenkins-functest-fuel-opnfv-jump-2-daily-master-190
112 # use regex to match branch info
113 rule = "daily-(.+?)-[0-9]*"
114 build_tag = get_build_tag()
115 m = re.search(rule, build_tag)
124 Get PoD Name from env variable NODE_NAME
127 return os.environ['NODE_NAME']
130 "Unable to retrieve the POD name from environment. " +
131 "Using pod name 'unknown-pod'")
137 Get build tag of jenkins jobs
140 build_tag = os.environ['BUILD_TAG']
142 logger.error("Impossible to retrieve the build tag")
143 build_tag = "unknown_build_tag"
152 return get_functest_config('results.test_db_url')
155 def logger_test_results(project, case_name, status, details):
156 pod_name = get_pod_name()
157 scenario = get_scenario()
158 version = get_version()
159 build_tag = get_build_tag()
163 "****************************************\n"
164 "\t %(p)s/%(n)s results \n\n"
165 "****************************************\n"
171 "build tag:\t%(b)s\n"
184 def push_results_to_db(project, case_name,
185 start_date, stop_date, criteria, details):
187 POST results to the Result target DB
189 # Retrieve params from CI and conf
190 url = get_db_url() + "/results"
193 installer = os.environ['INSTALLER_TYPE']
194 scenario = os.environ['DEPLOY_SCENARIO']
195 pod_name = os.environ['NODE_NAME']
196 build_tag = os.environ['BUILD_TAG']
197 except KeyError as e:
198 logger.error("Please set env var: " + str(e))
200 rule = "daily-(.+?)-[0-9]*"
201 m = re.search(rule, build_tag)
205 logger.error("Please fix BUILD_TAG env var: " + build_tag)
207 test_start = dt.fromtimestamp(start_date).strftime('%Y-%m-%d %H:%M:%S')
208 test_stop = dt.fromtimestamp(stop_date).strftime('%Y-%m-%d %H:%M:%S')
210 params = {"project_name": project, "case_name": case_name,
211 "pod_name": pod_name, "installer": installer,
212 "version": version, "scenario": scenario, "criteria": criteria,
213 "build_tag": build_tag, "start_date": test_start,
214 "stop_date": test_stop, "details": details}
217 headers = {'Content-Type': 'application/json'}
219 r = requests.post(url, data=json.dumps(params), headers=headers)
222 except requests.RequestException as exc:
224 error = ("Pushing Result to DB(%s) failed: %s" %
227 error = ("Pushing Result to DB(%s) failed: %s" % (url, exc))
228 except Exception as e:
229 error = ("Error [push_results_to_db("
231 "project: '%(project)s', "
235 "scenario: '%(s)s', "
236 "criteria: '%(c)s', "
237 "build_tag: '%(t)s', "
238 "details: '%(d)s')]: "
259 def get_resolvconf_ns():
261 Get nameservers from current resolv.conf
264 rconf = open("/etc/resolv.conf", "r")
265 line = rconf.readline()
266 resolver = dns.resolver.Resolver()
268 ip = re.search(r"\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b", line)
270 resolver.nameservers = [str(ip)]
272 result = resolver.query('opnfv.org')[0]
274 nameservers.append(ip.group())
275 except dns.exception.Timeout:
277 line = rconf.readline()
281 def get_ci_envvars():
283 Get the CI env variables
286 "installer": os.environ.get('INSTALLER_TYPE'),
287 "scenario": os.environ.get('DEPLOY_SCENARIO')}
291 def execute_command(cmd, info=False, error_msg="",
292 verbose=True, output_file=None):
294 error_msg = ("The command '%s' failed." % cmd)
295 msg_exec = ("Executing command: '%s'" % cmd)
298 logger.info(msg_exec)
300 logger.debug(msg_exec)
301 p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
302 stderr=subprocess.STDOUT)
304 f = open(output_file, "w")
305 for line in iter(p.stdout.readline, b''):
309 line = line.replace('\n', '')
315 returncode = p.wait()
318 logger.error(error_msg)
323 def get_dict_by_test(testname):
324 with open(get_testcases_file_dir()) as f:
325 testcases_yaml = yaml.safe_load(f)
327 for dic_tier in testcases_yaml.get("tiers"):
328 for dic_testcase in dic_tier['testcases']:
329 if dic_testcase['name'] == testname:
332 logger.error('Project %s is not defined in testcases.yaml' % testname)
336 def get_criteria_by_test(testname):
337 dict = get_dict_by_test(testname)
339 return dict['criteria']
343 # ----------------------------------------------------------
347 # -----------------------------------------------------------
348 def get_parameter_from_yaml(parameter, file):
350 Returns the value of a given parameter in file.yaml
351 parameter must be given in string format with dots
352 Example: general.openstack.image_name
354 with open(file) as f:
355 file_yaml = yaml.safe_load(f)
358 for element in parameter.split("."):
359 value = value.get(element)
361 raise ValueError("The parameter %s is not defined in"
362 " config_functest.yaml" % parameter)
366 def get_functest_config(parameter):
367 yaml_ = os.environ["CONFIG_FUNCTEST_YAML"]
368 return get_parameter_from_yaml(parameter, yaml_)
371 def check_success_rate(case_name, success_rate):
372 success_rate = float(success_rate)
373 criteria = get_criteria_by_test(case_name)
375 def get_criteria_value(op):
376 return float(criteria.split(op)[1].rstrip('%'))
382 c_value = get_criteria_value(op)
383 if eval("%s %s %s" % (success_rate, op, c_value)):
390 def merge_dicts(dict1, dict2):
391 for k in set(dict1.keys()).union(dict2.keys()):
392 if k in dict1 and k in dict2:
393 if isinstance(dict1[k], dict) and isinstance(dict2[k], dict):
394 yield (k, dict(merge_dicts(dict1[k], dict2[k])))
403 def get_testcases_file_dir():
404 return get_functest_config('general.functest.testcases_yaml')
407 def get_functest_yaml():
408 with open(os.environ["CONFIG_FUNCTEST_YAML"]) as f:
409 functest_yaml = yaml.safe_load(f)
414 def print_separator():
415 logger.info("==============================================")
419 """Measure the time it takes for a function to complete"""
420 @functools.wraps(func)
421 def timed(*args, **kwargs):
423 result = func(*args, **kwargs)
425 elapsed = '{0}'.format(te - ts)
426 logger.info('{f}(*{a}, **{kw}) took: {t} sec'.format(
427 f=func.__name__, a=args, kw=kwargs, t=elapsed))
428 return result, elapsed