blob: c8b641b5af5c991eceb071e902dee450641877b7 [file] [log] [blame]
koder aka kdanilov4643fd62015-02-10 16:20:13 -08001import abc
2import json
3import types
4import os.path
koder aka kdanilove21d7472015-02-14 19:02:04 -08005import logging
6
koder aka kdanilov4643fd62015-02-10 16:20:13 -08007from io_scenario import io
8from ssh_copy_directory import copy_paths
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -08009from utils import run_over_ssh
koder aka kdanilov4643fd62015-02-10 16:20:13 -080010
11
koder aka kdanilove21d7472015-02-14 19:02:04 -080012logger = logging.getLogger("io-perf-tool")
13
14
koder aka kdanilov4643fd62015-02-10 16:20:13 -080015class IPerfTest(object):
16 def __init__(self, on_result_cb):
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -080017 self.set_result_cb(on_result_cb)
18
19 def set_result_cb(self, on_result_cb):
koder aka kdanilov4643fd62015-02-10 16:20:13 -080020 self.on_result_cb = on_result_cb
21
22 def build(self, conn):
23 self.pre_run(conn)
24
25 def pre_run(self, conn):
26 pass
27
28 @abc.abstractmethod
29 def run(self, conn):
30 pass
31
32
Yulia Portnova7ddfa732015-02-24 17:32:58 +020033class TwoScriptTest(IPerfTest):
34 def __init__(self, opts, testtool, on_result_cb, keep_tmp_files):
35 super(TwoScriptTest, self).__init__(on_result_cb)
36 self.opts = opts
37 self.pre_run_script = None
38 self.run_script = None
39 self.tmp_dir = "/tmp/"
40 self.set_run_script()
41 self.set_pre_run_script()
42
43 def set_run_script(self):
44 self.pre_run_script = self.opts.pre_run_script
45
46 def set_pre_run_script(self):
47 self.run_script = self.opts.run_script
48
49 def get_remote_for_script(self, script):
50 return os.path.join(self.tmp_dir, script.rpartition('/')[2])
51
52 def copy_script(self, conn, src):
53 remote_path = self.get_remote_for_script(src)
54 copy_paths(conn, {src: remote_path})
55 return remote_path
56
57 def pre_run(self, conn):
58 remote_script = self.copy_script(conn, self.pre_run_script)
59 cmd = remote_script
60 code, out, err = run_over_ssh(conn, cmd)
61 if code != 0:
62 raise Exception("Pre run failed. %s" % err)
63
64 def run(self, conn):
65 remote_script = self.copy_script(conn, self.run_script)
Yulia Portnova3f65e7c2015-02-25 17:19:35 +020066 cmd = remote_script + ' ' + ' '.join(self.opts)
Yulia Portnova7ddfa732015-02-24 17:32:58 +020067 code, out, err = run_over_ssh(conn, cmd)
68 self.on_result(code, out, err, cmd)
69
70 def parse_results(self, out):
71 for line in out.split("\n"):
72 key, separator, value = line.partition(":")
73 if key and value:
74 self.on_result_cb((key, float(value)))
75
76 def on_result(self, code, out, err, cmd):
77 if 0 == code:
78 try:
79 self.parse_results(out)
80 except Exception as err:
81 msg_templ = "Error during postprocessing results: {0!r}"
82 raise RuntimeError(msg_templ.format(err.message))
83 else:
84 templ = "Command {0!r} failed with code {1}. Error output is:\n{2}"
85 logger.error(templ.format(cmd, code, err))
86
87
88class PgBenchTest(TwoScriptTest):
89
90 def set_run_script(self):
91 self.pre_run_script = "hl_tests/postgres/prepare.sh"
92
93 def set_pre_run_script(self):
94 self.run_script = "hl_tests/postgres/run.sh"
95
96
koder aka kdanilov4643fd62015-02-10 16:20:13 -080097def run_test_iter(obj, conn):
98 yield obj.pre_run(conn)
99 res = obj.run(conn)
100 if isinstance(res, types.GeneratorType):
101 for vl in res:
102 yield vl
103 else:
104 yield res
105
106
107class IOPerfTest(IPerfTest):
108 def __init__(self,
109 script_opts,
110 testtool_local,
111 on_result_cb,
112 keep_tmp_files):
113
114 IPerfTest.__init__(self, on_result_cb)
koder aka kdanilov50f18642015-02-11 08:54:44 -0800115
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800116 dst_testtool_path = '/tmp/io_tool'
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800117 self.script_opts = script_opts + ["--binary-path", dst_testtool_path]
koder aka kdanilov50f18642015-02-11 08:54:44 -0800118 io_py_local = os.path.join(os.path.dirname(io.__file__), "io.py")
119 self.io_py_remote = "/tmp/io.py"
120
121 self.files_to_copy = {testtool_local: dst_testtool_path,
122 io_py_local: self.io_py_remote}
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800123
124 def pre_run(self, conn):
koder aka kdanilov50f18642015-02-11 08:54:44 -0800125 copy_paths(conn, self.files_to_copy)
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800126
127 def run(self, conn):
koder aka kdanilov50f18642015-02-11 08:54:44 -0800128 args = ['env', 'python2', self.io_py_remote] + self.script_opts
koder aka kdanilove21d7472015-02-14 19:02:04 -0800129 cmd = " ".join(args)
130 code, out, err = run_over_ssh(conn, cmd)
131 self.on_result(code, out, err, cmd)
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800132
koder aka kdanilove21d7472015-02-14 19:02:04 -0800133 def on_result(self, code, out, err, cmd):
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800134 if 0 == code:
135 try:
136 for line in out.split("\n"):
137 if line.strip() != "":
138 self.on_result_cb(json.loads(line))
139 except Exception as err:
koder aka kdanilov0f0546c2015-02-17 20:42:05 -0800140 msg_templ = "Error during postprocessing results: {0!r}"
141 raise RuntimeError(msg_templ.format(err.message))
koder aka kdanilove21d7472015-02-14 19:02:04 -0800142 else:
143 templ = "Command {0!r} failed with code {1}. Error output is:\n{2}"
144 logger.error(templ.format(cmd, code, err))