]>
Commit | Line | Data |
---|---|---|
6fd52d67 CR |
1 | # Functional test that boots a complete Linux system via a cloud image |
2 | # | |
3 | # Copyright (c) 2018-2020 Red Hat, Inc. | |
4 | # | |
5 | # Author: | |
6 | # Cleber Rosa <crosa@redhat.com> | |
7 | # | |
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. | |
10 | ||
11 | import os | |
12 | ||
13 | from avocado_qemu import Test, BUILD_DIR | |
14 | ||
15 | from qemu.accel import kvm_available | |
16 | from qemu.accel import tcg_available | |
17 | ||
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 | |
0f26d94e | 23 | from avocado import skipIf |
6fd52d67 CR |
24 | |
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" | |
28 | ||
29 | ||
1c80c87c PD |
30 | class BootLinuxBase(Test): |
31 | def download_boot(self): | |
6fd52d67 CR |
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) | |
39 | if qemu_img is False: | |
40 | self.cancel('Could not find "qemu-img", which is required to ' | |
41 | 'create the bootable image') | |
42 | vmimage.QEMU_IMG = qemu_img | |
43 | ||
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' | |
49 | try: | |
1c80c87c | 50 | boot = vmimage.get( |
6fd52d67 CR |
51 | 'fedora', arch=image_arch, version='31', |
52 | checksum=self.chksum, | |
53 | algorithm='sha256', | |
54 | cache_dir=self.cache_dirs[0], | |
55 | snapshot_dir=self.workdir) | |
6fd52d67 CR |
56 | except: |
57 | self.cancel('Failed to download/prepare boot image') | |
1c80c87c | 58 | return boot.path |
6fd52d67 | 59 | |
0a779803 | 60 | def download_cloudinit(self, ssh_pubkey=None): |
6fd52d67 CR |
61 | self.log.info('Preparing cloudinit image') |
62 | try: | |
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, | |
66 | username='root', | |
67 | password='password', | |
68 | # QEMU's hard coded usermode router address | |
69 | phone_home_host='10.0.2.2', | |
0a779803 HR |
70 | phone_home_port=self.phone_home_port, |
71 | authorized_key=ssh_pubkey) | |
6fd52d67 CR |
72 | except Exception: |
73 | self.cancel('Failed to prepared cloudinit image') | |
1c80c87c PD |
74 | return cloudinit_iso |
75 | ||
76 | class BootLinux(BootLinuxBase): | |
77 | """ | |
78 | Boots a Linux system, checking for a successful initialization | |
79 | """ | |
80 | ||
81 | timeout = 900 | |
82 | chksum = None | |
83 | ||
0a779803 | 84 | def setUp(self, ssh_pubkey=None): |
1c80c87c PD |
85 | super(BootLinux, self).setUp() |
86 | self.vm.add_args('-smp', '2') | |
87 | self.vm.add_args('-m', '1024') | |
88 | self.prepare_boot() | |
0a779803 | 89 | self.prepare_cloudinit(ssh_pubkey) |
1c80c87c PD |
90 | |
91 | def prepare_boot(self): | |
92 | path = self.download_boot() | |
93 | self.vm.add_args('-drive', 'file=%s' % path) | |
94 | ||
0a779803 HR |
95 | def prepare_cloudinit(self, ssh_pubkey=None): |
96 | cloudinit_iso = self.download_cloudinit(ssh_pubkey) | |
1c80c87c | 97 | self.vm.add_args('-drive', 'file=%s,format=raw' % cloudinit_iso) |
6fd52d67 CR |
98 | |
99 | def launch_and_wait(self): | |
100 | self.vm.set_console() | |
101 | self.vm.launch() | |
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) | |
107 | ||
108 | ||
109 | class BootLinuxX8664(BootLinux): | |
110 | """ | |
111 | :avocado: tags=arch:x86_64 | |
112 | """ | |
113 | ||
114 | chksum = 'e3c1b309d9203604922d6e255c2c5d098a309c2d46215d8fc026954f3c5c27a0' | |
115 | ||
116 | def test_pc_i440fx_tcg(self): | |
117 | """ | |
118 | :avocado: tags=machine:pc | |
119 | :avocado: tags=accel:tcg | |
120 | """ | |
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() | |
125 | ||
126 | def test_pc_i440fx_kvm(self): | |
127 | """ | |
128 | :avocado: tags=machine:pc | |
129 | :avocado: tags=accel:kvm | |
130 | """ | |
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() | |
135 | ||
136 | def test_pc_q35_tcg(self): | |
137 | """ | |
138 | :avocado: tags=machine:q35 | |
139 | :avocado: tags=accel:tcg | |
140 | """ | |
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() | |
145 | ||
146 | def test_pc_q35_kvm(self): | |
147 | """ | |
148 | :avocado: tags=machine:q35 | |
149 | :avocado: tags=accel:kvm | |
150 | """ | |
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() | |
155 | ||
156 | ||
157 | class BootLinuxAarch64(BootLinux): | |
158 | """ | |
159 | :avocado: tags=arch:aarch64 | |
160 | :avocado: tags=machine:virt | |
161 | :avocado: tags=machine:gic-version=2 | |
162 | """ | |
163 | ||
164 | chksum = '1e18d9c0cf734940c4b5d5ec592facaed2af0ad0329383d5639c997fdf16fe49' | |
165 | ||
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') | |
172 | ||
173 | def test_virt_tcg(self): | |
174 | """ | |
175 | :avocado: tags=accel:tcg | |
176 | :avocado: tags=cpu:max | |
177 | """ | |
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() | |
185 | ||
99233758 | 186 | def test_virt_kvm_gicv2(self): |
6fd52d67 CR |
187 | """ |
188 | :avocado: tags=accel:kvm | |
189 | :avocado: tags=cpu:host | |
99233758 | 190 | :avocado: tags=device:gicv2 |
6fd52d67 CR |
191 | """ |
192 | if not kvm_available(self.arch, self.qemu_bin): | |
193 | self.cancel(KVM_NOT_AVAILABLE) | |
194 | self.vm.add_args("-accel", "kvm") | |
195 | self.vm.add_args("-cpu", "host") | |
196 | self.vm.add_args("-machine", "virt,gic-version=2") | |
197 | self.add_common_args() | |
99233758 PMD |
198 | self.launch_and_wait() |
199 | ||
200 | def test_virt_kvm_gicv3(self): | |
201 | """ | |
202 | :avocado: tags=accel:kvm | |
203 | :avocado: tags=cpu:host | |
204 | :avocado: tags=device:gicv3 | |
205 | """ | |
206 | if not kvm_available(self.arch, self.qemu_bin): | |
207 | self.cancel(KVM_NOT_AVAILABLE) | |
208 | self.vm.add_args("-accel", "kvm") | |
209 | self.vm.add_args("-cpu", "host") | |
210 | self.vm.add_args("-machine", "virt,gic-version=3") | |
211 | self.add_common_args() | |
6fd52d67 CR |
212 | self.launch_and_wait() |
213 | ||
214 | ||
215 | class BootLinuxPPC64(BootLinux): | |
216 | """ | |
217 | :avocado: tags=arch:ppc64 | |
218 | """ | |
219 | ||
220 | chksum = '7c3528b85a3df4b2306e892199a9e1e43f991c506f2cc390dc4efa2026ad2f58' | |
221 | ||
222 | def test_pseries_tcg(self): | |
223 | """ | |
224 | :avocado: tags=machine:pseries | |
225 | :avocado: tags=accel:tcg | |
226 | """ | |
227 | if not tcg_available(self.qemu_bin): | |
228 | self.cancel(TCG_NOT_AVAILABLE) | |
229 | self.vm.add_args("-accel", "tcg") | |
230 | self.launch_and_wait() | |
231 | ||
232 | ||
233 | class BootLinuxS390X(BootLinux): | |
234 | """ | |
235 | :avocado: tags=arch:s390x | |
236 | """ | |
237 | ||
238 | chksum = '4caaab5a434fd4d1079149a072fdc7891e354f834d355069ca982fdcaf5a122d' | |
239 | ||
0f26d94e | 240 | @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') |
6fd52d67 CR |
241 | def test_s390_ccw_virtio_tcg(self): |
242 | """ | |
243 | :avocado: tags=machine:s390-ccw-virtio | |
244 | :avocado: tags=accel:tcg | |
245 | """ | |
246 | if not tcg_available(self.qemu_bin): | |
247 | self.cancel(TCG_NOT_AVAILABLE) | |
248 | self.vm.add_args("-accel", "tcg") | |
249 | self.launch_and_wait() |