blob: 53c4af38f27cf150cd1fffe708db0f990ddf87fb [file] [log] [blame]
koder aka kdanilovda45e882015-04-06 02:24:42 +03001import re
koder aka kdanilov4643fd62015-02-10 16:20:13 -08002import abc
3import json
koder aka kdanilov4643fd62015-02-10 16:20:13 -08004import os.path
koder aka kdanilove21d7472015-02-14 19:02:04 -08005import logging
6
koder aka kdanilov2e928022015-04-08 13:47:15 +03007from disk_perf_test_tool.tests import disk_test_agent
koder aka kdanilov1c2b5112015-04-10 16:53:51 +03008from disk_perf_test_tool.tests.io_results_loader import parse_output
koder aka kdanilov2e928022015-04-08 13:47:15 +03009from disk_perf_test_tool.ssh_utils import copy_paths
10from disk_perf_test_tool.utils import run_over_ssh, ssize_to_b
koder aka kdanilov4643fd62015-02-10 16:20:13 -080011
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):
17 self.on_result_cb = on_result_cb
18
koder aka kdanilov4643fd62015-02-10 16:20:13 -080019 def pre_run(self, conn):
20 pass
21
22 @abc.abstractmethod
koder aka kdanilov2c473092015-03-29 17:12:13 +030023 def run(self, conn, barrier):
koder aka kdanilov4643fd62015-02-10 16:20:13 -080024 pass
25
26
Yulia Portnova7ddfa732015-02-24 17:32:58 +020027class TwoScriptTest(IPerfTest):
Yulia Portnova886a2562015-04-07 11:16:13 +030028 def __init__(self, opts, on_result_cb):
Yulia Portnova7ddfa732015-02-24 17:32:58 +020029 super(TwoScriptTest, self).__init__(on_result_cb)
30 self.opts = opts
31 self.pre_run_script = None
32 self.run_script = None
33 self.tmp_dir = "/tmp/"
34 self.set_run_script()
35 self.set_pre_run_script()
36
37 def set_run_script(self):
38 self.pre_run_script = self.opts.pre_run_script
39
40 def set_pre_run_script(self):
41 self.run_script = self.opts.run_script
42
43 def get_remote_for_script(self, script):
44 return os.path.join(self.tmp_dir, script.rpartition('/')[2])
45
46 def copy_script(self, conn, src):
47 remote_path = self.get_remote_for_script(src)
48 copy_paths(conn, {src: remote_path})
49 return remote_path
50
51 def pre_run(self, conn):
52 remote_script = self.copy_script(conn, self.pre_run_script)
53 cmd = remote_script
koder aka kdanilov2c473092015-03-29 17:12:13 +030054 code, out_err = run_over_ssh(conn, cmd)
Yulia Portnova7ddfa732015-02-24 17:32:58 +020055 if code != 0:
koder aka kdanilov2c473092015-03-29 17:12:13 +030056 raise Exception("Pre run failed. %s" % out_err)
Yulia Portnova7ddfa732015-02-24 17:32:58 +020057
koder aka kdanilov2c473092015-03-29 17:12:13 +030058 def run(self, conn, barrier):
Yulia Portnova7ddfa732015-02-24 17:32:58 +020059 remote_script = self.copy_script(conn, self.run_script)
Yulia Portnova886a2562015-04-07 11:16:13 +030060 cmd_opts = ' '.join(["%s %s" % (key, val) for key, val
61 in self.opts.items()])
62 cmd = remote_script + ' ' + cmd_opts
koder aka kdanilov2c473092015-03-29 17:12:13 +030063 code, out_err = run_over_ssh(conn, cmd)
64 self.on_result(code, out_err, cmd)
Yulia Portnova7ddfa732015-02-24 17:32:58 +020065
66 def parse_results(self, out):
67 for line in out.split("\n"):
68 key, separator, value = line.partition(":")
69 if key and value:
70 self.on_result_cb((key, float(value)))
71
koder aka kdanilov2c473092015-03-29 17:12:13 +030072 def on_result(self, code, out_err, cmd):
Yulia Portnova7ddfa732015-02-24 17:32:58 +020073 if 0 == code:
74 try:
koder aka kdanilov2c473092015-03-29 17:12:13 +030075 self.parse_results(out_err)
76 except Exception as exc:
Yulia Portnova7ddfa732015-02-24 17:32:58 +020077 msg_templ = "Error during postprocessing results: {0!r}"
koder aka kdanilov2c473092015-03-29 17:12:13 +030078 raise RuntimeError(msg_templ.format(exc.message))
Yulia Portnova7ddfa732015-02-24 17:32:58 +020079 else:
80 templ = "Command {0!r} failed with code {1}. Error output is:\n{2}"
koder aka kdanilov2c473092015-03-29 17:12:13 +030081 logger.error(templ.format(cmd, code, out_err))
Yulia Portnova7ddfa732015-02-24 17:32:58 +020082
83
84class PgBenchTest(TwoScriptTest):
85
86 def set_run_script(self):
Yulia Portnova886a2562015-04-07 11:16:13 +030087 self.pre_run_script = "tests/postgres/prepare.sh"
Yulia Portnova7ddfa732015-02-24 17:32:58 +020088
89 def set_pre_run_script(self):
Yulia Portnova886a2562015-04-07 11:16:13 +030090 self.run_script = "tests/postgres/run.sh"
Yulia Portnova7ddfa732015-02-24 17:32:58 +020091
92
koder aka kdanilov4643fd62015-02-10 16:20:13 -080093class IOPerfTest(IPerfTest):
koder aka kdanilovda45e882015-04-06 02:24:42 +030094 io_py_remote = "/tmp/disk_test_agent.py"
koder aka kdanilov2c473092015-03-29 17:12:13 +030095
koder aka kdanilov4643fd62015-02-10 16:20:13 -080096 def __init__(self,
koder aka kdanilov2c473092015-03-29 17:12:13 +030097 test_options,
98 on_result_cb):
koder aka kdanilov4643fd62015-02-10 16:20:13 -080099 IPerfTest.__init__(self, on_result_cb)
koder aka kdanilov2c473092015-03-29 17:12:13 +0300100 self.options = test_options
koder aka kdanilovda45e882015-04-06 02:24:42 +0300101 self.config_fname = test_options['cfg']
102 self.config_params = test_options.get('params', {})
103 self.tool = test_options.get('tool', 'fio')
104 self.raw_cfg = open(self.config_fname).read()
koder aka kdanilov50f18642015-02-11 08:54:44 -0800105
koder aka kdanilovda45e882015-04-06 02:24:42 +0300106 parse_func = disk_test_agent.parse_fio_config_full
107 self.configs = parse_func(self.raw_cfg, self.config_params)
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800108
109 def pre_run(self, conn):
koder aka kdanilovda45e882015-04-06 02:24:42 +0300110
111 # TODO: install fio, if not installed
112 run_over_ssh(conn, "apt-get -y install fio")
113
114 local_fname = disk_test_agent.__file__.rsplit('.')[0] + ".py"
koder aka kdanilov2c473092015-03-29 17:12:13 +0300115 self.files_to_copy = {local_fname: self.io_py_remote}
koder aka kdanilov50f18642015-02-11 08:54:44 -0800116 copy_paths(conn, self.files_to_copy)
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800117
koder aka kdanilov2c473092015-03-29 17:12:13 +0300118 cmd_templ = "dd if=/dev/zero of={0} bs={1} count={2}"
119 for secname, params in self.configs:
120 sz = ssize_to_b(params['size'])
121 msz = msz = sz / (1024 ** 2)
122 if sz % (1024 ** 2) != 0:
123 msz += 1
koder aka kdanilov6e2ae792015-03-04 18:02:24 -0800124
koder aka kdanilov2c473092015-03-29 17:12:13 +0300125 cmd = cmd_templ.format(params['filename'], 1024 ** 2, msz)
126 code, out_err = run_over_ssh(conn, cmd)
127
koder aka kdanilov6e2ae792015-03-04 18:02:24 -0800128 if code != 0:
koder aka kdanilov2c473092015-03-29 17:12:13 +0300129 raise RuntimeError("Preparation failed " + out_err)
koder aka kdanilov6e2ae792015-03-04 18:02:24 -0800130
koder aka kdanilov2c473092015-03-29 17:12:13 +0300131 def run(self, conn, barrier):
132 cmd_templ = "env python2 {0} --type {1} --json -"
133 cmd = cmd_templ.format(self.io_py_remote, self.tool)
koder aka kdanilovda45e882015-04-06 02:24:42 +0300134 logger.debug("Run {0}".format(cmd))
koder aka kdanilov2c473092015-03-29 17:12:13 +0300135 try:
koder aka kdanilovda45e882015-04-06 02:24:42 +0300136 barrier.wait()
137 code, out_err = run_over_ssh(conn, cmd, stdin_data=self.raw_cfg)
138 self.on_result(code, out_err, cmd)
koder aka kdanilov2c473092015-03-29 17:12:13 +0300139 finally:
140 barrier.exit()
141
142 def on_result(self, code, out_err, cmd):
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800143 if 0 == code:
144 try:
koder aka kdanilov1c2b5112015-04-10 16:53:51 +0300145 for data in parse_output(out_err):
koder aka kdanilov2e928022015-04-08 13:47:15 +0300146 self.on_result_cb(data)
koder aka kdanilov2c473092015-03-29 17:12:13 +0300147 except Exception as exc:
koder aka kdanilov0f0546c2015-02-17 20:42:05 -0800148 msg_templ = "Error during postprocessing results: {0!r}"
koder aka kdanilov2c473092015-03-29 17:12:13 +0300149 raise RuntimeError(msg_templ.format(exc.message))
koder aka kdanilove21d7472015-02-14 19:02:04 -0800150 else:
koder aka kdanilov2c473092015-03-29 17:12:13 +0300151 templ = "Command {0!r} failed with code {1}. Output is:\n{2}"
152 logger.error(templ.format(cmd, code, out_err))