cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

shell.py (11166B)


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