diff options
-rw-r--r-- | docker/Dockerfile | 3 | ||||
-rw-r--r-- | functest/api/base.py | 5 | ||||
-rw-r--r-- | functest/api/resources/v1/envs.py | 41 | ||||
-rw-r--r-- | functest/api/resources/v1/tasks.py | 43 | ||||
-rw-r--r-- | functest/api/resources/v1/testcases.py | 19 | ||||
-rw-r--r-- | functest/api/urls.py | 11 | ||||
-rw-r--r-- | functest/ci/download_images.sh | 4 | ||||
-rw-r--r-- | functest/ci/testcases.yaml | 6 | ||||
-rw-r--r-- | requirements.txt | 1 | ||||
-rw-r--r-- | upper-constraints.txt | 1 |
10 files changed, 117 insertions, 17 deletions
diff --git a/docker/Dockerfile b/docker/Dockerfile index 0c671459..5687b31e 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -95,9 +95,6 @@ RUN git clone --depth 1 -b $ODL_TAG https://git.opendaylight.org/gerrit/p/integr RUN git clone --depth 1 -b $VIMS_TAG https://github.com/boucherv-orange/clearwater-live-test /src/vims-test RUN git clone --depth 1 -b $VROUTER_TAG https://github.com/oolorg/opnfv-functest-vrouter.git ${REPOS_VNFS_DIR}/vrouter -# SFC integration -RUN /bin/bash -c ". /usr/local/lib/python2.7/dist-packages/sfc/tests/functest/setup_scripts/tacker_client_install.sh" - # Install tempest venv and create symlink for running refstack-client RUN ln -s /src/tempest /src/refstack-client/.tempest \ && virtualenv --system-site-packages /src/tempest/.venv diff --git a/functest/api/base.py b/functest/api/base.py index ffc56786..75f059b7 100644 --- a/functest/api/base.py +++ b/functest/api/base.py @@ -45,6 +45,11 @@ class ApiResource(Resource): return action, args + def _get_args(self): # pylint: disable=no-self-use + """ Convert the unicode to string for request.args """ + args = api_utils.change_to_str_in_dict(request.args) + return args + def _dispatch_post(self): """ Dispatch request """ action, args = self._post_args() diff --git a/functest/api/resources/v1/envs.py b/functest/api/resources/v1/envs.py index 9c455198..fb76fa63 100644 --- a/functest/api/resources/v1/envs.py +++ b/functest/api/resources/v1/envs.py @@ -10,11 +10,12 @@ Resources to handle environment related requests """ +import IPy from flask import jsonify from functest.api.base import ApiResource -from functest.cli.commands.cli_env import Env from functest.api.common import api_utils +from functest.cli.commands.cli_env import Env import functest.utils.functest_utils as ft_utils @@ -38,3 +39,41 @@ class V1Envs(ApiResource): return api_utils.result_handler(status=1, data=str(err)) return api_utils.result_handler( status=0, data="Prepare env successfully") + + def update_hosts(self, hosts_info): # pylint: disable=no-self-use + """ Update hosts info """ + + if not isinstance(hosts_info, dict): + return api_utils.result_handler( + status=1, data='Error, args should be a dict') + + for key, value in hosts_info.items(): + if key: + try: + IPy.IP(value) + except Exception: # pylint: disable=broad-except + return api_utils.result_handler( + status=1, data='The IP %s is invalid' % value) + else: + return api_utils.result_handler( + status=1, data='Domain name is absent') + + try: + functest_flag = "# SUT hosts info for Functest" + hosts_list = ('\n{} {} {}'.format(ip, host_name, functest_flag) + for host_name, ip in hosts_info.items()) + + with open("/etc/hosts", 'r') as file_hosts: + origin_lines = [line for line in file_hosts + if functest_flag not in line] + + with open("/etc/hosts", 'w') as file_hosts: + file_hosts.writelines(origin_lines) + file_hosts.write(functest_flag) + file_hosts.writelines(hosts_list) + except Exception: # pylint: disable=broad-except + return api_utils.result_handler( + status=1, data='Error when updating hosts info') + else: + return api_utils.result_handler( + status=0, data='Update hosts info successfully') diff --git a/functest/api/resources/v1/tasks.py b/functest/api/resources/v1/tasks.py index 7086e707..e05db51b 100644 --- a/functest/api/resources/v1/tasks.py +++ b/functest/api/resources/v1/tasks.py @@ -11,9 +11,10 @@ Resources to retrieve the task results """ - +import errno import json import logging +import os import uuid from flask import jsonify @@ -21,13 +22,14 @@ from flask import jsonify from functest.api.base import ApiResource from functest.api.common import api_utils from functest.api.database.v1.handlers import TasksHandler +from functest.utils.constants import CONST LOGGER = logging.getLogger(__name__) -class V1Tasks(ApiResource): - """ V1Tasks Resource class""" +class V1Task(ApiResource): + """ V1Task Resource class""" def get(self, task_id): # pylint: disable=no-self-use """ GET the result of the task id """ @@ -56,3 +58,38 @@ class V1Tasks(ApiResource): result = {'status': status, 'result': json.loads(task.result)} return jsonify(result) + + +class V1TaskLog(ApiResource): + """ V1TaskLog Resource class""" + + def get(self, task_id): # pylint: disable=no-self-use + """ GET the log of the task id """ + try: + uuid.UUID(task_id) + except ValueError: + return api_utils.result_handler(status=1, data='Invalid task id') + + task_handler = TasksHandler() + try: + task = task_handler.get_task_by_taskid(task_id) + except ValueError: + return api_utils.result_handler(status=1, data='No such task id') + + task_log_dir = CONST.__getattribute__('dir_results') + + try: + with open(os.path.join(task_log_dir, + '{}.log'.format(task_id)), 'r') as log_file: + data = log_file.readlines() + except OSError as err: + if err.errno == errno.ENOENT: + return api_utils.result_handler( + status=1, data='Log file does not exist') + + return api_utils.result_handler( + status=1, data='Error with log file') + + return_data = {'data': data} + + return api_utils.result_handler(status=task.status, data=return_data) diff --git a/functest/api/resources/v1/testcases.py b/functest/api/resources/v1/testcases.py index f146c24c..d708cf37 100644 --- a/functest/api/resources/v1/testcases.py +++ b/functest/api/resources/v1/testcases.py @@ -11,10 +11,12 @@ Resources to handle testcase related requests """ -import os import logging +import os +import pkg_resources import uuid +import ConfigParser from flask import abort, jsonify from functest.api.base import ApiResource @@ -84,6 +86,7 @@ class V1Testcase(ApiResource): """ The built_in function to run a test case """ case_name = args.get('testcase') + self._update_logging_ini(args.get('task_id')) if not os.path.isfile(CONST.__getattribute__('env_active')): raise Exception("Functest environment is not ready.") @@ -113,3 +116,17 @@ class V1Testcase(ApiResource): } return {'result': result} + + def _update_logging_ini(self, task_id): # pylint: disable=no-self-use + """ Update the log file for each task""" + config = ConfigParser.RawConfigParser() + config.read( + pkg_resources.resource_filename('functest', 'ci/logging.ini')) + log_path = os.path.join(CONST.__getattribute__('dir_results'), + '{}.log'.format(task_id)) + config.set('handler_file', 'args', '("{}",)'.format(log_path)) + + with open( + pkg_resources.resource_filename( + 'functest', 'ci/logging.ini'), 'wb') as configfile: + config.write(configfile) diff --git a/functest/api/urls.py b/functest/api/urls.py index f7bcae38..0cc22f80 100644 --- a/functest/api/urls.py +++ b/functest/api/urls.py @@ -25,8 +25,9 @@ URLPATTERNS = [ # GET /api/v1/functest/envs => GET environment Url('/api/v1/functest/envs', 'v1_envs'), - # POST /api/v1/functest/envs/action , {"action":"prepare"} - # => Prepare environment + # POST /api/v1/functest/envs/action + # {"action":"prepare"} => Prepare environment + # {"action":"update_hosts", "args": {}} => Update hosts info Url('/api/v1/functest/envs/action', 'v1_envs'), # GET /api/v1/functest/openstack/credentials => GET credentials @@ -62,5 +63,9 @@ URLPATTERNS = [ # GET /api/v1/functest/tasks/<task_id> # => GET the result of the task id - Url('/api/v1/functest/tasks/<task_id>', 'v1_tasks') + Url('/api/v1/functest/tasks/<task_id>', 'v1_task'), + + # GET /api/v1/functest/tasks/<task_id>/log + # => GET the log of the task + Url('/api/v1/functest/tasks/<task_id>/log', 'v1_task_log') ] diff --git a/functest/ci/download_images.sh b/functest/ci/download_images.sh index 88474d3a..cc0abc14 100644 --- a/functest/ci/download_images.sh +++ b/functest/ci/download_images.sh @@ -20,6 +20,4 @@ https://cloud-images.ubuntu.com/releases/14.04/release/ubuntu-14.04-server-cloud http://cloud.centos.org/altarch/7/images/aarch64/CentOS-7-aarch64-GenericCloud.qcow2.xz EOF -xz --decompress --force ${1:-/home/opnfv/functest/images}/CentOS-7-aarch64-GenericCloud.qcow2.xz - -exit $? +xz --decompress --force --keep ${1:-/home/opnfv/functest/images}/CentOS-7-aarch64-GenericCloud.qcow2.xz diff --git a/functest/ci/testcases.yaml b/functest/ci/testcases.yaml index 629499e1..64ca1f48 100644 --- a/functest/ci/testcases.yaml +++ b/functest/ci/testcases.yaml @@ -308,10 +308,10 @@ tiers: criteria: 100 blocking: false description: >- - Test suite for odl-sfc to test two chains and two SFs + Test suite for odl-sfc to test two chains with one SF and one chain with two SFs dependencies: - installer: '(apex)|(fuel)' - scenario: 'odl_l2-sfc' + installer: '' + scenario: 'odl.*sfc' run: module: 'functest.core.feature' class: 'BashFeature' diff --git a/requirements.txt b/requirements.txt index e1d34a36..ba5d91cb 100644 --- a/requirements.txt +++ b/requirements.txt @@ -23,6 +23,7 @@ openbaton-cli cloudify_rest_client Flask!=0.11,<1.0,>=0.10 # BSD Flask-RESTful>=0.3.5 # BSD +IPy mock>=2.0 # BSD iniparse==0.4 PrettyTable<0.8,>=0.7.1 # BSD diff --git a/upper-constraints.txt b/upper-constraints.txt index 74d363c5..fae94270 100644 --- a/upper-constraints.txt +++ b/upper-constraints.txt @@ -14,3 +14,4 @@ robotframework-httplibrary===0.4.2 robotframework-requests===0.4.7 robotframework-sshlibrary===2.1.3;python_version=='2.7' rally===0.9.1 +IPy===0.83 |