1 from __future__ import print_function
3 # Migration test command line shell integration
5 # Copyright (c) 2016 Red Hat, Inc.
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.
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.
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/>.
25 sys.path.append(os.path.join(os.path.dirname(__file__),
26 '..', '..', '..', 'scripts'))
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
40 class BaseShell(object):
43 parser = argparse.ArgumentParser(description="Migration Test Tool")
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")
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)
69 def get_engine(self, args):
70 return Engine(binary=args.binary,
71 dst_host=args.dst_host,
74 transport=args.transport,
79 def get_hardware(self, args):
83 return value.split(",")
85 return Hardware(cpus=args.cpus,
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),
93 locked_pages=args.locked_pages,
94 huge_pages=args.huge_pages,
95 prealloc_pages=args.prealloc_pages)
98 class Shell(BaseShell):
101 super(Shell, self).__init__()
103 parser = self._parser
105 parser.add_argument("--output", dest="output", default=None)
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)
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)
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)
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)
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)
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)
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,
136 pause_iters=args.pause_iters,
138 post_copy=args.post_copy,
139 post_copy_iters=args.post_copy_iters,
141 auto_converge=args.auto_converge,
142 auto_converge_step=args.auto_converge_step,
144 compression_mt=args.compression_mt,
145 compression_mt_threads=args.compression_mt_threads,
147 compression_xbzrle=args.compression_xbzrle,
148 compression_xbzrle_cache=args.compression_xbzrle_cache)
151 args = self._parser.parse_args(argv)
152 logging.basicConfig(level=(logging.DEBUG if args.debug else
153 logging.INFO if args.verbose else
157 engine = self.get_engine(args)
158 hardware = self.get_hardware(args)
159 scenario = self.get_scenario(args)
162 report = engine.run(hardware, scenario)
163 if args.output is None:
164 print(report.to_json())
166 with open(args.output, "w") as fh:
167 print(report.to_json(), file=fh)
169 except Exception as e:
170 print("Error: %s" % str(e), file=sys.stderr)
176 class BatchShell(BaseShell):
179 super(BatchShell, self).__init__()
181 parser = self._parser
183 parser.add_argument("--filter", dest="filter", default="*")
184 parser.add_argument("--output", dest="output", default=os.getcwd())
187 args = self._parser.parse_args(argv)
188 logging.basicConfig(level=(logging.DEBUG if args.debug else
189 logging.INFO if args.verbose else
193 engine = self.get_engine(args)
194 hardware = self.get_hardware(args)
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):
203 print("Skipping %s" % name)
207 print("Running %s" % name)
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):
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)
222 class PlotShell(object):
225 super(PlotShell, self).__init__()
227 self._parser = argparse.ArgumentParser(description="Migration Test Tool")
229 self._parser.add_argument("--output", dest="output", default=None)
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")
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")
240 self._parser.add_argument("reports", nargs='*')
243 args = self._parser.parse_args(argv)
244 logging.basicConfig(level=(logging.DEBUG if args.debug else
245 logging.INFO if args.verbose else
249 if len(args.reports) == 0:
250 print("At least one report required", file=sys.stderr)
253 if not (args.qemu_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)
261 for report in args.reports:
262 reports.append(Report.from_json_file(report))
265 args.migration_iters,
266 args.total_guest_cpu,
267 args.split_guest_cpu,
271 plot.generate(args.output)