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

Side by Side Diff: client/tests/kvm/rss_file_transfer.py

Issue 6246035: Merge remote branch 'cros/upstream' into master (Closed) Base URL: ssh://git@gitrw.chromium.org:9222/autotest.git@master
Patch Set: patch Created 9 years, 10 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 #!/usr/bin/python 1 #!/usr/bin/python
2 """ 2 """
3 Client for file transfer services offered by RSS (Remote Shell Server). 3 Client for file transfer services offered by RSS (Remote Shell Server).
4 4
5 @author: Michael Goldish (mgoldish@redhat.com) 5 @author: Michael Goldish (mgoldish@redhat.com)
6 @copyright: 2008-2010 Red Hat Inc. 6 @copyright: 2008-2010 Red Hat Inc.
7 """ 7 """
8 8
9 import socket, struct, time, sys, os, glob 9 import socket, struct, time, sys, os, glob
10 10
11 # Globals 11 # Globals
12 CHUNKSIZE = 65536 12 CHUNKSIZE = 65536
13 13
14 # Protocol message constants 14 # Protocol message constants
15 RSS_MAGIC = 0x525353 15 RSS_MAGIC = 0x525353
16 RSS_OK = 1 16 RSS_OK = 1
17 RSS_ERROR = 2 17 RSS_ERROR = 2
18 RSS_UPLOAD = 3 18 RSS_UPLOAD = 3
19 RSS_DOWNLOAD = 4 19 RSS_DOWNLOAD = 4
20 RSS_SET_PATH = 5 20 RSS_SET_PATH = 5
21 RSS_CREATE_FILE = 6 21 RSS_CREATE_FILE = 6
22 RSS_CREATE_DIR = 7 22 RSS_CREATE_DIR = 7
23 RSS_LEAVE_DIR = 8 23 RSS_LEAVE_DIR = 8
24 RSS_DONE = 9 24 RSS_DONE = 9
25 25
26 # See rss.cpp for protocol details. 26 # See rss.cpp for protocol details.
27 27
28 28
29 class FileTransferError(Exception): 29 class FileTransferError(Exception):
30 pass 30 def __init__(self, msg, e=None, filename=None):
31 Exception.__init__(self, msg, e, filename)
32 self.msg = msg
33 self.e = e
34 self.filename = filename
35
36 def __str__(self):
37 s = self.msg
38 if self.e and self.filename:
39 s += " (error: %s, filename: %s)" % (self.e, self.filename)
40 elif self.e:
41 s += " (%s)" % self.e
42 elif self.filename:
43 s += " (filename: %s)" % self.filename
44 return s
31 45
32 46
33 class FileTransferConnectError(FileTransferError): 47 class FileTransferConnectError(FileTransferError):
34 pass 48 pass
35 49
36 50
37 class FileTransferTimeoutError(FileTransferError): 51 class FileTransferTimeoutError(FileTransferError):
38 pass 52 pass
39 53
40 54
41 class FileTransferProtocolError(FileTransferError): 55 class FileTransferProtocolError(FileTransferError):
42 pass 56 pass
43 57
44 58
45 class FileTransferSendError(FileTransferError): 59 class FileTransferSocketError(FileTransferError):
46 pass 60 pass
47 61
48 62
49 class FileTransferServerError(FileTransferError): 63 class FileTransferServerError(FileTransferError):
50 pass 64 def __init__(self, errmsg):
65 FileTransferError.__init__(self, None, errmsg)
66
67 def __str__(self):
68 s = "Server said: %r" % self.e
69 if self.filename:
70 s += " (filename: %s)" % self.filename
71 return s
51 72
52 73
53 class FileTransferNotFoundError(FileTransferError): 74 class FileTransferNotFoundError(FileTransferError):
54 pass 75 pass
55 76
56 77
57 class FileTransferClient(object): 78 class FileTransferClient(object):
58 """ 79 """
59 Connect to a RSS (remote shell server) and transfer files. 80 Connect to a RSS (remote shell server) and transfer files.
60 """ 81 """
61 82
62 def __init__(self, address, port, timeout=10): 83 def __init__(self, address, port, log_func=None, timeout=20):
63 """ 84 """
64 Connect to a server. 85 Connect to a server.
65 86
66 @param address: The server's address 87 @param address: The server's address
67 @param port: The server's port 88 @param port: The server's port
89 @param log_func: If provided, transfer stats will be passed to this
90 function during the transfer
68 @param timeout: Time duration to wait for connection to succeed 91 @param timeout: Time duration to wait for connection to succeed
69 @raise FileTransferConnectError: Raised if the connection fails 92 @raise FileTransferConnectError: Raised if the connection fails
70 @raise FileTransferProtocolError: Raised if an incorrect magic number
71 is received
72 """ 93 """
73 self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 94 self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
74 self._socket.settimeout(timeout) 95 self._socket.settimeout(timeout)
75 try: 96 try:
76 self._socket.connect((address, port)) 97 self._socket.connect((address, port))
77 except socket.error: 98 except socket.error, e:
78 raise FileTransferConnectError("Could not connect to server") 99 raise FileTransferConnectError("Cannot connect to server at "
100 "%s:%s" % (address, port), e)
79 try: 101 try:
80 if self._receive_msg(timeout) != RSS_MAGIC: 102 if self._receive_msg(timeout) != RSS_MAGIC:
81 raise FileTransferConnectError("Received wrong magic number") 103 raise FileTransferConnectError("Received wrong magic number")
82 except FileTransferTimeoutError: 104 except FileTransferTimeoutError:
83 raise FileTransferConnectError("Timeout expired while waiting to " 105 raise FileTransferConnectError("Timeout expired while waiting to "
84 "receive magic number") 106 "receive magic number")
85 self._send(struct.pack("=i", CHUNKSIZE)) 107 self._send(struct.pack("=i", CHUNKSIZE))
108 self._log_func = log_func
109 self._last_time = time.time()
110 self._last_transferred = 0
111 self.transferred = 0
86 112
87 113
88 def __del__(self): 114 def __del__(self):
89 self.close() 115 self.close()
90 116
91 117
92 def close(self): 118 def close(self):
93 """ 119 """
94 Close the connection. 120 Close the connection.
95 """ 121 """
96 self._socket.close() 122 self._socket.close()
97 123
98 124
99 def _send(self, str): 125 def _send(self, str, timeout=60):
100 try: 126 try:
127 if timeout <= 0:
128 raise socket.timeout
129 self._socket.settimeout(timeout)
101 self._socket.sendall(str) 130 self._socket.sendall(str)
102 except socket.error: 131 except socket.timeout:
103 raise FileTransferSendError("Could not send data to server") 132 raise FileTransferTimeoutError("Timeout expired while sending "
133 "data to server")
134 except socket.error, e:
135 raise FileTransferSocketError("Could not send data to server", e)
104 136
105 137
106 def _receive(self, size, timeout=10): 138 def _receive(self, size, timeout=60):
107 strs = [] 139 strs = []
108 end_time = time.time() + timeout 140 end_time = time.time() + timeout
109 while size > 0: 141 try:
110 try: 142 while size > 0:
111 self._socket.settimeout(max(0.0001, end_time - time.time())) 143 timeout = end_time - time.time()
144 if timeout <= 0:
145 raise socket.timeout
146 self._socket.settimeout(timeout)
112 data = self._socket.recv(size) 147 data = self._socket.recv(size)
113 except socket.timeout: 148 if not data:
114 raise FileTransferTimeoutError("Timeout expired while " 149 raise FileTransferProtocolError("Connection closed "
115 "receiving data from server") 150 "unexpectedly while "
116 except socket.error: 151 "receiving data from "
117 raise FileTransferProtocolError("Error receiving data from " 152 "server")
118 "server") 153 strs.append(data)
119 if not data: 154 size -= len(data)
120 raise FileTransferProtocolError("Connection closed " 155 except socket.timeout:
121 "unexpectedly") 156 raise FileTransferTimeoutError("Timeout expired while receiving "
122 strs.append(data) 157 "data from server")
123 size -= len(data) 158 except socket.error, e:
159 raise FileTransferSocketError("Error receiving data from server",
160 e)
124 return "".join(strs) 161 return "".join(strs)
125 162
126 163
127 def _send_packet(self, str): 164 def _report_stats(self, str):
128 self._send(struct.pack("=I", len(str))) 165 if self._log_func:
129 self._send(str) 166 dt = time.time() - self._last_time
167 if dt >= 1:
168 transferred = self.transferred / 1048576.
169 speed = (self.transferred - self._last_transferred) / dt
170 speed /= 1048576.
171 self._log_func("%s %.3f MB (%.3f MB/sec)" %
172 (str, transferred, speed))
173 self._last_time = time.time()
174 self._last_transferred = self.transferred
130 175
131 176
132 def _receive_packet(self, timeout=10): 177 def _send_packet(self, str, timeout=60):
133 size = struct.unpack("=I", self._receive(4))[0] 178 self._send(struct.pack("=I", len(str)))
134 return self._receive(size, timeout) 179 self._send(str, timeout)
180 self.transferred += len(str) + 4
181 self._report_stats("Sent")
135 182
136 183
137 def _send_file_chunks(self, filename, timeout=30): 184 def _receive_packet(self, timeout=60):
185 size = struct.unpack("=I", self._receive(4))[0]
186 str = self._receive(size, timeout)
187 self.transferred += len(str) + 4
188 self._report_stats("Received")
189 return str
190
191
192 def _send_file_chunks(self, filename, timeout=60):
193 if self._log_func:
194 self._log_func("Sending file %s" % filename)
138 f = open(filename, "rb") 195 f = open(filename, "rb")
139 try: 196 try:
140 end_time = time.time() + timeout 197 try:
141 while time.time() < end_time: 198 end_time = time.time() + timeout
142 data = f.read(CHUNKSIZE) 199 while True:
143 self._send_packet(data) 200 data = f.read(CHUNKSIZE)
144 if len(data) < CHUNKSIZE: 201 self._send_packet(data, end_time - time.time())
145 break 202 if len(data) < CHUNKSIZE:
146 else: 203 break
147 raise FileTransferTimeoutError("Timeout expired while sending " 204 except FileTransferError, e:
148 "file %s" % filename) 205 e.filename = filename
206 raise
149 finally: 207 finally:
150 f.close() 208 f.close()
151 209
152 210
153 def _receive_file_chunks(self, filename, timeout=30): 211 def _receive_file_chunks(self, filename, timeout=60):
212 if self._log_func:
213 self._log_func("Receiving file %s" % filename)
154 f = open(filename, "wb") 214 f = open(filename, "wb")
155 try: 215 try:
156 end_time = time.time() + timeout 216 try:
157 while True: 217 end_time = time.time() + timeout
158 try: 218 while True:
159 data = self._receive_packet(end_time - time.time()) 219 data = self._receive_packet(end_time - time.time())
160 except FileTransferTimeoutError: 220 f.write(data)
161 raise FileTransferTimeoutError("Timeout expired while " 221 if len(data) < CHUNKSIZE:
162 "receiving file %s" % 222 break
163 filename) 223 except FileTransferError, e:
164 except FileTransferProtocolError: 224 e.filename = filename
165 raise FileTransferProtocolError("Error receiving file %s" % 225 raise
166 filename)
167 f.write(data)
168 if len(data) < CHUNKSIZE:
169 break
170 finally: 226 finally:
171 f.close() 227 f.close()
172 228
173 229
174 def _send_msg(self, msg, timeout=10): 230 def _send_msg(self, msg, timeout=60):
175 self._send(struct.pack("=I", msg)) 231 self._send(struct.pack("=I", msg))
176 232
177 233
178 def _receive_msg(self, timeout=10): 234 def _receive_msg(self, timeout=60):
179 s = self._receive(4, timeout) 235 s = self._receive(4, timeout)
180 return struct.unpack("=I", s)[0] 236 return struct.unpack("=I", s)[0]
181 237
182 238
183 def _handle_transfer_error(self): 239 def _handle_transfer_error(self):
184 # Save original exception 240 # Save original exception
185 e = sys.exc_info() 241 e = sys.exc_info()
186 try: 242 try:
187 # See if we can get an error message 243 # See if we can get an error message
188 msg = self._receive_msg() 244 msg = self._receive_msg()
189 except FileTransferError: 245 except FileTransferError:
190 # No error message -- re-raise original exception 246 # No error message -- re-raise original exception
191 raise e[0], e[1], e[2] 247 raise e[0], e[1], e[2]
192 if msg == RSS_ERROR: 248 if msg == RSS_ERROR:
193 errmsg = self._receive_packet() 249 errmsg = self._receive_packet()
194 raise FileTransferServerError("Server said: %s" % errmsg) 250 raise FileTransferServerError(errmsg)
195 raise e[0], e[1], e[2] 251 raise e[0], e[1], e[2]
196 252
197 253
198 class FileUploadClient(FileTransferClient): 254 class FileUploadClient(FileTransferClient):
199 """ 255 """
200 Connect to a RSS (remote shell server) and upload files or directory trees. 256 Connect to a RSS (remote shell server) and upload files or directory trees.
201 """ 257 """
202 258
203 def __init__(self, address, port, timeout=10): 259 def __init__(self, address, port, log_func=None, timeout=20):
204 """ 260 """
205 Connect to a server. 261 Connect to a server.
206 262
207 @param address: The server's address 263 @param address: The server's address
208 @param port: The server's port 264 @param port: The server's port
265 @param log_func: If provided, transfer stats will be passed to this
266 function during the transfer
209 @param timeout: Time duration to wait for connection to succeed 267 @param timeout: Time duration to wait for connection to succeed
210 @raise FileTransferConnectError: Raised if the connection fails 268 @raise FileTransferConnectError: Raised if the connection fails
211 @raise FileTransferProtocolError: Raised if an incorrect magic number 269 @raise FileTransferProtocolError: Raised if an incorrect magic number
212 is received 270 is received
213 @raise FileTransferSendError: Raised if the RSS_UPLOAD message cannot 271 @raise FileTransferSocketError: Raised if the RSS_UPLOAD message cannot
214 be sent to the server 272 be sent to the server
215 """ 273 """
216 super(FileUploadClient, self).__init__(address, port, timeout) 274 super(FileUploadClient, self).__init__(address, port, log_func, timeout)
217 self._send_msg(RSS_UPLOAD) 275 self._send_msg(RSS_UPLOAD)
218 276
219 277
220 def _upload_file(self, path, end_time): 278 def _upload_file(self, path, end_time):
221 if os.path.isfile(path): 279 if os.path.isfile(path):
222 self._send_msg(RSS_CREATE_FILE) 280 self._send_msg(RSS_CREATE_FILE)
223 self._send_packet(os.path.basename(path)) 281 self._send_packet(os.path.basename(path))
224 self._send_file_chunks(path, max(0, end_time - time.time())) 282 self._send_file_chunks(path, end_time - time.time())
225 elif os.path.isdir(path): 283 elif os.path.isdir(path):
226 self._send_msg(RSS_CREATE_DIR) 284 self._send_msg(RSS_CREATE_DIR)
227 self._send_packet(os.path.basename(path)) 285 self._send_packet(os.path.basename(path))
228 for filename in os.listdir(path): 286 for filename in os.listdir(path):
229 self._upload_file(os.path.join(path, filename), end_time) 287 self._upload_file(os.path.join(path, filename), end_time)
230 self._send_msg(RSS_LEAVE_DIR) 288 self._send_msg(RSS_LEAVE_DIR)
231 289
232 290
233 def upload(self, src_pattern, dst_path, timeout=600): 291 def upload(self, src_pattern, dst_path, timeout=600):
234 """ 292 """
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
270 except FileTransferError: 328 except FileTransferError:
271 self._handle_transfer_error() 329 self._handle_transfer_error()
272 else: 330 else:
273 # If nothing was transferred, raise an exception 331 # If nothing was transferred, raise an exception
274 if not matches: 332 if not matches:
275 raise FileTransferNotFoundError("Pattern %s does not " 333 raise FileTransferNotFoundError("Pattern %s does not "
276 "match any files or " 334 "match any files or "
277 "directories" % 335 "directories" %
278 src_pattern) 336 src_pattern)
279 # Look for RSS_OK or RSS_ERROR 337 # Look for RSS_OK or RSS_ERROR
280 msg = self._receive_msg(max(0, end_time - time.time())) 338 msg = self._receive_msg(end_time - time.time())
281 if msg == RSS_OK: 339 if msg == RSS_OK:
282 return 340 return
283 elif msg == RSS_ERROR: 341 elif msg == RSS_ERROR:
284 errmsg = self._receive_packet() 342 errmsg = self._receive_packet()
285 raise FileTransferServerError("Server said: %s" % errmsg) 343 raise FileTransferServerError(errmsg)
286 else: 344 else:
287 # Neither RSS_OK nor RSS_ERROR found 345 # Neither RSS_OK nor RSS_ERROR found
288 raise FileTransferProtocolError("Received unexpected msg") 346 raise FileTransferProtocolError("Received unexpected msg")
289 except: 347 except:
290 # In any case, if the transfer failed, close the connection 348 # In any case, if the transfer failed, close the connection
291 self.close() 349 self.close()
292 raise 350 raise
293 351
294 352
295 class FileDownloadClient(FileTransferClient): 353 class FileDownloadClient(FileTransferClient):
296 """ 354 """
297 Connect to a RSS (remote shell server) and download files or directory trees . 355 Connect to a RSS (remote shell server) and download files or directory trees .
298 """ 356 """
299 357
300 def __init__(self, address, port, timeout=10): 358 def __init__(self, address, port, log_func=None, timeout=20):
301 """ 359 """
302 Connect to a server. 360 Connect to a server.
303 361
304 @param address: The server's address 362 @param address: The server's address
305 @param port: The server's port 363 @param port: The server's port
364 @param log_func: If provided, transfer stats will be passed to this
365 function during the transfer
306 @param timeout: Time duration to wait for connection to succeed 366 @param timeout: Time duration to wait for connection to succeed
307 @raise FileTransferConnectError: Raised if the connection fails 367 @raise FileTransferConnectError: Raised if the connection fails
308 @raise FileTransferProtocolError: Raised if an incorrect magic number 368 @raise FileTransferProtocolError: Raised if an incorrect magic number
309 is received 369 is received
310 @raise FileTransferSendError: Raised if the RSS_UPLOAD message cannot 370 @raise FileTransferSendError: Raised if the RSS_UPLOAD message cannot
311 be sent to the server 371 be sent to the server
312 """ 372 """
313 super(FileDownloadClient, self).__init__(address, port, timeout) 373 super(FileDownloadClient, self).__init__(address, port, log_func, timeou t)
314 self._send_msg(RSS_DOWNLOAD) 374 self._send_msg(RSS_DOWNLOAD)
315 375
316 376
317 def download(self, src_pattern, dst_path, timeout=600): 377 def download(self, src_pattern, dst_path, timeout=600):
318 """ 378 """
319 Receive files or directory trees from the server. 379 Receive files or directory trees from the server.
320 The semantics of src_pattern and dst_path are similar to those of scp. 380 The semantics of src_pattern and dst_path are similar to those of scp.
321 For example, the following are OK: 381 For example, the following are OK:
322 src_pattern='C:\\foo.txt', dst_path='/tmp' 382 src_pattern='C:\\foo.txt', dst_path='/tmp'
323 (downloads a single file) 383 (downloads a single file)
(...skipping 27 matching lines...) Expand all
351 self._send_packet(src_pattern) 411 self._send_packet(src_pattern)
352 except FileTransferError: 412 except FileTransferError:
353 self._handle_transfer_error() 413 self._handle_transfer_error()
354 while True: 414 while True:
355 msg = self._receive_msg() 415 msg = self._receive_msg()
356 if msg == RSS_CREATE_FILE: 416 if msg == RSS_CREATE_FILE:
357 # Receive filename and file contents 417 # Receive filename and file contents
358 filename = self._receive_packet() 418 filename = self._receive_packet()
359 if os.path.isdir(dst_path): 419 if os.path.isdir(dst_path):
360 dst_path = os.path.join(dst_path, filename) 420 dst_path = os.path.join(dst_path, filename)
361 self._receive_file_chunks( 421 self._receive_file_chunks(dst_path, end_time - time.time())
362 dst_path, max(0, end_time - time.time()))
363 dst_path = os.path.dirname(dst_path) 422 dst_path = os.path.dirname(dst_path)
364 file_count += 1 423 file_count += 1
365 elif msg == RSS_CREATE_DIR: 424 elif msg == RSS_CREATE_DIR:
366 # Receive dirname and create the directory 425 # Receive dirname and create the directory
367 dirname = self._receive_packet() 426 dirname = self._receive_packet()
368 if os.path.isdir(dst_path): 427 if os.path.isdir(dst_path):
369 dst_path = os.path.join(dst_path, dirname) 428 dst_path = os.path.join(dst_path, dirname)
370 if not os.path.isdir(dst_path): 429 if not os.path.isdir(dst_path):
371 os.mkdir(dst_path) 430 os.mkdir(dst_path)
372 dir_count += 1 431 dir_count += 1
373 elif msg == RSS_LEAVE_DIR: 432 elif msg == RSS_LEAVE_DIR:
374 # Return to parent dir 433 # Return to parent dir
375 dst_path = os.path.dirname(dst_path) 434 dst_path = os.path.dirname(dst_path)
376 elif msg == RSS_DONE: 435 elif msg == RSS_DONE:
377 # Transfer complete 436 # Transfer complete
378 if not file_count and not dir_count: 437 if not file_count and not dir_count:
379 raise FileTransferNotFoundError("Pattern %s does not " 438 raise FileTransferNotFoundError("Pattern %s does not "
380 "match any files or " 439 "match any files or "
381 "directories that " 440 "directories that "
382 "could be downloaded" % 441 "could be downloaded" %
383 src_pattern) 442 src_pattern)
384 break 443 break
385 elif msg == RSS_ERROR: 444 elif msg == RSS_ERROR:
386 # Receive error message and abort 445 # Receive error message and abort
387 errmsg = self._receive_packet() 446 errmsg = self._receive_packet()
388 raise FileTransferServerError("Server said: %s" % errmsg) 447 raise FileTransferServerError(errmsg)
389 else: 448 else:
390 # Unexpected msg 449 # Unexpected msg
391 raise FileTransferProtocolError("Received unexpected msg") 450 raise FileTransferProtocolError("Received unexpected msg")
392 except: 451 except:
393 # In any case, if the transfer failed, close the connection 452 # In any case, if the transfer failed, close the connection
394 self.close() 453 self.close()
395 raise 454 raise
396 455
397 456
398 def upload(address, port, src_pattern, dst_path, timeout=60, 457 def upload(address, port, src_pattern, dst_path, log_func=None, timeout=60,
399 connect_timeout=10): 458 connect_timeout=20):
400 """ 459 """
401 Connect to server and upload files. 460 Connect to server and upload files.
402 461
403 @see: FileUploadClient 462 @see: FileUploadClient
404 """ 463 """
405 client = FileUploadClient(address, port, connect_timeout) 464 client = FileUploadClient(address, port, log_func, connect_timeout)
406 client.upload(src_pattern, dst_path, timeout) 465 client.upload(src_pattern, dst_path, timeout)
407 client.close() 466 client.close()
408 467
409 468
410 def download(address, port, src_pattern, dst_path, timeout=60, 469 def download(address, port, src_pattern, dst_path, log_func=None, timeout=60,
411 connect_timeout=10): 470 connect_timeout=20):
412 """ 471 """
413 Connect to server and upload files. 472 Connect to server and upload files.
414 473
415 @see: FileDownloadClient 474 @see: FileDownloadClient
416 """ 475 """
417 client = FileDownloadClient(address, port, connect_timeout) 476 client = FileDownloadClient(address, port, log_func, connect_timeout)
418 client.download(src_pattern, dst_path, timeout) 477 client.download(src_pattern, dst_path, timeout)
419 client.close() 478 client.close()
420 479
421 480
422 def main(): 481 def main():
423 import optparse 482 import optparse
424 483
425 usage = "usage: %prog [options] address port src_pattern dst_path" 484 usage = "usage: %prog [options] address port src_pattern dst_path"
426 parser = optparse.OptionParser(usage=usage) 485 parser = optparse.OptionParser(usage=usage)
427 parser.add_option("-d", "--download", 486 parser.add_option("-d", "--download",
428 action="store_true", dest="download", 487 action="store_true", dest="download",
429 help="download files from server") 488 help="download files from server")
430 parser.add_option("-u", "--upload", 489 parser.add_option("-u", "--upload",
431 action="store_true", dest="upload", 490 action="store_true", dest="upload",
432 help="upload files to server") 491 help="upload files to server")
492 parser.add_option("-v", "--verbose",
493 action="store_true", dest="verbose",
494 help="be verbose")
433 parser.add_option("-t", "--timeout", 495 parser.add_option("-t", "--timeout",
434 type="int", dest="timeout", default=3600, 496 type="int", dest="timeout", default=3600,
435 help="transfer timeout") 497 help="transfer timeout")
436 options, args = parser.parse_args() 498 options, args = parser.parse_args()
437 if options.download == options.upload: 499 if options.download == options.upload:
438 parser.error("you must specify either -d or -u") 500 parser.error("you must specify either -d or -u")
439 if len(args) != 4: 501 if len(args) != 4:
440 parser.error("incorrect number of arguments") 502 parser.error("incorrect number of arguments")
441 address, port, src_pattern, dst_path = args 503 address, port, src_pattern, dst_path = args
442 port = int(port) 504 port = int(port)
443 505
506 logger = None
507 if options.verbose:
508 def p(s):
509 print s
510 logger = p
511
444 if options.download: 512 if options.download:
445 download(address, port, src_pattern, dst_path, options.timeout) 513 download(address, port, src_pattern, dst_path, logger, options.timeout)
446 elif options.upload: 514 elif options.upload:
447 upload(address, port, src_pattern, dst_path, options.timeout) 515 upload(address, port, src_pattern, dst_path, logger, options.timeout)
448 516
449 517
450 if __name__ == "__main__": 518 if __name__ == "__main__":
451 main() 519 main()
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698