6f6b71536c
QEMU complains about us not being explicit with setting snapshot so lets do that. Also as cdroms are RO media we don't need to jump the hoops of setting up snapshots and replay disks - just declare the drive is a cdrom and nothing should change. Signed-off-by: Alex Bennée <alex.bennee@linaro.org> Message-Id: <20231211091346.14616-4-alex.bennee@linaro.org>
197 lines
6.2 KiB
Python
197 lines
6.2 KiB
Python
# Record/replay test that boots a complete Linux system via a cloud image
|
|
#
|
|
# Copyright (c) 2020 ISP RAS
|
|
#
|
|
# Author:
|
|
# Pavel Dovgalyuk <Pavel.Dovgaluk@ispras.ru>
|
|
#
|
|
# This work is licensed under the terms of the GNU GPL, version 2 or
|
|
# later. See the COPYING file in the top-level directory.
|
|
|
|
import os
|
|
import logging
|
|
import time
|
|
|
|
from avocado import skipUnless
|
|
from avocado_qemu import BUILD_DIR
|
|
from avocado.utils import cloudinit
|
|
from avocado.utils import network
|
|
from avocado.utils import vmimage
|
|
from avocado.utils import datadrainer
|
|
from avocado.utils.path import find_command
|
|
from avocado_qemu import LinuxTest
|
|
|
|
class ReplayLinux(LinuxTest):
|
|
"""
|
|
Boots a Linux system, checking for a successful initialization
|
|
"""
|
|
|
|
timeout = 1800
|
|
chksum = None
|
|
hdd = 'ide-hd'
|
|
cd = 'ide-cd'
|
|
bus = 'ide'
|
|
|
|
def setUp(self):
|
|
# LinuxTest does many replay-incompatible things, but includes
|
|
# useful methods. Do not setup LinuxTest here and just
|
|
# call some functions.
|
|
super(LinuxTest, self).setUp()
|
|
self._set_distro()
|
|
self.boot_path = self.download_boot()
|
|
self.phone_server = cloudinit.PhoneHomeServer(('0.0.0.0', 0),
|
|
self.name)
|
|
ssh_pubkey, self.ssh_key = self.set_up_existing_ssh_keys()
|
|
self.cloudinit_path = self.prepare_cloudinit(ssh_pubkey)
|
|
|
|
def vm_add_disk(self, vm, path, id, device):
|
|
bus_string = ''
|
|
if self.bus:
|
|
bus_string = ',bus=%s.%d' % (self.bus, id,)
|
|
vm.add_args('-drive', 'file=%s,snapshot=on,id=disk%s,if=none' % (path, id))
|
|
vm.add_args('-drive',
|
|
'driver=blkreplay,id=disk%s-rr,if=none,image=disk%s' % (id, id))
|
|
vm.add_args('-device',
|
|
'%s,drive=disk%s-rr%s' % (device, id, bus_string))
|
|
|
|
def vm_add_cdrom(self, vm, path, id, device):
|
|
vm.add_args('-drive', 'file=%s,id=disk%s,if=none,media=cdrom' % (path, id))
|
|
|
|
def launch_and_wait(self, record, args, shift):
|
|
self.require_netdev('user')
|
|
vm = self.get_vm()
|
|
vm.add_args('-smp', '1')
|
|
vm.add_args('-m', '1024')
|
|
vm.add_args('-netdev', 'user,id=vnet,hostfwd=:127.0.0.1:0-:22',
|
|
'-device', 'virtio-net,netdev=vnet')
|
|
vm.add_args('-object', 'filter-replay,id=replay,netdev=vnet')
|
|
if args:
|
|
vm.add_args(*args)
|
|
self.vm_add_disk(vm, self.boot_path, 0, self.hdd)
|
|
self.vm_add_cdrom(vm, self.cloudinit_path, 1, self.cd)
|
|
logger = logging.getLogger('replay')
|
|
if record:
|
|
logger.info('recording the execution...')
|
|
mode = 'record'
|
|
else:
|
|
logger.info('replaying the execution...')
|
|
mode = 'replay'
|
|
replay_path = os.path.join(self.workdir, 'replay.bin')
|
|
vm.add_args('-icount', 'shift=%s,rr=%s,rrfile=%s' %
|
|
(shift, mode, replay_path))
|
|
|
|
start_time = time.time()
|
|
|
|
vm.set_console()
|
|
vm.launch()
|
|
console_drainer = datadrainer.LineLogger(vm.console_socket.fileno(),
|
|
logger=self.log.getChild('console'),
|
|
stop_check=(lambda : not vm.is_running()))
|
|
console_drainer.start()
|
|
if record:
|
|
while not self.phone_server.instance_phoned_back:
|
|
self.phone_server.handle_request()
|
|
vm.shutdown()
|
|
logger.info('finished the recording with log size %s bytes'
|
|
% os.path.getsize(replay_path))
|
|
else:
|
|
vm.event_wait('SHUTDOWN', self.timeout)
|
|
vm.wait()
|
|
logger.info('successfully finished the replay')
|
|
elapsed = time.time() - start_time
|
|
logger.info('elapsed time %.2f sec' % elapsed)
|
|
return elapsed
|
|
|
|
def run_rr(self, args=None, shift=7):
|
|
t1 = self.launch_and_wait(True, args, shift)
|
|
t2 = self.launch_and_wait(False, args, shift)
|
|
logger = logging.getLogger('replay')
|
|
logger.info('replay overhead {:.2%}'.format(t2 / t1 - 1))
|
|
|
|
@skipUnless(os.getenv('AVOCADO_TIMEOUT_EXPECTED'), 'Test might timeout')
|
|
class ReplayLinuxX8664(ReplayLinux):
|
|
"""
|
|
:avocado: tags=arch:x86_64
|
|
:avocado: tags=accel:tcg
|
|
"""
|
|
|
|
chksum = 'e3c1b309d9203604922d6e255c2c5d098a309c2d46215d8fc026954f3c5c27a0'
|
|
|
|
def test_pc_i440fx(self):
|
|
"""
|
|
:avocado: tags=machine:pc
|
|
"""
|
|
self.run_rr(shift=1)
|
|
|
|
def test_pc_q35(self):
|
|
"""
|
|
:avocado: tags=machine:q35
|
|
"""
|
|
self.run_rr(shift=3)
|
|
|
|
@skipUnless(os.getenv('AVOCADO_TIMEOUT_EXPECTED'), 'Test might timeout')
|
|
class ReplayLinuxX8664Virtio(ReplayLinux):
|
|
"""
|
|
:avocado: tags=arch:x86_64
|
|
:avocado: tags=virtio
|
|
:avocado: tags=accel:tcg
|
|
"""
|
|
|
|
hdd = 'virtio-blk-pci'
|
|
cd = 'virtio-blk-pci'
|
|
bus = None
|
|
|
|
chksum = 'e3c1b309d9203604922d6e255c2c5d098a309c2d46215d8fc026954f3c5c27a0'
|
|
|
|
def test_pc_i440fx(self):
|
|
"""
|
|
:avocado: tags=machine:pc
|
|
"""
|
|
self.run_rr(shift=1)
|
|
|
|
def test_pc_q35(self):
|
|
"""
|
|
:avocado: tags=machine:q35
|
|
"""
|
|
self.run_rr(shift=3)
|
|
|
|
@skipUnless(os.getenv('AVOCADO_TIMEOUT_EXPECTED'), 'Test might timeout')
|
|
class ReplayLinuxAarch64(ReplayLinux):
|
|
"""
|
|
:avocado: tags=accel:tcg
|
|
:avocado: tags=arch:aarch64
|
|
:avocado: tags=machine:virt
|
|
:avocado: tags=cpu:max
|
|
"""
|
|
|
|
chksum = '1e18d9c0cf734940c4b5d5ec592facaed2af0ad0329383d5639c997fdf16fe49'
|
|
|
|
hdd = 'virtio-blk-device'
|
|
cd = 'virtio-blk-device'
|
|
bus = None
|
|
|
|
def get_common_args(self):
|
|
return ('-bios',
|
|
os.path.join(BUILD_DIR, 'pc-bios', 'edk2-aarch64-code.fd'),
|
|
"-cpu", "max,lpa2=off",
|
|
'-device', 'virtio-rng-pci,rng=rng0',
|
|
'-object', 'rng-builtin,id=rng0')
|
|
|
|
def test_virt_gicv2(self):
|
|
"""
|
|
:avocado: tags=machine:gic-version=2
|
|
"""
|
|
|
|
self.run_rr(shift=3,
|
|
args=(*self.get_common_args(),
|
|
"-machine", "virt,gic-version=2"))
|
|
|
|
def test_virt_gicv3(self):
|
|
"""
|
|
:avocado: tags=machine:gic-version=3
|
|
"""
|
|
|
|
self.run_rr(shift=3,
|
|
args=(*self.get_common_args(),
|
|
"-machine", "virt,gic-version=3"))
|