Add support to list and show runners & scenarios 05/905/3
authorHans Feldt <hans.feldt@ericsson.com>
Fri, 26 Jun 2015 09:53:21 +0000 (11:53 +0200)
committerHans Feldt <hans.feldt@ericsson.com>
Mon, 29 Jun 2015 07:07:46 +0000 (09:07 +0200)
Example usage and output:

$ yardstick runner list
+------------------------------------------------------------------------------+
| Type             | Description
+------------------------------------------------------------------------------+
| Duration         | Run a scenario for a certain amount of time
| Arithmetic       | Run a scenario arithmetically stepping an input value
| Constant         | Run a scenario a certain number of times
+------------------------------------------------------------------------------+
$ yardstick runner show Duration
Run a scenario for a certain amount of time

If the scenario ends before the time has elapsed, it will be started again.

  Parameters
    duration - amount of time the scenario will be run for
        type:    int
        unit:    seconds
        default: 1 sec
    interval - time to wait between each scenario invocation
        type:    int
        unit:    seconds
        default: 1 sec

$ yardstick scenario list
+------------------------------------------------------------------------------+
| Type             | Description
+------------------------------------------------------------------------------+
| Iperf3           | Execute iperf3 between two hosts
| Pktgen           | Execute pktgen between two hosts
| Ping             | Execute ping between two hosts
+------------------------------------------------------------------------------+
$ yardstick scenario show Iperf3
Execute iperf3 between two hosts

By default TCP is used but UDP can also be configured.
For more info see http://software.es.net/iperf

  Parameters
    bytes - number of bytes to transmit
      only valid with a non duration runner, mutually exclusive with blockcount
        type:    int
        unit:    bytes
        default: 56
    udp - use UDP rather than TCP
        type:    bool
        unit:    na
        default: false
    nodelay - set TCP no delay, disabling Nagle's Algorithm
        type:    bool
        unit:    na
        default: false
    blockcount - number of blocks (packets) to transmit,
      only valid with a non duration runner, mutually exclusive with bytes
        type:    int
        unit:    bytes
        default: -

JIRA: -
Change-Id: If218e129a30af7e20792190003c214677e732252
Signed-off-by: Hans Feldt <hans.feldt@ericsson.com>
yardstick/benchmark/runners/arithmetic.py
yardstick/benchmark/runners/base.py
yardstick/benchmark/runners/duration.py
yardstick/benchmark/scenarios/base.py
yardstick/benchmark/scenarios/networking/iperf3.py
yardstick/benchmark/scenarios/networking/ping.py
yardstick/benchmark/scenarios/networking/pktgen.py
yardstick/cmd/__init__.py
yardstick/cmd/cli.py
yardstick/cmd/commands/runner.py [new file with mode: 0644]
yardstick/cmd/commands/scenario.py [new file with mode: 0644]

index acf14d0..9efafff 100644 (file)
@@ -97,6 +97,30 @@ def _worker_process(queue, cls, method_name, context, scenario_args):
 
 
 class ArithmeticRunner(base.Runner):
+    '''Run a scenario arithmetically stepping an input value
+
+  Parameters
+    interval - time to wait between each scenario invocation
+        type:    int
+        unit:    seconds
+        default: 1 sec
+    name - name of scenario option that will be increased for each invocation
+        type:    string
+        unit:    na
+        default: none
+    start - value to use in first invocation of scenario
+        type:    int
+        unit:    na
+        default: none
+    step - value added to start value in next invocation of scenario
+        type:    int
+        unit:    na
+        default: none
+    stop - value indicating end of invocation
+        type:    int
+        unit:    na
+        default: none
+    '''
 
     __execution_type__ = 'Arithmetic'
 
index 38ca34f..08117c6 100644 (file)
@@ -41,12 +41,21 @@ class Runner(object):
     runners = []
 
     @staticmethod
