Merge "teststeps: Improvements and bugfixing of teststeps"
authorMartin Klozik <martinx.klozik@intel.com>
Wed, 15 Nov 2017 08:24:29 +0000 (08:24 +0000)
committerGerrit Code Review <gerrit@opnfv.org>
Wed, 15 Nov 2017 08:24:29 +0000 (08:24 +0000)
12 files changed:
ci/build-vsperf.sh
conf/01_testcases.conf
conf/02_vswitch.conf
conf/07_loadgen.conf [new file with mode: 0644]
core/component_factory.py
core/loader/loader.py
testcases/testcase.py
tools/load_gen/dummyloadgen/__init__.py [moved from tools/load_gen/dummy/__init__.py with 100% similarity]
tools/load_gen/dummyloadgen/dummyloadgen.py [moved from tools/load_gen/dummy/dummy.py with 100% similarity]
tools/load_gen/stress/stress.py
vsperf
vswitches/vpp_dpdk_vhost.py

index b60a7fa..a8a42ce 100755 (executable)
@@ -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
index df582df..bd5ba9e 100755 (executable)
 #                                  # 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",
             },
index 92521f9..6a830a0 100644 (file)
@@ -206,6 +206,7 @@ VSWITCH_JUMBO_FRAMES_SIZE = 9000
 #########################
 # Set of arguments used for startup of VPP
 # NOTE: DPDK socket mem allocation is driven by parameter DPDK_SOCKET_MEM
+VSWITCH_VPP_CLI_SOCK = ''
 VSWITCH_VPP_ARGS = {
     'unix' : [
         'interactive',      # required by VSPERF to detect successful VPP startup
diff --git a/conf/07_loadgen.conf b/conf/07_loadgen.conf
new file mode 100644 (file)
index 0000000..e7349a5
--- /dev/null
@@ -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"
+######################################################
index 0256b85..bd9a101 100644 (file)
@@ -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
index b0990fa..dcd77ce 100755 (executable)
 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.
 
index 1b8bf7d..37cdefa 100644 (file)
@@ -136,11 +136,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()
@@ -251,7 +246,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 +
index 4c69a17..0790d47 100644 (file)
@@ -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 8125ba4..68a961e 100755 (executable)
--- 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)
@@ -609,6 +616,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)
index 2ac70a1..c62e28d 100644 (file)
@@ -50,6 +50,7 @@ class VppDpdkVhost(IVSwitch, tasks.Process):
         self._phy_ports = []
         self._virt_ports = []
         self._switches = {}
+        self._vpp_ctl = ['sudo', S.getValue('TOOLS')['vppctl']]
 
         # configure DPDK NICs
         tmp_args = copy.deepcopy(S.getValue('VSWITCH_VPP_ARGS'))
@@ -71,8 +72,20 @@ class VppDpdkVhost(IVSwitch, tasks.Process):
         # configure path to the plugins
         tmp_args['plugin_path'] = S.getValue('TOOLS')['vpp_plugin_path']
 
+        # cli sock file must be used for VPP 17.10 and newer
+        if S.getValue('VSWITCH_VPP_CLI_SOCK'):
+            self._vpp_ctl += ['-s', S.getValue('VSWITCH_VPP_CLI_SOCK')]
+            tmp_args['unix'].append('cli-listen {}'.format(
+                S.getValue('VSWITCH_VPP_CLI_SOCK')))
+
+        mqs = int(S.getValue('VSWITCH_DPDK_MULTI_QUEUES'))
+        tmp_rxqs = ''
+        if mqs:
+            tmp_rxqs = " {{ num-rx-queues {} }}".format(mqs)
+
+        # configure physical ports
         for nic in S.getValue('NICS'):
-            tmp_args['dpdk'].append("dev {}".format(nic['pci']))
+            tmp_args['dpdk'].append("dev {}{}".format(nic['pci'], tmp_rxqs))
         self._vswitch_args = self._process_vpp_args(tmp_args)
 
     def _get_nic_info(self, key='Name'):
@@ -365,7 +378,7 @@ class VppDpdkVhost(IVSwitch, tasks.Process):
 
         :return: None
         """
-        cmd = ['sudo', S.getValue('TOOLS')['vppctl']] + args
+        cmd = self._vpp_ctl + args
         return tasks.run_task(cmd, self._logger, 'Running vppctl...', check_error)
 
     #