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

Unified 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, 11 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 side-by-side diff with in-line comments
Download patch
Index: client/tests/kvm/rss_file_transfer.py
diff --git a/client/tests/kvm/rss_file_transfer.py b/client/tests/kvm/rss_file_transfer.py
index 3de8259cca17d8c29870ce754d96a451c1e36123..4d00d174e48753a3d7a55e1b17cb7a6d795bbac2 100755
--- a/client/tests/kvm/rss_file_transfer.py
+++ b/client/tests/kvm/rss_file_transfer.py
@@ -27,7 +27,21 @@ RSS_DONE = 9
class FileTransferError(Exception):
- pass
+ def __init__(self, msg, e=None, filename=None):
+ Exception.__init__(self, msg, e, filename)
+ self.msg = msg
+ self.e = e
+ self.filename = filename
+
+ def __str__(self):
+ s = self.msg
+ if self.e and self.filename:
+ s += " (error: %s, filename: %s)" % (self.e, self.filename)
+ elif self.e:
+ s += " (%s)" % self.e
+ elif self.filename:
+ s += " (filename: %s)" % self.filename
+ return s
class FileTransferConnectError(FileTransferError):
@@ -42,12 +56,19 @@ class FileTransferProtocolError(FileTransferError):
pass
-class FileTransferSendError(FileTransferError):
+class FileTransferSocketError(FileTransferError):
pass
class FileTransferServerError(FileTransferError):
- pass
+ def __init__(self, errmsg):
+ FileTransferError.__init__(self, None, errmsg)
+
+ def __str__(self):
+ s = "Server said: %r" % self.e
+ if self.filename:
+ s += " (filename: %s)" % self.filename
+ return s
class FileTransferNotFoundError(FileTransferError):
@@ -59,23 +80,24 @@ class FileTransferClient(object):
Connect to a RSS (remote shell server) and transfer files.
"""
- def __init__(self, address, port, timeout=10):
+ def __init__(self, address, port, log_func=None, timeout=20):
"""
Connect to a server.
@param address: The server's address
@param port: The server's port
+ @param log_func: If provided, transfer stats will be passed to this
+ function during the transfer
@param timeout: Time duration to wait for connection to succeed
@raise FileTransferConnectError: Raised if the connection fails
- @raise FileTransferProtocolError: Raised if an incorrect magic number
- is received
"""
self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self._socket.settimeout(timeout)
try:
self._socket.connect((address, port))
- except socket.error:
- raise FileTransferConnectError("Could not connect to server")
+ except socket.error, e:
+ raise FileTransferConnectError("Cannot connect to server at "
+ "%s:%s" % (address, port), e)
try:
if self._receive_msg(timeout) != RSS_MAGIC:
raise FileTransferConnectError("Received wrong magic number")
@@ -83,6 +105,10 @@ class FileTransferClient(object):
raise FileTransferConnectError("Timeout expired while waiting to "
"receive magic number")
self._send(struct.pack("=i", CHUNKSIZE))
+ self._log_func = log_func
+ self._last_time = time.time()
+ self._last_transferred = 0
+ self.transferred = 0
def __del__(self):
@@ -96,86 +122,116 @@ class FileTransferClient(object):
self._socket.close()
- def _send(self, str):
+ def _send(self, str, timeout=60):
try:
+ if timeout <= 0:
+ raise socket.timeout
+ self._socket.settimeout(timeout)
self._socket.sendall(str)
- except socket.error:
- raise FileTransferSendError("Could not send data to server")
+ except socket.timeout:
+ raise FileTransferTimeoutError("Timeout expired while sending "
+ "data to server")
+ except socket.error, e:
+ raise FileTransferSocketError("Could not send data to server", e)
- def _receive(self, size, timeout=10):
+ def _receive(self, size, timeout=60):
strs = []
end_time = time.time() + timeout
- while size > 0:
- try:
- self._socket.settimeout(max(0.0001, end_time - time.time()))
+ try:
+ while size > 0:
+ timeout = end_time - time.time()
+ if timeout <= 0:
+ raise socket.timeout
+ self._socket.settimeout(timeout)
data = self._socket.recv(size)
- except socket.timeout:
- raise FileTransferTimeoutError("Timeout expired while "
- "receiving data from server")
- except socket.error:
- raise FileTransferProtocolError("Error receiving data from "
- "server")
- if not data:
- raise FileTransferProtocolError("Connection closed "
- "unexpectedly")
- strs.append(data)
- size -= len(data)
+ if not data:
+ raise FileTransferProtocolError("Connection closed "
+ "unexpectedly while "
+ "receiving data from "
+ "server")
+ strs.append(data)
+ size -= len(data)
+ except socket.timeout:
+ raise FileTransferTimeoutError("Timeout expired while receiving "
+ "data from server")
+ except socket.error, e:
+ raise FileTransferSocketError("Error receiving data from server",
+ e)
return "".join(strs)
- def _send_packet(self, str):
+ def _report_stats(self, str):
+ if self._log_func:
+ dt = time.time() - self._last_time
+ if dt >= 1:
+ transferred = self.transferred / 1048576.
+ speed = (self.transferred - self._last_transferred) / dt
+ speed /= 1048576.
+ self._log_func("%s %.3f MB (%.3f MB/sec)" %
+ (str, transferred, speed))
+ self._last_time = time.time()
+ self._last_transferred = self.transferred
+
+
+ def _send_packet(self, str, timeout=60):
self._send(struct.pack("=I", len(str)))
- self._send(str)
+ self._send(str, timeout)
+ self.transferred += len(str) + 4
+ self._report_stats("Sent")
- def _receive_packet(self, timeout=10):
+ def _receive_packet(self, timeout=60):
size = struct.unpack("=I", self._receive(4))[0]
- return self._receive(size, timeout)
+ str = self._receive(size, timeout)
+ self.transferred += len(str) + 4
+ self._report_stats("Received")
+ return str
- def _send_file_chunks(self, filename, timeout=30):
+ def _send_file_chunks(self, filename, timeout=60):
+ if self._log_func:
+ self._log_func("Sending file %s" % filename)
f = open(filename, "rb")
try:
- end_time = time.time() + timeout
- while time.time() < end_time:
- data = f.read(CHUNKSIZE)
- self._send_packet(data)
- if len(data) < CHUNKSIZE:
- break
- else:
- raise FileTransferTimeoutError("Timeout expired while sending "
- "file %s" % filename)
+ try:
+ end_time = time.time() + timeout
+ while True:
+ data = f.read(CHUNKSIZE)
+ self._send_packet(data, end_time - time.time())
+ if len(data) < CHUNKSIZE:
+ break
+ except FileTransferError, e:
+ e.filename = filename
+ raise
finally:
f.close()
- def _receive_file_chunks(self, filename, timeout=30):
+ def _receive_file_chunks(self, filename, timeout=60):
+ if self._log_func:
+ self._log_func("Receiving file %s" % filename)
f = open(filename, "wb")
try:
- end_time = time.time() + timeout
- while True:
- try:
+ try:
+ end_time = time.time() + timeout
+ while True:
data = self._receive_packet(end_time - time.time())
- except FileTransferTimeoutError:
- raise FileTransferTimeoutError("Timeout expired while "
- "receiving file %s" %
- filename)
- except FileTransferProtocolError:
- raise FileTransferProtocolError("Error receiving file %s" %
- filename)
- f.write(data)
- if len(data) < CHUNKSIZE:
- break
+ f.write(data)
+ if len(data) < CHUNKSIZE:
+ break
+ except FileTransferError, e:
+ e.filename = filename
+ raise
finally:
f.close()
- def _send_msg(self, msg, timeout=10):
+ def _send_msg(self, msg, timeout=60):
self._send(struct.pack("=I", msg))
- def _receive_msg(self, timeout=10):
+ def _receive_msg(self, timeout=60):
s = self._receive(4, timeout)
return struct.unpack("=I", s)[0]
@@ -191,7 +247,7 @@ class FileTransferClient(object):
raise e[0], e[1], e[2]
if msg == RSS_ERROR:
errmsg = self._receive_packet()
- raise FileTransferServerError("Server said: %s" % errmsg)
+ raise FileTransferServerError(errmsg)
raise e[0], e[1], e[2]
@@ -200,20 +256,22 @@ class FileUploadClient(FileTransferClient):
Connect to a RSS (remote shell server) and upload files or directory trees.
"""
- def __init__(self, address, port, timeout=10):
+ def __init__(self, address, port, log_func=None, timeout=20):
"""
Connect to a server.
@param address: The server's address
@param port: The server's port
+ @param log_func: If provided, transfer stats will be passed to this
+ function during the transfer
@param timeout: Time duration to wait for connection to succeed
@raise FileTransferConnectError: Raised if the connection fails
@raise FileTransferProtocolError: Raised if an incorrect magic number
is received
- @raise FileTransferSendError: Raised if the RSS_UPLOAD message cannot
+ @raise FileTransferSocketError: Raised if the RSS_UPLOAD message cannot
be sent to the server
"""
- super(FileUploadClient, self).__init__(address, port, timeout)
+ super(FileUploadClient, self).__init__(address, port, log_func, timeout)
self._send_msg(RSS_UPLOAD)
@@ -221,7 +279,7 @@ class FileUploadClient(FileTransferClient):
if os.path.isfile(path):
self._send_msg(RSS_CREATE_FILE)
self._send_packet(os.path.basename(path))
- self._send_file_chunks(path, max(0, end_time - time.time()))
+ self._send_file_chunks(path, end_time - time.time())
elif os.path.isdir(path):
self._send_msg(RSS_CREATE_DIR)
self._send_packet(os.path.basename(path))
@@ -277,12 +335,12 @@ class FileUploadClient(FileTransferClient):
"directories" %
src_pattern)
# Look for RSS_OK or RSS_ERROR
- msg = self._receive_msg(max(0, end_time - time.time()))
+ msg = self._receive_msg(end_time - time.time())
if msg == RSS_OK:
return
elif msg == RSS_ERROR:
errmsg = self._receive_packet()
- raise FileTransferServerError("Server said: %s" % errmsg)
+ raise FileTransferServerError(errmsg)
else:
# Neither RSS_OK nor RSS_ERROR found
raise FileTransferProtocolError("Received unexpected msg")
@@ -297,12 +355,14 @@ class FileDownloadClient(FileTransferClient):
Connect to a RSS (remote shell server) and download files or directory trees.
"""
- def __init__(self, address, port, timeout=10):
+ def __init__(self, address, port, log_func=None, timeout=20):
"""
Connect to a server.
@param address: The server's address
@param port: The server's port
+ @param log_func: If provided, transfer stats will be passed to this
+ function during the transfer
@param timeout: Time duration to wait for connection to succeed
@raise FileTransferConnectError: Raised if the connection fails
@raise FileTransferProtocolError: Raised if an incorrect magic number
@@ -310,7 +370,7 @@ class FileDownloadClient(FileTransferClient):
@raise FileTransferSendError: Raised if the RSS_UPLOAD message cannot
be sent to the server
"""
- super(FileDownloadClient, self).__init__(address, port, timeout)
+ super(FileDownloadClient, self).__init__(address, port, log_func, timeout)
self._send_msg(RSS_DOWNLOAD)
@@ -358,8 +418,7 @@ class FileDownloadClient(FileTransferClient):
filename = self._receive_packet()
if os.path.isdir(dst_path):
dst_path = os.path.join(dst_path, filename)
- self._receive_file_chunks(
- dst_path, max(0, end_time - time.time()))
+ self._receive_file_chunks(dst_path, end_time - time.time())
dst_path = os.path.dirname(dst_path)
file_count += 1
elif msg == RSS_CREATE_DIR:
@@ -385,7 +444,7 @@ class FileDownloadClient(FileTransferClient):
elif msg == RSS_ERROR:
# Receive error message and abort
errmsg = self._receive_packet()
- raise FileTransferServerError("Server said: %s" % errmsg)
+ raise FileTransferServerError(errmsg)
else:
# Unexpected msg
raise FileTransferProtocolError("Received unexpected msg")
@@ -395,26 +454,26 @@ class FileDownloadClient(FileTransferClient):
raise
-def upload(address, port, src_pattern, dst_path, timeout=60,
- connect_timeout=10):
+def upload(address, port, src_pattern, dst_path, log_func=None, timeout=60,
+ connect_timeout=20):
"""
Connect to server and upload files.
@see: FileUploadClient
"""
- client = FileUploadClient(address, port, connect_timeout)
+ client = FileUploadClient(address, port, log_func, connect_timeout)
client.upload(src_pattern, dst_path, timeout)
client.close()
-def download(address, port, src_pattern, dst_path, timeout=60,
- connect_timeout=10):
+def download(address, port, src_pattern, dst_path, log_func=None, timeout=60,
+ connect_timeout=20):
"""
Connect to server and upload files.
@see: FileDownloadClient
"""
- client = FileDownloadClient(address, port, connect_timeout)
+ client = FileDownloadClient(address, port, log_func, connect_timeout)
client.download(src_pattern, dst_path, timeout)
client.close()
@@ -430,6 +489,9 @@ def main():
parser.add_option("-u", "--upload",
action="store_true", dest="upload",
help="upload files to server")
+ parser.add_option("-v", "--verbose",
+ action="store_true", dest="verbose",
+ help="be verbose")
parser.add_option("-t", "--timeout",
type="int", dest="timeout", default=3600,
help="transfer timeout")
@@ -441,10 +503,16 @@ def main():
address, port, src_pattern, dst_path = args
port = int(port)
+ logger = None
+ if options.verbose:
+ def p(s):
+ print s
+ logger = p
+
if options.download:
- download(address, port, src_pattern, dst_path, options.timeout)
+ download(address, port, src_pattern, dst_path, logger, options.timeout)
elif options.upload:
- upload(address, port, src_pattern, dst_path, options.timeout)
+ upload(address, port, src_pattern, dst_path, logger, options.timeout)
if __name__ == "__main__":

Powered by Google App Engine
This is Rietveld 408576698