blob: bda93c23d4103df523837d2474b6a7fc0a35c628 [file] [log] [blame]
Chris Sosa47a7d4e2012-03-28 11:26:55 -07001# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Module containing gsutil helper methods."""
6
7import subprocess
Chris Sosa101fd862012-06-12 17:44:53 -07008import time
Chris Sosa47a7d4e2012-03-28 11:26:55 -07009
Gilad Arnoldabb352e2012-09-23 01:24:27 -070010
Chris Sosa47a7d4e2012-03-28 11:26:55 -070011GSUTIL_ATTEMPTS = 5
12
13
14class GSUtilError(Exception):
15 """Exception raises when we run into an error running gsutil."""
16 pass
17
18
19def GSUtilRun(cmd, err_msg):
20 """Runs a GSUTIL command up to GSUTIL_ATTEMPTS number of times.
21
Chris Sosa101fd862012-06-12 17:44:53 -070022 Attempts are tried with exponential backoff.
23
Chris Sosa47a7d4e2012-03-28 11:26:55 -070024 Returns:
25 stdout of the called gsutil command.
26 Raises:
27 subprocess.CalledProcessError if all attempt to run gsutil cmd fails.
28 """
29 proc = None
Chris Sosa101fd862012-06-12 17:44:53 -070030 sleep_timeout = 1
Chris Sosa47a7d4e2012-03-28 11:26:55 -070031 for _attempt in range(GSUTIL_ATTEMPTS):
32 # Note processes can hang when capturing from stderr. This command
33 # specifically doesn't pipe stderr.
34 proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
35 stdout, _stderr = proc.communicate()
36 if proc.returncode == 0:
37 return stdout
Chris Sosa101fd862012-06-12 17:44:53 -070038
39 time.sleep(sleep_timeout)
40 sleep_timeout *= 2
41
Chris Sosa47a7d4e2012-03-28 11:26:55 -070042 else:
43 raise GSUtilError('%s GSUTIL cmd %s failed with return code %d' % (
44 err_msg, cmd, proc.returncode))
45
46
47def DownloadFromGS(src, dst):
48 """Downloads object from gs_url |src| to |dst|.
49
50 Raises:
51 GSUtilError: if an error occurs during the download.
52 """
53 cmd = 'gsutil cp %s %s' % (src, dst)
54 msg = 'Failed to download "%s".' % src
55 GSUtilRun(cmd, msg)