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