diff options
36 files changed, 1182 insertions, 17 deletions
diff --git a/docs/userguide/03-installation.rst b/docs/userguide/03-installation.rst index 1a7495547..a3144ef2c 100644 --- a/docs/userguide/03-installation.rst +++ b/docs/userguide/03-installation.rst @@ -171,7 +171,7 @@ Run the Docker image: -e "INSTALLER_TYPE=${INSTALLER_TYPE}" \ -e "INSTALLER_IP=${INSTALLER_IP}" \ opnfv/yardstick \ - run_tests.sh ${YARDSTICK_DB_BACKEND} ${YARDSTICK_SUITE_NAME} + exec_tests.sh ${YARDSTICK_DB_BACKEND} ${YARDSTICK_SUITE_NAME} Where ``${INSTALLER_TYPE}`` can be apex, compass, fuel or joid, ``${INSTALLER_IP}`` is the installer master node IP address (i.e. 10.20.0.2 is default for fuel). ``${YARDSTICK_DB_BACKEND}`` @@ -180,6 +180,11 @@ For more details, please refer to the Jenkins job defined in Releng project, lab and sshkey are required. See the link https://git.opnfv.org/cgit/releng/tree/jjb/yardstick/yardstick-ci-jobs.yml. +Note: exec_tests.sh is used for executing test suite here, furthermore, if someone wants to execute the +test suite manually, it can be used as long as the parameters are configured correct. Another script +called run_tests.sh is used for unittest in Jenkins verify job, in local manaul environment, +it is recommended to run before test suite execuation. + Basic steps performed by the **Yardstick-CI** container: 1. clone yardstick and releng repos diff --git a/fuel-plugin/LICENSE b/fuel-plugin/LICENSE new file mode 100644 index 000000000..e06d20818 --- /dev/null +++ b/fuel-plugin/LICENSE @@ -0,0 +1,202 @@ +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/fuel-plugin/README.md b/fuel-plugin/README.md new file mode 100644 index 000000000..b5a954269 --- /dev/null +++ b/fuel-plugin/README.md @@ -0,0 +1,36 @@ +plugin-yardstick +================ + +Plugin description +Installs Yardstick on base-os node via a fuel plugin. + + +To build: +1) install fuel plugin builder (fpb) + sudo apt-get install createrepo rpm dpkg-dev + easy_install pip + pip install fuel-plugin-builder + +2) build plugin + fpb --build <plugin-name> + e.g.: fpb --build plugin-yardstick + +3) copy plugin rpm to fuel master + e.g. scp plugin-yardstick-0.1-0.1.0-1.noarch.rpm <user>@<server-name>:~/ + +4) install plugin + fuel plugins --install <plugin-name>.rpm + +5) prepare fuel environment + on fuel dashboard, go to settings/other + enable yardstick plugin with checkbox + save settings + +6) add nodes to environment + +7) deploy + +8) run +Once deployed, SSH to deployed node. Find IP of yardstick node. +SSH to yardstick node, Activate yardstick: + source yardstick_env/bin/activate diff --git a/fuel-plugin/deployment_scripts/install.sh b/fuel-plugin/deployment_scripts/install.sh new file mode 100755 index 000000000..f0bb3e366 --- /dev/null +++ b/fuel-plugin/deployment_scripts/install.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +set -eux + +HOST=$1 +INSTALL_HOME=/opt/yardstick +rm -rf $INSTALL_HOME; mkdir -p $INSTALL_HOME + +cd $INSTALL_HOME + +sudo apt-get install -y python-virtualenv python-dev python-pip libffi-dev libssl-dev libxml2-dev libxslt1-dev +pip install --user virtualenv +pip install --upgrade virtualenv + +# create python virtual env +virtualenv $INSTALL_HOME/yardstick_venv +# source $INSTALL_HOME/yardstick_venv/bin/activate + +easy_install -U setuptools + +mkdir bin +cd $INSTALL_HOME/bin + +curl http://$HOST:8080/plugins/fuel-plugin-yardstick-0.9/repositories/ubuntu/yardstick.tar.gz | tar xzvf - + +pip install -r tests/ci/requirements.txt diff --git a/fuel-plugin/deployment_scripts/puppet/manifests/yardstick-install.pp b/fuel-plugin/deployment_scripts/puppet/manifests/yardstick-install.pp new file mode 100644 index 000000000..6547cb452 --- /dev/null +++ b/fuel-plugin/deployment_scripts/puppet/manifests/yardstick-install.pp @@ -0,0 +1,33 @@ +$fuel_settings = parseyaml(file('/etc/astute.yaml')) +$master_ip = $::fuel_settings['master_ip'] + +$access_hash = hiera_hash('access', {}) +$admin_tenant = $access_hash['tenant'] +$admin_user = $access_hash['user'] +$admin_password = $access_hash['password'] +$region = hiera('region', 'RegionOne') + +$service_endpoint = hiera('service_endpoint', $management_vip) +$ssl_hash = hiera_hash('use_ssl', {}) +$internal_auth_protocol = get_ssl_property($ssl_hash, {}, 'keystone', 'internal', 'protocol', 'http') +$internal_auth_address = get_ssl_property($ssl_hash, {}, 'keystone', 'internal', 'hostname', [$service_endpoint]) +$identity_uri = "${internal_auth_protocol}://${internal_auth_address}:5000" +$auth_url = "${identity_uri}/${auth_api_version}" + +exec { "install yardstick": + command => "curl http://${master_ip}:8080/plugins/fuel-plugin-yardstick-0.9/deployment_scripts/install.sh | bash -s ${master_ip}", + path => "/usr/local/bin:/usr/bin:/usr/sbin:/bin:/sbin"; +} + +osnailyfacter::credentials_file { '/opt/yardstick/openrc': + admin_user => $admin_user, + admin_password => $admin_password, + admin_tenant => $admin_tenant, + region_name => $region, + auth_url => $auth_url, +} + +exec { "run yardstick": + command => "echo hello", + path => "/usr/local/bin:/usr/bin:/usr/sbin:/bin:/sbin"; +} diff --git a/fuel-plugin/deployment_tasks.yaml b/fuel-plugin/deployment_tasks.yaml new file mode 100644 index 000000000..90fae7192 --- /dev/null +++ b/fuel-plugin/deployment_tasks.yaml @@ -0,0 +1,20 @@ +- id: yardstick + type: group + role: [yardstick] + requires: [deploy_start] + required_for: [deploy_end] + tasks: [hiera, setup_repositories, fuel_pkgs, globals, tools, logging, netconfig, yardstick-install] + parameters: + strategy: + type: parallel + +- id: yardstick-install + type: puppet + version: 2.0.0 + groups: [yardstick] + required_for: [post_deployment_end] + requires: [post_deployment_start] + parameters: + puppet_manifest: puppet/manifests/yardstick-install.pp + puppet_modules: puppet/modules:/etc/puppet/modules + timeout: 720 diff --git a/fuel-plugin/environment_config.yaml b/fuel-plugin/environment_config.yaml new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/fuel-plugin/environment_config.yaml diff --git a/fuel-plugin/metadata.yaml b/fuel-plugin/metadata.yaml new file mode 100644 index 000000000..2f6c95281 --- /dev/null +++ b/fuel-plugin/metadata.yaml @@ -0,0 +1,36 @@ +# Plugin name +name: fuel-plugin-yardstick +# Human-readable name for your plugin +title: Install Yardstick +# Plugin version +version: '0.9.0' +# Description +description: Installs Yardstick +# Required fuel version +fuel_version: ['9.0'] +# Specify license of your plugin +licenses: ['Apache License Version 2.0'] +# Specify author or company name +authors: ['john.hinman@intel.com','david.j.chou@intel.com','ruijing.guo@intel.com'] +# A link to the plugin's page +homepage: 'https://gerrit.opnfv.org/gerrit/yardstick' +# Specify a group which your plugin implements, possible options: +# network, storage, storage::cinder, storage::glance, hypervisor, +# equipment +groups: [] +# Change `false` to `true` if the plugin can be installed in the environment +# after the deployment. +is_hotpluggable: true + +# Version of plugin package +package_version: '4.0.0' +# The plugin is compatible with releases in the list +releases: + - os: ubuntu + version: mitaka-9.0 + mode: ['ha'] + deployment_scripts_path: deployment_scripts/ + repository_path: repositories/ubuntu + +# Version of plugin package +package_version: '4.0.0' diff --git a/fuel-plugin/node_roles.yaml b/fuel-plugin/node_roles.yaml new file mode 100644 index 000000000..8ba827eeb --- /dev/null +++ b/fuel-plugin/node_roles.yaml @@ -0,0 +1,8 @@ +yardstick: + name: "Yardstick" + description: "Install Yardstick on nodes with this role" + has_primary: false # whether has primary role or not + public_ip_required: false # whether requires public net or not + weight: 50 # weight that will be used for ordering on fuel ui + limits: + min: 0 diff --git a/fuel-plugin/pre_build_hook b/fuel-plugin/pre_build_hook new file mode 100755 index 000000000..9446d2a1a --- /dev/null +++ b/fuel-plugin/pre_build_hook @@ -0,0 +1,31 @@ +#!/bin/bash + +set -eux + +BUILD_FOR=${BUILD_FOR:-ubuntu} +DIR="$(dirname `readlink -f $0`)" + +function build_pkg { + case $1 in + ubuntu) + rm -rf ${DIR}/repositories/ubuntu; mkdir -p ${DIR}/repositories/ubuntu + + # don't support online installation now + # cd ${DIR}/repositories/ubuntu + # Use aptititude; apt-get -d will skip download if package is already installed + # sudo apt-get install aptitude -y + # Download python packages into the repository + # aptitude download python-virtualenv python-dev libffi-dev libssl-dev + + cd ${DIR}/.. + tar -czf ${DIR}/repositories/ubuntu/yardstick.tar.gz . --exclude=yardstick.tar.gz + ;; + + *) echo "Not supported system"; exit 1;; + esac +} + +for system in $BUILD_FOR +do + build_pkg $system +done diff --git a/fuel-plugin/tasks.yaml b/fuel-plugin/tasks.yaml new file mode 100644 index 000000000..fe51488c7 --- /dev/null +++ b/fuel-plugin/tasks.yaml @@ -0,0 +1 @@ +[] diff --git a/fuel-plugin/vagrant/Vagrantfile b/fuel-plugin/vagrant/Vagrantfile new file mode 100644 index 000000000..271ff7937 --- /dev/null +++ b/fuel-plugin/vagrant/Vagrantfile @@ -0,0 +1,21 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Vagrantfile API/syntax version. Don't touch unless you know what you're doing! +VAGRANTFILE_API_VERSION = "2" + +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + + config.vm.box = "trusty-server-cloudimg-amd64" + config.vm.box_url = "https://cloud-images.ubuntu.com/vagrant/trusty/current/trusty-server-cloudimg-amd64-vagrant-disk1.box" + + config.vm.define "fuel" do | h | + h.vm.host_name = "fuel" + h.vm.provision :shell, :inline => "/vagrant/build_fuel_plugin.sh", privileged: false + h.vm.synced_folder "../..", "/yardstick" + h.vm.provider :virtualbox do |v| + v.customize ["modifyvm", :id, "--memory", 4096] + v.customize ["modifyvm", :id, "--cpus", 4] + end + end +end diff --git a/fuel-plugin/vagrant/build_fuel_plugin.sh b/fuel-plugin/vagrant/build_fuel_plugin.sh new file mode 100755 index 000000000..b016176fb --- /dev/null +++ b/fuel-plugin/vagrant/build_fuel_plugin.sh @@ -0,0 +1,16 @@ +#!/bin/bash +sudo apt-get update -y +sudo apt-get install createrepo rpm dpkg-dev -y +sudo apt-get install python-setuptools -y +sudo apt-get install python-pip -y +sudo easy_install pip +sudo pip install fuel-plugin-builder +sudo apt-get install ruby -y +sudo gem install rubygems-update +sudo gem install fpm +sudo apt-get install docker.io -y +cp -r /yardstick /home/vagrant +cd /home/vagrant/yardstick/fuel-plugin; +rm -rf vagrant/.vagrant +fpb --debug --build . +cp *.rpm /vagrant diff --git a/run_tests.sh b/run_tests.sh index 82c8251ff..972f6a27f 100755 --- a/run_tests.sh +++ b/run_tests.sh @@ -9,7 +9,7 @@ # http://www.apache.org/licenses/LICENSE-2.0 ############################################################################## -# Run yardstick's test suite(s) +# Run yardstick's flake8, unit, coverage, functional test getopts ":f" FILE_OPTION diff --git a/samples/cachestat.yaml b/samples/cachestat.yaml new file mode 100644 index 000000000..5786efa38 --- /dev/null +++ b/samples/cachestat.yaml @@ -0,0 +1,31 @@ +--- +# Sample benchmark task config file +# Reading cache hit/miss ratio and usage statistics + +schema: "yardstick:task:0.1" + +scenarios: +- + type: CACHEstat + options: + interval: 1 + + host: kratos.demo + + runner: + type: Duration + duration: 60 + +context: + name: demo + image: yardstick-trusty-server + flavor: yardstick-flavor + user: ubuntu + + servers: + kratos: + floating_ip: true + + networks: + test: + cidr: '10.0.1.0/24' diff --git a/samples/computecapacity.yaml b/samples/computecapacity.yaml new file mode 100644 index 000000000..0c6d46bf1 --- /dev/null +++ b/samples/computecapacity.yaml @@ -0,0 +1,24 @@ +--- +# Sample benchmark task config file +# Measure compute capacity and scale. +# Including number of cores, number of threads, available memory size and +# cache size. + +schema: "yardstick:task:0.1" + +scenarios: +- + type: ComputeCapacity + options: + + nodes: + host1: node5.LF + + runner: + type: Iteration + iterations: 1 + +context: + type: Node + name: LF + file: /root/yardstick/etc/yardstick/nodes/compass_sclab_virtual/pod.yaml diff --git a/tests/ci/docker/yardstick-ci/Dockerfile b/tests/ci/docker/yardstick-ci/Dockerfile index a2164a8a2..cc23073d2 100644 --- a/tests/ci/docker/yardstick-ci/Dockerfile +++ b/tests/ci/docker/yardstick-ci/Dockerfile @@ -49,5 +49,4 @@ RUN cd ${YARDSTICK_REPO_DIR} && pip install . ADD http://download.cirros-cloud.net/0.3.3/cirros-0.3.3-x86_64-disk.img /home/opnfv/images/ -COPY ./run_tests.sh /usr/local/bin/ - +COPY ./exec_tests.sh /usr/local/bin/ diff --git a/tests/ci/docker/yardstick-ci/run_tests.sh b/tests/ci/docker/yardstick-ci/exec_tests.sh index 680a329ca..9aee240da 100755 --- a/tests/ci/docker/yardstick-ci/run_tests.sh +++ b/tests/ci/docker/yardstick-ci/exec_tests.sh @@ -11,7 +11,7 @@ set -e : ${YARDSTICK_REPO:='https://gerrit.opnfv.org/gerrit/yardstick'} -: ${YARDSTICK_REPO_DIR:='/home/opnfv/yardstick'} +: ${YARDSTICK_REPO_DIR:='/home/opnfv/repos/yardstick'} : ${YARDSTICK_BRANCH:='master'} # branch, tag, sha1 or refspec : ${RELENG_REPO:='https://gerrit.opnfv.org/gerrit/releng'} @@ -51,5 +51,5 @@ git_checkout $YARDSTICK_BRANCH $YARDSTICK_REPO # setup the environment source $YARDSTICK_REPO_DIR/tests/ci/prepare_env.sh -# run tests +# execute tests $YARDSTICK_REPO_DIR/tests/ci/yardstick-verify $@ diff --git a/tests/unit/benchmark/scenarios/availability/test_attacker_general.py b/tests/unit/benchmark/scenarios/availability/test_attacker_general.py new file mode 100644 index 000000000..d6488a9a7 --- /dev/null +++ b/tests/unit/benchmark/scenarios/availability/test_attacker_general.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python + +############################################################################## +# Copyright (c) 2016 Juan Qiu and others +# juan_ qiu@tongji.edu.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 +############################################################################## + +# Unittest for yardstick.benchmark.scenarios.availability.attacker +# .attacker_general + +import mock +import unittest + +from yardstick.benchmark.scenarios.availability.attacker import baseattacker + +@mock.patch('yardstick.benchmark.scenarios.availability.attacker.' + 'attacker_general.ssh') +class GeneralAttackerServiceTestCase(unittest.TestCase): + + def setUp(self): + host = { + "ip": "10.20.0.5", + "user": "root", + "key_filename": "/root/.ssh/id_rsa" + } + self.context = {"node1": host} + self.attacker_cfg = { + 'fault_type': 'general-attacker', + 'action_parameter':{'process_name':'nova_api'}, + 'rollback_parameter':{'process_name':'nova_api'}, + 'key':'stop_service', + 'host': 'node1', + } + + def test__attacker_service_all_successful(self, mock_ssh): + + cls = baseattacker.BaseAttacker.get_attacker_cls(self.attacker_cfg) + ins = cls(self.attacker_cfg, self.context) + + mock_ssh.SSH().execute.return_value = (0, "running", '') + ins.setup() + ins.inject_fault() + ins.recover() + + def test__attacker_service_check_failuer(self, mock_ssh): + + cls = baseattacker.BaseAttacker.get_attacker_cls(self.attacker_cfg) + ins = cls(self.attacker_cfg, self.context) + + mock_ssh.SSH().execute.return_value = (0, "error check", '') + ins.setup() diff --git a/tests/unit/benchmark/scenarios/compute/cachestat_sample_output.txt b/tests/unit/benchmark/scenarios/compute/cachestat_sample_output.txt new file mode 100644 index 000000000..e2c79a9b1 --- /dev/null +++ b/tests/unit/benchmark/scenarios/compute/cachestat_sample_output.txt @@ -0,0 +1,5 @@ +Counting cache functions... Output every 1 seconds. + HITS MISSES DIRTIES RATIO BUFFERS_MB CACHE_MB + 6462 0 29 100.0% 1157 66782 + +Ending tracing... diff --git a/tests/unit/benchmark/scenarios/compute/test_cachestat.py b/tests/unit/benchmark/scenarios/compute/test_cachestat.py new file mode 100644 index 000000000..f5a6b5ff9 --- /dev/null +++ b/tests/unit/benchmark/scenarios/compute/test_cachestat.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python + +############################################################################## +# 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 +############################################################################## + +# Unittest for yardstick.benchmark.scenarios.compute.cachestat.CACHEstat + +import mock +import unittest +import os + +from yardstick.benchmark.scenarios.compute import cachestat + + +@mock.patch('yardstick.benchmark.scenarios.compute.cachestat.ssh') +class CACHEstatTestCase(unittest.TestCase): + + def setUp(self): + self.ctx = { + 'host': { + 'ip': '172.16.0.137', + 'user': 'root', + 'key_filename': "mykey.key" + } + } + + self.result = {} + + def test_cachestat_successful_setup(self, mock_ssh): + c = cachestat.CACHEstat({}, self.ctx) + mock_ssh.SSH().execute.return_value = (0, '', '') + + c.setup() + self.assertIsNotNone(c.client) + self.assertTrue(c.setup_done) + + def test_execute_command_success(self, mock_ssh): + c = cachestat.CACHEstat({}, self.ctx) + mock_ssh.SSH().execute.return_value = (0, '', '') + c.setup() + + expected_result = 'abcdefg' + mock_ssh.SSH().execute.return_value = (0, expected_result, '') + result = c._execute_command("foo") + self.assertEqual(result, expected_result) + + def test_execute_command_failed(self, mock_ssh): + c = cachestat.CACHEstat({}, self.ctx) + mock_ssh.SSH().execute.return_value = (0, '', '') + c.setup() + + mock_ssh.SSH().execute.return_value = (127, '', 'Failed executing \ + command') + self.assertRaises(RuntimeError, c._execute_command, + "cat /proc/meminfo") + + def test_get_cache_usage_successful(self, mock_ssh): + options = { + "interval": 1, + } + args = {"options": options} + c = cachestat.CACHEstat(args, self.ctx) + mock_ssh.SSH().execute.return_value = (0, '', '') + c.setup() + + output = self._read_file("cachestat_sample_output.txt") + mock_ssh.SSH().execute.return_value = (0, output, '') + result = c._get_cache_usage() + expected_result = {"cachestat": {"cache0": {"HITS": "6462",\ + "DIRTIES": "29", "RATIO": "100.0%", "MISSES": "0", "BUFFERS_MB": "1157",\ + "CACHE_MB": "66782"}}, "average": {"HITS": 6462, "DIRTIES": 29, "RATIO": "100.0%",\ + "MISSES": 0, "BUFFERS_MB":1157, "CACHE_MB": 66782}, "max": {"HITS": 6462,\ + "DIRTIES": 29, "RATIO": 100.0, "MISSES": 0, "BUFFERS_MB": 1157, "CACHE_MB": 66782}} + + self.assertEqual(result, expected_result) + + def _read_file(self, filename): + curr_path = os.path.dirname(os.path.abspath(__file__)) + output = os.path.join(curr_path, filename) + with open(output) as f: + sample_output = f.read() + return sample_output diff --git a/tests/unit/benchmark/scenarios/compute/test_computecapacity.py b/tests/unit/benchmark/scenarios/compute/test_computecapacity.py new file mode 100644 index 000000000..5745b7ec9 --- /dev/null +++ b/tests/unit/benchmark/scenarios/compute/test_computecapacity.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python + +############################################################################## +# 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 +############################################################################## + +# Unittest for yardstick.benchmark.scenarios.compute.computecapacity.ComputeCapacity + +import mock +import unittest +import os +import json + +from yardstick.benchmark.scenarios.compute import computecapacity + +SAMPLE_OUTPUT = '{"Cpu_number": "2", "Core_number": "24",\ + "Memory_size": "263753976 kB", "Thread_number": "48",\ + "Cache_size": "30720 KB"}' + + +@mock.patch('yardstick.benchmark.scenarios.compute.computecapacity.ssh') +class ComputeCapacityTestCase(unittest.TestCase): + + def setUp(self): + self.ctx = { + 'nodes': { + 'host1': { + 'ip': '172.16.0.137', + 'user': 'cirros', + 'key_filename': "mykey.key", + 'password': "root" + }, + } + } + + self.result = {} + + def test_capacity_successful_setup(self, mock_ssh): + c = computecapacity.ComputeCapacity({}, self.ctx) + mock_ssh.SSH().execute.return_value = (0, '', '') + + c.setup() + self.assertIsNotNone(c.client) + self.assertTrue(c.setup_done) + + def test_capacity_successful(self, mock_ssh): + c = computecapacity.ComputeCapacity({}, self.ctx) + + mock_ssh.SSH().execute.return_value = (0, SAMPLE_OUTPUT, '') + c.run(self.result) + expected_result = json.loads(SAMPLE_OUTPUT) + self.assertEqual(self.result, expected_result) + + def test_capacity_unsuccessful_script_error(self, mock_ssh): + c = computecapacity.ComputeCapacity({}, self.ctx) + + mock_ssh.SSH().execute.return_value = (1, '', 'FOOBAR') + self.assertRaises(RuntimeError, c.run, self.result) diff --git a/tests/unit/benchmark/scenarios/compute/test_ramspeed.py b/tests/unit/benchmark/scenarios/compute/test_ramspeed.py index 3de84c74c..100102d19 100644 --- a/tests/unit/benchmark/scenarios/compute/test_ramspeed.py +++ b/tests/unit/benchmark/scenarios/compute/test_ramspeed.py @@ -228,7 +228,8 @@ class RamspeedTestCase(unittest.TestCase): args = {'options': options} r = ramspeed.Ramspeed(args, self.ctx) - mock_ssh.SSH().execute.return_value = (1, '', 'No such type_id: 30 for Ramspeed scenario') + mock_ssh.SSH().execute.return_value = (1, '', 'No such type_id: 30 for \ + Ramspeed scenario') self.assertRaises(RuntimeError, r.run, self.result) diff --git a/tools/ubuntu-server-cloudimg-modify.sh b/tools/ubuntu-server-cloudimg-modify.sh index f9e0a2c47..2e8399a9b 100755 --- a/tools/ubuntu-server-cloudimg-modify.sh +++ b/tools/ubuntu-server-cloudimg-modify.sh @@ -1,3 +1,4 @@ +#!/bin/bash ############################################################################## # Copyright (c) 2015 Ericsson AB and others. # @@ -7,8 +8,6 @@ # http://www.apache.org/licenses/LICENSE-2.0 ############################################################################## -#!/bin/bash - # installs required packages # must be run from inside the image (either chrooted or running) @@ -63,11 +62,12 @@ apt-get install -y \ git clone https://github.com/kdlucas/byte-unixbench.git /opt/tempT make --directory /opt/tempT/UnixBench/ - -git clone https://github.com/beefyamoeba5/ramspeed.git /opt/tempT2 -cd /opt/tempT2/ramspeed-2.6.0 +git clone https://github.com/beefyamoeba5/ramspeed.git /opt/tempT/RAMspeed +cd /opt/tempT/RAMspeed/ramspeed-2.6.0 mkdir temp bash build.sh +git clone https://github.com/beefyamoeba5/cachestat.git /opt/tempT/Cachestat + # restore symlink ln -sf /run/resolvconf/resolv.conf /etc/resolv.conf diff --git a/yardstick/benchmark/scenarios/availability/attacker/attacker_general.py b/yardstick/benchmark/scenarios/availability/attacker/attacker_general.py new file mode 100644 index 000000000..018362a15 --- /dev/null +++ b/yardstick/benchmark/scenarios/availability/attacker/attacker_general.py @@ -0,0 +1,91 @@ +############################################################################## +# Copyright (c) 2016 Juan Qiu and others +# juan_ qiu@tongji.edu.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 +############################################################################## +import logging + +from baseattacker import BaseAttacker +import yardstick.ssh as ssh +from yardstick.benchmark.scenarios.availability import util + +LOG = logging.getLogger(__name__) + + +class GeneralAttacker(BaseAttacker): + + __attacker_type__ = 'general-attacker' + + def setup(self): + LOG.debug("config:%s context:%s" % (self._config, self._context)) + host = self._context.get(self._config['host'], None) + ip = host.get("ip", None) + user = host.get("user", "root") + key_filename = host.get("key_filename", "~/.ssh/id_rsa") + + self.connection = ssh.SSH(user, ip, key_filename=key_filename) + self.connection.wait(timeout=600) + LOG.debug("ssh host success!") + + self.key = self._config['key'] + + if "action_parameter" in self._config: + actionParameter = self._config['action_parameter'] + str = util.buildshellparams(actionParameter) + LOG.debug("inject parameter is: {0}".format(actionParameter)) + LOG.debug("inject parameter values are: {0}" + .format(actionParameter.values())) + l = list(item for item in actionParameter.values()) + self.action_param = str.format(*l) + + if "rollback_parameter" in self._config: + rollbackParameter = self._config['rollback_parameter'] + str = util.buildshellparams(rollbackParameter) + LOG.debug("recover parameter is: {0}".format(rollbackParameter)) + LOG.debug("recover parameter values are: {0}". + format(rollbackParameter.values())) + l = list(item for item in rollbackParameter.values()) + self.rollback_param = str.format(*l) + + self.fault_cfg = BaseAttacker.attacker_cfgs.get(self.key) + self.inject_script = self.get_script_fullpath( + self.fault_cfg['inject_script']) + self.recovery_script = self.get_script_fullpath( + self.fault_cfg['recovery_script']) + + def inject_fault(self): + LOG.debug("{0} starting inject!".format(self.key)) + LOG.debug("the inject_script path:{0}".format(self.inject_script)) + + if "action_parameter" in self._config: + LOG.debug("the shell command is: {0}".format(self.action_param)) + exit_status, stdout, stderr = self.connection.execute( + self.action_param, + stdin=open(self.inject_script, "r")) + else: + exit_status, stdout, stderr = self.connection.execute( + "/bin/bash -s ", + stdin=open(self.inject_script, "r")) + + LOG.debug("the inject_fault's exit status is: {0}".format(exit_status)) + if exit_status == 0: + LOG.debug("success,the inject_fault's output is: {0}" + .format(stdout)) + else: + LOG.error( + "the inject_fault's error, stdout:%s, stderr:%s" % + (stdout, stderr)) + + def recover(self): + if "rollback_parameter" in self._config: + LOG.debug("the shell command is: {0}".format(self.rollback_param)) + exit_status, stdout, stderr = self.connection.execute( + self.rollback_param, + stdin=open(self.recovery_script, "r")) + else: + exit_status, stdout, stderr = self.connection.execute( + "/bin/bash -s ", + stdin=open(self.recovery_script, "r")) diff --git a/yardstick/benchmark/scenarios/availability/attacker/baseattacker.py b/yardstick/benchmark/scenarios/availability/attacker/baseattacker.py index a1c6999e5..78276efa2 100644 --- a/yardstick/benchmark/scenarios/availability/attacker/baseattacker.py +++ b/yardstick/benchmark/scenarios/availability/attacker/baseattacker.py @@ -20,6 +20,31 @@ attacker_conf_path = pkg_resources.resource_filename( "attacker_conf.yaml") +class AttackerMgr(object): + + def __init__(self): + self._attacker_list = [] + + def init_attackers(self, attacker_cfgs, context): + LOG.debug("attackerMgr confg: %s" % attacker_cfgs) + + for cfg in attacker_cfgs: + attacker_cls = BaseAttacker.get_attacker_cls(cfg) + attacker_ins = attacker_cls(cfg, context) + attacker_ins.key = cfg['key'] + attacker_ins.setup() + self._attacker_list.append(attacker_ins) + + def __getitem__(self, item): + for obj in self._attacker_list: + if(obj.key == item): + return obj + + def recover(self): + for _instance in self._attacker_list: + _instance.recover() + + class BaseAttacker(object): attacker_cfgs = {} @@ -45,3 +70,6 @@ class BaseAttacker(object): def get_script_fullpath(self, path): base_path = os.path.dirname(attacker_conf_path) return os.path.join(base_path, path) + + def recover(self): + pass diff --git a/yardstick/benchmark/scenarios/availability/attacker_conf.yaml b/yardstick/benchmark/scenarios/availability/attacker_conf.yaml index 3f6c2aa8f..16b3d735c 100644 --- a/yardstick/benchmark/scenarios/availability/attacker_conf.yaml +++ b/yardstick/benchmark/scenarios/availability/attacker_conf.yaml @@ -11,3 +11,7 @@ kill-process: bare-metal-down: check_script: ha_tools/check_host_ping.bash recovery_script: ha_tools/ipmi_power.bash + +stop_service: + inject_script: ha_tools/stop_service.bash + recovery_script: ha_tools/start_service.bash diff --git a/yardstick/benchmark/scenarios/availability/util.py b/yardstick/benchmark/scenarios/availability/util.py new file mode 100644 index 000000000..2addef8ef --- /dev/null +++ b/yardstick/benchmark/scenarios/availability/util.py @@ -0,0 +1,19 @@ +############################################################################## +# Copyright (c) 2016 Juan Qiu +# juan_ qiu@tongji.edu.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 +############################################################################## + + +def buildshellparams(param): + i = 0 + values = [] + result = '/bin/bash -s' + for key in param.keys(): + values.append(param[key]) + result += " {%d}" % i + i = i + 1 + return result diff --git a/yardstick/benchmark/scenarios/compute/cache_stat.bash b/yardstick/benchmark/scenarios/compute/cache_stat.bash new file mode 100644 index 000000000..393af410c --- /dev/null +++ b/yardstick/benchmark/scenarios/compute/cache_stat.bash @@ -0,0 +1,30 @@ +#!/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 +############################################################################## + +# Run a cachestat cache benchmark in a host + +set -e + +INTERVAL=$1 + +run_cachestat() +{ + cd /opt/tempT/Cachestat + bash cachestat $INTERVAL +} + +main() +{ + # run the test + run_cachestat +} + +main diff --git a/yardstick/benchmark/scenarios/compute/cachestat.py b/yardstick/benchmark/scenarios/compute/cachestat.py new file mode 100644 index 000000000..da4aa754f --- /dev/null +++ b/yardstick/benchmark/scenarios/compute/cachestat.py @@ -0,0 +1,163 @@ +############################################################################## +# 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 +############################################################################## + +"""cache hit/miss ratio and usage statistics""" + +import pkg_resources +import logging +import re +import yardstick.ssh as ssh + +from yardstick.benchmark.scenarios import base + +LOG = logging.getLogger(__name__) + + +class CACHEstat(base.Scenario): + '''Collect cache statistics. + + This scenario reads system cache hit/miss ratio and other statistics on + a Linux host. + + cache statistics are read using 'cachestat'. + cachestat - show Linux page cache hit/miss statistics. + Uses Linux ftrace. + + This is a proof of concept using Linux ftrace capabilities on older + kernels, and works by using function profiling for in-kernel counters. + Specifically, four kernel functions are traced: + + mark_page_accessed() for measuring cache accesses + mark_buffer_dirty() for measuring cache writes + add_to_page_cache_lru() for measuring page additions + account_page_dirtied() for measuring page dirties + + It is possible that these functions have been renamed (or are different + logically) for your kernel version, and this script will not work as-is. + This script was written on Linux 3.13. This script is a sandcastle: the + kernel may wash some away, and you'll need to rebuild. + + USAGE: cachestat [-Dht] [interval] + eg, + cachestat 5 # show stats every 5 seconds + + Run "cachestat -h" for full usage. + + WARNING: This uses dynamic tracing of kernel functions, and could cause + kernel panics or freezes. Test, and know what you are doing, before use. + It also traces cache activity, which can be frequent, and cost some + overhead. The statistics should be treated as best-effort: there may be + some error margin depending on unusual workload types. + + REQUIREMENTS: CONFIG_FUNCTION_PROFILER, awk. + ''' + __scenario_type__ = "CACHEstat" + + TARGET_SCRIPT = "cache_stat.bash" + + def __init__(self, scenario_cfg, context_cfg): + """Scenario construction.""" + self.scenario_cfg = scenario_cfg + self.context_cfg = context_cfg + self.setup_done = False + + def setup(self): + """Scenario setup.""" + self.target_script = pkg_resources.resource_filename( + "yardstick.benchmark.scenarios.compute", + CACHEstat.TARGET_SCRIPT) + + host = self.context_cfg['host'] + user = host.get('user', 'ubuntu') + ip = host.get('ip', None) + key_filename = host.get('key_filename', '~/.ssh/id_rsa') + + LOG.info("user:%s, host:%s", user, ip) + self.client = ssh.SSH(user, ip, key_filename=key_filename) + self.client.wait(timeout=600) + + # copy scripts to host + self.client.run("cat > ~/cache_stat.sh", + stdin=open(self.target_script, 'rb')) + + self.setup_done = True + + def _execute_command(self, cmd): + """Execute a command on server.""" + LOG.info("Executing: %s" % cmd) + status, stdout, stderr = self.client.execute(cmd) + if status: + raise RuntimeError("Failed executing command: ", + cmd, stderr) + return stdout + + def _filtrate_result(self, result): + fields = [] + cachestat = {} + data_marker = re.compile("\d+") + ite = 0 + average = {'HITS': 0, 'MISSES': 0, 'DIRTIES': 0, 'RATIO': 0, + 'BUFFERS_MB': 0, 'CACHE_MB': 0} + maximum = {'HITS': 0, 'MISSES': 0, 'DIRTIES': 0, 'RATIO': 0, + 'BUFFERS_MB': 0, 'CACHE_MB': 0} + + # Parse cache stats + for row in result.split('\n'): + line = row.split() + + if line and line[0] == 'HITS': + # header fields + fields = line[:] + elif line and re.match(data_marker, line[0]): + cache = 'cache' + str(ite) + ite += 1 + values = line[:] + if values and len(values) == len(fields): + cachestat[cache] = dict(zip(fields, values)) + + for entry in cachestat: + for item in average: + if item != 'RATIO': + average[item] += int(cachestat[entry][item]) + else: + average[item] += float(cachestat[entry][item][:-1]) + + for item in maximum: + if item != 'RATIO': + if int(cachestat[entry][item]) > maximum[item]: + maximum[item] = int(cachestat[entry][item]) + else: + if float(cachestat[entry][item][:-1]) > maximum[item]: + maximum[item] = float(cachestat[entry][item][:-1]) + + for item in average: + if item != 'RATIO': + average[item] = average[item] / len(cachestat) + else: + average[item] = str(average[item] / len(cachestat)) + '%' + + return {'cachestat': cachestat, 'average': average, 'max': maximum} + + def _get_cache_usage(self): + """Get cache statistics.""" + options = self.scenario_cfg['options'] + interval = options.get("interval", 1) + + cmd = "sudo bash cache_stat.sh %s" % (interval) + + result = self._execute_command(cmd) + filtrated_result = self._filtrate_result(result) + + return filtrated_result + + def run(self, result): + if not self.setup_done: + self.setup() + + result.update(self._get_cache_usage()) diff --git a/yardstick/benchmark/scenarios/compute/computecapacity.bash b/yardstick/benchmark/scenarios/compute/computecapacity.bash new file mode 100644 index 000000000..98d4b8fb5 --- /dev/null +++ b/yardstick/benchmark/scenarios/compute/computecapacity.bash @@ -0,0 +1,55 @@ +#!/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 +############################################################################## + +# Measure compute capacity and scale of a host + +set -e + +# run capacity test +run_capacity() +{ + # Number of CPUs + CPU=$(grep 'physical id' /proc/cpuinfo | sort -u | wc -l) + # Number of physical cores in a single CPU + CORE=$(grep 'core id' /proc/cpuinfo | sort -u | wc -l) + # Total physical core number + CORES=$[$CPU * $CORE] + # Number of logical cores + THREAD=$(grep 'processor' /proc/cpuinfo | sort -u | wc -l) + # Total memory size + MEMORY=$(grep 'MemTotal' /proc/meminfo | sort -u) + ME=$(echo $MEMORY | awk '/ /{printf "%s %s", $2, $3}') + # Cache size per CPU + CACHE=$(grep 'cache size' /proc/cpuinfo | sort -u) + CA=$(echo $CACHE | awk '/ /{printf "%s", $4}') + CACHES=$[$CA * $CPU] +} + +# write the result to stdout in json format +output_json() +{ + echo -e "{ \ + \"Cpu_number\":\"$CPU\", \ + \"Core_number\":\"$CORES\", \ + \"Thread_number\":\"$THREAD\", \ + \"Memory_size\": \"$ME\", \ + \"Cache_size\": \"$CACHES KB\" \ + }" +} + +main() +{ + run_capacity + + output_json +} + +main diff --git a/yardstick/benchmark/scenarios/compute/computecapacity.py b/yardstick/benchmark/scenarios/compute/computecapacity.py new file mode 100644 index 000000000..366b470e8 --- /dev/null +++ b/yardstick/benchmark/scenarios/compute/computecapacity.py @@ -0,0 +1,68 @@ +############################################################################## +# 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 pkg_resources +import logging +import json + +import yardstick.ssh as ssh +from yardstick.benchmark.scenarios import base + +LOG = logging.getLogger(__name__) + + +class ComputeCapacity(base.Scenario): + """Measure compute capacity and scale. + + This scenario reads hardware specification, including number of cpus, + number of cores, number of threads, available memory size and total cache + size of a host. + """ + __scenario_type__ = "ComputeCapacity" + TARGET_SCRIPT = "computecapacity.bash" + + def __init__(self, scenario_cfg, context_cfg): + self.scenario_cfg = scenario_cfg + self.context_cfg = context_cfg + self.setup_done = False + + def setup(self): + """scenario setup""" + self.target_script = pkg_resources.resource_filename( + "yardstick.benchmark.scenarios.compute", + ComputeCapacity.TARGET_SCRIPT) + + nodes = self.context_cfg['nodes'] + node = nodes.get('host1', None) + host_user = node.get('user', 'ubuntu') + host_ip = node.get('ip', None) + host_pwd = node.get('password', 'root') + LOG.debug("user:%s, host:%s", host_user, host_ip) + self.client = ssh.SSH(host_user, host_ip, password=host_pwd) + self.client.wait(timeout=600) + + # copy script to host + self.client.run("cat > ~/computecapacity.sh", + stdin=open(self.target_script, 'rb')) + + self.setup_done = True + + def run(self, result): + """execute the benchmark""" + + if not self.setup_done: + self.setup() + + cmd = "sudo bash computecapacity.sh" + + LOG.debug("Executing command: %s", cmd) + status, stdout, stderr = self.client.execute(cmd) + if status: + raise RuntimeError(stderr) + + result.update(json.loads(stdout)) diff --git a/yardstick/benchmark/scenarios/compute/ramspeed_mark_benchmark.bash b/yardstick/benchmark/scenarios/compute/ramspeed_mark_benchmark.bash index fcb655968..526d0b9f6 100644 --- a/yardstick/benchmark/scenarios/compute/ramspeed_mark_benchmark.bash +++ b/yardstick/benchmark/scenarios/compute/ramspeed_mark_benchmark.bash @@ -21,7 +21,7 @@ OUTPUT_FILE=/tmp/ramspeed-out.log run_ramspeed() { - cd /opt/tempT2/ramspeed-2.6.0/ + cd /opt/tempT/RAMspeed/ramspeed-2.6.0/ ./ramspeed -b $TYPE_ID -g $LOAD -m $BLOCK_SIZE > $OUTPUT_FILE } diff --git a/yardstick/benchmark/scenarios/compute/ramspeed_mem_benchmark.bash b/yardstick/benchmark/scenarios/compute/ramspeed_mem_benchmark.bash index 69c2934af..931a06375 100644 --- a/yardstick/benchmark/scenarios/compute/ramspeed_mem_benchmark.bash +++ b/yardstick/benchmark/scenarios/compute/ramspeed_mem_benchmark.bash @@ -22,7 +22,7 @@ OUTPUT_FILE=/tmp/ramspeed-out.log run_ramspeed() { - cd /opt/tempT2/ramspeed-2.6.0/ + cd /opt/tempT/RAMspeed/ramspeed-2.6.0/ ./ramspeed -b $TYPE_ID -g $LOAD -m $BLOCK_SIZE -l $ITERATION > $OUTPUT_FILE } diff --git a/yardstick/benchmark/scenarios/networking/ping.py b/yardstick/benchmark/scenarios/networking/ping.py index fc4176650..aa1a500cf 100644 --- a/yardstick/benchmark/scenarios/networking/ping.py +++ b/yardstick/benchmark/scenarios/networking/ping.py @@ -41,10 +41,11 @@ class Ping(base.Scenario): user = host.get('user', 'ubuntu') ip = host.get('ip', None) key_filename = host.get('key_filename', '~/.ssh/id_rsa') + password = host.get('password', 'root') LOG.info("user:%s, host:%s", user, ip) - - self.connection = ssh.SSH(user, ip, key_filename=key_filename) + self.connection = ssh.SSH(user, ip, key_filename=key_filename, + password=password) self.connection.wait() def run(self, result): diff --git a/yardstick/plot/plotter.py b/yardstick/plot/plotter.py index 91dd521f7..4cbbdfe74 100644 --- a/yardstick/plot/plotter.py +++ b/yardstick/plot/plotter.py @@ -36,6 +36,7 @@ class Parser(object): 'fio': [] } self.default_input_loc = "/tmp/yardstick.out" + self.scenarios = {} def _get_parser(self): '''get a command-line parser''' @@ -59,7 +60,11 @@ class Parser(object): def _add_record(self, record): '''add record to the relevant scenario''' - runner_object = record['sargs']['runner']['object'] + if "runner_id" in record and "benchmark" not in record: + obj_name = record["scenario_cfg"]["runner"]["object"] + self.scenarios[record["runner_id"]] = obj_name + return + runner_object = self.scenarios[record["runner_id"]] for test_type in self.data.keys(): if test_type in runner_object: self.data[test_type].append(record) |