1 # Copyright 2014: Mirantis Inc.
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
8 # http://www.apache.org/licenses/LICENSE-2.0
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
16 # yardstick comment: this is a modified copy of
17 # rally/rally/benchmark/runners/constant.py
19 """A runner that runs a specific time before it returns
22 from __future__ import absolute_import
25 import multiprocessing
28 from contextlib import contextmanager
29 from itertools import takewhile
32 from collections import Mapping
33 from six.moves import zip
35 from yardstick.benchmark.runners import base
36 from yardstick.common import exceptions as y_exc
38 LOG = logging.getLogger(__name__)
41 class SearchRunnerHelper(object):
43 def __init__(self, cls, method_name, scenario_cfg, context_cfg, aborted):
44 super(SearchRunnerHelper, self).__init__()
46 self.method_name = method_name
47 self.scenario_cfg = scenario_cfg
48 self.context_cfg = context_cfg
49 self.aborted = aborted
50 self.runner_cfg = scenario_cfg['runner']
51 self.run_step = self.runner_cfg.get("run_step", "setup,run,teardown")
52 self.timeout = self.runner_cfg.get("timeout", 60)
53 self.interval = self.runner_cfg.get("interval", 1)
57 def __call__(self, *args, **kwargs):
58 if self.method is None:
60 return self.method(*args, **kwargs)
63 def get_benchmark_instance(self):
64 self.benchmark = self.cls(self.scenario_cfg, self.context_cfg)
66 if 'setup' in self.run_step:
67 self.benchmark.setup()
69 self.method = getattr(self.benchmark, self.method_name)
70 LOG.info("worker START, timeout %d sec, class %s", self.timeout, self.cls)
74 if 'teardown' in self.run_step:
75 self.benchmark.teardown()
77 def is_not_done(self):
78 if 'run' not in self.run_step:
81 max_time = time.time() + self.timeout
83 abort_iter = iter(self.aborted.is_set, True)
84 time_iter = takewhile(lambda t_now: t_now <= max_time, iter(time.time, -1))
86 for seq, _ in enumerate(zip(abort_iter, time_iter), 1):
88 time.sleep(self.interval)
91 class SearchRunner(base.Runner):
92 """Run a scenario for a certain amount of time
94 If the scenario ends before the time has elapsed, it will be started again.
97 timeout - amount of time the scenario will be run for
101 interval - time to wait between each scenario invocation
106 __execution_type__ = 'Search'
108 def __init__(self, config):
109 super(SearchRunner, self).__init__(config)
110 self.runner_cfg = None
111 self.runner_id = None
112 self.sla_action = None
113 self.worker_helper = None
115 def _worker_run_once(self, sequence):
116 LOG.debug("runner=%s seq=%s START", self.runner_id, sequence)
122 self.worker_helper(data)
123 except y_exc.SLAValidationError as error:
124 # SLA validation failed in scenario, determine what to do now
125 if self.sla_action == "assert":
127 elif self.sla_action == "monitor":
128 LOG.warning("SLA validation failed: %s", error.args)
130 except Exception as e: # pylint: disable=broad-except
131 errors = traceback.format_exc()
135 'runner_id': self.runner_id,
137 'timestamp': time.time(),
138 'sequence': sequence,
144 self.result_queue.put(record)
146 LOG.debug("runner=%s seq=%s END", self.runner_id, sequence)
148 # Have to search through all the VNF KPIs
149 kpi_done = any(kpi.get('done') for kpi in data.values() if isinstance(kpi, Mapping))
151 return kpi_done or (errors and self.sla_action is None)
153 def _worker_run(self, cls, method_name, scenario_cfg, context_cfg):
154 self.runner_cfg = scenario_cfg['runner']
155 self.runner_id = self.runner_cfg['runner_id'] = os.getpid()
157 self.worker_helper = SearchRunnerHelper(cls, method_name, scenario_cfg,
158 context_cfg, self.aborted)
161 self.sla_action = scenario_cfg['sla'].get('action', 'assert')
163 self.sla_action = None
165 self.result_queue.put({
166 'runner_id': self.runner_id,
167 'scenario_cfg': scenario_cfg,
168 'context_cfg': context_cfg
171 with self.worker_helper.get_benchmark_instance():
172 for sequence in self.worker_helper.is_not_done():
173 if self._worker_run_once(sequence):
174 LOG.info("worker END")
177 def _run_benchmark(self, cls, method, scenario_cfg, context_cfg):
178 name = "{}-{}-{}".format(self.__execution_type__, scenario_cfg.get("type"), os.getpid())
179 self.process = multiprocessing.Process(
181 target=self._worker_run,
182 args=(cls, method, scenario_cfg, context_cfg))