diff options
34 files changed, 764 insertions, 223 deletions
@@ -13,13 +13,15 @@ Repository: yardstick Committers: jorgen.w.karlsson@ericsson.com jean.gaoliang@huawei.com -vincenzo.m.riccobene@intel.com lvjing5@huawei.com wu.zhihui1@zte.com.cn 14_ykl@tongji.edu.cn limingjiang@huawei.com trevor.cooper@intel.com ross.b.brattain@intel.com +chenjiankun1@huawei.com +rodolfo.alonso.hernandez@intel.com +emma.l.foley@intel.com Link to TSC approval: http://meetbot.opnfv.org/meetings/ Link to approval of additional submitters: diff --git a/ansible/roles/enable_iommu_on_boot/tasks/main.yml b/ansible/roles/enable_iommu_on_boot/tasks/main.yml new file mode 100644 index 000000000..1b98a50b1 --- /dev/null +++ b/ansible/roles/enable_iommu_on_boot/tasks/main.yml @@ -0,0 +1,72 @@ +# Copyright (c) 2017 Intel Corporation +# +# 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. +--- +- name: Set iommu_boot_params for Intel + set_fact: + iommu_boot_params: ' intel_iommu=on iommu=pt' + when: hostvars[inventory_hostname]['ansible_system_vendor'] == "Intel Corporation" + +- name: Set iommu_boot_params for AMD + set_fact: + iommu_boot_params: ' amd_iommu=on iommu=pt' + when: hostvars[inventory_hostname]['ansible_system_vendor'] == "AuthenticAMD" + +- name: Set facts for this role + set_fact: + hugepages_help_string: ' # added by hugepages role' + iommu_help_string: ', added by iommu role' + hugepages_params: " default_hugepagesz=1G hugepagesz=1G hugepages=8" + iommu_original_kernel_params: 'GRUB_CMDLINE_LINUX="\$GRUB_CMDLINE_LINUX{{ hugepages_params }}' + iommu_enabled_kernel_params: '{{ iommu_original_kernel_params }}{{ iommu_boot_params }}"' + iommu_enabled_kernel_params_with_help: '{{ iommu_original_kernel_params }}{{ iommu_boot_params }}"{{ hugepages_help_string }}{{ iommu_help_string }}' + +- name: check if iommu is set by this role in /etc/default/grub + lineinfile: + path: /etc/default/grub + line: '{{ iommu_enabled_kernel_params_with_help }}' + #changed_when: no + check_mode: yes + register: is_mine_iommu_etc_grub + ignore_errors: True + +- name: check if iommu is set by someone else + command: "grep -o 'iommu' /etc/default/grub" + register: is_iommu + ignore_errors: True + +- fail: + msg: "Iommu already set by someone else" + when: is_mine_iommu_etc_grub.changed == false and is_iommu.stdout != "" + +- name: 'Configure iommu in /etc/default/grub' +# and /boot/grub/grub.cfg(when: ansible_distribution == "Ubuntu")' + lineinfile: + path: /etc/default/grub + regexp: '({{ iommu_original_kernel_params }})"{{ hugepages_help_string }}' + line: '\1{{ iommu_boot_params }}"{{ hugepages_help_string }}{{ iommu_help_string }}' + backrefs: yes + when: is_mine_iommu_etc_grub.changed == true + +- name: find boot grub.cfg + find: + paths: /boot + file_type: file + patterns: 'grub*.cfg' + recurse: yes + register: grub_files + +- include: manual_modify_grub.yml + # only tested on Ubuntu, kernel line is probably different on other distros + with_items: "{{ grub_files.files }}" + when: ansible_distribution == "Ubuntu" diff --git a/ansible/roles/enable_iommu_on_boot/tasks/manual_modify_grub.yml b/ansible/roles/enable_iommu_on_boot/tasks/manual_modify_grub.yml new file mode 100644 index 000000000..6760c3f9d --- /dev/null +++ b/ansible/roles/enable_iommu_on_boot/tasks/manual_modify_grub.yml @@ -0,0 +1,34 @@ +# Copyright (c) 2017 Intel Corporation +# +# 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. +--- + + +- name: check if iommu is set by this role in /boot grub.cfg files + lineinfile: + path: "{{ item.path }}" + regexp: '{{ hugepages_params }}{{ iommu_boot_params }}' + line: '' + #changed_when: no + check_mode: yes + register: is_mine_iommu_boot_grub + ignore_errors: True + +- name: added iommu to grub manually because we can't run update-grub in chroot + replace: + path: "{{ item.path }}" + regexp: '(.*linux\s+/boot/vmlinuz.*)$' + replace: '\1{{ iommu_boot_params }}' + when: is_mine_iommu_boot_grub.msg != "line replaced" + +- debug: var=ansible_kernel diff --git a/ansible/roles/enable_iommu_on_boot/vars/main.yml b/ansible/roles/enable_iommu_on_boot/vars/main.yml new file mode 100644 index 000000000..1b642dcb5 --- /dev/null +++ b/ansible/roles/enable_iommu_on_boot/vars/main.yml @@ -0,0 +1,17 @@ +# Copyright (c) 2017 Intel Corporation +# +# 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. +--- +update_grub: + Debian: "update-grub2" + RedHat: "grub2-mkconfig -o /boot/grub2/grub.cfg" diff --git a/docker/Dockerfile.aarch64.patch b/docker/Dockerfile.aarch64.patch index 33c352a1b..ca933514a 100644 --- a/docker/Dockerfile.aarch64.patch +++ b/docker/Dockerfile.aarch64.patch @@ -1,14 +1,15 @@ -From: Alexandru Nemes <alexandru.nemes@enea.com> -Date: Mon, 19 Jun 2017 14:18:24 +0300 +From: Cristina Pauna <cristina.pauna@enea.com> +Date: Thu, 11 Jan 2018 19:06:26 +0200 Subject: [PATCH] Patch for Yardstick AARCH64 Docker file +Signed-off-by: Cristina Pauna <cristina.pauna@enea.com> Signed-off-by: Alexandru Nemes <alexandru.nemes@enea.com> --- - docker/Dockerfile | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) + docker/Dockerfile | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile -index 96a5d77..03307a2 100644 +index 2ee5b4c..23e5ea5 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,5 +1,5 @@ @@ -22,15 +23,25 @@ index 96a5d77..03307a2 100644 # http://www.apache.org/licenses/LICENSE-2.0 ############################################################################## --FROM ubuntu:14.04 -+FROM aarch64/ubuntu:14.04 +-FROM ubuntu:16.04 ++FROM arm64v8/ubuntu:16.04 -LABEL image=opnfv/yardstick +LABEL image=opnfv/yardstick_aarch64 ARG BRANCH=master -@@ -40,8 +40,8 @@ RUN echo "daemon off;" >> /etc/nginx/nginx.conf +@@ -24,7 +24,8 @@ ENV YARDSTICK_REPO_DIR="${REPOS_DIR}/yardstick" \ + RELENG_REPO_DIR="${REPOS_DIR}/releng" \ + STORPERF_REPO_DIR="${REPOS_DIR}/storperf" + +-RUN apt-get update && apt-get install -y git python-setuptools python-pip && apt-get -y autoremove && apt-get clean ++RUN apt-get update && apt-get install -y git python-setuptools python-pip && apt-get -y autoremove && \ ++ apt-get install -y libssl-dev && apt-get -y install libffi-dev && apt-get clean + RUN easy_install -U setuptools==30.0.0 + RUN pip install appdirs==1.4.0 pyopenssl==17.5.0 + +@@ -43,8 +44,8 @@ RUN echo "daemon off;" >> /etc/nginx/nginx.conf EXPOSE 5000 @@ -39,4 +50,5 @@ index 96a5d77..03307a2 100644 +ADD http://download.cirros-cloud.net/daily/20161201/cirros-d161201-aarch64-disk.img ${IMAGE_DIR} +ADD http://cloud-images.ubuntu.com/xenial/current/xenial-server-cloudimg-arm64-disk1.img ${IMAGE_DIR} - COPY ./exec_tests.sh /usr/local/bin/
\ No newline at end of file + COPY ./exec_tests.sh /usr/local/bin/ + diff --git a/docs/testing/user/userguide/04-installation.rst b/docs/testing/user/userguide/04-installation.rst index 828c49581..caebecc09 100644 --- a/docs/testing/user/userguide/04-installation.rst +++ b/docs/testing/user/userguide/04-installation.rst @@ -107,6 +107,12 @@ Run the Docker image to get a Yardstick container:: ======================= ==================================================== --name yardstick The name for this container +If the host is restarted +^^^^^^^^^^^^^^^^^^^^^^^^ + +The yardstick container must be started if the host is rebooted:: + + docker start yardstick Configure the Yardstick container environment ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -301,12 +307,6 @@ Prerequisite preparation:: sudo -EH pip install appdirs==1.4.0 sudo -EH pip install virtualenv -Create a virtual environment:: - - virtualenv ~/yardstick_venv - export YARDSTICK_VENV=~/yardstick_venv - source ~/yardstick_venv/bin/activate - Download the source code and install Yardstick from it:: git clone https://gerrit.opnfv.org/gerrit/yardstick @@ -314,6 +314,10 @@ Download the source code and install Yardstick from it:: cd ~/yardstick sudo -EH ./install.sh +If the host is ever restarted, nginx and uwsgi need to be restarted:: + + service nginx restart + uwsgi -i /etc/yardstick/yardstick.ini Configure the Yardstick environment (**Todo**) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/docs/testing/user/userguide/opnfv_yardstick_tc081.rst b/docs/testing/user/userguide/opnfv_yardstick_tc081.rst index 90af8a382..793c3fdd5 100644 --- a/docs/testing/user/userguide/opnfv_yardstick_tc081.rst +++ b/docs/testing/user/userguide/opnfv_yardstick_tc081.rst @@ -4,7 +4,7 @@ .. (c) OPNFV, Huawei Technologies Co.,Ltd and others. ************************************* -Yardstick Test Case Description TC080 +Yardstick Test Case Description TC081 ************************************* .. _cirros-image: https://download.cirros-cloud.net @@ -21,7 +21,7 @@ Yardstick Test Case Description TC080 |metric | RTT (Round Trip Time) | | | | +--------------+--------------------------------------------------------------+ -|test purpose | The purpose of TC080 is to do a basic verification that | +|test purpose | The purpose of TC081 is to do a basic verification that | | | network latency is within acceptable boundaries when packets | | | travel between a containers and a VM. | | | | diff --git a/docs/testing/user/userguide/opnfv_yardstick_tc084.rst b/docs/testing/user/userguide/opnfv_yardstick_tc084.rst new file mode 100644 index 000000000..2e7b28e25 --- /dev/null +++ b/docs/testing/user/userguide/opnfv_yardstick_tc084.rst @@ -0,0 +1,140 @@ +.. This work is licensed under a Creative Commons Attribution 4.0 International +.. License. +.. http://creativecommons.org/licenses/by/4.0 +.. (c) OPNFV, Huawei Technologies Co.,Ltd and others. + +************************************* +Yardstick Test Case Description TC084 +************************************* + +.. _spec_cpu_2006: https://www.spec.org/cpu2006/ + ++-----------------------------------------------------------------------------+ +|Compute Performance | +| | ++--------------+--------------------------------------------------------------+ +|test case id | OPNFV_YARDSTICK_TC084_SPEC CPU 2006 FOR VM | +| | | ++--------------+--------------------------------------------------------------+ +|metric | compute-intensive performance | +| | | ++--------------+--------------------------------------------------------------+ +|test purpose | The purpose of TC084 is to evaluate the IaaS compute | +| | performance by using SPEC CPU 2006 benchmark. The SPEC CPU | +| | 2006 benchmark has several different ways to measure | +| | computer performance. One way is to measure how fast the | +| | computer completes a single task; this is called a speed | +| | measurement. Another way is to measure how many tasks | +| | computer can accomplish in a certain amount of time; this is | +| | called a throughput, capacity or rate measurement. | +| | | ++--------------+--------------------------------------------------------------+ +|test tool | SPEC CPU 2006 | +| | | +| | The SPEC CPU 2006 benchmark is SPEC's industry-standardized, | +| | CPU-intensive benchmark suite, stressing a system's | +| | processor, memory subsystem and compiler. This benchmark | +| | suite includes the SPECint benchmarks and the SPECfp | +| | benchmarks. The SPECint 2006 benchmark contains 12 different | +| | benchmark tests and the SPECfp 2006 benchmark contains 19 | +| | different benchmark tests. | +| | | +| | SPEC CPU 2006 is not always part of a Linux distribution. | +| | SPEC requires that users purchase a license and agree with | +| | their terms and conditions. For this test case, users must | +| | manually download cpu2006-1.2.iso from the SPEC website and | +| | save it under the yardstick/resources folder (e.g. /home/ | +| | opnfv/repos/yardstick/yardstick/resources/cpu2006-1.2.iso) | +| | SPEC CPU® 2006 benchmark is available for purchase via the | +| | SPEC order form (https://www.spec.org/order.html). | +| | | ++--------------+--------------------------------------------------------------+ +|test | This test case uses SPEC CPU 2006 benchmark to measure | +|description | compute-intensive performance of VMs. | +| | | ++--------------+--------------------------------------------------------------+ +|configuration | file: opnfv_yardstick_tc084.yaml | +| | | +| | benchmark_subset is set to int. | +| | | +| | SLA is not available in this test case. | +| | | ++--------------+--------------------------------------------------------------+ +|applicability | Test can be configured with different: | +| | | +| | * benchmark_subset - a subset of SPEC CPU 2006 benchmarks | +| | to run; | +| | * SPECint_benchmark - a SPECint benchmark to run; | +| | * SPECint_benchmark - a SPECfp benchmark to run; | +| | * output_format - desired report format; | +| | * runspec_config - SPEC CPU 2006 config file provided to | +| | the runspec binary; | +| | * runspec_iterations - the number of benchmark iterations | +| | to execute. For a reportable run, must be 3; | +| | * runspec_tune - tuning to use (base, peak, or all). For a | +| | reportable run, must be either base or all. Reportable | +| | runs do base first, then (optionally) peak; | +| | * runspec_size - size of input data to run (test, train, or | +| | ref). Reportable runs ensure that your binaries can | +| | produce correct results with the test and train workloads | +| | | ++--------------+--------------------------------------------------------------+ +|usability | This test case is used for executing SPEC CPU 2006 benchmark | +| | on virtual machines. The SPECint 2006 benchmark takes | +| | approximately 5 hours. (The time may vary due to different | +| | VM cpu configurations) | +| | | ++--------------+--------------------------------------------------------------+ +|references | spec_cpu_2006_ | +| | | +| | ETSI-NFV-TST001 | +| | | ++--------------+--------------------------------------------------------------+ +|pre-test | To run and install SPEC CPU 2006, the following are | +|conditions | required: | +| | * For SPECint 2006: Both C99 and C++98 compilers are | +| | installed in VM images; | +| | * For SPECfp 2006: All three of C99, C++98 and Fortran-95 | +| | compilers installed in VM images; | +| | * At least 4GB of disk space availabile on VM. | +| | | +| | gcc 4.8.* and g++ 4.8.* version have been tested in Ubuntu | +| | 14.04, Ubuntu 16.04 and Redhat Enterprise Linux 7.4 image. | +| | Higher gcc and g++ version may cause compiling error. | +| | | +| | For more SPEC CPU 2006 dependencies please visit | +| | (https://www.spec.org/cpu2006/Docs/techsupport.html) | +| | | ++--------------+--------------------------------------------------------------+ +|test sequence | description and expected result | +| | | ++--------------+--------------------------------------------------------------+ +|step 1 | cpu2006-1.2.iso has been saved under the yardstick/resources | +| | folder (e.g. /home/opnfv/repos/yardstick/yardstick/resources | +| | /cpu2006-1.2.iso). Additionally, to use your custom runspec | +| | config file you can save it under the yardstick/resources/ | +| | files folder and specify the config file name in the | +| | runspec_config parameter. | +| | | ++--------------+--------------------------------------------------------------+ +|step 2 | Upload SPEC CPU 2006 ISO to the target VM using scp and | +| | install SPEC CPU 2006. | +| | | ++--------------+--------------------------------------------------------------+ +|step 3 | Connect to the target server using SSH. | +| | If custom runspec config file is used, copy this file from | +| | yardstick to the target VM via the SSH tunnel. | +| | | ++--------------+--------------------------------------------------------------+ +|step 4 | SPEC CPU 2006 benchmark is invoked and SPEC CPU 2006 metrics | +| | are generated. | +| | | ++--------------+--------------------------------------------------------------+ +|step 5 | Text, HTML, CSV, PDF, and Configuration file outputs for the | +| | SPEC CPU 2006 metrics are fetched from the VM and stored | +| | under /tmp/result folder. | +| | | ++--------------+--------------------------------------------------------------+ +|test verdict | None. SPEC CPU 2006 results are collected and stored. | +| | | ++--------------+--------------------------------------------------------------+ diff --git a/requirements.txt b/requirements.txt index 7fdd8f005..88c0e659a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,7 +11,7 @@ Babel==2.3.4 # BSD; OSI Approved BSD License Jinja2==2.9.6 # BSD; OSI Approved BSD License SQLAlchemy==1.1.12 # MIT License; OSI Approved MIT License PTable==0.9.2 # BSD (3 clause); OSI Approved BSD License -ansible==2.3.2 # GPLv3; OSI Approved GNU General Public License v3 or later (GPLv3+) +ansible==2.4.2 # GPLv3; OSI Approved GNU General Public License v3 or later (GPLv3+) backport-ipaddress==0.1; python_version <= "2.7" # OSI Approved Python Software Foundation License chainmap==1.0.2 # Python Software Foundation License; OSI Approved Python Software Foundation License django==1.8.17 # BSD; OSI Approved BSD License diff --git a/tests/ci/load_images.sh b/tests/ci/load_images.sh index 80caf07ae..caaba9e8b 100755 --- a/tests/ci/load_images.sh +++ b/tests/ci/load_images.sh @@ -133,7 +133,7 @@ load_cirros_image() CIRROS_IMAGE_PATH="/home/opnfv/images/cirros-d161201-aarch64-disk.img" EXTRA_PARAMS="--property hw_video_model=vga --property short_id=ubuntu16.04" else - CIRROS_IMAGE_VERSION="Cirros-0.3.5" + CIRROS_IMAGE_VERSION="cirros-0.3.5" CIRROS_IMAGE_PATH="/home/opnfv/images/cirros-0.3.5-x86_64-disk.img" fi diff --git a/tests/unit/benchmark/contexts/standalone/test_model.py b/tests/unit/benchmark/contexts/standalone/test_model.py index 31ec2b7d1..a8c54f193 100644 --- a/tests/unit/benchmark/contexts/standalone/test_model.py +++ b/tests/unit/benchmark/contexts/standalone/test_model.py @@ -134,9 +134,9 @@ class ModelLibvirtTestCase(unittest.TestCase): as mock_parse: xml = copy.deepcopy(self.xml) mock_parse.return_value = xml - vf_pci = '0001:05:04.2' + vm_pci = '0001:05:04.2' model.Libvirt.add_sriov_interfaces( - self.pci_address_str, vf_pci, self.mac, xml_input) + vm_pci, self.pci_address_str, self.mac, xml_input) mock_parse.assert_called_once_with(xml_input) self.mock_write_xml.assert_called_once_with(xml_input) interface = xml.find('devices').find('interface') @@ -145,8 +145,29 @@ class ModelLibvirtTestCase(unittest.TestCase): mac = interface.find('mac') self.assertEqual(self.mac, mac.get('address')) source = interface.find('source') + source_address = source.find('address') self.assertIsNotNone(source.find('address')) - self.assertIsNotNone(interface.find('address')) + + self.assertEqual('pci', source_address.get('type')) + self.assertEqual('0x' + self.pci_address_str.split(':')[0], + source_address.get('domain')) + self.assertEqual('0x' + self.pci_address_str.split(':')[1], + source_address.get('bus')) + self.assertEqual('0x' + self.pci_address_str.split(':')[2].split('.')[0], + source_address.get('slot')) + self.assertEqual('0x' + self.pci_address_str.split(':')[2].split('.')[1], + source_address.get('function')) + + interface_address = interface.find('address') + self.assertEqual('pci', interface_address.get('type')) + self.assertEqual('0x' + vm_pci.split(':')[0], + interface_address.get('domain')) + self.assertEqual('0x' + vm_pci.split(':')[1], + interface_address.get('bus')) + self.assertEqual('0x' + vm_pci.split(':')[2].split('.')[0], + interface_address.get('slot')) + self.assertEqual('0x' + vm_pci.split(':')[2].split('.')[1], + interface_address.get('function')) def test_create_snapshot_qemu(self): result = "/var/lib/libvirt/images/0.qcow2" diff --git a/tests/unit/benchmark/scenarios/lib/test_create_volume.py b/tests/unit/benchmark/scenarios/lib/test_create_volume.py index fc633139e..ef2c0ccaf 100644 --- a/tests/unit/benchmark/scenarios/lib/test_create_volume.py +++ b/tests/unit/benchmark/scenarios/lib/test_create_volume.py @@ -9,28 +9,79 @@ import unittest import mock -from yardstick.benchmark.scenarios.lib.create_volume import CreateVolume +import yardstick.benchmark.scenarios.lib.create_volume class CreateVolumeTestCase(unittest.TestCase): + def setUp(self): + self._mock_cinder_client = mock.patch( + 'yardstick.common.openstack_utils.get_cinder_client') + self.mock_cinder_client = self._mock_cinder_client.start() + self._mock_glance_client = mock.patch( + 'yardstick.common.openstack_utils.get_glance_client') + self.mock_glance_client = self._mock_glance_client.start() + self.addCleanup(self._stop_mock) + + self.scenario_cfg = { + "options" : + { + 'volume_name': 'yardstick_test_volume_01', + 'size': '256', + 'image': 'cirros-0.3.5' + } + } + + self.scenario = ( + yardstick.benchmark.scenarios.lib.create_volume.CreateVolume( + scenario_cfg=self.scenario_cfg, + context_cfg={})) + + def _stop_mock(self): + self._mock_cinder_client.stop() + self._mock_glance_client.stop() + + def test_init(self): + self.mock_cinder_client.return_value = "All volumes are equal" + self.mock_glance_client.return_value = "Images are more equal" + + expected_vol_name = self.scenario_cfg["options"]["volume_name"] + expected_vol_size = self.scenario_cfg["options"]["size"] + expected_im_name = self.scenario_cfg["options"]["image"] + expected_im_id = None + + scenario = ( + yardstick.benchmark.scenarios.lib.create_volume.CreateVolume( + scenario_cfg=self.scenario_cfg, + context_cfg={})) + + self.assertEqual(expected_vol_name, scenario.volume_name) + self.assertEqual(expected_vol_size, scenario.volume_size) + self.assertEqual(expected_im_name, scenario.image_name) + self.assertEqual(expected_im_id, scenario.image_id) + self.assertEqual("All volumes are equal", scenario.cinder_client) + self.assertEqual("Images are more equal", scenario.glance_client) + + def test_setup(self): + self.assertFalse(self.scenario.setup_done) + self.scenario.setup() + self.assertTrue(self.scenario.setup_done) + @mock.patch('yardstick.common.openstack_utils.create_volume') @mock.patch('yardstick.common.openstack_utils.get_image_id') - @mock.patch('yardstick.common.openstack_utils.get_cinder_client') - @mock.patch('yardstick.common.openstack_utils.get_glance_client') - def test_create_volume(self, mock_get_glance_client, mock_get_cinder_client, mock_image_id, mock_create_volume): - options = { - 'volume_name': 'yardstick_test_volume_01', - 'size': '256', - 'image': 'cirros-0.3.5' - } - args = {"options": options} - obj = CreateVolume(args, {}) - obj.run({}) - self.assertTrue(mock_create_volume.called) - self.assertTrue(mock_image_id.called) - self.assertTrue(mock_get_glance_client.called) - self.assertTrue(mock_get_cinder_client.called) + def test_run(self, mock_image_id, mock_create_volume): + self.scenario.run() + + mock_image_id.assert_called_once() + mock_create_volume.assert_called_once() + + @mock.patch.object( + yardstick.benchmark.scenarios.lib.create_volume.CreateVolume, 'setup') + def test_run_no_setup(self, scenario_setup): + self.scenario.setup_done = False + self.scenario.run() + scenario_setup.assert_called_once() + def main(): unittest.main() diff --git a/tests/unit/network_services/nfvi/test_resource.py b/tests/unit/network_services/nfvi/test_resource.py index 5c2f890e8..4584b093d 100644 --- a/tests/unit/network_services/nfvi/test_resource.py +++ b/tests/unit/network_services/nfvi/test_resource.py @@ -12,11 +12,10 @@ # See the License for the specific language governing permissions and # limitations under the License. -from __future__ import absolute_import -import unittest - import errno + import mock +import unittest from yardstick.network_services.nfvi.resource import ResourceProfile from yardstick.network_services.nfvi import resource, collectd @@ -105,14 +104,16 @@ class TestResourceProfile(unittest.TestCase): def test___init__(self): self.assertEqual(True, self.resource_profile.enable) - def test_check_if_sa_running(self): - self.assertEqual(self.resource_profile.check_if_sa_running("collectd"), + def test_check_if_system_agent_running(self): + self.assertEqual(self.resource_profile.check_if_system_agent_running("collectd"), (0, "")) - def test_check_if_sa_running_excetion(self): + def test_check_if_system_agent_running_excetion(self): with mock.patch.object(self.resource_profile.connection, "execute") as mock_execute: mock_execute.side_effect = OSError(errno.ECONNRESET, "error") - self.assertEqual(self.resource_profile.check_if_sa_running("collectd"), (1, None)) + self.assertEqual( + self.resource_profile.check_if_system_agent_running("collectd"), + (1, None)) def test_get_cpu_data(self): reskey = ["", "cpufreq", "cpufreq-0"] @@ -139,8 +140,7 @@ class TestResourceProfile(unittest.TestCase): self.resource_profile._setup_ovs_stats(self.ssh_mock)) @mock.patch("yardstick.network_services.nfvi.resource.open") - @mock.patch("yardstick.network_services.nfvi.resource.os") - def test__provide_config_file(self, mock_open, mock_os): + def test__provide_config_file(self, *args): loadplugin = range(5) port_names = range(5) kwargs = { @@ -152,13 +152,13 @@ class TestResourceProfile(unittest.TestCase): self.ssh_mock.execute.assert_called_once() @mock.patch("yardstick.network_services.nfvi.resource.open") - def test_initiate_systemagent(self, mock_open): + def test_initiate_systemagent(self, *args): self.resource_profile._start_collectd = mock.Mock() self.assertIsNone( self.resource_profile.initiate_systemagent("/opt/nsb_bin")) @mock.patch("yardstick.network_services.nfvi.resource.open") - def test_initiate_systemagent_raise(self, mock_open): + def test_initiate_systemagent_raise(self, *args): self.resource_profile._start_collectd = mock.Mock(side_effect=RuntimeError) with self.assertRaises(RuntimeError): self.resource_profile.initiate_systemagent("/opt/nsb_bin") @@ -267,8 +267,10 @@ class TestResourceProfile(unittest.TestCase): def test_stop(self): self.assertIsNone(self.resource_profile.stop()) - def test_stop(self): + def test_stop_amqp_not_running(self): self.resource_profile.amqp_client = mock.MagicMock() + # TODO(efoley): Fix this incorrect test. + # Should check that we don't try to stop amqp when it's not running self.assertIsNone(self.resource_profile.stop()) if __name__ == '__main__': diff --git a/tests/unit/network_services/vnf_generic/vnf/test_prox_helpers.py b/tests/unit/network_services/vnf_generic/vnf/test_prox_helpers.py index ed49c7000..0ac46c632 100644 --- a/tests/unit/network_services/vnf_generic/vnf/test_prox_helpers.py +++ b/tests/unit/network_services/vnf_generic/vnf/test_prox_helpers.py @@ -16,15 +16,17 @@ # from itertools import repeat, chain -import mock import os import socket import time + +import mock import unittest from tests.unit import STL_MOCKS from yardstick.network_services.vnf_generic.vnf.base import VnfdHelper + STLClient = mock.MagicMock() stl_patch = mock.patch.dict("sys.modules", STL_MOCKS) stl_patch.start() @@ -1433,9 +1435,9 @@ class TestProxResourceHelper(unittest.TestCase): helper = ProxResourceHelper(mock.MagicMock()) helper.resource = resource = mock.MagicMock() - resource.check_if_sa_running.return_value = 0, '1234' + resource.check_if_system_agent_running.return_value = 0, '1234' resource.amqp_collect_nfvi_kpi.return_value = 543 - resource.check_if_sa_running.return_value = (0, None) + resource.check_if_system_agent_running.return_value = (0, None) expected = {'core': 543} result = helper.collect_collectd_kpi() @@ -1447,9 +1449,9 @@ class TestProxResourceHelper(unittest.TestCase): helper._result = {'z': 123} helper.resource = resource = mock.MagicMock() - resource.check_if_sa_running.return_value = 0, '1234' + resource.check_if_system_agent_running.return_value = 0, '1234' resource.amqp_collect_nfvi_kpi.return_value = 543 - resource.check_if_sa_running.return_value = (0, None) + resource.check_if_system_agent_running.return_value = (0, None) queue.empty.return_value = False queue.get.return_value = {'a': 789} diff --git a/tests/unit/network_services/vnf_generic/vnf/test_tg_prox.py b/tests/unit/network_services/vnf_generic/vnf/test_tg_prox.py index 7b4d79e02..0104e7f63 100644 --- a/tests/unit/network_services/vnf_generic/vnf/test_tg_prox.py +++ b/tests/unit/network_services/vnf_generic/vnf/test_tg_prox.py @@ -330,7 +330,7 @@ class TestProxTrafficGen(unittest.TestCase): prox_traffic_gen = ProxTrafficGen(NAME, self.VNFD0) prox_traffic_gen._vnf_wrapper.resource_helper.resource = mock.MagicMock( - **{"check_if_sa_running.return_value": [False]}) + **{"self.check_if_system_agent_running.return_value": [False]}) prox_traffic_gen._vnf_wrapper.vnf_execute = mock.Mock(return_value="") self.assertEqual({}, prox_traffic_gen.collect_kpi()) diff --git a/tests/unit/network_services/vnf_generic/vnf/test_vpe_vnf.py b/tests/unit/network_services/vnf_generic/vnf/test_vpe_vnf.py index 55cd4d2e8..1abc53688 100644 --- a/tests/unit/network_services/vnf_generic/vnf/test_vpe_vnf.py +++ b/tests/unit/network_services/vnf_generic/vnf/test_vpe_vnf.py @@ -15,11 +15,12 @@ # limitations under the License. # -import mock from multiprocessing import Process, Queue import os -import six.moves.configparser as configparser import time + +import mock +import six.moves.configparser as configparser import unittest from tests.unit import STL_MOCKS @@ -543,9 +544,9 @@ class TestVpeApproxVnf(unittest.TestCase): mock_ssh(ssh) resource = mock.Mock(autospec=ResourceProfile) - resource.check_if_sa_running.return_value = 1, '' + resource.check_if_system_agent_running.return_value = 1, '' resource.amqp_collect_nfvi_kpi.return_value = {'foo': 234} - resource.check_if_sa_running.return_value = (1, None) + resource.check_if_system_agent_running.return_value = (1, None) vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0) vpe_approx_vnf.q_in = mock.MagicMock() @@ -567,7 +568,7 @@ class TestVpeApproxVnf(unittest.TestCase): mock_ssh(ssh) resource = mock.Mock(autospec=ResourceProfile) - resource.check_if_sa_running.return_value = 0, '1234' + resource.check_if_system_agent_running.return_value = 0, '1234' resource.amqp_collect_nfvi_kpi.return_value = {'foo': 234} vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0) diff --git a/tools/run_tests.sh b/tools/run_tests.sh index 633c93859..32c4f19e4 100755 --- a/tools/run_tests.sh +++ b/tools/run_tests.sh @@ -29,9 +29,16 @@ run_tests() { echo "Running unittest ... " if [ $FILE_OPTION == "f" ]; then python -m unittest discover -v -s tests/unit > $logfile 2>&1 + if [ $? -ne 0 ]; then + echo "FAILED, results in $logfile" + exit 1 + fi python -m unittest discover -v -s yardstick/tests/unit >> $logfile 2>&1 else python -m unittest discover -v -s tests/unit + if [ $? -ne 0 ]; then + exit 1 + fi python -m unittest discover -v -s yardstick/tests/unit fi diff --git a/yardstick/benchmark/contexts/standalone/model.py b/yardstick/benchmark/contexts/standalone/model.py index 85ae14b1d..0d58e91b0 100644 --- a/yardstick/benchmark/contexts/standalone/model.py +++ b/yardstick/benchmark/contexts/standalone/model.py @@ -212,9 +212,8 @@ class Libvirt(object): mac.set('address', vf_mac) source = ET.SubElement(interface, 'source') - addr = ET.SubElement(source, 'address') pci_address = PciAddress(vf_pci.strip()) - cls._add_interface_address(addr, pci_address) + cls._add_interface_address(source, pci_address) pci_vm_address = PciAddress(vm_pci.strip()) cls._add_interface_address(interface, pci_vm_address) diff --git a/yardstick/benchmark/scenarios/lib/create_volume.py b/yardstick/benchmark/scenarios/lib/create_volume.py index c7086d0ef..df523a5ec 100644 --- a/yardstick/benchmark/scenarios/lib/create_volume.py +++ b/yardstick/benchmark/scenarios/lib/create_volume.py @@ -44,22 +44,21 @@ class CreateVolume(base.Scenario): self.setup_done = True - def run(self, result): + def run(self): """execute the test""" if not self.setup_done: self.setup() - if self.image_name: - self.image_id = op_utils.get_image_id(self.glance_client, - self.image_name) + self.image_id = op_utils.get_image_id(self.glance_client, + self.image_name) volume = op_utils.create_volume(self.cinder_client, self.volume_name, self.volume_size, self.image_id) status = volume.status while(status == 'creating' or status == 'downloading'): - LOG.info("Volume status is: %s" % status) + LOG.info("Volume status is: %s", status) time.sleep(5) volume = op_utils.get_volume_by_name(self.volume_name) status = volume.status diff --git a/yardstick/common/utils.py b/yardstick/common/utils.py index 82e20bec7..8604e900f 100644 --- a/yardstick/common/utils.py +++ b/yardstick/common/utils.py @@ -13,27 +13,22 @@ # License for the specific language governing permissions and limitations # under the License. -# yardstick comment: this is a modified copy of rally/rally/common/utils.py - -from __future__ import absolute_import -from __future__ import print_function - +import collections +from contextlib import closing import datetime import errno +import importlib +import ipaddress import logging import os +import random +import socket import subprocess import sys -import collections -import socket -import random -import ipaddress -from contextlib import closing import six from flask import jsonify from six.moves import configparser -from oslo_utils import importutils from oslo_serialization import jsonutils import yardstick @@ -70,27 +65,28 @@ def itersubclasses(cls, _seen=None): def import_modules_from_package(package): - """Import modules from package and append into sys.modules + """Import modules given a package name :param: package - Full package name. For example: rally.deploy.engines """ yardstick_root = os.path.dirname(os.path.dirname(yardstick.__file__)) - path = os.path.join(yardstick_root, *package.split(".")) + path = os.path.join(yardstick_root, *package.split('.')) for root, _, files in os.walk(path): - matches = (filename for filename in files if filename.endswith(".py") and - not filename.startswith("__")) - new_package = os.path.relpath(root, yardstick_root).replace(os.sep, ".") + matches = (filename for filename in files if filename.endswith('.py') + and not filename.startswith('__')) + new_package = os.path.relpath(root, yardstick_root).replace(os.sep, + '.') module_names = set( - ("{}.{}".format(new_package, filename.rsplit(".py", 1)[0]) for filename in matches)) - # find modules which haven't already been imported + '{}.{}'.format(new_package, filename.rsplit('.py', 1)[0]) + for filename in matches) + # Find modules which haven't already been imported missing_modules = module_names.difference(sys.modules) - logger.debug("importing %s", missing_modules) - # we have already checked for already imported modules, so we don't need to check again + logger.debug('Importing modules: %s', missing_modules) for module_name in missing_modules: try: - sys.modules[module_name] = importutils.import_module(module_name) + importlib.import_module(module_name) except (ImportError, SyntaxError): - logger.exception("unable to import %s", module_name) + logger.exception('Unable to import module %s', module_name) def makedirs(d): diff --git a/yardstick/network_services/collector/subscriber.py b/yardstick/network_services/collector/subscriber.py index 4dc5a796e..7e18302eb 100644 --- a/yardstick/network_services/collector/subscriber.py +++ b/yardstick/network_services/collector/subscriber.py @@ -62,12 +62,13 @@ class Collector(object): # Result example: # {"VNF1: { "tput" : [1000, 999] }, "VNF2": { "latency": 100 }} LOG.debug("collect KPI for %s", node_name) - if resource.check_if_sa_running("collectd")[0] != 0: + if resource.check_if_system_agent_running("collectd")[0] != 0: continue try: results[node_name] = {"core": resource.amqp_collect_nfvi_kpi()} LOG.debug("%s collect KPIs %s", node_name, results[node_name]['core']) - except Exception: - LOG.exception("") + # NOTE(elfoley): catch a more specific error + except Exception as exc: # pylint: disable=broad-except + LOG.exception(exc) return results diff --git a/yardstick/network_services/nfvi/resource.py b/yardstick/network_services/nfvi/resource.py index adf4d8ae6..dc5c46a86 100644 --- a/yardstick/network_services/nfvi/resource.py +++ b/yardstick/network_services/nfvi/resource.py @@ -13,20 +13,16 @@ # limitations under the License. """ Resource collection definitions """ -from __future__ import absolute_import -from __future__ import print_function - -import logging -from itertools import chain - import errno -import jinja2 +from itertools import chain +import logging +import multiprocessing import os import os.path import re -import multiprocessing -import pkg_resources +import jinja2 +import pkg_resources from oslo_config import cfg from oslo_utils.encodeutils import safe_decode @@ -92,7 +88,7 @@ class ResourceProfile(object): return cls(node, plugins=plugins, interval=interval, timeout=timeout) - def check_if_sa_running(self, process): + def check_if_system_agent_running(self, process): """ verify if system agent is running """ try: err, pid, _ = self.connection.execute("pgrep -f %s" % process) @@ -101,7 +97,7 @@ class ResourceProfile(object): except OSError as e: if e.errno in {errno.ECONNRESET}: # if we can't connect to check, then we won't be able to connect to stop it - LOG.exception("can't connect to host to check collectd status") + LOG.exception("Can't connect to host to check %s status", process) return 1, None raise @@ -327,7 +323,7 @@ class ResourceProfile(object): self.amqp_client.terminate() LOG.debug("Check if %s is running", agent) - status, pid = self.check_if_sa_running(agent) + status, pid = self.check_if_system_agent_running(agent) LOG.debug("status %s pid %s", status, pid) if status != 0: return diff --git a/yardstick/network_services/vnf_generic/vnf/sample_vnf.py b/yardstick/network_services/vnf_generic/vnf/sample_vnf.py index 5eeb6c889..fbaaa0ca8 100644 --- a/yardstick/network_services/vnf_generic/vnf/sample_vnf.py +++ b/yardstick/network_services/vnf_generic/vnf/sample_vnf.py @@ -13,38 +13,34 @@ # limitations under the License. """ Base class implementation for generic vnf implementation """ -from __future__ import absolute_import - -import posixpath -import time +from collections import Mapping import logging +from multiprocessing import Queue, Value, Process import os +import posixpath import re -import subprocess -from collections import Mapping -from multiprocessing import Queue, Value, Process - from six.moves import cStringIO +import subprocess +import time +from trex_stl_lib.trex_stl_client import LoggerApi +from trex_stl_lib.trex_stl_client import STLClient +from trex_stl_lib.trex_stl_exceptions import STLError from yardstick.benchmark.contexts.base import Context from yardstick.benchmark.scenarios.networking.vnf_generic import find_relative_file from yardstick.common import exceptions as y_exceptions from yardstick.common.process import check_if_process_failed +from yardstick.network_services.helpers.dpdkbindnic_helper import DpdkBindHelper from yardstick.network_services.helpers.samplevnf_helper import PortPairs from yardstick.network_services.helpers.samplevnf_helper import MultiPortConfig -from yardstick.network_services.helpers.dpdkbindnic_helper import DpdkBindHelper from yardstick.network_services.nfvi.resource import ResourceProfile +from yardstick.network_services.utils import get_nsb_option from yardstick.network_services.vnf_generic.vnf.base import GenericVNF -from yardstick.network_services.vnf_generic.vnf.base import QueueFileWrapper from yardstick.network_services.vnf_generic.vnf.base import GenericTrafficGen -from yardstick.network_services.utils import get_nsb_option - -from trex_stl_lib.trex_stl_client import STLClient -from trex_stl_lib.trex_stl_client import LoggerApi -from trex_stl_lib.trex_stl_exceptions import STLError - +from yardstick.network_services.vnf_generic.vnf.base import QueueFileWrapper from yardstick.ssh import AutoConnectSSH + DPDK_VERSION = "dpdk-16.07" LOG = logging.getLogger(__name__) @@ -346,7 +342,7 @@ class ResourceHelper(object): def _collect_resource_kpi(self): result = {} - status = self.resource.check_if_sa_running("collectd")[0] + status = self.resource.check_if_system_agent_running("collectd")[0] if status == 0: result = self.resource.amqp_collect_nfvi_kpi() diff --git a/tests/unit/dispatcher/__init__.py b/yardstick/tests/functional/common/__init__.py index e69de29bb..e69de29bb 100644 --- a/tests/unit/dispatcher/__init__.py +++ b/yardstick/tests/functional/common/__init__.py diff --git a/tests/unit/orchestrator/__init__.py b/yardstick/tests/functional/common/fake_module/__init__.py index e69de29bb..e69de29bb 100644 --- a/tests/unit/orchestrator/__init__.py +++ b/yardstick/tests/functional/common/fake_module/__init__.py diff --git a/yardstick/tests/functional/common/fake_module/fake_library.py b/yardstick/tests/functional/common/fake_module/fake_library.py new file mode 100644 index 000000000..28c7dc694 --- /dev/null +++ b/yardstick/tests/functional/common/fake_module/fake_library.py @@ -0,0 +1,17 @@ +# Copyright (c) 2018 Intel Corporation +# +# 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. + + +class FakeClassToBeImported(object): + pass diff --git a/yardstick/tests/functional/common/test_utils.py b/yardstick/tests/functional/common/test_utils.py new file mode 100644 index 000000000..b5333bbde --- /dev/null +++ b/yardstick/tests/functional/common/test_utils.py @@ -0,0 +1,34 @@ +# Copyright (c) 2018 Intel Corporation +# +# 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. + +import unittest +import sys + +from yardstick.common import utils + + +class ImportModulesFromPackageTestCase(unittest.TestCase): + + def test_import_package(self): + module_name = 'yardstick.tests.functional.common.fake_module' + library_name = 'fake_library' + class_name = 'FakeClassToBeImported' + self.assertNotIn(module_name, sys.modules) + + utils.import_modules_from_package(module_name) + self.assertIn(module_name, sys.modules) + module_obj = sys.modules[module_name] + library_obj = getattr(module_obj, library_name) + class_obj = getattr(library_obj, class_name) + self.assertEqual(class_name, class_obj().__class__.__name__) diff --git a/yardstick/tests/unit/common/test_utils.py b/yardstick/tests/unit/common/test_utils.py index 452b93a56..033bb0243 100644 --- a/yardstick/tests/unit/common/test_utils.py +++ b/yardstick/tests/unit/common/test_utils.py @@ -7,12 +7,9 @@ # http://www.apache.org/licenses/LICENSE-2.0 ############################################################################## -# Unittest for yardstick.common.utils - -from __future__ import absolute_import - from copy import deepcopy import errno +import importlib import ipaddress from itertools import product, chain import mock @@ -60,8 +57,8 @@ class ImportModulesFromPackageTestCase(unittest.TestCase): utils.import_modules_from_package('foo.bar') @mock.patch('yardstick.common.utils.os.walk') - @mock.patch('yardstick.common.utils.importutils') - def test_import_modules_from_package(self, mock_importutils, mock_walk): + @mock.patch.object(importlib, 'import_module') + def test_import_modules_from_package(self, mock_import_module, mock_walk): yardstick_root = os.path.dirname(os.path.dirname(yardstick.__file__)) mock_walk.return_value = ([ @@ -69,7 +66,7 @@ class ImportModulesFromPackageTestCase(unittest.TestCase): ]) utils.import_modules_from_package('foo.bar') - mock_importutils.import_module.assert_called_with('bar.baz') + mock_import_module.assert_called_once_with('bar.baz') class GetParaFromYaml(unittest.TestCase): diff --git a/yardstick/tests/unit/dispatcher/__init__.py b/yardstick/tests/unit/dispatcher/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/yardstick/tests/unit/dispatcher/__init__.py diff --git a/tests/unit/dispatcher/test_influxdb.py b/yardstick/tests/unit/dispatcher/test_influxdb.py index 7ebe8c90b..bca94e385 100644 --- a/tests/unit/dispatcher/test_influxdb.py +++ b/yardstick/tests/unit/dispatcher/test_influxdb.py @@ -11,20 +11,15 @@ # Unittest for yardstick.dispatcher.influxdb -from __future__ import absolute_import +import mock import unittest +from yardstick.dispatcher.influxdb import InfluxdbDispatcher +from yardstick import _init_logging -try: - from unittest import mock -except ImportError: - import mock -from yardstick import _init_logging _init_logging() -from yardstick.dispatcher.influxdb import InfluxdbDispatcher - class InfluxdbDispatcherTestCase(unittest.TestCase): diff --git a/tests/unit/dispatcher/test_influxdb_line_protocol.py b/yardstick/tests/unit/dispatcher/test_influxdb_line_protocol.py index 51dc39e3c..641e97fae 100644 --- a/tests/unit/dispatcher/test_influxdb_line_protocol.py +++ b/yardstick/tests/unit/dispatcher/test_influxdb_line_protocol.py @@ -11,7 +11,6 @@ # yardstick comment: this file is a modified copy of # influxdb-python/influxdb/tests/test_line_protocol.py -from __future__ import absolute_import import unittest from third_party.influxdb.influxdb_line_protocol import make_lines diff --git a/yardstick/tests/unit/orchestrator/__init__.py b/yardstick/tests/unit/orchestrator/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/yardstick/tests/unit/orchestrator/__init__.py diff --git a/tests/unit/orchestrator/test_heat.py b/yardstick/tests/unit/orchestrator/test_heat.py index c34ea53fc..faf70cdbc 100644 --- a/tests/unit/orchestrator/test_heat.py +++ b/yardstick/tests/unit/orchestrator/test_heat.py @@ -13,10 +13,11 @@ from contextlib import contextmanager from itertools import count from tempfile import NamedTemporaryFile -import unittest -import uuid import time +import uuid + import mock +import unittest from yardstick.benchmark.contexts import node from yardstick.orchestrator import heat @@ -65,6 +66,7 @@ class HeatContextTestCase(unittest.TestCase): self.assertEqual(heat.HEAT_KEY_UUID_LENGTH, len(k)) self.assertIn(k, str(u)) + class HeatTemplateTestCase(unittest.TestCase): def setUp(self): @@ -73,38 +75,63 @@ class HeatTemplateTestCase(unittest.TestCase): def test_add_tenant_network(self): self.template.add_network('some-network') - self.assertEqual(self.template.resources['some-network']['type'], 'OS::Neutron::Net') + self.assertEqual( + self.template.resources['some-network']['type'], + 'OS::Neutron::Net') def test_add_provider_network(self): self.template.add_network('some-network', 'physnet2', 'sriov') - self.assertEqual(self.template.resources['some-network']['type'], 'OS::Neutron::ProviderNet') - self.assertEqual(self.template.resources['some-network']['properties']['physical_network'], 'physnet2') + self.assertEqual( + self.template.resources['some-network']['type'], + 'OS::Neutron::ProviderNet') + self.assertEqual( + self.template.resources['some-network']['properties']['physical_network'], + 'physnet2') def test_add_subnet(self): - netattrs = {'cidr': '10.0.0.0/24', 'provider': None, 'external_network': 'ext_net'} - self.template.add_subnet('some-subnet', "some-network", netattrs['cidr']) - - self.assertEqual(self.template.resources['some-subnet']['type'], 'OS::Neutron::Subnet') - self.assertEqual(self.template.resources['some-subnet']['properties']['cidr'], '10.0.0.0/24') + netattrs = {'cidr': '10.0.0.0/24', + 'provider': None, 'external_network': 'ext_net'} + self.template.add_subnet( + 'some-subnet', "some-network", netattrs['cidr']) + + self.assertEqual( + self.template.resources['some-subnet']['type'], + 'OS::Neutron::Subnet') + self.assertEqual( + self.template.resources['some-subnet']['properties']['cidr'], + '10.0.0.0/24') def test_add_router(self): self.template.add_router('some-router', 'ext-net', 'some-subnet') - self.assertEqual(self.template.resources['some-router']['type'], 'OS::Neutron::Router') - self.assertIn('some-subnet', self.template.resources['some-router']['depends_on']) + self.assertEqual( + self.template.resources['some-router']['type'], + 'OS::Neutron::Router') + self.assertIn( + 'some-subnet', + self.template.resources['some-router']['depends_on']) def test_add_router_interface(self): - self.template.add_router_interface('some-router-if', 'some-router', 'some-subnet') + self.template.add_router_interface( + 'some-router-if', 'some-router', 'some-subnet') - self.assertEqual(self.template.resources['some-router-if']['type'], 'OS::Neutron::RouterInterface') - self.assertIn('some-subnet', self.template.resources['some-router-if']['depends_on']) + self.assertEqual( + self.template.resources['some-router-if']['type'], + 'OS::Neutron::RouterInterface') + self.assertIn( + 'some-subnet', + self.template.resources['some-router-if']['depends_on']) def test_add_servergroup(self): self.template.add_servergroup('some-server-group', 'anti-affinity') - self.assertEqual(self.template.resources['some-server-group']['type'], 'OS::Nova::ServerGroup') - self.assertEqual(self.template.resources['some-server-group']['properties']['policies'], ['anti-affinity']) + self.assertEqual( + self.template.resources['some-server-group']['type'], + 'OS::Nova::ServerGroup') + self.assertEqual( + self.template.resources['some-server-group']['properties']['policies'], + ['anti-affinity']) def test__add_resources_to_template_raw(self): test_context = node.NodeContext() @@ -136,49 +163,136 @@ class HeatTemplateTestCase(unittest.TestCase): heat_template.add_router("router1", "gw1", "subnet1") heat_template.add_router_interface("router_if1", "router1", "subnet1") heat_template.add_port("port1", "network1", "subnet1", "normal") - heat_template.add_port("port2", "network2", "subnet2", "normal", sec_group_id="sec_group1",provider="not-sriov") - heat_template.add_port("port3", "network2", "subnet2", "normal", sec_group_id="sec_group1",provider="sriov") - heat_template.add_floating_ip("floating_ip1", "network1", "port1", "router_if1") - heat_template.add_floating_ip("floating_ip2", "network2", "port2", "router_if2", "foo-secgroup") - heat_template.add_floating_ip_association("floating_ip1_association", "floating_ip1", "port1") + heat_template.add_port( + "port2", + "network2", + "subnet2", + "normal", + sec_group_id="sec_group1", + provider="not-sriov") + heat_template.add_port( + "port3", + "network2", + "subnet2", + "normal", + sec_group_id="sec_group1", + provider="sriov") + heat_template.add_floating_ip( + "floating_ip1", "network1", "port1", "router_if1") + heat_template.add_floating_ip( + "floating_ip2", "network2", "port2", "router_if2", "foo-secgroup") + heat_template.add_floating_ip_association( + "floating_ip1_association", "floating_ip1", "port1") heat_template.add_servergroup("server_grp2", "affinity") heat_template.add_servergroup("server_grp3", "anti-affinity") heat_template.add_security_group("security_group") - heat_template.add_server(name="server1", image="image1", flavor="flavor1", flavors=[]) - heat_template.add_server_group(name="servergroup", policies=["policy1","policy2"]) + heat_template.add_server( + name="server1", image="image1", flavor="flavor1", flavors=[]) + heat_template.add_server_group( + name="servergroup", policies=["policy1", "policy2"]) heat_template.add_server_group(name="servergroup", policies="policy1") - heat_template.add_server(name="server2", image="image1", flavor="flavor1", flavors=[], ports=["port1", "port2"], - networks=["network1", "network2"], scheduler_hints="hints1", user="user1", - key_name="foo-key", user_data="user", metadata={"cat": 1, "doc": 2}, - additional_properties={"prop1": 1, "prop2": 2}) - heat_template.add_server(name="server2", image="image1", flavor="flavor1", flavors=["flavor1", "flavor2"], - ports=["port1", "port2"], - networks=["network1", "network2"], scheduler_hints="hints1", user="user1", - key_name="foo-key", user_data="user", metadata={"cat": 1, "doc": 2}, - additional_properties={"prop1": 1, "prop2": 2} ) - heat_template.add_server(name="server2", image="image1", flavor="flavor1", flavors=["flavor3", "flavor4"], - ports=["port1", "port2"], - networks=["network1", "network2"], scheduler_hints="hints1", user="user1", - key_name="foo-key", user_data="user", metadata={"cat": 1, "doc": 2}, - additional_properties={"prop1": 1, "prop2": 2}) - heat_template.add_flavor(name="flavor1", vcpus=1, ram=2048, disk=1,extra_specs={"cat": 1, "dog": 2}) + heat_template.add_server( + name="server2", + image="image1", + flavor="flavor1", + flavors=[], + ports=[ + "port1", + "port2"], + networks=[ + "network1", + "network2"], + scheduler_hints="hints1", + user="user1", + key_name="foo-key", + user_data="user", + metadata={ + "cat": 1, + "doc": 2}, + additional_properties={ + "prop1": 1, + "prop2": 2}) + heat_template.add_server( + name="server2", + image="image1", + flavor="flavor1", + flavors=[ + "flavor1", + "flavor2"], + ports=[ + "port1", + "port2"], + networks=[ + "network1", + "network2"], + scheduler_hints="hints1", + user="user1", + key_name="foo-key", + user_data="user", + metadata={ + "cat": 1, + "doc": 2}, + additional_properties={ + "prop1": 1, + "prop2": 2}) + heat_template.add_server( + name="server2", + image="image1", + flavor="flavor1", + flavors=[ + "flavor3", + "flavor4"], + ports=[ + "port1", + "port2"], + networks=[ + "network1", + "network2"], + scheduler_hints="hints1", + user="user1", + key_name="foo-key", + user_data="user", + metadata={ + "cat": 1, + "doc": 2}, + additional_properties={ + "prop1": 1, + "prop2": 2}) + heat_template.add_flavor( + name="flavor1", + vcpus=1, + ram=2048, + disk=1, + extra_specs={ + "cat": 1, + "dog": 2}) heat_template.add_flavor(name=None, vcpus=1, ram=2048) - heat_template.add_server(name="server1", - image="image1", - flavor="flavor1", - flavors=[], - ports=["port1", "port2"], - networks=["network1", "network2"], - scheduler_hints="hints1", - user="user1", - key_name="foo-key", - user_data="user", - metadata={"cat": 1, "doc": 2}, - additional_properties= {"prop1": 1, "prop2": 2} ) + heat_template.add_server( + name="server1", + image="image1", + flavor="flavor1", + flavors=[], + ports=[ + "port1", + "port2"], + networks=[ + "network1", + "network2"], + scheduler_hints="hints1", + user="user1", + key_name="foo-key", + user_data="user", + metadata={ + "cat": 1, + "doc": 2}, + additional_properties={ + "prop1": 1, + "prop2": 2}) heat_template.add_network("network1") heat_template.add_flavor("test") - self.assertEqual(heat_template.resources['test']['type'], 'OS::Nova::Flavor') + self.assertEqual( + heat_template.resources['test']['type'], 'OS::Nova::Flavor') @mock_patch_target_module('op_utils') @mock_patch_target_module('heatclient') @@ -197,18 +311,25 @@ class HeatTemplateTestCase(unittest.TestCase): with mock.patch.object(self.template, 'status', return_value=None) as mock_status: # block with timeout hit timeout = 0 - with self.assertRaises(RuntimeError) as raised, timer() as time_data: + with self.assertRaises(RuntimeError) as raised, timer(): self.template.create(block=True, timeout=timeout) # ensure op_utils was used expected_op_utils_usage += 1 - self.assertEqual(mock_op_utils.get_session.call_count, expected_op_utils_usage) - self.assertEqual(mock_op_utils.get_endpoint.call_count, expected_op_utils_usage) - self.assertEqual(mock_op_utils.get_heat_api_version.call_count, expected_op_utils_usage) + self.assertEqual( + mock_op_utils.get_session.call_count, expected_op_utils_usage) + self.assertEqual( + mock_op_utils.get_endpoint.call_count, expected_op_utils_usage) + self.assertEqual( + mock_op_utils.get_heat_api_version.call_count, + expected_op_utils_usage) # ensure the constructor and instance were used - self.assertEqual(mock_heat_client_class.call_count, expected_constructor_calls) - self.assertEqual(mock_heat_client.stacks.create.call_count, expected_create_calls) + self.assertEqual(mock_heat_client_class.call_count, + expected_constructor_calls) + self.assertEqual( + mock_heat_client.stacks.create.call_count, + expected_create_calls) # ensure that the status was used self.assertGreater(mock_status.call_count, expected_status_calls) @@ -222,22 +343,33 @@ class HeatTemplateTestCase(unittest.TestCase): # block with create failed timeout = 10 mock_status.side_effect = iter([None, None, u'CREATE_FAILED']) - with self.assertRaises(RuntimeError) as raised, timer() as time_data: + with self.assertRaises(RuntimeError) as raised, timer(): self.template.create(block=True, timeout=timeout) - # ensure the existing heat_client was used and op_utils was used again - self.assertEqual(mock_op_utils.get_session.call_count, expected_op_utils_usage) - self.assertEqual(mock_op_utils.get_endpoint.call_count, expected_op_utils_usage) - self.assertEqual(mock_op_utils.get_heat_api_version.call_count, expected_op_utils_usage) + # ensure the existing heat_client was used and op_utils was used + # again + self.assertEqual( + mock_op_utils.get_session.call_count, expected_op_utils_usage) + self.assertEqual( + mock_op_utils.get_endpoint.call_count, expected_op_utils_usage) + self.assertEqual( + mock_op_utils.get_heat_api_version.call_count, + expected_op_utils_usage) # ensure the constructor was not used but the instance was used - self.assertEqual(mock_heat_client_class.call_count, expected_constructor_calls) - self.assertEqual(mock_heat_client.stacks.create.call_count, expected_create_calls) + self.assertEqual(mock_heat_client_class.call_count, + expected_constructor_calls) + self.assertEqual( + mock_heat_client.stacks.create.call_count, + expected_create_calls) # ensure that the status was used three times expected_status_calls += 3 self.assertEqual(mock_status.call_count, expected_status_calls) + # NOTE(elfoley): This needs to be split into multiple tests. + # The lines where the template is reset should serve as a guide for where + # to split. @mock_patch_target_module('op_utils') @mock_patch_target_module('heatclient') def test_create(self, mock_heat_client_class, mock_op_utils): @@ -250,7 +382,7 @@ class HeatTemplateTestCase(unittest.TestCase): {'output_key': 'key2', 'output_value': 'value2'}, {'output_key': 'key3', 'output_value': 'value3'}, ] - expected_outputs = { + expected_outputs = { # pylint: disable=unused-variable 'key1': 'value1', 'key2': 'value2', 'key3': 'value3', @@ -266,17 +398,25 @@ class HeatTemplateTestCase(unittest.TestCase): mock_status.return_value = None # no block - self.assertIsInstance(self.template.create(block=False, timeout=2), heat.HeatStack) + self.assertIsInstance(self.template.create( + block=False, timeout=2), heat.HeatStack) # ensure op_utils was used expected_op_utils_usage += 1 - self.assertEqual(mock_op_utils.get_session.call_count, expected_op_utils_usage) - self.assertEqual(mock_op_utils.get_endpoint.call_count, expected_op_utils_usage) - self.assertEqual(mock_op_utils.get_heat_api_version.call_count, expected_op_utils_usage) + self.assertEqual( + mock_op_utils.get_session.call_count, expected_op_utils_usage) + self.assertEqual( + mock_op_utils.get_endpoint.call_count, expected_op_utils_usage) + self.assertEqual( + mock_op_utils.get_heat_api_version.call_count, + expected_op_utils_usage) # ensure the constructor and instance were used - self.assertEqual(mock_heat_client_class.call_count, expected_constructor_calls) - self.assertEqual(mock_heat_client.stacks.create.call_count, expected_create_calls) + self.assertEqual(mock_heat_client_class.call_count, + expected_constructor_calls) + self.assertEqual( + mock_heat_client.stacks.create.call_count, + expected_create_calls) # ensure that the status was not used self.assertEqual(mock_status.call_count, expected_status_calls) @@ -288,11 +428,15 @@ class HeatTemplateTestCase(unittest.TestCase): self.template.name = 'block, immediate complete test' mock_status.return_value = self.template.HEAT_CREATE_COMPLETE_STATUS - self.assertIsInstance(self.template.create(block=True, timeout=2), heat.HeatStack) + self.assertIsInstance(self.template.create( + block=True, timeout=2), heat.HeatStack) # ensure existing instance was re-used and op_utils was not used - self.assertEqual(mock_heat_client_class.call_count, expected_constructor_calls) - self.assertEqual(mock_heat_client.stacks.create.call_count, expected_create_calls) + self.assertEqual(mock_heat_client_class.call_count, + expected_constructor_calls) + self.assertEqual( + mock_heat_client.stacks.create.call_count, + expected_create_calls) # ensure status was checked once expected_status_calls += 1 @@ -305,13 +449,17 @@ class HeatTemplateTestCase(unittest.TestCase): self.template.name = 'block, delayed complete test' success_index = 2 - mock_status.side_effect = index_value_iter(success_index, - self.template.HEAT_CREATE_COMPLETE_STATUS) - self.assertIsInstance(self.template.create(block=True, timeout=2), heat.HeatStack) + mock_status.side_effect = index_value_iter( + success_index, self.template.HEAT_CREATE_COMPLETE_STATUS) + self.assertIsInstance(self.template.create( + block=True, timeout=2), heat.HeatStack) # ensure existing instance was re-used and op_utils was not used - self.assertEqual(mock_heat_client_class.call_count, expected_constructor_calls) - self.assertEqual(mock_heat_client.stacks.create.call_count, expected_create_calls) + self.assertEqual(mock_heat_client_class.call_count, + expected_constructor_calls) + self.assertEqual( + mock_heat_client.stacks.create.call_count, + expected_create_calls) # ensure status was checked three more times expected_status_calls += 1 + success_index @@ -328,8 +476,7 @@ class HeatStackTestCase(unittest.TestCase): # call once and then call again if uuid is not none self.assertGreater(delete_mock.call_count, 1) - @mock.patch('yardstick.orchestrator.heat.op_utils') - def test_delete_all_calls_delete(self, mock_op): + def test_delete_all_calls_delete(self): # we must patch the object before we create an instance # so we can override delete() in all the instances with mock.patch.object(heat.HeatStack, "delete") as delete_mock: diff --git a/tests/unit/orchestrator/test_kubernetes.py b/yardstick/tests/unit/orchestrator/test_kubernetes.py index 1a3291c89..33fa1dca6 100644 --- a/tests/unit/orchestrator/test_kubernetes.py +++ b/yardstick/tests/unit/orchestrator/test_kubernetes.py @@ -64,7 +64,7 @@ service ssh restart;while true ; do sleep 10000; done" } ], "nodeSelector": { - "kubernetes.io/hostname": "node-01" + "kubernetes.io/hostname": "node-01" } } } @@ -75,7 +75,7 @@ service ssh restart;while true ; do sleep 10000; done" 'args': ['-c', 'chmod 700 ~/.ssh; chmod 600 ~/.ssh/*; \ service ssh restart;while true ; do sleep 10000; done'], 'ssh_key': 'k8s-86096c30-key', - 'nodeSelector': { 'kubernetes.io/hostname': 'node-01'} + 'nodeSelector': {'kubernetes.io/hostname': 'node-01'} } name = 'host-k8s-86096c30' output_r = KubernetesObject(name, **input_s).get_template() |