aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/actions/result.py55
-rw-r--r--api/actions/test.py8
-rwxr-xr-xapi/api-prepare.sh59
-rw-r--r--api/conf.py8
-rw-r--r--api/server.py8
-rw-r--r--api/urls.py11
-rw-r--r--api/utils/common.py31
-rw-r--r--api/utils/daemonthread.py8
-rw-r--r--api/utils/influx.py20
-rw-r--r--api/views.py35
-rw-r--r--api/yardstick.ini16
-rw-r--r--api/yardstick.sock0
-rw-r--r--docker/Dockerfile7
-rwxr-xr-xinstall.sh3
-rwxr-xr-xtests/ci/yardstick-verify2
-rw-r--r--tests/unit/api/actions/test_result.py29
-rw-r--r--tests/unit/api/actions/test_test.py8
-rw-r--r--tests/unit/api/test_views.py23
-rw-r--r--tests/unit/api/utils/test_common.py38
-rw-r--r--tests/unit/api/utils/test_daemonthread.py8
-rw-r--r--tests/unit/api/utils/test_influx.py22
21 files changed, 382 insertions, 17 deletions
diff --git a/api/actions/result.py b/api/actions/result.py
new file mode 100644
index 000000000..9f606d2cb
--- /dev/null
+++ b/api/actions/result.py
@@ -0,0 +1,55 @@
+##############################################################################
+# Copyright (c) 2016 Huawei Technologies Co.,Ltd and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+import logging
+
+from api.utils import influx as influx_utils
+from api.utils import common as common_utils
+from api import conf
+
+logger = logging.getLogger(__name__)
+
+
+def getResult(args):
+ try:
+ measurement = args['measurement']
+ task_id = args['task_id']
+ except KeyError:
+ message = 'measurement and task_id must be needed'
+ return common_utils.error_handler(message)
+
+ measurement = conf.TEST_CASE_PRE + measurement
+
+ query_sql = "select * from $table where task_id='$task_id'"
+ param = {'table': 'tasklist', 'task_id': task_id}
+ data = common_utils.translate_to_str(influx_utils.query(query_sql, param))
+
+ def _unfinished():
+ return common_utils.result_handler(0, [])
+
+ def _finished():
+ param = {'table': measurement, 'task_id': task_id}
+ data = common_utils.translate_to_str(influx_utils.query(query_sql,
+ param))
+
+ return common_utils.result_handler(1, data)
+
+ def _error():
+ return common_utils.result_handler(2, data[0]['error'])
+
+ try:
+ status = data[0]['status']
+
+ switcher = {
+ 0: _unfinished,
+ 1: _finished,
+ 2: _error
+ }
+ return switcher.get(status, lambda: 'nothing')()
+ except IndexError:
+ return common_utils.error_handler('no such task')
diff --git a/api/actions/test.py b/api/actions/test.py
index 0de70bb71..b1dc212c2 100644
--- a/api/actions/test.py
+++ b/api/actions/test.py
@@ -1,3 +1,11 @@
+##############################################################################
+# Copyright (c) 2016 Huawei Technologies Co.,Ltd and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
import uuid
import json
import os
diff --git a/api/api-prepare.sh b/api/api-prepare.sh
new file mode 100755
index 000000000..075d7875c
--- /dev/null
+++ b/api/api-prepare.sh
@@ -0,0 +1,59 @@
+#!/bin/bash
+
+# yardstick output config
+output_config='/etc/yardstick/yardstick.conf'
+
+if [[ ! -e "${output_config}" ]];then
+ gateway_ip=$(ip route | grep default | awk '{print $3}')
+ echo "${gateway_ip}"
+
+ install -d /etc/yardstick -m 0755 -o root
+
+ cat << EOF > "${output_config}"
+[DEFAULT]
+debug = True
+dispatcher = influxdb
+
+[dispatcher_file]
+file_path = /tmp/yardstick.out
+
+[dispatcher_http]
+timeout = 5
+# target = http://127.0.0.1:8000/results
+
+[dispatcher_influxdb]
+timeout = 5
+target = http://${gateway_ip}:8086
+db_name = yardstick
+username = root
+password = root
+EOF
+fi
+
+# nginx config
+nginx_config='/etc/nginx/conf.d/yardstick.conf'
+
+if [[ ! -e "${nginx_config}" ]];then
+
+ cat << EOF >> "${nginx_config}"
+server {
+ listen 5000;
+ server_name localhost;
+ index index.htm index.html;
+ location / {
+ include uwsgi_params;
+ uwsgi_pass unix:///home/opnfv/repos/yardstick/api/yardstick.sock;
+ }
+}
+EOF
+fi
+
+# nginx service start when boot
+cat << EOF >> /root/.bashrc
+
+nginx_status=\$(service nginx status | grep not)
+if [ -n "\${nginx_status}" ];then
+ service nginx restart
+ uwsgi -i /home/opnfv/repos/yardstick/api/yardstick.ini
+fi
+EOF
diff --git a/api/conf.py b/api/conf.py
index b5553f452..e1da4aba0 100644
--- a/api/conf.py
+++ b/api/conf.py
@@ -1,3 +1,11 @@
+##############################################################################
+# Copyright (c) 2016 Huawei Technologies Co.,Ltd and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
from pyroute2 import IPDB
diff --git a/api/server.py b/api/server.py
index d0e4d30a2..1cbe1725d 100644
--- a/api/server.py
+++ b/api/server.py
@@ -1,3 +1,11 @@
+##############################################################################
+# Copyright (c) 2016 Huawei Technologies Co.,Ltd and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
import logging
from flask import Flask
diff --git a/api/urls.py b/api/urls.py
index 9fa0bc935..2a9e72a76 100644
--- a/api/urls.py
+++ b/api/urls.py
@@ -1,7 +1,16 @@
+##############################################################################
+# Copyright (c) 2016 Huawei Technologies Co.,Ltd and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
from api import views
from api.utils.common import Url
urlpatterns = [
- Url('/yardstick/test/action', views.Test, 'test')
+ Url('/yardstick/test/action', views.Test, 'test'),
+ Url('/yardstick/result/action', views.Result, 'result')
]
diff --git a/api/utils/common.py b/api/utils/common.py
index 9d7998abd..04a6fe0d6 100644
--- a/api/utils/common.py
+++ b/api/utils/common.py
@@ -1,8 +1,20 @@
+##############################################################################
+# Copyright (c) 2016 Huawei Technologies Co.,Ltd and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
import collections
+import logging
+import json
from api.utils.daemonthread import DaemonThread
from yardstick.cmd.cli import YardstickCLI
+logger = logging.getLogger(__name__)
+
def translate_to_str(object):
if isinstance(object, collections.Mapping):
@@ -20,7 +32,7 @@ def get_command_list(command_list, opts, args):
command_list.extend(('--{}'.format(k) for k in opts if 'task-args' != k))
- task_args = opts.get('task_args', '')
+ task_args = opts.get('task-args', '')
if task_args:
command_list.extend(['--task-args', task_args])
@@ -32,6 +44,23 @@ def exec_command_task(command_list, task_id): # pragma: no cover
daemonthread.start()
+def error_handler(message):
+ logger.debug(message)
+ result = {
+ 'status': 'error',
+ 'message': message
+ }
+ return json.dumps(result)
+
+
+def result_handler(status, data):
+ result = {
+ 'status': status,
+ 'result': data
+ }
+ return json.dumps(result)
+
+
class Url(object):
def __init__(self, url, resource, endpoint):
diff --git a/api/utils/daemonthread.py b/api/utils/daemonthread.py
index 77a0f6ab7..47c0b9108 100644
--- a/api/utils/daemonthread.py
+++ b/api/utils/daemonthread.py
@@ -1,3 +1,11 @@
+##############################################################################
+# Copyright (c) 2016 Huawei Technologies Co.,Ltd and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
import threading
import os
import datetime
diff --git a/api/utils/influx.py b/api/utils/influx.py
index 52a90b61c..9366ed3e9 100644
--- a/api/utils/influx.py
+++ b/api/utils/influx.py
@@ -1,3 +1,11 @@
+##############################################################################
+# Copyright (c) 2016 Huawei Technologies Co.,Ltd and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
import logging
from urlparse import urlsplit
@@ -29,7 +37,7 @@ def get_data_db_client():
def _get_ip(url):
- return urlsplit(url).netloc.split(':')[0]
+ return urlsplit(url).hostname
def _write_data(measurement, field, timestamp, tags):
@@ -53,3 +61,13 @@ def write_data_tasklist(task_id, timestamp, status, error=''):
field = {'status': status, 'error': error}
tags = {'task_id': task_id}
_write_data('tasklist', field, timestamp, tags)
+
+
+def query(query_sql):
+ try:
+ client = get_data_db_client()
+ logger.debug('Start to query: %s', query_sql)
+ return list(client.query(query_sql).get_points())
+ except RuntimeError:
+ logger.error('dispatcher is not influxdb')
+ raise
diff --git a/api/views.py b/api/views.py
index 883091222..e78389f5a 100644
--- a/api/views.py
+++ b/api/views.py
@@ -1,4 +1,11 @@
-import json
+##############################################################################
+# Copyright (c) 2016 Huawei Technologies Co.,Ltd and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
import logging
from flask import request
@@ -6,7 +13,7 @@ from flask_restful import Resource
from api.utils import common as common_utils
from api.actions import test as test_action
-from api import conf
+from api.actions import result as result_action
logger = logging.getLogger(__name__)
@@ -17,13 +24,19 @@ class Test(Resource):
args = common_utils.translate_to_str(request.json.get('args', {}))
logger.debug('Input args is: action: %s, args: %s', action, args)
- if action not in conf.TEST_ACTION:
- logger.error('Wrong action')
- result = {
- 'status': 'error',
- 'message': 'wrong action'
- }
- return json.dumps(result)
+ try:
+ return getattr(test_action, action)(args)
+ except AttributeError:
+ return common_utils.error_handler('Wrong action')
- method = getattr(test_action, action)
- return method(args)
+
+class Result(Resource):
+ def get(self):
+ args = common_utils.translate_to_str(request.args)
+ action = args.get('action', '')
+ logger.debug('Input args is: action: %s, args: %s', action, args)
+
+ try:
+ return getattr(result_action, action)(args)
+ except AttributeError:
+ return common_utils.error_handler('Wrong action')
diff --git a/api/yardstick.ini b/api/yardstick.ini
new file mode 100644
index 000000000..535022960
--- /dev/null
+++ b/api/yardstick.ini
@@ -0,0 +1,16 @@
+[uwsgi]
+master = true
+debug = true
+chdir = /home/opnfv/repos/yardstick/api
+module = server
+plugins = python
+processes = 10
+threads = 5
+async = true
+max-requests = 5000
+chmod-socket = 666
+callable = app
+enable-threads = true
+close-on-exec = 1
+daemonize=/home/kklt/kklt/api/uwsgi.log
+socket = /home/opnfv/repos/yardstick/api/yardstick.sock
diff --git a/api/yardstick.sock b/api/yardstick.sock
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/api/yardstick.sock
diff --git a/docker/Dockerfile b/docker/Dockerfile
index fba6e2067..36db2bb13 100644
--- a/docker/Dockerfile
+++ b/docker/Dockerfile
@@ -43,6 +43,9 @@ RUN apt-get update && apt-get install -y \
python-dev \
libxml2-dev \
libxslt1-dev \
+ nginx \
+ uwsgi \
+ uwsgi-plugin-python \
python-setuptools && \
easy_install -U setuptools
@@ -60,6 +63,10 @@ RUN cd ${YARDSTICK_REPO_DIR} && easy_install -U pip
RUN cd ${YARDSTICK_REPO_DIR} && pip install -r requirements.txt
RUN cd ${YARDSTICK_REPO_DIR} && pip install .
+RUN ${YARDSTICK_REPO_DIR}/api/api-prepare.sh
+
+EXPOSE 5000
+
ADD http://download.cirros-cloud.net/0.3.3/cirros-0.3.3-x86_64-disk.img /home/opnfv/images/
ADD http://cloud-images.ubuntu.com/trusty/current/trusty-server-cloudimg-amd64-disk1.img /home/opnfv/images/
diff --git a/install.sh b/install.sh
index 80fc1e523..8fdd07569 100755
--- a/install.sh
+++ b/install.sh
@@ -13,6 +13,9 @@ apt-get update && apt-get install -y \
python-dev \
libxml2-dev \
libxslt1-dev \
+ nginx \
+ uswgi \
+ uwsgi-plugin-python \
python-setuptools && \
easy_install -U setuptools
diff --git a/tests/ci/yardstick-verify b/tests/ci/yardstick-verify
index 2b7ec9d34..1a6682f85 100755
--- a/tests/ci/yardstick-verify
+++ b/tests/ci/yardstick-verify
@@ -160,7 +160,7 @@ run_test()
mkdir -p /etc/yardstick
- cat << EOF >> /etc/yardstick/yardstick.conf
+ cat << EOF > /etc/yardstick/yardstick.conf
[DEFAULT]
debug = True
dispatcher = ${DISPATCHER_TYPE}
diff --git a/tests/unit/api/actions/test_result.py b/tests/unit/api/actions/test_result.py
new file mode 100644
index 000000000..168631905
--- /dev/null
+++ b/tests/unit/api/actions/test_result.py
@@ -0,0 +1,29 @@
+##############################################################################
+# Copyright (c) 2016 Huawei Technologies Co.,Ltd and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+import unittest
+import json
+
+from api.actions import result
+
+
+class GetResultTestCase(unittest.TestCase):
+
+ def test_getResult_with_no_taskid_arg(self):
+ args = {}
+ output = json.loads(result.getResult(args))
+
+ self.assertEqual('error', output['status'])
+
+
+def main():
+ unittest.main()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/tests/unit/api/actions/test_test.py b/tests/unit/api/actions/test_test.py
index 158062ff4..7ebe9fc24 100644
--- a/tests/unit/api/actions/test_test.py
+++ b/tests/unit/api/actions/test_test.py
@@ -1,3 +1,11 @@
+##############################################################################
+# Copyright (c) 2016 Huawei Technologies Co.,Ltd and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
import unittest
import json
diff --git a/tests/unit/api/test_views.py b/tests/unit/api/test_views.py
index 650ed569c..e57ec08a4 100644
--- a/tests/unit/api/test_views.py
+++ b/tests/unit/api/test_views.py
@@ -1,21 +1,42 @@
+##############################################################################
+# Copyright (c) 2016 Huawei Technologies Co.,Ltd and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
import unittest
import mock
import json
from api.views import Test
+from api.views import Result
class TestTestCase(unittest.TestCase):
@mock.patch('api.views.request')
def test_post(self, mock_request):
- mock_request.json.get.side_effect = ['runTestSuite', {}]
+ mock_request.json.get.side_effect = ['hello', {}]
result = json.loads(Test().post())
self.assertEqual('error', result['status'])
+class ResultTestCase(unittest.TestCase):
+
+ @mock.patch('api.views.request')
+ def test_get(self, mock_request):
+ mock_request.args.get.return_value = 'hello'
+
+ print Result().get()
+ result = json.loads(Result().get())
+
+ self.assertEqual('error', result['status'])
+
+
def main():
unittest.main()
diff --git a/tests/unit/api/utils/test_common.py b/tests/unit/api/utils/test_common.py
index 5d858a32c..9e050c714 100644
--- a/tests/unit/api/utils/test_common.py
+++ b/tests/unit/api/utils/test_common.py
@@ -1,4 +1,13 @@
+##############################################################################
+# Copyright (c) 2016 Huawei Technologies Co.,Ltd and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
import unittest
+import json
from api.utils import common
@@ -49,6 +58,35 @@ class GetCommandListTestCase(unittest.TestCase):
self.assertEqual(result_list, output_list)
+class ErrorHandlerTestCase(unittest.TestCase):
+
+ def test_error_handler(self):
+ message = 'hello world'
+ output_dict = json.loads(common.error_handler(message))
+
+ result = {
+ 'status': 'error',
+ 'message': message
+ }
+
+ self.assertEqual(result, output_dict)
+
+
+class ResultHandlerTestCase(unittest.TestCase):
+
+ def test_result_handler(self):
+ status = 1
+ data = ['hello world']
+ output_dict = json.loads(common.result_handler(status, data))
+
+ result = {
+ 'status': status,
+ 'result': data
+ }
+
+ self.assertEqual(result, output_dict)
+
+
def main():
unittest.main()
diff --git a/tests/unit/api/utils/test_daemonthread.py b/tests/unit/api/utils/test_daemonthread.py
index 918f1f506..f07f0fede 100644
--- a/tests/unit/api/utils/test_daemonthread.py
+++ b/tests/unit/api/utils/test_daemonthread.py
@@ -1,3 +1,11 @@
+##############################################################################
+# Copyright (c) 2016 Huawei Technologies Co.,Ltd and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
import unittest
import mock
diff --git a/tests/unit/api/utils/test_influx.py b/tests/unit/api/utils/test_influx.py
index 5f1e2c36f..0852da2dd 100644
--- a/tests/unit/api/utils/test_influx.py
+++ b/tests/unit/api/utils/test_influx.py
@@ -1,3 +1,11 @@
+##############################################################################
+# Copyright (c) 2016 Huawei Technologies Co.,Ltd and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
import unittest
import mock
import uuid
@@ -13,7 +21,7 @@ class GetDataDbClientTestCase(unittest.TestCase):
mock_parser.ConfigParser().get.return_value = 'file'
try:
influx.get_data_db_client()
- except Exception, e:
+ except Exception as e:
self.assertIsInstance(e, RuntimeError)
@@ -54,6 +62,18 @@ class WriteDataTasklistTestCase(unittest.TestCase):
mock_write_data.assert_called_with('tasklist', field, timestamp, tags)
+class QueryTestCase(unittest.TestCase):
+
+ @mock.patch('api.utils.influx.ConfigParser')
+ def test_query_dispatcher_not_influxdb(self, mock_parser):
+ mock_parser.ConfigParser().get.return_value = 'file'
+ try:
+ sql = 'select * form tasklist'
+ influx.query(sql)
+ except Exception as e:
+ self.assertIsInstance(e, RuntimeError)
+
+
def main():
unittest.main()