forked from riptano/ComboAMI
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ds0_utils.py
151 lines (122 loc) · 4.55 KB
/
ds0_utils.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
import gzip
import re
import shlex
import StringIO
import sys
import time
import urllib2
import logger
from email.parser import Parser
from argparse import ArgumentParser
def comboami_version():
return "2.6.3"
def comboami_defaultbranch():
return "2.6"
def curl_instance_data(url):
for i in range(20):
try:
req = urllib2.Request(url)
return req
except urllib2.HTTPError:
time.sleep(5)
sys.exit('Couldn\'t curl instance data after 60 seconds')
def read_instance_data(req):
data = urllib2.urlopen(req).read()
try:
stream = StringIO.StringIO(data)
gzipper = gzip.GzipFile(fileobj=stream)
return gzipper.read()
except IOError:
stream = StringIO.StringIO(data)
return stream.read()
def is_multipart_mime(data):
match = re.search('Content-Type: multipart', data)
if match:
return True
def get_user_data(req):
data = read_instance_data(req)
if is_multipart_mime(data):
message = Parser().parsestr(data)
for part in message.walk():
if (part.get_content_type() == 'text/plaintext'):
match = re.search('totalnodes', part.get_payload())
if (match):
return part.get_payload()
else:
return data
def get_ec2_data():
instance_data = {}
# Try to get EC2 User Data
try:
req = curl_instance_data('http://169.254.169.254/latest/user-data/')
instance_data['userdata'] = get_user_data(req)
except Exception, e:
instance_data['userdata'] = ''
return instance_data
def parse_ec2_userdata():
instance_data = get_ec2_data()
# Setup parser
parser = ArgumentParser()
# Development options
# Option that specifies repository to use for updating
parser.add_argument("--repository", action="store", type=str, dest="repository")
# Option that specifies the commit to use for updating (instead of the latest) -- kept for backwards compatibility
parser.add_argument("--forcecommit", action="store", type=str, dest="forcecommit")
try:
(args, unknown) = parser.parse_known_args(shlex.split(instance_data['userdata']))
return args
except:
return None
# Parse userdata options and return a git repository and commitish
# (a commitish is a string that represents a commit, it could be a branch,
# a tag, a short commit-hash, a long-hash, or anything that git rev-parse
# can handle)
#
# We'll use this to update the git-checkout baked into the AMI to deliver
# dynamic updates on boot
#
# This function is called from ds0_updater.py, and so if it is updated, the
# AMI must be rebaked. See the warning at the top of ds0_updater.py for details
def repository():
options = parse_ec2_userdata()
repository = None
commitish = ''
if options:
# User specified a --repository parameter, pull the repo and commitish
# out of it
if options.repository:
parts = options.repository.split('#')
nparts = len(parts)
if nparts > 0:
repository = parts[0]
if nparts > 1:
commitish = parts[1]
# For backwards compatibility, --forcecommit should allow specifying
# a commit from the default repository
elif options.forcecommit:
# Repository remains set to None in order to use the origin repo of
# the git-checkout baked into the repo
commitish = options.forcecommit
# No special repository or commit parameters were passed, use default
else:
# Repository = None, use the baked-in repo
commitish = comboami_defaultbranch()
return (repository, commitish)
# Returns a commit-hash that can be passed to git reset
#
# This function is called from ds0_updater.py, and so if it is updated, the
# AMI must be rebaked. See the warning at the top of ds0_updater.py for details
def get_git_reset_arg(commitish):
if not commitish:
return ''
# This will work if the commitish is a remote branch name
(commit_id, err) = logger.exe('git rev-parse origin/' + commitish)
if err:
# This will work if the commitish is a short-hash or long-hash
(commit_id, err) = logger.exe('git rev-parse ' + commitish)
if err:
# Can't figure out what commit is being referenced, return no
# commit-id and git reset will simply hard reset the workspace
# using the current commit in the git checkout baked into the AMI
return ''
return commit_id