]> git.proxmox.com Git - ceph.git/blob - ceph/src/spdk/test/vhost/fiotest/run_fio.py
bump version to 12.2.12-pve1
[ceph.git] / ceph / src / spdk / test / vhost / fiotest / run_fio.py
1 #!/usr/bin/env python
2
3 import os
4 import sys
5 import getopt
6 import subprocess
7 import signal
8 import re
9
10 fio_bin = "fio"
11
12
13 def show_help():
14 print("""Usage: python run_fio.py [options] [args]
15 Args:
16 [VMs] (ex. vm1_IP:vm1_port:vm1_disk1:vm_disk2,vm2_IP:vm2_port:vm2_disk1,etc...)
17 Options:
18 -h, --help Show this message.
19 -j, --job-files Paths to files with custom FIO jobs configuration.
20 -f, --fio-bin Location of FIO binary (Default "fio")
21 -o, --out Directory used to save generated job files and
22 files with test results (Default: same dir where
23 this script is located)
24 -p, --perf-vmex Enable aggregating statistic for VMEXITS for VMs
25 """)
26
27
28 def exec_cmd(cmd, blocking):
29 # Print result to STDOUT for now, we don't have json support yet.
30 p = subprocess.Popen(cmd.split(" "), stdout=subprocess.PIPE,
31 stderr=subprocess.STDOUT, stdin=subprocess.PIPE)
32 if blocking is True:
33 out, _ = p.communicate()
34 return p.returncode, out
35 return p
36
37
38 def save_file(path, mode, contents):
39 with open(path, mode) as fh:
40 fh.write(contents)
41 fh.close()
42
43
44 def run_fio(vms, fio_cfg_fname, out_path, perf_vmex=False):
45 global fio_bin
46 fio_cfg_prefix = fio_cfg_fname.split(".")[0]
47
48 # Build command for FIO
49 fio_cmd = " ".join([fio_bin, "--eta=never"])
50 for vm in vms:
51 # vm[0] = IP address, vm[1] = Port number
52 fio_cmd = " ".join([fio_cmd,
53 "--client={vm_ip},{vm_port}".format(vm_ip=vm[0], vm_port=vm[1]),
54 "--remote-config /root/{cfg}".format(cfg=fio_cfg_fname)])
55 print(fio_cmd)
56
57 if perf_vmex:
58 perf_dir = os.path.join(out_path, "perf_stats")
59 try:
60 os.mkdir(perf_dir)
61 except OSError:
62 pass
63
64 # Start gathering perf statistics for host and VM guests
65 perf_rec_file = os.path.join(perf_dir, "perf.data.kvm")
66 perf_run_cmd = "perf kvm --host --guest " + \
67 "-o {0} stat record -a".format(perf_rec_file)
68 print(perf_run_cmd)
69 perf_p = exec_cmd(perf_run_cmd, blocking=False)
70
71 # Run FIO test on VMs
72 rc, out = exec_cmd(fio_cmd, blocking=True)
73
74 # if for some reason output contains lines with "eta" - remove them
75 out = re.sub(r'.+\[eta\s+\d{2}m:\d{2}s\]', '', out)
76
77 if rc != 0:
78 print("ERROR! While executing FIO jobs - RC: {rc}, Err message: {out}".format(rc=rc, out=out))
79 sys.exit(rc)
80 else:
81 print(out)
82 save_file(os.path.join(out_path, ".".join([fio_cfg_prefix, "log"])), "w", out)
83
84 if perf_vmex:
85 # Stop gathering perf statistics and prepare some result files
86 perf_p.send_signal(signal.SIGINT)
87 perf_p.wait()
88
89 perf_stat_cmd = "perf kvm --host -i {perf_rec} stat report --event vmexit"\
90 .format(perf_rec=perf_rec_file)
91
92 rc, out = exec_cmd(" ".join([perf_stat_cmd, "--event vmexit"]),
93 blocking=True)
94 print("VMexit host stats:")
95 print("{perf_out}".format(perf_out=out))
96 save_file(os.path.join(perf_dir, "vmexit_stats_" + fio_cfg_prefix),
97 "w", "{perf_out}".format(perf_out=out))
98 try:
99 os.remove(perf_rec_file)
100 except OSError:
101 pass
102
103
104 def main():
105 global fio_bin
106
107 abspath = os.path.abspath(__file__)
108 dname = os.path.dirname(abspath)
109 os.chdir(os.path.join(dname, "../../.."))
110
111 vms = []
112 fio_cfgs = []
113 perf_vmex = False
114 out_dir = os.path.join(os.getcwd(), "fio_results")
115
116 try:
117 opts, args = getopt.getopt(sys.argv[1:], "hj:f:o:p",
118 ["help", "job-file=", "fio-bin=",
119 "out=", "perf-vmex"])
120 except getopt.GetoptError:
121 show_help()
122 sys.exit(1)
123
124 for o, a in opts:
125 if o in ("-j", "--job-file"):
126 fio_cfgs = a.split(",")
127 elif o in ("-h", "--help"):
128 show_help()
129 sys.exit(1)
130 elif o in ("-p", "--perf-vmex"):
131 perf_vmex = True
132 elif o in ("-o", "--out"):
133 out_dir = os.path.join(a, "fio_results")
134 elif o in ("-f", "--fio-bin"):
135 fio_bin = a
136
137 if len(fio_cfgs) < 1:
138 print("ERROR! No FIO jobs provided!")
139 sys.exit(1)
140
141 if len(args) < 1:
142 show_help()
143 sys.exit(1)
144 else:
145 # Get IP, port and fio 'filename' information from positional args
146 for arg in args[0].split(","):
147 _ = arg.split(":")
148 ip, port, filenames = _[0], _[1], ":".join(_[2:])
149 vms.append((ip, port, filenames))
150
151 if not os.path.exists(out_dir):
152 os.mkdir(out_dir)
153
154 for fio_cfg in fio_cfgs:
155 fio_cfg_fname = os.path.basename(fio_cfg)
156 print("Running job file: {0}".format(fio_cfg_fname))
157
158 for i, vm in enumerate(vms):
159 # VM - tuple of IP / Port / Filename for VM to run test
160 print("Preparing VM {0} - {1} for FIO job".format(i, vm[0]))
161
162 exec_cmd("./test/vhost/fiotest/vm_ssh.sh {vm_num} sh -c 'rm {cfg}'"
163 .format(vm_num=i, cfg=fio_cfg_fname), blocking=True)
164
165 # Copy FIO config to VM
166 with open(fio_cfg, "r") as fio_cfg_fh:
167 for line in fio_cfg_fh.readlines():
168 if "filename" in line:
169 line = "filename=" + vm[2]
170 out = exec_cmd("./test/vhost/fiotest/vm_ssh.sh {vm_num} sh -c 'echo {line} >> {cfg}'"
171 .format(vm_num=i, line=line.strip(), cfg=fio_cfg_fname), blocking=True)
172 if out[0] != 0:
173 print("ERROR! While copying FIO job config file to VM {vm_num} - {vm_ip}"
174 .format(vm_num=1, vm_ip=vm[0]))
175 sys.exit(1)
176
177 run_fio(vms, fio_cfg_fname, out_dir, perf_vmex)
178
179 if __name__ == "__main__":
180 sys.exit(main())