blob: bc1f8fcaef95c5ee575e1e026a728d915a2ca201 [file] [log] [blame]
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -08001import os
2import sys
3import json
4import time
5import pprint
6import os.path
7import argparse
koder aka kdanilov3f356262015-02-13 08:06:14 -08008import traceback
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -08009
10import io_scenario
11from itest import IOPerfTest
12from log import setlogger
13
14import ssh_runner
15import rally_runner
16
17from starts_vms import nova_connect, create_vms_mt, clear_all
18
19
20def run_io_test(tool,
21 script_args,
22 test_runner,
23 keep_temp_files=False):
24
25 files_dir = os.path.dirname(io_scenario.__file__)
26
27 path = 'iozone' if 'iozone' == tool else 'fio'
28 src_testtool_path = os.path.join(files_dir, path)
29
30 obj = IOPerfTest(script_args,
31 src_testtool_path,
32 None,
33 keep_temp_files)
34
35 return test_runner(obj)
36
37
38def parse_args(argv):
39 parser = argparse.ArgumentParser(
40 description="Run disk io performance test")
41
42 parser.add_argument("tool_type", help="test tool type",
43 choices=['iozone', 'fio'])
44
45 parser.add_argument("-l", dest='extra_logs',
46 action='store_true', default=False,
47 help="print some extra log info")
48
49 parser.add_argument("-o", "--io-opts", dest='io_opts',
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -080050 help="cmd line options for io.py")
51
koder aka kdanilov3f356262015-02-13 08:06:14 -080052 parser.add_argument("-f", "--io-opts-file", dest='io_opts_file',
53 type=argparse.FileType('r'), default=None,
54 help="file with cmd line options for io.py")
55
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -080056 parser.add_argument("-t", "--test-directory", help="directory with test",
57 dest="test_directory", required=True)
58
59 parser.add_argument("--max-preparation-time", default=300,
60 type=int, dest="max_preparation_time")
61
62 parser.add_argument("-k", "--keep", default=False,
63 help="keep temporary files",
64 dest="keep_temp_files", action='store_true')
65
66 parser.add_argument("--runner", required=True,
67 choices=["ssh", "rally"],
68 help="runner type")
69
70 parser.add_argument("--runner-extra-opts", default="",
71 dest="runner_opts", help="runner extra options")
72
73 return parser.parse_args(argv)
74
75
koder aka kdanilov3f356262015-02-13 08:06:14 -080076def print_measurements_stat(res):
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -080077 if len(res) != 0:
78 bw_mean = 0.0
79 for measurement in res:
80 bw_mean += measurement["bw_mean"]
81
82 bw_mean /= len(res)
83
84 it = ((bw_mean - measurement["bw_mean"]) ** 2 for measurement in res)
85 bw_dev = sum(it) ** 0.5
86
87 meta = res[0]['__meta__']
88 key = "{0} {1} {2}k".format(meta['action'],
89 's' if meta['sync'] else 'a',
90 meta['blocksize'])
91
92 print
93 print "====> " + json.dumps({key: (int(bw_mean), int(bw_dev))})
94 print
95 print "=" * 80
96
koder aka kdanilov3f356262015-02-13 08:06:14 -080097
98def get_io_opts(io_opts_file, io_opts):
99 if io_opts_file is not None and io_opts is not None:
100 print "Options --io-opts-file and --io-opts can't be " + \
101 "provided same time"
102 exit(1)
103
104 if io_opts_file is None and io_opts is None:
105 print "Either --io-opts-file or --io-opts should " + \
106 "be provided"
107 exit(1)
108
109 if io_opts_file is not None:
110 io_opts = []
111
112 opt_lines = io_opts_file.readlines()
113 opt_lines = [i for i in opt_lines if i != "" and not i.startswith("#")]
114
115 for opt_line in opt_lines:
116 io_opts.append([opt.strip()
117 for opt in opt_line.split(" ")
118 if opt.strip() != ""])
119 else:
120 io_opts = [[opt.strip()
121 for opt in io_opts.split(" ")
122 if opt.strip() != ""]]
123
124 if len(io_opts) == 0:
125 print "Can't found parameters for io. Check" + \
126 "--io-opts-file or --io-opts options"
127 exit(1)
128
129 return io_opts
130
131
132def main(argv):
133 opts = parse_args(argv)
134
135 if not opts.extra_logs:
136 def nolog(x):
137 pass
138
139 setlogger(nolog)
140
141 io_opts = get_io_opts(opts.io_opts_file, opts.io_opts)
142
143 if opts.runner == "rally":
144 for script_args in io_opts:
145 runner = rally_runner.get_rally_runner(
146 files_dir=os.path.dirname(io_scenario.__file__),
147 rally_extra_opts=opts.runner_opts.split(" "),
148 max_preparation_time=opts.max_preparation_time,
149 keep_temp_files=opts.keep_temp_files)
150
151 res = run_io_test(opts.tool_type,
152 script_args,
153 runner,
154 opts.keep_temp_files)
155
156 print "=" * 80
157 print pprint.pformat(res)
158 print "=" * 80
159
160 print_measurements_stat(res)
161
162 elif opts.runner == "ssh":
163 create_vms_opts = {}
164 for opt in opts.runner_opts.split(","):
165 name, val = opt.split("=", 1)
166 create_vms_opts[name] = val
167
168 user = create_vms_opts.pop("user")
169 key_file = create_vms_opts.pop("key_file")
170 aff_group = create_vms_opts.pop("aff_group", None)
171 raw_count = create_vms_opts.pop("count", "x1")
172
173 if raw_count.startswith("x"):
174 raise NotImplementedError("xXXXX count not implemented yet")
175 else:
176 count = int(raw_count)
177
178 if aff_group is not None:
179 scheduler_hints = {'group': aff_group}
180 else:
181 scheduler_hints = None
182
183 create_vms_opts['scheduler_hints'] = scheduler_hints
184
185 latest_start_time = opts.max_preparation_time + time.time()
186
187 nova = nova_connect()
188
189 # nova, amount, keypair_name, img_name,
190 # flavor_name, vol_sz=None, network_zone_name=None,
191 # flt_ip_pool=None, name_templ='ceph-test-{}',
192 # scheduler_hints=None
193
194 try:
195 ips = [i[0] for i in create_vms_mt(nova, count, **create_vms_opts)]
196
197 uris = ["{0}@{1}::{2}".format(user, ip, key_file) for ip in ips]
198
199 for script_args in io_opts:
200 runner = ssh_runner.get_ssh_runner(uris,
201 latest_start_time,
202 opts.keep_temp_files)
203 res = run_io_test(opts.tool_type,
204 script_args,
205 runner,
206 opts.keep_temp_files)
207 print "=" * 80
208 print pprint.pformat(res)
209 print "=" * 80
210
211 print_measurements_stat(res)
212 except:
213 traceback.print_exc()
214 finally:
215 clear_all(nova)
216
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -0800217 return 0
218
219
220ostack_prepare = """
221glance image-create --name 'ubuntu' --disk-format qcow2
222--container-format bare --is-public true --copy-from
223https://cloud-images.ubuntu.com/trusty/current/trusty-server-cloudimg-amd64-disk1.img
224
225nova flavor-create ceph.512 ceph.512 512 50 1
226nova server-group-create --policy anti-affinity ceph
227"""
228
229
230if __name__ == '__main__':
231 exit(main(sys.argv[1:]))