diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | INFO | 1 | ||||
-rw-r--r-- | func/ansible_api.py | 64 | ||||
-rw-r--r-- | func/args_handler.py | 59 | ||||
-rw-r--r-- | func/cli.py | 81 | ||||
-rw-r--r-- | func/driver.py | 1 | ||||
-rw-r--r-- | requirements.txt | 1 | ||||
-rw-r--r-- | tests/ansible_api_test.py | 19 | ||||
-rw-r--r-- | tests/args_handler_test.py | 35 | ||||
-rw-r--r-- | tests/cli_test.py | 14 | ||||
-rw-r--r-- | tests/data/hosts | 2 | ||||
-rw-r--r-- | tests/data/test.yml | 4 |
12 files changed, 213 insertions, 69 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/func/ansible_api.py b/func/ansible_api.py new file mode 100644 index 00000000..57224eb7 --- /dev/null +++ b/func/ansible_api.py @@ -0,0 +1,64 @@ +############################################################################## +# 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 collections import namedtuple +import logging + +from ansible.parsing.dataloader import DataLoader +from ansible.vars import VariableManager +from ansible.inventory import Inventory +from ansible.executor.playbook_executor import PlaybookExecutor + + +class AnsibleApi: + + def __init__(self): + self.variable_manager = VariableManager() + self.loader = DataLoader() + self.passwords = {} + self.pbex = None + + def _check_path(self, file_path): + if not os.path.exists(file_path): + logging.error('The playbook %s does not exist' % file_path) + return False + else: + return True + + def execute_playbook(self, hosts_file, playbook_path, pub_key_file, vars): + if not self._check_path(hosts_file): + return False + + inventory = Inventory(loader=self.loader, variable_manager=self.variable_manager, + host_list=hosts_file) + Options = namedtuple('Options', ['listtags', 'listtasks', 'listhosts', 'syntax', + 'connection', 'module_path', 'forks', 'remote_user', + 'private_key_file', 'ssh_common_args', 'ssh_extra_args', + 'sftp_extra_args', 'scp_extra_args', 'become', + 'become_method', 'become_user', 'verbosity', 'check']) + options = Options(listtags=False, listtasks=False, listhosts=False, syntax=False, + connection='ssh', module_path=None, forks=100, remote_user='root', + private_key_file=pub_key_file, ssh_common_args=None, + ssh_extra_args=None, sftp_extra_args=None, scp_extra_args=None, + become=True, become_method=None, become_user='root', verbosity=None, + check=False) + self.variable_manager.extra_vars = vars + + self.pbex = PlaybookExecutor(playbooks=[playbook_path], inventory=inventory, + variable_manager=self.variable_manager, loader=self.loader, + options=options, passwords=self.passwords) + + return self.pbex.run() + + def get_detail_playbook_stats(self): + if self.pbex: + stats = self.pbex._tqm._stats + return map(lambda x: (x, stats.summarize(x)), stats.processed.keys()) + else: + return None 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 291591b1..f26f63db 100644 --- a/func/driver.py +++ b/func/driver.py @@ -16,7 +16,6 @@ class Driver: def __init__(self): logging.info("Class driver initialized\n") - logging.info(os.environ['PWD']) self.installer_username = {'fuel': 'root', 'joid': 'ubuntu', 'apex': 'heat-admin'} diff --git a/requirements.txt b/requirements.txt index af07083d..cdaeef70 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,3 +10,4 @@ reportlab==3.0 Flask==0.11.1 Flask-RESTful==0.3.5 flask-restful-swagger==0.19 +ansible==2.1.1.0 diff --git a/tests/ansible_api_test.py b/tests/ansible_api_test.py new file mode 100644 index 00000000..e9f0a77d --- /dev/null +++ b/tests/ansible_api_test.py @@ -0,0 +1,19 @@ +############################################################################## +# 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 +############################################################################## +from func.ansible_api import AnsibleApi + + +class TestClass: + def test_call_ansible_api_success(self): + ansible_api = AnsibleApi() + ret = ansible_api.execute_playbook('tests/data/hosts', + 'tests/data/test.yml', + 'data/QtipKey', + {'keys': 'test'}) + assert ret == 3 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 bd31d987..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 @@ -18,3 +19,16 @@ class TestClass: cli(test_input) 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/data/hosts b/tests/data/hosts new file mode 100644 index 00000000..0a0ac539 --- /dev/null +++ b/tests/data/hosts @@ -0,0 +1,2 @@ +[sample_group_name] +127.0.0.1 diff --git a/tests/data/test.yml b/tests/data/test.yml new file mode 100644 index 00000000..270e86fd --- /dev/null +++ b/tests/data/test.yml @@ -0,0 +1,4 @@ +- hosts: sample_group_name + tasks: + - name: just an uname + command: uname -a |