OLD | NEW |
1 """ | 1 """ |
2 High-level KVM test utility functions. | 2 High-level KVM test utility functions. |
3 | 3 |
4 This module is meant to reduce code size by performing common test procedures. | 4 This module is meant to reduce code size by performing common test procedures. |
5 Generally, code here should look like test code. | 5 Generally, code here should look like test code. |
6 More specifically: | 6 More specifically: |
7 - Functions in this module should raise exceptions if things go wrong | 7 - Functions in this module should raise exceptions if things go wrong |
8 (unlike functions in kvm_utils.py and kvm_vm.py which report failure via | 8 (unlike functions in kvm_utils.py and kvm_vm.py which report failure via |
9 their returned values). | 9 their returned values). |
10 - Functions in this module may use logging.info(), in addition to | 10 - Functions in this module may use logging.info(), in addition to |
11 logging.debug() and logging.error(), to log messages the user may be | 11 logging.debug() and logging.error(), to log messages the user may be |
12 interested in (unlike kvm_utils.py and kvm_vm.py which use | 12 interested in (unlike kvm_utils.py and kvm_vm.py which use |
13 logging.debug() for anything that isn't an error). | 13 logging.debug() for anything that isn't an error). |
14 - Functions in this module typically use functions and classes from | 14 - Functions in this module typically use functions and classes from |
15 lower-level modules (e.g. kvm_utils.py, kvm_vm.py, kvm_subprocess.py). | 15 lower-level modules (e.g. kvm_utils.py, kvm_vm.py, kvm_subprocess.py). |
16 - Functions in this module should not be used by lower-level modules. | 16 - Functions in this module should not be used by lower-level modules. |
17 - Functions in this module should be used in the right context. | 17 - Functions in this module should be used in the right context. |
18 For example, a function should not be used where it may display | 18 For example, a function should not be used where it may display |
19 misleading or inaccurate info or debug messages. | 19 misleading or inaccurate info or debug messages. |
20 | 20 |
21 @copyright: 2008-2009 Red Hat Inc. | 21 @copyright: 2008-2009 Red Hat Inc. |
22 """ | 22 """ |
23 | 23 |
24 import time, os, logging, re, signal | 24 import time, os, logging, re, signal |
25 from autotest_lib.client.common_lib import error | 25 from autotest_lib.client.common_lib import error |
26 from autotest_lib.client.bin import utils | 26 from autotest_lib.client.bin import utils |
27 import kvm_utils, kvm_vm, kvm_subprocess, scan_results | 27 from autotest_lib.client.tools import scan_results |
| 28 import aexpect, virt_utils, virt_vm |
28 | 29 |
29 | 30 |
30 def get_living_vm(env, vm_name): | 31 def get_living_vm(env, vm_name): |
31 """ | 32 """ |
32 Get a VM object from the environment and make sure it's alive. | 33 Get a VM object from the environment and make sure it's alive. |
33 | 34 |
34 @param env: Dictionary with test environment. | 35 @param env: Dictionary with test environment. |
35 @param vm_name: Name of the desired VM object. | 36 @param vm_name: Name of the desired VM object. |
36 @return: A VM object. | 37 @return: A VM object. |
37 """ | 38 """ |
(...skipping 21 matching lines...) Expand all Loading... |
59 session = None | 60 session = None |
60 if serial: | 61 if serial: |
61 type = 'serial' | 62 type = 'serial' |
62 logging.info("Trying to log into guest %s using serial connection," | 63 logging.info("Trying to log into guest %s using serial connection," |
63 " timeout %ds", vm.name, timeout) | 64 " timeout %ds", vm.name, timeout) |
64 time.sleep(start) | 65 time.sleep(start) |
65 while time.time() < end_time: | 66 while time.time() < end_time: |
66 try: | 67 try: |
67 session = vm.serial_login() | 68 session = vm.serial_login() |
68 break | 69 break |
69 except kvm_utils.LoginError, e: | 70 except virt_utils.LoginError, e: |
70 logging.debug(e) | 71 logging.debug(e) |
71 time.sleep(step) | 72 time.sleep(step) |
72 else: | 73 else: |
73 type = 'remote' | 74 type = 'remote' |
74 logging.info("Trying to log into guest %s using remote connection," | 75 logging.info("Trying to log into guest %s using remote connection," |
75 " timeout %ds", vm.name, timeout) | 76 " timeout %ds", vm.name, timeout) |
76 time.sleep(start) | 77 time.sleep(start) |
77 while time.time() < end_time: | 78 while time.time() < end_time: |
78 try: | 79 try: |
79 session = vm.login(nic_index=nic_index) | 80 session = vm.login(nic_index=nic_index) |
80 break | 81 break |
81 except (kvm_utils.LoginError, kvm_vm.VMError), e: | 82 except (virt_utils.LoginError, virt_vm.VMError), e: |
82 logging.debug(e) | 83 logging.debug(e) |
83 time.sleep(step) | 84 time.sleep(step) |
84 if not session: | 85 if not session: |
85 raise error.TestFail("Could not log into guest %s using %s connection" % | 86 raise error.TestFail("Could not log into guest %s using %s connection" % |
86 (vm.name, type)) | 87 (vm.name, type)) |
87 logging.info("Logged into guest %s using %s connection", vm.name, type) | 88 logging.info("Logged into guest %s using %s connection", vm.name, type) |
88 return session | 89 return session |
89 | 90 |
90 | 91 |
91 def reboot(vm, session, method="shell", sleep_before_reset=10, nic_index=0, | 92 def reboot(vm, session, method="shell", sleep_before_reset=10, nic_index=0, |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
123 for m in monitors: | 124 for m in monitors: |
124 if not m.get_event("RESET"): | 125 if not m.get_event("RESET"): |
125 raise error.TestFail("RESET QMP event not received after " | 126 raise error.TestFail("RESET QMP event not received after " |
126 "system_reset (monitor '%s')" % m.name) | 127 "system_reset (monitor '%s')" % m.name) |
127 else: | 128 else: |
128 logging.info("RESET QMP event received") | 129 logging.info("RESET QMP event received") |
129 else: | 130 else: |
130 logging.error("Unknown reboot method: %s", method) | 131 logging.error("Unknown reboot method: %s", method) |
131 | 132 |
132 # Wait for the session to become unresponsive and close it | 133 # Wait for the session to become unresponsive and close it |
133 if not kvm_utils.wait_for(lambda: not session.is_responsive(timeout=30), | 134 if not virt_utils.wait_for(lambda: not session.is_responsive(timeout=30), |
134 120, 0, 1): | 135 120, 0, 1): |
135 raise error.TestFail("Guest refuses to go down") | 136 raise error.TestFail("Guest refuses to go down") |
136 session.close() | 137 session.close() |
137 | 138 |
138 # Try logging into the guest until timeout expires | 139 # Try logging into the guest until timeout expires |
139 logging.info("Guest is down. Waiting for it to go up again, timeout %ds", | 140 logging.info("Guest is down. Waiting for it to go up again, timeout %ds", |
140 timeout) | 141 timeout) |
141 session = vm.wait_for_login(nic_index, timeout=timeout) | 142 session = vm.wait_for_login(nic_index, timeout=timeout) |
142 logging.info("Guest is up again") | 143 logging.info("Guest is up again") |
143 return session | 144 return session |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
184 def mig_cancelled(): | 185 def mig_cancelled(): |
185 o = vm.monitor.info("migrate") | 186 o = vm.monitor.info("migrate") |
186 if isinstance(o, str): | 187 if isinstance(o, str): |
187 return ("Migration status: cancelled" in o or | 188 return ("Migration status: cancelled" in o or |
188 "Migration status: canceled" in o) | 189 "Migration status: canceled" in o) |
189 else: | 190 else: |
190 return (o.get("status") == "cancelled" or | 191 return (o.get("status") == "cancelled" or |
191 o.get("status") == "canceled") | 192 o.get("status") == "canceled") |
192 | 193 |
193 def wait_for_migration(): | 194 def wait_for_migration(): |
194 if not kvm_utils.wait_for(mig_finished, mig_timeout, 2, 2, | 195 if not virt_utils.wait_for(mig_finished, mig_timeout, 2, 2, |
195 "Waiting for migration to finish..."): | 196 "Waiting for migration to finish..."): |
196 raise error.TestFail("Timeout expired while waiting for migration " | 197 raise error.TestFail("Timeout expired while waiting for migration " |
197 "to finish") | 198 "to finish") |
198 | 199 |
199 if dest_host == 'localhost': | 200 if dest_host == 'localhost': |
200 dest_vm = vm.clone() | 201 dest_vm = vm.clone() |
201 | 202 |
202 if (dest_host == 'localhost') and stable_check: | 203 if (dest_host == 'localhost') and stable_check: |
203 # Pause the dest vm after creation | 204 # Pause the dest vm after creation |
204 dest_vm.params['extra_params'] = (dest_vm.params.get('extra_params','') | 205 dest_vm.params['extra_params'] = (dest_vm.params.get('extra_params','') |
(...skipping 14 matching lines...) Expand all Loading... |
219 elif mig_protocol == "exec": | 220 elif mig_protocol == "exec": |
220 uri = '"exec:nc localhost %s"' % dest_vm.migration_port | 221 uri = '"exec:nc localhost %s"' % dest_vm.migration_port |
221 | 222 |
222 if offline: | 223 if offline: |
223 vm.monitor.cmd("stop") | 224 vm.monitor.cmd("stop") |
224 vm.monitor.migrate(uri) | 225 vm.monitor.migrate(uri) |
225 | 226 |
226 if mig_cancel: | 227 if mig_cancel: |
227 time.sleep(2) | 228 time.sleep(2) |
228 vm.monitor.cmd("migrate_cancel") | 229 vm.monitor.cmd("migrate_cancel") |
229 if not kvm_utils.wait_for(mig_cancelled, 60, 2, 2, | 230 if not virt_utils.wait_for(mig_cancelled, 60, 2, 2, |
230 "Waiting for migration " | 231 "Waiting for migration " |
231 "cancellation"): | 232 "cancellation"): |
232 raise error.TestFail("Failed to cancel migration") | 233 raise error.TestFail("Failed to cancel migration") |
233 if offline: | 234 if offline: |
234 vm.monitor.cmd("cont") | 235 vm.monitor.cmd("cont") |
235 if dest_host == 'localhost': | 236 if dest_host == 'localhost': |
236 dest_vm.destroy(gracefully=False) | 237 dest_vm.destroy(gracefully=False) |
237 return vm | 238 return vm |
238 else: | 239 else: |
239 wait_for_migration() | 240 wait_for_migration() |
(...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
549 | 550 |
550 vm.copy_files_to(control_path, os.path.join(autotest_path, 'control')) | 551 vm.copy_files_to(control_path, os.path.join(autotest_path, 'control')) |
551 | 552 |
552 # Run the test | 553 # Run the test |
553 logging.info("Running autotest control file %s on guest, timeout %ss", | 554 logging.info("Running autotest control file %s on guest, timeout %ss", |
554 os.path.basename(control_path), timeout) | 555 os.path.basename(control_path), timeout) |
555 session.cmd("cd %s" % autotest_path) | 556 session.cmd("cd %s" % autotest_path) |
556 try: | 557 try: |
557 session.cmd("rm -f control.state") | 558 session.cmd("rm -f control.state") |
558 session.cmd("rm -rf results/*") | 559 session.cmd("rm -rf results/*") |
559 except kvm_subprocess.ShellError: | 560 except aexpect.ShellError: |
560 pass | 561 pass |
561 try: | 562 try: |
562 bg = None | 563 bg = None |
563 try: | 564 try: |
564 logging.info("---------------- Test output ----------------") | 565 logging.info("---------------- Test output ----------------") |
565 if migrate_background: | 566 if migrate_background: |
566 mig_timeout = float(params.get("mig_timeout", "3600")) | 567 mig_timeout = float(params.get("mig_timeout", "3600")) |
567 mig_protocol = params.get("migration_protocol", "tcp") | 568 mig_protocol = params.get("migration_protocol", "tcp") |
568 | 569 |
569 bg = kvm_utils.Thread(session.cmd_output, | 570 bg = virt_utils.Thread(session.cmd_output, |
570 kwargs={'cmd': "bin/autotest control", | 571 kwargs={'cmd': "bin/autotest control", |
571 'timeout': timeout, | 572 'timeout': timeout, |
572 'print_func': logging.info}) | 573 'print_func': logging.info}) |
573 | 574 |
574 bg.start() | 575 bg.start() |
575 | 576 |
576 while bg.is_alive(): | 577 while bg.is_alive(): |
577 logging.info("Tests is not ended, start a round of" | 578 logging.info("Tests is not ended, start a round of" |
578 "migration ...") | 579 "migration ...") |
579 vm.migrate(timeout=mig_timeout, protocol=mig_protocol) | 580 vm.migrate(timeout=mig_timeout, protocol=mig_protocol) |
580 else: | 581 else: |
581 session.cmd_output("bin/autotest control", timeout=timeout, | 582 session.cmd_output("bin/autotest control", timeout=timeout, |
582 print_func=logging.info) | 583 print_func=logging.info) |
583 finally: | 584 finally: |
584 logging.info("------------- End of test output ------------") | 585 logging.info("------------- End of test output ------------") |
585 if migrate_background and bg: | 586 if migrate_background and bg: |
586 bg.join() | 587 bg.join() |
587 except kvm_subprocess.ShellTimeoutError: | 588 except aexpect.ShellTimeoutError: |
588 if vm.is_alive(): | 589 if vm.is_alive(): |
589 get_results() | 590 get_results() |
590 get_results_summary() | 591 get_results_summary() |
591 raise error.TestError("Timeout elapsed while waiting for job to " | 592 raise error.TestError("Timeout elapsed while waiting for job to " |
592 "complete") | 593 "complete") |
593 else: | 594 else: |
594 raise error.TestError("Autotest job on guest failed " | 595 raise error.TestError("Autotest job on guest failed " |
595 "(VM terminated during job)") | 596 "(VM terminated during job)") |
596 except kvm_subprocess.ShellProcessTerminatedError: | 597 except aexpect.ShellProcessTerminatedError: |
597 get_results() | 598 get_results() |
598 raise error.TestError("Autotest job on guest failed " | 599 raise error.TestError("Autotest job on guest failed " |
599 "(Remote session terminated during job)") | 600 "(Remote session terminated during job)") |
600 | 601 |
601 results = get_results_summary() | 602 results = get_results_summary() |
602 get_results() | 603 get_results() |
603 | 604 |
604 # Make a list of FAIL/ERROR/ABORT results (make sure FAIL results appear | 605 # Make a list of FAIL/ERROR/ABORT results (make sure FAIL results appear |
605 # before ERROR results, and ERROR results appear before ABORT results) | 606 # before ERROR results, and ERROR results appear before ABORT results) |
606 bad_results = [r[0] for r in results if r[1] == "FAIL"] | 607 bad_results = [r[0] for r in results if r[1] == "FAIL"] |
(...skipping 29 matching lines...) Expand all Loading... |
636 | 637 |
637 def raw_ping(command, timeout, session, output_func): | 638 def raw_ping(command, timeout, session, output_func): |
638 """ | 639 """ |
639 Low-level ping command execution. | 640 Low-level ping command execution. |
640 | 641 |
641 @param command: Ping command. | 642 @param command: Ping command. |
642 @param timeout: Timeout of the ping command. | 643 @param timeout: Timeout of the ping command. |
643 @param session: Local executon hint or session to execute the ping command. | 644 @param session: Local executon hint or session to execute the ping command. |
644 """ | 645 """ |
645 if session is None: | 646 if session is None: |
646 process = kvm_subprocess.run_bg(command, output_func=output_func, | 647 process = aexpect.run_bg(command, output_func=output_func, |
647 timeout=timeout) | 648 timeout=timeout) |
648 | 649 |
649 # Send SIGINT signal to notify the timeout of running ping process, | 650 # Send SIGINT signal to notify the timeout of running ping process, |
650 # Because ping have the ability to catch the SIGINT signal so we can | 651 # Because ping have the ability to catch the SIGINT signal so we can |
651 # always get the packet loss ratio even if timeout. | 652 # always get the packet loss ratio even if timeout. |
652 if process.is_alive(): | 653 if process.is_alive(): |
653 kvm_utils.kill_process_tree(process.get_pid(), signal.SIGINT) | 654 virt_utils.kill_process_tree(process.get_pid(), signal.SIGINT) |
654 | 655 |
655 status = process.get_status() | 656 status = process.get_status() |
656 output = process.get_output() | 657 output = process.get_output() |
657 | 658 |
658 process.close() | 659 process.close() |
659 return status, output | 660 return status, output |
660 else: | 661 else: |
661 output = "" | 662 output = "" |
662 try: | 663 try: |
663 output = session.cmd_output(command, timeout=timeout, | 664 output = session.cmd_output(command, timeout=timeout, |
664 print_func=output_func) | 665 print_func=output_func) |
665 except kvm_subprocess.ShellTimeoutError: | 666 except aexpect.ShellTimeoutError: |
666 # Send ctrl+c (SIGINT) through ssh session | 667 # Send ctrl+c (SIGINT) through ssh session |
667 session.send("\003") | 668 session.send("\003") |
668 try: | 669 try: |
669 output2 = session.read_up_to_prompt(print_func=output_func) | 670 output2 = session.read_up_to_prompt(print_func=output_func) |
670 output += output2 | 671 output += output2 |
671 except kvm_subprocess.ExpectTimeoutError, e: | 672 except aexpect.ExpectTimeoutError, e: |
672 output += e.output | 673 output += e.output |
673 # We also need to use this session to query the return value | 674 # We also need to use this session to query the return value |
674 session.send("\003") | 675 session.send("\003") |
675 | 676 |
676 session.sendline(session.status_test_command) | 677 session.sendline(session.status_test_command) |
677 try: | 678 try: |
678 o2 = session.read_up_to_prompt() | 679 o2 = session.read_up_to_prompt() |
679 except kvm_subprocess.ExpectError: | 680 except aexpect.ExpectError: |
680 status = -1 | 681 status = -1 |
681 else: | 682 else: |
682 try: | 683 try: |
683 status = int(re.findall("\d+", o2)[0]) | 684 status = int(re.findall("\d+", o2)[0]) |
684 except: | 685 except: |
685 status = -1 | 686 status = -1 |
686 | 687 |
687 return status, output | 688 return status, output |
688 | 689 |
689 | 690 |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
744 """ | 745 """ |
745 | 746 |
746 output = session.cmd_output("ifconfig -a") | 747 output = session.cmd_output("ifconfig -a") |
747 | 748 |
748 try: | 749 try: |
749 ethname = re.findall("(\w+)\s+Link.*%s" % mac_address, output, | 750 ethname = re.findall("(\w+)\s+Link.*%s" % mac_address, output, |
750 re.IGNORECASE)[0] | 751 re.IGNORECASE)[0] |
751 return ethname | 752 return ethname |
752 except: | 753 except: |
753 return None | 754 return None |
OLD | NEW |