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
24 ACCEL_NOT_AVAILABLE_FMT
= "%s accelerator does not seem to be available"
25 KVM_NOT_AVAILABLE
= ACCEL_NOT_AVAILABLE_FMT
% "KVM"
26 TCG_NOT_AVAILABLE
= ACCEL_NOT_AVAILABLE_FMT
% "TCG"
29 class BootLinuxBase(Test
):
30 def download_boot(self
):
31 self
.log
.debug('Looking for and selecting a qemu-img binary to be '
32 'used to create the bootable snapshot image')
33 # If qemu-img has been built, use it, otherwise the system wide one
34 # will be used. If none is available, the test will cancel.
35 qemu_img
= os
.path
.join(BUILD_DIR
, 'qemu-img')
36 if not os
.path
.exists(qemu_img
):
37 qemu_img
= find_command('qemu-img', False)
39 self
.cancel('Could not find "qemu-img", which is required to '
40 'create the bootable image')
41 vmimage
.QEMU_IMG
= qemu_img
43 self
.log
.info('Downloading/preparing boot image')
44 # Fedora 31 only provides ppc64le images
45 image_arch
= self
.arch
46 if image_arch
== 'ppc64':
47 image_arch
= 'ppc64le'
50 'fedora', arch
=image_arch
, version
='31',
53 cache_dir
=self
.cache_dirs
[0],
54 snapshot_dir
=self
.workdir
)
56 self
.cancel('Failed to download/prepare boot image')
59 def download_cloudinit(self
):
60 self
.log
.info('Preparing cloudinit image')
62 cloudinit_iso
= os
.path
.join(self
.workdir
, 'cloudinit.iso')
63 self
.phone_home_port
= network
.find_free_port()
64 cloudinit
.iso(cloudinit_iso
, self
.name
,
67 # QEMU's hard coded usermode router address
68 phone_home_host
='10.0.2.2',
69 phone_home_port
=self
.phone_home_port
)
71 self
.cancel('Failed to prepared cloudinit image')
74 class BootLinux(BootLinuxBase
):
76 Boots a Linux system, checking for a successful initialization
83 super(BootLinux
, self
).setUp()
84 self
.vm
.add_args('-smp', '2')
85 self
.vm
.add_args('-m', '1024')
87 self
.prepare_cloudinit()
89 def prepare_boot(self
):
90 path
= self
.download_boot()
91 self
.vm
.add_args('-drive', 'file=%s' % path
)
93 def prepare_cloudinit(self
):
94 cloudinit_iso
= self
.download_cloudinit()
95 self
.vm
.add_args('-drive', 'file=%s,format=raw' % cloudinit_iso
)
97 def launch_and_wait(self
):
100 console_drainer
= datadrainer
.LineLogger(self
.vm
.console_socket
.fileno(),
101 logger
=self
.log
.getChild('console'))
102 console_drainer
.start()
103 self
.log
.info('VM launched, waiting for boot confirmation from guest')
104 cloudinit
.wait_for_phone_home(('0.0.0.0', self
.phone_home_port
), self
.name
)
107 class BootLinuxX8664(BootLinux
):
109 :avocado: tags=arch:x86_64
112 chksum
= 'e3c1b309d9203604922d6e255c2c5d098a309c2d46215d8fc026954f3c5c27a0'
114 def test_pc_i440fx_tcg(self
):
116 :avocado: tags=machine:pc
117 :avocado: tags=accel:tcg
119 if not tcg_available(self
.qemu_bin
):
120 self
.cancel(TCG_NOT_AVAILABLE
)
121 self
.vm
.add_args("-accel", "tcg")
122 self
.launch_and_wait()
124 def test_pc_i440fx_kvm(self
):
126 :avocado: tags=machine:pc
127 :avocado: tags=accel:kvm
129 if not kvm_available(self
.arch
, self
.qemu_bin
):
130 self
.cancel(KVM_NOT_AVAILABLE
)
131 self
.vm
.add_args("-accel", "kvm")
132 self
.launch_and_wait()
134 def test_pc_q35_tcg(self
):
136 :avocado: tags=machine:q35
137 :avocado: tags=accel:tcg
139 if not tcg_available(self
.qemu_bin
):
140 self
.cancel(TCG_NOT_AVAILABLE
)
141 self
.vm
.add_args("-accel", "tcg")
142 self
.launch_and_wait()
144 def test_pc_q35_kvm(self
):
146 :avocado: tags=machine:q35
147 :avocado: tags=accel:kvm
149 if not kvm_available(self
.arch
, self
.qemu_bin
):
150 self
.cancel(KVM_NOT_AVAILABLE
)
151 self
.vm
.add_args("-accel", "kvm")
152 self
.launch_and_wait()
155 class BootLinuxAarch64(BootLinux
):
157 :avocado: tags=arch:aarch64
158 :avocado: tags=machine:virt
159 :avocado: tags=machine:gic-version=2
162 chksum
= '1e18d9c0cf734940c4b5d5ec592facaed2af0ad0329383d5639c997fdf16fe49'
164 def add_common_args(self
):
165 self
.vm
.add_args('-bios',
166 os
.path
.join(BUILD_DIR
, 'pc-bios',
167 'edk2-aarch64-code.fd'))
168 self
.vm
.add_args('-device', 'virtio-rng-pci,rng=rng0')
169 self
.vm
.add_args('-object', 'rng-random,id=rng0,filename=/dev/urandom')
171 def test_virt_tcg(self
):
173 :avocado: tags=accel:tcg
174 :avocado: tags=cpu:max
176 if not tcg_available(self
.qemu_bin
):
177 self
.cancel(TCG_NOT_AVAILABLE
)
178 self
.vm
.add_args("-accel", "tcg")
179 self
.vm
.add_args("-cpu", "max")
180 self
.vm
.add_args("-machine", "virt,gic-version=2")
181 self
.add_common_args()
182 self
.launch_and_wait()
184 def test_virt_kvm(self
):
186 :avocado: tags=accel:kvm
187 :avocado: tags=cpu:host
189 if not kvm_available(self
.arch
, self
.qemu_bin
):
190 self
.cancel(KVM_NOT_AVAILABLE
)
191 self
.vm
.add_args("-accel", "kvm")
192 self
.vm
.add_args("-cpu", "host")
193 self
.vm
.add_args("-machine", "virt,gic-version=2")
194 self
.add_common_args()
195 self
.launch_and_wait()
198 class BootLinuxPPC64(BootLinux
):
200 :avocado: tags=arch:ppc64
203 chksum
= '7c3528b85a3df4b2306e892199a9e1e43f991c506f2cc390dc4efa2026ad2f58'
205 def test_pseries_tcg(self
):
207 :avocado: tags=machine:pseries
208 :avocado: tags=accel:tcg
210 if not tcg_available(self
.qemu_bin
):
211 self
.cancel(TCG_NOT_AVAILABLE
)
212 self
.vm
.add_args("-accel", "tcg")
213 self
.launch_and_wait()
216 class BootLinuxS390X(BootLinux
):
218 :avocado: tags=arch:s390x
221 chksum
= '4caaab5a434fd4d1079149a072fdc7891e354f834d355069ca982fdcaf5a122d'
223 def test_s390_ccw_virtio_tcg(self
):
225 :avocado: tags=machine:s390-ccw-virtio
226 :avocado: tags=accel:tcg
228 if not tcg_available(self
.qemu_bin
):
229 self
.cancel(TCG_NOT_AVAILABLE
)
230 self
.vm
.add_args("-accel", "tcg")
231 self
.launch_and_wait()