Merge "Add send socket commands function"
[yardstick.git] / yardstick / benchmark / scenarios / base.py
1 # Copyright 2013: 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 import abc
17 import time
18
19 import six
20 from stevedore import extension
21
22 import yardstick.common.utils as utils
23 from yardstick.common import exceptions as y_exc
24
25
26 def _iter_scenario_classes(scenario_type=None):
27     """Generator over all 'Scenario' subclasses
28
29     This function will iterate over all 'Scenario' subclasses defined in this
30     project and will load any class introduced by any installed plugin project,
31     defined in 'entry_points' section, under 'yardstick.scenarios' subsection.
32     """
33     extension.ExtensionManager(namespace='yardstick.scenarios',
34                                invoke_on_load=False)
35     for scenario in utils.itersubclasses(Scenario):
36         if not scenario_type:
37             yield scenario
38         elif getattr(scenario, '__scenario_type__', None) == scenario_type:
39             yield scenario
40
41
42 @six.add_metaclass(abc.ABCMeta)
43 class Scenario(object):
44
45     def setup(self):
46         """Default setup implementation for Scenario classes"""
47         pass
48
49     @abc.abstractmethod
50     def run(self, *args):
51         """Entry point for scenario classes, called from runner worker"""
52
53     def teardown(self):
54         """Default teardown implementation for Scenario classes"""
55         pass
56
57     def pre_run_wait_time(self, time_seconds):
58         """Time waited before executing the run method"""
59         pass
60
61     def post_run_wait_time(self, time_seconds):
62         """Time waited after executing the run method"""
63         time.sleep(time_seconds)
64
65     def verify_SLA(self, condition, error_msg):
66         if not condition:
67             raise y_exc.SLAValidationError(
68                 case_name=self.__scenario_type__, error_msg=error_msg)
69
70     @staticmethod
71     def get_types():
72         """return a list of known runner type (class) names"""
73         scenarios = []
74         for scenario in _iter_scenario_classes():
75             scenarios.append(scenario)
76         return scenarios
77
78     @staticmethod
79     def get_cls(scenario_type):
80         """return class of specified type"""
81         for scenario in _iter_scenario_classes(scenario_type):
82             return scenario
83
84         raise RuntimeError("No such scenario type %s" % scenario_type)
85
86     @staticmethod
87     def get(scenario_type):
88         """Returns instance of a scenario runner for execution type.
89         """
90         scenario = Scenario.get_cls(scenario_type)
91         return scenario.__module__ + "." + scenario.__name__
92
93     @classmethod
94     def get_scenario_type(cls):
95         """Return a string with the scenario type, if defined"""
96         return str(getattr(cls, '__scenario_type__', None))
97
98     @classmethod
99     def get_description(cls):
100         """Return a single line string with the class description
101
102         This function will retrieve the class docstring and return the first
103         line, or 'None' if it's empty.
104         """
105         return cls.__doc__.splitlines()[0] if cls.__doc__ else str(None)
106
107     @staticmethod
108     def _push_to_outputs(keys, values):
109         """Return a dictionary given the keys and the values"""
110         return dict(zip(keys, values))
111
112     @staticmethod
113     def _change_obj_to_dict(obj):
114         """Return a dictionary from the __dict__ attribute of an object"""
115         dic = {}
116         for k, v in vars(obj).items():
117             try:
118                 vars(v)
119             except TypeError:
120                 dic[k] = v
121         return dic
122
123     def get_mq_ids(self):  # pragma: no cover
124         """Return stored MQ producer IDs, if defined"""
125         pass