| 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 | 
|---|