1 # Functional test that boots a complete Linux system via a cloud image
3 # Copyright (c) 2018-2020 Red Hat, Inc.
6 # Cleber Rosa <crosa@redhat.com>
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.
13 from avocado_qemu
import Test
, BUILD_DIR
15 from qemu
.accel
import kvm_available
16 from qemu
.accel
import tcg_available
18 from avocado
.utils
import cloudinit
19 from avocado
.utils
import network
20 from avocado
.utils
import vmimage
21 from avocado
.utils
import datadrainer
22 from avocado
.utils
.path
import find_command
23 from avocado
import skipIf
25 ACCEL_NOT_AVAILABLE_FMT
= "%s accelerator does not seem to be available"
26 KVM_NOT_AVAILABLE
= ACCEL_NOT_AVAILABLE_FMT
% "KVM"
27 TCG_NOT_AVAILABLE
= ACCEL_NOT_AVAILABLE_FMT
% "TCG"
30 class BootLinuxBase(Test
):
31 def download_boot(self
):
32 self
.log
.debug('Looking for and selecting a qemu-img binary to be '
33 'used to create the bootable snapshot image')
34 # If qemu-img has been built, use it, otherwise the system wide one
35 # will be used. If none is available, the test will cancel.
36 qemu_img
= os
.path
.join(BUILD_DIR
, 'qemu-img')
37 if not os
.path
.exists(qemu_img
):
38 qemu_img
= find_command('qemu-img', False)
40 self
.cancel('Could not find "qemu-img", which is required to '
41 'create the bootable image')
42 vmimage
.QEMU_IMG
= qemu_img
44 self
.log
.info('Downloading/preparing boot image')
45 # Fedora 31 only provides ppc64le images
46 image_arch
= self
.arch
47 if image_arch
== 'ppc64':
48 image_arch
= 'ppc64le'
51 'fedora', arch
=image_arch
, version
='31',
54 cache_dir
=self
.cache_dirs
[0],
55 snapshot_dir
=self
.workdir
)
57 self
.cancel('Failed to download/prepare boot image')
60 def download_cloudinit(self
, ssh_pubkey
=None):
61 self
.log
.info('Preparing cloudinit image')
63 cloudinit_iso
= os
.path
.join(self
.workdir
, 'cloudinit.iso')
64 self
.phone_home_port
= network
.find_free_port()
65 cloudinit
.iso(cloudinit_iso
, self
.name
,
68 # QEMU's hard coded usermode router address
69 phone_home_host
='10.0.2.2',
70 phone_home_port
=self
.phone_home_port
,
71 authorized_key
=ssh_pubkey
)
73 self
.cancel('Failed to prepared cloudinit image')
76 class BootLinux(BootLinuxBase
):
78 Boots a Linux system, checking for a successful initialization
84 def setUp(self
, ssh_pubkey
=None):
85 super(BootLinux
, self
).setUp()
86 self
.vm
.add_args('-smp', '2')
87 self
.vm
.add_args('-m', '1024')
89 self
.prepare_cloudinit(ssh_pubkey
)
91 def prepare_boot(self
):
92 path
= self
.download_boot()
93 self
.vm
.add_args('-drive', 'file=%s' % path
)
95 def prepare_cloudinit(self
, ssh_pubkey
=None):
96 cloudinit_iso
= self
.download_cloudinit(ssh_pubkey
)
97 self
.vm
.add_args('-drive', 'file=%s,format=raw' % cloudinit_iso
)
99 def launch_and_wait(self
):
100 self
.vm
.set_console()
102 console_drainer
= datadrainer
.LineLogger(self
.vm
.console_socket
.fileno(),
103 logger
=self
.log
.getChild('console'))
104 console_drainer
.start()
105 self
.log
.info('VM launched, waiting for boot confirmation from guest')
106 cloudinit
.wait_for_phone_home(('0.0.0.0', self
.phone_home_port
), self
.name
)
109 class BootLinuxX8664(BootLinux
):
111 :avocado: tags=arch:x86_64
114 chksum
= 'e3c1b309d9203604922d6e255c2c5d098a309c2d46215d8fc026954f3c5c27a0'
116 def test_pc_i440fx_tcg(self
):
118 :avocado: tags=machine:pc
119 :avocado: tags=accel:tcg
121 if not tcg_available(self
.qemu_bin
):
122 self
.cancel(TCG_NOT_AVAILABLE
)
123 self
.vm
.add_args("-accel", "tcg")
124 self
.launch_and_wait()
126 def test_pc_i440fx_kvm(self
):
128 :avocado: tags=machine:pc
129 :avocado: tags=accel:kvm
131 if not kvm_available(self
.arch
, self
.qemu_bin
):
132 self
.cancel(KVM_NOT_AVAILABLE
)
133 self
.vm
.add_args("-accel", "kvm")
134 self
.launch_and_wait()
136 def test_pc_q35_tcg(self
):
138 :avocado: tags=machine:q35
139 :avocado: tags=accel:tcg
141 if not tcg_available(self
.qemu_bin
):
142 self
.cancel(TCG_NOT_AVAILABLE
)
143 self
.vm
.add_args("-accel", "tcg")
144 self
.launch_and_wait()
146 def test_pc_q35_kvm(self
):
148 :avocado: tags=machine:q35
149 :avocado: tags=accel:kvm
151 if not kvm_available(self
.arch
, self
.qemu_bin
):
152 self
.cancel(KVM_NOT_AVAILABLE
)
153 self
.vm
.add_args("-accel", "kvm")
154 self
.launch_and_wait()
157 class BootLinuxAarch64(BootLinux
):
159 :avocado: tags=arch:aarch64
160 :avocado: tags=machine:virt
161 :avocado: tags=machine:gic-version=2
164 chksum
= '1e18d9c0cf734940c4b5d5ec592facaed2af0ad0329383d5639c997fdf16fe49'
166 def add_common_args(self
):
167 self
.vm
.add_args('-bios',
168 os
.path
.join(BUILD_DIR
, 'pc-bios',
169 'edk2-aarch64-code.fd'))
170 self
.vm
.add_args('-device', 'virtio-rng-pci,rng=rng0')
171 self
.vm
.add_args('-object', 'rng-random,id=rng0,filename=/dev/urandom')
173 def test_virt_tcg(self
):
175 :avocado: tags=accel:tcg
176 :avocado: tags=cpu:max
178 if not tcg_available(self
.qemu_bin
):
179 self
.cancel(TCG_NOT_AVAILABLE
)
180 self
.vm
.add_args("-accel", "tcg")
181 self
.vm
.add_args("-cpu", "max")
182 self
.vm
.add_args("-machine", "virt,gic-version=2")
183 self
.add_common_args()
184 self
.launch_and_wait()
186 def test_virt_kvm(self
):
188 :avocado: tags=accel:kvm
189 :avocado: tags=cpu:host
191 if not kvm_available(self
.arch
, self
.qemu_bin
):
192 self
.cancel(KVM_NOT_AVAILABLE
)
193 self
.vm
.add_args("-accel", "kvm")
194 self
.vm
.add_args("-cpu", "host")
195 self
.vm
.add_args("-machine", "virt,gic-version=2")
196 self
.add_common_args()
197 self
.launch_and_wait()
200 class BootLinuxPPC64(BootLinux
):
202 :avocado: tags=arch:ppc64
205 chksum
= '7c3528b85a3df4b2306e892199a9e1e43f991c506f2cc390dc4efa2026ad2f58'
207 def test_pseries_tcg(self
):
209 :avocado: tags=machine:pseries
210 :avocado: tags=accel:tcg
212 if not tcg_available(self
.qemu_bin
):
213 self
.cancel(TCG_NOT_AVAILABLE
)
214 self
.vm
.add_args("-accel", "tcg")
215 self
.launch_and_wait()
218 class BootLinuxS390X(BootLinux
):
220 :avocado: tags=arch:s390x
223 chksum
= '4caaab5a434fd4d1079149a072fdc7891e354f834d355069ca982fdcaf5a122d'
225 @skipIf(os
.getenv('GITLAB_CI'), 'Running on GitLab')
226 def test_s390_ccw_virtio_tcg(self
):
228 :avocado: tags=machine:s390-ccw-virtio
229 :avocado: tags=accel:tcg
231 if not tcg_available(self
.qemu_bin
):
232 self
.cancel(TCG_NOT_AVAILABLE
)
233 self
.vm
.add_args("-accel", "tcg")
234 self
.launch_and_wait()