blob: 1852886e54873cf4f80224fa32b2d36d3ef65cd9 [file] [log] [blame]
lmr6f669ce2009-05-31 19:02:42 +00001import time, os, logging
2from autotest_lib.client.common_lib import utils, error
3import kvm_utils, ppm_utils, scan_results
4
5"""
6KVM test definitions.
7
8@copyright: 2008-2009 Red Hat Inc.
9"""
10
11
12def run_boot(test, params, env):
13 """
14 KVM reboot test:
15 1) Log into a guest
16 2) Send a reboot command to the guest
17 3) Wait until it's up.
18 4) Log into the guest to verify it's up again.
19
20 @param test: kvm test object
21 @param params: Dictionary with the test parameters
22 @param env: Dictionary with test environment.
23 """
24 vm = kvm_utils.env_get_vm(env, params.get("main_vm"))
25 if not vm:
26 raise error.TestError("VM object not found in environment")
27 if not vm.is_alive():
28 raise error.TestError("VM seems to be dead; Test requires a living VM")
29
30 logging.info("Waiting for guest to be up...")
31
32 session = kvm_utils.wait_for(vm.ssh_login, 240, 0, 2)
33 if not session:
34 raise error.TestFail("Could not log into guest")
35
36 logging.info("Logged in")
37
38 if params.get("reboot") == "yes":
39 # Send the VM's reboot command
40 session.sendline(vm.get_params().get("cmd_reboot"))
41 logging.info("Reboot command sent; waiting for guest to go down...")
42
43 if not kvm_utils.wait_for(lambda: not session.is_responsive(),
44 120, 0, 1):
45 raise error.TestFail("Guest refuses to go down")
46
47 session.close()
48
49 logging.info("Guest is down; waiting for it to go up again...")
50
51 session = kvm_utils.wait_for(vm.ssh_login, 120, 0, 2)
52 if not session:
53 raise error.TestFail("Could not log into guest after reboot")
54
55 logging.info("Guest is up again")
56
57 session.close()
58
59
lmr6faadb22009-06-18 14:57:45 +000060def run_shutdown(test, params, env):
61 """
62 KVM shutdown test:
63 1) Log into a guest
64 2) Send a shutdown command to the guest
65 3) Wait until it's down
66
67 @param test: kvm test object
68 @param params: Dictionary with the test parameters
69 @param env: Dictionary with test environment
70 """
71 vm = kvm_utils.env_get_vm(env, params.get("main_vm"))
72 if not vm:
73 raise error.TestError("VM object not found in environment")
74 if not vm.is_alive():
75 raise error.TestError("VM seems to be dead; Test requires a living VM")
76
77 logging.info("Waiting for guest to be up...")
78
79 session = kvm_utils.wait_for(vm.ssh_login, 240, 0, 2)
80 if not session:
81 raise error.TestFail("Could not log into guest")
82
83 logging.info("Logged in")
84
85 # Send the VM's shutdown command
86 session.sendline(vm.get_params().get("cmd_shutdown"))
87 session.close()
88
89 logging.info("Shutdown command sent; waiting for guest to go down...")
90
91 if not kvm_utils.wait_for(vm.is_dead, 120, 0, 1):
92 raise error.TestFail("Guest refuses to go down")
93
94 logging.info("Guest is down")
95
96
lmr6f669ce2009-05-31 19:02:42 +000097def run_migration(test, params, env):
98 """
99 KVM migration test:
100
101 1) Get two live VMs. One will be the 'source', the other will be the
102 'destination'.
103 2) Verify if the source VM supports migration. If it does, proceed with
104 the test
105 3) Send a migration command to the source vm and wait until it's finished.
106 4) Kill off the source vm
107 3) Log into the destination vm after the migration is finished.
108 4) Compare the output of a reference command executed on the source with
109 the output of the same command on the destination machine
110
111 @param test: kvm test object.
112 @param params: Dictionary with test parameters.
113 @param env: Dictionary with the test environment.
114 """
115 src_vm_name = params.get("migration_src")
116 vm = kvm_utils.env_get_vm(env, src_vm_name)
117 if not vm:
118 raise error.TestError("VM '%s' not found in environment" % src_vm_name)
119 if not vm.is_alive():
120 raise error.TestError("VM '%s' seems to be dead; Test requires a"
121 " living VM" % src_vm_name)
122
123 dest_vm_name = params.get("migration_dst")
124 dest_vm = kvm_utils.env_get_vm(env, dest_vm_name)
125 if not dest_vm:
126 raise error.TestError("VM '%s' not found in environment" % dest_vm_name)
127 if not dest_vm.is_alive():
128 raise error.TestError("VM '%s' seems to be dead; Test requires a"
129 " living VM" % dest_vm_name)
130
131 pre_scrdump_filename = os.path.join(test.debugdir, "migration_pre.ppm")
132 post_scrdump_filename = os.path.join(test.debugdir, "migration_post.ppm")
133
134 # See if migration is supported
135 s, o = vm.send_monitor_cmd("help info")
136 if not "info migrate" in o:
137 raise error.TestError("Migration is not supported")
138
139 # Log into guest and get the output of migration_test_command
140 logging.info("Waiting for guest to be up...")
141
142 session = kvm_utils.wait_for(vm.ssh_login, 240, 0, 2)
143 if not session:
144 raise error.TestFail("Could not log into guest")
145
146 logging.info("Logged in")
147
148 reference_output = session.get_command_output(params.get("migration_test_"
149 "command"))
150 session.close()
151
152 # Define the migration command
153 cmd = "migrate -d tcp:localhost:%d" % dest_vm.migration_port
154 logging.debug("Migration command: %s" % cmd)
155
156 # Migrate
157 s, o = vm.send_monitor_cmd(cmd)
158 if s:
159 logging.error("Migration command failed (command: %r, output: %r)" %
160 (cmd, o))
161 raise error.TestFail("Migration command failed")
162
163 # Define some helper functions
164 def mig_finished():
165 s, o = vm.send_monitor_cmd("info migrate")
166 if s:
167 return False
168 if "Migration status: active" in o:
169 return False
170 return True
171
172 def mig_succeeded():
173 s, o = vm.send_monitor_cmd("info migrate")
174 if s == 0 and "Migration status: completed" in o:
175 return True
176 return False
177
178 def mig_failed():
179 s, o = vm.send_monitor_cmd("info migrate")
180 if s == 0 and "Migration status: failed" in o:
181 return True
182 return False
183
184 # Wait for migration to finish
185 if not kvm_utils.wait_for(mig_finished, 90, 2, 2,
186 "Waiting for migration to finish..."):
187 raise error.TestFail("Timeout elapsed while waiting for migration to"
188 "finish")
189
190 # Report migration status
191 if mig_succeeded():
192 logging.info("Migration finished successfully")
193 else:
194 if mig_failed():
195 message = "Migration failed"
196 else:
197 message = "Migration ended with unknown status"
198 raise error.TestFail(message)
199
200 # Get 'post' screendump
201 dest_vm.send_monitor_cmd("screendump %s" % post_scrdump_filename)
202
203 # Get 'pre' screendump
204 vm.send_monitor_cmd("screendump %s" % pre_scrdump_filename)
205
206 # Kill the source VM
207 vm.send_monitor_cmd("quit", block=False)
208
209 # Hack: it seems that the first attempt to communicate with the SSH port
210 # following migration always fails (or succeeds after a very long time).
211 # So just connect to the port once so the following call to ssh_login
212 # succeeds.
213 dest_vm.is_sshd_running(timeout=0.0)
214
215 # Log into guest and get the output of migration_test_command
216 logging.info("Logging into guest after migration...")
217
218 session = dest_vm.ssh_login()
219 if not session:
220 raise error.TestFail("Could not log into guest after migration")
221
222 logging.info("Logged in after migration")
223
224 output = session.get_command_output(params.get("migration_test_command"))
225 session.close()
226
227 # Compare output to reference output
228 if output != reference_output:
229 logging.info("Command output before migration differs from command"
230 " output after migration")
231 logging.info("Command: %s" % params.get("migration_test_command"))
232 logging.info("Output before:" +
233 kvm_utils.format_str_for_message(reference_output))
234 logging.info("Output after:" + kvm_utils.format_str_for_message(output))
235 raise error.TestFail("Command produced different output before and"
236 " after migration")
237
238
239def run_autotest(test, params, env):
240 """
241 Run an autotest test inside a guest.
242
243 @param test: kvm test object.
244 @param params: Dictionary with test parameters.
245 @param env: Dictionary with the test environment.
246 """
247 vm = kvm_utils.env_get_vm(env, params.get("main_vm"))
248 if not vm:
249 raise error.TestError("VM object not found in environment")
250 if not vm.is_alive():
251 raise error.TestError("VM seems to be dead; Test requires a living VM")
252
253 logging.info("Logging into guest...")
254
255 session = kvm_utils.wait_for(vm.ssh_login, 240, 0, 2)
256 if not session:
257 raise error.TestFail("Could not log into guest")
258
259 logging.info("Logged in")
260
261 # Collect some info
262 test_name = params.get("test_name")
263 test_timeout = int(params.get("test_timeout", 300))
264 test_control_file = params.get("test_control_file", "control")
265 tarred_autotest_path = "/tmp/autotest.tar.bz2"
266 tarred_test_path = "/tmp/%s.tar.bz2" % test_name
267
268 # tar the contents of bindir/autotest
269 cmd = "cd %s; tar cvjf %s autotest/*"
270 cmd += " --exclude=autotest/tests"
271 cmd += " --exclude=autotest/results"
272 cmd += " --exclude=autotest/tmp"
273 cmd += " --exclude=autotest/control"
274 cmd += " --exclude=*.pyc"
275 cmd += " --exclude=*.svn"
276 cmd += " --exclude=*.git"
277 kvm_utils.run_bg(cmd % (test.bindir, tarred_autotest_path), timeout=30)
278
279 # tar the contents of bindir/autotest/tests/<test_name>
280 cmd = "cd %s; tar cvjf %s %s/*"
281 cmd += " --exclude=*.pyc"
282 cmd += " --exclude=*.svn"
283 cmd += " --exclude=*.git"
284 kvm_utils.run_bg(cmd % (os.path.join(test.bindir, "autotest", "tests"),
285 tarred_test_path, test_name), timeout=30)
286
287 # Check if we need to copy autotest.tar.bz2
288 copy = False
289 output = session.get_command_output("ls -l autotest.tar.bz2")
290 if "such file" in output:
291 copy = True
292 else:
293 size = int(output.split()[4])
294 if size != os.path.getsize(tarred_autotest_path):
295 copy = True
296 # Perform the copy
297 if copy:
298 logging.info("Copying autotest.tar.bz2 to guest"
299 " (file is missing or has a different size)...")
300 if not vm.scp_to_remote(tarred_autotest_path, ""):
301 raise error.TestFail("Could not copy autotest.tar.bz2 to guest")
302
303 # Check if we need to copy <test_name>.tar.bz2
304 copy = False
305 output = session.get_command_output("ls -l %s.tar.bz2" % test_name)
306 if "such file" in output:
307 copy = True
308 else:
309 size = int(output.split()[4])
310 if size != os.path.getsize(tarred_test_path):
311 copy = True
312 # Perform the copy
313 if copy:
314 logging.info("Copying %s.tar.bz2 to guest (file is missing or has a"
315 " different size)..." % test_name)
316 if not vm.scp_to_remote(tarred_test_path, ""):
317 raise error.TestFail("Could not copy %s.tar.bz2 to guest" %
318 test_name)
319
320 # Extract autotest.tar.bz2
321 logging.info("Extracting autotest.tar.bz2...")
322 status = session.get_command_status("tar xvfj autotest.tar.bz2")
323 if status != 0:
324 raise error.TestFail("Could not extract autotest.tar.bz2")
325
326 # mkdir autotest/tests
327 session.sendline("mkdir autotest/tests")
328
329 # Extract <test_name>.tar.bz2 into autotest/tests
330 logging.info("Extracting %s.tar.bz2..." % test_name)
331 status = session.get_command_status("tar xvfj %s.tar.bz2 -C "
332 "autotest/tests" % test_name)
333 if status != 0:
334 raise error.TestFail("Could not extract %s.tar.bz2" % test_name)
335
lmr16cf1652009-06-15 21:32:49 +0000336 # Cleaning up old remaining results
337 session.sendline("rm -rf autotest/results/*")
338 # Copying the selected control file (located inside
339 # test.bindir/autotest_control to the autotest dir
340 control_file_path = os.path.join(test.bindir, "autotest_control",
341 test_control_file)
342 if not vm.scp_to_remote(control_file_path, "autotest/control"):
343 raise error.TestFail("Could not copy the test control file to guest")
lmr6f669ce2009-05-31 19:02:42 +0000344 # Run the test
345 logging.info("Running test '%s'..." % test_name)
lmr16cf1652009-06-15 21:32:49 +0000346 session.sendline("cd autotest")
347 session.sendline("rm -f control.state")
lmr6f669ce2009-05-31 19:02:42 +0000348 session.read_up_to_prompt()
lmr16cf1652009-06-15 21:32:49 +0000349 session.sendline("bin/autotest control")
lmr6f669ce2009-05-31 19:02:42 +0000350 logging.info("---------------- Test output ----------------")
lmr16cf1652009-06-15 21:32:49 +0000351 match = session.read_up_to_prompt(timeout=test_timeout,
352 print_func=logging.info)[0]
lmr6f669ce2009-05-31 19:02:42 +0000353 logging.info("---------------- End of test output ----------------")
354 if not match:
lmr16cf1652009-06-15 21:32:49 +0000355 raise error.TestFail("Timeout elapsed while waiting for test to "
356 "complete")
357 # Get the results generated by autotest
358 output = session.get_command_output("cat results/*/status")
lmr6f669ce2009-05-31 19:02:42 +0000359
360 # Parse test results
361 result_list = scan_results.parse_results(output)
362
363 # Report test results and check for FAIL/ERROR status
364 logging.info("Results (test, status, duration, info):")
365 status_error = False
366 status_fail = False
367 if result_list == []:
368 status_fail = True
lmrd16a67d2009-06-10 19:52:59 +0000369 message_fail = ("Test '%s' did not produce any recognizable "
370 "results" % test_name)
lmr6f669ce2009-05-31 19:02:42 +0000371 for result in result_list:
372 logging.info(str(result))
373 if result[1] == "FAIL":
374 status_fail = True
lmr50bece42009-06-15 20:54:43 +0000375 message_fail = ("Test '%s' ended with FAIL "
376 "(info: '%s')" % (result[0], result[3]))
lmr6f669ce2009-05-31 19:02:42 +0000377 if result[1] == "ERROR":
378 status_error = True
lmr50bece42009-06-15 20:54:43 +0000379 message_error = ("Test '%s' ended with ERROR "
380 "(info: '%s')" % (result[0], result[3]))
lmr6f669ce2009-05-31 19:02:42 +0000381 if result[1] == "ABORT":
382 status_error = True
lmr50bece42009-06-15 20:54:43 +0000383 message_error = ("Test '%s' ended with ABORT "
384 "(info: '%s')" % (result[0], result[3]))
lmr6f669ce2009-05-31 19:02:42 +0000385
386 # Copy test results to the local bindir/guest_results
387 logging.info("Copying results back from guest...")
388 guest_results_dir = os.path.join(test.outputdir, "guest_results")
389 if not os.path.exists(guest_results_dir):
390 os.mkdir(guest_results_dir)
391 if not vm.scp_from_remote("autotest/results/default/*", guest_results_dir):
392 logging.error("Could not copy results back from guest")
393
394 # Fail the test if necessary
395 if status_fail:
396 raise error.TestFail(message_fail)
397 elif status_error:
398 raise error.TestError(message_error)
399
400
401def internal_yum_update(session, command, prompt, timeout):
402 """
403 Helper function to perform the yum update test.
404
405 @param session: SSH session stablished to the host
406 @param command: Command to be sent to the SSH connection
407 @param prompt: Machine prompt
408 @param timeout: How long to wait until we get an appropriate output from
409 the SSH session.
410 """
411 session.sendline(command)
412 end_time = time.time() + timeout
413 while time.time() < end_time:
414 (match, text) = session.read_until_last_line_matches(
415 ["[Ii]s this [Oo][Kk]", prompt], timeout=timeout)
416 if match == 0:
417 logging.info("Got 'Is this ok'; sending 'y'")
418 session.sendline("y")
419 elif match == 1:
420 logging.info("Got shell prompt")
421 return True
422 else:
423 logging.info("Timeout or process exited")
424 return False
425
426
427def run_yum_update(test, params, env):
428 """
429 Runs yum update and yum update kernel on the remote host (yum enabled
430 hosts only).
431
432 @param test: kvm test object.
433 @param params: Dictionary with test parameters.
434 @param env: Dictionary with the test environment.
435 """
436 vm = kvm_utils.env_get_vm(env, params.get("main_vm"))
437 if not vm:
438 message = "VM object not found in environment"
439 logging.error(message)
440 raise error.TestError(message)
441 if not vm.is_alive():
442 message = "VM seems to be dead; Test requires a living VM"
443 logging.error(message)
444 raise error.TestError(message)
445
446 logging.info("Logging into guest...")
447
448 session = kvm_utils.wait_for(vm.ssh_login, 120, 0, 2)
449 if not session:
450 message = "Could not log into guest"
451 logging.error(message)
452 raise error.TestFail(message)
453
454 logging.info("Logged in")
455
456 internal_yum_update(session, "yum update", params.get("ssh_prompt"), 600)
457 internal_yum_update(session, "yum update kernel",
458 params.get("ssh_prompt"), 600)
459
460 session.close()
461
462
463def run_linux_s3(test, params, env):
464 """
465 Suspend a guest Linux OS to memory.
466
467 @param test: kvm test object.
468 @param params: Dictionary with test parameters.
469 @param env: Dictionary with the test environment.
470 """
471 vm = kvm_utils.env_get_vm(env, params.get("main_vm"))
472 if not vm:
473 raise error.TestError("VM object not found in environment")
474 if not vm.is_alive():
475 raise error.TestError("VM seems to be dead; Test requires a living VM")
476
477 logging.info("Waiting for guest to be up...")
478
479 session = kvm_utils.wait_for(vm.ssh_login, 240, 0, 2)
480 if not session:
481 raise error.TestFail("Could not log into guest")
482
483 logging.info("Logged in")
484 logging.info("Checking that VM supports S3")
485
486 status = session.get_command_status("grep -q mem /sys/power/state")
487 if status == None:
488 logging.error("Failed to check if S3 exists")
489 elif status != 0:
490 raise error.TestFail("Guest does not support S3")
491
492 logging.info("Waiting for a while for X to start")
493 time.sleep(10)
494
495 src_tty = session.get_command_output("fgconsole").strip()
496 logging.info("Current virtual terminal is %s" % src_tty)
497 if src_tty not in map(str, range(1,10)):
498 raise error.TestFail("Got a strange current vt (%s)" % src_tty)
499
500 dst_tty = "1"
501 if src_tty == "1":
502 dst_tty = "2"
503
504 logging.info("Putting VM into S3")
505 command = "chvt %s && echo mem > /sys/power/state && chvt %s" % (dst_tty,
506 src_tty)
507 status = session.get_command_status(command, timeout=120)
508 if status != 0:
509 raise error.TestFail("Suspend to mem failed")
510
511 logging.info("VM resumed after S3")
512
513 session.close()