diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | INFO | 1 | ||||
-rw-r--r-- | docs/apidocs/.keep | 0 | ||||
-rw-r--r-- | docs/configguide/configuration.rst (renamed from docs/user_guides/02-installation.rst) | 153 | ||||
-rw-r--r-- | docs/configguide/index.rst | 13 | ||||
-rw-r--r-- | docs/roadmap/index.rst | 13 | ||||
-rw-r--r-- | docs/roadmap/roadmap.rst (renamed from docs/roadmap.rst) | 0 | ||||
-rw-r--r-- | docs/templates/index.rst | 35 | ||||
-rw-r--r-- | docs/templates/sample_config.yaml (renamed from docs/sample_config.yaml) | 0 | ||||
-rw-r--r-- | docs/user_guides/01-introduction.rst | 40 | ||||
-rw-r--r-- | docs/user_guides/index.rst | 17 | ||||
-rw-r--r-- | docs/userguide/01-compute.rst (renamed from docs/user_guides/test_cases/01-compute_testcases.rst) | 17 | ||||
-rw-r--r-- | docs/userguide/02-network.rst (renamed from docs/user_guides/test_cases/02-network_testcases.rst) | 19 | ||||
-rw-r--r-- | docs/userguide/03-storage.rst (renamed from docs/user_guides/test_cases/03-storage_testcases.rst) | 18 | ||||
-rw-r--r-- | docs/userguide/index.rst | 21 | ||||
-rw-r--r-- | docs/userguide/introduction.rst (renamed from docs/user_guides/03-usage-guide.rst) | 19 | ||||
-rw-r--r-- | docs/userguide/overview.rst | 22 | ||||
-rw-r--r-- | func/args_handler.py | 59 | ||||
-rw-r--r-- | func/cli.py | 81 | ||||
-rw-r--r-- | func/driver.py | 95 | ||||
-rw-r--r-- | func/env_setup.py | 59 | ||||
-rwxr-xr-x | func/fetch_compute_ips.sh | 117 | ||||
-rw-r--r-- | tests/args_handler_test.py | 35 | ||||
-rw-r--r-- | tests/cli_test.py | 18 | ||||
-rw-r--r-- | tests/driver_test.py | 75 | ||||
-rw-r--r-- | tests/env_setup_test.py | 49 |
26 files changed, 629 insertions, 348 deletions
@@ -65,3 +65,4 @@ target/ .*.sw? /docs_build/ /docs_output/ +.idea @@ -19,6 +19,7 @@ Prakash Ramchandran prakash.ramchandran@huawei.com Trevor Cooper trevor.cooper@intel.com Wenjing Chu chu.wenjing@gmail.com Yujun Zhang zhang.yujunz@zte.com.cn +Zhifeng Jiang Jiang.ZhiFeng@zte.com.cn Link to TSC approval of the project: diff --git a/docs/apidocs/.keep b/docs/apidocs/.keep new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/docs/apidocs/.keep diff --git a/docs/user_guides/02-installation.rst b/docs/configguide/configuration.rst index 2f2ecf96..f29947d5 100644 --- a/docs/user_guides/02-installation.rst +++ b/docs/configguide/configuration.rst @@ -1,35 +1,28 @@ -Installation -============ - .. This work is licensed under a Creative Commons Attribution 4.0 International License. .. http://creativecommons.org/licenses/by/4.0 -.. (c) <optionally add copywriters name> -.. two dots create a comment. please leave this logo at the top of each of your rst files. -.. image:: ../etc/opnfv-logo.png - :height: 40 - :width: 200 - :alt: OPNFV - :align: left -.. these two pipes are to seperate the logo from the first title +.. (c) 2015 Dell Inc. +.. (c) 2016 ZTE Corp. + -| +Qtip configuration +================== -QTIP currently supports by using a Docker image or by pulling the repo from the upstream -repository found at https://git.opnfv.org/qtip. Detailed steps about setting up QTIP using both of these options -can be found below. +QTIP currently supports by using a Docker image or by pulling the repo from +the upstream repository found at https://git.opnfv.org/qtip. Detailed steps +about setting up QTIP using both of these options can be found below. -To use QTIP you should have access to an OpenStack environment, -with at least Nova, Neutron, Glance, Keystone and Heat installed. +To use QTIP you should have access to an OpenStack environment, with at least +Nova, Neutron, Glance, Keystone and Heat installed. Add a brief introduction +to configure OPNFV with this specific installer -The steps needed to run QTIP are: -Running QTIP by pulling the upstream code ------------------------------------------ +Pre-configuration activities +---------------------------- -.. _install-dependencies: Setting QTIP framework on Ubuntu 14.04 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + Install dependencies: :: @@ -46,96 +39,116 @@ Download source code and install python dependencies: git clone https://git.opnfv.org/qtip cd qtip + Installing QTIP using Docker ---------------------------------- +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -QTIP has a Docker images on the docker hub which can be pull after docker has been installed. +QTIP has a Docker images on the docker hub. Pulling opnfv/qtip docker image +from docker hub: +:: -Installing Docker -^^^^^^^^^^^^^^^^^ -The first step is to install docker: + sudo docker pull opnfv/qtip + +Verify that opnfv/qtip has been downloaded. It should be listed as an image by +running the following command. :: - sudo apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D + sudo docker images + +Run the Docker instance: +:: + docker run opnfv/qtip -i -t bash -Add an entry for your Ubuntu operating system +Now you are in the container and QTIP can be found in the /repos/qtip and can +be navigated to using the following command. :: - Open the /etc/apt/sources.list.d/docker.list file in your favorite editor. + cd repos/qtip -If the file doesn’t exist, create it. -Remove any existing entries. +OpenStack parameters and credentials +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Add an entry for your Ubuntu operating system. -On Ubuntu Trusty 14.04 (LTS) +Environment variables +""""""""""""""""""""" + +Before running QTIP it is necessary to export OpenStack environment variables +from the OpenStack *openrc* file. This can be done by running the following +command. :: - deb https://apt.dockerproject.org/repo ubuntu-trusty main + source get_env_info.sh -n {INSTALLER_TYPE} -i {INSTALLER_IP} + source opnfv-creds.sh -Update the package manager +This provides a ``opnfv-creds.sh`` file which can be sources to get the +environment variables. For running QTIP manually, it is also necessary to +export the installer type. :: - sudo apt-get update + export INSTALLER_TYPE="{installer-type}" -Install Docker: -:: - sudo apt-get install docker-engine +QTIP default key pair +"""""""""""""""""""""" -Starting Docker Daemon: -:: +QTIP uses a SSH key pair to connect to the guest image. This key pair can +be found in the ``data/`` directory. - sudo service docker start -Pulling opnfv/qtip docker image from docker hub: -:: +Hardware configuration +---------------------- - sudo docker pull opnfv/qtip +Qtip does not have specific hardware requriements, and it can runs over any +OPNFV installer. -Verify that opnfv/qtip has been downloaded. It should be listed as an image by running the following command. -:: - sudo docker images +Jumphost configuration +---------------------- -Run the Docker instance: +Installer Docker on Jumphost, which is used for running Qtip image. + +The first step is to install docker: :: - docker run opnfv/qtip -i -t bash + sudo apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 + --recv-keys 58118E89F3A912897C070ADBF76221572C52609D -Now you are in the container and QTIP can be found in the /repos/qtip and can be navigated to using the following command. +Add an entry for your Ubuntu operating system: :: - cd repos/qtip + Open the /etc/apt/sources.list.d/docker.list file in your favorite editor. +If the file doesn’t exist, create it. -OpenStack parameters and credentials ------------------------------------- +Remove any existing entries. +Add an entry for your Ubuntu operating system. -Environment variables -^^^^^^^^^^^^^^^^^^^^^ -Before running QTIP it is necessary to export OpenStack environment variables -from the OpenStack *openrc* file. This can be done by running the following command. +On Ubuntu Trusty 14.04 (LTS) :: - source get_env_info.sh -n {INSTALLER_TYPE} -i {INSTALLER_IP} - source opnfv-creds.sh + deb https://apt.dockerproject.org/repo ubuntu-trusty main -This provides a ``opnfv-creds.sh`` file which can be sources to get the environment variables. -For running QTIP manually, it is also necessary to export the installer type. :: +Update the package manager +:: - export INSTALLER_TYPE="{installer-type}" + sudo apt-get update -QTIP default key pair -^^^^^^^^^^^^^^^^^^^^^^^^^^ -QTIP uses a SSH key pair to connect to the guest image. This key pair can -be found in the ``data/`` directory. +Install Docker: +:: -Examples --------- -QTIP Has been made with the intention of requiring minimal interaction from the user. + sudo apt-get install docker-engine + +Starting Docker Daemon: +:: + + sudo service docker start + + +Platform components configuration +--------------------------------- +Describe the configuration of each component in the installer diff --git a/docs/configguide/index.rst b/docs/configguide/index.rst new file mode 100644 index 00000000..e8b6f4e1 --- /dev/null +++ b/docs/configguide/index.rst @@ -0,0 +1,13 @@ +.. This work is licensed under a Creative Commons Attribution 4.0 International License. +.. http://creativecommons.org/licenses/by/4.0 +.. (c) 2015 Dell Inc. +.. (c) 2016 ZTE Corp. + +**************** +QTIP Configguide +**************** + +.. toctree:: + :maxdepth: 2 + + ./configuration.rst diff --git a/docs/roadmap/index.rst b/docs/roadmap/index.rst new file mode 100644 index 00000000..4e30d5ae --- /dev/null +++ b/docs/roadmap/index.rst @@ -0,0 +1,13 @@ +.. This work is licensed under a Creative Commons Attribution 4.0 International License. +.. http://creativecommons.org/licenses/by/4.0 +.. (c) 2015 Dell Inc. +.. (c) 2016 ZTE Corp. + +************ +Qtip Roadmap +************ + +.. toctree:: + :maxdepth: 2 + + ./roadmap.rst diff --git a/docs/roadmap.rst b/docs/roadmap/roadmap.rst index 42caec92..42caec92 100644 --- a/docs/roadmap.rst +++ b/docs/roadmap/roadmap.rst diff --git a/docs/templates/index.rst b/docs/templates/index.rst index c893df6f..1a8bc649 100644 --- a/docs/templates/index.rst +++ b/docs/templates/index.rst @@ -1,30 +1,13 @@ -.. OPNFV Release Engineering documentation, created by - sphinx-quickstart on Tue Jun 9 19:12:31 2015. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. +.. This work is licensed under a Creative Commons Attribution 4.0 International License. +.. http://creativecommons.org/licenses/by/4.0 +.. (c) 2015 Dell Inc. +.. (c) 2016 ZTE Corp. -.. image:: ../etc/opnfv-logo.png - :height: 40 - :width: 200 - :alt: OPNFV - :align: left - -Example Documentation table of contents -======================================= - -Contents: +************** +QTIP Templates +************** .. toctree:: - :numbered: - :maxdepth: 4 - - testcase_description_v2_template.rst - -Indices and tables -================== - -* :ref:`search` - -Revision: _sha1_ + :maxdepth: 2 -Build date: |today| + ./testcase_description_v2_template.rst diff --git a/docs/sample_config.yaml b/docs/templates/sample_config.yaml index 8dcaa11c..8dcaa11c 100644 --- a/docs/sample_config.yaml +++ b/docs/templates/sample_config.yaml diff --git a/docs/user_guides/01-introduction.rst b/docs/user_guides/01-introduction.rst deleted file mode 100644 index 6322d092..00000000 --- a/docs/user_guides/01-introduction.rst +++ /dev/null @@ -1,40 +0,0 @@ -Introduction -============ - -.. This work is licensed under a Creative Commons Attribution 4.0 International License. -.. http://creativecommons.org/licenses/by/4.0 -.. (c) <optionally add copywriters name> -.. two dots create a comment. please leave this logo at the top of each of your rst files. -.. image:: ../etc/opnfv-logo.png - :height: 40 - :width: 200 - :alt: OPNFV - :align: left -.. these two pipes are to seperate the logo from the first title - -| - -**Welcome to QTIP's documentation !** - -.. _QTIP: https://wiki.opnfv.org/platform_performance_benchmarking - -QTIP_ is an OPNFV Project. - -QTIP aims to benchmark OPNFV platforms through a "Bottom up" approach, testing bare-metal components first. - -The overall problem this project tries to solve is the general characterization of an OPNFV platform. -It will focus on general performance questions that are common to the platform itself, or applicable to multiple OPNFV use cases. -QTIP will provide the capability to quantify a platform's performance behavior in a standardized, rigorous, and open way. - -The *QTIP* framework is deployed in the Dell OPNFV community lab. It is -infrastructure and application independent. - -.. _Pharos: https://wiki.opnfv.org/pharos -.. seealso:: Pharos_ for information on OPNFV community labs. - -**Contact QTIP** - -Feedback? `Contact us`_ - -.. _Contact us: opnfv-users@lists.opnfv.org - diff --git a/docs/user_guides/index.rst b/docs/user_guides/index.rst deleted file mode 100644 index da14761c..00000000 --- a/docs/user_guides/index.rst +++ /dev/null @@ -1,17 +0,0 @@ -================================ -QTIP Framework Documentation -================================= - -.. toctree:: - :numbered: - :maxdepth: 4 - - 01-introduction.rst - 02-installation.rst - 03-usage-guide.rst - test_cases/01-compute_testcases.rst - test_cases/02-network_testcases.rst - test_cases/03-storage_testcases.rst - -Revision: _sha1_ -Build date: |today| diff --git a/docs/user_guides/test_cases/01-compute_testcases.rst b/docs/userguide/01-compute.rst index b3531298..6e6a7a04 100644 --- a/docs/user_guides/test_cases/01-compute_testcases.rst +++ b/docs/userguide/01-compute.rst @@ -1,19 +1,12 @@ -Compute test cases -================== - .. This wonk is licensed under a Creative Commons Attribution 4.0 International License. .. http://cneativecommons.org/licenses/by/4.0 -.. (c) <optionally add copywniters name> -.. two dots cneate a comment. please leave this logo at the top of each of your rst files. +.. (c) 2015 Dell Inc. +.. (c) 2016 ZTE Corp. -.. image:: ../../etc/opnfv-logo.png - :height: 40 - :width: 200 - :alt: OPNFV - :align: left -.. these two pipes ane to seperate the logo from the first title -| +Compute test cases +================== + Introduction ------------ diff --git a/docs/user_guides/test_cases/02-network_testcases.rst b/docs/userguide/02-network.rst index 45c2d824..bc475ad3 100644 --- a/docs/user_guides/test_cases/02-network_testcases.rst +++ b/docs/userguide/02-network.rst @@ -1,18 +1,11 @@ -Network test cases -================== - .. This work is licensed under a Creative Commons Attribution 4.0 International License. .. http://creativecommons.org/licenses/by/4.0 -.. (c) <optionally add copywriters name> -.. two dots create a comment. please leave this logo at the top of each of your rst files. -.. image:: ../../etc/opnfv-logo.png - :height: 40 - :width: 200 - :alt: OPNFV - :align: left -.. these two pipes are to seperate the logo from the first title - -| +.. (c) 2015 Dell Inc. +.. (c) 2016 ZTE Corp. + + +Network test cases +================== QTIP uses IPerf3 as the main tool for testing the network throughput. There are three tests that are run through the QTIP framework. diff --git a/docs/user_guides/test_cases/03-storage_testcases.rst b/docs/userguide/03-storage.rst index cd557683..ea3bb4f3 100644 --- a/docs/user_guides/test_cases/03-storage_testcases.rst +++ b/docs/userguide/03-storage.rst @@ -1,18 +1,11 @@ -Storage test cases -================== - .. This work is licensed under a Creative Commons Attribution 4.0 International License. .. http://creativecommons.org/licenses/by/4.0 -.. (c) <optionally add copywriters name> -.. two dots create a comment. please leave this logo at the top of each of your rst files. -.. image:: ../../etc/opnfv-logo.png - :height: 40 - :width: 200 - :alt: OPNFV - :align: left -.. these two pipes are to seperate the logo from the first title +.. (c) 2015 Dell Inc. +.. (c) 2016 ZTE Corp. -| + +Storage test cases +================== The QTIP benchmark suite aims to evaluate storage components within an OPNFV platform. For Brahamaputra release, FIO would evaluate File System performance for the host machine. @@ -36,4 +29,3 @@ The FIO Job would consist of: 6. Block size :4K For this Job, I/O per second would be measured along mean I/O latency to provide storage performance numbers. - diff --git a/docs/userguide/index.rst b/docs/userguide/index.rst new file mode 100644 index 00000000..fe24293a --- /dev/null +++ b/docs/userguide/index.rst @@ -0,0 +1,21 @@ +.. This work is licensed under a Creative Commons Attribution 4.0 International License. +.. http://creativecommons.org/licenses/by/4.0 +.. (c) 2015 Dell Inc. +.. (c) 2016 ZTE Corp. + + +************** +QTIP Userguide +************** + +Colorado 1.0 +------------ + +.. toctree:: + :maxdepth: 2 + + ./overview.rst + ./introduction.rst + ./01-compute_testcases.rst + ./02-network_testcases.rst + ./03-storage_testcases.rst diff --git a/docs/user_guides/03-usage-guide.rst b/docs/userguide/introduction.rst index 56cc16b3..d3bba51d 100644 --- a/docs/user_guides/03-usage-guide.rst +++ b/docs/userguide/introduction.rst @@ -1,18 +1,12 @@ -Guide to run QTIP: -================== - .. This work is licensed under a Creative Commons Attribution 4.0 International License. .. http://creativecommons.org/licenses/by/4.0 -.. (c) <optionally add copywriters name> -.. two dots create a comment. please leave this logo at the top of each of your rst files. -.. image:: ../etc/opnfv-logo.png - :height: 40 - :width: 200 - :alt: OPNFV - :align: left -.. these two pipes are to seperate the logo from the first title +.. (c) 2015 Dell Inc. +.. (c) 2016 ZTE Corp. + -| +***************** +Qtip Introduction +***************** This guide will serve as a first step to familiarize the user with how to run QTIP the first time when the user clones QTIP on to their host machine. @@ -341,4 +335,3 @@ Running QTIP on the using `default` as the pod name and for the `storage` suite Results: -------- QTIP generates results in the `results/` directory are listed down under the particularly benchmark name. So all the results for dhrystone would be listed and time stamped. - diff --git a/docs/userguide/overview.rst b/docs/userguide/overview.rst new file mode 100644 index 00000000..82b7de91 --- /dev/null +++ b/docs/userguide/overview.rst @@ -0,0 +1,22 @@ +.. This work is licensed under a Creative Commons Attribution 4.0 International License. +.. http://creativecommons.org/licenses/by/4.0 +.. (c) 2015 Dell Inc. +.. (c) 2016 ZTE Corp. + + +******** +Overview +******** + +.. _QTIP: https://wiki.opnfv.org/platform_performance_benchmarking + +QTIP_ is an OPNFV Project. + +QTIP aims to benchmark OPNFV platforms through a "Bottom up" approach, testing +bare-metal components first. + +The overall problem this project tries to solve is the general +characterization of an OPNFV platform. It will focus on general performance +questions that are common to the platform itself, or applicable to multiple +OPNFV use cases. QTIP will provide the capability to quantify a platform's +performance behavior in a standardized, rigorous, and open way. diff --git a/func/args_handler.py b/func/args_handler.py new file mode 100644 index 00000000..f2726eb8 --- /dev/null +++ b/func/args_handler.py @@ -0,0 +1,59 @@ +############################################################################## +# Copyright (c) 2016 ZTE Corp 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 os +from func.env_setup import Env_setup +from func.spawn_vm import SpawnVM +from func.driver import Driver + + +def get_files_in_test_list(suit_name): + with open('test_list/' + suit_name, 'r') as fin_put: + benchmark_list = fin_put.readlines() + return map(lambda x: x.rstrip(), benchmark_list) + + +def get_files_in_test_case(lab, suit_name): + return os.listdir('./test_cases/{0}/{1}'.format(lab, suit_name)) + + +def get_benchmark_path(lab, suit, benchmark): + return './test_cases/{0}/{1}/{2}'.format(lab, suit, benchmark) + + +def check_suit_in_test_list(suit_name): + return True if os.path.isfile('test_list/' + suit_name) else False + + +def check_lab_name(lab_name): + return True if os.path.isdir('test_cases/' + lab_name) else False + + +def _get_f_name(test_case_path): + return test_case_path.split('/')[-1] + + +def prepare_ansible_env(benchmark_test_case): + env_setup = Env_setup() + [benchmark, vm_info, benchmark_details, proxy_info] = env_setup.parse(benchmark_test_case) + SpawnVM(vm_info) if len(vm_info) else None + env_setup.call_ping_test() + env_setup.call_ssh_test() + env_setup.update_ansible() + return benchmark, benchmark_details, proxy_info, env_setup + + +def run_benchmark(benchmark, benchmark_details, proxy_info, env_setup, benchmark_test_case): + driver = Driver() + driver.drive_bench(benchmark, env_setup.roles_dict.items(), _get_f_name(benchmark_test_case), + benchmark_details, env_setup.ip_pw_dict.items(), proxy_info) + + +def prepare_and_run_benchmark(benchmark_test_case): + benchmark, benchmark_details, proxy_info, env_setup = prepare_ansible_env(benchmark_test_case) + run_benchmark(benchmark, benchmark_details, proxy_info, env_setup, benchmark_test_case) diff --git a/func/cli.py b/func/cli.py index 4613b507..01694a9b 100644 --- a/func/cli.py +++ b/func/cli.py @@ -8,50 +8,13 @@ ############################################################################## import sys -import os -from func.env_setup import Env_setup -from func.driver import Driver -from func.spawn_vm import SpawnVM +import args_handler import argparse class cli: @staticmethod - def _getfile(file_path): - with open('test_list/' + file_path, 'r') as fin_put: - _benchmarks = fin_put.readlines() - for items in range(len(_benchmarks)): - _benchmarks[items] = _benchmarks[items].rstrip() - return _benchmarks - - @staticmethod - def _getsuite(file_path): - - return file_path - - @staticmethod - def _check_test_list(filename): - - if os.path.isfile('test_list/' + filename): - return True - else: - return False - - @staticmethod - def _check_lab_name(lab_name): - - if os.path.isdir('test_cases/' + lab_name): - return True - else: - return False - - @staticmethod - def _get_f_name(file_name): - - return file_name[0: file_name.find('.')] - - @staticmethod def _parse_args(args): parser = argparse.ArgumentParser() parser.add_argument('-l ', '--lab', required=True, help='Name of Lab ' @@ -72,40 +35,22 @@ class cli: def __init__(self, args=sys.argv[1:]): - suite = [] args = self._parse_args(args) - - if not self._check_test_list(args.file): + if not args_handler.check_suit_in_test_list(args.file): print '\n\n ERROR: Test File Does not exist in test_list/ please enter correct file \n\n' sys.exit(0) - if not self._check_lab_name(args.lab): - print '\n\n You have specified a lab that is not present in test_cases/ please enter correct \ - file. If unsure how to proceed, use -l default.\n\n' + if not args_handler.check_lab_name(args.lab): + print '\n\n You have specified a lab that is not present in test_cases/ please enter \ + correct file. If unsure how to proceed, use -l default.\n\n' sys.exit(0) + suite = args.file + benchmarks = args_handler.get_files_in_test_list(suite) + test_cases = args_handler.get_files_in_test_case(args.lab, suite) + benchmarks_list = filter(lambda x: x in test_cases, benchmarks) - benchmarks = self._getfile(args.file) - suite.append(args.file) - suite = self._getsuite(suite) - for items in range(len(benchmarks)): - if suite and benchmarks: - obj = Env_setup() - if os.path.isfile('./test_cases/' + args.lab.lower() + '/' + suite[0] + '/' + benchmarks[items]): - [benchmark, vm_info, benchmark_details, proxy_info] = \ - obj.parse('./test_cases/' + args.lab.lower() + '/' + suite[0] + '/' + benchmarks[items]) + map(lambda x: args_handler.prepare_and_run_benchmark( + args_handler.get_benchmark_path(args.lab.lower(), suite, x)), benchmarks_list) - if len(vm_info) != 0: - SpawnVM(vm_info) - obj.call_ping_test() - obj.call_ssh_test() - obj.update_ansible() - dvr = Driver() - dvr.drive_bench(benchmark, - obj.roles_dict.items(), - self._get_f_name(benchmarks[items]), - benchmark_details, - obj.ip_pw_dict.items(), - proxy_info) - else: - print (benchmarks[items], ' is not a Template in the Directory - \ - Enter a Valid file name. or use qtip.py -h for list') + print('{0} is not a Template in the Directory Enter a Valid file name.' + 'or use qtip.py -h for list'.format(filter(lambda x: x not in test_cases, benchmarks))) diff --git a/func/driver.py b/func/driver.py index 33dbe320..f26f63db 100644 --- a/func/driver.py +++ b/func/driver.py @@ -8,53 +8,66 @@ ############################################################################## import os import json -from collections import defaultdict +import logging class Driver: def __init__(self): - print "Class driver initialized\n" - print os.environ['PWD'] - self.dic_json = defaultdict() + logging.info("Class driver initialized\n") + self.installer_username = {'fuel': 'root', + 'joid': 'ubuntu', + 'apex': 'heat-admin'} - def drive_bench(self, benchmark, roles, benchmark_fname, benchmark_detail=None, pip_dict=None, proxy_info=None): + @staticmethod + def merge_two_dicts(x, y): + ''' + It is from http://stackoverflow.com/questions/38987/ + how-can-i-merge-two-python-dictionaries-in-a-single-expression + ''' + z = x.copy() + z.update(y) + return z + + def get_common_var_json(self, benchmark_fname, benchmark_detail, pip_dict, proxy_info): + common_json = {'Dest_dir': 'results', + 'ip1': '', + 'ip2': '', + 'installer': str(os.environ['INSTALLER_TYPE']), + 'workingdir': str(os.environ['PWD']), + 'fname': str(benchmark_fname), + 'username': self.installer_username[str(os.environ['INSTALLER_TYPE'])]} + common_json.update(benchmark_detail) if benchmark_detail else None + common_json.update(proxy_info) if proxy_info else None + return common_json + + def get_special_var_json(self, role, roles, benchmark_detail, pip_dict): + special_json = {} + index = roles.index(role) + 1 + special_json.update({'role': role[0]}) + private_ip = pip_dict[0][1] if pip_dict[0][1][0] else 'NONE' + map(lambda x: special_json.update({'ip' + str(index): x}), role[1])\ + if benchmark_detail and (role[0] == '1-server') else None + map(lambda x: special_json.update({'privateip' + str(index): private_ip}), role[1])\ + if benchmark_detail and (role[0] == '1-server') else None + return special_json + + def run_ansible_playbook(self, benchmark, extra_vars): + extra_vars_json = json.dumps(dict(extra_vars.items())) + logging.info(extra_vars_json) + run_play = 'ansible-playbook ./benchmarks/playbooks/{0}.yaml' \ + '--private-key=./data/QtipKey -i ./data/hosts --extra-vars \'{1}\'' \ + .format(benchmark, extra_vars_json) + os.system(run_play) + + def drive_bench(self, benchmark, roles, benchmark_fname, + benchmark_detail=None, pip_dict=None, proxy_info=None): roles = sorted(roles) pip_dict = sorted(pip_dict) - result_dir = 'results' - benchmark_name = benchmark + '.yaml' - self.dic_json['Dest_dir'] = str(result_dir) - self.dic_json['ip1'] = '' - self.dic_json['ip2'] = '' - self.dic_json['installer'] = str(os.environ['INSTALLER_TYPE']) - self.dic_json['workingdir'] = str(os.environ['PWD']) - self.dic_json['fname'] = str(benchmark_fname) - self.dic_json['username'] = str('root') - - for key in proxy_info.keys(): - self.dic_json[key] = proxy_info[key] - - if os.environ['INSTALLER_TYPE'] == str('joid'): - self.dic_json['username'] = str('ubuntu') - if os.environ['INSTALLER_TYPE'] == str('apex'): - self.dic_json['username'] = str('heat-admin') - for k, v in benchmark_detail: - self.dic_json[k] = v - for k, v in roles: - self.dic_json['role'] = k - index = 1 - if benchmark_detail is not None: - for values in v: - if k == '1-server': - print values, 'saving IP' - self.dic_json['ip' + str(index)] = str(values) - if pip_dict[0][1][0]: - self.dic_json['privateip' + str(index)] = pip_dict[0][1] - if not pip_dict[0][1][0]: - self.dic_json['privateip' + str(index)] = 'NONE' - index = index + 1 - dic_json = json.dumps(dict(self.dic_json.items())) - print dic_json - run_play = 'ansible-playbook ./benchmarks/playbooks/{0} --private-key=./data/QtipKey -i ./data/hosts --extra-vars \'{1}\''.format(benchmark_name, dic_json) - os.system(run_play) + var_json = self.get_common_var_json(benchmark_fname, benchmark_detail, pip_dict, proxy_info) + map(lambda role: self.run_ansible_playbook + (benchmark, self.merge_two_dicts(var_json, + self.get_special_var_json(role, roles, + benchmark_detail, + pip_dict))), roles) diff --git a/func/env_setup.py b/func/env_setup.py index f59883a0..1f86f0ea 100644 --- a/func/env_setup.py +++ b/func/env_setup.py @@ -1,5 +1,5 @@ ############################################################################## -# Copyright (c) 2015 Dell Inc and others. +# Copyright (c) 2016 Dell Inc, ZTE and others. # # All rights reserved. This program and the accompanying materials # are made available under the terms of the Apache License, Version 2.0 @@ -14,9 +14,16 @@ import yaml import time import paramiko import socket +from os.path import expanduser +import random +import logging + +LOG = logging.getLogger(__name__) +LOG.setLevel(logging.DEBUG) class Env_setup: + roles_ip_list = [] # ROLE and its corresponding IP address list ip_pw_list = [] # IP and password, this will be used to ssh roles_dict = defaultdict(list) @@ -112,10 +119,58 @@ class Env_setup: break print ('\n\n %s is UP \n\n ' % ipvar) - def get_host_machine_info(self, host_tag): + @staticmethod + def fetch_compute_ips(): + LOG.info("Fetch compute ips through installer") + ips = [] + + installer_type = os.environ['INSTALLER_TYPE'] + installer_ip = os.environ['INSTALLER_IP'] + if installer_type.down.lower() != "fuel" or "compass": + raise RuntimeError("%s is not supported" % installer_type) + if installer_ip: + raise RuntimeError("undefine environment variable INSTALLER_IP") + + cmd = "bash ./fetch_compute_ip.sh -i %s -a %s" % \ + (installer_type, installer_ip) + os.system(cmd) + home = expanduser("~") + os.chdir(home) + with open("ips.log", "r") as file: + data = file.read() + if data: + ips.extend(data.rstrip('\n').split('\n')) + LOG.info("All compute ips: %s" % ips) + return ips + + def check_machine_ips(self, host_tag): + LOG.info("Check machine ips") + ips = self.fetch_compute_ips() + ips_num = len(ips) + num = len(host_tag) + if num > ips_num: + err = "host num %s > compute ips num %s" % (num, ips_num) + raise RuntimeError(err) + for x in range(num): + hostlabel = 'machine_' + str(x + 1) + if host_tag[hostlabel]['ip']: + if host_tag[hostlabel]['ip'] in ips: + info = "%s's ip %s is defined by test case yaml file" % \ + (hostlabel, host_tag[hostlabel]['ip']) + LOG.info(info) + else: + err = "%s is not in %s" % (host_tag[hostlabel]['ip'], ips) + raise RuntimeError(err) + else: + host_tag[hostlabel]['ip'] = random.choice(ips) + info = "assign ip %s to %s" % (host_tag[hostlabel]['ip'], hostlabel) + ips.remove(host_tag[hostlabel]['ip']) + + def get_host_machine_info(self, host_tag): num = len(host_tag) offset = len(self.roles_ip_list) + self.check_machine_ips(host_tag) for x in range(num): hostlabel = 'machine_' + str(x + 1) self.roles_ip_list.insert( diff --git a/func/fetch_compute_ips.sh b/func/fetch_compute_ips.sh new file mode 100755 index 00000000..c1cc4c6e --- /dev/null +++ b/func/fetch_compute_ips.sh @@ -0,0 +1,117 @@ +#!/bin/bash +############################################################################## +#Copyright (c) 2016 Ericsson AB, ZTE and others. +#jose.lausuch@ericsson.com +#wu.zhihui1@zte.com.cn +#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 +############################################################################## + + +usage(){ + echo "usage: $0 [-v] -i <installer_type> -a <installer_ip>" >&2 + echo "[-v] Virtualized deployment" >&2 +} + +info() { + logger -s -t "fetch_compute_info.info" "$*" +} + + +error() { + logger -s -t "fetch_compute_info.error" "$*" + exit 1 +} + +verify_connectivity(){ + local ip=$1 + info "Verifying connectivity to $ip..." + for i in $(seq 0 10); do + if ping -c 1 -W 1 $ip > /dev/null; then + info "$ip is reachable!" + return 0 + fi + sleep 1 + done + error "Can not talk to $ip." +} + +:${DEPLOY_TYPE:=''} + +#Getoptions +whilegetopts ":d:i:a:h:v" optchar; do + case "${optchar}" in + i) installer_type=${OPTARG} ;; + a) installer_ip=${OPTARG} ;; + v) DEPLOY_TYPE="virt" ;; + *) echo "Non-option argument: '-${OPTARG}'" >&2 + usage + exit 2 + ;; + esac +done + +#set vars from env if not provided by user as options +installer_type=${installer_type:-$INSTALLER_TYPE} +installer_ip=${installer_ip:-$INSTALLER_IP} + +if[ -z $installer_type ] || [ -z $installer_ip ]; then + usage + exit 2 +fi + +ssh_options="-oUserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no" + +#Start fetching compute ip +if[ "$installer_type" == "fuel" ]; then + verify_connectivity $installer_ip + + env=$(sshpass -p r00tme ssh 2>/dev/null $ssh_options root@${installer_ip} \ + 'fuel env'|grep operational|head -1|awk '{print $1}') &> /dev/null + if [ -z $env ]; then + error "No operational environment detected in Fuel" + fi + env_id="${FUEL_ENV:-$env}" + + # Check if compute is alive (online='True') + IPS=$(sshpass -p r00tme ssh 2>/dev/null $ssh_options root@${installer_ip} \ + "fuel node --env ${env_id} | grep compute | grep 'True\| 1' | awk -F\| '{print \$5}' " | \ + sed 's/ //g') &> /dev/null + + +elif[ "$installer_type" == "apex" ]; then + echo "not implement now" + exit 1 + +elif[ "$installer_type" == "compass" ]; then + # need test + verify_connectivity $installer_ip + IPS=$(sshpass -p'root' ssh 2>/dev/null $ssh_options root@${installer_ip} \ + 'mysql -ucompass -pcompass -Dcompass -e"select * from cluster;"' \ + | awk -F"," '{for(i=1;i<NF;i++)if($i~/\"host[4-5]\"/) {print $(i+1);}}' \ + | grep -oP "\d+.\d+.\d+.\d+") + +elif[ "$installer_type" == "joid" ]; then + echo "not implement now" + exit 1 + +elif[ "$installer_type" == "foreman" ]; then + echo "not implement now" + exit 1 + +else + error "Installer $installer is not supported by this script" +fi + +if[ -z $IPS ]; then + error "The compute node $IPS are not up. Please check that the POD is correctly deployed." +else + echo "-------- all compute node ips: --------" + touch $HOME/ips.log + echo "$IPS" > $HOME/ips.log + echo $IPS +fi + +exit0 diff --git a/tests/args_handler_test.py b/tests/args_handler_test.py new file mode 100644 index 00000000..7f977f21 --- /dev/null +++ b/tests/args_handler_test.py @@ -0,0 +1,35 @@ +############################################################################## +# Copyright (c) 2016 ZTE Corp 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 pytest +import mock +import func.args_handler + + +class TestClass: + @pytest.mark.parametrize("test_input, expected", [ + ('./test_cases/zte-pod1/network/iperf_bm.yaml', + ["iperf", + [('1-server', ['10.20.0.23']), ('2-host', ['10.20.0.24'])], + "iperf_bm.yaml", + [('duration', 20), ('protocol', 'tcp'), ('bandwidthGbps', 10)], + [("10.20.0.24", [None]), ("10.20.0.23", [None])], {}]) + ]) + @mock.patch('func.args_handler.Env_setup.call_ping_test') + @mock.patch('func.args_handler.Env_setup.call_ssh_test') + @mock.patch('func.args_handler.Env_setup.update_ansible') + @mock.patch('func.args_handler.SpawnVM') + @mock.patch('func.args_handler.Driver.drive_bench') + def test_prepare_and_run_benchmark_successful(self, mock_driver, mock_sqawn_vm, mock_env_setup_ping, + mock_env_setup_ssh, mock_update_ansible, test_input, expected): + mock_ips = mock.Mock(return_value=["10.20.0.23", "10.20.0.24"]) + func.args_handler.Env_setup.fetch_compute_ips = mock_ips + func.args_handler.prepare_and_run_benchmark(test_input) + call = mock_driver.call_args + call_args, call_kwargs = call + assert sorted(map(sorted, call_args)) == sorted(map(sorted, expected)) diff --git a/tests/cli_test.py b/tests/cli_test.py index f12e8fed..f9861dee 100644 --- a/tests/cli_test.py +++ b/tests/cli_test.py @@ -1,4 +1,5 @@ import pytest +import mock from func.cli import cli @@ -16,5 +17,18 @@ class TestClass: def test_cli_error(self, capfd, test_input, expected): with pytest.raises(SystemExit): cli(test_input) - resout, reserr = capfd.readouterr() - assert expected in resout + resout, reserr = capfd.readouterr() + assert expected in resout + + @pytest.mark.parametrize("test_input, expected", [ + (['-l', + 'zte-pod1', + '-f', + 'storage'], [('./test_cases/zte-pod1/storage/fio_bm.yaml'), + ('./test_cases/zte-pod1/storage/fio_vm.yaml')]) + ]) + @mock.patch('func.cli.args_handler.prepare_and_run_benchmark') + def test_cli_successful(self, mock_args_handler, test_input, expected): + cli(test_input) + call_list = map(lambda x: mock_args_handler.call_args_list[x][0][0], range(len(expected))) + assert sorted(call_list) == sorted(expected) diff --git a/tests/driver_test.py b/tests/driver_test.py index 39adc939..a5b13588 100644 --- a/tests/driver_test.py +++ b/tests/driver_test.py @@ -16,20 +16,20 @@ class TestClass: 'https_proxy': 'http://10.20.0.1:8118', 'no_proxy': 'localhost,127.0.0.1,10.20.*,192.168.*'}, 'fuel'], - {'Dest_dir': 'results', - 'ip1': '', - 'ip2': '', - 'installer': 'fuel', - 'workingdir': '/home', - 'fname': 'iperf_bm.yaml', - 'username': 'root', - 'http_proxy': 'http://10.20.0.1:8118', - 'https_proxy': 'http://10.20.0.1:8118', - 'no_proxy': 'localhost,127.0.0.1,10.20.*,192.168.*', - 'duration': 20, - 'protocol': 'tcp', - 'bandwidthGbps': 0, - "role": "host"}), + [{'Dest_dir': 'results', + 'ip1': '', + 'ip2': '', + 'installer': 'fuel', + 'workingdir': '/home', + 'fname': 'iperf_bm.yaml', + 'username': 'root', + 'http_proxy': 'http://10.20.0.1:8118', + 'https_proxy': 'http://10.20.0.1:8118', + 'no_proxy': 'localhost,127.0.0.1,10.20.*,192.168.*', + 'duration': 20, + 'protocol': 'tcp', + 'bandwidthGbps': 0, + "role": "host"}]), (["iperf", [('1-server', ['10.20.0.13']), ('2-host', ['10.20.0.15'])], "iperf_vm.yaml", @@ -37,18 +37,29 @@ class TestClass: [("10.20.0.13", [None]), ("10.20.0.15", [None])], {}, 'joid'], - {'Dest_dir': 'results', - 'ip1': '10.20.0.13', - 'ip2': '', - 'installer': 'joid', - "privateip1": "NONE", - 'workingdir': '/home', - 'fname': 'iperf_vm.yaml', - 'username': 'ubuntu', - 'duration': 20, - 'protocol': 'tcp', - 'bandwidthGbps': 0, - "role": "2-host"}) + [{'Dest_dir': 'results', + 'ip1': '10.20.0.13', + 'ip2': '', + 'installer': 'joid', + "privateip1": "NONE", + 'workingdir': '/home', + 'fname': 'iperf_vm.yaml', + 'username': 'ubuntu', + 'duration': 20, + 'protocol': 'tcp', + 'bandwidthGbps': 0, + "role": "1-server"}, + {'Dest_dir': 'results', + 'ip1': '', + 'ip2': '', + 'installer': 'joid', + 'workingdir': '/home', + 'fname': 'iperf_vm.yaml', + 'username': 'ubuntu', + 'duration': 20, + 'protocol': 'tcp', + 'bandwidthGbps': 0, + "role": "2-host"}]) ]) @mock.patch('func.driver.os.system') def test_driver_success(self, mock_system, test_input, expected): @@ -57,9 +68,11 @@ class TestClass: k.start() dri = Driver() dri.drive_bench(test_input[0], test_input[1], test_input[2], test_input[3], test_input[4], test_input[5]) - call = mock_system.call_args + call_list = mock_system.call_args_list k.stop() - call_args, call_kwargs = call - real_call = call_args[0].split('extra-vars \'')[1] - real_call = real_call[0: len(real_call) - 1] - assert json.loads(real_call) == json.loads(json.dumps(expected)) + print call_list + for call in call_list: + call_args, call_kwargs = call + real_call = call_args[0].split('extra-vars \'')[1] + real_call = real_call[0: len(real_call) - 1] + assert json.loads(real_call) == json.loads(json.dumps(expected[call_list.index(call)])) diff --git a/tests/env_setup_test.py b/tests/env_setup_test.py index 9112ff94..cc3c6b60 100644 --- a/tests/env_setup_test.py +++ b/tests/env_setup_test.py @@ -1,6 +1,16 @@ +############################################################################## +# Copyright (c) 2016 ZTE 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 pytest import filecmp from func.env_setup import Env_setup +import mock class TestClass: @@ -31,6 +41,8 @@ class TestClass: print (test_input) print (expected) test_class = Env_setup() + mock_ips = mock.Mock(return_value=["10.20.0.28", "10.20.0.29"]) + test_class.fetch_compute_ips = mock_ips benchmark, vm_para, details, proxy = \ test_class.parse(test_input) assert benchmark == expected[0] @@ -40,12 +52,16 @@ class TestClass: def test_parse_vm_error(self): test_class = Env_setup() + mock_ips = mock.Mock(return_value=["10.20.0.28", "10.20.0.29"]) + test_class.fetch_compute_ips = mock_ips with pytest.raises(KeyError) as excinfo: test_class.parse("tests/test_case/vm_error.yaml") assert "benchmark" in str(excinfo.value) def test_update_ansible(self): test_class = Env_setup() + mock_ips = mock.Mock(return_value=["10.20.0.28", "10.20.0.29"]) + test_class.fetch_compute_ips = mock_ips test_class.parse("tests/test_case/bm_without_proxy.yaml") test_class.update_ansible() result = filecmp.cmp('tests/output/hosts', 'data/hosts') @@ -53,7 +69,40 @@ class TestClass: def test_ping(self, capfd): test_class = Env_setup() + mock_ips = mock.Mock(return_value=["127.0.0.1", "10.20.0.29"]) + test_class.fetch_compute_ips = mock_ips test_class.parse("tests/test_case/bm_ping.yaml") test_class.call_ping_test() resout, reserr = capfd.readouterr() assert '127.0.0.1 is UP' in resout + + def test_check_machine_ips_without_ip(self): + test_class = Env_setup() + mock_ips = mock.Mock(return_value=["10.20.0.28", "10.20.0.29"]) + test_class.fetch_compute_ips = mock_ips + inputs = {"machine_1": {"ip": "", "pw": "", "role": "host"}, + "machine_2": {"ip": "", "pw": "", "role": "host"}} + test_class.check_machine_ips(inputs) + assert inputs["machine_1"]['ip'] in ["10.20.0.28", "10.20.0.29"] + assert inputs["machine_2"]['ip'] in ["10.20.0.28", "10.20.0.29"] + assert inputs["machine_1"]['ip'] != inputs["machine_2"]['ip'] + + def test_check_machine_ips_with_ip(self): + test_class = Env_setup() + mock_ips = mock.Mock(return_value=["10.20.0.28", "10.20.0.29"]) + test_class.fetch_compute_ips = mock_ips + inputs = {"machine_1": {"ip": "10.20.0.28", "pw": "", "role": "host"}, + "machine_2": {"ip": "10.20.0.29", "pw": "", "role": "host"}} + test_class.check_machine_ips(inputs) + assert inputs["machine_1"]['ip'] in ["10.20.0.28", "10.20.0.29"] + assert inputs["machine_2"]['ip'] in ["10.20.0.28", "10.20.0.29"] + assert inputs["machine_1"]['ip'] != inputs["machine_2"]['ip'] + + def test_check_machine_ips_with_invalid_ip(self): + test_class = Env_setup() + mock_ips = mock.Mock(return_value=["10.20.0.28", "10.20.0.29"]) + test_class.fetch_compute_ips = mock_ips + inputs = {"machine_1": {"ip": "10.20.0.3", "pw": "", "role": "host"}, + "machine_2": {"ip": "10.20.0.4", "pw": "", "role": "host"}} + with pytest.raises(RuntimeError): + test_class.check_machine_ips(inputs) |