-    def _get_cls(runner_type):
+    def get_cls(runner_type):
+        '''return class of specified type'''
         for runner in utils.itersubclasses(Runner):
             if runner_type == runner.__execution_type__:
                 return runner
         raise RuntimeError("No such runner_type %s" % runner_type)
 
+    @staticmethod
+    def get_types():
+        '''return a list of known runner type (class) names'''
+        types = []
+        for runner in utils.itersubclasses(Runner):
+            types.append(runner)
+        return types
+
     @staticmethod
     def get(config):
         """Returns instance of a scenario runner for execution type.
@@ -62,7 +71,7 @@ class Runner(object):
                 args=(config["output_filename"], Runner.queue))
             Runner.dump_process.start()
 
-        return Runner._get_cls(config["type"])(config, Runner.queue)
+        return Runner.get_cls(config["type"])(config, Runner.queue)
 
     @staticmethod
     def release(runner):
index 61d498f..363320a 100644 (file)
@@ -89,7 +89,20 @@ def _worker_process(queue, cls, method_name, context, scenario_args):
 
 
 class DurationRunner(base.Runner):
-
+    '''Run a scenario for a certain amount of time
+
+If the scenario ends before the time has elapsed, it will be started again.
+
+  Parameters
+    duration - amount of time the scenario will be run for
+        type:    int
+        unit:    seconds
+        default: 1 sec
+    interval - time to wait between each scenario invocation
+        type:    int
+        unit:    seconds
+        default: 1 sec
+    '''
     __execution_type__ = 'Duration'
 
     def _run_benchmark(self, cls, method, scenario_args):
index e1e31fd..8146067 100644 (file)
@@ -27,6 +27,23 @@ class Scenario(object):
         ''' default impl for scenario teardown '''
         pass
 
+    @staticmethod
+    def get_types():
+        '''return a list of known runner type (class) names'''
+        scenarios = []
+        for scenario in utils.itersubclasses(Scenario):
+            scenarios.append(scenario)
+        return scenarios
+
+    @staticmethod
+    def get_cls(scenario_type):
+        '''return class of specified type'''
+        for scenario in utils.itersubclasses(Scenario):
+            if scenario_type == scenario.__scenario_type__:
+                return scenario
+
+        raise RuntimeError("No such scenario type %s" % scenario_type)
+
     @staticmethod
     def get(scenario_type):
         """Returns instance of a scenario runner for execution type.
index 9901444..8842372 100644 (file)
@@ -22,7 +22,31 @@ LOG.setLevel(logging.DEBUG)
 
 
 class Iperf(base.Scenario):
-    """Executes an iperf3 benchmark between two hosts"""
+    """Execute iperf3 between two hosts
+
+By default TCP is used but UDP can also be configured.
+For more info see http://software.es.net/iperf
+
+  Parameters
+    bytes - number of bytes to transmit
+      only valid with a non duration runner, mutually exclusive with blockcount
+        type:    int
+        unit:    bytes
+        default: 56
+    udp - use UDP rather than TCP
+        type:    bool
+        unit:    na
+        default: false
+    nodelay - set TCP no delay, disabling Nagle's Algorithm
+        type:    bool
+        unit:    na
+        default: false
+    blockcount - number of blocks (packets) to transmit,
+      only valid with a non duration runner, mutually exclusive with bytes
+        type:    int
+        unit:    bytes
+        default: -
+    """
     __scenario_type__ = "Iperf3"
 
     def __init__(self, context):
index ddf6864..630b007 100644 (file)
@@ -19,7 +19,15 @@ LOG = logging.getLogger(__name__)
 
 
 class Ping(base.Scenario):
-    """Executes a ping benchmark between two hosts"""
+    """Execute ping between two hosts
+
+  Parameters
+    packetsize - number of data bytes to send
+        type:    int
+        unit:    bytes
+        default: 56
+    """
+
     __scenario_type__ = "Ping"
 
     TARGET_SCRIPT = 'ping_benchmark.bash'
index 8038cad..430c959 100644 (file)
@@ -18,7 +18,11 @@ LOG.setLevel(logging.DEBUG)
 
 
 class Pktgen(base.Scenario):
