summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docker/Dockerfile3
-rw-r--r--functest/api/base.py5
-rw-r--r--functest/api/resources/v1/envs.py41
-rw-r--r--functest/api/resources/v1/tasks.py43
-rw-r--r--functest/api/resources/v1/testcases.py19
-rw-r--r--functest/api/urls.py11
-rw-r--r--functest/ci/download_images.sh4
-rw-r--r--functest/ci/testcases.yaml6
-rw-r--r--requirements.txt1
-rw-r--r--upper-constraints.txt1
10 files changed, 117 insertions, 17 deletions
diff --git a/docker/Dockerfile b/docker/Dockerfile
index 0c671459c..5687b31e7 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 ffc567860..75f059b74 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 9c455198d..fb76fa63f 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 7086e7075..e05db51be 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 f146c24ce..d708cf37b 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 f7bcae389..0cc22f80f 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 88474d3a7..cc0abc142 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 629499e19..64ca1f482 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 e1d34a36a..ba5d91cb8 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 74d363c50..fae94270c 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