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 BootLinux(Test
):
31 Boots a Linux system, checking for a successful initialization
38 super(BootLinux
, self
).setUp()
39 self
.vm
.add_args('-smp', '2')
40 self
.vm
.add_args('-m', '1024')
42 self
.prepare_cloudinit()
44 def prepare_boot(self
):
45 self
.log
.debug('Looking for and selecting a qemu-img binary to be '
46 'used to create the bootable snapshot image')
47 # If qemu-img has been built, use it, otherwise the system wide one
48 # will be used. If none is available, the test will cancel.
49 qemu_img
= os
.path
.join(BUILD_DIR
, 'qemu-img')
50 if not os
.path
.exists(qemu_img
):
51 qemu_img
= find_command('qemu-img', False)
53 self
.cancel('Could not find "qemu-img", which is required to '
54 'create the bootable image')
55 vmimage
.QEMU_IMG
= qemu_img
57 self
.log
.info('Downloading/preparing boot image')
58 # Fedora 31 only provides ppc64le images
59 image_arch
= self
.arch
60 if image_arch
== 'ppc64':
61 image_arch
= 'ppc64le'
63 self
.boot
= vmimage
.get(
64 'fedora', arch
=image_arch
, version
='31',
67 cache_dir
=self
.cache_dirs
[0],
68 snapshot_dir
=self
.workdir
)
69 self
.vm
.add_args('-drive', 'file=%s' % self
.boot
.path
)
71 self
.cancel('Failed to download/prepare boot image')
73 def prepare_cloudinit(self
):
74 self
.log
.info('Preparing cloudinit image')
76 cloudinit_iso
= os
.path
.join(self
.workdir
, 'cloudinit.iso')
77 self
.phone_home_port
= network
.find_free_port()
78 cloudinit
.iso(cloudinit_iso
, self
.name
,
81 # QEMU's hard coded usermode router address
82 phone_home_host
='10.0.2.2',
83 phone_home_port
=self
.phone_home_port
)
84 self
.vm
.add_args('-drive', 'file=%s,format=raw' % cloudinit_iso
)
86 self
.cancel('Failed to prepared cloudinit image')
88 def launch_and_wait(self
):
91 console_drainer
= datadrainer
.LineLogger(self
.vm
.console_socket
.fileno(),
92 logger
=self
.log
.getChild('console'))
93 console_drainer
.start()
94 self
.log
.info('VM launched, waiting for boot confirmation from guest')
95 cloudinit
.wait_for_phone_home(('0.0.0.0', self
.phone_home_port
), self
.name
)
98 class BootLinuxX8664(BootLinux
):
100 :avocado: tags=arch:x86_64
103 chksum
= 'e3c1b309d9203604922d6e255c2c5d098a309c2d46215d8fc026954f3c5c27a0'
105 def test_pc_i440fx_tcg(self
):
107 :avocado: tags=machine:pc
108 :avocado: tags=accel:tcg
110 if not tcg_available(self
.qemu_bin
):
111 self
.cancel(TCG_NOT_AVAILABLE
)
112 self
.vm
.add_args("-accel", "tcg")
113 self
.launch_and_wait()
115 def test_pc_i440fx_kvm(self
):
117 :avocado: tags=machine:pc
118 :avocado: tags=accel:kvm
120 if not kvm_available(self
.arch
, self
.qemu_bin
):
121 self
.cancel(KVM_NOT_AVAILABLE
)
122 self
.vm
.add_args("-accel", "kvm")
123 self
.launch_and_wait()
125 def test_pc_q35_tcg(self
):
127 :avocado: tags=machine:q35
128 :avocado: tags=accel:tcg
130 if not tcg_available(self
.qemu_bin
):
131 self
.cancel(TCG_NOT_AVAILABLE
)
132 self
.vm
.add_args("-accel", "tcg")
133 self
.launch_and_wait()
135 def test_pc_q35_kvm(self
):
137 :avocado: tags=machine:q35
138 :avocado: tags=accel:kvm
140 if not kvm_available(self
.arch
, self
.qemu_bin
):
141 self
.cancel(KVM_NOT_AVAILABLE
)
142 self
.vm
.add_args("-accel", "kvm")
143 self
.launch_and_wait()
146 class BootLinuxAarch64(BootLinux
):
148 :avocado: tags=arch:aarch64
149 :avocado: tags=machine:virt
150 :avocado: tags=machine:gic-version=2
153 chksum
= '1e18d9c0cf734940c4b5d5ec592facaed2af0ad0329383d5639c997fdf16fe49'
155 def add_common_args(self
):
156 self
.vm
.add_args('-bios',
157 os
.path
.join(BUILD_DIR
, 'pc-bios',
158 'edk2-aarch64-code.fd'))
159 self
.vm
.add_args('-device', 'virtio-rng-pci,rng=rng0')
160 self
.vm
.add_args('-object', 'rng-random,id=rng0,filename=/dev/urandom')
162 def test_virt_tcg(self
):
164 :avocado: tags=accel:tcg
165 :avocado: tags=cpu:max
167 if not tcg_available(self
.qemu_bin
):
168 self
.cancel(TCG_NOT_AVAILABLE
)
169 self
.vm
.add_args("-accel", "tcg")
170 self
.vm
.add_args("-cpu", "max")
171 self
.vm
.add_args("-machine", "virt,gic-version=2")
172 self
.add_common_args()
173 self
.launch_and_wait()
175 def test_virt_kvm(self
):
177 :avocado: tags=accel:kvm
178 :avocado: tags=cpu:host
180 if not kvm_available(self
.arch
, self
.qemu_bin
):
181 self
.cancel(KVM_NOT_AVAILABLE
)
182 self
.vm
.add_args("-accel", "kvm")
183 self
.vm
.add_args("-cpu", "host")
184 self
.vm
.add_args("-machine", "virt,gic-version=2")
185 self
.add_common_args()
186 self
.launch_and_wait()
189 class BootLinuxPPC64(BootLinux
):
191 :avocado: tags=arch:ppc64
194 chksum
= '7c3528b85a3df4b2306e892199a9e1e43f991c506f2cc390dc4efa2026ad2f58'
196 def test_pseries_tcg(self
):
198 :avocado: tags=machine:pseries
199 :avocado: tags=accel:tcg
201 if not tcg_available(self
.qemu_bin
):
202 self
.cancel(TCG_NOT_AVAILABLE
)
203 self
.vm
.add_args("-accel", "tcg")
204 self
.launch_and_wait()
207 class BootLinuxS390X(BootLinux
):
209 :avocado: tags=arch:s390x
212 chksum
= '4caaab5a434fd4d1079149a072fdc7891e354f834d355069ca982fdcaf5a122d'
214 def test_s390_ccw_virtio_tcg(self
):
216 :avocado: tags=machine:s390-ccw-virtio
217 :avocado: tags=accel:tcg
219 if not tcg_available(self
.qemu_bin
):
220 self
.cancel(TCG_NOT_AVAILABLE
)
221 self
.vm
.add_args("-accel", "tcg")
222 self
.launch_and_wait()