blob: deab59e3254094ed2053c19aa3f746dace427ad4 [file] [log] [blame]
lmr5c226e32009-07-27 13:13:01 +00001import time, os, logging, re, commands
lmr6f669ce2009-05-31 19:02:42 +00002from autotest_lib.client.common_lib import utils, error
lmrd85c55b2009-07-23 01:42:10 +00003import kvm_utils, kvm_subprocess, ppm_utils, scan_results
lmr6f669ce2009-05-31 19:02:42 +00004
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
lmr912c74b2009-08-17 20:43:27 +000032 session = kvm_utils.wait_for(vm.remote_login, 240, 0, 2)
lmr6f669ce2009-05-31 19:02:42 +000033 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
lmr912c74b2009-08-17 20:43:27 +000040 session.sendline(vm.get_params().get("reboot_command"))
lmr6f669ce2009-05-31 19:02:42 +000041 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
lmr912c74b2009-08-17 20:43:27 +000051 session = kvm_utils.wait_for(vm.remote_login, 240, 0, 2)
lmr6f669ce2009-05-31 19:02:42 +000052 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
lmr912c74b2009-08-17 20:43:27 +000079 session = kvm_utils.wait_for(vm.remote_login, 240, 0, 2)
lmr6faadb22009-06-18 14:57:45 +000080 if not session:
81 raise error.TestFail("Could not log into guest")
82
lmr20773742009-08-13 04:43:45 +000083 try:
84 logging.info("Logged in")
lmr6faadb22009-06-18 14:57:45 +000085
lmr20773742009-08-13 04:43:45 +000086 # Send the VM's shutdown command
lmr912c74b2009-08-17 20:43:27 +000087 session.sendline(vm.get_params().get("shutdown_command"))
lmr6faadb22009-06-18 14:57:45 +000088
lmr20773742009-08-13 04:43:45 +000089 logging.info("Shutdown command sent; waiting for guest to go down...")
lmr6faadb22009-06-18 14:57:45 +000090
lmr20773742009-08-13 04:43:45 +000091 if not kvm_utils.wait_for(vm.is_dead, 240, 0, 1):
92 raise error.TestFail("Guest refuses to go down")
lmr6faadb22009-06-18 14:57:45 +000093
lmr20773742009-08-13 04:43:45 +000094 logging.info("Guest is down")
95 finally:
96 session.close()
lmr6faadb22009-06-18 14:57:45 +000097
98
lmr6f669ce2009-05-31 19:02:42 +000099def run_migration(test, params, env):
100 """
101 KVM migration test:
lmr4d5cc792009-09-09 22:01:57 +0000102 1) Get a live VM and clone it.
103 2) Verify that 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.
lmr6f669ce2009-05-31 19:02:42 +0000108 4) Compare the output of a reference command executed on the source with
lmr4d5cc792009-09-09 22:01:57 +0000109 the output of the same command on the destination machine.
lmr6f669ce2009-05-31 19:02:42 +0000110
111 @param test: kvm test object.
112 @param params: Dictionary with test parameters.
113 @param env: Dictionary with the test environment.
114 """
lmr4d5cc792009-09-09 22:01:57 +0000115 vm = kvm_utils.env_get_vm(env, params.get("main_vm"))
lmr6f669ce2009-05-31 19:02:42 +0000116 if not vm:
lmr4d5cc792009-09-09 22:01:57 +0000117 raise error.TestError("VM object not found in environment")
lmr6f669ce2009-05-31 19:02:42 +0000118 if not vm.is_alive():
lmr4d5cc792009-09-09 22:01:57 +0000119 raise error.TestError("VM seems to be dead; Test requires a living VM")
lmr6f669ce2009-05-31 19:02:42 +0000120
121 # See if migration is supported
122 s, o = vm.send_monitor_cmd("help info")
123 if not "info migrate" in o:
124 raise error.TestError("Migration is not supported")
125
lmr4d5cc792009-09-09 22:01:57 +0000126 dest_vm = vm.clone()
127 dest_vm.create(for_migration=True)
128
lmr6f669ce2009-05-31 19:02:42 +0000129 # Log into guest and get the output of migration_test_command
130 logging.info("Waiting for guest to be up...")
131
lmr912c74b2009-08-17 20:43:27 +0000132 session = kvm_utils.wait_for(vm.remote_login, 240, 0, 2)
lmr6f669ce2009-05-31 19:02:42 +0000133 if not session:
134 raise error.TestFail("Could not log into guest")
135
136 logging.info("Logged in")
137
138 reference_output = session.get_command_output(params.get("migration_test_"
139 "command"))
140 session.close()
141
142 # Define the migration command
143 cmd = "migrate -d tcp:localhost:%d" % dest_vm.migration_port
144 logging.debug("Migration command: %s" % cmd)
145
146 # Migrate
147 s, o = vm.send_monitor_cmd(cmd)
148 if s:
149 logging.error("Migration command failed (command: %r, output: %r)" %
150 (cmd, o))
151 raise error.TestFail("Migration command failed")
152
153 # Define some helper functions
154 def mig_finished():
155 s, o = vm.send_monitor_cmd("info migrate")
lmr4d5cc792009-09-09 22:01:57 +0000156 return s == 0 and not "Migration status: active" in o
lmr6f669ce2009-05-31 19:02:42 +0000157
158 def mig_succeeded():
159 s, o = vm.send_monitor_cmd("info migrate")
lmr4d5cc792009-09-09 22:01:57 +0000160 return s == 0 and "Migration status: completed" in o
lmr6f669ce2009-05-31 19:02:42 +0000161
162 def mig_failed():
163 s, o = vm.send_monitor_cmd("info migrate")
lmr4d5cc792009-09-09 22:01:57 +0000164 return s == 0 and "Migration status: failed" in o
lmr6f669ce2009-05-31 19:02:42 +0000165
166 # Wait for migration to finish
167 if not kvm_utils.wait_for(mig_finished, 90, 2, 2,
168 "Waiting for migration to finish..."):
lmr4d5cc792009-09-09 22:01:57 +0000169 raise error.TestFail("Timeout elapsed while waiting for migration to "
lmr6f669ce2009-05-31 19:02:42 +0000170 "finish")
171
172 # Report migration status
173 if mig_succeeded():
174 logging.info("Migration finished successfully")
lmr4d5cc792009-09-09 22:01:57 +0000175 elif mig_failed():
176 raise error.TestFail("Migration failed")
lmr6f669ce2009-05-31 19:02:42 +0000177 else:
lmr4d5cc792009-09-09 22:01:57 +0000178 raise error.TestFail("Migration ended with unknown status")
lmr6f669ce2009-05-31 19:02:42 +0000179
180 # Kill the source VM
lmr4d5cc792009-09-09 22:01:57 +0000181 vm.destroy(gracefully=False)
lmr6f669ce2009-05-31 19:02:42 +0000182
183 # Log into guest and get the output of migration_test_command
184 logging.info("Logging into guest after migration...")
185
lmr912c74b2009-08-17 20:43:27 +0000186 session = dest_vm.remote_login()
lmr6f669ce2009-05-31 19:02:42 +0000187 if not session:
188 raise error.TestFail("Could not log into guest after migration")
189
190 logging.info("Logged in after migration")
191
192 output = session.get_command_output(params.get("migration_test_command"))
193 session.close()
194
195 # Compare output to reference output
196 if output != reference_output:
lmr4d5cc792009-09-09 22:01:57 +0000197 logging.info("Command output before migration differs from command "
198 "output after migration")
lmr6f669ce2009-05-31 19:02:42 +0000199 logging.info("Command: %s" % params.get("migration_test_command"))
200 logging.info("Output before:" +
201 kvm_utils.format_str_for_message(reference_output))
202 logging.info("Output after:" + kvm_utils.format_str_for_message(output))
lmr4d5cc792009-09-09 22:01:57 +0000203 raise error.TestFail("Command produced different output before and "
204 "after migration")
205
206 kvm_utils.env_register_vm(env, params.get("main_vm"), dest_vm)
lmr6f669ce2009-05-31 19:02:42 +0000207
208
209def run_autotest(test, params, env):
210 """
211 Run an autotest test inside a guest.
212
213 @param test: kvm test object.
214 @param params: Dictionary with test parameters.
215 @param env: Dictionary with the test environment.
216 """
217 vm = kvm_utils.env_get_vm(env, params.get("main_vm"))
218 if not vm:
219 raise error.TestError("VM object not found in environment")
220 if not vm.is_alive():
221 raise error.TestError("VM seems to be dead; Test requires a living VM")
222
223 logging.info("Logging into guest...")
224
lmr912c74b2009-08-17 20:43:27 +0000225 session = kvm_utils.wait_for(vm.remote_login, 240, 0, 2)
lmr6f669ce2009-05-31 19:02:42 +0000226 if not session:
227 raise error.TestFail("Could not log into guest")
228
229 logging.info("Logged in")
230
231 # Collect some info
232 test_name = params.get("test_name")
233 test_timeout = int(params.get("test_timeout", 300))
234 test_control_file = params.get("test_control_file", "control")
235 tarred_autotest_path = "/tmp/autotest.tar.bz2"
236 tarred_test_path = "/tmp/%s.tar.bz2" % test_name
237
238 # tar the contents of bindir/autotest
239 cmd = "cd %s; tar cvjf %s autotest/*"
240 cmd += " --exclude=autotest/tests"
241 cmd += " --exclude=autotest/results"
242 cmd += " --exclude=autotest/tmp"
243 cmd += " --exclude=autotest/control"
244 cmd += " --exclude=*.pyc"
245 cmd += " --exclude=*.svn"
246 cmd += " --exclude=*.git"
lmrd85c55b2009-07-23 01:42:10 +0000247 kvm_subprocess.run_fg(cmd % (test.bindir, tarred_autotest_path), timeout=30)
lmr6f669ce2009-05-31 19:02:42 +0000248
249 # tar the contents of bindir/autotest/tests/<test_name>
250 cmd = "cd %s; tar cvjf %s %s/*"
251 cmd += " --exclude=*.pyc"
252 cmd += " --exclude=*.svn"
253 cmd += " --exclude=*.git"
lmrd85c55b2009-07-23 01:42:10 +0000254 kvm_subprocess.run_fg(cmd %
255 (os.path.join(test.bindir, "autotest", "tests"),
256 tarred_test_path, test_name), timeout=30)
lmr6f669ce2009-05-31 19:02:42 +0000257
258 # Check if we need to copy autotest.tar.bz2
259 copy = False
260 output = session.get_command_output("ls -l autotest.tar.bz2")
261 if "such file" in output:
262 copy = True
263 else:
264 size = int(output.split()[4])
265 if size != os.path.getsize(tarred_autotest_path):
266 copy = True
267 # Perform the copy
268 if copy:
269 logging.info("Copying autotest.tar.bz2 to guest"
270 " (file is missing or has a different size)...")
lmr912c74b2009-08-17 20:43:27 +0000271 if not vm.copy_files_to(tarred_autotest_path, ""):
lmr6f669ce2009-05-31 19:02:42 +0000272 raise error.TestFail("Could not copy autotest.tar.bz2 to guest")
273
274 # Check if we need to copy <test_name>.tar.bz2
275 copy = False
276 output = session.get_command_output("ls -l %s.tar.bz2" % test_name)
277 if "such file" in output:
278 copy = True
279 else:
280 size = int(output.split()[4])
281 if size != os.path.getsize(tarred_test_path):
282 copy = True
283 # Perform the copy
284 if copy:
285 logging.info("Copying %s.tar.bz2 to guest (file is missing or has a"
286 " different size)..." % test_name)
lmr912c74b2009-08-17 20:43:27 +0000287 if not vm.copy_files_to(tarred_test_path, ""):
lmr6f669ce2009-05-31 19:02:42 +0000288 raise error.TestFail("Could not copy %s.tar.bz2 to guest" %
289 test_name)
290
291 # Extract autotest.tar.bz2
292 logging.info("Extracting autotest.tar.bz2...")
293 status = session.get_command_status("tar xvfj autotest.tar.bz2")
294 if status != 0:
295 raise error.TestFail("Could not extract autotest.tar.bz2")
296
297 # mkdir autotest/tests
298 session.sendline("mkdir autotest/tests")
299
300 # Extract <test_name>.tar.bz2 into autotest/tests
301 logging.info("Extracting %s.tar.bz2..." % test_name)
302 status = session.get_command_status("tar xvfj %s.tar.bz2 -C "
303 "autotest/tests" % test_name)
304 if status != 0:
305 raise error.TestFail("Could not extract %s.tar.bz2" % test_name)
306
lmr16cf1652009-06-15 21:32:49 +0000307 # Cleaning up old remaining results
308 session.sendline("rm -rf autotest/results/*")
309 # Copying the selected control file (located inside
310 # test.bindir/autotest_control to the autotest dir
311 control_file_path = os.path.join(test.bindir, "autotest_control",
312 test_control_file)
lmr912c74b2009-08-17 20:43:27 +0000313 if not vm.copy_files_to(control_file_path, "autotest/control"):
lmr16cf1652009-06-15 21:32:49 +0000314 raise error.TestFail("Could not copy the test control file to guest")
lmr6f669ce2009-05-31 19:02:42 +0000315 # Run the test
316 logging.info("Running test '%s'..." % test_name)
lmr16cf1652009-06-15 21:32:49 +0000317 session.sendline("cd autotest")
318 session.sendline("rm -f control.state")
lmr6f669ce2009-05-31 19:02:42 +0000319 session.read_up_to_prompt()
lmr16cf1652009-06-15 21:32:49 +0000320 session.sendline("bin/autotest control")
lmr6f669ce2009-05-31 19:02:42 +0000321 logging.info("---------------- Test output ----------------")
lmr16cf1652009-06-15 21:32:49 +0000322 match = session.read_up_to_prompt(timeout=test_timeout,
323 print_func=logging.info)[0]
lmr6f669ce2009-05-31 19:02:42 +0000324 logging.info("---------------- End of test output ----------------")
325 if not match:
lmr16cf1652009-06-15 21:32:49 +0000326 raise error.TestFail("Timeout elapsed while waiting for test to "
327 "complete")
328 # Get the results generated by autotest
329 output = session.get_command_output("cat results/*/status")
lmr6f669ce2009-05-31 19:02:42 +0000330
331 # Parse test results
332 result_list = scan_results.parse_results(output)
333
334 # Report test results and check for FAIL/ERROR status
335 logging.info("Results (test, status, duration, info):")
336 status_error = False
337 status_fail = False
338 if result_list == []:
339 status_fail = True
lmrd16a67d2009-06-10 19:52:59 +0000340 message_fail = ("Test '%s' did not produce any recognizable "
341 "results" % test_name)
lmr6f669ce2009-05-31 19:02:42 +0000342 for result in result_list:
343 logging.info(str(result))
344 if result[1] == "FAIL":
345 status_fail = True
lmr50bece42009-06-15 20:54:43 +0000346 message_fail = ("Test '%s' ended with FAIL "
347 "(info: '%s')" % (result[0], result[3]))
lmr6f669ce2009-05-31 19:02:42 +0000348 if result[1] == "ERROR":
349 status_error = True
lmr50bece42009-06-15 20:54:43 +0000350 message_error = ("Test '%s' ended with ERROR "
351 "(info: '%s')" % (result[0], result[3]))
lmr6f669ce2009-05-31 19:02:42 +0000352 if result[1] == "ABORT":
353 status_error = True
lmr50bece42009-06-15 20:54:43 +0000354 message_error = ("Test '%s' ended with ABORT "
355 "(info: '%s')" % (result[0], result[3]))
lmr6f669ce2009-05-31 19:02:42 +0000356
357 # Copy test results to the local bindir/guest_results
358 logging.info("Copying results back from guest...")
359 guest_results_dir = os.path.join(test.outputdir, "guest_results")
360 if not os.path.exists(guest_results_dir):
361 os.mkdir(guest_results_dir)
lmr912c74b2009-08-17 20:43:27 +0000362 if not vm.copy_files_from("autotest/results/default/*", guest_results_dir):
lmr6f669ce2009-05-31 19:02:42 +0000363 logging.error("Could not copy results back from guest")
364
365 # Fail the test if necessary
366 if status_fail:
367 raise error.TestFail(message_fail)
368 elif status_error:
369 raise error.TestError(message_error)
370
371
372def internal_yum_update(session, command, prompt, timeout):
373 """
374 Helper function to perform the yum update test.
375
lmr912c74b2009-08-17 20:43:27 +0000376 @param session: shell session stablished to the host
377 @param command: Command to be sent to the shell session
lmr6f669ce2009-05-31 19:02:42 +0000378 @param prompt: Machine prompt
379 @param timeout: How long to wait until we get an appropriate output from
lmr912c74b2009-08-17 20:43:27 +0000380 the shell session.
lmr6f669ce2009-05-31 19:02:42 +0000381 """
382 session.sendline(command)
383 end_time = time.time() + timeout
384 while time.time() < end_time:
385 (match, text) = session.read_until_last_line_matches(
386 ["[Ii]s this [Oo][Kk]", prompt], timeout=timeout)
387 if match == 0:
388 logging.info("Got 'Is this ok'; sending 'y'")
389 session.sendline("y")
390 elif match == 1:
391 logging.info("Got shell prompt")
392 return True
393 else:
394 logging.info("Timeout or process exited")
395 return False
396
397
398def run_yum_update(test, params, env):
399 """
400 Runs yum update and yum update kernel on the remote host (yum enabled
401 hosts only).
402
403 @param test: kvm test object.
404 @param params: Dictionary with test parameters.
405 @param env: Dictionary with the test environment.
406 """
407 vm = kvm_utils.env_get_vm(env, params.get("main_vm"))
408 if not vm:
409 message = "VM object not found in environment"
410 logging.error(message)
411 raise error.TestError(message)
412 if not vm.is_alive():
413 message = "VM seems to be dead; Test requires a living VM"
414 logging.error(message)
415 raise error.TestError(message)
416
417 logging.info("Logging into guest...")
418
lmr912c74b2009-08-17 20:43:27 +0000419 session = kvm_utils.wait_for(vm.remote_login, 240, 0, 2)
lmr6f669ce2009-05-31 19:02:42 +0000420 if not session:
421 message = "Could not log into guest"
422 logging.error(message)
423 raise error.TestFail(message)
424
425 logging.info("Logged in")
426
lmr912c74b2009-08-17 20:43:27 +0000427 internal_yum_update(session, "yum update", params.get("shell_prompt"), 600)
lmr6f669ce2009-05-31 19:02:42 +0000428 internal_yum_update(session, "yum update kernel",
lmr912c74b2009-08-17 20:43:27 +0000429 params.get("shell_prompt"), 600)
lmr6f669ce2009-05-31 19:02:42 +0000430
431 session.close()
432
433
434def run_linux_s3(test, params, env):
435 """
436 Suspend a guest Linux OS to memory.
437
438 @param test: kvm test object.
439 @param params: Dictionary with test parameters.
440 @param env: Dictionary with the test environment.
441 """
442 vm = kvm_utils.env_get_vm(env, params.get("main_vm"))
443 if not vm:
444 raise error.TestError("VM object not found in environment")
445 if not vm.is_alive():
446 raise error.TestError("VM seems to be dead; Test requires a living VM")
447
448 logging.info("Waiting for guest to be up...")
449
lmr912c74b2009-08-17 20:43:27 +0000450 session = kvm_utils.wait_for(vm.remote_login, 240, 0, 2)
lmr6f669ce2009-05-31 19:02:42 +0000451 if not session:
452 raise error.TestFail("Could not log into guest")
453
454 logging.info("Logged in")
455 logging.info("Checking that VM supports S3")
456
457 status = session.get_command_status("grep -q mem /sys/power/state")
458 if status == None:
459 logging.error("Failed to check if S3 exists")
460 elif status != 0:
461 raise error.TestFail("Guest does not support S3")
462
463 logging.info("Waiting for a while for X to start")
464 time.sleep(10)
465
466 src_tty = session.get_command_output("fgconsole").strip()
467 logging.info("Current virtual terminal is %s" % src_tty)
468 if src_tty not in map(str, range(1,10)):
469 raise error.TestFail("Got a strange current vt (%s)" % src_tty)
470
471 dst_tty = "1"
472 if src_tty == "1":
473 dst_tty = "2"
474
475 logging.info("Putting VM into S3")
476 command = "chvt %s && echo mem > /sys/power/state && chvt %s" % (dst_tty,
477 src_tty)
478 status = session.get_command_status(command, timeout=120)
479 if status != 0:
480 raise error.TestFail("Suspend to mem failed")
481
482 logging.info("VM resumed after S3")
483
484 session.close()
lmra04d7c92009-06-19 13:05:39 +0000485
486
487def run_stress_boot(tests, params, env):
488 """
489 Boots VMs until one of them becomes unresponsive, and records the maximum
490 number of VMs successfully started:
491 1) boot the first vm
492 2) boot the second vm cloned from the first vm, check whether it boots up
lmr912c74b2009-08-17 20:43:27 +0000493 and all booted vms respond to shell commands
lmra04d7c92009-06-19 13:05:39 +0000494 3) go on until cannot create VM anymore or cannot allocate memory for VM
495
496 @param test: kvm test object
497 @param params: Dictionary with the test parameters
498 @param env: Dictionary with test environment.
499 """
500 # boot the first vm
501 vm = kvm_utils.env_get_vm(env, params.get("main_vm"))
lmra04d7c92009-06-19 13:05:39 +0000502 if not vm:
503 raise error.TestError("VM object not found in environment")
504 if not vm.is_alive():
505 raise error.TestError("VM seems to be dead; Test requires a living VM")
506
507 logging.info("Waiting for first guest to be up...")
508
lmr912c74b2009-08-17 20:43:27 +0000509 session = kvm_utils.wait_for(vm.remote_login, 240, 0, 2)
lmra04d7c92009-06-19 13:05:39 +0000510 if not session:
511 raise error.TestFail("Could not log into first guest")
512
513 num = 2
lmra04d7c92009-06-19 13:05:39 +0000514 sessions = [session]
lmr26bac242009-08-13 04:14:24 +0000515 address_index = int(params.get("clone_address_index_base", 10))
lmra04d7c92009-06-19 13:05:39 +0000516
517 # boot the VMs
518 while num <= int(params.get("max_vms")):
519 try:
520 vm_name = "vm" + str(num)
521
522 # clone vm according to the first one
lmr26bac242009-08-13 04:14:24 +0000523 vm_params = vm.get_params().copy()
524 vm_params["address_index"] = str(address_index)
lmra04d7c92009-06-19 13:05:39 +0000525 curr_vm = vm.clone(vm_name, vm_params)
526 kvm_utils.env_register_vm(env, vm_name, curr_vm)
527 params['vms'] += " " + vm_name
528
lmra04d7c92009-06-19 13:05:39 +0000529 logging.info("Booting guest #%d" % num)
530 if not curr_vm.create():
531 raise error.TestFail("Cannot create VM #%d" % num)
532
lmr912c74b2009-08-17 20:43:27 +0000533 curr_vm_session = kvm_utils.wait_for(curr_vm.remote_login, 240, 0, 2)
lmra04d7c92009-06-19 13:05:39 +0000534 if not curr_vm_session:
535 raise error.TestFail("Could not log into guest #%d" % num)
536
537 logging.info("Guest #%d boots up successfully" % num)
538 sessions.append(curr_vm_session)
539
lmr912c74b2009-08-17 20:43:27 +0000540 # check whether all previous shell sessions are responsive
lmr26bac242009-08-13 04:14:24 +0000541 for i, se in enumerate(sessions):
542 if se.get_command_status(params.get("alive_test_cmd")) != 0:
lmra04d7c92009-06-19 13:05:39 +0000543 raise error.TestFail("Session #%d is not responsive" % i)
544 num += 1
lmr26bac242009-08-13 04:14:24 +0000545 address_index += 1
lmra04d7c92009-06-19 13:05:39 +0000546
547 except (error.TestFail, OSError):
548 for se in sessions:
549 se.close()
550 logging.info("Total number booted: %d" % (num - 1))
551 raise
552 else:
553 for se in sessions:
554 se.close()
555 logging.info("Total number booted: %d" % (num -1))
lmr5c226e32009-07-27 13:13:01 +0000556
557
558def run_timedrift(test, params, env):
559 """
560 Time drift test (mainly for Windows guests):
561
562 1) Log into a guest.
563 2) Take a time reading from the guest and host.
564 3) Run load on the guest and host.
565 4) Take a second time reading.
566 5) Stop the load and rest for a while.
567 6) Take a third time reading.
568 7) If the drift immediately after load is higher than a user-
569 specified value (in %), fail.
570 If the drift after the rest period is higher than a user-specified value,
571 fail.
572
573 @param test: KVM test object.
574 @param params: Dictionary with test parameters.
575 @param env: Dictionary with the test environment.
576 """
lmr25e89fc2009-08-07 20:29:16 +0000577 # Helper functions
578 def set_cpu_affinity(pid, mask):
579 """
580 Set the CPU affinity of all threads of the process with PID pid.
lmr152da2d2009-09-09 22:16:21 +0000581 Do this recursively for all child processes as well.
lmr25e89fc2009-08-07 20:29:16 +0000582
583 @param pid: The process ID.
584 @param mask: The CPU affinity mask.
585 @return: A dict containing the previous mask for each thread.
586 """
587 tids = commands.getoutput("ps -L --pid=%s -o lwp=" % pid).split()
588 prev_masks = {}
589 for tid in tids:
590 prev_mask = commands.getoutput("taskset -p %s" % tid).split()[-1]
591 prev_masks[tid] = prev_mask
592 commands.getoutput("taskset -p %s %s" % (mask, tid))
lmr152da2d2009-09-09 22:16:21 +0000593 children = commands.getoutput("ps --ppid=%s -o pid=" % pid).split()
594 for child in children:
595 prev_masks.update(set_cpu_affinity(child, mask))
lmr25e89fc2009-08-07 20:29:16 +0000596 return prev_masks
597
598 def restore_cpu_affinity(prev_masks):
599 """
600 Restore the CPU affinity of several threads.
601
602 @param prev_masks: A dict containing TIDs as keys and masks as values.
603 """
604 for tid, mask in prev_masks.items():
605 commands.getoutput("taskset -p %s %s" % (mask, tid))
606
lmrff2a7c52009-08-10 00:09:22 +0000607 def get_time(session, time_command, time_filter_re, time_format):
lmr25e89fc2009-08-07 20:29:16 +0000608 """
609 Returns the host time and guest time.
610
lmrff2a7c52009-08-10 00:09:22 +0000611 @param session: A shell session.
612 @param time_command: Command to issue to get the current guest time.
613 @param time_filter_re: Regex filter to apply on the output of
614 time_command in order to get the current time.
615 @param time_format: Format string to pass to time.strptime() with the
616 result of the regex filter.
lmr25e89fc2009-08-07 20:29:16 +0000617 @return: A tuple containing the host time and guest time.
618 """
619 host_time = time.time()
620 session.sendline(time_command)
621 (match, s) = session.read_up_to_prompt()
622 s = re.findall(time_filter_re, s)[0]
623 guest_time = time.mktime(time.strptime(s, time_format))
624 return (host_time, guest_time)
625
lmr5c226e32009-07-27 13:13:01 +0000626 vm = kvm_utils.env_get_vm(env, params.get("main_vm"))
627 if not vm:
628 raise error.TestError("VM object not found in environment")
629 if not vm.is_alive():
630 raise error.TestError("VM seems to be dead; Test requires a living VM")
631
632 logging.info("Waiting for guest to be up...")
633
lmr912c74b2009-08-17 20:43:27 +0000634 session = kvm_utils.wait_for(vm.remote_login, 240, 0, 2)
lmr5c226e32009-07-27 13:13:01 +0000635 if not session:
636 raise error.TestFail("Could not log into guest")
637
638 logging.info("Logged in")
639
640 # Collect test parameters:
641 # Command to run to get the current time
642 time_command = params.get("time_command")
643 # Filter which should match a string to be passed to time.strptime()
644 time_filter_re = params.get("time_filter_re")
645 # Time format for time.strptime()
646 time_format = params.get("time_format")
647 guest_load_command = params.get("guest_load_command")
648 guest_load_stop_command = params.get("guest_load_stop_command")
649 host_load_command = params.get("host_load_command")
650 guest_load_instances = int(params.get("guest_load_instances", "1"))
651 host_load_instances = int(params.get("host_load_instances", "0"))
652 # CPU affinity mask for taskset
653 cpu_mask = params.get("cpu_mask", "0xFF")
654 load_duration = float(params.get("load_duration", "30"))
655 rest_duration = float(params.get("rest_duration", "10"))
656 drift_threshold = float(params.get("drift_threshold", "200"))
657 drift_threshold_after_rest = float(params.get("drift_threshold_after_rest",
658 "200"))
659
660 guest_load_sessions = []
661 host_load_sessions = []
662
lmr5c226e32009-07-27 13:13:01 +0000663 # Set the VM's CPU affinity
lmr25e89fc2009-08-07 20:29:16 +0000664 prev_affinity = set_cpu_affinity(vm.get_pid(), cpu_mask)
lmr5c226e32009-07-27 13:13:01 +0000665
666 try:
667 # Get time before load
lmrff2a7c52009-08-10 00:09:22 +0000668 (host_time_0, guest_time_0) = get_time(session, time_command,
669 time_filter_re, time_format)
lmr5c226e32009-07-27 13:13:01 +0000670
671 # Run some load on the guest
672 logging.info("Starting load on guest...")
673 for i in range(guest_load_instances):
lmr912c74b2009-08-17 20:43:27 +0000674 load_session = vm.remote_login()
lmr5c226e32009-07-27 13:13:01 +0000675 if not load_session:
676 raise error.TestFail("Could not log into guest")
677 load_session.set_output_prefix("(guest load %d) " % i)
678 load_session.set_output_func(logging.debug)
679 load_session.sendline(guest_load_command)
680 guest_load_sessions.append(load_session)
681
682 # Run some load on the host
683 logging.info("Starting load on host...")
684 for i in range(host_load_instances):
685 host_load_sessions.append(
686 kvm_subprocess.run_bg(host_load_command,
687 output_func=logging.debug,
688 output_prefix="(host load %d) " % i,
689 timeout=0.5))
lmr152da2d2009-09-09 22:16:21 +0000690 # Set the CPU affinity of the load process
lmr5c226e32009-07-27 13:13:01 +0000691 pid = host_load_sessions[-1].get_shell_pid()
lmr25e89fc2009-08-07 20:29:16 +0000692 set_cpu_affinity(pid, cpu_mask)
lmr5c226e32009-07-27 13:13:01 +0000693
694 # Sleep for a while (during load)
695 logging.info("Sleeping for %s seconds..." % load_duration)
696 time.sleep(load_duration)
697
698 # Get time delta after load
lmrff2a7c52009-08-10 00:09:22 +0000699 (host_time_1, guest_time_1) = get_time(session, time_command,
700 time_filter_re, time_format)
lmr5c226e32009-07-27 13:13:01 +0000701
702 # Report results
703 host_delta = host_time_1 - host_time_0
704 guest_delta = guest_time_1 - guest_time_0
705 drift = 100.0 * (host_delta - guest_delta) / host_delta
706 logging.info("Host duration: %.2f" % host_delta)
707 logging.info("Guest duration: %.2f" % guest_delta)
708 logging.info("Drift: %.2f%%" % drift)
709
710 finally:
711 logging.info("Cleaning up...")
712 # Restore the VM's CPU affinity
lmr25e89fc2009-08-07 20:29:16 +0000713 restore_cpu_affinity(prev_affinity)
lmr5c226e32009-07-27 13:13:01 +0000714 # Stop the guest load
715 if guest_load_stop_command:
716 session.get_command_output(guest_load_stop_command)
717 # Close all load shell sessions
718 for load_session in guest_load_sessions:
719 load_session.close()
720 for load_session in host_load_sessions:
721 load_session.close()
722
723 # Sleep again (rest)
724 logging.info("Sleeping for %s seconds..." % rest_duration)
725 time.sleep(rest_duration)
726
727 # Get time after rest
lmrff2a7c52009-08-10 00:09:22 +0000728 (host_time_2, guest_time_2) = get_time(session, time_command,
729 time_filter_re, time_format)
lmr5c226e32009-07-27 13:13:01 +0000730
731 # Report results
732 host_delta_total = host_time_2 - host_time_0
733 guest_delta_total = guest_time_2 - guest_time_0
734 drift_total = 100.0 * (host_delta_total - guest_delta_total) / host_delta
735 logging.info("Total host duration including rest: %.2f" % host_delta_total)
736 logging.info("Total guest duration including rest: %.2f" % guest_delta_total)
737 logging.info("Total drift after rest: %.2f%%" % drift_total)
738
lmr5b829602009-08-07 20:36:06 +0000739 session.close()
740
lmr5c226e32009-07-27 13:13:01 +0000741 # Fail the test if necessary
742 if drift > drift_threshold:
743 raise error.TestFail("Time drift too large: %.2f%%" % drift)
lmr67bf4442009-08-28 17:29:45 +0000744 if drift_total > drift_threshold_after_rest:
lmr5c226e32009-07-27 13:13:01 +0000745 raise error.TestFail("Time drift too large after rest period: %.2f%%"
746 % drift_total)
lmr3efa0bd2009-08-18 20:00:56 +0000747
748
749def run_autoit(test, params, env):
750 """
751 A wrapper for AutoIt scripts.
752
753 1) Log into a guest.
754 2) Run AutoIt script.
755 3) Wait for script execution to complete.
756 4) Pass/fail according to exit status of script.
757
758 @param test: KVM test object.
759 @param params: Dictionary with test parameters.
760 @param env: Dictionary with the test environment.
761 """
762 vm = kvm_utils.env_get_vm(env, params.get("main_vm"))
763 if not vm:
764 raise error.TestError("VM object not found in environment")
765 if not vm.is_alive():
766 raise error.TestError("VM seems to be dead; Test requires a living VM")
767
768 logging.info("Waiting for guest to be up...")
769
770 session = kvm_utils.wait_for(vm.remote_login, 240, 0, 2)
771 if not session:
772 raise error.TestFail("Could not log into guest")
773
774 try:
775 logging.info("Logged in; starting script...")
776
777 # Collect test parameters
778 binary = params.get("autoit_binary")
779 script = params.get("autoit_script")
780 script_params = params.get("autoit_script_params", "")
781 timeout = float(params.get("autoit_script_timeout", 600))
782
783 # Send AutoIt script to guest (this code will be replaced once we
784 # support sending files to Windows guests)
785 session.sendline("del script.au3")
786 file = open(kvm_utils.get_path(test.bindir, script))
787 for line in file.readlines():
788 # Insert a '^' before each character
789 line = "".join("^" + c for c in line.rstrip())
790 if line:
791 # Append line to the file
792 session.sendline("echo %s>>script.au3" % line)
793 file.close()
794
795 session.read_up_to_prompt()
796
797 command = "cmd /c %s script.au3 %s" % (binary, script_params)
798
799 logging.info("---------------- Script output ----------------")
800 status = session.get_command_status(command,
801 print_func=logging.info,
802 timeout=timeout)
803 logging.info("---------------- End of script output ----------------")
804
805 if status is None:
806 raise error.TestFail("Timeout expired before script execution "
807 "completed (or something weird happened)")
808 if status != 0:
809 raise error.TestFail("Script execution failed")
810
811 finally:
812 session.close()