-    """Executes a pktgen benchmark between two hosts"""
+    """Execute pktgen between two hosts
+
+  Parameters
+    TBD
+    """
     __scenario_type__ = "Pktgen"
 
     TARGET_SCRIPT = 'pktgen_benchmark.bash'
index e69de29..df891e3 100644 (file)
@@ -0,0 +1,15 @@
+##############################################################################
+# Copyright (c) 2015 Ericsson AB 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
+##############################################################################
+
+
+def print_hbar(barlen):
+    '''print to stdout a horizontal bar'''
+    print("+"),
+    print("-" * barlen),
+    print("+")
index 78e4e4c..3f6c73c 100644 (file)
@@ -18,6 +18,8 @@ from pkg_resources import get_distribution
 from argparse import RawDescriptionHelpFormatter
 
 from yardstick.cmd.commands import task
+from yardstick.cmd.commands import runner
+from yardstick.cmd.commands import scenario
 
 
 class YardstickCLI():
@@ -25,7 +27,9 @@ class YardstickCLI():
 
     # Command categories
     categories = {
-        'task': task.TaskCommands
+        'task': task.TaskCommands,
+        'runner': runner.RunnerCommands,
+        'scenario': scenario.ScenarioCommands
     }
 
     def __init__(self):
diff --git a/yardstick/cmd/commands/runner.py b/yardstick/cmd/commands/runner.py
new file mode 100644 (file)
index 0000000..84bc3c6
--- /dev/null
@@ -0,0 +1,38 @@
+##############################################################################
+# Copyright (c) 2015 Ericsson AB 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
+##############################################################################
+
+""" Handler for yardstick command 'runner' """
+
+from yardstick.benchmark.runners.base import Runner
+from yardstick.common.utils import cliargs
+from yardstick.cmd import print_hbar
+
+
+class RunnerCommands(object):
+    '''Runner commands.
+
+       Set of commands to discover and display runner types.
+    '''
+
+    def do_list(self, args):
+        '''List existing runner types'''
+        types = Runner.get_types()
+        print_hbar(78)
+        print("| %-16s | %-60s" % ("Type", "Description"))
+        print_hbar(78)
+        for rtype in types:
+            print "| %-16s | %-60s" % (rtype.__execution_type__,
+                                       rtype.__doc__.split("\n")[0])
+        print_hbar(78)
+
+    @cliargs("type", type=str, help="runner type", nargs=1)
+    def do_show(self, args):
+        '''Show details of a specific runner type'''
+        rtype = Runner.get_cls(args.type[0])
+        print rtype.__doc__
diff --git a/yardstick/cmd/commands/scenario.py b/yardstick/cmd/commands/scenario.py
new file mode 100644 (file)
index 0000000..00d46cf
--- /dev/null
@@ -0,0 +1,38 @@
+##############################################################################
+# Copyright (c) 2015 Ericsson AB 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
+##############################################################################
+
+""" Handler for yardstick command 'scenario' """
+
+from yardstick.benchmark.scenarios.base import Scenario
+from yardstick.common.utils import cliargs
+from yardstick.cmd import print_hbar
+
+
+class ScenarioCommands(object):
+    '''Scenario commands.
+
+       Set of commands to discover and display scenario types.
+    '''
+
+    def do_list(self, args):
+        '''List existing scenario types'''
+        types = Scenario.get_types()
+        print_hbar(78)
+        print("| %-16s | %-60s" % ("Type", "Description"))
+        print_hbar(78)
+        for stype in types:
+            print("| %-16s | %-60s" % (stype.__scenario_type__,
+                                       stype.__doc__.split("\n")[0]))
+        print_hbar(78)
+
+    @cliargs("type", type=str, help="runner type", nargs=1)
+    def do_show(self, args):
+        '''Show details of a specific scenario type'''
+        stype = Scenario.get_cls(args.type[0])
+        print stype.__doc__