OLD | NEW |
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 """ | 2 """ |
3 A class and functions used for running and controlling child processes. | 3 A class and functions used for running and controlling child processes. |
4 | 4 |
5 @copyright: 2008-2009 Red Hat Inc. | 5 @copyright: 2008-2009 Red Hat Inc. |
6 """ | 6 """ |
7 | 7 |
8 import os, sys, pty, select, termios, fcntl | 8 import os, sys, pty, select, termios, fcntl |
9 | 9 |
10 | 10 |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
182 _unlock(lock_server_running) | 182 _unlock(lock_server_running) |
183 exit(0) | 183 exit(0) |
184 | 184 |
185 | 185 |
186 # The following is the client part of the module. | 186 # The following is the client part of the module. |
187 | 187 |
188 import subprocess, time, signal, re, threading, logging | 188 import subprocess, time, signal, re, threading, logging |
189 import common, kvm_utils | 189 import common, kvm_utils |
190 | 190 |
191 | 191 |
| 192 class ExpectError(Exception): |
| 193 def __init__(self, patterns, output): |
| 194 Exception.__init__(self, patterns, output) |
| 195 self.patterns = patterns |
| 196 self.output = output |
| 197 |
| 198 def _pattern_str(self): |
| 199 if len(self.patterns) == 1: |
| 200 return "pattern %r" % self.patterns[0] |
| 201 else: |
| 202 return "patterns %r" % self.patterns |
| 203 |
| 204 def __str__(self): |
| 205 return ("Unknown error occurred while looking for %s (output: %r)" % |
| 206 (self._pattern_str(), self.output)) |
| 207 |
| 208 |
| 209 class ExpectTimeoutError(ExpectError): |
| 210 def __str__(self): |
| 211 return ("Timeout expired while looking for %s (output: %r)" % |
| 212 (self._pattern_str(), self.output)) |
| 213 |
| 214 |
| 215 class ExpectProcessTerminatedError(ExpectError): |
| 216 def __init__(self, patterns, status, output): |
| 217 ExpectError.__init__(self, patterns, output) |
| 218 self.status = status |
| 219 |
| 220 def __str__(self): |
| 221 return ("Process terminated while looking for %s " |
| 222 "(status: %s, output: %r)" % (self._pattern_str(), |
| 223 self.status, self.output)) |
| 224 |
| 225 |
| 226 class ShellError(Exception): |
| 227 def __init__(self, cmd, output): |
| 228 Exception.__init__(self, cmd, output) |
| 229 self.cmd = cmd |
| 230 self.output = output |
| 231 |
| 232 def __str__(self): |
| 233 return ("Could not execute shell command %r (output: %r)" % |
| 234 (self.cmd, self.output)) |
| 235 |
| 236 |
| 237 class ShellTimeoutError(ShellError): |
| 238 def __str__(self): |
| 239 return ("Timeout expired while waiting for shell command to " |
| 240 "complete: %r (output: %r)" % (self.cmd, self.output)) |
| 241 |
| 242 |
| 243 class ShellProcessTerminatedError(ShellError): |
| 244 # Raised when the shell process itself (e.g. ssh, netcat, telnet) |
| 245 # terminates unexpectedly |
| 246 def __init__(self, cmd, status, output): |
| 247 ShellError.__init__(self, cmd, output) |
| 248 self.status = status |
| 249 |
| 250 def __str__(self): |
| 251 return ("Shell process terminated while waiting for command to " |
| 252 "complete: %r (status: %s, output: %r)" % |
| 253 (self.cmd, self.status, self.output)) |
| 254 |
| 255 |
| 256 class ShellCmdError(ShellError): |
| 257 # Raised when a command executed in a shell terminates with a nonzero |
| 258 # exit code (status) |
| 259 def __init__(self, cmd, status, output): |
| 260 ShellError.__init__(self, cmd, output) |
| 261 self.status = status |
| 262 |
| 263 def __str__(self): |
| 264 return ("Shell command failed: %r (status: %s, output: %r)" % |
| 265 (self.cmd, self.status, self.output)) |
| 266 |
| 267 |
| 268 class ShellStatusError(ShellError): |
| 269 # Raised when the command's exit status cannot be obtained |
| 270 def __str__(self): |
| 271 return ("Could not get exit status of command: %r (output: %r)" % |
| 272 (self.cmd, self.output)) |
| 273 |
| 274 |
192 def run_bg(command, termination_func=None, output_func=None, output_prefix="", | 275 def run_bg(command, termination_func=None, output_func=None, output_prefix="", |
193 timeout=1.0): | 276 timeout=1.0): |
194 """ | 277 """ |
195 Run command as a subprocess. Call output_func with each line of output | 278 Run command as a subprocess. Call output_func with each line of output |
196 from the subprocess (prefixed by output_prefix). Call termination_func | 279 from the subprocess (prefixed by output_prefix). Call termination_func |
197 when the subprocess terminates. Return when timeout expires or when the | 280 when the subprocess terminates. Return when timeout expires or when the |
198 subprocess exits -- whichever occurs first. | 281 subprocess exits -- whichever occurs first. |
199 | 282 |
200 @brief: Run a subprocess in the background and collect its output and | 283 @brief: Run a subprocess in the background and collect its output and |
201 exit status. | 284 exit status. |
202 | 285 |
203 @param command: The shell command to execute | 286 @param command: The shell command to execute |
204 @param termination_func: A function to call when the process terminates | 287 @param termination_func: A function to call when the process terminates |
205 (should take an integer exit status parameter) | 288 (should take an integer exit status parameter) |
206 @param output_func: A function to call with each line of output from | 289 @param output_func: A function to call with each line of output from |
207 the subprocess (should take a string parameter) | 290 the subprocess (should take a string parameter) |
208 @param output_prefix: A string to pre-pend to each line of the output, | 291 @param output_prefix: A string to pre-pend to each line of the output, |
209 before passing it to stdout_func | 292 before passing it to stdout_func |
210 @param timeout: Time duration (in seconds) to wait for the subprocess to | 293 @param timeout: Time duration (in seconds) to wait for the subprocess to |
211 terminate before returning | 294 terminate before returning |
212 | 295 |
213 @return: A kvm_tail object. | 296 @return: A Tail object. |
214 """ | 297 """ |
215 process = kvm_tail(command=command, | 298 process = Tail(command=command, |
216 termination_func=termination_func, | 299 termination_func=termination_func, |
217 output_func=output_func, | 300 output_func=output_func, |
218 output_prefix=output_prefix) | 301 output_prefix=output_prefix) |
219 | 302 |
220 end_time = time.time() + timeout | 303 end_time = time.time() + timeout |
221 while time.time() < end_time and process.is_alive(): | 304 while time.time() < end_time and process.is_alive(): |
222 time.sleep(0.1) | 305 time.sleep(0.1) |
223 | 306 |
224 return process | 307 return process |
225 | 308 |
226 | 309 |
227 def run_fg(command, output_func=None, output_prefix="", timeout=1.0): | 310 def run_fg(command, output_func=None, output_prefix="", timeout=1.0): |
228 """ | 311 """ |
(...skipping 20 matching lines...) Expand all Loading... |
249 process = run_bg(command, None, output_func, output_prefix, timeout) | 332 process = run_bg(command, None, output_func, output_prefix, timeout) |
250 output = process.get_output() | 333 output = process.get_output() |
251 if process.is_alive(): | 334 if process.is_alive(): |
252 status = None | 335 status = None |
253 else: | 336 else: |
254 status = process.get_status() | 337 status = process.get_status() |
255 process.close() | 338 process.close() |
256 return (status, output) | 339 return (status, output) |
257 | 340 |
258 | 341 |
259 class kvm_spawn: | 342 class Spawn: |
260 """ | 343 """ |
261 This class is used for spawning and controlling a child process. | 344 This class is used for spawning and controlling a child process. |
262 | 345 |
263 A new instance of this class can either run a new server (a small Python | 346 A new instance of this class can either run a new server (a small Python |
264 program that reads output from the child process and reports it to the | 347 program that reads output from the child process and reports it to the |
265 client and to a text file) or attach to an already running server. | 348 client and to a text file) or attach to an already running server. |
266 When a server is started it runs the child process. | 349 When a server is started it runs the child process. |
267 The server writes output from the child's STDOUT and STDERR to a text file. | 350 The server writes output from the child's STDOUT and STDERR to a text file. |
268 The text file can be accessed at any time using get_output(). | 351 The text file can be accessed at any time using get_output(). |
269 In addition, the server opens as many pipes as requested by the client and | 352 In addition, the server opens as many pipes as requested by the client and |
270 writes the output to them. | 353 writes the output to them. |
271 The pipes are requested and accessed by classes derived from kvm_spawn. | 354 The pipes are requested and accessed by classes derived from Spawn. |
272 These pipes are referred to as "readers". | 355 These pipes are referred to as "readers". |
273 The server also receives input from the client and sends it to the child | 356 The server also receives input from the client and sends it to the child |
274 process. | 357 process. |
275 An instance of this class can be pickled. Every derived class is | 358 An instance of this class can be pickled. Every derived class is |
276 responsible for restoring its own state by properly defining | 359 responsible for restoring its own state by properly defining |
277 __getinitargs__(). | 360 __getinitargs__(). |
278 | 361 |
279 The first named pipe is used by _tail(), a function that runs in the | 362 The first named pipe is used by _tail(), a function that runs in the |
280 background and reports new output from the child as it is produced. | 363 background and reports new output from the child as it is produced. |
281 The second named pipe is used by a set of functions that read and parse | 364 The second named pipe is used by a set of functions that read and parse |
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
545 | 628 |
546 @param str: String to send to the child process. | 629 @param str: String to send to the child process. |
547 """ | 630 """ |
548 self.send(str + self.linesep) | 631 self.send(str + self.linesep) |
549 | 632 |
550 | 633 |
551 _thread_kill_requested = False | 634 _thread_kill_requested = False |
552 | 635 |
553 def kill_tail_threads(): | 636 def kill_tail_threads(): |
554 """ | 637 """ |
555 Kill all kvm_tail threads. | 638 Kill all Tail threads. |
556 | 639 |
557 After calling this function no new threads should be started. | 640 After calling this function no new threads should be started. |
558 """ | 641 """ |
559 global _thread_kill_requested | 642 global _thread_kill_requested |
560 _thread_kill_requested = True | 643 _thread_kill_requested = True |
561 for t in threading.enumerate(): | 644 for t in threading.enumerate(): |
562 if hasattr(t, "name") and t.name.startswith("tail_thread"): | 645 if hasattr(t, "name") and t.name.startswith("tail_thread"): |
563 t.join(10) | 646 t.join(10) |
564 _thread_kill_requested = False | 647 _thread_kill_requested = False |
565 | 648 |
566 | 649 |
567 class kvm_tail(kvm_spawn): | 650 class Tail(Spawn): |
568 """ | 651 """ |
569 This class runs a child process in the background and sends its output in | 652 This class runs a child process in the background and sends its output in |
570 real time, line-by-line, to a callback function. | 653 real time, line-by-line, to a callback function. |
571 | 654 |
572 See kvm_spawn's docstring. | 655 See Spawn's docstring. |
573 | 656 |
574 This class uses a single pipe reader to read data in real time from the | 657 This class uses a single pipe reader to read data in real time from the |
575 child process and report it to a given callback function. | 658 child process and report it to a given callback function. |
576 When the child process exits, its exit status is reported to an additional | 659 When the child process exits, its exit status is reported to an additional |
577 callback function. | 660 callback function. |
578 | 661 |
579 When this class is unpickled, it automatically resumes reporting output. | 662 When this class is unpickled, it automatically resumes reporting output. |
580 """ | 663 """ |
581 | 664 |
582 def __init__(self, command=None, id=None, auto_close=False, echo=False, | 665 def __init__(self, command=None, id=None, auto_close=False, echo=False, |
(...skipping 20 matching lines...) Expand all Loading... |
603 @param output_func: Function to call whenever a line of output is | 686 @param output_func: Function to call whenever a line of output is |
604 available from the STDOUT or STDERR streams of the process. | 687 available from the STDOUT or STDERR streams of the process. |
605 The function must accept a single string parameter. The string | 688 The function must accept a single string parameter. The string |
606 does not include the final newline. | 689 does not include the final newline. |
607 @param output_params: Parameters to send to output_func before the | 690 @param output_params: Parameters to send to output_func before the |
608 output line. | 691 output line. |
609 @param output_prefix: String to prepend to lines sent to output_func. | 692 @param output_prefix: String to prepend to lines sent to output_func. |
610 """ | 693 """ |
611 # Add a reader and a close hook | 694 # Add a reader and a close hook |
612 self._add_reader("tail") | 695 self._add_reader("tail") |
613 self._add_close_hook(kvm_tail._join_thread) | 696 self._add_close_hook(Tail._join_thread) |
614 | 697 |
615 # Init the superclass | 698 # Init the superclass |
616 kvm_spawn.__init__(self, command, id, auto_close, echo, linesep) | 699 Spawn.__init__(self, command, id, auto_close, echo, linesep) |
617 | 700 |
618 # Remember some attributes | 701 # Remember some attributes |
619 self.termination_func = termination_func | 702 self.termination_func = termination_func |
620 self.termination_params = termination_params | 703 self.termination_params = termination_params |
621 self.output_func = output_func | 704 self.output_func = output_func |
622 self.output_params = output_params | 705 self.output_params = output_params |
623 self.output_prefix = output_prefix | 706 self.output_prefix = output_prefix |
624 | 707 |
625 # Start the thread in the background | 708 # Start the thread in the background |
626 self.tail_thread = None | 709 self.tail_thread = None |
627 if termination_func or output_func: | 710 if termination_func or output_func: |
628 self._start_thread() | 711 self._start_thread() |
629 | 712 |
630 | 713 |
631 def __getinitargs__(self): | 714 def __getinitargs__(self): |
632 return kvm_spawn.__getinitargs__(self) + (self.termination_func, | 715 return Spawn.__getinitargs__(self) + (self.termination_func, |
633 self.termination_params, | 716 self.termination_params, |
634 self.output_func, | 717 self.output_func, |
635 self.output_params, | 718 self.output_params, |
636 self.output_prefix) | 719 self.output_prefix) |
637 | 720 |
638 | 721 |
639 def set_termination_func(self, termination_func): | 722 def set_termination_func(self, termination_func): |
640 """ | 723 """ |
641 Set the termination_func attribute. See __init__() for details. | 724 Set the termination_func attribute. See __init__() for details. |
642 | 725 |
643 @param termination_func: Function to call when the process terminates. | 726 @param termination_func: Function to call when the process terminates. |
644 Must take a single parameter -- the exit status. | 727 Must take a single parameter -- the exit status. |
645 """ | 728 """ |
646 self.termination_func = termination_func | 729 self.termination_func = termination_func |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
758 | 841 |
759 def _join_thread(self): | 842 def _join_thread(self): |
760 # Wait for the tail thread to exit | 843 # Wait for the tail thread to exit |
761 # (it's done this way because self.tail_thread may become None at any | 844 # (it's done this way because self.tail_thread may become None at any |
762 # time) | 845 # time) |
763 t = self.tail_thread | 846 t = self.tail_thread |
764 if t: | 847 if t: |
765 t.join() | 848 t.join() |
766 | 849 |
767 | 850 |
768 class kvm_expect(kvm_tail): | 851 class Expect(Tail): |
769 """ | 852 """ |
770 This class runs a child process in the background and provides expect-like | 853 This class runs a child process in the background and provides expect-like |
771 services. | 854 services. |
772 | 855 |
773 It also provides all of kvm_tail's functionality. | 856 It also provides all of Tail's functionality. |
774 """ | 857 """ |
775 | 858 |
776 def __init__(self, command=None, id=None, auto_close=False, echo=False, | 859 def __init__(self, command=None, id=None, auto_close=True, echo=False, |
777 linesep="\n", termination_func=None, termination_params=(), | 860 linesep="\n", termination_func=None, termination_params=(), |
778 output_func=None, output_params=(), output_prefix=""): | 861 output_func=None, output_params=(), output_prefix=""): |
779 """ | 862 """ |
780 Initialize the class and run command as a child process. | 863 Initialize the class and run command as a child process. |
781 | 864 |
782 @param command: Command to run, or None if accessing an already running | 865 @param command: Command to run, or None if accessing an already running |
783 server. | 866 server. |
784 @param id: ID of an already running server, if accessing a running | 867 @param id: ID of an already running server, if accessing a running |
785 server, or None if starting a new one. | 868 server, or None if starting a new one. |
786 @param auto_close: If True, close() the instance automatically when its | 869 @param auto_close: If True, close() the instance automatically when its |
(...skipping 12 matching lines...) Expand all Loading... |
799 The function must accept a single string parameter. The string | 882 The function must accept a single string parameter. The string |
800 does not include the final newline. | 883 does not include the final newline. |
801 @param output_params: Parameters to send to output_func before the | 884 @param output_params: Parameters to send to output_func before the |
802 output line. | 885 output line. |
803 @param output_prefix: String to prepend to lines sent to output_func. | 886 @param output_prefix: String to prepend to lines sent to output_func. |
804 """ | 887 """ |
805 # Add a reader | 888 # Add a reader |
806 self._add_reader("expect") | 889 self._add_reader("expect") |
807 | 890 |
808 # Init the superclass | 891 # Init the superclass |
809 kvm_tail.__init__(self, command, id, auto_close, echo, linesep, | 892 Tail.__init__(self, command, id, auto_close, echo, linesep, |
810 termination_func, termination_params, | 893 termination_func, termination_params, |
811 output_func, output_params, output_prefix) | 894 output_func, output_params, output_prefix) |
812 | 895 |
813 | 896 |
814 def __getinitargs__(self): | 897 def __getinitargs__(self): |
815 return kvm_tail.__getinitargs__(self) | 898 return Tail.__getinitargs__(self) |
816 | 899 |
817 | 900 |
818 def read_nonblocking(self, timeout=None): | 901 def read_nonblocking(self, timeout=None): |
819 """ | 902 """ |
820 Read from child until there is nothing to read for timeout seconds. | 903 Read from child until there is nothing to read for timeout seconds. |
821 | 904 |
822 @param timeout: Time (seconds) to wait before we give up reading from | 905 @param timeout: Time (seconds) to wait before we give up reading from |
823 the child process, or None to use the default value. | 906 the child process, or None to use the default value. |
824 """ | 907 """ |
825 if timeout is None: | 908 if timeout is None: |
(...skipping 25 matching lines...) Expand all Loading... |
851 @param patterns: List of strings (regular expression patterns). | 934 @param patterns: List of strings (regular expression patterns). |
852 """ | 935 """ |
853 for i in range(len(patterns)): | 936 for i in range(len(patterns)): |
854 if not patterns[i]: | 937 if not patterns[i]: |
855 continue | 938 continue |
856 if re.search(patterns[i], str): | 939 if re.search(patterns[i], str): |
857 return i | 940 return i |
858 | 941 |
859 | 942 |
860 def read_until_output_matches(self, patterns, filter=lambda x: x, | 943 def read_until_output_matches(self, patterns, filter=lambda x: x, |
861 timeout=30.0, internal_timeout=None, | 944 timeout=60, internal_timeout=None, |
862 print_func=None): | 945 print_func=None): |
863 """ | 946 """ |
864 Read using read_nonblocking until a match is found using match_patterns, | 947 Read using read_nonblocking until a match is found using match_patterns, |
865 or until timeout expires. Before attempting to search for a match, the | 948 or until timeout expires. Before attempting to search for a match, the |
866 data is filtered using the filter function provided. | 949 data is filtered using the filter function provided. |
867 | 950 |
868 @brief: Read from child using read_nonblocking until a pattern | 951 @brief: Read from child using read_nonblocking until a pattern |
869 matches. | 952 matches. |
870 @param patterns: List of strings (regular expression patterns) | 953 @param patterns: List of strings (regular expression patterns) |
871 @param filter: Function to apply to the data read from the child before | 954 @param filter: Function to apply to the data read from the child before |
872 attempting to match it against the patterns (should take and | 955 attempting to match it against the patterns (should take and |
873 return a string) | 956 return a string) |
874 @param timeout: The duration (in seconds) to wait until a match is | 957 @param timeout: The duration (in seconds) to wait until a match is |
875 found | 958 found |
876 @param internal_timeout: The timeout to pass to read_nonblocking | 959 @param internal_timeout: The timeout to pass to read_nonblocking |
877 @param print_func: A function to be used to print the data being read | 960 @param print_func: A function to be used to print the data being read |
878 (should take a string parameter) | 961 (should take a string parameter) |
879 @return: Tuple containing the match index (or None if no match was | 962 @return: Tuple containing the match index and the data read so far |
880 found) and the data read so far. | 963 @raise ExpectTimeoutError: Raised if timeout expires |
| 964 @raise ExpectProcessTerminatedError: Raised if the child process |
| 965 terminates while waiting for output |
| 966 @raise ExpectError: Raised if an unknown error occurs |
881 """ | 967 """ |
882 match = None | |
883 data = "" | |
884 | |
885 fd = self._get_fd("expect") | 968 fd = self._get_fd("expect") |
| 969 o = "" |
886 end_time = time.time() + timeout | 970 end_time = time.time() + timeout |
887 while True: | 971 while True: |
888 try: | 972 try: |
889 r, w, x = select.select([fd], [], [], | 973 r, w, x = select.select([fd], [], [], |
890 max(0, end_time - time.time())) | 974 max(0, end_time - time.time())) |
891 except (select.error, TypeError): | 975 except (select.error, TypeError): |
892 break | 976 break |
893 if fd not in r: | 977 if not r: |
| 978 raise ExpectTimeoutError(patterns, o) |
| 979 # Read data from child |
| 980 data = self.read_nonblocking(internal_timeout) |
| 981 if not data: |
894 break | 982 break |
895 # Read data from child | |
896 newdata = self.read_nonblocking(internal_timeout) | |
897 # Print it if necessary | 983 # Print it if necessary |
898 if print_func and newdata: | 984 if print_func: |
899 str = newdata | 985 for line in data.splitlines(): |
900 if str.endswith("\n"): | |
901 str = str[:-1] | |
902 for line in str.split("\n"): | |
903 print_func(line) | 986 print_func(line) |
904 data += newdata | 987 # Look for patterns |
| 988 o += data |
| 989 match = self.match_patterns(filter(o), patterns) |
| 990 if match is not None: |
| 991 return match, o |
905 | 992 |
906 done = False | 993 # Check if the child has terminated |
907 # Look for patterns | 994 if kvm_utils.wait_for(lambda: not self.is_alive(), 5, 0, 0.1): |
908 match = self.match_patterns(filter(data), patterns) | 995 raise ExpectProcessTerminatedError(patterns, self.get_status(), o) |
909 if match is not None: | 996 else: |
910 done = True | 997 # This shouldn't happen |
911 # Check if child has died | 998 raise ExpectError(patterns, o) |
912 if not self.is_alive(): | |
913 logging.debug("Process terminated with status %s" % | |
914 self.get_status()) | |
915 done = True | |
916 # Are we done? | |
917 if done: break | |
918 | |
919 # Print some debugging info | |
920 if match is None and (self.is_alive() or self.get_status() != 0): | |
921 logging.debug("Timeout elapsed or process terminated. Output:" + | |
922 kvm_utils.format_str_for_message(data.strip())) | |
923 | |
924 return (match, data) | |
925 | 999 |
926 | 1000 |
927 def read_until_last_word_matches(self, patterns, timeout=30.0, | 1001 def read_until_last_word_matches(self, patterns, timeout=60, |
928 internal_timeout=None, print_func=None): | 1002 internal_timeout=None, print_func=None): |
929 """ | 1003 """ |
930 Read using read_nonblocking until the last word of the output matches | 1004 Read using read_nonblocking until the last word of the output matches |
931 one of the patterns (using match_patterns), or until timeout expires. | 1005 one of the patterns (using match_patterns), or until timeout expires. |
932 | 1006 |
933 @param patterns: A list of strings (regular expression patterns) | 1007 @param patterns: A list of strings (regular expression patterns) |
934 @param timeout: The duration (in seconds) to wait until a match is | 1008 @param timeout: The duration (in seconds) to wait until a match is |
935 found | 1009 found |
936 @param internal_timeout: The timeout to pass to read_nonblocking | 1010 @param internal_timeout: The timeout to pass to read_nonblocking |
937 @param print_func: A function to be used to print the data being read | 1011 @param print_func: A function to be used to print the data being read |
938 (should take a string parameter) | 1012 (should take a string parameter) |
939 @return: A tuple containing the match index (or None if no match was | 1013 @return: A tuple containing the match index and the data read so far |
940 found) and the data read so far. | 1014 @raise ExpectTimeoutError: Raised if timeout expires |
| 1015 @raise ExpectProcessTerminatedError: Raised if the child process |
| 1016 terminates while waiting for output |
| 1017 @raise ExpectError: Raised if an unknown error occurs |
941 """ | 1018 """ |
942 def get_last_word(str): | 1019 def get_last_word(str): |
943 if str: | 1020 if str: |
944 return str.split()[-1] | 1021 return str.split()[-1] |
945 else: | 1022 else: |
946 return "" | 1023 return "" |
947 | 1024 |
948 return self.read_until_output_matches(patterns, get_last_word, | 1025 return self.read_until_output_matches(patterns, get_last_word, |
949 timeout, internal_timeout, | 1026 timeout, internal_timeout, |
950 print_func) | 1027 print_func) |
951 | 1028 |
952 | 1029 |
953 def read_until_last_line_matches(self, patterns, timeout=30.0, | 1030 def read_until_last_line_matches(self, patterns, timeout=60, |
954 internal_timeout=None, print_func=None): | 1031 internal_timeout=None, print_func=None): |
955 """ | 1032 """ |
956 Read using read_nonblocking until the last non-empty line of the output | 1033 Read using read_nonblocking until the last non-empty line of the output |
957 matches one of the patterns (using match_patterns), or until timeout | 1034 matches one of the patterns (using match_patterns), or until timeout |
958 expires. Return a tuple containing the match index (or None if no match | 1035 expires. Return a tuple containing the match index (or None if no match |
959 was found) and the data read so far. | 1036 was found) and the data read so far. |
960 | 1037 |
961 @brief: Read using read_nonblocking until the last non-empty line | 1038 @brief: Read using read_nonblocking until the last non-empty line |
962 matches a pattern. | 1039 matches a pattern. |
963 | 1040 |
964 @param patterns: A list of strings (regular expression patterns) | 1041 @param patterns: A list of strings (regular expression patterns) |
965 @param timeout: The duration (in seconds) to wait until a match is | 1042 @param timeout: The duration (in seconds) to wait until a match is |
966 found | 1043 found |
967 @param internal_timeout: The timeout to pass to read_nonblocking | 1044 @param internal_timeout: The timeout to pass to read_nonblocking |
968 @param print_func: A function to be used to print the data being read | 1045 @param print_func: A function to be used to print the data being read |
969 (should take a string parameter) | 1046 (should take a string parameter) |
| 1047 @return: A tuple containing the match index and the data read so far |
| 1048 @raise ExpectTimeoutError: Raised if timeout expires |
| 1049 @raise ExpectProcessTerminatedError: Raised if the child process |
| 1050 terminates while waiting for output |
| 1051 @raise ExpectError: Raised if an unknown error occurs |
970 """ | 1052 """ |
971 def get_last_nonempty_line(str): | 1053 def get_last_nonempty_line(str): |
972 nonempty_lines = [l for l in str.splitlines() if l.strip()] | 1054 nonempty_lines = [l for l in str.splitlines() if l.strip()] |
973 if nonempty_lines: | 1055 if nonempty_lines: |
974 return nonempty_lines[-1] | 1056 return nonempty_lines[-1] |
975 else: | 1057 else: |
976 return "" | 1058 return "" |
977 | 1059 |
978 return self.read_until_output_matches(patterns, get_last_nonempty_line, | 1060 return self.read_until_output_matches(patterns, get_last_nonempty_line, |
979 timeout, internal_timeout, | 1061 timeout, internal_timeout, |
980 print_func) | 1062 print_func) |
981 | 1063 |
982 | 1064 |
983 class kvm_shell_session(kvm_expect): | 1065 class ShellSession(Expect): |
984 """ | 1066 """ |
985 This class runs a child process in the background. It it suited for | 1067 This class runs a child process in the background. It it suited for |
986 processes that provide an interactive shell, such as SSH and Telnet. | 1068 processes that provide an interactive shell, such as SSH and Telnet. |
987 | 1069 |
988 It provides all services of kvm_expect and kvm_tail. In addition, it | 1070 It provides all services of Expect and Tail. In addition, it |
989 provides command running services, and a utility function to test the | 1071 provides command running services, and a utility function to test the |
990 process for responsiveness. | 1072 process for responsiveness. |
991 """ | 1073 """ |
992 | 1074 |
993 def __init__(self, command=None, id=None, auto_close=True, echo=False, | 1075 def __init__(self, command=None, id=None, auto_close=True, echo=False, |
994 linesep="\n", termination_func=None, termination_params=(), | 1076 linesep="\n", termination_func=None, termination_params=(), |
995 output_func=None, output_params=(), output_prefix="", | 1077 output_func=None, output_params=(), output_prefix="", |
996 prompt=r"[\#\$]\s*$", status_test_command="echo $?"): | 1078 prompt=r"[\#\$]\s*$", status_test_command="echo $?"): |
997 """ | 1079 """ |
998 Initialize the class and run command as a child process. | 1080 Initialize the class and run command as a child process. |
(...skipping 16 matching lines...) Expand all Loading... |
1015 @param output_func: Function to call whenever a line of output is | 1097 @param output_func: Function to call whenever a line of output is |
1016 available from the STDOUT or STDERR streams of the process. | 1098 available from the STDOUT or STDERR streams of the process. |
1017 The function must accept a single string parameter. The string | 1099 The function must accept a single string parameter. The string |
1018 does not include the final newline. | 1100 does not include the final newline. |
1019 @param output_params: Parameters to send to output_func before the | 1101 @param output_params: Parameters to send to output_func before the |
1020 output line. | 1102 output line. |
1021 @param output_prefix: String to prepend to lines sent to output_func. | 1103 @param output_prefix: String to prepend to lines sent to output_func. |
1022 @param prompt: Regular expression describing the shell's prompt line. | 1104 @param prompt: Regular expression describing the shell's prompt line. |
1023 @param status_test_command: Command to be used for getting the last | 1105 @param status_test_command: Command to be used for getting the last |
1024 exit status of commands run inside the shell (used by | 1106 exit status of commands run inside the shell (used by |
1025 get_command_status_output() and friends). | 1107 cmd_status_output() and friends). |
1026 """ | 1108 """ |
1027 # Init the superclass | 1109 # Init the superclass |
1028 kvm_expect.__init__(self, command, id, auto_close, echo, linesep, | 1110 Expect.__init__(self, command, id, auto_close, echo, linesep, |
1029 termination_func, termination_params, | 1111 termination_func, termination_params, |
1030 output_func, output_params, output_prefix) | 1112 output_func, output_params, output_prefix) |
1031 | 1113 |
1032 # Remember some attributes | 1114 # Remember some attributes |
1033 self.prompt = prompt | 1115 self.prompt = prompt |
1034 self.status_test_command = status_test_command | 1116 self.status_test_command = status_test_command |
1035 | 1117 |
1036 | 1118 |
1037 def __getinitargs__(self): | 1119 def __getinitargs__(self): |
1038 return kvm_expect.__getinitargs__(self) + (self.prompt, | 1120 return Expect.__getinitargs__(self) + (self.prompt, |
1039 self.status_test_command) | 1121 self.status_test_command) |
1040 | 1122 |
1041 | 1123 |
1042 def set_prompt(self, prompt): | 1124 def set_prompt(self, prompt): |
1043 """ | 1125 """ |
1044 Set the prompt attribute for later use by read_up_to_prompt. | 1126 Set the prompt attribute for later use by read_up_to_prompt. |
1045 | 1127 |
1046 @param: String that describes the prompt contents. | 1128 @param: String that describes the prompt contents. |
1047 """ | 1129 """ |
1048 self.prompt = prompt | 1130 self.prompt = prompt |
1049 | 1131 |
(...skipping 28 matching lines...) Expand all Loading... |
1078 # Wait up to timeout seconds for some output from the child | 1160 # Wait up to timeout seconds for some output from the child |
1079 end_time = time.time() + timeout | 1161 end_time = time.time() + timeout |
1080 while time.time() < end_time: | 1162 while time.time() < end_time: |
1081 time.sleep(0.5) | 1163 time.sleep(0.5) |
1082 if self.read_nonblocking(timeout=0).strip(): | 1164 if self.read_nonblocking(timeout=0).strip(): |
1083 return True | 1165 return True |
1084 # No output -- report unresponsive | 1166 # No output -- report unresponsive |
1085 return False | 1167 return False |
1086 | 1168 |
1087 | 1169 |
1088 def read_up_to_prompt(self, timeout=30.0, internal_timeout=None, | 1170 def read_up_to_prompt(self, timeout=60, internal_timeout=None, |
1089 print_func=None): | 1171 print_func=None): |
1090 """ | 1172 """ |
1091 Read using read_nonblocking until the last non-empty line of the output | 1173 Read using read_nonblocking until the last non-empty line of the output |
1092 matches the prompt regular expression set by set_prompt, or until | 1174 matches the prompt regular expression set by set_prompt, or until |
1093 timeout expires. | 1175 timeout expires. |
1094 | 1176 |
1095 @brief: Read using read_nonblocking until the last non-empty line | 1177 @brief: Read using read_nonblocking until the last non-empty line |
1096 matches the prompt. | 1178 matches the prompt. |
1097 | 1179 |
1098 @param timeout: The duration (in seconds) to wait until a match is | 1180 @param timeout: The duration (in seconds) to wait until a match is |
1099 found | 1181 found |
1100 @param internal_timeout: The timeout to pass to read_nonblocking | 1182 @param internal_timeout: The timeout to pass to read_nonblocking |
1101 @param print_func: A function to be used to print the data being | 1183 @param print_func: A function to be used to print the data being |
1102 read (should take a string parameter) | 1184 read (should take a string parameter) |
1103 | 1185 |
1104 @return: A tuple containing True/False indicating whether the prompt | 1186 @return: The data read so far |
1105 was found, and the data read so far. | 1187 @raise ExpectTimeoutError: Raised if timeout expires |
| 1188 @raise ExpectProcessTerminatedError: Raised if the shell process |
| 1189 terminates while waiting for output |
| 1190 @raise ExpectError: Raised if an unknown error occurs |
1106 """ | 1191 """ |
1107 (match, output) = self.read_until_last_line_matches([self.prompt], | 1192 m, o = self.read_until_last_line_matches([self.prompt], timeout, |
1108 timeout, | 1193 internal_timeout, print_func) |
1109 internal_timeout, | 1194 return o |
1110 print_func) | |
1111 return (match is not None, output) | |
1112 | 1195 |
1113 | 1196 |
1114 def get_command_status_output(self, command, timeout=30.0, | 1197 def cmd_output(self, cmd, timeout=60, internal_timeout=None, |
1115 internal_timeout=None, print_func=None): | 1198 print_func=None): |
1116 """ | 1199 """ |
1117 Send a command and return its exit status and output. | 1200 Send a command and return its output. |
1118 | 1201 |
1119 @param command: Command to send (must not contain newline characters) | 1202 @param cmd: Command to send (must not contain newline characters) |
1120 @param timeout: The duration (in seconds) to wait until a match is | 1203 @param timeout: The duration (in seconds) to wait for the prompt to |
1121 found | 1204 return |
1122 @param internal_timeout: The timeout to pass to read_nonblocking | 1205 @param internal_timeout: The timeout to pass to read_nonblocking |
1123 @param print_func: A function to be used to print the data being read | 1206 @param print_func: A function to be used to print the data being read |
1124 (should take a string parameter) | 1207 (should take a string parameter) |
1125 | 1208 |
1126 @return: A tuple (status, output) where status is the exit status or | 1209 @return: The output of cmd |
1127 None if no exit status is available (e.g. timeout elapsed), and | 1210 @raise ShellTimeoutError: Raised if timeout expires |
1128 output is the output of command. | 1211 @raise ShellProcessTerminatedError: Raised if the shell process |
| 1212 terminates while waiting for output |
| 1213 @raise ShellError: Raised if an unknown error occurs |
1129 """ | 1214 """ |
1130 def remove_command_echo(str, cmd): | 1215 def remove_command_echo(str, cmd): |
1131 if str and str.splitlines()[0] == cmd: | 1216 if str and str.splitlines()[0] == cmd: |
1132 str = "".join(str.splitlines(True)[1:]) | 1217 str = "".join(str.splitlines(True)[1:]) |
1133 return str | 1218 return str |
1134 | 1219 |
1135 def remove_last_nonempty_line(str): | 1220 def remove_last_nonempty_line(str): |
1136 return "".join(str.rstrip().splitlines(True)[:-1]) | 1221 return "".join(str.rstrip().splitlines(True)[:-1]) |
1137 | 1222 |
1138 # Print some debugging info | 1223 logging.debug("Sending command: %s" % cmd) |
1139 logging.debug("Sending command: %s" % command) | 1224 self.read_nonblocking(timeout=0) |
| 1225 self.sendline(cmd) |
| 1226 try: |
| 1227 o = self.read_up_to_prompt(timeout, internal_timeout, print_func) |
| 1228 except ExpectError, e: |
| 1229 o = remove_command_echo(e.output, cmd) |
| 1230 if isinstance(e, ExpectTimeoutError): |
| 1231 raise ShellTimeoutError(cmd, o) |
| 1232 elif isinstance(e, ExpectProcessTerminatedError): |
| 1233 raise ShellProcessTerminatedError(cmd, e.status, o) |
| 1234 else: |
| 1235 raise ShellError(cmd, o) |
1140 | 1236 |
1141 # Read everything that's waiting to be read | 1237 # Remove the echoed command and the final shell prompt |
1142 self.read_nonblocking(timeout=0) | 1238 return remove_last_nonempty_line(remove_command_echo(o, cmd)) |
1143 | |
1144 # Send the command and get its output | |
1145 self.sendline(command) | |
1146 (match, output) = self.read_up_to_prompt(timeout, internal_timeout, | |
1147 print_func) | |
1148 # Remove the echoed command from the output | |
1149 output = remove_command_echo(output, command) | |
1150 # If the prompt was not found, return the output so far | |
1151 if not match: | |
1152 return (None, output) | |
1153 # Remove the final shell prompt from the output | |
1154 output = remove_last_nonempty_line(output) | |
1155 | |
1156 # Send the 'echo ...' command to get the last exit status | |
1157 self.sendline(self.status_test_command) | |
1158 (match, status) = self.read_up_to_prompt(10.0, internal_timeout) | |
1159 if not match: | |
1160 return (None, output) | |
1161 status = remove_command_echo(status, self.status_test_command) | |
1162 status = remove_last_nonempty_line(status) | |
1163 # Get the first line consisting of digits only | |
1164 digit_lines = [l for l in status.splitlines() if l.strip().isdigit()] | |
1165 if not digit_lines: | |
1166 return (None, output) | |
1167 status = int(digit_lines[0].strip()) | |
1168 | |
1169 # Print some debugging info | |
1170 if status != 0: | |
1171 logging.debug("Command failed; status: %d, output:%s", status, | |
1172 kvm_utils.format_str_for_message(output.strip())) | |
1173 | |
1174 return (status, output) | |
1175 | 1239 |
1176 | 1240 |
1177 def get_command_status(self, command, timeout=30.0, internal_timeout=None, | 1241 def cmd_status_output(self, cmd, timeout=60, internal_timeout=None, |
1178 print_func=None): | 1242 print_func=None): |
1179 """ | 1243 """ |
1180 Send a command and return its exit status. | 1244 Send a command and return its exit status and output. |
1181 | 1245 |
1182 @param command: Command to send | 1246 @param cmd: Command to send (must not contain newline characters) |
1183 @param timeout: The duration (in seconds) to wait until a match is | 1247 @param timeout: The duration (in seconds) to wait for the prompt to |
1184 found | 1248 return |
1185 @param internal_timeout: The timeout to pass to read_nonblocking | 1249 @param internal_timeout: The timeout to pass to read_nonblocking |
1186 @param print_func: A function to be used to print the data being read | 1250 @param print_func: A function to be used to print the data being read |
1187 (should take a string parameter) | 1251 (should take a string parameter) |
1188 | 1252 |
1189 @return: Exit status or None if no exit status is available (e.g. | 1253 @return: A tuple (status, output) where status is the exit status and |
1190 timeout elapsed). | 1254 output is the output of cmd |
| 1255 @raise ShellTimeoutError: Raised if timeout expires |
| 1256 @raise ShellProcessTerminatedError: Raised if the shell process |
| 1257 terminates while waiting for output |
| 1258 @raise ShellStatusError: Raised if the exit status cannot be obtained |
| 1259 @raise ShellError: Raised if an unknown error occurs |
1191 """ | 1260 """ |
1192 (status, output) = self.get_command_status_output(command, timeout, | 1261 o = self.cmd_output(cmd, timeout, internal_timeout, print_func) |
1193 internal_timeout, | 1262 try: |
1194 print_func) | 1263 # Send the 'echo $?' (or equivalent) command to get the exit status |
1195 return status | 1264 s = self.cmd_output(self.status_test_command, 10, internal_timeout) |
| 1265 except ShellError: |
| 1266 raise ShellStatusError(cmd, o) |
| 1267 |
| 1268 # Get the first line consisting of digits only |
| 1269 digit_lines = [l for l in s.splitlines() if l.strip().isdigit()] |
| 1270 if digit_lines: |
| 1271 return int(digit_lines[0].strip()), o |
| 1272 else: |
| 1273 raise ShellStatusError(cmd, o) |
1196 | 1274 |
1197 | 1275 |
1198 def get_command_output(self, command, timeout=30.0, internal_timeout=None, | 1276 def cmd_status(self, cmd, timeout=60, internal_timeout=None, |
1199 print_func=None): | 1277 print_func=None): |
1200 """ | 1278 """ |
1201 Send a command and return its output. | 1279 Send a command and return its exit status. |
1202 | 1280 |
1203 @param command: Command to send | 1281 @param cmd: Command to send (must not contain newline characters) |
1204 @param timeout: The duration (in seconds) to wait until a match is | 1282 @param timeout: The duration (in seconds) to wait for the prompt to |
1205 found | 1283 return |
1206 @param internal_timeout: The timeout to pass to read_nonblocking | 1284 @param internal_timeout: The timeout to pass to read_nonblocking |
1207 @param print_func: A function to be used to print the data being read | 1285 @param print_func: A function to be used to print the data being read |
1208 (should take a string parameter) | 1286 (should take a string parameter) |
| 1287 |
| 1288 @return: The exit status of cmd |
| 1289 @raise ShellTimeoutError: Raised if timeout expires |
| 1290 @raise ShellProcessTerminatedError: Raised if the shell process |
| 1291 terminates while waiting for output |
| 1292 @raise ShellStatusError: Raised if the exit status cannot be obtained |
| 1293 @raise ShellError: Raised if an unknown error occurs |
1209 """ | 1294 """ |
1210 (status, output) = self.get_command_status_output(command, timeout, | 1295 s, o = self.cmd_status_output(cmd, timeout, internal_timeout, |
1211 internal_timeout, | 1296 print_func) |
1212 print_func) | 1297 return s |
1213 return output | 1298 |
| 1299 |
| 1300 def cmd(self, cmd, timeout=60, internal_timeout=None, print_func=None): |
| 1301 """ |
| 1302 Send a command and return its output. If the command's exit status is |
| 1303 nonzero, raise an exception. |
| 1304 |
| 1305 @param cmd: Command to send (must not contain newline characters) |
| 1306 @param timeout: The duration (in seconds) to wait for the prompt to |
| 1307 return |
| 1308 @param internal_timeout: The timeout to pass to read_nonblocking |
| 1309 @param print_func: A function to be used to print the data being read |
| 1310 (should take a string parameter) |
| 1311 |
| 1312 @return: The output of cmd |
| 1313 @raise ShellTimeoutError: Raised if timeout expires |
| 1314 @raise ShellProcessTerminatedError: Raised if the shell process |
| 1315 terminates while waiting for output |
| 1316 @raise ShellError: Raised if the exit status cannot be obtained or if |
| 1317 an unknown error occurs |
| 1318 @raise ShellStatusError: Raised if the exit status cannot be obtained |
| 1319 @raise ShellError: Raised if an unknown error occurs |
| 1320 @raise ShellCmdError: Raised if the exit status is nonzero |
| 1321 """ |
| 1322 s, o = self.cmd_status_output(cmd, timeout, internal_timeout, |
| 1323 print_func) |
| 1324 if s != 0: |
| 1325 raise ShellCmdError(cmd, s, o) |
| 1326 return o |
| 1327 |
| 1328 |
| 1329 def get_command_output(self, cmd, timeout=60, internal_timeout=None, |
| 1330 print_func=None): |
| 1331 """ |
| 1332 Alias for cmd_output() for backward compatibility. |
| 1333 """ |
| 1334 return self.cmd_output(cmd, timeout, internal_timeout, print_func) |
| 1335 |
| 1336 |
| 1337 def get_command_status_output(self, cmd, timeout=60, internal_timeout=None, |
| 1338 print_func=None): |
| 1339 """ |
| 1340 Alias for cmd_status_output() for backward compatibility. |
| 1341 """ |
| 1342 return self.cmd_status_output(cmd, timeout, internal_timeout, |
| 1343 print_func) |
| 1344 |
| 1345 |
| 1346 def get_command_status(self, cmd, timeout=60, internal_timeout=None, |
| 1347 print_func=None): |
| 1348 """ |
| 1349 Alias for cmd_status() for backward compatibility. |
| 1350 """ |
| 1351 return self.cmd_status(cmd, timeout, internal_timeout, print_func) |
OLD | NEW |