From c383ae3fa6ccb865575eacf78209fdd3ac7efa69 Mon Sep 17 00:00:00 2001 From: chenjiankun Date: Mon, 28 Nov 2016 01:51:47 +0000 Subject: Create API and command to create a influxDB container JIRA: YARDSTICK-425 This API is used to create a influxDB Container Add command line to create a influxDB Container, too Change-Id: If9c2d04b779924d492a5d5ea91f7968fa959570e Signed-off-by: chenjiankun --- api/actions/env.py | 85 ++++++++++++++++++++++++++++++++++++ api/api-prepare.sh | 40 ++++------------- api/urls.py | 3 +- api/views.py | 13 ++++++ install.sh | 2 +- requirements.txt | 1 + tests/unit/api/actions/test_env.py | 50 +++++++++++++++++++++ tests/unit/api/test_views.py | 12 +++++ tests/unit/cmd/commands/test_env.py | 29 ++++++++++++ tests/unit/common/test_httpClient.py | 33 ++++++++++++++ yardstick/cmd/cli.py | 4 +- yardstick/cmd/commands/env.py | 17 ++++++++ yardstick/common/constants.py | 7 +++ yardstick/common/httpClient.py | 27 ++++++++++++ yardstick/common/utils.py | 9 ++++ 15 files changed, 298 insertions(+), 34 deletions(-) create mode 100644 api/actions/env.py create mode 100644 tests/unit/api/actions/test_env.py create mode 100644 tests/unit/cmd/commands/test_env.py create mode 100644 tests/unit/common/test_httpClient.py create mode 100644 yardstick/cmd/commands/env.py create mode 100644 yardstick/common/httpClient.py 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/api-prepare.sh b/api/api-prepare.sh index 075d7875c..c05dbb5ff 100755 --- a/api/api-prepare.sh +++ b/api/api-prepare.sh @@ -1,41 +1,19 @@ #!/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 +############################################################################## +# 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}" + cat << EOF > "${nginx_config}" server { listen 5000; server_name localhost; diff --git a/api/urls.py b/api/urls.py index 2a9e72a76..eaaf8b6d1 100644 --- a/api/urls.py +++ b/api/urls.py @@ -12,5 +12,6 @@ from api.utils.common import Url urlpatterns = [ Url('/yardstick/test/action', views.Test, 'test'), - Url('/yardstick/result/action', views.Result, 'result') + Url('/yardstick/result/action', views.Result, 'result'), + Url('/yardstick/env/action', views.Env, 'env') ] diff --git a/api/views.py b/api/views.py index e78389f5a..7357625e0 100644 --- a/api/views.py +++ b/api/views.py @@ -14,6 +14,7 @@ from flask_restful import Resource from api.utils import common as common_utils from api.actions import test as test_action from api.actions import result as result_action +from api.actions import env as env_action logger = logging.getLogger(__name__) @@ -40,3 +41,15 @@ class Result(Resource): 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/install.sh b/install.sh index 8fdd07569..afb735195 100755 --- a/install.sh +++ b/install.sh @@ -14,7 +14,7 @@ apt-get update && apt-get install -y \ libxml2-dev \ libxslt1-dev \ nginx \ - uswgi \ + uwsgi \ uwsgi-plugin-python \ python-setuptools && \ easy_install -U setuptools diff --git a/requirements.txt b/requirements.txt index ab20c7541..b47951e0a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -81,3 +81,4 @@ flask==0.11.1 flask-restful==0.3.5 influxdb==3.0.0 pyroute2==0.4.10 +docker-py==1.10.6 diff --git a/tests/unit/api/actions/test_env.py b/tests/unit/api/actions/test_env.py new file mode 100644 index 000000000..e674d73d2 --- /dev/null +++ b/tests/unit/api/actions/test_env.py @@ -0,0 +1,50 @@ +############################################################################## +# 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 + +from api.actions import env + + +class CreateInfluxDBContainerTestCase(unittest.TestCase): + + @mock.patch('api.actions.env._create_influxdb_container') + def test_create_influxdb_container(self, mock_create_container): + env.createInfluxDBContainer({}) + mock_create_container.assert_called_with() + + +class CreateInfluxdbContainerTestCase(unittest.TestCase): + + @mock.patch('api.actions.env.Client') + def test_create_influxdb_container(self, mock_influx_client): + env._create_influxdb_container() + self.assertFalse(mock_influx_client()._create_container.called) + + +class ConfigInfluxdbTestCase(unittest.TestCase): + + @mock.patch('api.actions.env.influx.get_data_db_client') + def test_config_influxdb(self, mock_influx_client): + env._config_influxdb() + mock_influx_client.assert_called_with() + + +class ConfigOutputFile(unittest.TestCase): + + def test_config_output_file(self): + pass + + +def main(): + unittest.main() + + +if __name__ == '__main__': + main() diff --git a/tests/unit/api/test_views.py b/tests/unit/api/test_views.py index e57ec08a4..b83556713 100644 --- a/tests/unit/api/test_views.py +++ b/tests/unit/api/test_views.py @@ -12,6 +12,7 @@ import json from api.views import Test from api.views import Result +from api.views import Env class TestTestCase(unittest.TestCase): @@ -37,6 +38,17 @@ class ResultTestCase(unittest.TestCase): self.assertEqual('error', result['status']) +class EnvTestCase(unittest.TestCase): + + @mock.patch('api.views.request') + def test_post(self, mock_request): + mock_request.json.get.side_effect = ['hello', {}] + + result = json.loads(Env().post()) + + self.assertEqual('error', result['status']) + + def main(): unittest.main() diff --git a/tests/unit/cmd/commands/test_env.py b/tests/unit/cmd/commands/test_env.py new file mode 100644 index 000000000..af1ab8030 --- /dev/null +++ b/tests/unit/cmd/commands/test_env.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 mock + +from yardstick.cmd.commands.env import EnvCommand + + +class EnvCommandTestCase(unittest.TestCase): + + @mock.patch('yardstick.cmd.commands.env.HttpClient') + def test_do_influxdb(self, mock_http_client): + env = EnvCommand() + env.do_influxdb({}) + self.assertTrue(mock_http_client().post.called) + + +def main(): + unittest.main() + + +if __name__ == '__main__': + main() diff --git a/tests/unit/common/test_httpClient.py b/tests/unit/common/test_httpClient.py new file mode 100644 index 000000000..b39dc2332 --- /dev/null +++ b/tests/unit/common/test_httpClient.py @@ -0,0 +1,33 @@ +############################################################################## +# 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 yardstick.common import httpClient + + +class HttpClientTestCase(unittest.TestCase): + + @mock.patch('yardstick.common.httpClient.requests') + def test_post(self, mock_requests): + url = 'http://localhost:5000/hello' + data = {'hello': 'world'} + headers = {'Content-Type': 'application/json'} + httpClient.HttpClient().post(url, data) + mock_requests.post.assert_called_with(url, data=json.dumps(data), + headers=headers) + + +def main(): + unittest.main() + + +if __name__ == '__main__': + main() diff --git a/yardstick/cmd/cli.py b/yardstick/cmd/cli.py index ee8d1c529..d141731e1 100644 --- a/yardstick/cmd/cli.py +++ b/yardstick/cmd/cli.py @@ -24,6 +24,7 @@ from yardstick.cmd.commands import runner from yardstick.cmd.commands import scenario from yardstick.cmd.commands import testcase from yardstick.cmd.commands import plugin +from yardstick.cmd.commands import env CONF = cfg.CONF cli_opts = [ @@ -62,7 +63,8 @@ class YardstickCLI(): 'runner': runner.RunnerCommands, 'scenario': scenario.ScenarioCommands, 'testcase': testcase.TestcaseCommands, - 'plugin': plugin.PluginCommands + 'plugin': plugin.PluginCommands, + 'env': env.EnvCommand } def __init__(self): diff --git a/yardstick/cmd/commands/env.py b/yardstick/cmd/commands/env.py new file mode 100644 index 000000000..d9c0c0a3f --- /dev/null +++ b/yardstick/cmd/commands/env.py @@ -0,0 +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 yardstick.common.httpClient import HttpClient + + +class EnvCommand(object): + + def do_influxdb(self, args): + url = 'http://localhost:5000/yardstick/env/action' + data = {'action': 'createInfluxDBContainer'} + HttpClient().post(url, data) diff --git a/yardstick/common/constants.py b/yardstick/common/constants.py index 40b29a717..8fbc82f0e 100644 --- a/yardstick/common/constants.py +++ b/yardstick/common/constants.py @@ -1,3 +1,10 @@ CONFIG_SAMPLE = '/etc/yardstick/config.yaml' RELENG_DIR = 'releng.dir' + +DOCKER_URL = 'unix://var/run/docker.sock' + +# database config +USER = 'root' +PASSWORD = 'root' +DATABASE = 'yardstick' diff --git a/yardstick/common/httpClient.py b/yardstick/common/httpClient.py new file mode 100644 index 000000000..b6959b400 --- /dev/null +++ b/yardstick/common/httpClient.py @@ -0,0 +1,27 @@ +############################################################################## +# 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 json +import logging + +import requests + +logger = logging.getLogger(__name__) + + +class HttpClient(object): + + def post(self, url, data): + data = json.dumps(data) + headers = {'Content-Type': 'application/json'} + try: + response = requests.post(url, data=data, headers=headers) + result = response.json() + logger.debug('The result is: %s', result) + except Exception as e: + logger.debug('Failed: %s', e) diff --git a/yardstick/common/utils.py b/yardstick/common/utils.py index d639fb66a..afbe4e8ec 100644 --- a/yardstick/common/utils.py +++ b/yardstick/common/utils.py @@ -18,6 +18,7 @@ import os import sys import yaml +import errno from oslo_utils import importutils import yardstick @@ -91,3 +92,11 @@ def get_para_from_yaml(file_path, args): else: print 'file not exist' return None + + +def makedirs(d): + try: + os.makedirs(d) + except OSError as e: + if e.errno != errno.EEXIST: + raise -- cgit 1.2.3-korg