From 485ac777fd9cded7c145917bfcbe701276f3c855 Mon Sep 17 00:00:00 2001 From: "Sridhar K. N. Rao" Date: Thu, 5 Oct 2017 09:29:35 +0530 Subject: load_gen: Supporting loading of load_gen via loader. Currently all tools are loaded via loader utility, except load_gen. Load_gens were loaded directly through component_factory. This patch adds support to load load_gens through loader utility. The changes are as follows: 1. Configuration changes:The common.conf include configuration of directory. testcases.conf includes changes to load configuration, where tool is no more part of the load-configuration. The custom.conf has configuration of LOADGEN to be used - this configuration replaces the earlier 'tool' configuration parameter. 2. loader_utility_changes: In loader.py, loadgen_loader is defined, which is used in new get_loadgen function. 3. component_factory changes: in create_loadgen, similar to other tools, the function just retuns the object of loadgen_class. 4. Renaming of Dummy load_gen: Loader fails to load properly a dummy loadgen due to name-clash with dummy in pkt_gen. To avoid this name clash dummy is renamed to dummyloadgen. 5. testcase changes: create_loadgen is now called with output of loader's get_loadgen_class. 6. Fixed Pylint Errors and extra-space at the end. 7. Included CLI options support for --loadgen and --list-loadgens. Thanks to Martin K. 8. Added the missing loadgen parameter in testcases.conf. 9. Fixed the missing comma error. 10. Added CI change in build-vsperf.sh 11. Fixed configuration reading in stress/stress.py JIRA: VSPERF-533 Change-Id: I3fbb259618825a12fef55320a748a4f02509190b Signed-off-by: Sridhar K. N. Rao Signed-off-by: Martin Klozik --- ci/build-vsperf.sh | 2 +- conf/01_testcases.conf | 9 +++++--- conf/07_loadgen.conf | 21 +++++++++++++++++++ core/component_factory.py | 22 ++++++-------------- core/loader/loader.py | 32 +++++++++++++++++++++++++++++ testcases/testcase.py | 7 +------ tools/load_gen/dummy/__init__.py | 16 --------------- tools/load_gen/dummy/dummy.py | 32 ----------------------------- tools/load_gen/dummyloadgen/__init__.py | 16 +++++++++++++++ tools/load_gen/dummyloadgen/dummyloadgen.py | 32 +++++++++++++++++++++++++++++ tools/load_gen/stress/stress.py | 6 ++++-- vsperf | 15 ++++++++++++++ 12 files changed, 134 insertions(+), 76 deletions(-) create mode 100644 conf/07_loadgen.conf delete mode 100644 tools/load_gen/dummy/__init__.py delete mode 100644 tools/load_gen/dummy/dummy.py create mode 100644 tools/load_gen/dummyloadgen/__init__.py create mode 100644 tools/load_gen/dummyloadgen/dummyloadgen.py diff --git a/ci/build-vsperf.sh b/ci/build-vsperf.sh index b60a7fa7..a8a42cee 100755 --- a/ci/build-vsperf.sh +++ b/ci/build-vsperf.sh @@ -369,7 +369,7 @@ function execute_vsperf_sanity() { DATE_SUFFIX=$(date -u +"%Y-%m-%d_%H-%M-%S") LOG_FILE="${LOG_FILE_PREFIX}_sanity_${DATE_SUFFIX}.log" echo "Execution of VSPERF sanity checks:" - for PARAM in '--version' '--help' '--list-trafficgens' '--list-collectors' '--list-vswitches' '--list-fwdapps' '--list-vnfs' '--list-settings' '--list' '--integration --list'; do + for PARAM in '--version' '--help' '--list-trafficgens' '--list-collectors' '--list-vswitches' '--list-fwdapps' '--list-vnfs' '--list-loadgens' '--list-settings' '--list' '--integration --list'; do echo -e "-------------------------------------------------------------------" >> $LOG_FILE echo "$VSPERF_BIN $PARAM $CONF_FILE" >> $LOG_FILE echo -e "-------------------------------------------------------------------" >> $LOG_FILE diff --git a/conf/01_testcases.conf b/conf/01_testcases.conf index df582df9..bd5ba9eb 100755 --- a/conf/01_testcases.conf +++ b/conf/01_testcases.conf @@ -27,9 +27,12 @@ # # ip_port. # "Load": dictionary # Optional. Configures background load # # during testcase execution. +# # The tool used to generate load is +# # defined by LOADGEN configuration. +# # Default setting of Dummy can be found in +# # 07_loadgen.conf. # Description of "Load" dictionary keys, their meanings and available values: # -# "tool": "stress" # One of the supported load generators. # "load": 0-100 # percentage of cores which should be # # utilized by load generator # # e.g. load = 70%, detected cpu cores = 14 => @@ -331,12 +334,12 @@ PERFORMANCE_TESTS = [ "Deployment": "p2p", "Description": "LTD.CPU.RFC2544.0PacketLoss", "Load" : { - "tool" : "stress-ng", "load" : 100, "reserved" : 4, "pattern" : "c", }, "Parameters" : { + "LOADGEN" : "StressNg", "TRAFFIC" : { "traffic_type" : "rfc2544_throughput", }, @@ -347,12 +350,12 @@ PERFORMANCE_TESTS = [ "Deployment": "p2p", "Description": "LTD.Memory.RFC2544.0PacketLoss", "Load" : { - "tool" : "stress-ng", "load" : 50, "pattern" : "m", "load_memory" : 80, }, "Parameters" : { + "LOADGEN" : "StressNg", "TRAFFIC" : { "traffic_type" : "rfc2544_throughput", }, diff --git a/conf/07_loadgen.conf b/conf/07_loadgen.conf new file mode 100644 index 00000000..e7349a5d --- /dev/null +++ b/conf/07_loadgen.conf @@ -0,0 +1,21 @@ +# Copyright 2015 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. + +LOADGEN_DIR = os.path.join(ROOT_DIR, 'tools/load_gen') + +###################################################### +# LOADGEN tool: one of DummyLoadGen, Stress, StressNg +###################################################### +LOADGEN = "DummyLoadGen" +###################################################### diff --git a/core/component_factory.py b/core/component_factory.py index 0256b85c..bd9a1019 100644 --- a/core/component_factory.py +++ b/core/component_factory.py @@ -24,9 +24,6 @@ from core.vswitch_controller_op2p import VswitchControllerOP2P from core.vswitch_controller_ptunp import VswitchControllerPtunP from core.vnf_controller import VnfController from core.pktfwd_controller import PktFwdController -from tools.load_gen.stress.stress import Stress -from tools.load_gen.stress_ng.stress_ng import StressNg -from tools.load_gen.dummy.dummy import DummyLoadGen def __init__(): @@ -115,24 +112,17 @@ def create_collector(collector_class, result_dir, test_name): """ return collector_class(result_dir, test_name) -def create_loadgen(loadgen_type, loadgen_cfg): - """Return a new ILoadGenerator for the loadgen type. +def create_loadgen(loadgen_class, loadgen_cfg): + """Return a new ILoadGenerator for the loadgen class. - The returned load generator has the given loadgen type and loadgen - generator class. + The returned load generator is of given loadgen generator class. - :param loadgen_type: Name of loadgen type - :param loadgen_class: Reference to load generator class to be used. + :param loadgen_class: Name to load generator class to be used. + :param loadgen_cfg: Configuration for the loadgen :return: A new ILoadGenerator class """ # pylint: disable=too-many-function-args - loadgen_type = loadgen_type.lower() - if loadgen_type.find("dummy") >= 0: - return DummyLoadGen(loadgen_cfg) - elif loadgen_type.find("stress-ng") >= 0: - return StressNg(loadgen_cfg) - elif loadgen_type.find("stress") >= 0: - return Stress(loadgen_cfg) + return loadgen_class(loadgen_cfg) def create_pktfwd(deployment, pktfwd_class): """Return a new packet forwarder controller diff --git a/core/loader/loader.py b/core/loader/loader.py index b0990fa7..dcd77ced 100755 --- a/core/loader/loader.py +++ b/core/loader/loader.py @@ -18,11 +18,13 @@ from conf import settings from core.loader.loader_servant import LoaderServant from tools.collectors.collector import ICollector +from tools.load_gen.load_gen import ILoadGenerator from tools.pkt_fwd.pkt_fwd import IPktFwd from tools.pkt_gen.trafficgen import ITrafficGenerator from vswitches.vswitch import IVSwitch from vnfs.vnf.vnf import IVnf +# pylint: disable=too-many-public-methods class Loader(object): """Loader class - main object context holder. """ @@ -30,6 +32,7 @@ class Loader(object): _metrics_loader = None _vswitch_loader = None _vnf_loader = None + _loadgen_loader = None def __init__(self): """Loader ctor - initialization method. @@ -48,6 +51,11 @@ class Loader(object): settings.getValue('COLLECTOR'), ICollector) + self._loadgen_loader = LoaderServant( + settings.getValue('LOADGEN_DIR'), + settings.getValue('LOADGEN'), + ILoadGenerator) + self._vswitch_loader = LoaderServant( settings.getValue('VSWITCH_DIR'), settings.getValue('VSWITCH'), @@ -126,6 +134,30 @@ class Loader(object): """ return self._metrics_loader.get_classes_printable() + def get_loadgen_class(self): + """Returns type of currently configured loadgen implementation. + + :return: Type of ILoadGenerator implementation if available. + None otherwise. + """ + return self._loadgen_loader.get_class() + + def get_loadgens(self): + """Returns dictionary of all available loadgens + + :return: Dictionary of loadgens + - key: name of the class which implements ILoadGenerator + - value: Type of class which implements ILoadGenerator + """ + return self._loadgen_loader.get_classes() + + def get_loadgens_printable(self): + """Returns all available loadgens in printable format + + :return: String containing printable list of loadgens + """ + return self._loadgen_loader.get_classes_printable() + def get_vswitch(self): """Returns instance of currently configured vswitch implementation. diff --git a/testcases/testcase.py b/testcases/testcase.py index 01b3a975..3d9ffe4b 100644 --- a/testcases/testcase.py +++ b/testcases/testcase.py @@ -131,11 +131,6 @@ class TestCase(object): # check if test requires background load and which generator it uses self._load_cfg = cfg.get('Load', None) - if self._load_cfg and 'tool' in self._load_cfg: - self._loadgen = self._load_cfg['tool'] - else: - # background load is not requested, so use dummy implementation - self._loadgen = "Dummy" if self._frame_mod: self._frame_mod = self._frame_mod.lower() @@ -247,7 +242,7 @@ class TestCase(object): loader.get_collector_class(), self._results_dir, self.name) self._loadgen = component_factory.create_loadgen( - self._loadgen, + loader.get_loadgen_class(), self._load_cfg) self._output_file = os.path.join(self._results_dir, "result_" + self.name + diff --git a/tools/load_gen/dummy/__init__.py b/tools/load_gen/dummy/__init__.py deleted file mode 100644 index 834e9f63..00000000 --- a/tools/load_gen/dummy/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright 2015 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. - -"""Package with wrapper of dummy load generator -""" diff --git a/tools/load_gen/dummy/dummy.py b/tools/load_gen/dummy/dummy.py deleted file mode 100644 index 91bef4fa..00000000 --- a/tools/load_gen/dummy/dummy.py +++ /dev/null @@ -1,32 +0,0 @@ -# Copyright 2015-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. - -"""Class with implementation of wrapper of dummy load generator""" - -from tools.load_gen.load_gen import ILoadGenerator - -# pylint: disable=super-init-not-called -class DummyLoadGen(ILoadGenerator): - """Dummy load generator, which doesn't generate any load""" - def __init__(self, stress_config): - """Initialise process state.""" - pass - - def start(self): - """Start stress load if it was requested""" - pass - - def kill(self, dummy_signal='-15', dummy_sleep=2): - """Kill stress load if it is active""" - pass diff --git a/tools/load_gen/dummyloadgen/__init__.py b/tools/load_gen/dummyloadgen/__init__.py new file mode 100644 index 00000000..834e9f63 --- /dev/null +++ b/tools/load_gen/dummyloadgen/__init__.py @@ -0,0 +1,16 @@ +# Copyright 2015 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. + +"""Package with wrapper of dummy load generator +""" diff --git a/tools/load_gen/dummyloadgen/dummyloadgen.py b/tools/load_gen/dummyloadgen/dummyloadgen.py new file mode 100644 index 00000000..91bef4fa --- /dev/null +++ b/tools/load_gen/dummyloadgen/dummyloadgen.py @@ -0,0 +1,32 @@ +# Copyright 2015-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. + +"""Class with implementation of wrapper of dummy load generator""" + +from tools.load_gen.load_gen import ILoadGenerator + +# pylint: disable=super-init-not-called +class DummyLoadGen(ILoadGenerator): + """Dummy load generator, which doesn't generate any load""" + def __init__(self, stress_config): + """Initialise process state.""" + pass + + def start(self): + """Start stress load if it was requested""" + pass + + def kill(self, dummy_signal='-15', dummy_sleep=2): + """Kill stress load if it is active""" + pass diff --git a/tools/load_gen/stress/stress.py b/tools/load_gen/stress/stress.py index 4c69a170..0790d47c 100644 --- a/tools/load_gen/stress/stress.py +++ b/tools/load_gen/stress/stress.py @@ -52,8 +52,10 @@ class Stress(ILoadGenerator): return # check if load tool binary is available - if not ('tool' in stress_config) or subprocess.call("which " + stress_config['tool'], shell=True) > 0: - self._logger.error("stress tool binary '%s' is not available", stress_config['tool']) + if subprocess.call("which {}".format(self._process_args['name']), + shell=True) > 0: + self._logger.error("stress tool binary '%s' is not available", + self._process_args['name']) return # calculate requested load details and load split among different diff --git a/vsperf b/vsperf index 6efe53da..46b6b416 100755 --- a/vsperf +++ b/vsperf @@ -147,6 +147,8 @@ def parse_arguments(): help='list all system forwarding applications and exit') parser.add_argument('--list-vnfs', action='store_true', help='list all system vnfs and exit') + parser.add_argument('--list-loadgens', action='store_true', + help='list all background load generators') parser.add_argument('--list-settings', action='store_true', help='list effective settings configuration and exit') parser.add_argument('exact_test_name', nargs='*', help='Exact names of\ @@ -174,6 +176,7 @@ def parse_arguments(): group.add_argument('--vswitch', help='vswitch implementation to use') group.add_argument('--fwdapp', help='packet forwarding application to use') group.add_argument('--vnf', help='vnf to use') + group.add_argument('--loadgen', help='loadgen to use') group.add_argument('--sysmetrics', help='system metrics logger to use') group = parser.add_argument_group('test behavior options') group.add_argument('--xunit', action='store_true', @@ -439,6 +442,10 @@ def handle_list_options(args): print(Loader().get_pktfwds_printable()) sys.exit(0) + if args['list_loadgens']: + print(Loader().get_loadgens_printable()) + sys.exit(0) + if args['list_settings']: print(str(settings)) sys.exit(0) @@ -591,6 +598,14 @@ def main(): settings.getValue('VNF_DIR')) sys.exit(1) + if args['loadgen']: + loadgens = Loader().get_loadgens() + if args['loadgen'] not in loadgens: + _LOGGER.error('There are no loadgens matching \'%s\' found in' + ' \'%s\'. Exiting...', args['loadgen'], + settings.getValue('LOADGEN_DIR')) + sys.exit(1) + if args['exact_test_name'] and args['tests']: _LOGGER.error("Cannot specify tests with both positional args and --test.") sys.exit(1) -- cgit 1.2.3-korg