3
# ubuntu-ec2-run: ec2-run-instances that support human readable
6
# Copyright (C) 2011 Dustin Kirkland <kirkland@ubuntu.com>
8
# Authors: Dustin Kirkland <kirkland@ubuntu.com>
10
# This program is free software: you can redistribute it and/or modify
11
# it under the terms of the GNU General Public License as published by
12
# the Free Software Foundation, version 3 of the License.
14
# This program is distributed in the hope that it will be useful,
15
# but WITHOUT ANY WARRANTY; without even the implied warranty of
16
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
# GNU General Public License for more details.
19
# You should have received a copy of the GNU General Public License
20
# along with this program. If not, see <http://www.gnu.org/licenses/>.
22
KNOWN_RELEASES = ["lucid", "maverick", "natty", "oneiric", "precise",
26
Usage: ubuntu-ec2-run [ options ] arguments
28
Run an ec2 instance of Ubuntu.
31
--dry-run: only report what would be done
33
All non-understood options are passed through to $EC2_PRE-run-instances
35
ubuntu-ec2-run passes the following arguments to cloud-image-query
36
in order to select an AMI to run. Defaults are marked with a '*':
39
stream: release* daily
40
arch: amd64*, x86_64, i386
41
store: ebs*, instance-store, instance
42
pvtype: pv*, hvm, paravirtual
44
Note, that --instance-type/-t will modify arch appropriately
47
* ubuntu-ec2-run oneiric daily --dry-run
48
# us-east-1/ebs/ubuntu-oneiric-daily-amd64-server-20110902
49
ec2-run-instances --instance-type=t1.micro ami-0ba16262
50
* EC2_PRE=euca- ubuntu-ec2-run lucid released --dry-run
51
# us-east-1/ebs/ubuntu-oneiric-daily-amd64-server-20110902
52
euca-run-instances released --instance-type=t1.micro ami-0ba16262
53
* ubuntu-ec2-run oneiric hvm --dry-run
54
# us-east-1/hvm/ubuntu-oneiric-11.10-beta1-amd64-server-20110831
55
ec2-run-instances ./bin/ubuntu-ec2-run --instance-type=cc1.4xlarge \\
56
--block-device-mapping /dev/sdb=ephemeral0 \\
57
--block-device-mapping /dev/sdc=ephemeral1 ami-b79754de
58
* ubuntu-ec2-run --region us-west-1 --instance-type \\
59
m1.small oneiric instance --dry-run
60
# us-west-1/instance-store/ubuntu-oneiric-11.10-beta1-i386-server-20110831
61
ec2-run-instances --region us-west-1 --instance-type m1.small ami-39bfe27c
62
""" % {'rels': ' '.join(KNOWN_RELEASES)}
70
# This could/should use `distro-info --supported`
72
"amd64", "x86_64", "i386",
75
"ebs", "instance-store", "instance",
76
"hvm", "paravirtual", "pv",
80
def get_argopt(args, optnames):
86
if opt.startswith("--"):
91
elif cur.startswith("%s=" % opt):
92
ret = args[i].split("=")[1]
103
def get_block_device_mappings(itype):
104
# cleaned from http://aws.amazon.com/ec2/instance-types/
105
# t1.micro 0 # m1.large 850 # cg1.4xlarge 1690
106
# m1.small 160 # m2.2xlarge 850 # m1.xlarge 1690
107
# c1.medium 350 # c1.xlarge 1690 # m2.4xlarge 1690
108
# m1.medium 410 # cc1.4xlarge 1690 # hi1.4xlarge 2048
109
# m2.xlarge 420 # cc1.4xlarge 1690 # cc2.8xlarge 3370
113
if (itype in ("t1.micro", "m1.small", "c1.medium") or
114
itype.startswith("m3.")):
115
pass # the first one is always attached. ephemeral0=sda2
116
elif itype in ("m2.xlarge", "m1.medium"):
117
bdmaps = ["/dev/sdb=ephemeral0"]
118
elif (itype in ("m1.large", "m2.2xlarge", "hi1.4xlarge") or
119
itype.startswith("cg1.") or itype.startswith("cc1.")):
120
bdmaps = ["/dev/sdb=ephemeral0", "/dev/sdc=ephemeral1"]
121
elif (itype in ("m1.xlarge", "m2.4xlarge", "c1.xlarge") or
122
itype.startswith("cc2.8xlarge")):
123
bdmaps = ["sdb=ephemeral0", "sdc=ephemeral1",
124
"sdd=ephemeral2", "sde=ephemeral3"]
127
args.extend(("--block-device-mapping", m,))
130
if "--help" in sys.argv or "-h" in sys.argv:
131
sys.stdout.write(USAGE)
134
if len(sys.argv) == 1:
135
sys.stderr.write(USAGE)
139
for name in ("EC2_PRE", "EC2PRE"):
140
if name in os.environ:
141
pre = os.environ[name]
143
# if the prefix is something like "myec2 "
144
# then assume that 'myec2' is a command itself
145
if pre.strip() == pre:
146
ri_cmd = ["%srun-instances" % pre]
148
ri_cmd = [pre.strip(), "run-instances"]
150
query_cmd = ["ubuntu-cloudimg-query",
151
"--format=%{ami}\n%{itype}\n%{summary}\n%{store}\n"]
154
# Get the list of releases. If they have 'ubuntu-distro-info', then use that
155
# otherwise, fall back to our builtin list of releases
157
out = subprocess.check_output(["ubuntu-distro-info", "--all"])
158
all_rels = out.strip().split("\n")
162
if seen_lucid or r == "lucid":
166
releases = KNOWN_RELEASES
169
# each arg_group is a list of arguments and a boolean that indicates
170
# if the value of that argument should be passed to query_cmd
171
# ec2-run-instances default instance-type is m1.small
173
(("--region",), True),
174
(("--instance-type", "-t"), True),
175
(("--block-device-mapping", "-b"), False),
179
for opts, passthrough in arg_groups:
180
arg_value = get_argopt(sys.argv, opts)
181
if arg_value is not None and passthrough:
182
query_cmd.append(arg_value)
183
flags[opts[0]] = arg_value
187
for arg in sys.argv[1:]:
188
if arg in aliases or arg in releases:
189
query_cmd.append(arg)
190
elif arg == "--dry-run":
197
cmd += " '%s'" % i.replace("\n", "\\n")
201
(ami, itype, summary, store, endl) = \
202
subprocess.check_output(query_cmd).split("\n")
204
sys.stderr.write("Unexpected output of command:\n %s" % cmd)
205
except subprocess.CalledProcessError as e:
206
sys.stderr.write("Failed. The following command returned failure:\n")
207
sys.stderr.write(" %s\n" % cmd)
210
sys.stderr.write("You do not have '%s' in your path\n" % query_cmd[0])
213
if flags.get("--instance-type", None) is None:
214
ri_cmd.append("--instance-type=%s" % itype)
216
if store == "ebs" and flags.get("--block-device-mapping", None) is None:
217
ri_cmd.extend(get_block_device_mappings(itype))
221
sys.stderr.write("# %s\n" % summary)
223
print ' '.join(ri_cmd)
225
os.execvp(ri_cmd[0], ri_cmd)
226
###############################################################################