diff options
Diffstat (limited to 'functest/utils')
-rw-r--r-- | functest/utils/decorators.py | 36 | ||||
-rw-r--r-- | functest/utils/env.py | 2 | ||||
-rwxr-xr-x | functest/utils/functest_logger.py | 60 | ||||
-rw-r--r-- | functest/utils/functest_utils.py | 47 | ||||
-rw-r--r-- | functest/utils/openstack_tacker.py | 79 | ||||
-rwxr-xr-x | functest/utils/openstack_utils.py | 17 |
6 files changed, 141 insertions, 100 deletions
diff --git a/functest/utils/decorators.py b/functest/utils/decorators.py new file mode 100644 index 00000000..99bcef3e --- /dev/null +++ b/functest/utils/decorators.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python + +import mock +import requests.sessions +import urlparse + + +def can_dump_request_to_file(method): + + def dump_preparedrequest(request, **kwargs): + parseresult = urlparse.urlparse(request.url) + if parseresult.scheme == "file": + with open(parseresult.path.replace('/results', ''), 'a') as f: + headers = "" + for key in request.headers: + headers += key + " " + request.headers[key] + "\n" + message = "{} {}\n{}\n{}\n\n\n".format( + request.method, request.url, headers, request.body) + f.write(message) + return mock.Mock() + + def patch_request(method, url, **kwargs): + with requests.sessions.Session() as session: + parseresult = urlparse.urlparse(url) + if parseresult.scheme == "file": + with mock.patch.object( + session, 'send', side_effect=dump_preparedrequest): + return session.request(method=method, url=url, **kwargs) + else: + return session.request(method=method, url=url, **kwargs) + + def hook(*args, **kwargs): + with mock.patch('requests.api.request', side_effect=patch_request): + return method(*args, **kwargs) + + return hook diff --git a/functest/utils/env.py b/functest/utils/env.py index fa5245fb..7e4df2ea 100644 --- a/functest/utils/env.py +++ b/functest/utils/env.py @@ -3,7 +3,7 @@ import re default_envs = { 'NODE_NAME': 'unknown_pod', - 'CI_DEBUG': 'true', + 'CI_DEBUG': 'false', 'DEPLOY_SCENARIO': 'os-nosdn-nofeature-noha', 'DEPLOY_TYPE': 'virt', 'INSTALLER_TYPE': None, diff --git a/functest/utils/functest_logger.py b/functest/utils/functest_logger.py index f09f56be..022211cb 100755 --- a/functest/utils/functest_logger.py +++ b/functest/utils/functest_logger.py @@ -28,42 +28,38 @@ import json from functest.utils.constants import CONST -logger = logging.getLogger(__name__) +class Logger(object): -def is_debug(): - if CONST.CI_DEBUG and CONST.CI_DEBUG.lower() == "true": - return True - return False - - -def setup_logging(default_path=CONST.dir_functest_logging_cfg, - default_level=logging.INFO, - env_key='LOG_CFG'): - path = default_path - value = os.getenv(env_key, None) - if value: - path = value - if os.path.exists(path): - with open(path, 'rt') as f: - config = json.load(f) - if (config['handlers'] and - config['handlers']['console']): - stream_level = logging.INFO - if is_debug(): - stream_level = logging.DEBUG - config['handlers']['console']['level'] = stream_level - logging.config.dictConfig(config) - else: - logging.basicConfig(level=default_level) - - -setup_logging() - - -class Logger: def __init__(self, logger_name): + self.setup_logging() self.logger = logging.getLogger(logger_name) + logging.getLogger("paramiko").setLevel(logging.WARNING) def getLogger(self): return self.logger + + def is_debug(self): + if CONST.CI_DEBUG and CONST.CI_DEBUG.lower() == "true": + return True + return False + + def setup_logging(self, default_path=CONST.dir_functest_logging_cfg, + default_level=logging.INFO, + env_key='LOG_CFG'): + path = default_path + value = os.getenv(env_key, None) + if value: + path = value + if os.path.exists(path): + with open(path, 'rt') as f: + config = json.load(f) + if (config['handlers'] and + config['handlers']['console']): + stream_level = logging.INFO + if self.is_debug(): + stream_level = logging.DEBUG + config['handlers']['console']['level'] = stream_level + logging.config.dictConfig(config) + else: + logging.basicConfig(level=default_level) diff --git a/functest/utils/functest_utils.py b/functest/utils/functest_utils.py index 04055464..dbed811a 100644 --- a/functest/utils/functest_utils.py +++ b/functest/utils/functest_utils.py @@ -23,10 +23,9 @@ import requests import yaml from git import Repo -from functest.utils.constants import CONST +from functest.utils import decorators import functest.utils.functest_logger as ft_logger - logger = ft_logger.Logger("functest_utils").getLogger() @@ -184,43 +183,14 @@ def logger_test_results(project, case_name, status, details): 'd': details}) -def write_results_to_file(project, case_name, start_date, - stop_date, criteria, details): - file_path = re.split(r'://', CONST.results_test_db_url)[1] - - try: - installer = os.environ['INSTALLER_TYPE'] - scenario = os.environ['DEPLOY_SCENARIO'] - pod_name = os.environ['NODE_NAME'] - except KeyError as e: - logger.error("Please set env var: " + str(e)) - return False - - test_start = dt.fromtimestamp(start_date).strftime('%Y-%m-%d %H:%M:%S') - test_stop = dt.fromtimestamp(stop_date).strftime('%Y-%m-%d %H:%M:%S') - - params = {"project_name": project, "case_name": case_name, - "pod_name": pod_name, "installer": installer, - "scenario": scenario, "criteria": criteria, - "start_date": test_start, "stop_date": test_stop, - "details": details} - try: - with open(file_path, "a+w") as outfile: - json.dump(params, outfile) - outfile.write("\n") - return True - except Exception as e: - logger.error("write result data into a file failed: %s" % e) - return False - - +@decorators.can_dump_request_to_file def push_results_to_db(project, case_name, start_date, stop_date, criteria, details): """ POST results to the Result target DB """ # Retrieve params from CI and conf - url = CONST.results_test_db_url + "/results" + url = get_db_url() + "/results" try: installer = os.environ['INSTALLER_TYPE'] @@ -300,7 +270,7 @@ def get_resolvconf_ns(): while line: ip = re.search(r"\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b", line) if ip: - resolver.nameservers = [str(ip)] + resolver.nameservers = [ip.group(0)] try: result = resolver.query('opnfv.org')[0] if result != "": @@ -321,6 +291,13 @@ def get_ci_envvars(): return ci_env_var +def execute_command_raise(cmd, info=False, error_msg="", + verbose=True, output_file=None): + ret = execute_command(cmd, info, error_msg, verbose, output_file) + if ret != 0: + raise Exception(error_msg) + + def execute_command(cmd, info=False, error_msg="", verbose=True, output_file=None): if not error_msg: @@ -392,7 +369,7 @@ def get_parameter_from_yaml(parameter, file): value = value.get(element) if value is None: raise ValueError("The parameter %s is not defined in" - " config_functest.yaml" % parameter) + " %s" % (parameter, file)) return value diff --git a/functest/utils/openstack_tacker.py b/functest/utils/openstack_tacker.py index c7ac89af..8327fdbe 100644 --- a/functest/utils/openstack_tacker.py +++ b/functest/utils/openstack_tacker.py @@ -45,8 +45,16 @@ def get_vnfd_id(tacker_client, vnfd_name): return get_id_from_name(tacker_client, 'vnfd', vnfd_name) -def get_vnf_id(tacker_client, vnf_name): - return get_id_from_name(tacker_client, 'vnf', vnf_name) +def get_vnf_id(tacker_client, vnf_name, timeout=5): + vnf_id = None + while vnf_id is None and timeout >= 0: + vnf_id = get_id_from_name(tacker_client, 'vnf', vnf_name) + if vnf_id is None: + logger.info("Could not retrieve ID for vnf with name [%s]." + " Retrying." % vnf_name) + time.sleep(1) + timeout -= 1 + return vnf_id def get_sfc_id(tacker_client, sfc_name): @@ -108,7 +116,8 @@ def list_vnfs(tacker_client, verbose=False): return None -def create_vnf(tacker_client, vnf_name, vnfd_id=None, vnfd_name=None): +def create_vnf(tacker_client, vnf_name, vnfd_id=None, + vnfd_name=None, param_file=None): try: vnf_body = { 'vnf': { @@ -116,6 +125,11 @@ def create_vnf(tacker_client, vnf_name, vnfd_id=None, vnfd_name=None): 'name': vnf_name } } + if param_file is not None: + params = None + with open(param_file) as f: + params = f.read() + vnf_body['vnf']['attributes']['param_values'] = params if vnfd_id is not None: vnf_body['vnf']['vnfd_id'] = vnfd_id else: @@ -130,32 +144,44 @@ def create_vnf(tacker_client, vnf_name, vnfd_id=None, vnfd_name=None): return None -def wait_for_vnf(tacker_client, vnf_id=None, vnf_name=None): +def get_vnf(tacker_client, vnf_id=None, vnf_name=None): try: - _id = None - if vnf_id is not None: - _id = vnf_id - elif vnf_name is not None: - while _id is None: - try: - _id = get_vnf_id(tacker_client, vnf_name) - except: - logger.error("Bazinga") - else: + if vnf_id is None and vnf_name is None: raise Exception('You must specify vnf_id or vnf_name') - while True: - vnf = [v for v in list_vnfs(tacker_client, verbose=True)['vnfs'] - if v['id'] == _id] - vnf = vnf[0] - logger.info('Waiting for vnf {0}'.format(str(vnf))) + + _id = get_vnf_id(tacker_client, vnf_name) if vnf_id is None else vnf_id + + if _id is not None: + all_vnfs = list_vnfs(tacker_client, verbose=True)['vnfs'] + return next((vnf for vnf in all_vnfs if vnf['id'] == _id), None) + else: + raise Exception('Could not retrieve ID from name [%s]' % vnf_name) + + except Exception, e: + logger.error("Could not retrieve VNF [vnf_id=%s, vnf_name=%s] - %s" + % (vnf_id, vnf_name, e)) + return None + + +def wait_for_vnf(tacker_client, vnf_id=None, vnf_name=None, timeout=60): + try: + vnf = get_vnf(tacker_client, vnf_id, vnf_name) + if vnf is None: + raise Exception("Could not retrieve VNF - id='%s', name='%s'" + % vnf_id, vnf_name) + logger.info('Waiting for vnf {0}'.format(str(vnf))) + while vnf['status'] != 'ACTIVE' and timeout >= 0: if vnf['status'] == 'ERROR': - raise Exception('Error when booting vnf %s' % _id) + raise Exception('Error when booting vnf %s' % vnf['id']) elif vnf['status'] == 'PENDING_CREATE': time.sleep(3) - continue - else: - break - return _id + timeout -= 3 + vnf = get_vnf(tacker_client, vnf_id, vnf_name) + + if (timeout < 0): + raise Exception('Timeout when booting vnf %s' % vnf['id']) + + return vnf['id'] except Exception, e: logger.error("error [wait_for_vnf(tacker_client, '%s', '%s')]: %s" % (vnf_id, vnf_name, e)) @@ -189,7 +215,8 @@ def list_sfcs(tacker_client, verbose=False): def create_sfc(tacker_client, sfc_name, chain_vnf_ids=None, - chain_vnf_names=None): + chain_vnf_names=None, + symmetrical=False): try: sfc_body = { 'sfc': { @@ -198,6 +225,8 @@ def create_sfc(tacker_client, sfc_name, 'chain': [] } } + if symmetrical: + sfc_body['sfc']['symmetrical'] = True if chain_vnf_ids is not None: sfc_body['sfc']['chain'] = chain_vnf_ids else: diff --git a/functest/utils/openstack_utils.py b/functest/utils/openstack_utils.py index 64f18504..3093cb55 100755 --- a/functest/utils/openstack_utils.py +++ b/functest/utils/openstack_utils.py @@ -10,7 +10,7 @@ import os import os.path -import subprocess +import re import sys import time @@ -112,12 +112,15 @@ def get_credentials(other_creds={}): def source_credentials(rc_file): - pipe = subprocess.Popen(". %s; env" % rc_file, stdout=subprocess.PIPE, - shell=True) - output = pipe.communicate()[0] - env = dict((line.split("=", 1) for line in output.splitlines())) - os.environ.update(env) - return env + with open(rc_file, "r") as f: + for line in f: + var = line.rstrip('"\n').replace('export ', '').split("=") + # The two next lines should be modified as soon as rc_file + # conforms with common rules. Be aware that it could induce + # issues if value starts with ' + key = re.sub(r'^["\' ]*|[ \'"]*$', '', var[0]) + value = re.sub(r'^["\' ]*|[ \'"]*$', '', "".join(var[1:])) + os.environ[key] = value def get_credentials_for_rally(): |