blob: b073879f3b2f8c1985097b441bb001fa78107cb3 [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
8from disk_perf_test_tool.ssh_utils import copy_paths
9from disk_perf_test_tool.utils import run_over_ssh, ssize_to_b
koder aka kdanilov4643fd62015-02-10 16:20:13 -080010
koder aka kdanilove21d7472015-02-14 19:02:04 -080011logger = logging.getLogger("io-perf-tool")
12
13
koder aka kdanilov4643fd62015-02-10 16:20:13 -080014class IPerfTest(object):
15 def __init__(self, on_result_cb):
16 self.on_result_cb = on_result_cb
17
koder aka kdanilov4643fd62015-02-10 16:20:13 -080018 def pre_run(self, conn):
19 pass
20
21 @abc.abstractmethod
koder aka kdanilov2c473092015-03-29 17:12:13 +030022 def run(self, conn, barrier):
koder aka kdanilov4643fd62015-02-10 16:20:13 -080023 pass
24
25
Yulia Portnova7ddfa732015-02-24 17:32:58 +020026class TwoScriptTest(IPerfTest):
Yulia Portnova886a2562015-04-07 11:16:13 +030027 def __init__(self, opts, on_result_cb):
Yulia Portnova7ddfa732015-02-24 17:32:58 +020028 super(TwoScriptTest, self).__init__(on_result_cb)
29 self.opts = opts
30 self.pre_run_script = None
31 self.run_script = None
32 self.tmp_dir = "/tmp/"
33 self.set_run_script()
34 self.set_pre_run_script()
35
36 def set_run_script(self):
37 self.pre_run_script = self.opts.pre_run_script
38
39 def set_pre_run_script(self):
40 self.run_script = self.opts.run_script
41
42 def get_remote_for_script(self, script):
43 return os.path.join(self.tmp_dir, script.rpartition('/')[2])
44
45 def copy_script(self, conn, src):
46 remote_path = self.get_remote_for_script(src)
47 copy_paths(conn, {src: remote_path})
48 return remote_path
49
50 def pre_run(self, conn):
51 remote_script = self.copy_script(conn, self.pre_run_script)
52 cmd = remote_script
koder aka kdanilov2c473092015-03-29 17:12:13 +030053 code, out_err = run_over_ssh(conn, cmd)
Yulia Portnova7ddfa732015-02-24 17:32:58 +020054 if code != 0:
koder aka kdanilov2c473092015-03-29 17:12:13 +030055 raise Exception("Pre run failed. %s" % out_err)
Yulia Portnova7ddfa732015-02-24 17:32:58 +020056
koder aka kdanilov2c473092015-03-29 17:12:13 +030057 def run(self, conn, barrier):
Yulia Portnova7ddfa732015-02-24 17:32:58 +020058 remote_script = self.copy_script(conn, self.run_script)
Yulia Portnova886a2562015-04-07 11:16:13 +030059 cmd_opts = ' '.join(["%s %s" % (key, val) for key, val
60 in self.opts.items()])
61 cmd = remote_script + ' ' + cmd_opts
koder aka kdanilov2c473092015-03-29 17:12:13 +030062 code, out_err = run_over_ssh(conn, cmd)
63 self.on_result(code, out_err, cmd)
Yulia Portnova7ddfa732015-02-24 17:32:58 +020064
65 def parse_results(self, out):
66 for line in out.split("\n"):
67 key, separator, value = line.partition(":")
68 if key and value:
69 self.on_result_cb((key, float(value)))
70
koder aka kdanilov2c473092015-03-29 17:12:13 +030071 def on_result(self, code, out_err, cmd):
Yulia Portnova7ddfa732015-02-24 17:32:58 +020072 if 0 == code:
73 try:
koder aka kdanilov2c473092015-03-29 17:12:13 +030074 self.parse_results(out_err)
75 except Exception as exc:
Yulia Portnova7ddfa732015-02-24 17:32:58 +020076 msg_templ = "Error during postprocessing results: {0!r}"
koder aka kdanilov2c473092015-03-29 17:12:13 +030077 raise RuntimeError(msg_templ.format(exc.message))
Yulia Portnova7ddfa732015-02-24 17:32:58 +020078 else:
79 templ = "Command {0!r} failed with code {1}. Error output is:\n{2}"
koder aka kdanilov2c473092015-03-29 17:12:13 +030080 logger.error(templ.format(cmd, code, out_err))
Yulia Portnova7ddfa732015-02-24 17:32:58 +020081
82
83class PgBenchTest(TwoScriptTest):
84
85 def set_run_script(self):
Yulia Portnova886a2562015-04-07 11:16:13 +030086 self.pre_run_script = "tests/postgres/prepare.sh"
Yulia Portnova7ddfa732015-02-24 17:32:58 +020087
88 def set_pre_run_script(self):
Yulia Portnova886a2562015-04-07 11:16:13 +030089 self.run_script = "tests/postgres/run.sh"
Yulia Portnova7ddfa732015-02-24 17:32:58 +020090
91
koder aka kdanilov4643fd62015-02-10 16:20:13 -080092class IOPerfTest(IPerfTest):
koder aka kdanilovda45e882015-04-06 02:24:42 +030093 io_py_remote = "/tmp/disk_test_agent.py"
koder aka kdanilov2c473092015-03-29 17:12:13 +030094
koder aka kdanilov4643fd62015-02-10 16:20:13 -080095 def __init__(self,
koder aka kdanilov2c473092015-03-29 17:12:13 +030096 test_options,
97 on_result_cb):
koder aka kdanilov4643fd62015-02-10 16:20:13 -080098 IPerfTest.__init__(self, on_result_cb)
koder aka kdanilov2c473092015-03-29 17:12:13 +030099 self.options = test_options
koder aka kdanilovda45e882015-04-06 02:24:42 +0300100 self.config_fname = test_options['cfg']
101 self.config_params = test_options.get('params', {})
102 self.tool = test_options.get('tool', 'fio')
103 self.raw_cfg = open(self.config_fname).read()
koder aka kdanilov50f18642015-02-11 08:54:44 -0800104
koder aka kdanilovda45e882015-04-06 02:24:42 +0300105 parse_func = disk_test_agent.parse_fio_config_full
106 self.configs = parse_func(self.raw_cfg, self.config_params)
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800107
108 def pre_run(self, conn):
koder aka kdanilovda45e882015-04-06 02:24:42 +0300109
110 # TODO: install fio, if not installed
111 run_over_ssh(conn, "apt-get -y install fio")
112
113 local_fname = disk_test_agent.__file__.rsplit('.')[0] + ".py"
koder aka kdanilov2c473092015-03-29 17:12:13 +0300114 self.files_to_copy = {local_fname: self.io_py_remote}
koder aka kdanilov50f18642015-02-11 08:54:44 -0800115 copy_paths(conn, self.files_to_copy)
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800116
koder aka kdanilov2c473092015-03-29 17:12:13 +0300117 cmd_templ = "dd if=/dev/zero of={0} bs={1} count={2}"
118 for secname, params in self.configs:
119 sz = ssize_to_b(params['size'])
120 msz = msz = sz / (1024 ** 2)
121 if sz % (1024 ** 2) != 0:
122 msz += 1
koder aka kdanilov6e2ae792015-03-04 18:02:24 -0800123
koder aka kdanilov2c473092015-03-29 17:12:13 +0300124 cmd = cmd_templ.format(params['filename'], 1024 ** 2, msz)
125 code, out_err = run_over_ssh(conn, cmd)
126
koder aka kdanilov6e2ae792015-03-04 18:02:24 -0800127 if code != 0:
koder aka kdanilov2c473092015-03-29 17:12:13 +0300128 raise RuntimeError("Preparation failed " + out_err)
koder aka kdanilov6e2ae792015-03-04 18:02:24 -0800129
koder aka kdanilov2c473092015-03-29 17:12:13 +0300130 def run(self, conn, barrier):
131 cmd_templ = "env python2 {0} --type {1} --json -"
132 cmd = cmd_templ.format(self.io_py_remote, self.tool)
koder aka kdanilovda45e882015-04-06 02:24:42 +0300133 logger.debug("Run {0}".format(cmd))
koder aka kdanilov2c473092015-03-29 17:12:13 +0300134 try:
koder aka kdanilovda45e882015-04-06 02:24:42 +0300135 barrier.wait()
136 code, out_err = run_over_ssh(conn, cmd, stdin_data=self.raw_cfg)
137 self.on_result(code, out_err, cmd)
koder aka kdanilov2c473092015-03-29 17:12:13 +0300138 finally:
139 barrier.exit()
140
141 def on_result(self, code, out_err, cmd):
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800142 if 0 == code:
143 try:
koder aka kdanilov2e928022015-04-08 13:47:15 +0300144 for data in disk_test_agent.parse_output(out_err):
145 self.on_result_cb(data)
koder aka kdanilov2c473092015-03-29 17:12:13 +0300146 except Exception as exc:
koder aka kdanilov0f0546c2015-02-17 20:42:05 -0800147 msg_templ = "Error during postprocessing results: {0!r}"
koder aka kdanilov2c473092015-03-29 17:12:13 +0300148 raise RuntimeError(msg_templ.format(exc.message))
koder aka kdanilove21d7472015-02-14 19:02:04 -0800149 else:
koder aka kdanilov2c473092015-03-29 17:12:13 +0300150 templ = "Command {0!r} failed with code {1}. Output is:\n{2}"
151 logger.error(templ.format(cmd, code, out_err))