Merge "vsperf: Enhanced vswitchperf configuration"
[yardstick.git] / yardstick / benchmark / runners / iteration.py
1 # Copyright 2014: Mirantis Inc.
2 # All Rights Reserved.
3 #
4 #    Licensed under the Apache License, Version 2.0 (the "License"); you may
5 #    not use this file except in compliance with the License. You may obtain
6 #    a copy of the License at
7 #
8 #         http://www.apache.org/licenses/LICENSE-2.0
9 #
10 #    Unless required by applicable law or agreed to in writing, software
11 #    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 #    License for the specific language governing permissions and limitations
14 #    under the License.
15
16 # yardstick comment: this is a modified copy of
17 # rally/rally/benchmark/runners/constant.py
18
19 '''A runner that runs a configurable number of times before it returns
20 '''
21
22 import os
23 import multiprocessing
24 import logging
25 import traceback
26 import time
27
28 from yardstick.benchmark.runners import base
29
30 LOG = logging.getLogger(__name__)
31
32
33 def _worker_process(queue, cls, method_name, scenario_cfg,
34                     context_cfg, aborted):
35
36     sequence = 1
37
38     runner_cfg = scenario_cfg['runner']
39
40     interval = runner_cfg.get("interval", 1)
41     iterations = runner_cfg.get("iterations", 1)
42     run_step = runner_cfg.get("run_step", "setup,run,teardown")
43     LOG.info("worker START, iterations %d times, class %s", iterations, cls)
44
45     runner_cfg['runner_id'] = os.getpid()
46
47     benchmark = cls(scenario_cfg, context_cfg)
48     if "setup" in run_step:
49         benchmark.setup()
50
51     method = getattr(benchmark, method_name)
52
53     queue.put({'runner_id': runner_cfg['runner_id'],
54                'scenario_cfg': scenario_cfg,
55                'context_cfg': context_cfg})
56
57     sla_action = None
58     if "sla" in scenario_cfg:
59         sla_action = scenario_cfg["sla"].get("action", "assert")
60     if "run" in run_step:
61         while True:
62
63             LOG.debug("runner=%(runner)s seq=%(sequence)s START",
64                       {"runner": runner_cfg["runner_id"],
65                        "sequence": sequence})
66
67             data = {}
68             errors = ""
69
70             try:
71                 method(data)
72             except AssertionError as assertion:
73                 # SLA validation failed in scenario, determine what to do now
74                 if sla_action == "assert":
75                     raise
76                 elif sla_action == "monitor":
77                     LOG.warning("SLA validation failed: %s", assertion.args)
78                     errors = assertion.args
79             except Exception as e:
80                 errors = traceback.format_exc()
81                 LOG.exception(e)
82
83             time.sleep(interval)
84
85             benchmark_output = {
86                 'timestamp': time.time(),
87                 'sequence': sequence,
88                 'data': data,
89                 'errors': errors
90             }
91
92             record = {'runner_id': runner_cfg['runner_id'],
93                       'benchmark': benchmark_output}
94
95             queue.put(record)
96
97             LOG.debug("runner=%(runner)s seq=%(sequence)s END",
98                       {"runner": runner_cfg["runner_id"],
99                        "sequence": sequence})
100
101             sequence += 1
102
103             if (errors and sla_action is None) or \
104                     (sequence > iterations or aborted.is_set()):
105                 LOG.info("worker END")
106                 break
107     if "teardown" in run_step:
108         benchmark.teardown()
109
110
111 class IterationRunner(base.Runner):
112     '''Run a scenario for a configurable number of times
113
114 If the scenario ends before the time has elapsed, it will be started again.
115
116   Parameters
117     iterations - amount of times the scenario will be run for
118         type:    int
119         unit:    na
120         default: 1
121     interval - time to wait between each scenario invocation
122         type:    int
123         unit:    seconds
124         default: 1 sec
125     '''
126     __execution_type__ = 'Iteration'
127
128     def _run_benchmark(self, cls, method, scenario_cfg, context_cfg):
129         self.process = multiprocessing.Process(
130             target=_worker_process,
131             args=(self.result_queue, cls, method, scenario_cfg,
132                   context_cfg, self.aborted))
133         self.process.start()