diff options
Diffstat (limited to 'api')
-rw-r--r-- | api/actions/env.py | 85 | ||||
-rw-r--r-- | api/actions/result.py | 61 | ||||
-rw-r--r-- | api/actions/test.py | 22 | ||||
-rwxr-xr-x | api/api-prepare.sh | 37 | ||||
-rw-r--r-- | api/conf.py | 8 | ||||
-rw-r--r-- | api/server.py | 11 | ||||
-rw-r--r-- | api/urls.py | 12 | ||||
-rw-r--r-- | api/utils/common.py | 34 | ||||
-rw-r--r-- | api/utils/daemonthread.py | 8 | ||||
-rw-r--r-- | api/utils/influx.py | 20 | ||||
-rw-r--r-- | api/views.py | 50 | ||||
-rw-r--r-- | api/yardstick.ini | 16 | ||||
-rw-r--r-- | api/yardstick.sock | 0 |
13 files changed, 336 insertions, 28 deletions
diff --git a/api/actions/env.py b/api/actions/env.py new file mode 100644 index 000000000..321649940 --- /dev/null +++ b/api/actions/env.py @@ -0,0 +1,85 @@ +############################################################################## +# 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 +import threading +import time + +from docker import Client + +from yardstick.common import constants as config +from yardstick.common import utils as yardstick_utils +from api import conf as api_conf +from api.utils import common as common_utils +from api.utils import influx + +logger = logging.getLogger(__name__) + + +def createInfluxDBContainer(args): + try: + container = _create_influxdb_container() + _config_output_file() + thread = threading.Thread(target=_config_influxdb) + thread.start() + return common_utils.result_handler('success', container) + except Exception as e: + message = 'Failed to create influxdb container: %s' % e + return common_utils.error_handler(message) + + +def _create_influxdb_container(): + client = Client(base_url=config.DOCKER_URL) + + ports = [8083, 8086] + port_bindings = {k: k for k in ports} + host_config = client.create_host_config(port_bindings=port_bindings) + + container = client.create_container(image='tutum/influxdb', + ports=ports, + detach=True, + tty=True, + host_config=host_config) + client.start(container) + return container + + +def _config_influxdb(): + time.sleep(20) + try: + client = influx.get_data_db_client() + client.create_user(config.USER, config.PASSWORD, config.DATABASE) + client.create_database(config.DATABASE) + logger.info('Success to config influxDB') + except Exception as e: + logger.debug('Failed to config influxDB: %s', e) + + +def _config_output_file(): + yardstick_utils.makedirs('/etc/yardstick') + with open('/etc/yardstick/yardstick.conf', 'w') as f: + f.write("""\ +[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://%s:8086 +db_name = yardstick +username = root +password = root +""" + % api_conf.GATEWAY_IP) diff --git a/api/actions/result.py b/api/actions/result.py new file mode 100644 index 000000000..10112ac68 --- /dev/null +++ b/api/actions/result.py @@ -0,0 +1,61 @@ +############################################################################## +# 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 +import uuid +import re + +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'] + + if re.search("[^a-zA-Z0-9_-]", measurement): + raise ValueError('invalid measurement parameter') + + uuid.UUID(task_id) + except KeyError: + message = 'measurement and task_id must be provided' + return common_utils.error_handler(message) + + measurement = conf.TEST_CASE_PRE + measurement + + query_template = "select * from %s where task_id='%s'" + query_sql = query_template % ('tasklist', task_id) + data = common_utils.translate_to_str(influx_utils.query(query_sql)) + + def _unfinished(): + return common_utils.result_handler(0, []) + + def _finished(): + query_sql = query_template % (measurement, task_id) + data = common_utils.translate_to_str(influx_utils.query(query_sql)) + + 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..fda0ffd32 100644 --- a/api/actions/test.py +++ b/api/actions/test.py @@ -1,5 +1,12 @@ +############################################################################## +# 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 import logging @@ -14,12 +21,7 @@ def runTestCase(args): opts = args.get('opts', {}) testcase = args['testcase'] except KeyError: - logger.error('Lack of testcase argument') - result = { - 'status': 'error', - 'message': 'need testcase name' - } - return json.dumps(result) + return common_utils.error_handler('Lack of testcase argument') testcase = os.path.join(conf.TEST_CASE_PATH, conf.TEST_CASE_PRE + testcase + '.yaml') @@ -33,8 +35,4 @@ def runTestCase(args): logger.debug('Start to execute command list') common_utils.exec_command_task(command_list, task_id) - result = { - 'status': 'success', - 'task_id': task_id - } - return json.dumps(result) + return common_utils.result_handler('success', task_id) diff --git a/api/api-prepare.sh b/api/api-prepare.sh new file mode 100755 index 000000000..c05dbb5ff --- /dev/null +++ b/api/api-prepare.sh @@ -0,0 +1,37 @@ +#!/bin/bash +############################################################################## +# 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 +############################################################################## + +# 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..3f104c61a 100644 --- a/api/server.py +++ b/api/server.py @@ -1,9 +1,18 @@ +############################################################################## +# 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 from flask_restful import Api from api.urls import urlpatterns +from yardstick import _init_logging logger = logging.getLogger(__name__) @@ -15,5 +24,7 @@ reduce(lambda a, b: a.add_resource(b.resource, b.url, endpoint=b.endpoint) or a, urlpatterns, api) if __name__ == '__main__': + _init_logging() + logger.setLevel(logging.DEBUG) logger.info('Starting server') app.run(host='0.0.0.0') diff --git a/api/urls.py b/api/urls.py index 9fa0bc935..323e5cb9f 100644 --- a/api/urls.py +++ b/api/urls.py @@ -1,7 +1,17 @@ +############################################################################## +# 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/testcases/release/action', views.Release, 'release'), + Url('/yardstick/results', views.Results, 'results'), + Url('/yardstick/env/action', views.Env, 'env') ] diff --git a/api/utils/common.py b/api/utils/common.py index 9d7998abd..e3e64a72b 100644 --- a/api/utils/common.py +++ b/api/utils/common.py @@ -1,8 +1,21 @@ +############################################################################## +# 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 + +from flask import jsonify 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,9 +33,9 @@ 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]) + command_list.extend(['--task-args', str(task_args)]) return command_list @@ -32,6 +45,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 jsonify(result) + + +def result_handler(status, data): + result = { + 'status': status, + 'result': data + } + return jsonify(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..065de673b 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,24 +13,43 @@ 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 +from api.actions import env as env_action logger = logging.getLogger(__name__) -class Test(Resource): +class Release(Resource): def post(self): action = common_utils.translate_to_str(request.json.get('action', '')) 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 Results(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') + + +class Env(Resource): + def post(self): + action = common_utils.translate_to_str(request.json.get('action', '')) + args = common_utils.translate_to_str(request.json.get('args', {})) + logger.debug('Input args is: action: %s, args: %s', action, args) + + try: + return getattr(env_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..01025c2ef --- /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/opnfv/repos/yardstick/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 |