-##############################################################################
-# Copyright (c) 2015 Ericsson AB and others.
+# Copyright 2014: Mirantis Inc.
+# All Rights Reserved.
#
-# 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
-##############################################################################
-
-'''A runner that every run arithmetically steps a specified input value to
-the scenario. This just means a step value is added to the previous value.
+# 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.
+
+# yardstick comment: this is a modified copy of
+# rally/rally/benchmark/runners/constant.py
+
+'''A runner that every run arithmetically steps specified input value(s) to
+the scenario. This just means step value(s) is added to the previous value(s).
+It is possible to combine several named input values and run with those either
+as nested for loops or combine each i:th index of each "input value list"
+until the end of the shortest list is reached (optimally all lists should be
+defined with the same number of values when using such iter_type).
'''
import os
import logging
import traceback
import time
+import itertools
from yardstick.benchmark.runners import base
LOG = logging.getLogger(__name__)
-def _worker_process(queue, cls, method_name, context, scenario_args):
+def _worker_process(queue, cls, method_name, scenario_cfg,
+ context_cfg, aborted):
sequence = 1
- interval = context.get("interval", 1)
- arg_name = context.get('name')
- stop = context.get('stop')
- step = context.get('step')
- options = scenario_args['options']
- start = options.get(arg_name, 0)
+ runner_cfg = scenario_cfg['runner']
- context['runner'] = os.getpid()
+ interval = runner_cfg.get("interval", 1)
+ if 'options' in scenario_cfg:
+ options = scenario_cfg['options']
+ else: # options must be instatiated if not present in yaml
+ options = {}
+ scenario_cfg['options'] = options
- LOG.info("worker START, step(%s, %d, %d, %d), class %s",
- arg_name, start, stop, step, cls)
+ runner_cfg['runner_id'] = os.getpid()
- benchmark = cls(context)
+ LOG.info("worker START, class %s", cls)
+
+ benchmark = cls(scenario_cfg, context_cfg)
benchmark.setup()
method = getattr(benchmark, method_name)
- record_context = {"runner": context["runner"],
- "host": context["host"]}
+ queue.put({'runner_id': runner_cfg['runner_id'],
+ 'scenario_cfg': scenario_cfg,
+ 'context_cfg': context_cfg})
sla_action = None
- if "sla" in scenario_args:
- sla_action = scenario_args["sla"].get("action", "assert")
- margin = 1 if step > 0 else -1
-
- for value in range(start, stop+margin, step):
-
- options[arg_name] = value
+ if "sla" in scenario_cfg:
+ sla_action = scenario_cfg["sla"].get("action", "assert")
+
+ # To both be able to include the stop value and handle backwards stepping
+ def margin(start, stop):
+ return -1 if start > stop else 1
+
+ param_iters = \
+ [xrange(d['start'], d['stop'] + margin(d['start'], d['stop']),
+ d['step']) for d in runner_cfg['iterators']]
+ param_names = [d['name'] for d in runner_cfg['iterators']]
+
+ iter_type = runner_cfg.get("iter_type", "nested_for_loops")
+
+ if iter_type == 'nested_for_loops':
+ # Create a complete combination set of all parameter lists
+ loop_iter = itertools.product(*param_iters)
+ elif iter_type == 'tuple_loops':
+ # Combine each i;th index of respective parameter list
+ loop_iter = itertools.izip(*param_iters)
+ else:
+ LOG.warning("iter_type unrecognized: %s", iter_type)
+ raise
+
+ # Populate options and run the requested method for each value combination
+ for comb_values in loop_iter:
+
+ if aborted.is_set():
+ break
LOG.debug("runner=%(runner)s seq=%(sequence)s START" %
- {"runner": context["runner"], "sequence": sequence})
+ {"runner": runner_cfg["runner_id"], "sequence": sequence})
+
+ for i, value in enumerate(comb_values):
+ options[param_names[i]] = value
data = {}
errors = ""
try:
- data = method(scenario_args)
+ method(data)
except AssertionError as assertion:
# SLA validation failed in scenario, determine what to do now
if sla_action == "assert":
'errors': errors
}
- queue.put({'context': record_context, 'sargs': scenario_args,
- 'benchmark': benchmark_output})
+ record = {'runner_id': runner_cfg['runner_id'],
+ 'benchmark': benchmark_output}
+
+ queue.put(record)
LOG.debug("runner=%(runner)s seq=%(sequence)s END" %
- {"runner": context["runner"], "sequence": sequence})
+ {"runner": runner_cfg["runner_id"], "sequence": sequence})
sequence += 1
- if errors:
+ if (errors and sla_action is None):
break
benchmark.teardown()
class ArithmeticRunner(base.Runner):
- '''Run a scenario arithmetically stepping an input value
+ '''Run a scenario arithmetically stepping input value(s)
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
+ iter_type: - Iteration type of input parameter(s): nested_for_loops
+ or tuple_loops
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
+ default: nested_for_loops
+ -
+ name - name of scenario option that will be increased for each invocation
+ type: string
+ unit: na
+ default: na
+ start - value to use in first invocation of scenario
+ type: int
+ unit: na
+ default: none
+ stop - value indicating end of invocation. Can be set to same
+ value as start for one single value.
+ type: int
+ unit: na
+ default: none
+ step - value added to start value in next invocation of scenario.
+ Must not be set to zero. Can be set negative if start > stop
+ type: int
+ unit: na
+ default: none
+ -
+ name - and so on......
'''
__execution_type__ = 'Arithmetic'
- def _run_benchmark(self, cls, method, scenario_args):
+ def _run_benchmark(self, cls, method, scenario_cfg, context_cfg):
self.process = multiprocessing.Process(
target=_worker_process,
- args=(self.result_queue, cls, method, self.config, scenario_args))
+ args=(self.result_queue, cls, method, scenario_cfg,
+ context_cfg, self.aborted))
self.process.start()