blob: 801b84ed05d0a2bbf8555c4a78b762c25605d5a8 [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
lmr9ce347d2009-09-09 22:26:53 +000016 2) Send a reboot command or a system_reset monitor command (optional)
17 3) Wait until the guest is up again
18 4) Log into the guest to verify it's up again
lmr6f669ce2009-05-31 19:02:42 +000019
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
lmr9ce347d2009-09-09 22:26:53 +000036 try:
37 logging.info("Logged in")
lmr6f669ce2009-05-31 19:02:42 +000038
lmr9ce347d2009-09-09 22:26:53 +000039 if params.get("reboot_method") == "shell":
40 # Send a reboot command to the guest's shell
41 session.sendline(vm.get_params().get("reboot_command"))
42 logging.info("Reboot command sent; waiting for guest to go "
43 "down...")
44 elif params.get("reboot_method") == "system_reset":
45 # Sleep for a while -- give the guest a chance to finish booting
46 time.sleep(float(params.get("sleep_before_reset", 10)))
47 # Send a system_reset monitor command
48 vm.send_monitor_cmd("system_reset")
49 logging.info("system_reset monitor command sent; waiting for "
50 "guest to go down...")
51 else: return
lmr6f669ce2009-05-31 19:02:42 +000052
lmr9ce347d2009-09-09 22:26:53 +000053 # Wait for the session to become unresponsive
lmr6f669ce2009-05-31 19:02:42 +000054 if not kvm_utils.wait_for(lambda: not session.is_responsive(),
55 120, 0, 1):
56 raise error.TestFail("Guest refuses to go down")
57
58 session.close()
59
60 logging.info("Guest is down; waiting for it to go up again...")
61
lmr912c74b2009-08-17 20:43:27 +000062 session = kvm_utils.wait_for(vm.remote_login, 240, 0, 2)
lmr6f669ce2009-05-31 19:02:42 +000063 if not session:
64 raise error.TestFail("Could not log into guest after reboot")
65
66 logging.info("Guest is up again")
67
lmr9ce347d2009-09-09 22:26:53 +000068 finally:
69 session.close()
lmr6f669ce2009-05-31 19:02:42 +000070
71
lmr6faadb22009-06-18 14:57:45 +000072def run_shutdown(test, params, env):
73 """
74 KVM shutdown test:
75 1) Log into a guest
76 2) Send a shutdown command to the guest
77 3) Wait until it's down
78
79 @param test: kvm test object
80 @param params: Dictionary with the test parameters
81 @param env: Dictionary with test environment
82 """
83 vm = kvm_utils.env_get_vm(env, params.get("main_vm"))
84 if not vm:
85 raise error.TestError("VM object not found in environment")
86 if not vm.is_alive():
87 raise error.TestError("VM seems to be dead; Test requires a living VM")
88
89 logging.info("Waiting for guest to be up...")
90
lmr912c74b2009-08-17 20:43:27 +000091 session = kvm_utils.wait_for(vm.remote_login, 240, 0, 2)
lmr6faadb22009-06-18 14:57:45 +000092 if not session:
93 raise error.TestFail("Could not log into guest")
94
lmr20773742009-08-13 04:43:45 +000095 try:
96 logging.info("Logged in")
lmr6faadb22009-06-18 14:57:45 +000097
lmr20773742009-08-13 04:43:45 +000098 # Send the VM's shutdown command
lmr912c74b2009-08-17 20:43:27 +000099 session.sendline(vm.get_params().get("shutdown_command"))
lmr6faadb22009-06-18 14:57:45 +0000100
lmr20773742009-08-13 04:43:45 +0000101 logging.info("Shutdown command sent; waiting for guest to go down...")
lmr6faadb22009-06-18 14:57:45 +0000102
lmr20773742009-08-13 04:43:45 +0000103 if not kvm_utils.wait_for(vm.is_dead, 240, 0, 1):
104 raise error.TestFail("Guest refuses to go down")
lmr6faadb22009-06-18 14:57:45 +0000105
lmr20773742009-08-13 04:43:45 +0000106 logging.info("Guest is down")
107 finally:
108 session.close()
lmr6faadb22009-06-18 14:57:45 +0000109
110
lmr6f669ce2009-05-31 19:02:42 +0000111def run_migration(test, params, env):
112 """
113 KVM migration test:
lmr4d5cc792009-09-09 22:01:57 +0000114 1) Get a live VM and clone it.
115 2) Verify that the source VM supports migration. If it does, proceed with
116 the test.
117 3) Send a migration command to the source VM and wait until it's finished.
118 4) Kill off the source VM.
119 3) Log into the destination VM after the migration is finished.
lmr6f669ce2009-05-31 19:02:42 +0000120 4) Compare the output of a reference command executed on the source with
lmr4d5cc792009-09-09 22:01:57 +0000121 the output of the same command on the destination machine.
lmr6f669ce2009-05-31 19:02:42 +0000122
123 @param test: kvm test object.
124 @param params: Dictionary with test parameters.
125 @param env: Dictionary with the test environment.
126 """
lmr4d5cc792009-09-09 22:01:57 +0000127 vm = kvm_utils.env_get_vm(env, params.get("main_vm"))
lmr6f669ce2009-05-31 19:02:42 +0000128 if not vm:
lmr4d5cc792009-09-09 22:01:57 +0000129 raise error.TestError("VM object not found in environment")
lmr6f669ce2009-05-31 19:02:42 +0000130 if not vm.is_alive():
lmr4d5cc792009-09-09 22:01:57 +0000131 raise error.TestError("VM seems to be dead; Test requires a living VM")
lmr6f669ce2009-05-31 19:02:42 +0000132
133 # See if migration is supported
134 s, o = vm.send_monitor_cmd("help info")
135 if not "info migrate" in o:
136 raise error.TestError("Migration is not supported")
137
lmr4d5cc792009-09-09 22:01:57 +0000138 dest_vm = vm.clone()
139 dest_vm.create(for_migration=True)
140
lmr6f669ce2009-05-31 19:02:42 +0000141 # Log into guest and get the output of migration_test_command
142 logging.info("Waiting for guest to be up...")
143
lmr912c74b2009-08-17 20:43:27 +0000144 session = kvm_utils.wait_for(vm.remote_login, 240, 0, 2)
lmr6f669ce2009-05-31 19:02:42 +0000145 if not session:
146 raise error.TestFail("Could not log into guest")
147
148 logging.info("Logged in")
149
150 reference_output = session.get_command_output(params.get("migration_test_"
151 "command"))
152 session.close()
153
154 # Define the migration command
155 cmd = "migrate -d tcp:localhost:%d" % dest_vm.migration_port
156 logging.debug("Migration command: %s" % cmd)
157
158 # Migrate
159 s, o = vm.send_monitor_cmd(cmd)
160 if s:
161 logging.error("Migration command failed (command: %r, output: %r)" %
162 (cmd, o))
163 raise error.TestFail("Migration command failed")
164
165 # Define some helper functions
166 def mig_finished():
167 s, o = vm.send_monitor_cmd("info migrate")
lmr4d5cc792009-09-09 22:01:57 +0000168 return s == 0 and not "Migration status: active" in o
lmr6f669ce2009-05-31 19:02:42 +0000169
170 def mig_succeeded():
171 s, o = vm.send_monitor_cmd("info migrate")
lmr4d5cc792009-09-09 22:01:57 +0000172 return s == 0 and "Migration status: completed" in o
lmr6f669ce2009-05-31 19:02:42 +0000173
174 def mig_failed():
175 s, o = vm.send_monitor_cmd("info migrate")
lmr4d5cc792009-09-09 22:01:57 +0000176 return s == 0 and "Migration status: failed" in o
lmr6f669ce2009-05-31 19:02:42 +0000177
178 # Wait for migration to finish
179 if not kvm_utils.wait_for(mig_finished, 90, 2, 2,
180 "Waiting for migration to finish..."):
lmr4d5cc792009-09-09 22:01:57 +0000181 raise error.TestFail("Timeout elapsed while waiting for migration to "
lmr6f669ce2009-05-31 19:02:42 +0000182 "finish")
183
184 # Report migration status
185 if mig_succeeded():
186 logging.info("Migration finished successfully")
lmr4d5cc792009-09-09 22:01:57 +0000187 elif mig_failed():
188 raise error.TestFail("Migration failed")
lmr6f669ce2009-05-31 19:02:42 +0000189 else:
lmr4d5cc792009-09-09 22:01:57 +0000190 raise error.TestFail("Migration ended with unknown status")
lmr6f669ce2009-05-31 19:02:42 +0000191
192 # Kill the source VM
lmr4d5cc792009-09-09 22:01:57 +0000193 vm.destroy(gracefully=False)
lmr6f669ce2009-05-31 19:02:42 +0000194
195 # Log into guest and get the output of migration_test_command
196 logging.info("Logging into guest after migration...")
197
lmr912c74b2009-08-17 20:43:27 +0000198 session = dest_vm.remote_login()
lmr6f669ce2009-05-31 19:02:42 +0000199 if not session:
200 raise error.TestFail("Could not log into guest after migration")
201
202 logging.info("Logged in after migration")
203
204 output = session.get_command_output(params.get("migration_test_command"))
205 session.close()
206
207 # Compare output to reference output
208 if output != reference_output:
lmr4d5cc792009-09-09 22:01:57 +0000209 logging.info("Command output before migration differs from command "
210 "output after migration")
lmr6f669ce2009-05-31 19:02:42 +0000211 logging.info("Command: %s" % params.get("migration_test_command"))
212 logging.info("Output before:" +
213 kvm_utils.format_str_for_message(reference_output))
214 logging.info("Output after:" + kvm_utils.format_str_for_message(output))
lmr4d5cc792009-09-09 22:01:57 +0000215 raise error.TestFail("Command produced different output before and "
216 "after migration")
217
218 kvm_utils.env_register_vm(env, params.get("main_vm"), dest_vm)
lmr6f669ce2009-05-31 19:02:42 +0000219
220
221def run_autotest(test, params, env):
222 """
223 Run an autotest test inside a guest.
224
225 @param test: kvm test object.
226 @param params: Dictionary with test parameters.
227 @param env: Dictionary with the test environment.
228 """
229 vm = kvm_utils.env_get_vm(env, params.get("main_vm"))
230 if not vm:
231 raise error.TestError("VM object not found in environment")
232 if not vm.is_alive():
233 raise error.TestError("VM seems to be dead; Test requires a living VM")
234
235 logging.info("Logging into guest...")
236
lmr912c74b2009-08-17 20:43:27 +0000237 session = kvm_utils.wait_for(vm.remote_login, 240, 0, 2)
lmr6f669ce2009-05-31 19:02:42 +0000238 if not session:
239 raise error.TestFail("Could not log into guest")
240
241 logging.info("Logged in")
242
243 # Collect some info
244 test_name = params.get("test_name")
245 test_timeout = int(params.get("test_timeout", 300))
246 test_control_file = params.get("test_control_file", "control")
247 tarred_autotest_path = "/tmp/autotest.tar.bz2"
248 tarred_test_path = "/tmp/%s.tar.bz2" % test_name
249
250 # tar the contents of bindir/autotest
251 cmd = "cd %s; tar cvjf %s autotest/*"
252 cmd += " --exclude=autotest/tests"
253 cmd += " --exclude=autotest/results"
254 cmd += " --exclude=autotest/tmp"
255 cmd += " --exclude=autotest/control"
256 cmd += " --exclude=*.pyc"
257 cmd += " --exclude=*.svn"
258 cmd += " --exclude=*.git"
lmrd85c55b2009-07-23 01:42:10 +0000259 kvm_subprocess.run_fg(cmd % (test.bindir, tarred_autotest_path), timeout=30)
lmr6f669ce2009-05-31 19:02:42 +0000260
261 # tar the contents of bindir/autotest/tests/<test_name>
262 cmd = "cd %s; tar cvjf %s %s/*"
263 cmd += " --exclude=*.pyc"
264 cmd += " --exclude=*.svn"
265 cmd += " --exclude=*.git"
lmrd85c55b2009-07-23 01:42:10 +0000266 kvm_subprocess.run_fg(cmd %
267 (os.path.join(test.bindir, "autotest", "tests"),
268 tarred_test_path, test_name), timeout=30)
lmr6f669ce2009-05-31 19:02:42 +0000269
270 # Check if we need to copy autotest.tar.bz2
271 copy = False
272 output = session.get_command_output("ls -l autotest.tar.bz2")
273 if "such file" in output:
274 copy = True
275 else:
276 size = int(output.split()[4])
277 if size != os.path.getsize(tarred_autotest_path):
278 copy = True
279 # Perform the copy
280 if copy:
281 logging.info("Copying autotest.tar.bz2 to guest"
282 " (file is missing or has a different size)...")
lmr912c74b2009-08-17 20:43:27 +0000283 if not vm.copy_files_to(tarred_autotest_path, ""):
lmr6f669ce2009-05-31 19:02:42 +0000284 raise error.TestFail("Could not copy autotest.tar.bz2 to guest")
285
286 # Check if we need to copy <test_name>.tar.bz2
287 copy = False
288 output = session.get_command_output("ls -l %s.tar.bz2" % test_name)
289 if "such file" in output:
290 copy = True
291 else:
292 size = int(output.split()[4])
293 if size != os.path.getsize(tarred_test_path):
294 copy = True
295 # Perform the copy
296 if copy:
297 logging.info("Copying %s.tar.bz2 to guest (file is missing or has a"
298 " different size)..." % test_name)
lmr912c74b2009-08-17 20:43:27 +0000299 if not vm.copy_files_to(tarred_test_path, ""):
lmr6f669ce2009-05-31 19:02:42 +0000300 raise error.TestFail("Could not copy %s.tar.bz2 to guest" %
301 test_name)
302
303 # Extract autotest.tar.bz2
304 logging.info("Extracting autotest.tar.bz2...")
305 status = session.get_command_status("tar xvfj autotest.tar.bz2")
306 if status != 0:
307 raise error.TestFail("Could not extract autotest.tar.bz2")
308
309 # mkdir autotest/tests
310 session.sendline("mkdir autotest/tests")
311
312 # Extract <test_name>.tar.bz2 into autotest/tests
313 logging.info("Extracting %s.tar.bz2..." % test_name)
314 status = session.get_command_status("tar xvfj %s.tar.bz2 -C "
315 "autotest/tests" % test_name)
316 if status != 0:
317 raise error.TestFail("Could not extract %s.tar.bz2" % test_name)
318
lmr16cf1652009-06-15 21:32:49 +0000319 # Cleaning up old remaining results
320 session.sendline("rm -rf autotest/results/*")
321 # Copying the selected control file (located inside
322 # test.bindir/autotest_control to the autotest dir
323 control_file_path = os.path.join(test.bindir, "autotest_control",
324 test_control_file)
lmr912c74b2009-08-17 20:43:27 +0000325 if not vm.copy_files_to(control_file_path, "autotest/control"):
lmr16cf1652009-06-15 21:32:49 +0000326 raise error.TestFail("Could not copy the test control file to guest")
lmr6f669ce2009-05-31 19:02:42 +0000327 # Run the test
328 logging.info("Running test '%s'..." % test_name)
lmr16cf1652009-06-15 21:32:49 +0000329 session.sendline("cd autotest")
330 session.sendline("rm -f control.state")
lmr6f669ce2009-05-31 19:02:42 +0000331 session.read_up_to_prompt()
lmr16cf1652009-06-15 21:32:49 +0000332 session.sendline("bin/autotest control")
lmr6f669ce2009-05-31 19:02:42 +0000333 logging.info("---------------- Test output ----------------")
lmr16cf1652009-06-15 21:32:49 +0000334 match = session.read_up_to_prompt(timeout=test_timeout,
335 print_func=logging.info)[0]
lmr6f669ce2009-05-31 19:02:42 +0000336 logging.info("---------------- End of test output ----------------")
337 if not match:
lmr16cf1652009-06-15 21:32:49 +0000338 raise error.TestFail("Timeout elapsed while waiting for test to "
339 "complete")
340 # Get the results generated by autotest
341 output = session.get_command_output("cat results/*/status")
lmr6f669ce2009-05-31 19:02:42 +0000342
343 # Parse test results
344 result_list = scan_results.parse_results(output)
345
346 # Report test results and check for FAIL/ERROR status
347 logging.info("Results (test, status, duration, info):")
348 status_error = False
349 status_fail = False
350 if result_list == []:
351 status_fail = True
lmrd16a67d2009-06-10 19:52:59 +0000352 message_fail = ("Test '%s' did not produce any recognizable "
353 "results" % test_name)
lmr6f669ce2009-05-31 19:02:42 +0000354 for result in result_list:
355 logging.info(str(result))
356 if result[1] == "FAIL":
357 status_fail = True
lmr50bece42009-06-15 20:54:43 +0000358 message_fail = ("Test '%s' ended with FAIL "
359 "(info: '%s')" % (result[0], result[3]))
lmr6f669ce2009-05-31 19:02:42 +0000360 if result[1] == "ERROR":
361 status_error = True
lmr50bece42009-06-15 20:54:43 +0000362 message_error = ("Test '%s' ended with ERROR "
363 "(info: '%s')" % (result[0], result[3]))
lmr6f669ce2009-05-31 19:02:42 +0000364 if result[1] == "ABORT":
365 status_error = True
lmr50bece42009-06-15 20:54:43 +0000366 message_error = ("Test '%s' ended with ABORT "
367 "(info: '%s')" % (result[0], result[3]))
lmr6f669ce2009-05-31 19:02:42 +0000368
369 # Copy test results to the local bindir/guest_results
370 logging.info("Copying results back from guest...")
371 guest_results_dir = os.path.join(test.outputdir, "guest_results")
372 if not os.path.exists(guest_results_dir):
373 os.mkdir(guest_results_dir)
lmr912c74b2009-08-17 20:43:27 +0000374 if not vm.copy_files_from("autotest/results/default/*", guest_results_dir):
lmr6f669ce2009-05-31 19:02:42 +0000375 logging.error("Could not copy results back from guest")
376
377 # Fail the test if necessary
378 if status_fail:
379 raise error.TestFail(message_fail)
380 elif status_error:
381 raise error.TestError(message_error)
382
383
384def internal_yum_update(session, command, prompt, timeout):
385 """
386 Helper function to perform the yum update test.
387
lmr912c74b2009-08-17 20:43:27 +0000388 @param session: shell session stablished to the host
389 @param command: Command to be sent to the shell session
lmr6f669ce2009-05-31 19:02:42 +0000390 @param prompt: Machine prompt
391 @param timeout: How long to wait until we get an appropriate output from
lmr912c74b2009-08-17 20:43:27 +0000392 the shell session.
lmr6f669ce2009-05-31 19:02:42 +0000393 """
394 session.sendline(command)
395 end_time = time.time() + timeout
396 while time.time() < end_time:
397 (match, text) = session.read_until_last_line_matches(
398 ["[Ii]s this [Oo][Kk]", prompt], timeout=timeout)
399 if match == 0:
400 logging.info("Got 'Is this ok'; sending 'y'")
401 session.sendline("y")
402 elif match == 1:
403 logging.info("Got shell prompt")
404 return True
405 else:
406 logging.info("Timeout or process exited")
407 return False
408
409
410def run_yum_update(test, params, env):
411 """
412 Runs yum update and yum update kernel on the remote host (yum enabled
413 hosts only).
414
415 @param test: kvm test object.
416 @param params: Dictionary with test parameters.
417 @param env: Dictionary with the test environment.
418 """
419 vm = kvm_utils.env_get_vm(env, params.get("main_vm"))
420 if not vm:
421 message = "VM object not found in environment"
422 logging.error(message)
423 raise error.TestError(message)
424 if not vm.is_alive():
425 message = "VM seems to be dead; Test requires a living VM"
426 logging.error(message)
427 raise error.TestError(message)
428
429 logging.info("Logging into guest...")
430
lmr912c74b2009-08-17 20:43:27 +0000431 session = kvm_utils.wait_for(vm.remote_login, 240, 0, 2)
lmr6f669ce2009-05-31 19:02:42 +0000432 if not session:
433 message = "Could not log into guest"
434 logging.error(message)
435 raise error.TestFail(message)
436
437 logging.info("Logged in")
438
lmr912c74b2009-08-17 20:43:27 +0000439 internal_yum_update(session, "yum update", params.get("shell_prompt"), 600)
lmr6f669ce2009-05-31 19:02:42 +0000440 internal_yum_update(session, "yum update kernel",
lmr912c74b2009-08-17 20:43:27 +0000441 params.get("shell_prompt"), 600)
lmr6f669ce2009-05-31 19:02:42 +0000442
443 session.close()
444
445
446def run_linux_s3(test, params, env):
447 """
448 Suspend a guest Linux OS to memory.
449
450 @param test: kvm test object.
451 @param params: Dictionary with test parameters.
452 @param env: Dictionary with the test environment.
453 """
454 vm = kvm_utils.env_get_vm(env, params.get("main_vm"))
455 if not vm:
456 raise error.TestError("VM object not found in environment")
457 if not vm.is_alive():
458 raise error.TestError("VM seems to be dead; Test requires a living VM")
459
460 logging.info("Waiting for guest to be up...")
461
lmr912c74b2009-08-17 20:43:27 +0000462 session = kvm_utils.wait_for(vm.remote_login, 240, 0, 2)
lmr6f669ce2009-05-31 19:02:42 +0000463 if not session:
464 raise error.TestFail("Could not log into guest")
465
466 logging.info("Logged in")
467 logging.info("Checking that VM supports S3")
468
469 status = session.get_command_status("grep -q mem /sys/power/state")
470 if status == None:
471 logging.error("Failed to check if S3 exists")
472 elif status != 0:
473 raise error.TestFail("Guest does not support S3")
474
475 logging.info("Waiting for a while for X to start")
476 time.sleep(10)
477
478 src_tty = session.get_command_output("fgconsole").strip()
479 logging.info("Current virtual terminal is %s" % src_tty)
480 if src_tty not in map(str, range(1,10)):
481 raise error.TestFail("Got a strange current vt (%s)" % src_tty)
482
483 dst_tty = "1"
484 if src_tty == "1":
485 dst_tty = "2"
486
487 logging.info("Putting VM into S3")
488 command = "chvt %s && echo mem > /sys/power/state && chvt %s" % (dst_tty,
489 src_tty)
490 status = session.get_command_status(command, timeout=120)
491 if status != 0:
492 raise error.TestFail("Suspend to mem failed")
493
494 logging.info("VM resumed after S3")
495
496 session.close()
lmra04d7c92009-06-19 13:05:39 +0000497
498
499def run_stress_boot(tests, params, env):
500 """
501 Boots VMs until one of them becomes unresponsive, and records the maximum
502 number of VMs successfully started:
503 1) boot the first vm
504 2) boot the second vm cloned from the first vm, check whether it boots up
lmr912c74b2009-08-17 20:43:27 +0000505 and all booted vms respond to shell commands
lmra04d7c92009-06-19 13:05:39 +0000506 3) go on until cannot create VM anymore or cannot allocate memory for VM
507
508 @param test: kvm test object
509 @param params: Dictionary with the test parameters
510 @param env: Dictionary with test environment.
511 """
512 # boot the first vm
513 vm = kvm_utils.env_get_vm(env, params.get("main_vm"))
lmra04d7c92009-06-19 13:05:39 +0000514 if not vm:
515 raise error.TestError("VM object not found in environment")
516 if not vm.is_alive():
517 raise error.TestError("VM seems to be dead; Test requires a living VM")
518
519 logging.info("Waiting for first guest to be up...")
520
lmr912c74b2009-08-17 20:43:27 +0000521 session = kvm_utils.wait_for(vm.remote_login, 240, 0, 2)
lmra04d7c92009-06-19 13:05:39 +0000522 if not session:
523 raise error.TestFail("Could not log into first guest")
524
525 num = 2
lmra04d7c92009-06-19 13:05:39 +0000526 sessions = [session]
lmr26bac242009-08-13 04:14:24 +0000527 address_index = int(params.get("clone_address_index_base", 10))
lmra04d7c92009-06-19 13:05:39 +0000528
529 # boot the VMs
530 while num <= int(params.get("max_vms")):
531 try:
532 vm_name = "vm" + str(num)
533
534 # clone vm according to the first one
lmr26bac242009-08-13 04:14:24 +0000535 vm_params = vm.get_params().copy()
536 vm_params["address_index"] = str(address_index)
lmra04d7c92009-06-19 13:05:39 +0000537 curr_vm = vm.clone(vm_name, vm_params)
538 kvm_utils.env_register_vm(env, vm_name, curr_vm)
539 params['vms'] += " " + vm_name
540
lmra04d7c92009-06-19 13:05:39 +0000541 logging.info("Booting guest #%d" % num)
542 if not curr_vm.create():
543 raise error.TestFail("Cannot create VM #%d" % num)
544
lmr912c74b2009-08-17 20:43:27 +0000545 curr_vm_session = kvm_utils.wait_for(curr_vm.remote_login, 240, 0, 2)
lmra04d7c92009-06-19 13:05:39 +0000546 if not curr_vm_session:
547 raise error.TestFail("Could not log into guest #%d" % num)
548
549 logging.info("Guest #%d boots up successfully" % num)
550 sessions.append(curr_vm_session)
551
lmr912c74b2009-08-17 20:43:27 +0000552 # check whether all previous shell sessions are responsive
lmr26bac242009-08-13 04:14:24 +0000553 for i, se in enumerate(sessions):
554 if se.get_command_status(params.get("alive_test_cmd")) != 0:
lmra04d7c92009-06-19 13:05:39 +0000555 raise error.TestFail("Session #%d is not responsive" % i)
556 num += 1
lmr26bac242009-08-13 04:14:24 +0000557 address_index += 1
lmra04d7c92009-06-19 13:05:39 +0000558
559 except (error.TestFail, OSError):
560 for se in sessions:
561 se.close()
562 logging.info("Total number booted: %d" % (num - 1))
563 raise
564 else:
565 for se in sessions:
566 se.close()
567 logging.info("Total number booted: %d" % (num -1))
lmr5c226e32009-07-27 13:13:01 +0000568
569
570def run_timedrift(test, params, env):
571 """
572 Time drift test (mainly for Windows guests):
573
574 1) Log into a guest.
575 2) Take a time reading from the guest and host.
576 3) Run load on the guest and host.
577 4) Take a second time reading.
578 5) Stop the load and rest for a while.
579 6) Take a third time reading.
580 7) If the drift immediately after load is higher than a user-
581 specified value (in %), fail.
582 If the drift after the rest period is higher than a user-specified value,
583 fail.
584
585 @param test: KVM test object.
586 @param params: Dictionary with test parameters.
587 @param env: Dictionary with the test environment.
588 """
lmr25e89fc2009-08-07 20:29:16 +0000589 # Helper functions
590 def set_cpu_affinity(pid, mask):
591 """
592 Set the CPU affinity of all threads of the process with PID pid.
lmr152da2d2009-09-09 22:16:21 +0000593 Do this recursively for all child processes as well.
lmr25e89fc2009-08-07 20:29:16 +0000594
595 @param pid: The process ID.
596 @param mask: The CPU affinity mask.
597 @return: A dict containing the previous mask for each thread.
598 """
599 tids = commands.getoutput("ps -L --pid=%s -o lwp=" % pid).split()
600 prev_masks = {}
601 for tid in tids:
602 prev_mask = commands.getoutput("taskset -p %s" % tid).split()[-1]
603 prev_masks[tid] = prev_mask
604 commands.getoutput("taskset -p %s %s" % (mask, tid))
lmr152da2d2009-09-09 22:16:21 +0000605 children = commands.getoutput("ps --ppid=%s -o pid=" % pid).split()
606 for child in children:
607 prev_masks.update(set_cpu_affinity(child, mask))
lmr25e89fc2009-08-07 20:29:16 +0000608 return prev_masks
609
610 def restore_cpu_affinity(prev_masks):
611 """
612 Restore the CPU affinity of several threads.
613
614 @param prev_masks: A dict containing TIDs as keys and masks as values.
615 """
616 for tid, mask in prev_masks.items():
617 commands.getoutput("taskset -p %s %s" % (mask, tid))
618
lmrff2a7c52009-08-10 00:09:22 +0000619 def get_time(session, time_command, time_filter_re, time_format):
lmr25e89fc2009-08-07 20:29:16 +0000620 """
621 Returns the host time and guest time.
622
lmrff2a7c52009-08-10 00:09:22 +0000623 @param session: A shell session.
624 @param time_command: Command to issue to get the current guest time.
625 @param time_filter_re: Regex filter to apply on the output of
626 time_command in order to get the current time.
627 @param time_format: Format string to pass to time.strptime() with the
628 result of the regex filter.
lmr25e89fc2009-08-07 20:29:16 +0000629 @return: A tuple containing the host time and guest time.
630 """
631 host_time = time.time()
632 session.sendline(time_command)
633 (match, s) = session.read_up_to_prompt()
634 s = re.findall(time_filter_re, s)[0]
635 guest_time = time.mktime(time.strptime(s, time_format))
636 return (host_time, guest_time)
637
lmr5c226e32009-07-27 13:13:01 +0000638 vm = kvm_utils.env_get_vm(env, params.get("main_vm"))
639 if not vm:
640 raise error.TestError("VM object not found in environment")
641 if not vm.is_alive():
642 raise error.TestError("VM seems to be dead; Test requires a living VM")
643
644 logging.info("Waiting for guest to be up...")
645
lmr912c74b2009-08-17 20:43:27 +0000646 session = kvm_utils.wait_for(vm.remote_login, 240, 0, 2)
lmr5c226e32009-07-27 13:13:01 +0000647 if not session:
648 raise error.TestFail("Could not log into guest")
649
650 logging.info("Logged in")
651
652 # Collect test parameters:
653 # Command to run to get the current time
654 time_command = params.get("time_command")
655 # Filter which should match a string to be passed to time.strptime()
656 time_filter_re = params.get("time_filter_re")
657 # Time format for time.strptime()
658 time_format = params.get("time_format")
659 guest_load_command = params.get("guest_load_command")
660 guest_load_stop_command = params.get("guest_load_stop_command")
661 host_load_command = params.get("host_load_command")
662 guest_load_instances = int(params.get("guest_load_instances", "1"))
663 host_load_instances = int(params.get("host_load_instances", "0"))
664 # CPU affinity mask for taskset
665 cpu_mask = params.get("cpu_mask", "0xFF")
666 load_duration = float(params.get("load_duration", "30"))
667 rest_duration = float(params.get("rest_duration", "10"))
668 drift_threshold = float(params.get("drift_threshold", "200"))
669 drift_threshold_after_rest = float(params.get("drift_threshold_after_rest",
670 "200"))
671
672 guest_load_sessions = []
673 host_load_sessions = []
674
lmr5c226e32009-07-27 13:13:01 +0000675 # Set the VM's CPU affinity
lmr25e89fc2009-08-07 20:29:16 +0000676 prev_affinity = set_cpu_affinity(vm.get_pid(), cpu_mask)
lmr5c226e32009-07-27 13:13:01 +0000677
678 try:
679 # Get time before load
lmrff2a7c52009-08-10 00:09:22 +0000680 (host_time_0, guest_time_0) = get_time(session, time_command,
681 time_filter_re, time_format)
lmr5c226e32009-07-27 13:13:01 +0000682
683 # Run some load on the guest
684 logging.info("Starting load on guest...")
685 for i in range(guest_load_instances):
lmr912c74b2009-08-17 20:43:27 +0000686 load_session = vm.remote_login()
lmr5c226e32009-07-27 13:13:01 +0000687 if not load_session:
688 raise error.TestFail("Could not log into guest")
689 load_session.set_output_prefix("(guest load %d) " % i)
690 load_session.set_output_func(logging.debug)
691 load_session.sendline(guest_load_command)
692 guest_load_sessions.append(load_session)
693
694 # Run some load on the host
695 logging.info("Starting load on host...")
696 for i in range(host_load_instances):
697 host_load_sessions.append(
698 kvm_subprocess.run_bg(host_load_command,
699 output_func=logging.debug,
700 output_prefix="(host load %d) " % i,
701 timeout=0.5))
lmr152da2d2009-09-09 22:16:21 +0000702 # Set the CPU affinity of the load process
lmrfb151b52009-09-09 22:19:11 +0000703 pid = host_load_sessions[-1].get_pid()
lmr25e89fc2009-08-07 20:29:16 +0000704 set_cpu_affinity(pid, cpu_mask)
lmr5c226e32009-07-27 13:13:01 +0000705
706 # Sleep for a while (during load)
707 logging.info("Sleeping for %s seconds..." % load_duration)
708 time.sleep(load_duration)
709
710 # Get time delta after load
lmrff2a7c52009-08-10 00:09:22 +0000711 (host_time_1, guest_time_1) = get_time(session, time_command,
712 time_filter_re, time_format)
lmr5c226e32009-07-27 13:13:01 +0000713
714 # Report results
715 host_delta = host_time_1 - host_time_0
716 guest_delta = guest_time_1 - guest_time_0
717 drift = 100.0 * (host_delta - guest_delta) / host_delta
718 logging.info("Host duration: %.2f" % host_delta)
719 logging.info("Guest duration: %.2f" % guest_delta)
720 logging.info("Drift: %.2f%%" % drift)
721
722 finally:
723 logging.info("Cleaning up...")
724 # Restore the VM's CPU affinity
lmr25e89fc2009-08-07 20:29:16 +0000725 restore_cpu_affinity(prev_affinity)
lmr5c226e32009-07-27 13:13:01 +0000726 # Stop the guest load
727 if guest_load_stop_command:
728 session.get_command_output(guest_load_stop_command)
729 # Close all load shell sessions
730 for load_session in guest_load_sessions:
731 load_session.close()
732 for load_session in host_load_sessions:
733 load_session.close()
734
735 # Sleep again (rest)
736 logging.info("Sleeping for %s seconds..." % rest_duration)
737 time.sleep(rest_duration)
738
739 # Get time after rest
lmrff2a7c52009-08-10 00:09:22 +0000740 (host_time_2, guest_time_2) = get_time(session, time_command,
741 time_filter_re, time_format)
lmr5c226e32009-07-27 13:13:01 +0000742
743 # Report results
744 host_delta_total = host_time_2 - host_time_0
745 guest_delta_total = guest_time_2 - guest_time_0
746 drift_total = 100.0 * (host_delta_total - guest_delta_total) / host_delta
747 logging.info("Total host duration including rest: %.2f" % host_delta_total)
748 logging.info("Total guest duration including rest: %.2f" % guest_delta_total)
749 logging.info("Total drift after rest: %.2f%%" % drift_total)
750
lmr5b829602009-08-07 20:36:06 +0000751 session.close()
752
lmr5c226e32009-07-27 13:13:01 +0000753 # Fail the test if necessary
754 if drift > drift_threshold:
755 raise error.TestFail("Time drift too large: %.2f%%" % drift)
lmr67bf4442009-08-28 17:29:45 +0000756 if drift_total > drift_threshold_after_rest:
lmr5c226e32009-07-27 13:13:01 +0000757 raise error.TestFail("Time drift too large after rest period: %.2f%%"
758 % drift_total)
lmr3efa0bd2009-08-18 20:00:56 +0000759
760
761def run_autoit(test, params, env):
762 """
763 A wrapper for AutoIt scripts.
764
765 1) Log into a guest.
766 2) Run AutoIt script.
767 3) Wait for script execution to complete.
768 4) Pass/fail according to exit status of script.
769
770 @param test: KVM test object.
771 @param params: Dictionary with test parameters.
772 @param env: Dictionary with the test environment.
773 """
774 vm = kvm_utils.env_get_vm(env, params.get("main_vm"))
775 if not vm:
776 raise error.TestError("VM object not found in environment")
777 if not vm.is_alive():
778 raise error.TestError("VM seems to be dead; Test requires a living VM")
779
780 logging.info("Waiting for guest to be up...")
781
782 session = kvm_utils.wait_for(vm.remote_login, 240, 0, 2)
783 if not session:
784 raise error.TestFail("Could not log into guest")
785
786 try:
787 logging.info("Logged in; starting script...")
788
789 # Collect test parameters
790 binary = params.get("autoit_binary")
791 script = params.get("autoit_script")
792 script_params = params.get("autoit_script_params", "")
793 timeout = float(params.get("autoit_script_timeout", 600))
794
795 # Send AutoIt script to guest (this code will be replaced once we
796 # support sending files to Windows guests)
797 session.sendline("del script.au3")
798 file = open(kvm_utils.get_path(test.bindir, script))
799 for line in file.readlines():
800 # Insert a '^' before each character
801 line = "".join("^" + c for c in line.rstrip())
802 if line:
803 # Append line to the file
804 session.sendline("echo %s>>script.au3" % line)
805 file.close()
806
807 session.read_up_to_prompt()
808
809 command = "cmd /c %s script.au3 %s" % (binary, script_params)
810
811 logging.info("---------------- Script output ----------------")
812 status = session.get_command_status(command,
813 print_func=logging.info,
814 timeout=timeout)
815 logging.info("---------------- End of script output ----------------")
816
817 if status is None:
818 raise error.TestFail("Timeout expired before script execution "
819 "completed (or something weird happened)")
820 if status != 0:
821 raise error.TestFail("Script execution failed")
822
823 finally:
824 session.close()