1
from email.utils import parsedate
6
import oauth.oauth as oauth
16
def read_config(url, creds):
17
"""Read cloud-init config from given `url` into `creds` dict.
19
Updates any keys in `creds` that are None with their corresponding
22
Important keys include `metadata_url`, and the actual OAuth
25
if url.startswith("http://") or url.startswith("https://"):
26
cfg_str = urllib2.urlopen(urllib2.Request(url=url))
28
if url.startswith("file://"):
30
cfg_str = open(url, "r").read()
32
cfg = yaml.safe_load(cfg_str)
34
# Support reading cloud-init config for MAAS datasource.
35
if 'datasource' in cfg:
36
cfg = cfg['datasource']['MAAS']
38
for key in creds.keys():
39
if key in cfg and creds[key] == None:
43
def oauth_headers(url, consumer_key, token_key, token_secret, consumer_secret,
45
"""Build OAuth headers using given credentials."""
46
consumer = oauth.OAuthConsumer(consumer_key, consumer_secret)
47
token = oauth.OAuthToken(token_key, token_secret)
49
timestamp = int(time.time()) + clockskew
52
'oauth_version': "1.0",
53
'oauth_nonce': oauth.generate_nonce(),
54
'oauth_timestamp': timestamp,
55
'oauth_token': token.key,
56
'oauth_consumer_key': consumer.key,
58
req = oauth.OAuthRequest(http_url=url, parameters=params)
60
oauth.OAuthSignatureMethod_PLAINTEXT(), consumer, token)
61
return(req.to_header())
64
def authenticate_headers(url, headers, creds, clockskew):
65
"""Update and sign a dict of request headers."""
66
if creds.get('consumer_key', None) != None:
67
headers.update(oauth_headers(
69
consumer_key=creds['consumer_key'],
70
token_key=creds['token_key'],
71
token_secret=creds['token_secret'],
72
consumer_secret=creds['consumer_secret'],
77
sys.stderr.write(msg + "\n")
80
def geturl(url, creds, headers=None, data=None):
81
# Takes a dict of creds to be passed through to oauth_headers,
82
# so it should have consumer_key, token_key, ...
86
headers = dict(headers)
90
exc = Exception("Unexpected Error")
91
for naptime in (1, 1, 2, 4, 8, 16, 32):
92
authenticate_headers(url, headers, creds, clockskew)
94
req = urllib2.Request(url=url, data=data, headers=headers)
95
return urllib2.urlopen(req).read()
96
except urllib2.HTTPError as exc:
97
if 'date' not in exc.headers:
98
warn("date field not in %d headers" % exc.code)
100
elif exc.code in (401, 403):
101
date = exc.headers['date']
103
ret_time = time.mktime(parsedate(date))
104
clockskew = int(ret_time - time.time())
105
warn("updated clock skew to %d" % clockskew)
107
warn("failed to convert date '%s'" % date)
108
except Exception as exc:
111
warn("request to %s failed. sleeping %d.: %s" % (url, naptime, exc))