qemu/tests/avocado/replay_linux.py
<<
>>
Prefs
   1# Record/replay test that boots a complete Linux system via a cloud image
   2#
   3# Copyright (c) 2020 ISP RAS
   4#
   5# Author:
   6#  Pavel Dovgalyuk <Pavel.Dovgaluk@ispras.ru>
   7#
   8# This work is licensed under the terms of the GNU GPL, version 2 or
   9# later.  See the COPYING file in the top-level directory.
  10
  11import os
  12import logging
  13import time
  14
  15from avocado import skipUnless
  16from avocado.utils import cloudinit
  17from avocado.utils import network
  18from avocado.utils import vmimage
  19from avocado.utils import datadrainer
  20from avocado.utils.path import find_command
  21from avocado_qemu import LinuxTest
  22
  23class ReplayLinux(LinuxTest):
  24    """
  25    Boots a Linux system, checking for a successful initialization
  26    """
  27
  28    timeout = 1800
  29    chksum = None
  30    hdd = 'ide-hd'
  31    cd = 'ide-cd'
  32    bus = 'ide'
  33
  34    def setUp(self):
  35        super(ReplayLinux, self).setUp()
  36        self.boot_path = self.download_boot()
  37        self.cloudinit_path = self.prepare_cloudinit()
  38
  39    def vm_add_disk(self, vm, path, id, device):
  40        bus_string = ''
  41        if self.bus:
  42            bus_string = ',bus=%s.%d' % (self.bus, id,)
  43        vm.add_args('-drive', 'file=%s,snapshot,id=disk%s,if=none' % (path, id))
  44        vm.add_args('-drive',
  45            'driver=blkreplay,id=disk%s-rr,if=none,image=disk%s' % (id, id))
  46        vm.add_args('-device',
  47            '%s,drive=disk%s-rr%s' % (device, id, bus_string))
  48
  49    def launch_and_wait(self, record, args, shift):
  50        vm = self.get_vm()
  51        vm.add_args('-smp', '1')
  52        vm.add_args('-m', '1024')
  53        vm.add_args('-object', 'filter-replay,id=replay,netdev=hub0port0')
  54        if args:
  55            vm.add_args(*args)
  56        self.vm_add_disk(vm, self.boot_path, 0, self.hdd)
  57        self.vm_add_disk(vm, self.cloudinit_path, 1, self.cd)
  58        logger = logging.getLogger('replay')
  59        if record:
  60            logger.info('recording the execution...')
  61            mode = 'record'
  62        else:
  63            logger.info('replaying the execution...')
  64            mode = 'replay'
  65        replay_path = os.path.join(self.workdir, 'replay.bin')
  66        vm.add_args('-icount', 'shift=%s,rr=%s,rrfile=%s' %
  67                    (shift, mode, replay_path))
  68
  69        start_time = time.time()
  70
  71        vm.set_console()
  72        vm.launch()
  73        console_drainer = datadrainer.LineLogger(vm.console_socket.fileno(),
  74                                    logger=self.log.getChild('console'),
  75                                    stop_check=(lambda : not vm.is_running()))
  76        console_drainer.start()
  77        if record:
  78            cloudinit.wait_for_phone_home(('0.0.0.0', self.phone_home_port),
  79                                          self.name)
  80            vm.shutdown()
  81            logger.info('finished the recording with log size %s bytes'
  82                % os.path.getsize(replay_path))
  83        else:
  84            vm.event_wait('SHUTDOWN', self.timeout)
  85            vm.shutdown(True)
  86            logger.info('successfully fihished the replay')
  87        elapsed = time.time() - start_time
  88        logger.info('elapsed time %.2f sec' % elapsed)
  89        return elapsed
  90
  91    def run_rr(self, args=None, shift=7):
  92        t1 = self.launch_and_wait(True, args, shift)
  93        t2 = self.launch_and_wait(False, args, shift)
  94        logger = logging.getLogger('replay')
  95        logger.info('replay overhead {:.2%}'.format(t2 / t1 - 1))
  96
  97@skipUnless(os.getenv('AVOCADO_TIMEOUT_EXPECTED'), 'Test might timeout')
  98class ReplayLinuxX8664(ReplayLinux):
  99    """
 100    :avocado: tags=arch:x86_64
 101    :avocado: tags=accel:tcg
 102    """
 103
 104    chksum = 'e3c1b309d9203604922d6e255c2c5d098a309c2d46215d8fc026954f3c5c27a0'
 105
 106    def test_pc_i440fx(self):
 107        """
 108        :avocado: tags=machine:pc
 109        """
 110        self.run_rr(shift=1)
 111
 112    def test_pc_q35(self):
 113        """
 114        :avocado: tags=machine:q35
 115        """
 116        self.run_rr(shift=3)
 117