summaryrefslogtreecommitdiff
path: root/boto/utils.py
diff options
context:
space:
mode:
authorJames Saryerwinnie <js@jamesls.com>2013-04-18 04:14:08 -0700
committerJames Saryerwinnie <js@jamesls.com>2013-04-18 04:14:08 -0700
commit89f4947000587e12042e5b35c4557871b21137b9 (patch)
tree0606c64058f8402e74b29c621105b74292ff366c /boto/utils.py
parentb5852b0aa5ac91f462b28ac9decee33d872dec4d (diff)
parent699d861f453aff8a398f9cd5a8de91ec8e36a8cf (diff)
downloadboto-2.9.0.tar.gz
Merge branch 'release-2.9.0'2.9.0
* release-2.9.0: (158 commits) Bump version to 2.9.0 Added underlying DynamoDB v2 support. Add redshift to setup.py/docs index Updated requests to something more modern. Only use 2 metadata service calls to get credentials Fix #1146: return response from custom url opener Fixed missing import. Add metadata_service_num_attempts config option Added cleanup for the snapshots created. Added support for redshift. Let total attempts by 1 + num_retries Add more diagnostics to debug logs Change GS calls to make_request to always convert to utf-8 bytes. Allow kwargs to be passed through to uplaoder Remove whitespace, fix long line lengths Improve VPC and VPN support Added sleeps to allow amazon time to propogate Added error handling for out of space during downloads Initial integration tests for idempotent subscribe Removed dead code from resumable upload handler ...
Diffstat (limited to 'boto/utils.py')
-rw-r--r--boto/utils.py49
1 files changed, 34 insertions, 15 deletions
diff --git a/boto/utils.py b/boto/utils.py
index d1f88b6c..e5c083f3 100644
--- a/boto/utils.py
+++ b/boto/utils.py
@@ -90,7 +90,9 @@ qsa_of_interest = ['acl', 'cors', 'defaultObjectAcl', 'location', 'logging',
# GET bucket?storageClass is not part of the S3 API.)
'storageClass',
# websiteConfig is a QSA for buckets in Google Cloud Storage.
- 'websiteConfig']
+ 'websiteConfig',
+ # compose is a QSA for objects in Google Cloud Storage.
+ 'compose']
_first_cap_regex = re.compile('(.)([A-Z][a-z]+)')
@@ -208,8 +210,7 @@ def retry_url(url, retry_on_404=True, num_retries=10):
req = urllib2.Request(url)
r = opener.open(req)
result = r.read()
- resp = urllib2.urlopen(req)
- return resp.read()
+ return result
except urllib2.HTTPError, e:
# in 2.6 you use getcode(), in 2.5 and earlier you use code
if hasattr(e, 'getcode'):
@@ -218,12 +219,12 @@ def retry_url(url, retry_on_404=True, num_retries=10):
code = e.code
if code == 404 and not retry_on_404:
return ''
- except urllib2.URLError, e:
- raise e
except Exception, e:
pass
boto.log.exception('Caught exception reading instance data')
- time.sleep(2 ** i)
+ # If not on the last iteration of the loop then sleep.
+ if i + 1 != num_retries:
+ time.sleep(2 ** i)
boto.log.error('Unable to read instance data, giving up')
return ''
@@ -310,8 +311,23 @@ class LazyLoadMetadata(dict):
return super(LazyLoadMetadata, self).__repr__()
+def _build_instance_metadata_url(url, version, path):
+ """
+ Builds an EC2 metadata URL for fetching information about an instance.
+
+ Requires the following arguments: a URL, a version and a path.
+
+ Example:
+
+ >>> _build_instance_metadata_url('http://169.254.169.254', 'latest', 'meta-data')
+ http://169.254.169.254/latest/meta-data/
+
+ """
+ return '%s/%s/%s/' % (url, version, path)
+
+
def get_instance_metadata(version='latest', url='http://169.254.169.254',
- timeout=None, num_retries=5):
+ data='meta-data', timeout=None, num_retries=5):
"""
Returns the instance metadata as a nested Python dictionary.
Simple values (e.g. local_hostname, hostname, etc.) will be
@@ -327,8 +343,8 @@ def get_instance_metadata(version='latest', url='http://169.254.169.254',
original = socket.getdefaulttimeout()
socket.setdefaulttimeout(timeout)
try:
- return _get_instance_metadata('%s/%s/meta-data/' % (url, version),
- num_retries=num_retries)
+ metadata_url = _build_instance_metadata_url(url, version, data)
+ return _get_instance_metadata(metadata_url, num_retries=num_retries)
except urllib2.URLError, e:
return None
finally:
@@ -342,7 +358,7 @@ def get_instance_identity(version='latest', url='http://169.254.169.254',
Returns the instance identity as a nested Python dictionary.
"""
iid = {}
- base_url = 'http://169.254.169.254/latest/dynamic/instance-identity'
+ base_url = _build_instance_metadata_url(url, version, 'dynamic/instance-identity')
if timeout is not None:
original = socket.getdefaulttimeout()
socket.setdefaulttimeout(timeout)
@@ -365,7 +381,7 @@ def get_instance_identity(version='latest', url='http://169.254.169.254',
def get_instance_userdata(version='latest', sep=None,
url='http://169.254.169.254'):
- ud_url = '%s/%s/user-data' % (url, version)
+ ud_url = _build_instance_metadata_url(url, version, 'user-data')
user_data = retry_url(ud_url, retry_on_404=False)
if user_data:
if sep:
@@ -378,7 +394,7 @@ def get_instance_userdata(version='latest', sep=None,
ISO8601 = '%Y-%m-%dT%H:%M:%SZ'
ISO8601_MS = '%Y-%m-%dT%H:%M:%S.%fZ'
-
+RFC1123 = '%a, %d %b %Y %H:%M:%S %Z'
def get_ts(ts=None):
if not ts:
@@ -392,9 +408,12 @@ def parse_ts(ts):
dt = datetime.datetime.strptime(ts, ISO8601)
return dt
except ValueError:
- dt = datetime.datetime.strptime(ts, ISO8601_MS)
- return dt
-
+ try:
+ dt = datetime.datetime.strptime(ts, ISO8601_MS)
+ return dt
+ except ValueError:
+ dt = datetime.datetime.strptime(ts, RFC1123)
+ return dt
def find_class(module_name, class_name=None):
if class_name: