blob: ca0b8c07c5fcb65952fe2ec988e1597ac238b526 [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
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"
lmrd85c55b2009-07-23 01:42:10 +0000277 kvm_subprocess.run_fg(cmd % (test.bindir, tarred_autotest_path), timeout=30)
lmr6f669ce2009-05-31 19:02:42 +0000278
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"
lmrd85c55b2009-07-23 01:42:10 +0000284 kvm_subprocess.run_fg(cmd %
285 (os.path.join(test.bindir, "autotest", "tests"),
286 tarred_test_path, test_name), timeout=30)
lmr6f669ce2009-05-31 19:02:42 +0000287
288 # Check if we need to copy autotest.tar.bz2
289 copy = False
290 output = session.get_command_output("ls -l autotest.tar.bz2")
291 if "such file" in output:
292 copy = True
293 else:
294 size = int(output.split()[4])
295 if size != os.path.getsize(tarred_autotest_path):
296 copy = True
297 # Perform the copy
298 if copy:
299 logging.info("Copying autotest.tar.bz2 to guest"
300 " (file is missing or has a different size)...")
301 if not vm.scp_to_remote(tarred_autotest_path, ""):
302 raise error.TestFail("Could not copy autotest.tar.bz2 to guest")
303
304 # Check if we need to copy <test_name>.tar.bz2
305 copy = False
306 output = session.get_command_output("ls -l %s.tar.bz2" % test_name)
307 if "such file" in output:
308 copy = True
309 else:
310 size = int(output.split()[4])
311 if size != os.path.getsize(tarred_test_path):
312 copy = True
313 # Perform the copy
314 if copy:
315 logging.info("Copying %s.tar.bz2 to guest (file is missing or has a"
316 " different size)..." % test_name)
317 if not vm.scp_to_remote(tarred_test_path, ""):
318 raise error.TestFail("Could not copy %s.tar.bz2 to guest" %
319 test_name)
320
321 # Extract autotest.tar.bz2
322 logging.info("Extracting autotest.tar.bz2...")
323 status = session.get_command_status("tar xvfj autotest.tar.bz2")
324 if status != 0:
325 raise error.TestFail("Could not extract autotest.tar.bz2")
326
327 # mkdir autotest/tests
328 session.sendline("mkdir autotest/tests")
329
330 # Extract <test_name>.tar.bz2 into autotest/tests
331 logging.info("Extracting %s.tar.bz2..." % test_name)
332 status = session.get_command_status("tar xvfj %s.tar.bz2 -C "
333 "autotest/tests" % test_name)
334 if status != 0:
335 raise error.TestFail("Could not extract %s.tar.bz2" % test_name)
336
lmr16cf1652009-06-15 21:32:49 +0000337 # Cleaning up old remaining results
338 session.sendline("rm -rf autotest/results/*")
339 # Copying the selected control file (located inside
340 # test.bindir/autotest_control to the autotest dir
341 control_file_path = os.path.join(test.bindir, "autotest_control",
342 test_control_file)
343 if not vm.scp_to_remote(control_file_path, "autotest/control"):
344 raise error.TestFail("Could not copy the test control file to guest")
lmr6f669ce2009-05-31 19:02:42 +0000345 # Run the test
346 logging.info("Running test '%s'..." % test_name)
lmr16cf1652009-06-15 21:32:49 +0000347 session.sendline("cd autotest")
348 session.sendline("rm -f control.state")
lmr6f669ce2009-05-31 19:02:42 +0000349 session.read_up_to_prompt()
lmr16cf1652009-06-15 21:32:49 +0000350 session.sendline("bin/autotest control")
lmr6f669ce2009-05-31 19:02:42 +0000351 logging.info("---------------- Test output ----------------")
lmr16cf1652009-06-15 21:32:49 +0000352 match = session.read_up_to_prompt(timeout=test_timeout,
353 print_func=logging.info)[0]
lmr6f669ce2009-05-31 19:02:42 +0000354 logging.info("---------------- End of test output ----------------")
355 if not match:
lmr16cf1652009-06-15 21:32:49 +0000356 raise error.TestFail("Timeout elapsed while waiting for test to "
357 "complete")
358 # Get the results generated by autotest
359 output = session.get_command_output("cat results/*/status")
lmr6f669ce2009-05-31 19:02:42 +0000360
361 # Parse test results
362 result_list = scan_results.parse_results(output)
363
364 # Report test results and check for FAIL/ERROR status
365 logging.info("Results (test, status, duration, info):")
366 status_error = False
367 status_fail = False
368 if result_list == []:
369 status_fail = True
lmrd16a67d2009-06-10 19:52:59 +0000370 message_fail = ("Test '%s' did not produce any recognizable "
371 "results" % test_name)
lmr6f669ce2009-05-31 19:02:42 +0000372 for result in result_list:
373 logging.info(str(result))
374 if result[1] == "FAIL":
375 status_fail = True
lmr50bece42009-06-15 20:54:43 +0000376 message_fail = ("Test '%s' ended with FAIL "
377 "(info: '%s')" % (result[0], result[3]))
lmr6f669ce2009-05-31 19:02:42 +0000378 if result[1] == "ERROR":
379 status_error = True
lmr50bece42009-06-15 20:54:43 +0000380 message_error = ("Test '%s' ended with ERROR "
381 "(info: '%s')" % (result[0], result[3]))
lmr6f669ce2009-05-31 19:02:42 +0000382 if result[1] == "ABORT":
383 status_error = True
lmr50bece42009-06-15 20:54:43 +0000384 message_error = ("Test '%s' ended with ABORT "
385 "(info: '%s')" % (result[0], result[3]))
lmr6f669ce2009-05-31 19:02:42 +0000386
387 # Copy test results to the local bindir/guest_results
388 logging.info("Copying results back from guest...")
389 guest_results_dir = os.path.join(test.outputdir, "guest_results")
390 if not os.path.exists(guest_results_dir):
391 os.mkdir(guest_results_dir)
392 if not vm.scp_from_remote("autotest/results/default/*", guest_results_dir):
393 logging.error("Could not copy results back from guest")
394
395 # Fail the test if necessary
396 if status_fail:
397 raise error.TestFail(message_fail)
398 elif status_error:
399 raise error.TestError(message_error)
400
401
402def internal_yum_update(session, command, prompt, timeout):
403 """
404 Helper function to perform the yum update test.
405
406 @param session: SSH session stablished to the host
407 @param command: Command to be sent to the SSH connection
408 @param prompt: Machine prompt
409 @param timeout: How long to wait until we get an appropriate output from
410 the SSH session.
411 """
412 session.sendline(command)
413 end_time = time.time() + timeout
414 while time.time() < end_time:
415 (match, text) = session.read_until_last_line_matches(
416 ["[Ii]s this [Oo][Kk]", prompt], timeout=timeout)
417 if match == 0:
418 logging.info("Got 'Is this ok'; sending 'y'")
419 session.sendline("y")
420 elif match == 1:
421 logging.info("Got shell prompt")
422 return True
423 else:
424 logging.info("Timeout or process exited")
425 return False
426
427
428def run_yum_update(test, params, env):
429 """
430 Runs yum update and yum update kernel on the remote host (yum enabled
431 hosts only).
432
433 @param test: kvm test object.
434 @param params: Dictionary with test parameters.
435 @param env: Dictionary with the test environment.
436 """
437 vm = kvm_utils.env_get_vm(env, params.get("main_vm"))
438 if not vm:
439 message = "VM object not found in environment"
440 logging.error(message)
441 raise error.TestError(message)
442 if not vm.is_alive():
443 message = "VM seems to be dead; Test requires a living VM"
444 logging.error(message)
445 raise error.TestError(message)
446
447 logging.info("Logging into guest...")
448
449 session = kvm_utils.wait_for(vm.ssh_login, 120, 0, 2)
450 if not session:
451 message = "Could not log into guest"
452 logging.error(message)
453 raise error.TestFail(message)
454
455 logging.info("Logged in")
456
457 internal_yum_update(session, "yum update", params.get("ssh_prompt"), 600)
458 internal_yum_update(session, "yum update kernel",
459 params.get("ssh_prompt"), 600)
460
461 session.close()
462
463
464def run_linux_s3(test, params, env):
465 """
466 Suspend a guest Linux OS to memory.
467
468 @param test: kvm test object.
469 @param params: Dictionary with test parameters.
470 @param env: Dictionary with the test environment.
471 """
472 vm = kvm_utils.env_get_vm(env, params.get("main_vm"))
473 if not vm:
474 raise error.TestError("VM object not found in environment")
475 if not vm.is_alive():
476 raise error.TestError("VM seems to be dead; Test requires a living VM")
477
478 logging.info("Waiting for guest to be up...")
479
480 session = kvm_utils.wait_for(vm.ssh_login, 240, 0, 2)
481 if not session:
482 raise error.TestFail("Could not log into guest")
483
484 logging.info("Logged in")
485 logging.info("Checking that VM supports S3")
486
487 status = session.get_command_status("grep -q mem /sys/power/state")
488 if status == None:
489 logging.error("Failed to check if S3 exists")
490 elif status != 0:
491 raise error.TestFail("Guest does not support S3")
492
493 logging.info("Waiting for a while for X to start")
494 time.sleep(10)
495
496 src_tty = session.get_command_output("fgconsole").strip()
497 logging.info("Current virtual terminal is %s" % src_tty)
498 if src_tty not in map(str, range(1,10)):
499 raise error.TestFail("Got a strange current vt (%s)" % src_tty)
500
501 dst_tty = "1"
502 if src_tty == "1":
503 dst_tty = "2"
504
505 logging.info("Putting VM into S3")
506 command = "chvt %s && echo mem > /sys/power/state && chvt %s" % (dst_tty,
507 src_tty)
508 status = session.get_command_status(command, timeout=120)
509 if status != 0:
510 raise error.TestFail("Suspend to mem failed")
511
512 logging.info("VM resumed after S3")
513
514 session.close()
lmra04d7c92009-06-19 13:05:39 +0000515
516
517def run_stress_boot(tests, params, env):
518 """
519 Boots VMs until one of them becomes unresponsive, and records the maximum
520 number of VMs successfully started:
521 1) boot the first vm
522 2) boot the second vm cloned from the first vm, check whether it boots up
523 and all booted vms can ssh-login
524 3) go on until cannot create VM anymore or cannot allocate memory for VM
525
526 @param test: kvm test object
527 @param params: Dictionary with the test parameters
528 @param env: Dictionary with test environment.
529 """
530 # boot the first vm
531 vm = kvm_utils.env_get_vm(env, params.get("main_vm"))
lmra04d7c92009-06-19 13:05:39 +0000532 if not vm:
533 raise error.TestError("VM object not found in environment")
534 if not vm.is_alive():
535 raise error.TestError("VM seems to be dead; Test requires a living VM")
536
537 logging.info("Waiting for first guest to be up...")
538
539 session = kvm_utils.wait_for(vm.ssh_login, 240, 0, 2)
540 if not session:
541 raise error.TestFail("Could not log into first guest")
542
543 num = 2
544 vms = []
545 sessions = [session]
546
547 # boot the VMs
548 while num <= int(params.get("max_vms")):
549 try:
550 vm_name = "vm" + str(num)
551
552 # clone vm according to the first one
553 vm_params = params.copy()
554 vm_params['image_snapshot'] = "yes"
555 vm_params['kill_vm'] = "yes"
556 vm_params['kill_vm_gracefully'] = "no"
557 curr_vm = vm.clone(vm_name, vm_params)
558 kvm_utils.env_register_vm(env, vm_name, curr_vm)
559 params['vms'] += " " + vm_name
560
561 #vms.append(curr_vm)
562 logging.info("Booting guest #%d" % num)
563 if not curr_vm.create():
564 raise error.TestFail("Cannot create VM #%d" % num)
565
566 curr_vm_session = kvm_utils.wait_for(curr_vm.ssh_login, 240, 0, 2)
567 if not curr_vm_session:
568 raise error.TestFail("Could not log into guest #%d" % num)
569
570 logging.info("Guest #%d boots up successfully" % num)
571 sessions.append(curr_vm_session)
572
573 # check whether all previous ssh sessions are responsive
574 for i, vm_session in enumerate(sessions):
575 if vm_session.get_command_status(params.get("alive_test_cmd")):
576 raise error.TestFail("Session #%d is not responsive" % i)
577 num += 1
578
579 except (error.TestFail, OSError):
580 for se in sessions:
581 se.close()
582 logging.info("Total number booted: %d" % (num - 1))
583 raise
584 else:
585 for se in sessions:
586 se.close()
587 logging.info("Total number booted: %d" % (num -1))
lmr5c226e32009-07-27 13:13:01 +0000588
589
590def run_timedrift(test, params, env):
591 """
592 Time drift test (mainly for Windows guests):
593
594 1) Log into a guest.
595 2) Take a time reading from the guest and host.
596 3) Run load on the guest and host.
597 4) Take a second time reading.
598 5) Stop the load and rest for a while.
599 6) Take a third time reading.
600 7) If the drift immediately after load is higher than a user-
601 specified value (in %), fail.
602 If the drift after the rest period is higher than a user-specified value,
603 fail.
604
605 @param test: KVM test object.
606 @param params: Dictionary with test parameters.
607 @param env: Dictionary with the test environment.
608 """
609 vm = kvm_utils.env_get_vm(env, params.get("main_vm"))
610 if not vm:
611 raise error.TestError("VM object not found in environment")
612 if not vm.is_alive():
613 raise error.TestError("VM seems to be dead; Test requires a living VM")
614
615 logging.info("Waiting for guest to be up...")
616
617 session = kvm_utils.wait_for(vm.ssh_login, 240, 0, 2)
618 if not session:
619 raise error.TestFail("Could not log into guest")
620
621 logging.info("Logged in")
622
623 # Collect test parameters:
624 # Command to run to get the current time
625 time_command = params.get("time_command")
626 # Filter which should match a string to be passed to time.strptime()
627 time_filter_re = params.get("time_filter_re")
628 # Time format for time.strptime()
629 time_format = params.get("time_format")
630 guest_load_command = params.get("guest_load_command")
631 guest_load_stop_command = params.get("guest_load_stop_command")
632 host_load_command = params.get("host_load_command")
633 guest_load_instances = int(params.get("guest_load_instances", "1"))
634 host_load_instances = int(params.get("host_load_instances", "0"))
635 # CPU affinity mask for taskset
636 cpu_mask = params.get("cpu_mask", "0xFF")
637 load_duration = float(params.get("load_duration", "30"))
638 rest_duration = float(params.get("rest_duration", "10"))
639 drift_threshold = float(params.get("drift_threshold", "200"))
640 drift_threshold_after_rest = float(params.get("drift_threshold_after_rest",
641 "200"))
642
643 guest_load_sessions = []
644 host_load_sessions = []
645
646 # Remember the VM's previous CPU affinity
647 prev_cpu_mask = commands.getoutput("taskset -p %s" % vm.get_pid())
648 prev_cpu_mask = prev_cpu_mask.split()[-1]
649 # Set the VM's CPU affinity
650 commands.getoutput("taskset -p %s %s" % (cpu_mask, vm.get_pid()))
651
652 try:
653 # Get time before load
654 host_time_0 = time.time()
655 session.sendline(time_command)
656 (match, s) = session.read_up_to_prompt()
657 s = re.findall(time_filter_re, s)[0]
658 guest_time_0 = time.mktime(time.strptime(s, time_format))
659
660 # Run some load on the guest
661 logging.info("Starting load on guest...")
662 for i in range(guest_load_instances):
663 load_session = vm.ssh_login()
664 if not load_session:
665 raise error.TestFail("Could not log into guest")
666 load_session.set_output_prefix("(guest load %d) " % i)
667 load_session.set_output_func(logging.debug)
668 load_session.sendline(guest_load_command)
669 guest_load_sessions.append(load_session)
670
671 # Run some load on the host
672 logging.info("Starting load on host...")
673 for i in range(host_load_instances):
674 host_load_sessions.append(
675 kvm_subprocess.run_bg(host_load_command,
676 output_func=logging.debug,
677 output_prefix="(host load %d) " % i,
678 timeout=0.5))
679 # Set the CPU affinity of the shell running the load process
680 pid = host_load_sessions[-1].get_shell_pid()
681 commands.getoutput("taskset -p %s %s" % (cpu_mask, pid))
682 # Try setting the CPU affinity of the load process itself
683 pid = host_load_sessions[-1].get_pid()
684 if pid:
685 commands.getoutput("taskset -p %s %s" % (cpu_mask, pid))
686
687 # Sleep for a while (during load)
688 logging.info("Sleeping for %s seconds..." % load_duration)
689 time.sleep(load_duration)
690
691 # Get time delta after load
692 host_time_1 = time.time()
693 session.sendline(time_command)
694 (match, s) = session.read_up_to_prompt()
695 s = re.findall(time_filter_re, s)[0]
696 guest_time_1 = time.mktime(time.strptime(s, time_format))
697
698 # Report results
699 host_delta = host_time_1 - host_time_0
700 guest_delta = guest_time_1 - guest_time_0
701 drift = 100.0 * (host_delta - guest_delta) / host_delta
702 logging.info("Host duration: %.2f" % host_delta)
703 logging.info("Guest duration: %.2f" % guest_delta)
704 logging.info("Drift: %.2f%%" % drift)
705
706 finally:
707 logging.info("Cleaning up...")
708 # Restore the VM's CPU affinity
709 commands.getoutput("taskset -p %s %s" % (prev_cpu_mask, vm.get_pid()))
710 # Stop the guest load
711 if guest_load_stop_command:
712 session.get_command_output(guest_load_stop_command)
713 # Close all load shell sessions
714 for load_session in guest_load_sessions:
715 load_session.close()
716 for load_session in host_load_sessions:
717 load_session.close()
718
719 # Sleep again (rest)
720 logging.info("Sleeping for %s seconds..." % rest_duration)
721 time.sleep(rest_duration)
722
723 # Get time after rest
724 host_time_2 = time.time()
725 session.sendline(time_command)
726 (match, s) = session.read_up_to_prompt()
727 s = re.findall(time_filter_re, s)[0]
728 guest_time_2 = time.mktime(time.strptime(s, time_format))
729
730 # Report results
731 host_delta_total = host_time_2 - host_time_0
732 guest_delta_total = guest_time_2 - guest_time_0
733 drift_total = 100.0 * (host_delta_total - guest_delta_total) / host_delta
734 logging.info("Total host duration including rest: %.2f" % host_delta_total)
735 logging.info("Total guest duration including rest: %.2f" % guest_delta_total)
736 logging.info("Total drift after rest: %.2f%%" % drift_total)
737
738 # Fail the test if necessary
739 if drift > drift_threshold:
740 raise error.TestFail("Time drift too large: %.2f%%" % drift)
741 if drift > drift_threshold_after_rest:
742 raise error.TestFail("Time drift too large after rest period: %.2f%%"
743 % drift_total)
744
745 session.close()