blob: ad0c9d20b918b1a6ca794b198a7018acc840a8e6 [file] [log] [blame]
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -08001import os
2import sys
3import json
4import time
5import pprint
koder aka kdanilove21d7472015-02-14 19:02:04 -08006import logging
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -08007import os.path
8import argparse
koder aka kdanilov3f356262015-02-13 08:06:14 -08009import traceback
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -080010
11import io_scenario
12from itest import IOPerfTest
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -080013
14import ssh_runner
koder aka kdanilov7dec9df2015-02-15 21:35:19 -080015
16try:
17 import rally_runner
18except ImportError:
19 rally_runner = None
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -080020
21from starts_vms import nova_connect, create_vms_mt, clear_all
22
23
koder aka kdanilove21d7472015-02-14 19:02:04 -080024logger = logging.getLogger("io-perf-tool")
25logger.setLevel(logging.DEBUG)
26ch = logging.StreamHandler()
27ch.setLevel(logging.DEBUG)
28logger.addHandler(ch)
29
30log_format = '%(asctime)s - %(levelname)s - %(name)s - %(message)s'
31formatter = logging.Formatter(log_format,
32 "%H:%M:%S")
33ch.setFormatter(formatter)
34
35
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -080036def run_io_test(tool,
37 script_args,
38 test_runner,
39 keep_temp_files=False):
40
41 files_dir = os.path.dirname(io_scenario.__file__)
42
43 path = 'iozone' if 'iozone' == tool else 'fio'
44 src_testtool_path = os.path.join(files_dir, path)
45
46 obj = IOPerfTest(script_args,
47 src_testtool_path,
48 None,
49 keep_temp_files)
50
51 return test_runner(obj)
52
53
54def parse_args(argv):
55 parser = argparse.ArgumentParser(
56 description="Run disk io performance test")
57
58 parser.add_argument("tool_type", help="test tool type",
59 choices=['iozone', 'fio'])
60
61 parser.add_argument("-l", dest='extra_logs',
62 action='store_true', default=False,
63 help="print some extra log info")
64
65 parser.add_argument("-o", "--io-opts", dest='io_opts',
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -080066 help="cmd line options for io.py")
67
koder aka kdanilov3f356262015-02-13 08:06:14 -080068 parser.add_argument("-f", "--io-opts-file", dest='io_opts_file',
69 type=argparse.FileType('r'), default=None,
70 help="file with cmd line options for io.py")
71
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -080072 parser.add_argument("-t", "--test-directory", help="directory with test",
73 dest="test_directory", required=True)
74
75 parser.add_argument("--max-preparation-time", default=300,
76 type=int, dest="max_preparation_time")
77
78 parser.add_argument("-k", "--keep", default=False,
79 help="keep temporary files",
80 dest="keep_temp_files", action='store_true')
81
koder aka kdanilov7dec9df2015-02-15 21:35:19 -080082 choices = ["ssh"]
83 if rally_runner is not None:
84 choices.append("rally")
85
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -080086 parser.add_argument("--runner", required=True,
koder aka kdanilov7dec9df2015-02-15 21:35:19 -080087 choices=choices, help="runner type")
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -080088
89 parser.add_argument("--runner-extra-opts", default="",
90 dest="runner_opts", help="runner extra options")
91
92 return parser.parse_args(argv)
93
94
koder aka kdanilove21d7472015-02-14 19:02:04 -080095def format_measurements_stat(res):
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -080096 if len(res) != 0:
97 bw_mean = 0.0
98 for measurement in res:
99 bw_mean += measurement["bw_mean"]
100
101 bw_mean /= len(res)
102
103 it = ((bw_mean - measurement["bw_mean"]) ** 2 for measurement in res)
104 bw_dev = sum(it) ** 0.5
105
106 meta = res[0]['__meta__']
koder aka kdanilov7dec9df2015-02-15 21:35:19 -0800107
108 sync = meta['sync']
109 direct = meta['direct_io']
110
111 if sync and direct:
112 ss = "d+"
113 elif sync:
114 ss = "s"
115 elif direct:
116 ss = "d"
117 else:
118 ss = "a"
119
120 key = "{0} {1} {2} {3}k".format(meta['action'], ss,
121 meta['concurence'],
122 meta['blocksize'])
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -0800123
koder aka kdanilove21d7472015-02-14 19:02:04 -0800124 data = json.dumps({key: (int(bw_mean), int(bw_dev))})
125
126 return "\n====> {0}\n\n{1}\n".format(data, "=" * 80)
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -0800127
koder aka kdanilov3f356262015-02-13 08:06:14 -0800128
129def get_io_opts(io_opts_file, io_opts):
130 if io_opts_file is not None and io_opts is not None:
131 print "Options --io-opts-file and --io-opts can't be " + \
132 "provided same time"
133 exit(1)
134
135 if io_opts_file is None and io_opts is None:
136 print "Either --io-opts-file or --io-opts should " + \
137 "be provided"
138 exit(1)
139
140 if io_opts_file is not None:
141 io_opts = []
142
143 opt_lines = io_opts_file.readlines()
144 opt_lines = [i for i in opt_lines if i != "" and not i.startswith("#")]
145
146 for opt_line in opt_lines:
koder aka kdanilove21d7472015-02-14 19:02:04 -0800147 if opt_line.strip() != "":
148 io_opts.append([opt.strip()
149 for opt in opt_line.strip().split(" ")
150 if opt.strip() != ""])
koder aka kdanilov3f356262015-02-13 08:06:14 -0800151 else:
152 io_opts = [[opt.strip()
153 for opt in io_opts.split(" ")
154 if opt.strip() != ""]]
155
156 if len(io_opts) == 0:
157 print "Can't found parameters for io. Check" + \
158 "--io-opts-file or --io-opts options"
159 exit(1)
160
161 return io_opts
162
163
koder aka kdanilove21d7472015-02-14 19:02:04 -0800164def format_result(res):
165 data = "\n{0}\n".format("=" * 80)
166 data += pprint.pformat(res) + "\n"
167 data += "{0}\n".format("=" * 80)
168 return data + "\n" + format_measurements_stat(res) + "\n"
169
170
koder aka kdanilov3f356262015-02-13 08:06:14 -0800171def main(argv):
172 opts = parse_args(argv)
173
174 if not opts.extra_logs:
175 def nolog(x):
176 pass
177
koder aka kdanilov3f356262015-02-13 08:06:14 -0800178 io_opts = get_io_opts(opts.io_opts_file, opts.io_opts)
179
180 if opts.runner == "rally":
koder aka kdanilove21d7472015-02-14 19:02:04 -0800181 logger.debug("Use rally runner")
koder aka kdanilov3f356262015-02-13 08:06:14 -0800182 for script_args in io_opts:
koder aka kdanilove21d7472015-02-14 19:02:04 -0800183
184 cmd_line = " ".join(script_args)
185 logger.debug("Run test with {0!r} params".format(cmd_line))
186
koder aka kdanilov3f356262015-02-13 08:06:14 -0800187 runner = rally_runner.get_rally_runner(
188 files_dir=os.path.dirname(io_scenario.__file__),
189 rally_extra_opts=opts.runner_opts.split(" "),
190 max_preparation_time=opts.max_preparation_time,
191 keep_temp_files=opts.keep_temp_files)
192
193 res = run_io_test(opts.tool_type,
194 script_args,
195 runner,
196 opts.keep_temp_files)
koder aka kdanilove21d7472015-02-14 19:02:04 -0800197 logger.debug(format_result(res))
koder aka kdanilov3f356262015-02-13 08:06:14 -0800198
199 elif opts.runner == "ssh":
koder aka kdanilove21d7472015-02-14 19:02:04 -0800200 logger.debug("Use ssh runner")
koder aka kdanilov3f356262015-02-13 08:06:14 -0800201 create_vms_opts = {}
202 for opt in opts.runner_opts.split(","):
203 name, val = opt.split("=", 1)
204 create_vms_opts[name] = val
205
206 user = create_vms_opts.pop("user")
207 key_file = create_vms_opts.pop("key_file")
208 aff_group = create_vms_opts.pop("aff_group", None)
209 raw_count = create_vms_opts.pop("count", "x1")
210
koder aka kdanilove21d7472015-02-14 19:02:04 -0800211 logger.debug("Connection to nova")
koder aka kdanilovec530332015-02-13 11:12:53 -0800212 nova = nova_connect()
213
koder aka kdanilov3f356262015-02-13 08:06:14 -0800214 if raw_count.startswith("x"):
koder aka kdanilove21d7472015-02-14 19:02:04 -0800215 logger.debug("Getting amount of compute services")
koder aka kdanilovec530332015-02-13 11:12:53 -0800216 count = len(nova.services.list(binary="nova-compute"))
koder aka kdanilove21d7472015-02-14 19:02:04 -0800217 count *= int(raw_count[1:])
koder aka kdanilov3f356262015-02-13 08:06:14 -0800218 else:
219 count = int(raw_count)
220
221 if aff_group is not None:
222 scheduler_hints = {'group': aff_group}
223 else:
224 scheduler_hints = None
225
226 create_vms_opts['scheduler_hints'] = scheduler_hints
227
koder aka kdanilov3f356262015-02-13 08:06:14 -0800228 # nova, amount, keypair_name, img_name,
229 # flavor_name, vol_sz=None, network_zone_name=None,
koder aka kdanilov7dec9df2015-02-15 21:35:19 -0800230 # flt_ip_pool=None, name_templ='ceph-test-{0}',
koder aka kdanilov3f356262015-02-13 08:06:14 -0800231 # scheduler_hints=None
232
koder aka kdanilov7dec9df2015-02-15 21:35:19 -0800233 logger.debug("Will start {0} vms".format(count))
koder aka kdanilove21d7472015-02-14 19:02:04 -0800234
koder aka kdanilov3f356262015-02-13 08:06:14 -0800235 try:
236 ips = [i[0] for i in create_vms_mt(nova, count, **create_vms_opts)]
237
238 uris = ["{0}@{1}::{2}".format(user, ip, key_file) for ip in ips]
239
240 for script_args in io_opts:
koder aka kdanilove21d7472015-02-14 19:02:04 -0800241 cmd_line = " ".join(script_args)
242 logger.debug("Run test with {0!r} params".format(cmd_line))
243 latest_start_time = opts.max_preparation_time + time.time()
koder aka kdanilov3f356262015-02-13 08:06:14 -0800244 runner = ssh_runner.get_ssh_runner(uris,
245 latest_start_time,
246 opts.keep_temp_files)
247 res = run_io_test(opts.tool_type,
248 script_args,
249 runner,
250 opts.keep_temp_files)
koder aka kdanilove21d7472015-02-14 19:02:04 -0800251 logger.debug(format_result(res))
koder aka kdanilov3f356262015-02-13 08:06:14 -0800252
koder aka kdanilov3f356262015-02-13 08:06:14 -0800253 except:
254 traceback.print_exc()
255 finally:
koder aka kdanilove21d7472015-02-14 19:02:04 -0800256 logger.debug("Clearing")
koder aka kdanilov3f356262015-02-13 08:06:14 -0800257 clear_all(nova)
258
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -0800259 return 0
260
261
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -0800262if __name__ == '__main__':
263 exit(main(sys.argv[1:]))