diff options
15 files changed, 181 insertions, 48 deletions
diff --git a/ansible/build_yardstick_image.yml b/ansible/build_yardstick_image.yml index c9b6e74e9..4ad6e97a9 100644 --- a/ansible/build_yardstick_image.yml +++ b/ansible/build_yardstick_image.yml @@ -59,7 +59,7 @@ - set_fact: raw_imgfile: "{{ workspace }}/{{ raw_imgfile_basename }}" - # cleanup non-lxd + # cleanup non-lxd - name: unmount all old mount points mount: name: "{{ item }}" @@ -74,6 +74,13 @@ command: kpartx -dv "{{ raw_imgfile }}" ignore_errors: true + - name: delete loop devices for image file + # use this because kpartx -dv will fail if raw_imgfile was delete + # but in theory we could have deleted file still attached to loopback device? + # use grep because of // and awk + shell: losetup -O NAME,BACK-FILE | grep "{{ raw_imgfile }}" | awk '{ print $1 }' | xargs -l1 losetup -d + ignore_errors: true + - name: delete {{ raw_imgfile }} file: path: "{{ raw_imgfile }}" @@ -114,8 +121,15 @@ with_sequence: start=0 end=9 tags: mknod_devices + - name: Debug dump loop devices + command: losetup + register: losetup_output + + - debug: + var: losetup_output + verbosity: 2 + - name: find first partition device -# command: kpartx -l "{{ loop_device }}" command: kpartx -l "{{ raw_imgfile }}" register: kpartx_res diff --git a/api/resources/v1/testsuites.py b/api/resources/v1/testsuites.py index 5f72c2ea6..3e14670b4 100644 --- a/api/resources/v1/testsuites.py +++ b/api/resources/v1/testsuites.py @@ -20,6 +20,7 @@ from yardstick.common.utils import result_handler from yardstick.benchmark.core import Param from yardstick.benchmark.core.task import Task from api.swagger import models +from api.database.v1.handlers import TasksHandler LOG = logging.getLogger(__name__) LOG.setLevel(logging.DEBUG) @@ -58,7 +59,7 @@ class V1Testsuite(ApiResource): task_args.update(args.get('opts', {})) param = Param(task_args) - task_thread = TaskThread(Task().start, param) + task_thread = TaskThread(Task().start, param, TasksHandler()) task_thread.start() return result_handler(consts.API_SUCCESS, {'task_id': task_id}) diff --git a/requirements.txt b/requirements.txt index 409bcd8c1..02545de1d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -55,7 +55,7 @@ python-keystoneclient==3.13.0 # OSI Approved Apache Software License python-neutronclient==6.5.0 # OSI Approved Apache Software License python-novaclient==9.1.1 # OSI Approved Apache Software License pyzmq==16.0.2 # LGPL+BSD; OSI Approved GNU Library or Lesser General Public License (LGPL); OSI Approved BSD License -requests==2.18.2 # Apache 2.0; OSI Approved Apache Software License +requests==2.11.1 # Apache 2.0; OSI Approved Apache Software License requestsexceptions==1.3.0 # OSI Approved Apache Software License scp==0.10.2 # LGPL shade==1.22.2 # OSI Approved Apache Software License diff --git a/tests/opnfv/test_suites/opnfv_k8-nosdn-stor4nfv-ha.yaml b/tests/opnfv/test_suites/opnfv_k8-nosdn-stor4nfv-ha_daily.yaml index cb2b1311d..cb2b1311d 100644 --- a/tests/opnfv/test_suites/opnfv_k8-nosdn-stor4nfv-ha.yaml +++ b/tests/opnfv/test_suites/opnfv_k8-nosdn-stor4nfv-ha_daily.yaml diff --git a/tests/opnfv/test_suites/opnfv_k8-nosdn-stor4nfv-noha.yaml b/tests/opnfv/test_suites/opnfv_k8-nosdn-stor4nfv-noha_daily.yaml index 961b8da89..961b8da89 100644 --- a/tests/opnfv/test_suites/opnfv_k8-nosdn-stor4nfv-noha.yaml +++ b/tests/opnfv/test_suites/opnfv_k8-nosdn-stor4nfv-noha_daily.yaml diff --git a/tests/opnfv/test_suites/opnfv_os-nosdn-nofeature-ha_daily.yaml b/tests/opnfv/test_suites/opnfv_os-nosdn-nofeature-ha_daily.yaml index fa3c7898b..7c213e2d9 100644 --- a/tests/opnfv/test_suites/opnfv_os-nosdn-nofeature-ha_daily.yaml +++ b/tests/opnfv/test_suites/opnfv_os-nosdn-nofeature-ha_daily.yaml @@ -93,12 +93,10 @@ test_cases: file_name: opnfv_yardstick_tc027.yaml constraint: installer: compass,fuel - pod: huawei-pod1,lf-pod2,ericsson-pod3,ericsson-pod4 + pod: huawei-pod1,lf-pod2 task_args: huawei-pod1: '{"file": "etc/yardstick/nodes/compass_sclab_physical/pod.yaml"}' lf-pod2: '{"file": "etc/yardstick/nodes/fuel_baremetal/pod.yaml", "openrc":"/root/openrc", "external_network":"admin_floating_net"}' - ericsson-pod3: '{"file": "etc/yardstick/nodes/fuel_baremetal/pod.yaml", "openrc":"/root/openrc", "external_network":"admin_floating_net"}' - ericsson-pod4: '{"file": "etc/yardstick/nodes/fuel_baremetal/pod.yaml", "openrc":"/root/openrc", "external_network":"admin_floating_net"}' - file_name: opnfv_yardstick_tc074.yaml constraint: @@ -115,72 +113,82 @@ test_cases: file_name: opnfv_yardstick_tc045.yaml constraint: installer: compass,fuel - pod: huawei-pod2,ericsson-pod1 + pod: huawei-pod1,lf-pod2 task_args: - huawei-pod2: '{"file": "etc/yardstick/nodes/compass_sclab_physical/pod.yaml"}' - ericsson-pod1: '{"file": "etc/yardstick/nodes/fuel_baremetal/pod.yaml"}' + huawei-pod1: '{"file": "etc/yardstick/nodes/compass_sclab_physical/pod.yaml"}' + lf-pod2: '{"file": "etc/yardstick/nodes/fuel_baremetal/pod.yaml"}' - file_name: opnfv_yardstick_tc046.yaml constraint: - installer: fuel + installer: compass,fuel + pod: huawei-pod1,lf-pod2 task_args: - default: '{"file": "etc/yardstick/nodes/fuel_baremetal/pod.yaml"}' + huawei-pod1: '{"file": "etc/yardstick/nodes/compass_sclab_physical/pod.yaml"}' + lf-pod2: '{"file": "etc/yardstick/nodes/fuel_baremetal/pod.yaml"}' - file_name: opnfv_yardstick_tc047.yaml constraint: installer: compass,fuel - pod: huawei-pod2,ericsson-pod1 + pod: huawei-pod1,lf-pod2 task_args: - huawei-pod2: '{"file": "etc/yardstick/nodes/compass_sclab_physical/pod.yaml"}' - ericsson-pod1: '{"file": "etc/yardstick/nodes/fuel_baremetal/pod.yaml"}' + huawei-pod1: '{"file": "etc/yardstick/nodes/compass_sclab_physical/pod.yaml"}' + lf-pod2: '{"file": "etc/yardstick/nodes/fuel_baremetal/pod.yaml"}' - file_name: opnfv_yardstick_tc048.yaml constraint: installer: compass,fuel - pod: huawei-pod2,ericsson-pod1 + pod: huawei-pod1,lf-pod2 task_args: - huawei-pod2: '{"file": "etc/yardstick/nodes/compass_sclab_physical/pod.yaml"}' - ericsson-pod1: '{"file": "etc/yardstick/nodes/fuel_baremetal/pod.yaml"}' + huawei-pod1: '{"file": "etc/yardstick/nodes/compass_sclab_physical/pod.yaml"}' + lf-pod2: '{"file": "etc/yardstick/nodes/fuel_baremetal/pod.yaml"}' - file_name: opnfv_yardstick_tc049.yaml constraint: - installer: fuel + installer: compass,fuel + pod: huawei-pod1,lf-pod2 task_args: - default: '{"file": "etc/yardstick/nodes/fuel_baremetal/pod.yaml"}' + huawei-pod1: '{"file": "etc/yardstick/nodes/compass_sclab_physical/pod.yaml"}' + lf-pod2: '{"file": "etc/yardstick/nodes/fuel_baremetal/pod.yaml"}' - file_name: opnfv_yardstick_tc050.yaml constraint: - installer: fuel + installer: compass,fuel + pod: huawei-pod1,lf-pod2 task_args: - default: '{"file": "etc/yardstick/nodes/fuel_baremetal/pod.yaml"}' + huawei-pod1: '{"file": "etc/yardstick/nodes/compass_sclab_physical/pod.yaml"}' + lf-pod2: '{"file": "etc/yardstick/nodes/fuel_baremetal/pod.yaml"}' - file_name: opnfv_yardstick_tc051.yaml constraint: installer: compass,fuel - pod: huawei-pod2,ericsson-pod1 + pod: huawei-pod1,lf-pod2 task_args: - huawei-pod2: '{"file": "etc/yardstick/nodes/compass_sclab_physical/pod.yaml"}' - ericsson-pod1: '{"file": "etc/yardstick/nodes/fuel_baremetal/pod.yaml"}' + huawei-pod1: '{"file": "etc/yardstick/nodes/compass_sclab_physical/pod.yaml"}' + lf-pod2: '{"file": "etc/yardstick/nodes/fuel_baremetal/pod.yaml"}' - file_name: opnfv_yardstick_tc052.yaml constraint: - installer: fuel + installer: compass,fuel + pod: huawei-pod1,lf-pod2 task_args: - default: '{"file": "etc/yardstick/nodes/fuel_baremetal/pod.yaml"}' + huawei-pod1: '{"file": "etc/yardstick/nodes/compass_sclab_physical/pod.yaml"}' + lf-pod2: '{"file": "etc/yardstick/nodes/fuel_baremetal/pod.yaml"}' - file_name: opnfv_yardstick_tc053.yaml constraint: - installer: fuel + installer: compass,fuel + pod: huawei-pod1,lf-pod2 task_args: - default: '{"file": "etc/yardstick/nodes/fuel_baremetal/pod.yaml"}' + huawei-pod1: '{"file": "etc/yardstick/nodes/compass_sclab_physical/pod.yaml"}' + lf-pod2: '{"file": "etc/yardstick/nodes/fuel_baremetal/pod.yaml"}' - file_name: opnfv_yardstick_tc019.yaml constraint: installer: compass,fuel - pod: huawei-pod2,ericsson-pod1 + pod: huawei-pod1,lf-pod2 task_args: - huawei-pod2: '{"file": "etc/yardstick/nodes/compass_sclab_physical/pod.yaml"}' - ericsson-pod1: '{"file": "etc/yardstick/nodes/fuel_baremetal/pod.yaml"}' + huawei-pod1: '{"file": "etc/yardstick/nodes/compass_sclab_physical/pod.yaml"}' + lf-pod2: '{"file": "etc/yardstick/nodes/fuel_baremetal/pod.yaml"}' - file_name: opnfv_yardstick_tc025.yaml constraint: diff --git a/tests/unit/network_services/vnf_generic/vnf/test_sample_vnf.py b/tests/unit/network_services/vnf_generic/vnf/test_sample_vnf.py index c7d2abcd5..26bd1dadd 100644 --- a/tests/unit/network_services/vnf_generic/vnf/test_sample_vnf.py +++ b/tests/unit/network_services/vnf_generic/vnf/test_sample_vnf.py @@ -533,10 +533,12 @@ class TestDpdkVnfSetupEnvHelper(unittest.TestCase): @mock.patch.object(six, 'BytesIO', return_value=six.BytesIO(b'100\n')) @mock.patch.object(utils, 'read_meminfo', return_value={'Hugepagesize': '2048'}) - def test__setup_hugepages(self, mock_meminfo, *args): + def test__setup_hugepages_no_hugepages_defined(self, mock_meminfo, *args): ssh_helper = mock.Mock() + scenario_helper = mock.Mock() + scenario_helper.all_options = {} dpdk_setup_helper = DpdkVnfSetupEnvHelper( - mock.ANY, ssh_helper, mock.ANY) + mock.ANY, ssh_helper, scenario_helper) with mock.patch.object(sample_vnf.LOG, 'info') as mock_info: dpdk_setup_helper._setup_hugepages() mock_info.assert_called_once_with( @@ -544,6 +546,22 @@ class TestDpdkVnfSetupEnvHelper(unittest.TestCase): '%s', 2048, 8192, 100) mock_meminfo.assert_called_once_with(ssh_helper) + @mock.patch.object(six, 'BytesIO', return_value=six.BytesIO(b'100\n')) + @mock.patch.object(utils, 'read_meminfo', + return_value={'Hugepagesize': '1048576'}) + def test__setup_hugepages_8gb_hugepages_defined(self, mock_meminfo, *args): + ssh_helper = mock.Mock() + scenario_helper = mock.Mock() + scenario_helper.all_options = {'hugepages_gb': 8} + dpdk_setup_helper = DpdkVnfSetupEnvHelper( + mock.ANY, ssh_helper, scenario_helper) + with mock.patch.object(sample_vnf.LOG, 'info') as mock_info: + dpdk_setup_helper._setup_hugepages() + mock_info.assert_called_once_with( + 'Hugepages size (kB): %s, number claimed: %s, number set: ' + '%s', 1048576, 8, 100) + mock_meminfo.assert_called_once_with(ssh_helper) + @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.open') @mock.patch.object(utils, 'find_relative_file') @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.MultiPortConfig') diff --git a/yardstick/benchmark/runners/duration.py b/yardstick/benchmark/runners/duration.py index fbf72a74c..60b0348c3 100644 --- a/yardstick/benchmark/runners/duration.py +++ b/yardstick/benchmark/runners/duration.py @@ -66,6 +66,8 @@ def _worker_process(queue, cls, method_name, scenario_cfg, data = {} errors = "" + benchmark.pre_run_wait_time(interval) + try: result = method(data) except AssertionError as assertion: @@ -77,7 +79,7 @@ def _worker_process(queue, cls, method_name, scenario_cfg, errors = assertion.args # catch all exceptions because with multiprocessing we can have un-picklable exception # problems https://bugs.python.org/issue9400 - except Exception: + except Exception: # pylint: disable=broad-except errors = traceback.format_exc() LOG.exception("") else: @@ -86,7 +88,7 @@ def _worker_process(queue, cls, method_name, scenario_cfg, # if we do timeout we don't care about dropping individual KPIs output_queue.put(result, True, QUEUE_PUT_TIMEOUT) - time.sleep(interval) + benchmark.post_run_wait_time(interval) benchmark_output = { 'timestamp': time.time(), diff --git a/yardstick/benchmark/runners/iteration.py b/yardstick/benchmark/runners/iteration.py index cb0424377..20d6da054 100644 --- a/yardstick/benchmark/runners/iteration.py +++ b/yardstick/benchmark/runners/iteration.py @@ -71,6 +71,8 @@ def _worker_process(queue, cls, method_name, scenario_cfg, data = {} errors = "" + benchmark.pre_run_wait_time(interval) + try: result = method(data) except AssertionError as assertion: @@ -90,7 +92,7 @@ def _worker_process(queue, cls, method_name, scenario_cfg, scenario_cfg['options']['rate'] -= delta sequence = 1 continue - except Exception: + except Exception: # pylint: disable=broad-except errors = traceback.format_exc() LOG.exception("") else: @@ -99,7 +101,7 @@ def _worker_process(queue, cls, method_name, scenario_cfg, # if we do timeout we don't care about dropping individual KPIs output_queue.put(result, True, QUEUE_PUT_TIMEOUT) - time.sleep(interval) + benchmark.post_run_wait_time(interval) benchmark_output = { 'timestamp': time.time(), diff --git a/yardstick/benchmark/scenarios/base.py b/yardstick/benchmark/scenarios/base.py index 10a728828..58a02805c 100644 --- a/yardstick/benchmark/scenarios/base.py +++ b/yardstick/benchmark/scenarios/base.py @@ -13,9 +13,10 @@ # License for the specific language governing permissions and limitations # under the License. -# yardstick comment: this is a modified copy of -# rally/rally/benchmark/scenarios/base.py +import abc +import time +import six from stevedore import extension import yardstick.common.utils as utils @@ -37,20 +38,29 @@ def _iter_scenario_classes(scenario_type=None): yield scenario +@six.add_metaclass(abc.ABCMeta) class Scenario(object): def setup(self): - """ default impl for scenario setup """ + """Default setup implementation for Scenario classes""" pass + @abc.abstractmethod def run(self, *args): - """ catcher for not implemented run methods in subclasses """ - raise RuntimeError("run method not implemented") + """Entry point for scenario classes, called from runner worker""" def teardown(self): - """ default impl for scenario teardown """ + """Default teardown implementation for Scenario classes""" pass + def pre_run_wait_time(self, time_seconds): + """Time waited before executing the run method""" + pass + + def post_run_wait_time(self, time_seconds): + """Time waited after executing the run method""" + time.sleep(time_seconds) + @staticmethod def get_types(): """return a list of known runner type (class) names""" @@ -88,10 +98,14 @@ class Scenario(object): """ return cls.__doc__.splitlines()[0] if cls.__doc__ else str(None) - def _push_to_outputs(self, keys, values): + @staticmethod + def _push_to_outputs(keys, values): + """Return a dictionary given the keys and the values""" return dict(zip(keys, values)) - def _change_obj_to_dict(self, obj): + @staticmethod + def _change_obj_to_dict(obj): + """Return a dictionary from the __dict__ attribute of an object""" dic = {} for k, v in vars(obj).items(): try: diff --git a/yardstick/benchmark/scenarios/networking/vnf_generic.py b/yardstick/benchmark/scenarios/networking/vnf_generic.py index 0e4785294..be2fa3f3b 100644 --- a/yardstick/benchmark/scenarios/networking/vnf_generic.py +++ b/yardstick/benchmark/scenarios/networking/vnf_generic.py @@ -14,6 +14,7 @@ import copy import logging +import time import ipaddress from itertools import chain @@ -484,3 +485,11 @@ class NetworkServiceTestCase(scenario_base.Scenario): # https://bugs.python.org/issue9400 LOG.exception("") raise RuntimeError("Error in teardown") + + def pre_run_wait_time(self, time_seconds): + """Time waited before executing the run method""" + time.sleep(time_seconds) + + def post_run_wait_time(self, time_seconds): + """Time waited after executing the run method""" + pass diff --git a/yardstick/network_services/vnf_generic/vnf/sample_vnf.py b/yardstick/network_services/vnf_generic/vnf/sample_vnf.py index addbd9aa4..77488c479 100644 --- a/yardstick/network_services/vnf_generic/vnf/sample_vnf.py +++ b/yardstick/network_services/vnf_generic/vnf/sample_vnf.py @@ -79,7 +79,6 @@ class DpdkVnfSetupEnvHelper(SetupEnvHelper): APP_NAME = 'DpdkVnf' FIND_NET_CMD = "find /sys/class/net -lname '*{}*' -printf '%f'" NR_HUGEPAGES_PATH = '/proc/sys/vm/nr_hugepages' - HUGEPAGES_KB = 1024 * 1024 * 16 @staticmethod def _update_packet_type(ip_pipeline_cfg, traffic_options): @@ -118,7 +117,8 @@ class DpdkVnfSetupEnvHelper(SetupEnvHelper): def _setup_hugepages(self): meminfo = utils.read_meminfo(self.ssh_helper) hp_size_kb = int(meminfo['Hugepagesize']) - nr_hugepages = int(abs(self.HUGEPAGES_KB / hp_size_kb)) + hugepages_gb = self.scenario_helper.all_options.get('hugepages_gb', 16) + nr_hugepages = int(abs(hugepages_gb * 1024 * 1024 / hp_size_kb)) self.ssh_helper.execute('echo %s | sudo tee %s' % (nr_hugepages, self.NR_HUGEPAGES_PATH)) hp = six.BytesIO() diff --git a/yardstick/tests/unit/apiserver/resources/v1/__init__.py b/yardstick/tests/unit/apiserver/resources/v1/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/yardstick/tests/unit/apiserver/resources/v1/__init__.py diff --git a/yardstick/tests/unit/apiserver/resources/v1/test_testsuites.py b/yardstick/tests/unit/apiserver/resources/v1/test_testsuites.py new file mode 100644 index 000000000..85c045f44 --- /dev/null +++ b/yardstick/tests/unit/apiserver/resources/v1/test_testsuites.py @@ -0,0 +1,35 @@ +############################################################################## +# Copyright (c) 2018 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 mock + +import unittest + +from yardstick.tests.unit.apiserver import APITestCase +from api.utils.thread import TaskThread + + +class TestsuiteTestCase(APITestCase): + + def test_run_test_suite(self): + if self.app is None: + unittest.skip('host config error') + return + + TaskThread.start = mock.MagicMock() + + url = 'yardstick/testsuites/action' + data = { + 'action': 'run_test_suite', + 'args': { + 'opts': {}, + 'testsuite': 'opnfv_smoke' + } + } + resp = self._post(url, data) + self.assertEqual(resp.get('status'), 1) diff --git a/yardstick/tests/unit/benchmark/scenarios/test_base.py b/yardstick/tests/unit/benchmark/scenarios/test_base.py index 985338532..284a71cc8 100644 --- a/yardstick/tests/unit/benchmark/scenarios/test_base.py +++ b/yardstick/tests/unit/benchmark/scenarios/test_base.py @@ -13,10 +13,21 @@ # License for the specific language governing permissions and limitations # under the License. +import time + +import mock + from yardstick.benchmark.scenarios import base from yardstick.tests.unit import base as ut_base +class _TestScenario(base.Scenario): + __scenario_type__ = 'Test Scenario' + + def run(self): + pass + + class ScenarioTestCase(ut_base.BaseUnitTestCase): def test_get_scenario_type(self): @@ -85,6 +96,25 @@ class ScenarioTestCase(ut_base.BaseUnitTestCase): self.assertEqual('No such scenario type %s' % wrong_scenario_name, str(exc.exception)) + def test_scenario_abstract_class(self): + # pylint: disable=abstract-class-instantiated + with self.assertRaises(TypeError): + base.Scenario() + + @mock.patch.object(time, 'sleep') + def test_pre_run_wait_time(self, mock_sleep): + """Ensure default behaviour (backwards compatibility): no wait time""" + test_scenario = _TestScenario() + test_scenario.pre_run_wait_time(mock.ANY) + mock_sleep.assert_not_called() + + @mock.patch.object(time, 'sleep') + def test_post_run_wait_time(self, mock_sleep): + """Ensure default behaviour (backwards compatibility): wait time""" + test_scenario = _TestScenario() + test_scenario.post_run_wait_time(100) + mock_sleep.assert_called_once_with(100) + class IterScenarioClassesTestCase(ut_base.BaseUnitTestCase): |