OLD | NEW |
1 # Copyright 2013 The Chromium Authors. All rights reserved. | 1 # Copyright 2013 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 """A wrapper around ssh for common operations on a CrOS-based device""" | 4 """A wrapper around ssh for common operations on a CrOS-based device""" |
5 import logging | 5 import logging |
6 import re | 6 import re |
7 import os | 7 import os |
8 import shutil | 8 import shutil |
9 import stat | 9 import stat |
10 import subprocess | 10 import subprocess |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
69 return False | 69 return False |
70 | 70 |
71 class LoginException(Exception): | 71 class LoginException(Exception): |
72 pass | 72 pass |
73 | 73 |
74 class KeylessLoginRequiredException(LoginException): | 74 class KeylessLoginRequiredException(LoginException): |
75 pass | 75 pass |
76 | 76 |
77 class CrOSInterface(object): | 77 class CrOSInterface(object): |
78 # pylint: disable=R0923 | 78 # pylint: disable=R0923 |
79 def __init__(self, hostname = None, ssh_identity = None): | 79 def __init__(self, hostname=None, ssh_identity=None): |
80 self._hostname = hostname | 80 self._hostname = hostname |
81 # List of ports generated from GetRemotePort() that may not be in use yet. | 81 # List of ports generated from GetRemotePort() that may not be in use yet. |
82 self._reserved_ports = [] | 82 self._reserved_ports = [] |
83 | 83 |
84 if self.local: | 84 if self.local: |
85 return | 85 return |
86 | 86 |
87 self._ssh_identity = None | 87 self._ssh_identity = None |
88 self._ssh_args = ['-o ConnectTimeout=5', | 88 self._ssh_args = ['-o ConnectTimeout=5', |
89 '-o StrictHostKeyChecking=no', | 89 '-o StrictHostKeyChecking=no', |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
141 def _RemoveSSHWarnings(self, toClean): | 141 def _RemoveSSHWarnings(self, toClean): |
142 """Removes specific ssh warning lines from a string. | 142 """Removes specific ssh warning lines from a string. |
143 | 143 |
144 Args: | 144 Args: |
145 toClean: A string that may be containing multiple lines. | 145 toClean: A string that may be containing multiple lines. |
146 | 146 |
147 Returns: | 147 Returns: |
148 A copy of toClean with all the Warning lines removed. | 148 A copy of toClean with all the Warning lines removed. |
149 """ | 149 """ |
150 # Remove the Warning about connecting to a new host for the first time. | 150 # Remove the Warning about connecting to a new host for the first time. |
151 return re.sub('Warning: Permanently added [^\n]* to the list of known ' | 151 return re.sub( |
152 'hosts.\s\n', '', toClean) | 152 r'Warning: Permanently added [^\n]* to the list of known hosts.\s\n', |
| 153 '', toClean) |
153 | 154 |
154 def RunCmdOnDevice(self, args, cwd=None, quiet=False): | 155 def RunCmdOnDevice(self, args, cwd=None, quiet=False): |
155 stdout, stderr = GetAllCmdOutput( | 156 stdout, stderr = GetAllCmdOutput( |
156 self.FormSSHCommandLine(args), cwd, quiet=quiet) | 157 self.FormSSHCommandLine(args), cwd, quiet=quiet) |
157 # The initial login will add the host to the hosts file but will also print | 158 # The initial login will add the host to the hosts file but will also print |
158 # a warning to stderr that we need to remove. | 159 # a warning to stderr that we need to remove. |
159 stderr = self._RemoveSSHWarnings(stderr) | 160 stderr = self._RemoveSSHWarnings(stderr) |
160 return stdout, stderr | 161 return stdout, stderr |
161 | 162 |
162 def TryLogin(self): | 163 def TryLogin(self): |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
203 return exists | 204 return exists |
204 | 205 |
205 def PushFile(self, filename, remote_filename): | 206 def PushFile(self, filename, remote_filename): |
206 if self.local: | 207 if self.local: |
207 args = ['cp', '-r', filename, remote_filename] | 208 args = ['cp', '-r', filename, remote_filename] |
208 stdout, stderr = GetAllCmdOutput(args, quiet=True) | 209 stdout, stderr = GetAllCmdOutput(args, quiet=True) |
209 if stderr != '': | 210 if stderr != '': |
210 raise OSError('No such file or directory %s' % stderr) | 211 raise OSError('No such file or directory %s' % stderr) |
211 return | 212 return |
212 | 213 |
213 args = ['scp', '-r' ] + self._ssh_args | 214 args = ['scp', '-r'] + self._ssh_args |
214 if self._ssh_identity: | 215 if self._ssh_identity: |
215 args.extend(['-i', self._ssh_identity]) | 216 args.extend(['-i', self._ssh_identity]) |
216 | 217 |
217 args.extend([os.path.abspath(filename), | 218 args.extend([os.path.abspath(filename), |
218 'root@%s:%s' % (self._hostname, remote_filename)]) | 219 'root@%s:%s' % (self._hostname, remote_filename)]) |
219 | 220 |
220 stdout, stderr = GetAllCmdOutput(args, quiet=True) | 221 stdout, stderr = GetAllCmdOutput(args, quiet=True) |
221 stderr = self._RemoveSSHWarnings(stderr) | 222 stderr = self._RemoveSSHWarnings(stderr) |
222 if stderr != '': | 223 if stderr != '': |
223 raise OSError('No such file or directory %s' % stderr) | 224 raise OSError('No such file or directory %s' % stderr) |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
280 """Returns (pid, cmd, ppid, state) of all processes on the device.""" | 281 """Returns (pid, cmd, ppid, state) of all processes on the device.""" |
281 stdout, stderr = self.RunCmdOnDevice([ | 282 stdout, stderr = self.RunCmdOnDevice([ |
282 '/bin/ps', '--no-headers', | 283 '/bin/ps', '--no-headers', |
283 '-A', | 284 '-A', |
284 '-o', 'pid,ppid,args:4096,state'], quiet=True) | 285 '-o', 'pid,ppid,args:4096,state'], quiet=True) |
285 assert stderr == '', stderr | 286 assert stderr == '', stderr |
286 procs = [] | 287 procs = [] |
287 for l in stdout.split('\n'): # pylint: disable=E1103 | 288 for l in stdout.split('\n'): # pylint: disable=E1103 |
288 if l == '': | 289 if l == '': |
289 continue | 290 continue |
290 m = re.match('^\s*(\d+)\s+(\d+)\s+(.+)\s+(.+)', l, re.DOTALL) | 291 m = re.match(r'^\s*(\d+)\s+(\d+)\s+(.+)\s+(.+)', l, re.DOTALL) |
291 assert m | 292 assert m |
292 procs.append((int(m.group(1)), m.group(3).rstrip(), | 293 procs.append((int(m.group(1)), m.group(3).rstrip(), |
293 int(m.group(2)), m.group(4))) | 294 int(m.group(2)), m.group(4))) |
294 logging.debug("ListProcesses(<predicate>)->[%i processes]" % len(procs)) | 295 logging.debug("ListProcesses(<predicate>)->[%i processes]" % len(procs)) |
295 return procs | 296 return procs |
296 | 297 |
297 def _GetSessionManagerPid(self, procs): | 298 def _GetSessionManagerPid(self, procs): |
298 """Returns the pid of the session_manager process, given the list of | 299 """Returns the pid of the session_manager process, given the list of |
299 processes.""" | 300 processes.""" |
300 for pid, process, _, _ in procs: | 301 for pid, process, _, _ in procs: |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
432 '/usr/local/autotest/bin/screenshot.py', | 433 '/usr/local/autotest/bin/screenshot.py', |
433 screenshot_file]) | 434 screenshot_file]) |
434 return | 435 return |
435 logging.warning('screenshot directory full.') | 436 logging.warning('screenshot directory full.') |
436 | 437 |
437 def RestartUI(self, clear_enterprise_policy): | 438 def RestartUI(self, clear_enterprise_policy): |
438 logging.info('(Re)starting the ui (logs the user out)') | 439 logging.info('(Re)starting the ui (logs the user out)') |
439 if clear_enterprise_policy: | 440 if clear_enterprise_policy: |
440 self.RunCmdOnDevice(['stop', 'ui']) | 441 self.RunCmdOnDevice(['stop', 'ui']) |
441 self.RmRF('/var/lib/whitelist/*') | 442 self.RmRF('/var/lib/whitelist/*') |
442 self.RmRF('/home/chronos/Local\ State') | 443 self.RmRF(r'/home/chronos/Local\ State') |
443 | 444 |
444 if self.IsServiceRunning('ui'): | 445 if self.IsServiceRunning('ui'): |
445 self.RunCmdOnDevice(['restart', 'ui']) | 446 self.RunCmdOnDevice(['restart', 'ui']) |
446 else: | 447 else: |
447 self.RunCmdOnDevice(['start', 'ui']) | 448 self.RunCmdOnDevice(['start', 'ui']) |
448 | 449 |
449 def CloseConnection(self): | 450 def CloseConnection(self): |
450 if not self.local: | 451 if not self.local: |
451 with open(os.devnull, 'w') as devnull: | 452 with open(os.devnull, 'w') as devnull: |
452 subprocess.call(self.FormSSHCommandLine(['-O', 'exit', self._hostname]), | 453 subprocess.call(self.FormSSHCommandLine(['-O', 'exit', self._hostname]), |
453 stdout=devnull, stderr=devnull) | 454 stdout=devnull, stderr=devnull) |
OLD | NEW |