| OLD | NEW |
| 1 import logging, os, sys, subprocess, tempfile, traceback | 1 import logging, os, sys, subprocess, tempfile, traceback |
| 2 import time | 2 import time |
| 3 | 3 |
| 4 from autotest_lib.client.common_lib import utils | 4 from autotest_lib.client.common_lib import utils |
| 5 from autotest_lib.server import utils as server_utils | 5 from autotest_lib.server import utils as server_utils |
| 6 from autotest_lib.server.hosts import abstract_ssh, monitors | 6 from autotest_lib.server.hosts import abstract_ssh, monitors |
| 7 | 7 |
| 8 MONITORDIR = monitors.__path__[0] | 8 MONITORDIR = monitors.__path__[0] |
| 9 SUPPORTED_PYTHON_VERS = ('2.4', '2.5', '2.6') | 9 SUPPORTED_PYTHON_VERS = ('2.4', '2.5', '2.6') |
| 10 DEFAULT_PYTHON = '/usr/bin/python' | 10 DEFAULT_PYTHON = '/usr/bin/python' |
| 11 | 11 |
| 12 | 12 |
| 13 class Error(Exception): | 13 class Error(Exception): |
| 14 pass | 14 pass |
| 15 | 15 |
| 16 | 16 |
| 17 class InvalidPatternsPathError(Error): | 17 class InvalidPatternsPathError(Error): |
| 18 """An invalid patterns_path was specified.""" | 18 """An invalid patterns_path was specified.""" |
| 19 | 19 |
| 20 | 20 |
| 21 class InvalidConfigurationError(Error): | 21 class InvalidConfigurationError(Error): |
| 22 """An invalid configuration was specified.""" | 22 """An invalid configuration was specified.""" |
| 23 | 23 |
| 24 | 24 |
| 25 class FollowFilesLaunchError(Error): | 25 class FollowFilesLaunchError(Error): |
| 26 """Error occurred launching followfiles remotely.""" | 26 """Error occurred launching followfiles remotely.""" |
| 27 | 27 |
| 28 | 28 |
| 29 def run_cmd_on_host(hostname, cmd, stdin, stdout, stderr): | |
| 30 base_cmd = abstract_ssh.make_ssh_command() | |
| 31 full_cmd = "%s %s \"%s\"" % (base_cmd, hostname, | |
| 32 server_utils.sh_escape(cmd)) | |
| 33 | |
| 34 return subprocess.Popen(full_cmd, stdin=stdin, stdout=stdout, | |
| 35 stderr=stderr, shell=True) | |
| 36 | |
| 37 | |
| 38 def list_remote_pythons(host): | 29 def list_remote_pythons(host): |
| 39 """List out installed pythons on host.""" | 30 """List out installed pythons on host.""" |
| 40 result = host.run('ls /usr/bin/python[0-9]*') | 31 result = host.run('ls /usr/bin/python[0-9]*') |
| 41 return result.stdout.splitlines() | 32 return result.stdout.splitlines() |
| 42 | 33 |
| 43 | 34 |
| 44 def select_supported_python(installed_pythons): | 35 def select_supported_python(installed_pythons): |
| 45 """Select a supported python from a list""" | 36 """Select a supported python from a list""" |
| 46 for python in installed_pythons: | 37 for python in installed_pythons: |
| 47 if python[-3:] in SUPPORTED_PYTHON_VERS: | 38 if python[-3:] in SUPPORTED_PYTHON_VERS: |
| (...skipping 17 matching lines...) Expand all Loading... |
| 65 supported_python = select_supported_python(installed_pythons) | 56 supported_python = select_supported_python(installed_pythons) |
| 66 if not supported_python: | 57 if not supported_python: |
| 67 if DEFAULT_PYTHON in installed_pythons: | 58 if DEFAULT_PYTHON in installed_pythons: |
| 68 logging.info('No versioned Python binary found, ' | 59 logging.info('No versioned Python binary found, ' |
| 69 'defaulting to: %s', DEFAULT_PYTHON) | 60 'defaulting to: %s', DEFAULT_PYTHON) |
| 70 supported_python = DEFAULT_PYTHON | 61 supported_python = DEFAULT_PYTHON |
| 71 else: | 62 else: |
| 72 raise FollowFilesLaunchError('No supported Python on host.') | 63 raise FollowFilesLaunchError('No supported Python on host.') |
| 73 | 64 |
| 74 remote_monitordir = copy_monitordir(host) | 65 remote_monitordir = copy_monitordir(host) |
| 75 remote_script_path = os.path.join( | 66 remote_script_path = os.path.join(remote_monitordir, 'followfiles.py') |
| 76 remote_monitordir, 'followfiles.py') | |
| 77 | 67 |
| 78 followfiles_cmd = '%s %s --lastlines_dirpath=%s %s' % ( | 68 followfiles_cmd = '%s %s --lastlines_dirpath=%s %s' % ( |
| 79 supported_python, remote_script_path, | 69 supported_python, remote_script_path, |
| 80 lastlines_dirpath, ' '.join(follow_paths)) | 70 lastlines_dirpath, ' '.join(follow_paths)) |
| 81 | 71 |
| 82 devnull_r = open(os.devnull, 'r') | 72 remote_ff_proc = subprocess.Popen(host._make_ssh_cmd(followfiles_cmd), |
| 83 devnull_w = open(os.devnull, 'w') | 73 stdin=open(os.devnull, 'r'), |
| 84 remote_followfiles_proc = run_cmd_on_host( | 74 stdout=subprocess.PIPE, shell=True) |
| 85 host.hostname, followfiles_cmd, stdout=subprocess.PIPE, | 75 |
| 86 stdin=devnull_r, stderr=devnull_w) | 76 |
| 87 # Give it enough time to crash if it's going to (it shouldn't). | 77 # Give it enough time to crash if it's going to (it shouldn't). |
| 88 time.sleep(5) | 78 time.sleep(5) |
| 89 doa = remote_followfiles_proc.poll() | 79 doa = remote_ff_proc.poll() |
| 90 if doa: | 80 if doa: |
| 91 raise FollowFilesLaunchError('ssh command crashed.') | 81 raise FollowFilesLaunchError('ssh command crashed.') |
| 92 | 82 |
| 93 return remote_followfiles_proc | 83 return remote_ff_proc |
| 94 | 84 |
| 95 | 85 |
| 96 def resolve_patterns_path(patterns_path): | 86 def resolve_patterns_path(patterns_path): |
| 97 """Resolve patterns_path to existing absolute local path or raise. | 87 """Resolve patterns_path to existing absolute local path or raise. |
| 98 | 88 |
| 99 As a convenience we allow users to specify a non-absolute patterns_path. | 89 As a convenience we allow users to specify a non-absolute patterns_path. |
| 100 However these need to be resolved before allowing them to be passed down | 90 However these need to be resolved before allowing them to be passed down |
| 101 to console.py. | 91 to console.py. |
| 102 | 92 |
| 103 For now we expect non-absolute ones to be in self.monitordir. | 93 For now we expect non-absolute ones to be in self.monitordir. |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 292 pattern_paths: list; Local alert pattern definition files. | 282 pattern_paths: list; Local alert pattern definition files. |
| 293 """ | 283 """ |
| 294 if not follow_paths or (pattern_paths and not follow_paths): | 284 if not follow_paths or (pattern_paths and not follow_paths): |
| 295 raise InvalidConfigurationError | 285 raise InvalidConfigurationError |
| 296 | 286 |
| 297 return type( | 287 return type( |
| 298 'LogfileMonitorMixin%d' % id(follow_paths), | 288 'LogfileMonitorMixin%d' % id(follow_paths), |
| 299 (LogfileMonitorMixin,), | 289 (LogfileMonitorMixin,), |
| 300 {'follow_paths': follow_paths, | 290 {'follow_paths': follow_paths, |
| 301 'pattern_paths': pattern_paths or ()}) | 291 'pattern_paths': pattern_paths or ()}) |
| OLD | NEW |