]> Git Repo - qemu.git/blob - tests/migration/guestperf/shell.py
a6b8cec1e0cb9933b2a53e5915687e9691108f45
[qemu.git] / tests / migration / guestperf / shell.py
1 from __future__ import print_function
2 #
3 # Migration test command line shell integration
4 #
5 # Copyright (c) 2016 Red Hat, Inc.
6 #
7 # This library is free software; you can redistribute it and/or
8 # modify it under the terms of the GNU Lesser General Public
9 # License as published by the Free Software Foundation; either
10 # version 2 of the License, or (at your option) any later version.
11 #
12 # This library is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 # Lesser General Public License for more details.
16 #
17 # You should have received a copy of the GNU Lesser General Public
18 # License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 #
20
21
22 import os
23 import os.path
24 import sys
25 sys.path.append(os.path.join(os.path.dirname(__file__),
26                              '..', '..', '..', 'scripts'))
27 import argparse
28 import fnmatch
29 import platform
30 import logging
31
32 from guestperf.hardware import Hardware
33 from guestperf.engine import Engine
34 from guestperf.scenario import Scenario
35 from guestperf.comparison import COMPARISONS
36 from guestperf.plot import Plot
37 from guestperf.report import Report
38
39
40 class BaseShell(object):
41
42     def __init__(self):
43         parser = argparse.ArgumentParser(description="Migration Test Tool")
44
45         # Test args
46         parser.add_argument("--debug", dest="debug", default=False, action="store_true")
47         parser.add_argument("--verbose", dest="verbose", default=False, action="store_true")
48         parser.add_argument("--sleep", dest="sleep", default=15, type=int)
49         parser.add_argument("--binary", dest="binary", default="/usr/bin/qemu-system-x86_64")
50         parser.add_argument("--dst-host", dest="dst_host", default="localhost")
51         parser.add_argument("--kernel", dest="kernel", default="/boot/vmlinuz-%s" % platform.release())
52         parser.add_argument("--initrd", dest="initrd", default="tests/migration/initrd-stress.img")
53         parser.add_argument("--transport", dest="transport", default="unix")
54
55
56         # Hardware args
57         parser.add_argument("--cpus", dest="cpus", default=1, type=int)
58         parser.add_argument("--mem", dest="mem", default=1, type=int)
59         parser.add_argument("--src-cpu-bind", dest="src_cpu_bind", default="")
60         parser.add_argument("--src-mem-bind", dest="src_mem_bind", default="")
61         parser.add_argument("--dst-cpu-bind", dest="dst_cpu_bind", default="")
62         parser.add_argument("--dst-mem-bind", dest="dst_mem_bind", default="")
63         parser.add_argument("--prealloc-pages", dest="prealloc_pages", default=False)
64         parser.add_argument("--huge-pages", dest="huge_pages", default=False)
65         parser.add_argument("--locked-pages", dest="locked_pages", default=False)
66
67         self._parser = parser
68
69     def get_engine(self, args):
70         return Engine(binary=args.binary,
71                       dst_host=args.dst_host,
72                       kernel=args.kernel,
73                       initrd=args.initrd,
74                       transport=args.transport,
75                       sleep=args.sleep,
76                       debug=args.debug,
77                       verbose=args.verbose)
78
79     def get_hardware(self, args):
80         def split_map(value):
81             if value == "":
82                 return []
83             return value.split(",")
84
85         return Hardware(cpus=args.cpus,
86                         mem=args.mem,
87
88                         src_cpu_bind=split_map(args.src_cpu_bind),
89                         src_mem_bind=split_map(args.src_mem_bind),
90                         dst_cpu_bind=split_map(args.dst_cpu_bind),
91                         dst_mem_bind=split_map(args.dst_mem_bind),
92
93                         locked_pages=args.locked_pages,
94                         huge_pages=args.huge_pages,
95                         prealloc_pages=args.prealloc_pages)
96
97
98 class Shell(BaseShell):
99
100     def __init__(self):
101         super(Shell, self).__init__()
102
103         parser = self._parser
104
105         parser.add_argument("--output", dest="output", default=None)
106
107         # Scenario args
108         parser.add_argument("--max-iters", dest="max_iters", default=30, type=int)
109         parser.add_argument("--max-time", dest="max_time", default=300, type=int)
110         parser.add_argument("--bandwidth", dest="bandwidth", default=125000, type=int)
111         parser.add_argument("--downtime", dest="downtime", default=500, type=int)
112
113         parser.add_argument("--pause", dest="pause", default=False, action="store_true")
114         parser.add_argument("--pause-iters", dest="pause_iters", default=5, type=int)
115
116         parser.add_argument("--post-copy", dest="post_copy", default=False, action="store_true")
117         parser.add_argument("--post-copy-iters", dest="post_copy_iters", default=5, type=int)
118
119         parser.add_argument("--auto-converge", dest="auto_converge", default=False, action="store_true")
120         parser.add_argument("--auto-converge-step", dest="auto_converge_step", default=10, type=int)
121
122         parser.add_argument("--compression-mt", dest="compression_mt", default=False, action="store_true")
123         parser.add_argument("--compression-mt-threads", dest="compression_mt_threads", default=1, type=int)
124
125         parser.add_argument("--compression-xbzrle", dest="compression_xbzrle", default=False, action="store_true")
126         parser.add_argument("--compression-xbzrle-cache", dest="compression_xbzrle_cache", default=10, type=int)
127
128     def get_scenario(self, args):
129         return Scenario(name="perfreport",
130                         downtime=args.downtime,
131                         bandwidth=args.bandwidth,
132                         max_iters=args.max_iters,
133                         max_time=args.max_time,
134
135                         pause=args.pause,
136                         pause_iters=args.pause_iters,
137
138                         post_copy=args.post_copy,
139                         post_copy_iters=args.post_copy_iters,
140
141                         auto_converge=args.auto_converge,
142                         auto_converge_step=args.auto_converge_step,
143
144                         compression_mt=args.compression_mt,
145                         compression_mt_threads=args.compression_mt_threads,
146
147                         compression_xbzrle=args.compression_xbzrle,
148                         compression_xbzrle_cache=args.compression_xbzrle_cache)
149
150     def run(self, argv):
151         args = self._parser.parse_args(argv)
152         logging.basicConfig(level=(logging.DEBUG if args.debug else
153                                    logging.INFO if args.verbose else
154                                    logging.WARN))
155
156
157         engine = self.get_engine(args)
158         hardware = self.get_hardware(args)
159         scenario = self.get_scenario(args)
160
161         try:
162             report = engine.run(hardware, scenario)
163             if args.output is None:
164                 print(report.to_json())
165             else:
166                 with open(args.output, "w") as fh:
167                     print(report.to_json(), file=fh)
168             return 0
169         except Exception as e:
170             print("Error: %s" % str(e), file=sys.stderr)
171             if args.debug:
172                 raise
173             return 1
174
175
176 class BatchShell(BaseShell):
177
178     def __init__(self):
179         super(BatchShell, self).__init__()
180
181         parser = self._parser
182
183         parser.add_argument("--filter", dest="filter", default="*")
184         parser.add_argument("--output", dest="output", default=os.getcwd())
185
186     def run(self, argv):
187         args = self._parser.parse_args(argv)
188         logging.basicConfig(level=(logging.DEBUG if args.debug else
189                                    logging.INFO if args.verbose else
190                                    logging.WARN))
191
192
193         engine = self.get_engine(args)
194         hardware = self.get_hardware(args)
195
196         try:
197             for comparison in COMPARISONS:
198                 compdir = os.path.join(args.output, comparison._name)
199                 for scenario in comparison._scenarios:
200                     name = os.path.join(comparison._name, scenario._name)
201                     if not fnmatch.fnmatch(name, args.filter):
202                         if args.verbose:
203                             print("Skipping %s" % name)
204                         continue
205
206                     if args.verbose:
207                         print("Running %s" % name)
208
209                     dirname = os.path.join(args.output, comparison._name)
210                     filename = os.path.join(dirname, scenario._name + ".json")
211                     if not os.path.exists(dirname):
212                         os.makedirs(dirname)
213                     report = engine.run(hardware, scenario)
214                     with open(filename, "w") as fh:
215                         print(report.to_json(), file=fh)
216         except Exception as e:
217             print("Error: %s" % str(e), file=sys.stderr)
218             if args.debug:
219                 raise
220
221
222 class PlotShell(object):
223
224     def __init__(self):
225         super(PlotShell, self).__init__()
226
227         self._parser = argparse.ArgumentParser(description="Migration Test Tool")
228
229         self._parser.add_argument("--output", dest="output", default=None)
230
231         self._parser.add_argument("--debug", dest="debug", default=False, action="store_true")
232         self._parser.add_argument("--verbose", dest="verbose", default=False, action="store_true")
233
234         self._parser.add_argument("--migration-iters", dest="migration_iters", default=False, action="store_true")
235         self._parser.add_argument("--total-guest-cpu", dest="total_guest_cpu", default=False, action="store_true")
236         self._parser.add_argument("--split-guest-cpu", dest="split_guest_cpu", default=False, action="store_true")
237         self._parser.add_argument("--qemu-cpu", dest="qemu_cpu", default=False, action="store_true")
238         self._parser.add_argument("--vcpu-cpu", dest="vcpu_cpu", default=False, action="store_true")
239
240         self._parser.add_argument("reports", nargs='*')
241
242     def run(self, argv):
243         args = self._parser.parse_args(argv)
244         logging.basicConfig(level=(logging.DEBUG if args.debug else
245                                    logging.INFO if args.verbose else
246                                    logging.WARN))
247
248
249         if len(args.reports) == 0:
250             print("At least one report required", file=sys.stderr)
251             return 1
252
253         if not (args.qemu_cpu or
254                 args.vcpu_cpu or
255                 args.total_guest_cpu or
256                 args.split_guest_cpu):
257             print("At least one chart type is required", file=sys.stderr)
258             return 1
259
260         reports = []
261         for report in args.reports:
262             reports.append(Report.from_json_file(report))
263
264         plot = Plot(reports,
265                     args.migration_iters,
266                     args.total_guest_cpu,
267                     args.split_guest_cpu,
268                     args.qemu_cpu,
269                     args.vcpu_cpu)
270
271         plot.generate(args.output)
This page took 0.029805 seconds and 2 git commands to generate.