ironfan 3.1.0.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +51 -0
- data/.rspec +3 -0
- data/CHANGELOG.md +130 -0
- data/Gemfile +26 -0
- data/LICENSE.md +201 -0
- data/README.md +328 -0
- data/Rakefile +104 -0
- data/TODO.md +16 -0
- data/VERSION +1 -0
- data/chefignore +41 -0
- data/cluster_chef-knife.gemspec +123 -0
- data/cluster_chef.gemspec +111 -0
- data/config/client.rb +59 -0
- data/config/proxy.pac +12 -0
- data/config/ubuntu10.04-ironfan.erb +157 -0
- data/config/ubuntu11.10-ironfan.erb +145 -0
- data/ironfan.gemspec +121 -0
- data/lib/chef/knife/bootstrap/ubuntu10.04-ironfan.erb +157 -0
- data/lib/chef/knife/bootstrap/ubuntu11.10-ironfan.erb +145 -0
- data/lib/chef/knife/cluster_bootstrap.rb +74 -0
- data/lib/chef/knife/cluster_kick.rb +94 -0
- data/lib/chef/knife/cluster_kill.rb +73 -0
- data/lib/chef/knife/cluster_launch.rb +164 -0
- data/lib/chef/knife/cluster_list.rb +50 -0
- data/lib/chef/knife/cluster_proxy.rb +126 -0
- data/lib/chef/knife/cluster_show.rb +61 -0
- data/lib/chef/knife/cluster_ssh.rb +141 -0
- data/lib/chef/knife/cluster_start.rb +40 -0
- data/lib/chef/knife/cluster_stop.rb +43 -0
- data/lib/chef/knife/cluster_sync.rb +77 -0
- data/lib/chef/knife/generic_command.rb +66 -0
- data/lib/chef/knife/knife_common.rb +195 -0
- data/lib/ironfan.rb +143 -0
- data/lib/ironfan/chef_layer.rb +299 -0
- data/lib/ironfan/cloud.rb +412 -0
- data/lib/ironfan/cluster.rb +118 -0
- data/lib/ironfan/compute.rb +153 -0
- data/lib/ironfan/deprecated.rb +33 -0
- data/lib/ironfan/discovery.rb +177 -0
- data/lib/ironfan/dsl_object.rb +124 -0
- data/lib/ironfan/facet.rb +144 -0
- data/lib/ironfan/fog_layer.rb +150 -0
- data/lib/ironfan/private_key.rb +130 -0
- data/lib/ironfan/role_implications.rb +58 -0
- data/lib/ironfan/security_group.rb +119 -0
- data/lib/ironfan/server.rb +281 -0
- data/lib/ironfan/server_slice.rb +260 -0
- data/lib/ironfan/volume.rb +157 -0
- data/spec/ironfan/cluster_spec.rb +13 -0
- data/spec/ironfan/facet_spec.rb +69 -0
- data/spec/ironfan/server_slice_spec.rb +19 -0
- data/spec/ironfan/server_spec.rb +112 -0
- data/spec/ironfan_spec.rb +193 -0
- data/spec/spec_helper.rb +50 -0
- data/spec/spec_helper/dummy_chef.rb +25 -0
- data/spec/test_config.rb +20 -0
- data/tasks/chef_config.rake +38 -0
- data/tasks/jeweler_use_alt_branch.rake +53 -0
- metadata +217 -0
@@ -0,0 +1,299 @@
|
|
1
|
+
#
|
2
|
+
# OK so things get a little fishy here, and it's all Opscode's fault ;-)
|
3
|
+
#
|
4
|
+
# There's currently no API for setting ACLs. However, if the *client the
|
5
|
+
# node will run as* is the *client that creates the node*, it is granted the
|
6
|
+
# correct permissions.
|
7
|
+
#
|
8
|
+
# * client exists, node exists: don't need to do anything. We trust that permissions are correct.
|
9
|
+
# * client absent, node exists: client created, node is fine. We trust that permissions are correct.
|
10
|
+
# * client absent, node absent: client created, so have key; client creates node, so it has write permissions.
|
11
|
+
# * client exists, node absent: FAIL.
|
12
|
+
#
|
13
|
+
# The current implementation persists the client keys locally to your
|
14
|
+
# Chef::Config[:client_key_dir]. This is insecure and unmanageable; and the
|
15
|
+
# node will shortly re-register the key, making it invalide anyway.
|
16
|
+
#
|
17
|
+
# If the client's private_key is empty/wrong and the node is absent, it will
|
18
|
+
# cause an error. in that case, you can:
|
19
|
+
#
|
20
|
+
# * create the node yourself in the management console, and
|
21
|
+
# grant access to its eponymous client; OR
|
22
|
+
# * nuke the client key from orbit (it's the only way to be sure) and re-run,
|
23
|
+
# taking all responsibility for the catastrophic results of an errant nuke; OR
|
24
|
+
# * wait for opscode to open API access for ACLs.
|
25
|
+
#
|
26
|
+
#
|
27
|
+
|
28
|
+
module Ironfan
|
29
|
+
module DryRunnable
|
30
|
+
# Run given block unless in dry_run mode (Ironfan.chef_config[:dry_run]
|
31
|
+
# is true)
|
32
|
+
def unless_dry_run
|
33
|
+
if Ironfan.chef_config[:dry_run]
|
34
|
+
ui.info(" ... but not really (#{ui.color("dry run", :bold, :yellow)} for server #{name})")
|
35
|
+
else
|
36
|
+
yield
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
ComputeBuilder.class_eval do
|
42
|
+
def new_chef_role(role_name, cluster, facet=nil)
|
43
|
+
chef_role = Chef::Role.new
|
44
|
+
chef_role.name role_name
|
45
|
+
chef_role.description "Ironfan generated role for #{[cluster_name, facet_name].compact.join('-')}" unless chef_role.description
|
46
|
+
chef_role.instance_eval{ @cluster = cluster; @facet = facet; }
|
47
|
+
@chef_roles << chef_role
|
48
|
+
chef_role
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
ServerSlice.class_eval do
|
53
|
+
include DryRunnable
|
54
|
+
def sync_roles
|
55
|
+
step(" syncing cluster and facet roles")
|
56
|
+
unless_dry_run do
|
57
|
+
chef_roles.each(&:save)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
#
|
63
|
+
# Ironfan::Server methods that handle chef actions
|
64
|
+
#
|
65
|
+
Server.class_eval do
|
66
|
+
include DryRunnable
|
67
|
+
|
68
|
+
# The chef client, if it already exists in the server.
|
69
|
+
# Use the 'ensure' method to create/update it.
|
70
|
+
def chef_client
|
71
|
+
return @chef_client unless @chef_client.nil?
|
72
|
+
@chef_client = cluster.find_client(fullname) || false
|
73
|
+
end
|
74
|
+
|
75
|
+
# The chef node, if it already exists in the server.
|
76
|
+
# Use the 'ensure' method to create/update it.
|
77
|
+
def chef_node
|
78
|
+
return @chef_node unless @chef_node.nil?
|
79
|
+
@chef_node = cluster.find_node(fullname) || false
|
80
|
+
end
|
81
|
+
|
82
|
+
# true if chef client is created and discovered
|
83
|
+
def chef_client?
|
84
|
+
chef_client.present?
|
85
|
+
end
|
86
|
+
|
87
|
+
# true if chef node is created and discovered
|
88
|
+
def chef_node?
|
89
|
+
chef_node.present?
|
90
|
+
end
|
91
|
+
|
92
|
+
def delete_chef
|
93
|
+
if chef_node then
|
94
|
+
step(" deleting chef node", :red)
|
95
|
+
unless_dry_run do
|
96
|
+
chef_node.destroy
|
97
|
+
end
|
98
|
+
@chef_node = nil
|
99
|
+
end
|
100
|
+
if chef_client
|
101
|
+
step(" deleting chef client", :red)
|
102
|
+
unless_dry_run do
|
103
|
+
chef_client.destroy
|
104
|
+
end
|
105
|
+
@chef_client = nil
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# creates or updates the chef node.
|
110
|
+
#
|
111
|
+
# See notes at top of file for why all this jiggery-fuckery
|
112
|
+
#
|
113
|
+
# * client exists, node exists: assume client can update, weep later when
|
114
|
+
# the initial chef run fails. Not much we can do here -- holler at opscode.
|
115
|
+
# * client exists, node absent: see if client can create, fail otherwise
|
116
|
+
# * client absent, node absent: see if client can create both, fail otherwise
|
117
|
+
# * client absent, node exists: fail (we can't get permissions)
|
118
|
+
def sync_chef_node
|
119
|
+
step(" syncing chef node using the server's key")
|
120
|
+
# force-fetch the node so that we have its full attributes (the discovery
|
121
|
+
# does not pull all of it back)
|
122
|
+
@chef_node = handle_chef_response('404'){ Chef::Node.load( fullname ) }
|
123
|
+
# sets @chef_client if it exists
|
124
|
+
chef_client
|
125
|
+
#
|
126
|
+
case
|
127
|
+
when @chef_client && @chef_node then _update_chef_node # this will fail later if the chef client is in a bad state but whaddayagonnado
|
128
|
+
when @chef_client && (! @chef_node) then _create_chef_node
|
129
|
+
when (! @chef_client) && (! @chef_node) then # create both
|
130
|
+
ensure_chef_client
|
131
|
+
_create_chef_node
|
132
|
+
when (! @chef_client) && @chef_node
|
133
|
+
raise("The #{fullname} node exists, but its client does not.\nDue to limitations in the Opscode API, if we create a client, it will lack write permissions to the node. Small sadness now avoids much sadness later\nYou must either create a client manually, fix its permissions in the Chef console, and drop its client key where we can find it; or (if you are aware of the consequences) do \nknife node delete #{fullname}")
|
134
|
+
end
|
135
|
+
@chef_node
|
136
|
+
end
|
137
|
+
|
138
|
+
def client_key
|
139
|
+
@client_key ||= Ironfan::ChefClientKey.new("client-#{fullname}", chef_client) do |body|
|
140
|
+
chef_client.private_key(body) if chef_client.present? && body.present?
|
141
|
+
cloud.user_data(:client_key => body)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def chef_client_script_content
|
146
|
+
return @chef_client_script_content if @chef_client_script_content
|
147
|
+
return unless cloud.chef_client_script
|
148
|
+
script_filename = File.expand_path("../../config/#{cloud.chef_client_script}", File.dirname(__FILE__))
|
149
|
+
@chef_client_script_content = safely{ File.read(script_filename) }
|
150
|
+
end
|
151
|
+
|
152
|
+
def announce_state state
|
153
|
+
@chef_node.set[:state] = state
|
154
|
+
end
|
155
|
+
|
156
|
+
protected
|
157
|
+
|
158
|
+
# Create the chef client on the server. Do not call this directly -- go
|
159
|
+
# through sync_chef_node.
|
160
|
+
#
|
161
|
+
# this is done as the eponymous client, ensuring that the client does in
|
162
|
+
# fact have permissions on the node
|
163
|
+
#
|
164
|
+
# preconditions: @chef_node is set
|
165
|
+
def _create_chef_node(&block)
|
166
|
+
step(" creating chef node", :green)
|
167
|
+
@chef_node = Chef::Node.new
|
168
|
+
@chef_node.name(fullname)
|
169
|
+
set_chef_node_attributes
|
170
|
+
set_chef_node_environment
|
171
|
+
sync_volume_attributes
|
172
|
+
unless_dry_run do
|
173
|
+
chef_api_server_as_client.post_rest('nodes', @chef_node)
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
# Update the chef client on the server. Do not call this directly -- go
|
178
|
+
# through create_or_update_chef_node.
|
179
|
+
#
|
180
|
+
# this is done as the eponymous client, ensuring that the client does in
|
181
|
+
# fact have permissions on the node.
|
182
|
+
#
|
183
|
+
# preconditions: @chef_node is set
|
184
|
+
def _update_chef_node
|
185
|
+
step(" updating chef node", :blue)
|
186
|
+
set_chef_node_attributes
|
187
|
+
set_chef_node_environment
|
188
|
+
sync_volume_attributes
|
189
|
+
unless_dry_run do
|
190
|
+
chef_api_server_as_admin.put_rest("nodes/#{@chef_node.name}", @chef_node)
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
|
195
|
+
def sync_volume_attributes
|
196
|
+
composite_volumes.each do |vol_name, vol|
|
197
|
+
chef_node.normal[:volumes] ||= Mash.new
|
198
|
+
chef_node.normal[:volumes][vol_name] = vol.to_mash.compact
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
def set_chef_node_attributes
|
203
|
+
step(" setting node runlist and essential attributes")
|
204
|
+
@chef_node.run_list = Chef::RunList.new(*@settings[:run_list])
|
205
|
+
@chef_node.normal[ :organization] = Chef::Config[:organization] if Chef::Config[:organization]
|
206
|
+
@chef_node.override[:cluster_name] = cluster_name
|
207
|
+
@chef_node.override[:facet_name] = facet_name
|
208
|
+
@chef_node.override[:facet_index] = facet_index
|
209
|
+
end
|
210
|
+
|
211
|
+
def set_chef_node_environment
|
212
|
+
@chef_node.chef_environment(environment.to_s) if environment.present?
|
213
|
+
end
|
214
|
+
|
215
|
+
#
|
216
|
+
# Don't call this directly -- only through ensure_chef_node_and_client
|
217
|
+
#
|
218
|
+
def ensure_chef_client
|
219
|
+
step(" ensuring chef client exists")
|
220
|
+
return @chef_client if chef_client
|
221
|
+
step( " creating chef client", :green)
|
222
|
+
@chef_client = Chef::ApiClient.new
|
223
|
+
@chef_client.name(fullname)
|
224
|
+
@chef_client.admin(false)
|
225
|
+
#
|
226
|
+
# ApiClient#create sends extra params that fail -- we'll do it ourselves
|
227
|
+
# purposefully *not* catching the 'but it already exists' error: if it
|
228
|
+
# didn't show up in the discovery process, we're in an inconsistent state
|
229
|
+
unless_dry_run do
|
230
|
+
response = chef_api_server_as_admin.post_rest("clients", { 'name' => fullname, 'admin' => false, 'private_key' => true })
|
231
|
+
client_key.body = response['private_key']
|
232
|
+
end
|
233
|
+
client_key.save
|
234
|
+
@chef_client
|
235
|
+
end
|
236
|
+
|
237
|
+
def chef_api_server_as_client
|
238
|
+
return @chef_api_server_as_client if @chef_api_server_as_client
|
239
|
+
unless File.exists?(client_key.filename)
|
240
|
+
raise("Cannot create chef node #{fullname} -- client #{@chef_client} exists but no client key found in #{client_key.filename}.")
|
241
|
+
end
|
242
|
+
@chef_api_server_as_client = Chef::REST.new(Chef::Config[:chef_server_url], fullname, client_key.filename)
|
243
|
+
end
|
244
|
+
|
245
|
+
def chef_api_server_as_admin
|
246
|
+
@chef_api_server_as_admin ||= Chef::REST.new(Chef::Config[:chef_server_url])
|
247
|
+
end
|
248
|
+
|
249
|
+
# Execute the given chef call, but don't explode if the given http status
|
250
|
+
# code comes back
|
251
|
+
#
|
252
|
+
# @return chef object, or false if the server returned a recoverable response
|
253
|
+
def handle_chef_response(recoverable_responses, &block)
|
254
|
+
begin
|
255
|
+
block.call
|
256
|
+
rescue Net::HTTPServerException => e
|
257
|
+
raise unless Array(recoverable_responses).include?(e.response.code)
|
258
|
+
Chef::Log.debug("Swallowing a #{e.response.code} response in #{self.fullname}: #{e}")
|
259
|
+
return false
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
#
|
264
|
+
# The below *was* present but was pulled from the API by opscode for some reason (2011/10/20)
|
265
|
+
#
|
266
|
+
|
267
|
+
# # The client is required to have these permissions on its eponymous node
|
268
|
+
# REQUIRED_PERMISSIONS = %w[read create update]
|
269
|
+
#
|
270
|
+
# #
|
271
|
+
# # Verify that the client has required _acl's on the node.
|
272
|
+
# #
|
273
|
+
# # We don't raise an error, just a very noisy warning.
|
274
|
+
# #
|
275
|
+
# def check_node_permissions
|
276
|
+
# step(" ensuring chef node permissions are correct")
|
277
|
+
# chef_server_rest = Chef::REST.new(Chef::Config[:chef_server_url])
|
278
|
+
# handle_chef_response('404') do
|
279
|
+
# perms = chef_server_rest.get_rest("nodes/#{fullname}/_acl")
|
280
|
+
# perms_valid = {}
|
281
|
+
# REQUIRED_PERMISSIONS.each{|perm| perms_valid[perm] = perms[perm] && perms[perm]['actors'].include?(fullname) }
|
282
|
+
# Chef::Log.debug("Checking permissions: #{perms_valid.inspect} -- #{ perms_valid.values.all? ? 'correct' : 'BADNESS' }")
|
283
|
+
# unless perms_valid.values.all?
|
284
|
+
# ui.info(" ************************ ")
|
285
|
+
# ui.info(" ")
|
286
|
+
# ui.info(" INCONSISTENT PERMISSIONS for node #{fullname}:")
|
287
|
+
# ui.info(" The client[#{fullname}] should have permissions for #{REQUIRED_PERMISSIONS.join(', ')}")
|
288
|
+
# ui.info(" Instead, they are #{perms_valid.inspect}")
|
289
|
+
# ui.info(" You should create the node #{fullname} as client[#{fullname}], not as yourself.")
|
290
|
+
# ui.info(" ")
|
291
|
+
# ui.info(" Please adjust the permissions on the Opscode console, at")
|
292
|
+
# ui.info(" https://manage.opscode.com/nodes/#{fullname}/_acl")
|
293
|
+
# ui.info(" ")
|
294
|
+
# ui.info(" ************************ ")
|
295
|
+
# end
|
296
|
+
# end
|
297
|
+
# end
|
298
|
+
end
|
299
|
+
end
|
@@ -0,0 +1,412 @@
|
|
1
|
+
module Ironfan
|
2
|
+
module Cloud
|
3
|
+
|
4
|
+
#
|
5
|
+
# Right now only one cloud provider is implemented, so the separation
|
6
|
+
# between `cloud` and `cloud(:ec2)` is muddy.
|
7
|
+
#
|
8
|
+
# The goal though is to allow
|
9
|
+
#
|
10
|
+
# * cloud with no predicate -- definitions that apply to all cloud
|
11
|
+
# providers. If you only use one provider ever nothing stops you from
|
12
|
+
# always saying `cloud`.
|
13
|
+
# * Declarations irrelevant to other providers are acceptable and will be ignored
|
14
|
+
# * Declarations that are wrong in the context of other providers (a `public_ip`
|
15
|
+
# that is not available) will presumably cause a downstream error -- it's
|
16
|
+
# your responsibility to overlay with provider-correct values.
|
17
|
+
# * There are several declarations that *could* be sensibly abstracted, but
|
18
|
+
# are not. Rather than specifying `flavor 'm1.xlarge'`, I could ask for
|
19
|
+
# :ram => 15, :cores => 4 or storage => 1500 and get the cheapest machine
|
20
|
+
# that met or exceeded each constraint -- the default of `:price =>
|
21
|
+
# :smallest` would get me a t1.micro on EC2, a 256MB on
|
22
|
+
# Rackspace. Availability zones could also plausibly be parameterized.
|
23
|
+
#
|
24
|
+
# @example
|
25
|
+
# # these apply regardless of cloud provider
|
26
|
+
# cloud do
|
27
|
+
# # this makes sense everywhere
|
28
|
+
# image_name 'maverick'
|
29
|
+
#
|
30
|
+
# # this is not offered by many providers, and its value is non-portable;
|
31
|
+
# # but if you only run in one cloud there's harm in putting it here
|
32
|
+
# # or overriding it.
|
33
|
+
# public_ip '1.2.3.4'
|
34
|
+
#
|
35
|
+
# # Implemented differently across providers but its meaning is clear
|
36
|
+
# security_group :nagios
|
37
|
+
#
|
38
|
+
# # This is harmless for the other clouds
|
39
|
+
# availability_zones ['us-east-1d']
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
# # these only apply to ec2 launches.
|
43
|
+
# # `ec2` is sugar for `cloud(:ec2)`.
|
44
|
+
# ec2 do
|
45
|
+
# spot_price_fraction 0.4
|
46
|
+
# end
|
47
|
+
#
|
48
|
+
class Base < Ironfan::DslObject
|
49
|
+
has_keys(
|
50
|
+
:name, :flavor, :image_name, :image_id, :keypair,
|
51
|
+
:chef_client_script, :public_ip, :permanent )
|
52
|
+
attr_accessor :owner
|
53
|
+
|
54
|
+
def initialize(owner, *args)
|
55
|
+
self.owner = owner
|
56
|
+
super(*args)
|
57
|
+
end
|
58
|
+
|
59
|
+
# default values to apply where no value was set
|
60
|
+
# @returns [Hash] hash of defaults
|
61
|
+
def defaults
|
62
|
+
reverse_merge!({
|
63
|
+
:image_name => 'natty',
|
64
|
+
})
|
65
|
+
end
|
66
|
+
|
67
|
+
# The username to ssh with.
|
68
|
+
# @return the ssh_user if set explicitly; otherwise, the user implied by the image name, if any; or else 'root'
|
69
|
+
def ssh_user(val=nil)
|
70
|
+
from_setting_or_image_info :ssh_user, val, 'root'
|
71
|
+
end
|
72
|
+
|
73
|
+
# Location of ssh private keys
|
74
|
+
def ssh_identity_dir(val=nil)
|
75
|
+
set :ssh_identity_dir, File.expand_path(val) unless val.nil?
|
76
|
+
@settings.include?(:ssh_identity_dir) ? @settings[:ssh_identity_dir] : Chef::Config.ec2_key_dir
|
77
|
+
end
|
78
|
+
|
79
|
+
# SSH identity file used for knife ssh, knife boostrap and such
|
80
|
+
def ssh_identity_file(val=nil)
|
81
|
+
set :ssh_identity_file, File.expand_path(val) unless val.nil?
|
82
|
+
@settings.include?(:ssh_identity_file) ? @settings[:ssh_identity_file] : File.join(ssh_identity_dir, "#{keypair}.pem")
|
83
|
+
end
|
84
|
+
|
85
|
+
# ID of the machine image to use.
|
86
|
+
# @return the image_id if set explicitly; otherwise, the id implied by the image name
|
87
|
+
def image_id(val=nil)
|
88
|
+
from_setting_or_image_info :image_id, val
|
89
|
+
end
|
90
|
+
|
91
|
+
# Distribution knife should target when bootstrapping an instance
|
92
|
+
# @return the bootstrap_distro if set explicitly; otherwise, the bootstrap_distro implied by the image name
|
93
|
+
def bootstrap_distro(val=nil)
|
94
|
+
from_setting_or_image_info :bootstrap_distro, val, "ubuntu10.04-gems"
|
95
|
+
end
|
96
|
+
|
97
|
+
def validation_key
|
98
|
+
IO.read(Chef::Config.validation_key) rescue ''
|
99
|
+
end
|
100
|
+
|
101
|
+
# The instance price, drawn from the compute flavor's info
|
102
|
+
def price
|
103
|
+
flavor_info[:price]
|
104
|
+
end
|
105
|
+
|
106
|
+
# The instance bitness, drawn from the compute flavor's info
|
107
|
+
def bits
|
108
|
+
flavor_info[:bits]
|
109
|
+
end
|
110
|
+
|
111
|
+
protected
|
112
|
+
# If value was explicitly set, use that; if the Chef::Config[:ec2_image_info] implies a value use that; otherwise use the default
|
113
|
+
def from_setting_or_image_info(key, val=nil, default=nil)
|
114
|
+
@settings[key] = val unless val.nil?
|
115
|
+
return @settings[key] if @settings.include?(key)
|
116
|
+
return image_info[key] unless image_info.nil?
|
117
|
+
return default # otherwise
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
class Ec2 < Base
|
122
|
+
has_keys(
|
123
|
+
:region, :availability_zones, :backing,
|
124
|
+
:spot_price, :spot_price_fraction,
|
125
|
+
:user_data, :security_groups,
|
126
|
+
:monitoring
|
127
|
+
)
|
128
|
+
|
129
|
+
def initialize(*args)
|
130
|
+
super *args
|
131
|
+
@settings[:security_groups] ||= Mash.new
|
132
|
+
@settings[:user_data] ||= Mash.new
|
133
|
+
end
|
134
|
+
|
135
|
+
#
|
136
|
+
# Sets some defaults for amazon cloud usage, and registers the root volume
|
137
|
+
#
|
138
|
+
def defaults
|
139
|
+
owner.volume(:root).reverse_merge!({
|
140
|
+
:device => '/dev/sda1',
|
141
|
+
:mount_point => '/',
|
142
|
+
:mountable => false,
|
143
|
+
})
|
144
|
+
self.reverse_merge!({
|
145
|
+
:availability_zones => ['us-east-1d'],
|
146
|
+
:backing => 'ebs',
|
147
|
+
:flavor => 't1.micro',
|
148
|
+
})
|
149
|
+
super
|
150
|
+
end
|
151
|
+
|
152
|
+
# adds a security group to the cloud instance
|
153
|
+
def security_group(sg_name, hsh={}, &block)
|
154
|
+
sg_name = sg_name.to_s
|
155
|
+
security_groups[sg_name] ||= Ironfan::Cloud::SecurityGroup.new(self, sg_name)
|
156
|
+
security_groups[sg_name].configure(hsh, &block)
|
157
|
+
security_groups[sg_name]
|
158
|
+
end
|
159
|
+
|
160
|
+
# With a value, sets the spot price to the given fraction of the
|
161
|
+
# instance's full price (as found in Ironfan::Cloud::Aws::FLAVOR_INFO)
|
162
|
+
# With no value, returns the spot price as a fraction of the full instance price.
|
163
|
+
def spot_price_fraction(val=nil)
|
164
|
+
if val
|
165
|
+
spot_price( price.to_f * val )
|
166
|
+
else
|
167
|
+
spot_price / price rescue 0
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
# EC2 User data -- DNA typically used to bootstrap the machine.
|
172
|
+
# @param [Hash] value -- when present, merged with the existing user data (overriding it)
|
173
|
+
# @return the user_data hash
|
174
|
+
def user_data(hsh={})
|
175
|
+
@settings[:user_data].merge!(hsh.to_hash) unless hsh.empty?
|
176
|
+
@settings[:user_data]
|
177
|
+
end
|
178
|
+
|
179
|
+
def reverse_merge!(hsh)
|
180
|
+
super(hsh.to_mash.compact)
|
181
|
+
@settings[:security_groups].reverse_merge!(hsh.security_groups) if hsh.respond_to?(:security_groups)
|
182
|
+
@settings[:user_data ].reverse_merge!(hsh.user_data) if hsh.respond_to?(:user_data)
|
183
|
+
self
|
184
|
+
end
|
185
|
+
|
186
|
+
def region(val=nil)
|
187
|
+
set(:region, val)
|
188
|
+
if @settings[:region] then @settings[:region]
|
189
|
+
elsif default_availability_zone then default_availability_zone.gsub(/^(\w+-\w+-\d)[a-z]/, '\1')
|
190
|
+
else nil
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
def default_availability_zone
|
195
|
+
availability_zones.first if availability_zones
|
196
|
+
end
|
197
|
+
|
198
|
+
# Bring the ephemeral storage (local scratch disks) online
|
199
|
+
def mount_ephemerals(attrs={})
|
200
|
+
owner.volume(:ephemeral0, attrs){ device '/dev/sdb'; volume_id 'ephemeral0' ; mount_point '/mnt' ; tags( :bulk => true, :local => true, :fallback => true) } if flavor_info[:ephemeral_volumes] > 0
|
201
|
+
owner.volume(:ephemeral1, attrs){ device '/dev/sdc'; volume_id 'ephemeral1' ; mount_point '/mnt2'; tags( :bulk => true, :local => true, :fallback => true) } if flavor_info[:ephemeral_volumes] > 1
|
202
|
+
owner.volume(:ephemeral2, attrs){ device '/dev/sdd'; volume_id 'ephemeral2' ; mount_point '/mnt3'; tags( :bulk => true, :local => true, :fallback => true) } if flavor_info[:ephemeral_volumes] > 2
|
203
|
+
owner.volume(:ephemeral3, attrs){ device '/dev/sde'; volume_id 'ephemeral3' ; mount_point '/mnt4'; tags( :bulk => true, :local => true, :fallback => true) } if flavor_info[:ephemeral_volumes] > 3
|
204
|
+
end
|
205
|
+
|
206
|
+
# Utility methods
|
207
|
+
|
208
|
+
def image_info
|
209
|
+
Chef::Config[:ec2_image_info][ [region, bits, backing, image_name] ] or ( ui.warn "Make sure to define the machine's region, bits, backing and image_name. (Have #{[region, bits, backing, image_name].inspect})" ; {} )
|
210
|
+
end
|
211
|
+
|
212
|
+
def list_images
|
213
|
+
ui.info("Available images:")
|
214
|
+
Chef::Config[:ec2_image_info].each do |flavor_name, flavor|
|
215
|
+
ui.info(" #{flavor_name}\t#{flavor.inspect}")
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
def flavor(val=nil)
|
220
|
+
if val && (not FLAVOR_INFO.has_key?(val.to_s))
|
221
|
+
ui.warn("Unknown machine image flavor '#{val}'")
|
222
|
+
list_flavors
|
223
|
+
end
|
224
|
+
set :flavor, val
|
225
|
+
end
|
226
|
+
|
227
|
+
def flavor_info
|
228
|
+
FLAVOR_INFO[flavor] or ( ui.warn "Please define the machine's flavor: have #{self.inspect}" ; {} )
|
229
|
+
end
|
230
|
+
|
231
|
+
def list_flavors
|
232
|
+
ui.info("Available flavors:")
|
233
|
+
FLAVOR_INFO.each do |flavor_name, flavor|
|
234
|
+
ui.info(" #{flavor_name}\t#{flavor.inspect}")
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
# code $/hr $/mo $/day CPU/$ Mem/$ mem cpu cores cpcore storage bits IO type name
|
239
|
+
# t1.micro $0.02 14 0.48 10.00 33.50 0.67 0.2 1 0.2 0 64 Low Micro Micro
|
240
|
+
# m1.small $0.085 61 2.04 11.76 20.00 1.7 1 1 1 160 32 Moderate Standard Small
|
241
|
+
# c1.medium $0.17 123 4.08 29.41 10.00 1.7 5 2 2.5 350 32 Moderate High-CPU Medium
|
242
|
+
# m1.large $0.34 246 8.16 11.76 22.06 7.5 4 2 2 850 64 High Standard Large
|
243
|
+
# m2.xlarge $0.50 363 12.00 13.00 35.40 17.7 6.5 2 3.25 420 64 Moderate High-Memory Extra Large
|
244
|
+
# c1.xlarge $0.68 493 16.32 29.41 10.29 7 20 8 2.5 1690 64 High High-CPU Extra Large
|
245
|
+
# m1.xlarge $0.68 493 16.32 11.76 22.06 15 8 4 2 1690 64 High Standard Extra Large
|
246
|
+
# m2.2xlarge $1.00 726 24.00 13.00 34.20 34.2 13 4 3.25 850 64 High High-Memory Double Extra Large
|
247
|
+
# m2.4xlarge $2.00 1452 48.00 13.00 34.20 68.4 26 8 3.25 1690 64 High High-Memory Quadruple Extra Large
|
248
|
+
# cc1.4xlarge $1.60 1161 38.40 20.94 14.38 23 33.5 2 16.75 1690 64 Very High 10GB Compute Quadruple Extra Large
|
249
|
+
# cg1.4xlarge $2.10 1524 50.40 15.95 10.48 22 33.5 2 16.75 1690 64 Very High 10GB Cluster GPU Quadruple Extra Large
|
250
|
+
|
251
|
+
FLAVOR_INFO = {
|
252
|
+
't1.micro' => { :price => 0.02, :bits => '64-bit', :ram => 686, :cores => 1, :core_size => 0.25, :inst_disks => 0, :inst_disk_size => 0, :ephemeral_volumes => 0 },
|
253
|
+
'm1.small' => { :price => 0.085, :bits => '32-bit', :ram => 1740, :cores => 1, :core_size => 1, :inst_disks => 1, :inst_disk_size => 160, :ephemeral_volumes => 1 },
|
254
|
+
'c1.medium' => { :price => 0.17, :bits => '32-bit', :ram => 1740, :cores => 2, :core_size => 2.5, :inst_disks => 1, :inst_disk_size => 350, :ephemeral_volumes => 1 },
|
255
|
+
'm1.large' => { :price => 0.34, :bits => '64-bit', :ram => 7680, :cores => 2, :core_size => 2, :inst_disks => 2, :inst_disk_size => 850, :ephemeral_volumes => 2 },
|
256
|
+
'm2.xlarge' => { :price => 0.50, :bits => '64-bit', :ram => 18124, :cores => 2, :core_size => 3.25, :inst_disks => 1, :inst_disk_size => 420, :ephemeral_volumes => 1 },
|
257
|
+
'c1.xlarge' => { :price => 0.68, :bits => '64-bit', :ram => 7168, :cores => 8, :core_size => 2.5, :inst_disks => 4, :inst_disk_size => 1690, :ephemeral_volumes => 4 },
|
258
|
+
'm1.xlarge' => { :price => 0.68, :bits => '64-bit', :ram => 15360, :cores => 4, :core_size => 2, :inst_disks => 4, :inst_disk_size => 1690, :ephemeral_volumes => 4 },
|
259
|
+
'm2.2xlarge' => { :price => 1.00, :bits => '64-bit', :ram => 35020, :cores => 4, :core_size => 3.25, :inst_disks => 2, :inst_disk_size => 850, :ephemeral_volumes => 2 },
|
260
|
+
'm2.4xlarge' => { :price => 2.00, :bits => '64-bit', :ram => 70041, :cores => 8, :core_size => 3.25, :inst_disks => 4, :inst_disk_size => 1690, :ephemeral_volumes => 4 },
|
261
|
+
'cc1.4xlarge' => { :price => 1.60, :bits => '64-bit', :ram => 23552, :cores => 2, :core_size =>16.75, :inst_disks => 4, :inst_disk_size => 1690, :ephemeral_volumes => 2 },
|
262
|
+
'cg1.4xlarge' => { :price => 2.10, :bits => '64-bit', :ram => 22528, :cores => 2, :core_size =>16.75, :inst_disks => 4, :inst_disk_size => 1690, :ephemeral_volumes => 2 },
|
263
|
+
}
|
264
|
+
|
265
|
+
#
|
266
|
+
# To add to this list, use this snippet:
|
267
|
+
#
|
268
|
+
# Chef::Config[:ec2_image_info] ||= {}
|
269
|
+
# Chef::Config[:ec2_image_info].merge!({
|
270
|
+
# # ... lines like the below
|
271
|
+
# })
|
272
|
+
#
|
273
|
+
# in your knife.rb or whereever. We'll notice that it exists and add to it, rather than clobbering it.
|
274
|
+
#
|
275
|
+
Chef::Config[:ec2_image_info] ||= {}
|
276
|
+
Chef::Config[:ec2_image_info].merge!({
|
277
|
+
|
278
|
+
#
|
279
|
+
# Lucid (Ubuntu 9.10)
|
280
|
+
#
|
281
|
+
%w[us-east-1 64-bit instance karmic ] => { :image_id => 'ami-55739e3c', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
282
|
+
%w[us-east-1 32-bit instance karmic ] => { :image_id => 'ami-bb709dd2', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
283
|
+
%w[us-west-1 64-bit instance karmic ] => { :image_id => 'ami-cb2e7f8e', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
284
|
+
%w[us-west-1 32-bit instance karmic ] => { :image_id => 'ami-c32e7f86', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
285
|
+
%w[eu-west-1 64-bit instance karmic ] => { :image_id => 'ami-05c2e971', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
286
|
+
%w[eu-west-1 32-bit instance karmic ] => { :image_id => 'ami-2fc2e95b', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
287
|
+
|
288
|
+
#
|
289
|
+
# Lucid (Ubuntu 10.04.3)
|
290
|
+
#
|
291
|
+
%w[ap-southeast-1 64-bit ebs lucid ] => { :image_id => 'ami-77f28d25', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
292
|
+
%w[ap-southeast-1 32-bit ebs lucid ] => { :image_id => 'ami-4df28d1f', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
293
|
+
%w[ap-southeast-1 64-bit instance lucid ] => { :image_id => 'ami-57f28d05', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
294
|
+
%w[ap-southeast-1 32-bit instance lucid ] => { :image_id => 'ami-a5f38cf7', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
295
|
+
%w[eu-west-1 64-bit ebs lucid ] => { :image_id => 'ami-ab4d67df', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
296
|
+
%w[eu-west-1 32-bit ebs lucid ] => { :image_id => 'ami-a94d67dd', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
297
|
+
%w[eu-west-1 64-bit instance lucid ] => { :image_id => 'ami-a54d67d1', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
298
|
+
%w[eu-west-1 32-bit instance lucid ] => { :image_id => 'ami-cf4d67bb', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
299
|
+
#
|
300
|
+
%w[us-east-1 64-bit ebs lucid ] => { :image_id => 'ami-4b4ba522', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
301
|
+
%w[us-east-1 32-bit ebs lucid ] => { :image_id => 'ami-714ba518', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
302
|
+
%w[us-east-1 64-bit instance lucid ] => { :image_id => 'ami-fd4aa494', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
303
|
+
%w[us-east-1 32-bit instance lucid ] => { :image_id => 'ami-2d4aa444', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
304
|
+
#
|
305
|
+
%w[us-west-1 64-bit ebs lucid ] => { :image_id => 'ami-d197c694', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
306
|
+
%w[us-west-1 32-bit ebs lucid ] => { :image_id => 'ami-cb97c68e', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
307
|
+
%w[us-west-1 64-bit instance lucid ] => { :image_id => 'ami-c997c68c', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
308
|
+
%w[us-west-1 32-bit instance lucid ] => { :image_id => 'ami-c597c680', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
309
|
+
|
310
|
+
#
|
311
|
+
# Maverick (Ubuntu 10.10)
|
312
|
+
#
|
313
|
+
%w[ ap-southeast-1 64-bit ebs maverick ] => { :image_id => 'ami-32423c60', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
314
|
+
%w[ ap-southeast-1 64-bit instance maverick ] => { :image_id => 'ami-12423c40', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
315
|
+
%w[ ap-southeast-1 32-bit ebs maverick ] => { :image_id => 'ami-0c423c5e', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
316
|
+
%w[ ap-southeast-1 32-bit instance maverick ] => { :image_id => 'ami-7c423c2e', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
317
|
+
#
|
318
|
+
%w[ eu-west-1 64-bit ebs maverick ] => { :image_id => 'ami-e59ca991', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
319
|
+
%w[ eu-west-1 64-bit instance maverick ] => { :image_id => 'ami-1b9ca96f', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
320
|
+
%w[ eu-west-1 32-bit ebs maverick ] => { :image_id => 'ami-fb9ca98f', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
321
|
+
%w[ eu-west-1 32-bit instance maverick ] => { :image_id => 'ami-339ca947', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
322
|
+
#
|
323
|
+
%w[ us-east-1 64-bit ebs maverick ] => { :image_id => 'ami-cef405a7', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
324
|
+
%w[ us-east-1 64-bit instance maverick ] => { :image_id => 'ami-08f40561', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
325
|
+
%w[ us-east-1 32-bit ebs maverick ] => { :image_id => 'ami-ccf405a5', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
326
|
+
%w[ us-east-1 32-bit instance maverick ] => { :image_id => 'ami-a6f504cf', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
327
|
+
#
|
328
|
+
%w[ us-west-1 64-bit ebs maverick ] => { :image_id => 'ami-af7e2eea', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
329
|
+
%w[ us-west-1 64-bit instance maverick ] => { :image_id => 'ami-a17e2ee4', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
330
|
+
%w[ us-west-1 32-bit ebs maverick ] => { :image_id => 'ami-ad7e2ee8', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
331
|
+
%w[ us-west-1 32-bit instance maverick ] => { :image_id => 'ami-957e2ed0', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
332
|
+
|
333
|
+
#
|
334
|
+
# Natty (Ubuntu 11.04)
|
335
|
+
#
|
336
|
+
%w[ ap-northeast-1 32-bit ebs natty ] => { :image_id => 'ami-00b10501', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
337
|
+
%w[ ap-northeast-1 32-bit instance natty ] => { :image_id => 'ami-f0b004f1', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
338
|
+
%w[ ap-northeast-1 64-bit ebs natty ] => { :image_id => 'ami-02b10503', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
339
|
+
%w[ ap-northeast-1 64-bit instance natty ] => { :image_id => 'ami-fab004fb', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
340
|
+
#
|
341
|
+
%w[ ap-southeast-1 32-bit ebs natty ] => { :image_id => 'ami-06255f54', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
342
|
+
%w[ ap-southeast-1 32-bit instance natty ] => { :image_id => 'ami-72255f20', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
343
|
+
%w[ ap-southeast-1 64-bit ebs natty ] => { :image_id => 'ami-04255f56', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
344
|
+
%w[ ap-southeast-1 64-bit instance natty ] => { :image_id => 'ami-7a255f28', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
345
|
+
#
|
346
|
+
%w[ eu-west-1 32-bit ebs natty ] => { :image_id => 'ami-a4f7c5d0', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
347
|
+
%w[ eu-west-1 32-bit instance natty ] => { :image_id => 'ami-fef7c58a', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
348
|
+
%w[ eu-west-1 64-bit ebs natty ] => { :image_id => 'ami-a6f7c5d2', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
349
|
+
%w[ eu-west-1 64-bit instance natty ] => { :image_id => 'ami-c0f7c5b4', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
350
|
+
#
|
351
|
+
%w[ us-east-1 32-bit ebs natty ] => { :image_id => 'ami-e358958a', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
352
|
+
%w[ us-east-1 32-bit instance natty ] => { :image_id => 'ami-c15994a8', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
353
|
+
%w[ us-east-1 64-bit ebs natty ] => { :image_id => 'ami-fd589594', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
354
|
+
%w[ us-east-1 64-bit instance natty ] => { :image_id => 'ami-71589518', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
355
|
+
#
|
356
|
+
%w[ us-west-1 32-bit ebs natty ] => { :image_id => 'ami-43580406', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
357
|
+
%w[ us-west-1 32-bit instance natty ] => { :image_id => 'ami-e95f03ac', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
358
|
+
%w[ us-west-1 64-bit ebs natty ] => { :image_id => 'ami-4d580408', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
359
|
+
%w[ us-west-1 64-bit instance natty ] => { :image_id => 'ami-a15f03e4', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
360
|
+
|
361
|
+
#
|
362
|
+
# Oneric (Ubuntu 11.10)
|
363
|
+
#
|
364
|
+
%w[ ap-northeast-1 32-bit ebs oneric ] => { :image_id => 'ami-84902785', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
365
|
+
%w[ ap-northeast-1 32-bit instance oneric ] => { :image_id => 'ami-5e90275f', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
366
|
+
%w[ ap-northeast-1 64-bit ebs oneric ] => { :image_id => 'ami-88902789', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
367
|
+
%w[ ap-northeast-1 64-bit instance oneric ] => { :image_id => 'ami-7c90277d', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
368
|
+
#
|
369
|
+
%w[ ap-southeast-1 32-bit ebs oneric ] => { :image_id => 'ami-0a327758', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
370
|
+
%w[ ap-southeast-1 32-bit instance oneric ] => { :image_id => 'ami-00327752', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
371
|
+
%w[ ap-southeast-1 64-bit ebs oneric ] => { :image_id => 'ami-0832775a', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
372
|
+
%w[ ap-southeast-1 64-bit instance oneric ] => { :image_id => 'ami-04327756', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
373
|
+
#
|
374
|
+
%w[ eu-west-1 32-bit ebs oneric ] => { :image_id => 'ami-11f0cc65', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
375
|
+
%w[ eu-west-1 32-bit instance oneric ] => { :image_id => 'ami-4ff0cc3b', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
376
|
+
%w[ eu-west-1 64-bit ebs oneric ] => { :image_id => 'ami-1df0cc69', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
377
|
+
%w[ eu-west-1 64-bit instance oneric ] => { :image_id => 'ami-23f0cc57', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
378
|
+
#
|
379
|
+
%w[ us-east-1 32-bit ebs oneric ] => { :image_id => 'ami-a562a9cc', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
380
|
+
%w[ us-east-1 32-bit instance oneric ] => { :image_id => 'ami-3962a950', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
381
|
+
%w[ us-east-1 64-bit ebs oneric ] => { :image_id => 'ami-bf62a9d6', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
382
|
+
%w[ us-east-1 64-bit instance oneric ] => { :image_id => 'ami-c162a9a8', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
383
|
+
#
|
384
|
+
%w[ us-west-1 32-bit ebs oneric ] => { :image_id => 'ami-c9a1fe8c', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
385
|
+
%w[ us-west-1 32-bit instance oneric ] => { :image_id => 'ami-21a1fe64', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
386
|
+
%w[ us-west-1 64-bit ebs oneric ] => { :image_id => 'ami-cba1fe8e', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
387
|
+
%w[ us-west-1 64-bit instance oneric ] => { :image_id => 'ami-3fa1fe7a', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
388
|
+
#
|
389
|
+
%w[ us-west-2 32-bit ebs oneric ] => { :image_id => 'ami-ea9a17da', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
390
|
+
%w[ us-west-2 32-bit instance oneric ] => { :image_id => 'ami-f49a17c4', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
391
|
+
%w[ us-west-2 64-bit ebs oneric ] => { :image_id => 'ami-ec9a17dc', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
392
|
+
%w[ us-west-2 64-bit instance oneric ] => { :image_id => 'ami-fe9a17ce', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
|
393
|
+
})
|
394
|
+
end
|
395
|
+
|
396
|
+
class Slicehost < Base
|
397
|
+
# server_name
|
398
|
+
# slicehost_password
|
399
|
+
# Proc.new { |password| Chef::Config[:knife][:slicehost_password] = password }
|
400
|
+
|
401
|
+
# personality
|
402
|
+
end
|
403
|
+
|
404
|
+
class Rackspace < Base
|
405
|
+
# api_key, api_username, server_name
|
406
|
+
end
|
407
|
+
|
408
|
+
class Terremark < Base
|
409
|
+
# password, username, service
|
410
|
+
end
|
411
|
+
end
|
412
|
+
end
|