blob: 2f09ef83b17c82b0a037fb24cb8f50410822539b [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
gstepanov8053b012015-02-16 17:25:27 +020013from rest_api import add_test
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -080014
15import ssh_runner
koder aka kdanilov7dec9df2015-02-15 21:35:19 -080016
17try:
18 import rally_runner
19except ImportError:
20 rally_runner = None
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -080021
22from starts_vms import nova_connect, create_vms_mt, clear_all
23
24
koder aka kdanilove21d7472015-02-14 19:02:04 -080025logger = logging.getLogger("io-perf-tool")
26logger.setLevel(logging.DEBUG)
27ch = logging.StreamHandler()
28ch.setLevel(logging.DEBUG)
29logger.addHandler(ch)
30
31log_format = '%(asctime)s - %(levelname)s - %(name)s - %(message)s'
32formatter = logging.Formatter(log_format,
33 "%H:%M:%S")
34ch.setFormatter(formatter)
35
36
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -080037def run_io_test(tool,
38 script_args,
39 test_runner,
40 keep_temp_files=False):
41
42 files_dir = os.path.dirname(io_scenario.__file__)
43
44 path = 'iozone' if 'iozone' == tool else 'fio'
45 src_testtool_path = os.path.join(files_dir, path)
46
47 obj = IOPerfTest(script_args,
48 src_testtool_path,
49 None,
50 keep_temp_files)
51
52 return test_runner(obj)
53
54
55def parse_args(argv):
56 parser = argparse.ArgumentParser(
57 description="Run disk io performance test")
58
59 parser.add_argument("tool_type", help="test tool type",
60 choices=['iozone', 'fio'])
61
62 parser.add_argument("-l", dest='extra_logs',
63 action='store_true', default=False,
64 help="print some extra log info")
65
66 parser.add_argument("-o", "--io-opts", dest='io_opts',
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -080067 help="cmd line options for io.py")
68
koder aka kdanilov3f356262015-02-13 08:06:14 -080069 parser.add_argument("-f", "--io-opts-file", dest='io_opts_file',
70 type=argparse.FileType('r'), default=None,
71 help="file with cmd line options for io.py")
72
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -080073 parser.add_argument("-t", "--test-directory", help="directory with test",
74 dest="test_directory", required=True)
75
76 parser.add_argument("--max-preparation-time", default=300,
77 type=int, dest="max_preparation_time")
78
gstepanov8053b012015-02-16 17:25:27 +020079 parser.add_argument("-b", "--build-info", default=None,
80 dest="build_name")
81
82 parser.add_argument("-d", "--data-server-url", default=None,
83 dest="data_server_url")
84
85 parser.add_argument("-n", "--lab-name", default=None,
86 dest="lab_name")
87
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -080088 parser.add_argument("-k", "--keep", default=False,
89 help="keep temporary files",
90 dest="keep_temp_files", action='store_true')
91
koder aka kdanilov7dec9df2015-02-15 21:35:19 -080092 choices = ["ssh"]
93 if rally_runner is not None:
94 choices.append("rally")
95
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -080096 parser.add_argument("--runner", required=True,
koder aka kdanilov7dec9df2015-02-15 21:35:19 -080097 choices=choices, help="runner type")
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -080098
99 parser.add_argument("--runner-extra-opts", default="",
100 dest="runner_opts", help="runner extra options")
101
102 return parser.parse_args(argv)
103
104
koder aka kdanilove21d7472015-02-14 19:02:04 -0800105def format_measurements_stat(res):
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -0800106 if len(res) != 0:
107 bw_mean = 0.0
108 for measurement in res:
109 bw_mean += measurement["bw_mean"]
110
111 bw_mean /= len(res)
112
113 it = ((bw_mean - measurement["bw_mean"]) ** 2 for measurement in res)
114 bw_dev = sum(it) ** 0.5
115
116 meta = res[0]['__meta__']
koder aka kdanilov7dec9df2015-02-15 21:35:19 -0800117
118 sync = meta['sync']
119 direct = meta['direct_io']
120
121 if sync and direct:
122 ss = "d+"
123 elif sync:
124 ss = "s"
125 elif direct:
126 ss = "d"
127 else:
128 ss = "a"
129
130 key = "{0} {1} {2} {3}k".format(meta['action'], ss,
131 meta['concurence'],
132 meta['blocksize'])
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -0800133
koder aka kdanilove21d7472015-02-14 19:02:04 -0800134 data = json.dumps({key: (int(bw_mean), int(bw_dev))})
135
gstepanov8053b012015-02-16 17:25:27 +0200136 return data
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -0800137
koder aka kdanilov3f356262015-02-13 08:06:14 -0800138
139def get_io_opts(io_opts_file, io_opts):
140 if io_opts_file is not None and io_opts is not None:
141 print "Options --io-opts-file and --io-opts can't be " + \
142 "provided same time"
143 exit(1)
144
145 if io_opts_file is None and io_opts is None:
146 print "Either --io-opts-file or --io-opts should " + \
147 "be provided"
148 exit(1)
149
150 if io_opts_file is not None:
151 io_opts = []
152
153 opt_lines = io_opts_file.readlines()
154 opt_lines = [i for i in opt_lines if i != "" and not i.startswith("#")]
155
156 for opt_line in opt_lines:
koder aka kdanilove21d7472015-02-14 19:02:04 -0800157 if opt_line.strip() != "":
158 io_opts.append([opt.strip()
159 for opt in opt_line.strip().split(" ")
160 if opt.strip() != ""])
koder aka kdanilov3f356262015-02-13 08:06:14 -0800161 else:
162 io_opts = [[opt.strip()
163 for opt in io_opts.split(" ")
164 if opt.strip() != ""]]
165
166 if len(io_opts) == 0:
167 print "Can't found parameters for io. Check" + \
168 "--io-opts-file or --io-opts options"
169 exit(1)
170
171 return io_opts
172
173
koder aka kdanilove21d7472015-02-14 19:02:04 -0800174def format_result(res):
175 data = "\n{0}\n".format("=" * 80)
176 data += pprint.pformat(res) + "\n"
177 data += "{0}\n".format("=" * 80)
koder aka kdanilovfe056622015-02-19 08:46:15 -0800178 templ = "{0}\n\n====> {1}\n\n{2}\n\n"
179 return templ.format(data, format_measurements_stat(res), "=" * 80)
koder aka kdanilove21d7472015-02-14 19:02:04 -0800180
181
koder aka kdanilov3f356262015-02-13 08:06:14 -0800182def main(argv):
183 opts = parse_args(argv)
184
185 if not opts.extra_logs:
186 def nolog(x):
187 pass
188
koder aka kdanilov3f356262015-02-13 08:06:14 -0800189 io_opts = get_io_opts(opts.io_opts_file, opts.io_opts)
gstepanov8053b012015-02-16 17:25:27 +0200190 data_server_url = opts.data_server_url
koder aka kdanilovfe056622015-02-19 08:46:15 -0800191 # lab_name = opts.lab_name
gstepanov8053b012015-02-16 17:25:27 +0200192 build_name = opts.build_name
koder aka kdanilov3f356262015-02-13 08:06:14 -0800193
194 if opts.runner == "rally":
koder aka kdanilove21d7472015-02-14 19:02:04 -0800195 logger.debug("Use rally runner")
koder aka kdanilov3f356262015-02-13 08:06:14 -0800196 for script_args in io_opts:
koder aka kdanilove21d7472015-02-14 19:02:04 -0800197
198 cmd_line = " ".join(script_args)
199 logger.debug("Run test with {0!r} params".format(cmd_line))
200
koder aka kdanilov3f356262015-02-13 08:06:14 -0800201 runner = rally_runner.get_rally_runner(
202 files_dir=os.path.dirname(io_scenario.__file__),
203 rally_extra_opts=opts.runner_opts.split(" "),
204 max_preparation_time=opts.max_preparation_time,
205 keep_temp_files=opts.keep_temp_files)
206
207 res = run_io_test(opts.tool_type,
208 script_args,
209 runner,
210 opts.keep_temp_files)
koder aka kdanilove21d7472015-02-14 19:02:04 -0800211 logger.debug(format_result(res))
koder aka kdanilov3f356262015-02-13 08:06:14 -0800212
213 elif opts.runner == "ssh":
koder aka kdanilove21d7472015-02-14 19:02:04 -0800214 logger.debug("Use ssh runner")
koder aka kdanilov3f356262015-02-13 08:06:14 -0800215 create_vms_opts = {}
216 for opt in opts.runner_opts.split(","):
217 name, val = opt.split("=", 1)
218 create_vms_opts[name] = val
219
220 user = create_vms_opts.pop("user")
221 key_file = create_vms_opts.pop("key_file")
222 aff_group = create_vms_opts.pop("aff_group", None)
223 raw_count = create_vms_opts.pop("count", "x1")
224
koder aka kdanilove21d7472015-02-14 19:02:04 -0800225 logger.debug("Connection to nova")
koder aka kdanilovec530332015-02-13 11:12:53 -0800226 nova = nova_connect()
227
koder aka kdanilov3f356262015-02-13 08:06:14 -0800228 if raw_count.startswith("x"):
koder aka kdanilove21d7472015-02-14 19:02:04 -0800229 logger.debug("Getting amount of compute services")
koder aka kdanilovec530332015-02-13 11:12:53 -0800230 count = len(nova.services.list(binary="nova-compute"))
koder aka kdanilove21d7472015-02-14 19:02:04 -0800231 count *= int(raw_count[1:])
koder aka kdanilov3f356262015-02-13 08:06:14 -0800232 else:
233 count = int(raw_count)
234
235 if aff_group is not None:
236 scheduler_hints = {'group': aff_group}
237 else:
238 scheduler_hints = None
239
240 create_vms_opts['scheduler_hints'] = scheduler_hints
241
koder aka kdanilov3f356262015-02-13 08:06:14 -0800242 # nova, amount, keypair_name, img_name,
243 # flavor_name, vol_sz=None, network_zone_name=None,
koder aka kdanilov7dec9df2015-02-15 21:35:19 -0800244 # flt_ip_pool=None, name_templ='ceph-test-{0}',
koder aka kdanilov3f356262015-02-13 08:06:14 -0800245 # scheduler_hints=None
246
koder aka kdanilov7dec9df2015-02-15 21:35:19 -0800247 logger.debug("Will start {0} vms".format(count))
koder aka kdanilove21d7472015-02-14 19:02:04 -0800248
koder aka kdanilov3f356262015-02-13 08:06:14 -0800249 try:
250 ips = [i[0] for i in create_vms_mt(nova, count, **create_vms_opts)]
251
252 uris = ["{0}@{1}::{2}".format(user, ip, key_file) for ip in ips]
253
254 for script_args in io_opts:
koder aka kdanilove21d7472015-02-14 19:02:04 -0800255 cmd_line = " ".join(script_args)
256 logger.debug("Run test with {0!r} params".format(cmd_line))
257 latest_start_time = opts.max_preparation_time + time.time()
koder aka kdanilov3f356262015-02-13 08:06:14 -0800258 runner = ssh_runner.get_ssh_runner(uris,
259 latest_start_time,
260 opts.keep_temp_files)
261 res = run_io_test(opts.tool_type,
262 script_args,
263 runner,
264 opts.keep_temp_files)
koder aka kdanilove21d7472015-02-14 19:02:04 -0800265 logger.debug(format_result(res))
koder aka kdanilov3f356262015-02-13 08:06:14 -0800266
koder aka kdanilov3f356262015-02-13 08:06:14 -0800267 except:
268 traceback.print_exc()
269 finally:
koder aka kdanilove21d7472015-02-14 19:02:04 -0800270 logger.debug("Clearing")
koder aka kdanilov3f356262015-02-13 08:06:14 -0800271 clear_all(nova)
272
gstepanov8053b012015-02-16 17:25:27 +0200273 result = json.loads(format_measurements_stat(res))
274 result['name'] = build_name
275 add_test(build_name, result, data_server_url)
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -0800276 return 0
277
278
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -0800279if __name__ == '__main__':
280 exit(main(sys.argv[1:]))