Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(209)

Side by Side Diff: tools/chrome_remote_control/chrome_remote_control/cros_interface.py

Issue 10984018: [chrome_remote_control] Add pylint to PRESUMMIT and fix lint (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: for landing Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 # Copyright (c) 2012 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 os 6 import os
7 import re 7 import re
8 import socket
9 import subprocess 8 import subprocess
10 import sys 9 import sys
11 import time 10 import time
12 import tempfile 11 import tempfile
13 import util 12
13 from chrome_remote_control import util
14 14
15 _next_remote_port = 9224 15 _next_remote_port = 9224
16 16
17 # TODO(nduca): This whole file is built up around making individual ssh calls 17 # TODO(nduca): This whole file is built up around making individual ssh calls
18 # for each operation. It really could get away with a single ssh session built 18 # for each operation. It really could get away with a single ssh session built
19 # around pexpect, I suspect, if we wanted it to be faster. But, this was 19 # around pexpect, I suspect, if we wanted it to be faster. But, this was
20 # convenient. 20 # convenient.
21 21
22 def RunCmd(args, cwd=None): 22 def RunCmd(args, cwd=None):
23 """Opens a subprocess to execute a program and returns its return value. 23 """Opens a subprocess to execute a program and returns its return value.
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
56 stderr=subprocess.PIPE, stdin=devnull, shell=False) 56 stderr=subprocess.PIPE, stdin=devnull, shell=False)
57 stdout, stderr = p.communicate() 57 stdout, stderr = p.communicate()
58 logging.debug(' > stdout=[%s], stderr=[%s]', stdout, stderr) 58 logging.debug(' > stdout=[%s], stderr=[%s]', stdout, stderr)
59 return stdout, stderr 59 return stdout, stderr
60 60
61 class DeviceSideProcess(object): 61 class DeviceSideProcess(object):
62 def __init__(self, 62 def __init__(self,
63 cri, 63 cri,
64 device_side_args, 64 device_side_args,
65 prevent_output=True, 65 prevent_output=True,
66 extra_ssh_args=[], 66 extra_ssh_args=None,
67 leave_ssh_alive=False, 67 leave_ssh_alive=False,
68 env={}, 68 env=None,
69 login_shell=False): 69 login_shell=False):
70 70
71 # Init members first so that Close will always succeed. 71 # Init members first so that Close will always succeed.
72 self._cri = cri 72 self._cri = cri
73 self._proc = None 73 self._proc = None
74 self._devnull = open(os.devnull, 'w') 74 self._devnull = open(os.devnull, 'w')
75 75
76 if prevent_output: 76 if prevent_output:
77 out = self._devnull 77 out = self._devnull
78 else: 78 else:
79 out = sys.stderr 79 out = sys.stderr
80 80
81 cri.GetCmdOutput(['rm', '-rf', '/tmp/cros_interface_remote_device_pid']) 81 cri.GetCmdOutput(['rm', '-rf', '/tmp/cros_interface_remote_device_pid'])
82 env_str = ' '.join(['%s=%s' % (k,v) for k,v in env.items()])
83 cmd_str = ' '.join(device_side_args) 82 cmd_str = ' '.join(device_side_args)
84 if env_str: 83 if env:
84 env_str = ' '.join(['%s=%s' % (k, v) for k, v in env.items()])
85 cmd = env_str + ' ' + cmd_str 85 cmd = env_str + ' ' + cmd_str
86 else: 86 else:
87 cmd = cmd_str 87 cmd = cmd_str
88 contents = """%s&\n""" % cmd 88 contents = """%s&\n""" % cmd
89 contents += 'echo $! > /tmp/cros_interface_remote_device_pid\n' 89 contents += 'echo $! > /tmp/cros_interface_remote_device_pid\n'
90 cri.PushContents(contents, '/tmp/cros_interface_remote_device_bootstrap.sh') 90 cri.PushContents(contents, '/tmp/cros_interface_remote_device_bootstrap.sh')
91 91
92 cmdline = ['/bin/bash'] 92 cmdline = ['/bin/bash']
93 if login_shell: 93 if login_shell:
94 cmdline.append('-l') 94 cmdline.append('-l')
95 cmdline.append('/tmp/cros_interface_remote_device_bootstrap.sh') 95 cmdline.append('/tmp/cros_interface_remote_device_bootstrap.sh')
96 proc =subprocess.Popen( 96 proc = subprocess.Popen(
97 cri._FormSSHCommandLine(cmdline, 97 cri.FormSSHCommandLine(cmdline,
98 extra_ssh_args=extra_ssh_args), 98 extra_ssh_args=extra_ssh_args),
99 stdout=out, 99 stdout=out,
100 stderr=out, 100 stderr=out,
101 stdin=self._devnull, 101 stdin=self._devnull,
102 shell=False) 102 shell=False)
103 103
104 time.sleep(0.1) 104 time.sleep(0.1)
105 def TryGetResult(): 105 def TryGetResult():
106 try: 106 try:
107 self._pid = cri.GetFileContents( 107 self._pid = cri.GetFileContents(
(...skipping 15 matching lines...) Expand all
123 123
124 self._pid = int(self._pid) 124 self._pid = int(self._pid)
125 if not self.IsAlive(): 125 if not self.IsAlive():
126 raise OSError('Process did not come up or did not stay alive verry long!') 126 raise OSError('Process did not come up or did not stay alive verry long!')
127 self._cri = cri 127 self._cri = cri
128 128
129 def Close(self, try_sigint_first=False): 129 def Close(self, try_sigint_first=False):
130 if self.IsAlive(): 130 if self.IsAlive():
131 # Try to politely shutdown, first. 131 # Try to politely shutdown, first.
132 if try_sigint_first: 132 if try_sigint_first:
133 stdout, stder = self._cri._GetAllCmdOutput( 133 self._cri.GetAllCmdOutput(
134 ['kill', '-INT', str(self._pid)]) 134 ['kill', '-INT', str(self._pid)])
135 try: 135 try:
136 self.Wait(timeout=0.5) 136 self.Wait(timeout=0.5)
137 except util.TimeoutException: 137 except util.TimeoutException:
138 pass 138 pass
139 139
140 if self.IsAlive(): 140 if self.IsAlive():
141 stdout, stder = self._cri._GetAllCmdOutput( 141 self._cri.GetAllCmdOutput(
142 ['kill', '-KILL', str(self._pid)]) 142 ['kill', '-KILL', str(self._pid)])
143 try: 143 try:
144 self.Wait(timeout=1) 144 self.Wait(timeout=5)
145 except util.TimeoutException: 145 except util.TimeoutException:
146 pass 146 pass
147 147
148 if self.IsAlive(): 148 if self.IsAlive():
149 raise Exception('Could not shutdown the process.') 149 raise Exception('Could not shutdown the process.')
150 150
151 self._cri = None 151 self._cri = None
152 if self._proc: 152 if self._proc:
153 self._proc.kill() 153 self._proc.kill()
154 self._proc = None 154 self._proc = None
(...skipping 30 matching lines...) Expand all
185 return True 185 return True
186 except OSError: 186 except OSError:
187 return False 187 return False
188 188
189 class LoginException(Exception): 189 class LoginException(Exception):
190 pass 190 pass
191 191
192 class KeylessLoginRequiredException(LoginException): 192 class KeylessLoginRequiredException(LoginException):
193 pass 193 pass
194 194
195 class CrOSInterface(object): 195 class CrOSInterface(object): # pylint: disable=R0923
196 def __init__(self, hostname): 196 def __init__(self, hostname):
197 self._hostname = hostname 197 self._hostname = hostname
198 198
199 def _FormSSHCommandLine(self, args, extra_ssh_args=[]): 199 @property
200 def hostname(self):
201 return self._hostname
202
203 def FormSSHCommandLine(self, args, extra_ssh_args=None):
200 full_args = ['ssh', 204 full_args = ['ssh',
201 '-o ConnectTimeout=5', 205 '-o ConnectTimeout=5',
202 '-o ForwardAgent=no', 206 '-o ForwardAgent=no',
203 '-o ForwardX11=no', 207 '-o ForwardX11=no',
204 '-o ForwardX11Trusted=no', 208 '-o ForwardX11Trusted=no',
205 '-o KbdInteractiveAuthentication=no', 209 '-o KbdInteractiveAuthentication=no',
206 '-o StrictHostKeyChecking=yes', 210 '-o StrictHostKeyChecking=yes',
207 '-n'] 211 '-n']
208 if len(extra_ssh_args): 212 if extra_ssh_args:
209 full_args.extend(extra_ssh_args) 213 full_args.extend(extra_ssh_args)
210 full_args.append('root@%s' % self._hostname) 214 full_args.append('root@%s' % self._hostname)
211 full_args.extend(args) 215 full_args.extend(args)
212 return full_args 216 return full_args
213 217
214 def _GetAllCmdOutput(self, args, cwd=None): 218 def GetAllCmdOutput(self, args, cwd=None):
215 return GetAllCmdOutput(self._FormSSHCommandLine(args), cwd) 219 return GetAllCmdOutput(self.FormSSHCommandLine(args), cwd)
216 220
217 def TryLogin(self): 221 def TryLogin(self):
218 stdout, stderr = self._GetAllCmdOutput(['echo', '$USER']) 222 stdout, stderr = self.GetAllCmdOutput(['echo', '$USER'])
219 223
220 if stderr != '': 224 if stderr != '':
221 if 'Host key verification failed' in stderr: 225 if 'Host key verification failed' in stderr:
222 raise LoginException(('%s host key verification failed. ' + 226 raise LoginException(('%s host key verification failed. ' +
223 'SSH to it manually to fix connectivity.') % 227 'SSH to it manually to fix connectivity.') %
224 self._hostname) 228 self._hostname)
225 if 'Operation timed out' in stderr: 229 if 'Operation timed out' in stderr:
226 raise LoginException('Timed out while logging into %s' % self._hostname) 230 raise LoginException('Timed out while logging into %s' % self._hostname)
227 raise LoginException('While logging into %s, got %s' % ( 231 raise LoginException('While logging into %s, got %s' % (
228 self._hostname,stderr.strip())) 232 self._hostname, stderr))
229 if stdout != 'root\n': 233 if stdout != 'root\n':
230 raise LoginException( 234 raise LoginException(
231 'Logged into %s, expected $USER=root, but got %s.' % ( 235 'Logged into %s, expected $USER=root, but got %s.' % (
232 self._hostname, stdout)) 236 self._hostname, stdout))
233 237
234 def FileExistsOnDevice(self, file_name): 238 def FileExistsOnDevice(self, file_name):
235 stdout, stderr = self._GetAllCmdOutput([ 239 stdout, stderr = self.GetAllCmdOutput([
236 'if', 'test', '-a', file_name, ';', 240 'if', 'test', '-a', file_name, ';',
237 'then', 'echo', '1', ';', 241 'then', 'echo', '1', ';',
238 'fi' 242 'fi'
239 ]) 243 ])
240 if stderr != '': 244 if stderr != '':
241 if "Connection timed out" in stderr: 245 if "Connection timed out" in stderr:
242 raise OSError('Machine wasn\'t responding to ssh: %s' % 246 raise OSError('Machine wasn\'t responding to ssh: %s' %
243 stderr) 247 stderr)
244 raise OSError('Unepected error: %s' % stderr) 248 raise OSError('Unepected error: %s' % stderr)
245 return stdout == '1\n' 249 return stdout == '1\n'
(...skipping 23 matching lines...) Expand all
269 'root@%s:%s' % (self._hostname, filename), 273 'root@%s:%s' % (self._hostname, filename),
270 os.path.abspath(f.name)]) 274 os.path.abspath(f.name)])
271 if stderr != '': 275 if stderr != '':
272 assert 'No such file or directory' in stderr 276 assert 'No such file or directory' in stderr
273 raise OSError 277 raise OSError
274 278
275 with open(f.name, 'r') as f2: 279 with open(f.name, 'r') as f2:
276 return f2.read() 280 return f2.read()
277 281
278 def ListProcesses(self): 282 def ListProcesses(self):
279 stdout, stderr = self._GetAllCmdOutput([ 283 stdout, stderr = self.GetAllCmdOutput([
280 '/bin/ps', '--no-headers', 284 '/bin/ps', '--no-headers',
281 '-A', 285 '-A',
282 '-o', 'pid,args']) 286 '-o', 'pid,args'])
283 assert stderr == '' 287 assert stderr == ''
284 procs = [] 288 procs = []
285 for l in stdout.split('\n'): 289 for l in stdout.split('\n'): # pylint: disable=E1103
286 if l == '': 290 if l == '':
287 continue 291 continue
288 m = re.match('^\s*(\d+)\s+(.+)', l, re.DOTALL) 292 m = re.match('^\s*(\d+)\s+(.+)', l, re.DOTALL)
289 assert m 293 assert m
290 procs.append(m.groups()) 294 procs.append(m.groups())
291 return procs 295 return procs
292 296
293 def KillAllMatching(self, predicate): 297 def KillAllMatching(self, predicate):
294 kills = ['kill', '-KILL'] 298 kills = ['kill', '-KILL']
295 for p in self.ListProcesses(): 299 for p in self.ListProcesses():
296 if predicate(p[1]): 300 if predicate(p[1]):
297 logging.info('Killing %s', repr(p)) 301 logging.info('Killing %s', repr(p))
298 kills.append(p[0]) 302 kills.append(p[0])
299 if len(kills) > 2: 303 if len(kills) > 2:
300 self.GetCmdOutput(kills) 304 self.GetCmdOutput(kills)
301 return len(kills) - 2 305 return len(kills) - 2
302 306
303 def IsServiceRunning(self, service_name): 307 def IsServiceRunning(self, service_name):
304 stdout, stderr = self._GetAllCmdOutput([ 308 stdout, stderr = self.GetAllCmdOutput([
305 'status', service_name]) 309 'status', service_name])
306 assert stderr == '' 310 assert stderr == ''
307 return 'running, process' in stdout 311 return 'running, process' in stdout
308 312
309 def GetCmdOutput(self, args): 313 def GetCmdOutput(self, args):
310 stdout, stderr = self._GetAllCmdOutput(args) 314 stdout, stderr = self.GetAllCmdOutput(args)
311 assert stderr == '' 315 assert stderr == ''
312 return stdout 316 return stdout
313 317
314 def GetRemotePort(self): 318 def GetRemotePort(self):
315 global _next_remote_port 319 global _next_remote_port
316 port = _next_remote_port 320 port = _next_remote_port
317 _next_remote_port += 1 321 _next_remote_port += 1
318 return port 322 return port
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698