xref: /qemu/tests/avocado/replay_linux.py (revision 727385c4)
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