]>
Commit | Line | Data |
---|---|---|
c47c336e PMD |
1 | # Functional test that boots a VM and run commands via a SSH session |
2 | # | |
3 | # Copyright (c) Philippe Mathieu-Daudé <[email protected]> | |
4 | # | |
5 | # This work is licensed under the terms of the GNU GPL, version 2 or | |
6 | # later. See the COPYING file in the top-level directory. | |
7 | ||
8 | import os | |
9 | import re | |
10 | import base64 | |
11 | import logging | |
12 | import paramiko | |
13 | import time | |
14 | ||
15 | from avocado import skipIf | |
16 | from avocado_qemu import Test | |
17 | from avocado.utils import process | |
18 | from avocado.utils import archive | |
19 | ||
20 | ||
21 | class LinuxSSH(Test): | |
22 | ||
23 | timeout = 150 # Not for 'configure --enable-debug --enable-debug-tcg' | |
24 | ||
25 | KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' | |
26 | VM_IP = '127.0.0.1' | |
27 | ||
28 | IMAGE_INFO = { | |
29 | 'be': { | |
30 | 'image_url': 'https://people.debian.org/~aurel32/qemu/mips/' | |
31 | 'debian_wheezy_mips_standard.qcow2', | |
32 | 'image_hash': '8987a63270df67345b2135a6b7a4885a35e392d5', | |
33 | 'rsa_hostkey': b'AAAAB3NzaC1yc2EAAAADAQABAAABAQCca1VitiyLAdQOld' | |
34 | b'zT43IOEVJZ0wHD78GJi8wDAjMiYWUzNSSn0rXGQsINHuH5' | |
35 | b'IlF+kBZsHinb/FtKCAyS9a8uCHhQI4SuB4QhAb0+39MlUw' | |
36 | b'Mm0CLkctgM2eUUZ6MQMQvDlqnue6CCkxN62EZYbaxmby7j' | |
37 | b'CQa1125o1HRKBvdGm2zrJWxXAfA+f1v6jHLyE8Jnu83eQ+' | |
38 | b'BFY25G+Vzx1PVc3zQBwJ8r0NGTRqy2//oWQP0h+bMsgeFe' | |
39 | b'KH/J3RJM22vg6+I4JAdBFcxnK+l781h1FuRxOn4O/Xslbg' | |
40 | b'go6WtB4V4TOsw2E/KfxI5IZ/icxF+swVcnvF46Hf3uQc/0' | |
41 | b'BBqb', | |
42 | }, | |
43 | 'le': { | |
44 | 'image_url': 'https://people.debian.org/~aurel32/qemu/mipsel/' | |
45 | 'debian_wheezy_mipsel_standard.qcow2', | |
46 | 'image_hash': '7866764d9de3ef536ffca24c9fb9f04ffdb45802', | |
47 | 'rsa_hostkey': b'AAAAB3NzaC1yc2EAAAADAQABAAABAQClXJlBT71HL5yKvv' | |
48 | b'gfC7jmxSWx5zSBCzET6CLZczwAafSIs7YKfNOy/dQTxhuk' | |
49 | b'yIGFUugZFoF3E9PzdhunuyvyTd56MPoNIqFbb5rGokwU5I' | |
50 | b'TOx3dBHZR0mClypL6MVrwe0bsiIb8GhF1zioNwcsaAZnAi' | |
51 | b'KfXStVDtXvn/kLLq+xLABYt48CC5KYWoFaCoICskLAY+qo' | |
52 | b'L+LWyAnQisj4jAH8VSaSKIImFpfkHWEXPhHcC4ZBlDKtnH' | |
53 | b'po9vhfCHgnfW3Pzrqmk8BI4HysqPFVmJWkJGlGUL+sGeg3' | |
54 | b'ZZolAYuDXGuBrw8ooPJq2v2dOH+z6dyD2q/ypmAbyPqj5C' | |
55 | b'rc8H', | |
56 | }, | |
57 | } | |
58 | ||
59 | def wait_for_console_pattern(self, success_message, | |
60 | failure_message='Oops'): | |
61 | console = self.vm.console_socket.makefile() | |
62 | console_logger = logging.getLogger('console') | |
63 | while True: | |
64 | msg = console.readline() | |
65 | console_logger.debug(msg.strip()) | |
66 | if success_message in msg: | |
67 | break | |
68 | if failure_message in msg: | |
69 | fail = 'Failure message found in console: %s' % failure_message | |
70 | self.fail(fail) | |
71 | ||
72 | def get_portfwd(self): | |
73 | res = self.vm.command('human-monitor-command', | |
74 | command_line='info usernet') | |
75 | line = res.split('\r\n')[2] | |
76 | port = re.split(r'.*TCP.HOST_FORWARD.*127\.0\.0\.1 (\d+)\s+10\..*', | |
77 | line)[1] | |
78 | self.log.debug("sshd listening on port:" + port) | |
79 | return port | |
80 | ||
81 | def ssh_connect(self, username, password, rsa_hostkey_b64=None): | |
82 | self.ssh_logger = logging.getLogger('ssh') | |
83 | self.ssh_username = username | |
84 | self.ssh_ps1 = '# ' if username is 'root' else '$ ' | |
85 | self.ssh_client = paramiko.SSHClient() | |
86 | port = self.get_portfwd() | |
87 | if rsa_hostkey_b64: | |
88 | rsa_hostkey_bin = base64.b64decode(rsa_hostkey_b64) | |
89 | rsa_hostkey = paramiko.RSAKey(data = rsa_hostkey_bin) | |
90 | ipport = '[%s]:%s' % (self.VM_IP, port) | |
91 | self.ssh_logger.debug('ipport ' + ipport) | |
92 | self.ssh_client.get_host_keys().add(ipport, 'ssh-rsa', rsa_hostkey) | |
93 | for i in range(10): | |
94 | try: | |
95 | self.ssh_client.connect(self.VM_IP, int(port), | |
96 | username, password, banner_timeout=90) | |
97 | self.ssh_logger.info("Entering interactive session.") | |
98 | return | |
99 | except: | |
100 | time.sleep(4) | |
101 | pass | |
102 | self.fail("sshd timeout") | |
103 | ||
104 | def ssh_disconnect_vm(self): | |
105 | self.ssh_client.close() | |
106 | ||
107 | def ssh_command(self, command, is_root=True): | |
108 | self.ssh_logger.info(self.ssh_ps1 + command) | |
109 | stdin, stdout, stderr = self.ssh_client.exec_command(command) | |
110 | stdout_lines = [line.strip('\n') for line in stdout] | |
111 | for line in stdout_lines: | |
112 | self.ssh_logger.info(line) | |
113 | stderr_lines = [line.strip('\n') for line in stderr] | |
114 | for line in stderr_lines: | |
115 | self.ssh_logger.warning(line) | |
116 | return stdout_lines, stderr_lines | |
117 | ||
118 | def boot_debian_wheezy_image_and_ssh_login(self, endianess, kernel_path): | |
119 | image_url = self.IMAGE_INFO[endianess]['image_url'] | |
120 | image_hash = self.IMAGE_INFO[endianess]['image_hash'] | |
121 | image_path = self.fetch_asset(image_url, asset_hash=image_hash) | |
122 | rsa_hostkey_b64 = self.IMAGE_INFO[endianess]['rsa_hostkey'] | |
123 | ||
124 | self.vm.set_machine('malta') | |
125 | self.vm.set_console() | |
126 | kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE | |
127 | + 'console=ttyS0 root=/dev/sda1') | |
128 | self.vm.add_args('-no-reboot', | |
129 | '-kernel', kernel_path, | |
130 | '-append', kernel_command_line, | |
131 | '-hda', image_path, | |
132 | '-netdev', 'user,id=vnet,hostfwd=:127.0.0.1:0-:22', | |
133 | '-device', 'pcnet,netdev=vnet') | |
134 | self.vm.launch() | |
135 | ||
136 | self.log.info('VM launched, waiting for sshd') | |
137 | console_pattern = 'Starting OpenBSD Secure Shell server: sshd' | |
138 | self.wait_for_console_pattern(console_pattern) | |
139 | self.log.info('sshd ready') | |
140 | ||
141 | self.ssh_connect('root', 'root', rsa_hostkey_b64=rsa_hostkey_b64) | |
142 | ||
143 | def shutdown_via_ssh(self): | |
144 | self.ssh_command('poweroff') | |
145 | self.ssh_disconnect_vm() | |
146 | self.wait_for_console_pattern('Power down') | |
147 | ||
148 | def run_common_commands(self): | |
149 | stdout, stderr = self.ssh_command('lspci -d 11ab:4620') | |
150 | self.assertIn(True, ["GT-64120" in line for line in stdout]) | |
151 | ||
152 | stdout, stderr = self.ssh_command('cat /sys/bus/i2c/devices/i2c-0/name') | |
153 | self.assertIn(True, ["SMBus PIIX4 adapter" in line | |
154 | for line in stdout]) | |
155 | ||
156 | stdout, stderr = self.ssh_command('cat /proc/mtd') | |
157 | self.assertIn(True, ["YAMON" in line | |
158 | for line in stdout]) | |
159 | ||
160 | # Empty 'Board Config' | |
161 | stdout, stderr = self.ssh_command('md5sum /dev/mtd2ro') | |
162 | self.assertIn(True, ["0dfbe8aa4c20b52e1b8bf3cb6cbdf193" in line | |
163 | for line in stdout]) | |
164 | ||
165 | def do_test_mips_malta(self, endianess, kernel_path, uname_m): | |
166 | self.boot_debian_wheezy_image_and_ssh_login(endianess, kernel_path) | |
167 | ||
168 | stdout, stderr = self.ssh_command('uname -a') | |
169 | self.assertIn(True, [uname_m + " GNU/Linux" in line for line in stdout]) | |
170 | ||
171 | self.run_common_commands() | |
172 | self.shutdown_via_ssh() | |
173 | ||
174 | @skipIf(os.getenv('CONTINUOUS_INTEGRATION'), 'Running on Travis-CI') | |
175 | def test_mips_malta32eb_kernel3_2_0(self): | |
176 | """ | |
177 | :avocado: tags=arch:mips | |
178 | :avocado: tags=machine:malta | |
179 | :avocado: tags=endian:big | |
180 | :avocado: tags=device:pcnet32 | |
181 | """ | |
182 | kernel_url = ('https://people.debian.org/~aurel32/qemu/mips/' | |
183 | 'vmlinux-3.2.0-4-4kc-malta') | |
184 | kernel_hash = '592e384a4edc16dade52a6cd5c785c637bcbc9ad' | |
185 | kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) | |
186 | ||
187 | self.do_test_mips_malta('be', kernel_path, 'mips') | |
188 | ||
189 | @skipIf(os.getenv('CONTINUOUS_INTEGRATION'), 'Running on Travis-CI') | |
190 | def test_mips_malta32el_kernel3_2_0(self): | |
191 | """ | |
192 | :avocado: tags=arch:mipsel | |
193 | :avocado: tags=machine:malta | |
194 | :avocado: tags=endian:little | |
195 | :avocado: tags=device:pcnet32 | |
196 | """ | |
197 | kernel_url = ('https://people.debian.org/~aurel32/qemu/mipsel/' | |
198 | 'vmlinux-3.2.0-4-4kc-malta') | |
199 | kernel_hash = 'a66bea5a8adaa2cb3d36a1d4e0ccdb01be8f6c2a' | |
200 | kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) | |
201 | ||
202 | self.do_test_mips_malta('le', kernel_path, 'mips') | |
203 | ||
204 | @skipIf(os.getenv('CONTINUOUS_INTEGRATION'), 'Running on Travis-CI') | |
205 | def test_mips_malta64eb_kernel3_2_0(self): | |
206 | """ | |
207 | :avocado: tags=arch:mips64 | |
208 | :avocado: tags=machine:malta | |
209 | :avocado: tags=endian:big | |
210 | :avocado: tags=device:pcnet32 | |
211 | """ | |
212 | kernel_url = ('https://people.debian.org/~aurel32/qemu/mips/' | |
213 | 'vmlinux-3.2.0-4-5kc-malta') | |
214 | kernel_hash = 'db6eea7de35d36c77d8c165b6bcb222e16eb91db' | |
215 | kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) | |
216 | self.do_test_mips_malta('be', kernel_path, 'mips64') | |
217 | ||
218 | @skipIf(os.getenv('CONTINUOUS_INTEGRATION'), 'Running on Travis-CI') | |
219 | def test_mips_malta64el_kernel3_2_0(self): | |
220 | """ | |
221 | :avocado: tags=arch:mips64el | |
222 | :avocado: tags=machine:malta | |
223 | :avocado: tags=endian:little | |
224 | :avocado: tags=device:pcnet32 | |
225 | """ | |
226 | kernel_url = ('https://people.debian.org/~aurel32/qemu/mipsel/' | |
227 | 'vmlinux-3.2.0-4-5kc-malta') | |
228 | kernel_hash = '6a7f77245acf231415a0e8b725d91ed2f3487794' | |
229 | kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) | |
230 | self.do_test_mips_malta('le', kernel_path, 'mips64') |