Merge "Fixes incorrect parenthesis format & adds ft_logger import"
[functest.git] / 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
11 import json
12 import os
13 import os.path
14 import re
15 import requests
16 import shutil
17 import socket
18 import subprocess
19 import sys
20 import urllib2
21 import yaml
22 from git import Repo
23 import functest.ci.tier_builder as tb
24
25
26 """ global variables """
27 REPOS_DIR = os.getenv('repos_dir')
28 FUNCTEST_REPO = ("%s/functest/" % REPOS_DIR)
29
30
31 # ----------------------------------------------------------
32 #
33 #               INTERNET UTILS
34 #
35 # -----------------------------------------------------------
36 def check_internet_connectivity(url='http://www.opnfv.org/'):
37     """
38     Check if there is access to the internet
39     """
40     try:
41         urllib2.urlopen(url, timeout=5)
42         return True
43     except urllib2.URLError:
44         return False
45
46
47 def download_url(url, dest_path):
48     """
49     Download a file to a destination path given a URL
50     """
51     name = url.rsplit('/')[-1]
52     dest = dest_path + "/" + name
53     try:
54         response = urllib2.urlopen(url)
55     except (urllib2.HTTPError, urllib2.URLError):
56         return False
57
58     with open(dest, 'wb') as f:
59         shutil.copyfileobj(response, f)
60     return True
61
62
63 # ----------------------------------------------------------
64 #
65 #               CI UTILS
66 #
67 # -----------------------------------------------------------
68 def get_git_branch(repo_path):
69     """
70     Get git branch name
71     """
72     repo = Repo(repo_path)
73     branch = repo.active_branch
74     return branch.name
75
76
77 def get_installer_type(logger=None):
78     """
79     Get installer type (fuel, apex, joid, compass)
80     """
81     try:
82         installer = os.environ['INSTALLER_TYPE']
83     except KeyError:
84         if logger:
85             logger.error("Impossible to retrieve the installer type")
86         installer = "Unknown_installer"
87
88     return installer
89
90
91 def get_scenario(logger=None):
92     """
93     Get scenario
94     """
95     try:
96         scenario = os.environ['DEPLOY_SCENARIO']
97     except KeyError:
98         if logger:
99             logger.error("Impossible to retrieve the scenario")
100         scenario = "Unknown_scenario"
101
102     return scenario
103
104
105 def get_version(logger=None):
106     """
107     Get version
108     """
109     # Use the build tag to retrieve the version
110     # By default version is unknown
111     # if launched through CI the build tag has the following format
112     # jenkins-<project>-<installer>-<pod>-<job>-<branch>-<id>
113     # e.g. jenkins-functest-fuel-opnfv-jump-2-daily-master-190
114     # use regex to match branch info
115     rule = "daily-(.+?)-[0-9]*"
116     build_tag = get_build_tag(logger)
117     m = re.search(rule, build_tag)
118     if m:
119         return m.group(1)
120     else:
121         return "unknown"
122
123
124 def get_pod_name(logger=None):
125     """
126     Get PoD Name from env variable NODE_NAME
127     """
128     try:
129         return os.environ['NODE_NAME']
130     except KeyError:
131         if logger:
132             logger.error(
133                 "Unable to retrieve the POD name from environment. " +
134                 "Using pod name 'unknown-pod'")
135         return "unknown-pod"
136
137
138 def get_build_tag(logger=None):
139     """
140     Get build tag of jenkins jobs
141     """
142     try:
143         build_tag = os.environ['BUILD_TAG']
144     except KeyError:
145         if logger:
146             logger.error("Impossible to retrieve the build tag")
147         build_tag = "unknown_build_tag"
148
149     return build_tag
150
151
152 def get_db_url(logger=None):
153     """
154     Returns DB URL
155     """
156     with open(os.environ["CONFIG_FUNCTEST_YAML"]) as f:
157         functest_yaml = yaml.safe_load(f)
158     f.close()
159     db_url = functest_yaml.get("results").get("test_db_url")
160     return db_url
161
162
163 def push_results_to_db(project, case_name, logger,
164                        start_date, stop_date, criteria, details):
165     """
166     POST results to the Result target DB
167     """
168     # Retrieve params from CI and conf
169     url = get_db_url(logger) + "/results"
170     installer = get_installer_type(logger)
171     scenario = get_scenario(logger)
172     version = get_version(logger)
173     pod_name = get_pod_name(logger)
174     build_tag = get_build_tag(logger)
175
176     params = {"project_name": project, "case_name": case_name,
177               "pod_name": pod_name, "installer": installer,
178               "version": version, "scenario": scenario, "criteria": criteria,
179               "build_tag": build_tag, "start_date": start_date,
180               "stop_date": stop_date, "details": details}
181
182     headers = {'Content-Type': 'application/json'}
183     try:
184         r = requests.post(url, data=json.dumps(params), headers=headers)
185         if logger:
186             logger.debug(r)
187         return True
188     except Exception, e:
189         print ("Error [push_results_to_db('%s', '%s', '%s', " +
190                "'%s', '%s', '%s', '%s', '%s', '%s')]:" %
191                (url, project, case_name, pod_name, version,
192                 scenario, criteria, build_tag, details)), e
193         return False
194
195
196 def get_resolvconf_ns():
197     """
198     Get nameservers from current resolv.conf
199     """
200     nameservers = []
201     rconf = open("/etc/resolv.conf", "r")
202     line = rconf.readline()
203     while line:
204         ip = re.search(r"\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b", line)
205         sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
206         if ip:
207             result = sock.connect_ex((ip.group(), 53))
208             if result == 0:
209                 nameservers.append(ip.group())
210         line = rconf.readline()
211     return nameservers
212
213
214 def get_ci_envvars():
215     """
216     Get the CI env variables
217     """
218     ci_env_var = {
219         "installer": os.environ.get('INSTALLER_TYPE'),
220         "scenario": os.environ.get('DEPLOY_SCENARIO')}
221     return ci_env_var
222
223
224 def execute_command(cmd, logger=None,
225                     exit_on_error=True,
226                     info=False,
227                     error_msg="",
228                     verbose=True):
229     if not error_msg:
230         error_msg = ("The command '%s' failed." % cmd)
231     msg_exec = ("Executing command: '%s'" % cmd)
232     if verbose:
233         if logger:
234             if info:
235                 logger.info(msg_exec)
236             else:
237                 logger.debug(msg_exec)
238         else:
239             print(msg_exec)
240     p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
241     while True:
242         line = p.stdout.readline().replace('\n', '')
243         if not line:
244             break
245         if logger:
246             if info:
247                 logger.info(line)
248             else:
249                 logger.debug(line)
250         else:
251             print line
252     p.communicate()
253     if p.returncode != 0:
254         if verbose:
255             if logger:
256                 logger.error(error_msg)
257             else:
258                 print(error_msg)
259         if exit_on_error:
260             sys.exit(1)
261
262     return p.returncode
263
264
265 def get_deployment_dir(logger=None):
266     """
267     Returns current Rally deployment directory
268     """
269     with open(os.environ["CONFIG_FUNCTEST_YAML"]) as f:
270         functest_yaml = yaml.safe_load(f)
271     f.close()
272     deployment_name = functest_yaml.get("rally").get("deployment_name")
273     rally_dir = functest_yaml.get("general").get("directories").get(
274         "dir_rally_inst")
275     cmd = ("rally deployment list | awk '/" + deployment_name +
276            "/ {print $2}'")
277     p = subprocess.Popen(cmd, shell=True,
278                          stdout=subprocess.PIPE,
279                          stderr=subprocess.STDOUT)
280     deployment_uuid = p.stdout.readline().rstrip()
281     if deployment_uuid == "":
282         if logger:
283             logger.error("Rally deployment not found.")
284         exit(-1)
285     deployment_dir = (rally_dir + "/tempest/for-deployment-" +
286                       deployment_uuid)
287     return deployment_dir
288
289
290 def get_criteria_by_test(testname):
291     criteria = ""
292     file = FUNCTEST_REPO + "/ci/testcases.yaml"
293     tiers = tb.TierBuilder("", "", file)
294     for tier in tiers.get_tiers():
295         for test in tier.get_tests():
296             if test.get_name() == testname:
297                 criteria = test.get_criteria()
298
299     return criteria