1 # Record/replay test that boots a complete Linux system via a cloud image
3 # Copyright (c) 2020 ISP RAS
6 # Pavel Dovgalyuk <Pavel.Dovgaluk@ispras.ru>
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.
15 from avocado
import skipUnless
16 from avocado_qemu
import BUILD_DIR
17 from avocado
.utils
import cloudinit
18 from avocado
.utils
import network
19 from avocado
.utils
import vmimage
20 from avocado
.utils
import datadrainer
21 from avocado
.utils
.path
import find_command
22 from avocado_qemu
import LinuxTest
24 class ReplayLinux(LinuxTest
):
26 Boots a Linux system, checking for a successful initialization
36 # LinuxTest does many replay-incompatible things, but includes
37 # useful methods. Do not setup LinuxTest here and just
38 # call some functions.
39 super(LinuxTest
, self
).setUp()
41 self
.boot_path
= self
.download_boot()
42 self
.phone_server
= cloudinit
.PhoneHomeServer(('0.0.0.0', 0),
44 ssh_pubkey
, self
.ssh_key
= self
.set_up_existing_ssh_keys()
45 self
.cloudinit_path
= self
.prepare_cloudinit(ssh_pubkey
)
47 def vm_add_disk(self
, vm
, path
, id, device
):
50 bus_string
= ',bus=%s.%d' % (self
.bus
, id,)
51 vm
.add_args('-drive', 'file=%s,snapshot,id=disk%s,if=none' % (path
, id))
53 'driver=blkreplay,id=disk%s-rr,if=none,image=disk%s' % (id, id))
54 vm
.add_args('-device',
55 '%s,drive=disk%s-rr%s' % (device
, id, bus_string
))
57 def launch_and_wait(self
, record
, args
, shift
):
58 self
.require_netdev('user')
60 vm
.add_args('-smp', '1')
61 vm
.add_args('-m', '1024')
62 vm
.add_args('-netdev', 'user,id=vnet,hostfwd=:127.0.0.1:0-:22',
63 '-device', 'virtio-net,netdev=vnet')
64 vm
.add_args('-object', 'filter-replay,id=replay,netdev=vnet')
67 self
.vm_add_disk(vm
, self
.boot_path
, 0, self
.hdd
)
68 self
.vm_add_disk(vm
, self
.cloudinit_path
, 1, self
.cd
)
69 logger
= logging
.getLogger('replay')
71 logger
.info('recording the execution...')
74 logger
.info('replaying the execution...')
76 replay_path
= os
.path
.join(self
.workdir
, 'replay.bin')
77 vm
.add_args('-icount', 'shift=%s,rr=%s,rrfile=%s' %
78 (shift
, mode
, replay_path
))
80 start_time
= time
.time()
84 console_drainer
= datadrainer
.LineLogger(vm
.console_socket
.fileno(),
85 logger
=self
.log
.getChild('console'),
86 stop_check
=(lambda : not vm
.is_running()))
87 console_drainer
.start()
89 while not self
.phone_server
.instance_phoned_back
:
90 self
.phone_server
.handle_request()
92 logger
.info('finished the recording with log size %s bytes'
93 % os
.path
.getsize(replay_path
))
95 vm
.event_wait('SHUTDOWN', self
.timeout
)
97 logger
.info('successfully fihished the replay')
98 elapsed
= time
.time() - start_time
99 logger
.info('elapsed time %.2f sec' % elapsed
)
102 def run_rr(self
, args
=None, shift
=7):
103 t1
= self
.launch_and_wait(True, args
, shift
)
104 t2
= self
.launch_and_wait(False, args
, shift
)
105 logger
= logging
.getLogger('replay')
106 logger
.info('replay overhead {:.2%}'.format(t2
/ t1
- 1))
108 @skipUnless(os
.getenv('AVOCADO_TIMEOUT_EXPECTED'), 'Test might timeout')
109 class ReplayLinuxX8664(ReplayLinux
):
111 :avocado: tags=arch:x86_64
112 :avocado: tags=accel:tcg
115 chksum
= 'e3c1b309d9203604922d6e255c2c5d098a309c2d46215d8fc026954f3c5c27a0'
117 def test_pc_i440fx(self
):
119 :avocado: tags=machine:pc
123 def test_pc_q35(self
):
125 :avocado: tags=machine:q35
129 @skipUnless(os
.getenv('AVOCADO_TIMEOUT_EXPECTED'), 'Test might timeout')
130 class ReplayLinuxX8664Virtio(ReplayLinux
):
132 :avocado: tags=arch:x86_64
133 :avocado: tags=virtio
134 :avocado: tags=accel:tcg
137 hdd
= 'virtio-blk-pci'
138 cd
= 'virtio-blk-pci'
141 chksum
= 'e3c1b309d9203604922d6e255c2c5d098a309c2d46215d8fc026954f3c5c27a0'
143 def test_pc_i440fx(self
):
145 :avocado: tags=machine:pc
149 def test_pc_q35(self
):
151 :avocado: tags=machine:q35
155 @skipUnless(os
.getenv('AVOCADO_TIMEOUT_EXPECTED'), 'Test might timeout')
156 class ReplayLinuxAarch64(ReplayLinux
):
158 :avocado: tags=accel:tcg
159 :avocado: tags=arch:aarch64
160 :avocado: tags=machine:virt
161 :avocado: tags=cpu:max
164 chksum
= '1e18d9c0cf734940c4b5d5ec592facaed2af0ad0329383d5639c997fdf16fe49'
166 hdd
= 'virtio-blk-device'
167 cd
= 'virtio-blk-device'
170 def get_common_args(self
):
172 os
.path
.join(BUILD_DIR
, 'pc-bios', 'edk2-aarch64-code.fd'),
173 "-cpu", "max,lpa2=off",
174 '-device', 'virtio-rng-pci,rng=rng0',
175 '-object', 'rng-builtin,id=rng0')
177 def test_virt_gicv2(self
):
179 :avocado: tags=machine:gic-version=2
183 args
=(*self
.get_common_args(),
184 "-machine", "virt,gic-version=2"))
186 def test_virt_gicv3(self
):
188 :avocado: tags=machine:gic-version=3
192 args
=(*self
.get_common_args(),
193 "-machine", "virt,gic-version=3"))