blob: 1cbf88c65b3548bb6746e42442174bdc62317713 [file] [log] [blame]
koder aka kdanilov4643fd62015-02-10 16:20:13 -08001import abc
koder aka kdanilov4643fd62015-02-10 16:20:13 -08002import os.path
koder aka kdanilov88407ff2015-05-26 15:35:57 +03003import functools
koder aka kdanilov652cd802015-04-13 12:21:07 +03004
koder aka kdanilov4643fd62015-02-10 16:20:13 -08005
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +03006from wally.ssh_utils import run_over_ssh, copy_paths
7
8
koder aka kdanilov88407ff2015-05-26 15:35:57 +03009def cached_prop(func):
10 @property
11 @functools.wraps(func)
12 def closure(self):
13 val = getattr(self, "_" + func.__name__)
14 if val is NoData:
15 val = func(self)
16 setattr(self, "_" + func.__name__, val)
17 return val
18 return closure
19
20
21class NoData(object):
22 pass
23
24
25class VMThData(object):
26 "store set of values for VM_COUNT * TH_COUNT"
27
28
29class IOTestResult(object):
30 def __init__(self):
31 self.run_config = None
32 self.suite_config = None
33 self.run_interval = None
34
35 self.bw = None
36 self.lat = None
37 self.iops = None
38 self.slat = None
39 self.clat = None
40
41 self.fio_section = None
42
43 self._lat_log = NoData
44 self._iops_log = NoData
45 self._bw_log = NoData
46
47 self._sensors_data = NoData
48 self._raw_resuls = NoData
49
50 def to_jsonable(self):
51 pass
52
53 @property
54 def thread_count(self):
55 pass
56
57 @property
58 def sync_mode(self):
59 pass
60
61 @property
62 def abbrev_name(self):
63 pass
64
65 @property
66 def full_name(self):
67 pass
68
69 @cached_prop
70 def lat_log(self):
71 pass
72
73 @cached_prop
74 def iops_log(self):
75 pass
76
77 @cached_prop
78 def bw_log(self):
79 pass
80
81 @cached_prop
82 def sensors_data(self):
83 pass
84
85 @cached_prop
86 def raw_resuls(self):
87 pass
88
89
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +030090class TestResults(object):
91 def __init__(self, config, params, results,
koder aka kdanilov88407ff2015-05-26 15:35:57 +030092 raw_result, run_interval, vm_count,
93 test_name, **attrs):
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +030094 self.config = config
95 self.params = params
96 self.results = results
97 self.raw_result = raw_result
98 self.run_interval = run_interval
99 self.vm_count = vm_count
koder aka kdanilovbb5fe072015-05-21 02:50:23 +0300100 self.test_name = test_name
koder aka kdanilov88407ff2015-05-26 15:35:57 +0300101 self.__dict__.update(attrs)
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +0300102
103 def __str__(self):
104 res = "{0}({1}):\n results:\n".format(
105 self.__class__.__name__,
106 self.summary())
107
108 for name, val in self.results.items():
109 res += " {0}={1}\n".format(name, val)
110
111 res += " params:\n"
112
113 for name, val in self.params.items():
114 res += " {0}={1}\n".format(name, val)
115
116 return res
117
118 @abc.abstractmethod
119 def summary(self):
120 pass
121
122 @abc.abstractmethod
123 def get_yamable(self):
124 pass
koder aka kdanilove21d7472015-02-14 19:02:04 -0800125
126
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800127class IPerfTest(object):
koder aka kdanilovabd6ead2015-04-24 02:03:07 +0300128 def __init__(self, options, is_primary, on_result_cb, test_uuid, node,
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +0300129 total_nodes_count,
koder aka kdanilov2066daf2015-04-23 21:05:41 +0300130 log_directory=None,
131 coordination_queue=None,
132 remote_dir="/tmp/wally"):
koder aka kdanilovabd6ead2015-04-24 02:03:07 +0300133 self.options = options
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800134 self.on_result_cb = on_result_cb
koder aka kdanilov4500a5f2015-04-17 16:55:17 +0300135 self.log_directory = log_directory
136 self.node = node
koder aka kdanilov4d4771c2015-04-23 01:32:02 +0300137 self.test_uuid = test_uuid
koder aka kdanilovec1b9732015-04-23 20:43:29 +0300138 self.coordination_queue = coordination_queue
koder aka kdanilov2066daf2015-04-23 21:05:41 +0300139 self.remote_dir = remote_dir
koder aka kdanilovabd6ead2015-04-24 02:03:07 +0300140 self.is_primary = is_primary
koder aka kdanilove2de58c2015-04-24 22:59:36 +0300141 self.stop_requested = False
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +0300142 self.total_nodes_count = total_nodes_count
koder aka kdanilove2de58c2015-04-24 22:59:36 +0300143
144 def request_stop(self):
145 self.stop_requested = True
koder aka kdanilov2066daf2015-04-23 21:05:41 +0300146
147 def join_remote(self, path):
148 return os.path.join(self.remote_dir, path)
koder aka kdanilovec1b9732015-04-23 20:43:29 +0300149
150 def coordinate(self, data):
151 if self.coordination_queue is not None:
koder aka kdanilove2de58c2015-04-24 22:59:36 +0300152 self.coordination_queue.put((self.node.get_conn_id(), data))
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800153
koder aka kdanilov4d4771c2015-04-23 01:32:02 +0300154 def pre_run(self):
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800155 pass
156
koder aka kdanilov4d4771c2015-04-23 01:32:02 +0300157 def cleanup(self):
koder aka kdanilov4500a5f2015-04-17 16:55:17 +0300158 pass
159
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +0300160 @classmethod
161 @abc.abstractmethod
162 def load(cls, data):
163 pass
164
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800165 @abc.abstractmethod
koder aka kdanilov4d4771c2015-04-23 01:32:02 +0300166 def run(self, barrier):
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800167 pass
168
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +0300169 @classmethod
170 def format_for_console(cls, data):
171 msg = "{0}.format_for_console".format(cls.__name__)
172 raise NotImplementedError(msg)
173
koder aka kdanilov4d4771c2015-04-23 01:32:02 +0300174 def run_over_ssh(self, cmd, **kwargs):
175 return run_over_ssh(self.node.connection, cmd,
176 node=self.node.get_conn_id(), **kwargs)
177
koder aka kdanilovec1b9732015-04-23 20:43:29 +0300178 @classmethod
179 def coordination_th(cls, coord_q, barrier, num_threads):
180 pass
181
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800182
Yulia Portnova7ddfa732015-02-24 17:32:58 +0200183class TwoScriptTest(IPerfTest):
koder aka kdanilovabd6ead2015-04-24 02:03:07 +0300184 def __init__(self, *dt, **mp):
koder aka kdanilov4d4771c2015-04-23 01:32:02 +0300185 IPerfTest.__init__(self, *dt, **mp)
Yulia Portnova7ddfa732015-02-24 17:32:58 +0200186
Yulia Portnovab1a15072015-05-06 14:59:25 +0300187 if 'scripts_path' in self.options:
188 self.root = self.options['scripts_path']
koder aka kdanilovabd6ead2015-04-24 02:03:07 +0300189 self.run_script = self.options['run_script']
Yulia Portnovab1a15072015-05-06 14:59:25 +0300190 self.prerun_script = self.options['prerun_script']
Yulia Portnova7ddfa732015-02-24 17:32:58 +0200191
192 def get_remote_for_script(self, script):
Yulia Portnovab1a15072015-05-06 14:59:25 +0300193 return os.path.join(self.remote_dir, script.rpartition('/')[2])
Yulia Portnova7ddfa732015-02-24 17:32:58 +0200194
koder aka kdanilov4d4771c2015-04-23 01:32:02 +0300195 def pre_run(self):
Yulia Portnovab1a15072015-05-06 14:59:25 +0300196 copy_paths(self.node.connection, {self.root: self.remote_dir})
197 cmd = self.get_remote_for_script(self.pre_run_script)
198 self.run_over_ssh(cmd, timeout=2000)
Yulia Portnova7ddfa732015-02-24 17:32:58 +0200199
koder aka kdanilov4d4771c2015-04-23 01:32:02 +0300200 def run(self, barrier):
Yulia Portnovab1a15072015-05-06 14:59:25 +0300201 remote_script = self.get_remote_for_script(self.run_script)
Yulia Portnova886a2562015-04-07 11:16:13 +0300202 cmd_opts = ' '.join(["%s %s" % (key, val) for key, val
koder aka kdanilovabd6ead2015-04-24 02:03:07 +0300203 in self.options.items()])
Yulia Portnova886a2562015-04-07 11:16:13 +0300204 cmd = remote_script + ' ' + cmd_opts
Yulia Portnovab1a15072015-05-06 14:59:25 +0300205 out_err = self.run_over_ssh(cmd, timeout=6000)
koder aka kdanilov66839a92015-04-11 13:22:31 +0300206 self.on_result(out_err, cmd)
Yulia Portnova7ddfa732015-02-24 17:32:58 +0200207
208 def parse_results(self, out):
209 for line in out.split("\n"):
210 key, separator, value = line.partition(":")
211 if key and value:
212 self.on_result_cb((key, float(value)))
213
koder aka kdanilov66839a92015-04-11 13:22:31 +0300214 def on_result(self, out_err, cmd):
215 try:
216 self.parse_results(out_err)
217 except Exception as exc:
koder aka kdanilovec1b9732015-04-23 20:43:29 +0300218 msg_templ = "Error during postprocessing results: {0!s}. {1}"
219 raise RuntimeError(msg_templ.format(exc, out_err))
Yulia Portnova7ddfa732015-02-24 17:32:58 +0200220
Yulia Portnovab1a15072015-05-06 14:59:25 +0300221 def merge_results(self, results):
222 tpcm = sum([val[1] for val in results])
223 return {"res": {"TpmC": tpcm}}