Remove logger_test_results
[functest.git] / functest / utils / functest_utils.py
1 #!/usr/bin/env python
2 #
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
9 #
10 import functools
11 import json
12 import logging
13 import os
14 import pkg_resources
15 import re
16 import shutil
17 import subprocess
18 import sys
19 import time
20 from datetime import datetime as dt
21
22 import dns.resolver
23 import requests
24 from six.moves import urllib
25 import yaml
26
27 from functest.utils import constants
28 from functest.utils import decorators
29 from functest.utils.constants import CONST
30
31 logger = logging.getLogger(__name__)
32
33
34 # ----------------------------------------------------------
35 #
36 #               INTERNET UTILS
37 #
38 # -----------------------------------------------------------
39 def check_internet_connectivity(url='http://www.opnfv.org/'):
40     """
41     Check if there is access to the internet
42     """
43     try:
44         urllib.request.urlopen(url, timeout=5)
45         return True
46     except urllib.error.URLError:
47         return False
48
49
50 def download_url(url, dest_path):
51     """
52     Download a file to a destination path given a URL
53     """
54     name = url.rsplit('/')[-1]
55     dest = dest_path + "/" + name
56     try:
57         response = urllib.request.urlopen(url)
58     except (urllib.error.HTTPError, urllib.error.URLError):
59         return False
60
61     with open(dest, 'wb') as f:
62         shutil.copyfileobj(response, f)
63     return True
64
65
66 # ----------------------------------------------------------
67 #
68 #               CI UTILS
69 #
70 # -----------------------------------------------------------
71 def get_version():
72     """
73     Get version
74     """
75     # Use the build tag to retrieve the version
76     # By default version is unknown
77     # if launched through CI the build tag has the following format
78     # jenkins-<project>-<installer>-<pod>-<job>-<branch>-<id>
79     # e.g. jenkins-functest-fuel-opnfv-jump-2-daily-master-190
80     # jenkins-functest-fuel-baremetal-weekly-master-8
81     # use regex to match branch info
82     rule = "(dai|week)ly-(.+?)-[0-9]*"
83     build_tag = CONST.__getattribute__('BUILD_TAG')
84     if not build_tag:
85         build_tag = 'none'
86     m = re.search(rule, build_tag)
87     if m:
88         return m.group(2)
89     else:
90         return "unknown"
91
92
93 @decorators.can_dump_request_to_file
94 def push_results_to_db(project, case_name,
95                        start_date, stop_date, result, details):
96     """
97     POST results to the Result target DB
98     """
99     # Retrieve params from CI and conf
100     if (hasattr(CONST, 'TEST_DB_URL')):
101         url = CONST.__getattribute__('TEST_DB_URL')
102     else:
103         url = CONST.__getattribute__("results_test_db_url")
104
105     try:
106         installer = os.environ['INSTALLER_TYPE']
107         scenario = os.environ['DEPLOY_SCENARIO']
108         pod_name = os.environ['NODE_NAME']
109         build_tag = os.environ['BUILD_TAG']
110     except KeyError as e:
111         logger.error("Please set env var: " + str(e))
112         return False
113     version = get_version()
114     test_start = dt.fromtimestamp(start_date).strftime('%Y-%m-%d %H:%M:%S')
115     test_stop = dt.fromtimestamp(stop_date).strftime('%Y-%m-%d %H:%M:%S')
116
117     params = {"project_name": project, "case_name": case_name,
118               "pod_name": pod_name, "installer": installer,
119               "version": version, "scenario": scenario, "criteria": result,
120               "build_tag": build_tag, "start_date": test_start,
121               "stop_date": test_stop, "details": details}
122
123     error = None
124     headers = {'Content-Type': 'application/json'}
125     try:
126         r = requests.post(url, data=json.dumps(params, sort_keys=True),
127                           headers=headers)
128         logger.debug(r)
129         r.raise_for_status()
130     except requests.RequestException as exc:
131         if 'r' in locals():
132             error = ("Pushing Result to DB(%s) failed: %s" %
133                      (r.url, r.content))
134         else:
135             error = ("Pushing Result to DB(%s) failed: %s" % (url, exc))
136     except Exception as e:
137         error = ("Error [push_results_to_db("
138                  "DB: '%(db)s', "
139                  "project: '%(project)s', "
140                  "case: '%(case)s', "
141                  "pod: '%(pod)s', "
142                  "version: '%(v)s', "
143                  "scenario: '%(s)s', "
144                  "criteria: '%(c)s', "
145                  "build_tag: '%(t)s', "
146                  "details: '%(d)s')]: "
147                  "%(error)s" %
148                  {
149                      'db': url,
150                      'project': project,
151                      'case': case_name,
152                      'pod': pod_name,
153                      'v': version,
154                      's': scenario,
155                      'c': result,
156                      't': build_tag,
157                      'd': details,
158                      'error': e
159                  })
160     finally:
161         if error:
162             logger.error(error)
163             return False
164         return True
165
166
167 def get_resolvconf_ns():
168     """
169     Get nameservers from current resolv.conf
170     """
171     nameservers = []
172     rconf = open("/etc/resolv.conf", "r")
173     line = rconf.readline()
174     resolver = dns.resolver.Resolver()
175     while line:
176         ip = re.search(r"\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b", line)
177         if ip:
178             resolver.nameservers = [ip.group(0)]
179             try:
180                 result = resolver.query('opnfv.org')[0]
181                 if result != "":
182                     nameservers.append(ip.group())
183             except dns.exception.Timeout:
184                 pass
185         line = rconf.readline()
186     return nameservers
187
188
189 def get_ci_envvars():
190     """
191     Get the CI env variables
192     """
193     ci_env_var = {
194         "installer": os.environ.get('INSTALLER_TYPE'),
195         "scenario": os.environ.get('DEPLOY_SCENARIO')}
196     return ci_env_var
197
198
199 def execute_command_raise(cmd, info=False, error_msg="",
200                           verbose=True, output_file=None):
201     ret = execute_command(cmd, info, error_msg, verbose, output_file)
202     if ret != 0:
203         raise Exception(error_msg)
204
205
206 def execute_command(cmd, info=False, error_msg="",
207                     verbose=True, output_file=None):
208     if not error_msg:
209         error_msg = ("The command '%s' failed." % cmd)
210     msg_exec = ("Executing command: '%s'" % cmd)
211     if verbose:
212         if info:
213             logger.info(msg_exec)
214         else:
215             logger.debug(msg_exec)
216     p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
217                          stderr=subprocess.STDOUT)
218     if output_file:
219         f = open(output_file, "w")
220     for line in iter(p.stdout.readline, b''):
221         if output_file:
222             f.write(line)
223         else:
224             line = line.replace('\n', '')
225             print(line)
226             sys.stdout.flush()
227     if output_file:
228         f.close()
229     p.stdout.close()
230     returncode = p.wait()
231     if returncode != 0:
232         if verbose:
233             logger.error(error_msg)
234
235     return returncode
236
237
238 def get_dict_by_test(testname):
239     with open(pkg_resources.resource_filename(
240             'functest', 'ci/testcases.yaml')) as f:
241         testcases_yaml = yaml.safe_load(f)
242
243     for dic_tier in testcases_yaml.get("tiers"):
244         for dic_testcase in dic_tier['testcases']:
245             if dic_testcase['case_name'] == testname:
246                 return dic_testcase
247
248     logger.error('Project %s is not defined in testcases.yaml' % testname)
249     return None
250
251
252 def get_criteria_by_test(testname):
253     dict = get_dict_by_test(testname)
254     if dict:
255         return dict['criteria']
256     return None
257
258
259 # ----------------------------------------------------------
260 #
261 #               YAML UTILS
262 #
263 # -----------------------------------------------------------
264 def get_parameter_from_yaml(parameter, file):
265     """
266     Returns the value of a given parameter in file.yaml
267     parameter must be given in string format with dots
268     Example: general.openstack.image_name
269     """
270     with open(file) as f:
271         file_yaml = yaml.safe_load(f)
272     f.close()
273     value = file_yaml
274     for element in parameter.split("."):
275         value = value.get(element)
276         if value is None:
277             raise ValueError("The parameter %s is not defined in"
278                              " %s" % (parameter, file))
279     return value
280
281
282 def get_functest_config(parameter):
283     yaml_ = constants.CONST.__getattribute__('CONFIG_FUNCTEST_YAML')
284     return get_parameter_from_yaml(parameter, yaml_)
285
286
287 def get_functest_yaml():
288     with open(constants.CONST.__getattribute__('CONFIG_FUNCTEST_YAML')) as f:
289         functest_yaml = yaml.safe_load(f)
290     f.close()
291     return functest_yaml
292
293
294 def print_separator():
295     logger.info("==============================================")
296
297
298 def timethis(func):
299     """Measure the time it takes for a function to complete"""
300     @functools.wraps(func)
301     def timed(*args, **kwargs):
302         ts = time.time()
303         result = func(*args, **kwargs)
304         te = time.time()
305         elapsed = '{0}'.format(te - ts)
306         logger.info('{f}(*{a}, **{kw}) took: {t} sec'.format(
307             f=func.__name__, a=args, kw=kwargs, t=elapsed))
308         return result, elapsed
309     return timed