ironfan 3.2.2 → 4.0.0

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.
Files changed (66) hide show
  1. data/CHANGELOG.md +5 -0
  2. data/VERSION +1 -1
  3. data/ironfan.gemspec +33 -20
  4. data/lib/chef/knife/cluster_kick.rb +17 -17
  5. data/lib/chef/knife/cluster_kill.rb +13 -7
  6. data/lib/chef/knife/cluster_launch.rb +60 -66
  7. data/lib/chef/knife/cluster_pry.rb +2 -2
  8. data/lib/chef/knife/cluster_show.rb +3 -6
  9. data/lib/chef/knife/cluster_ssh.rb +5 -11
  10. data/lib/chef/knife/cluster_start.rb +2 -4
  11. data/lib/chef/knife/cluster_stop.rb +1 -3
  12. data/lib/chef/knife/cluster_sync.rb +13 -21
  13. data/lib/chef/knife/ironfan_knife_common.rb +11 -9
  14. data/lib/chef/knife/ironfan_script.rb +2 -1
  15. data/lib/gorillib/resolution.rb +119 -0
  16. data/lib/ironfan/broker/computer.rb +316 -0
  17. data/lib/ironfan/broker/drive.rb +21 -0
  18. data/lib/ironfan/broker.rb +37 -0
  19. data/lib/ironfan/builder.rb +14 -0
  20. data/lib/ironfan/deprecated.rb +16 -58
  21. data/lib/ironfan/dsl/cloud.rb +21 -0
  22. data/lib/ironfan/dsl/cluster.rb +27 -0
  23. data/lib/ironfan/dsl/compute.rb +84 -0
  24. data/lib/ironfan/dsl/ec2.rb +260 -0
  25. data/lib/ironfan/dsl/facet.rb +25 -0
  26. data/lib/ironfan/dsl/role.rb +19 -0
  27. data/lib/ironfan/dsl/server.rb +31 -0
  28. data/lib/ironfan/dsl/virtualbox.rb +8 -0
  29. data/lib/ironfan/dsl/volume.rb +45 -0
  30. data/lib/ironfan/dsl.rb +7 -0
  31. data/lib/ironfan/headers.rb +58 -0
  32. data/lib/ironfan/provider/chef/client.rb +77 -0
  33. data/lib/ironfan/provider/chef/node.rb +133 -0
  34. data/lib/ironfan/provider/chef/role.rb +69 -0
  35. data/lib/ironfan/provider/chef.rb +28 -0
  36. data/lib/ironfan/provider/ec2/ebs_volume.rb +137 -0
  37. data/lib/ironfan/provider/ec2/elastic_ip.rb +10 -0
  38. data/lib/ironfan/provider/ec2/key_pair.rb +65 -0
  39. data/lib/ironfan/provider/ec2/machine.rb +258 -0
  40. data/lib/ironfan/provider/ec2/placement_group.rb +24 -0
  41. data/lib/ironfan/provider/ec2/security_group.rb +118 -0
  42. data/lib/ironfan/provider/ec2.rb +47 -0
  43. data/lib/ironfan/provider/virtualbox/machine.rb +10 -0
  44. data/lib/ironfan/provider/virtualbox.rb +8 -0
  45. data/lib/ironfan/provider.rb +139 -0
  46. data/lib/ironfan/requirements.rb +52 -0
  47. data/lib/ironfan.rb +44 -33
  48. metadata +34 -21
  49. data/lib/chef/knife/cluster_vagrant.rb +0 -144
  50. data/lib/chef/knife/vagrant/ironfan_environment.rb +0 -18
  51. data/lib/chef/knife/vagrant/ironfan_provisioners.rb +0 -27
  52. data/lib/chef/knife/vagrant/skeleton_vagrantfile.rb +0 -119
  53. data/lib/ironfan/chef_layer.rb +0 -300
  54. data/lib/ironfan/cloud.rb +0 -323
  55. data/lib/ironfan/cluster.rb +0 -118
  56. data/lib/ironfan/compute.rb +0 -139
  57. data/lib/ironfan/discovery.rb +0 -190
  58. data/lib/ironfan/dsl_builder.rb +0 -99
  59. data/lib/ironfan/facet.rb +0 -143
  60. data/lib/ironfan/fog_layer.rb +0 -196
  61. data/lib/ironfan/private_key.rb +0 -130
  62. data/lib/ironfan/role_implications.rb +0 -58
  63. data/lib/ironfan/security_group.rb +0 -133
  64. data/lib/ironfan/server.rb +0 -291
  65. data/lib/ironfan/server_slice.rb +0 -265
  66. data/lib/ironfan/volume.rb +0 -146
@@ -1,300 +0,0 @@
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.dry_run?
34
- ui.info(" ... but not really (#{ui.color("dry run", :bold, :yellow)} for server #{name})")
35
- return nil
36
- else
37
- yield
38
- end
39
- end
40
- end
41
-
42
- ComputeBuilder.class_eval do
43
- def new_chef_role(role_name, cluster, facet=nil)
44
- chef_role = Chef::Role.new
45
- chef_role.name role_name
46
- chef_role.description "Ironfan generated role for #{[cluster_name, facet_name].compact.join('-')}" unless chef_role.description
47
- chef_role.instance_eval{ @cluster = cluster; @facet = facet; }
48
- @chef_roles << chef_role
49
- chef_role
50
- end
51
- end
52
-
53
- ServerSlice.class_eval do
54
- include DryRunnable
55
- def sync_roles
56
- step(" syncing cluster and facet roles")
57
- unless_dry_run do
58
- chef_roles.each(&:save)
59
- end
60
- end
61
- end
62
-
63
- #
64
- # Ironfan::Server methods that handle chef actions
65
- #
66
- Server.class_eval do
67
- include DryRunnable
68
-
69
- # The chef client, if it already exists in the server.
70
- # Use the 'ensure' method to create/update it.
71
- def chef_client
72
- return @chef_client unless @chef_client.nil?
73
- @chef_client = cluster.find_client(fullname) || false
74
- end
75
-
76
- # # The chef node, if it already exists in the server.
77
- # # Use the 'ensure' method to create/update it.
78
- # def chef_node
79
- # return @chef_node unless @chef_node.nil?
80
- # @chef_node = cluster.find_node(fullname) || false
81
- # end
82
-
83
- # true if chef client is created and discovered
84
- def chef_client?
85
- chef_client.present?
86
- end
87
-
88
- # true if chef node is created and discovered
89
- def chef_node?
90
- chef_node.present?
91
- end
92
-
93
- def delete_chef
94
- if chef_node then
95
- step(" deleting chef node", :red)
96
- unless_dry_run do
97
- chef_node.destroy
98
- end
99
- @chef_node = nil
100
- end
101
- if chef_client
102
- step(" deleting chef client", :red)
103
- unless_dry_run do
104
- chef_client.destroy
105
- end
106
- @chef_client = nil
107
- end
108
- end
109
-
110
- # creates or updates the chef node.
111
- #
112
- # See notes at top of file for why all this jiggery-fuckery
113
- #
114
- # * client exists, node exists: assume client can update, weep later when
115
- # the initial chef run fails. Not much we can do here -- holler at opscode.
116
- # * client exists, node absent: see if client can create, fail otherwise
117
- # * client absent, node absent: see if client can create both, fail otherwise
118
- # * client absent, node exists: fail (we can't get permissions)
119
- def sync_chef_node
120
- step(" syncing chef node using the server's key")
121
- # force-fetch the node so that we have its full attributes (the discovery
122
- # does not pull all of it back)
123
- @chef_node = handle_chef_response('404'){ Chef::Node.load( fullname ) }
124
- # sets @chef_client if it exists
125
- chef_client
126
- #
127
- case
128
- when @chef_client && @chef_node then _update_chef_node # this will fail later if the chef client is in a bad state but whaddayagonnado
129
- when @chef_client && (! @chef_node) then _create_chef_node
130
- when (! @chef_client) && (! @chef_node) then # create both
131
- ensure_chef_client
132
- _create_chef_node
133
- when (! @chef_client) && @chef_node
134
- 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}")
135
- end
136
- @chef_node
137
- end
138
-
139
- def client_key
140
- @client_key ||= Ironfan::ChefClientKey.new("client-#{fullname}", chef_client) do |body|
141
- chef_client.private_key(body) if chef_client.present? && body.present?
142
- cloud.user_data(:client_key => body)
143
- end
144
- end
145
-
146
- def chef_client_script_content
147
- return @chef_client_script_content if @chef_client_script_content
148
- return unless cloud.chef_client_script
149
- script_filename = File.expand_path("../../config/#{cloud.chef_client_script}", File.dirname(File.realdirpath(__FILE__)))
150
- @chef_client_script_content = safely{ File.read(script_filename) }
151
- end
152
-
153
- def announce_state state
154
- @chef_node.set[:state] = state
155
- end
156
-
157
- protected
158
-
159
- # Create the chef client on the server. Do not call this directly -- go
160
- # through sync_chef_node.
161
- #
162
- # this is done as the eponymous client, ensuring that the client does in
163
- # fact have permissions on the node
164
- #
165
- # preconditions: @chef_node is set
166
- def _create_chef_node(&block)
167
- step(" creating chef node", :green)
168
- @chef_node = Chef::Node.new
169
- @chef_node.name(fullname)
170
- set_chef_node_attributes
171
- set_chef_node_environment
172
- sync_volume_attributes
173
- unless_dry_run do
174
- chef_api_server_as_client.post_rest('nodes', @chef_node)
175
- end
176
- end
177
-
178
- # Update the chef client on the server. Do not call this directly -- go
179
- # through create_or_update_chef_node.
180
- #
181
- # this is done as the eponymous client, ensuring that the client does in
182
- # fact have permissions on the node.
183
- #
184
- # preconditions: @chef_node is set
185
- def _update_chef_node
186
- step(" updating chef node", :blue)
187
- set_chef_node_attributes
188
- set_chef_node_environment
189
- sync_volume_attributes
190
- unless_dry_run do
191
- chef_api_server_as_admin.put_rest("nodes/#{@chef_node.name}", @chef_node)
192
- end
193
- end
194
-
195
- def sync_volume_attributes
196
- volumes.each_pair do |vol_name, vol|
197
- chef_node.normal[:volumes] ||= Mash.new
198
- chef_node.normal[:volumes][vol_name] = vol.attributes.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(*combined_run_list)
205
- @chef_node.normal[:organization] = organization if organization
206
- @chef_node.normal[:permanent] = cloud.permanent if cloud.permanent
207
- @chef_node.normal[:cluster_name] = cluster_name
208
- @chef_node.normal[:facet_name] = facet_name
209
- @chef_node.normal[:facet_index] = facet_index
210
- end
211
-
212
- def set_chef_node_environment
213
- @chef_node.chef_environment(environment.to_s) if environment.present?
214
- end
215
-
216
- #
217
- # Don't call this directly -- only through ensure_chef_node_and_client
218
- #
219
- def ensure_chef_client
220
- step(" ensuring chef client exists")
221
- return @chef_client if chef_client
222
- step( " creating chef client", :green)
223
- @chef_client = Chef::ApiClient.new
224
- @chef_client.name(fullname)
225
- @chef_client.admin(false)
226
- #
227
- # ApiClient#create sends extra params that fail -- we'll do it ourselves
228
- # purposefully *not* catching the 'but it already exists' error: if it
229
- # didn't show up in the discovery process, we're in an inconsistent state
230
- unless_dry_run do
231
- response = chef_api_server_as_admin.post_rest("clients", { 'name' => fullname, 'admin' => false, 'private_key' => true })
232
- client_key.body = response['private_key']
233
- end
234
- client_key.save
235
- @chef_client
236
- end
237
-
238
- def chef_api_server_as_client
239
- return @chef_api_server_as_client if @chef_api_server_as_client
240
- unless File.exists?(client_key.filename)
241
- raise("Cannot create chef node #{fullname} -- client #{@chef_client} exists but no client key found in #{client_key.filename}.")
242
- end
243
- @chef_api_server_as_client = Chef::REST.new(Chef::Config[:chef_server_url], fullname, client_key.filename)
244
- end
245
-
246
- def chef_api_server_as_admin
247
- @chef_api_server_as_admin ||= Chef::REST.new(Chef::Config[:chef_server_url])
248
- end
249
-
250
- # Execute the given chef call, but don't explode if the given http status
251
- # code comes back
252
- #
253
- # @return chef object, or false if the server returned a recoverable response
254
- def handle_chef_response(recoverable_responses, &block)
255
- begin
256
- block.call
257
- rescue Net::HTTPServerException => e
258
- raise unless Array(recoverable_responses).include?(e.response.code)
259
- Chef::Log.debug("Swallowing a #{e.response.code} response in #{self.fullname}: #{e}")
260
- return false
261
- end
262
- end
263
-
264
- #
265
- # The below *was* present but was pulled from the API by opscode for some reason (2011/10/20)
266
- #
267
-
268
- # # The client is required to have these permissions on its eponymous node
269
- # REQUIRED_PERMISSIONS = %w[read create update]
270
- #
271
- # #
272
- # # Verify that the client has required _acl's on the node.
273
- # #
274
- # # We don't raise an error, just a very noisy warning.
275
- # #
276
- # def check_node_permissions
277
- # step(" ensuring chef node permissions are correct")
278
- # chef_server_rest = Chef::REST.new(Chef::Config[:chef_server_url])
279
- # handle_chef_response('404') do
280
- # perms = chef_server_rest.get_rest("nodes/#{fullname}/_acl")
281
- # perms_valid = {}
282
- # REQUIRED_PERMISSIONS.each{|perm| perms_valid[perm] = perms[perm] && perms[perm]['actors'].include?(fullname) }
283
- # Chef::Log.debug("Checking permissions: #{perms_valid.inspect} -- #{ perms_valid.values.all? ? 'correct' : 'BADNESS' }")
284
- # unless perms_valid.values.all?
285
- # ui.info(" ************************ ")
286
- # ui.info(" ")
287
- # ui.info(" INCONSISTENT PERMISSIONS for node #{fullname}:")
288
- # ui.info(" The client[#{fullname}] should have permissions for #{REQUIRED_PERMISSIONS.join(', ')}")
289
- # ui.info(" Instead, they are #{perms_valid.inspect}")
290
- # ui.info(" You should create the node #{fullname} as client[#{fullname}], not as yourself.")
291
- # ui.info(" ")
292
- # ui.info(" Please adjust the permissions on the Opscode console, at")
293
- # ui.info(" https://manage.opscode.com/nodes/#{fullname}/_acl")
294
- # ui.info(" ")
295
- # ui.info(" ************************ ")
296
- # end
297
- # end
298
- # end
299
- end
300
- end
data/lib/ironfan/cloud.rb DELETED
@@ -1,323 +0,0 @@
1
- require 'ironfan/private_key'
2
-
3
- module Ironfan
4
- module CloudDsl
5
- class Base < Ironfan::DslBuilder
6
- magic :bootstrap_distro, String, :default => "ubuntu10.04-gems"
7
- magic :chef_client_script, String
8
- magic :flavor, String
9
- magic :flavor_info, Array
10
- magic :image_name, String
11
- magic :ssh_user, String, :default => 'root'
12
-
13
- magic :owner, Whatever
14
-
15
- def initialize(container, *args)
16
- owner container
17
- super(*args)
18
- end
19
-
20
- def to_hash
21
- Chef::Log.warn("Using to_hash is depreciated, use attributes instead")
22
- attributes
23
- end
24
-
25
- # Stub to be filled by child classes
26
- def defaults
27
- end
28
-
29
- # # TODO: Replace the lambda with an underlay from image_info?
30
- # magic :image_id, String, :default => lambda { image_info[:image_id] unless image_info.nil? }
31
- def image_id
32
- return @image_id if @image_id
33
- image_info[:image_id] unless image_info.nil?
34
- end
35
- ## TODO: Replace with code that will assume ssh_identity_dir if ssh_identity_file isn't absolutely pathed
36
- # # SSH identity file used for knife ssh, knife boostrap and such
37
- # def ssh_identity_file(val=nil)
38
- # set :ssh_identity_file, File.expand_path(val) unless val.nil?
39
- # @settings.include?(:ssh_identity_file) ? @settings[:ssh_identity_file] : File.join(ssh_identity_dir, "#{keypair}.pem")
40
- # end
41
- end
42
-
43
- class Ec2 < Base
44
- #
45
- # To add to this list, use this snippet:
46
- #
47
- # Chef::Config[:ec2_image_info] ||= {}
48
- # Chef::Config[:ec2_image_info].merge!({
49
- # # ... lines like the below
50
- # })
51
- #
52
- # in your knife.rb or whereever. We'll notice that it exists and add to it, rather than clobbering it.
53
- #
54
- Chef::Config[:ec2_image_info] ||= {}
55
- Chef::Config[:ec2_image_info].merge!({
56
-
57
- #
58
- # Lucid (Ubuntu 9.10)
59
- #
60
- %w[us-east-1 64-bit instance karmic ] => { :image_id => 'ami-55739e3c', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
61
- %w[us-east-1 32-bit instance karmic ] => { :image_id => 'ami-bb709dd2', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
62
- %w[us-west-1 64-bit instance karmic ] => { :image_id => 'ami-cb2e7f8e', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
63
- %w[us-west-1 32-bit instance karmic ] => { :image_id => 'ami-c32e7f86', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
64
- %w[eu-west-1 64-bit instance karmic ] => { :image_id => 'ami-05c2e971', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
65
- %w[eu-west-1 32-bit instance karmic ] => { :image_id => 'ami-2fc2e95b', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
66
-
67
- #
68
- # Lucid (Ubuntu 10.04.3)
69
- #
70
- %w[ap-southeast-1 64-bit ebs lucid ] => { :image_id => 'ami-77f28d25', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
71
- %w[ap-southeast-1 32-bit ebs lucid ] => { :image_id => 'ami-4df28d1f', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
72
- %w[ap-southeast-1 64-bit instance lucid ] => { :image_id => 'ami-57f28d05', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
73
- %w[ap-southeast-1 32-bit instance lucid ] => { :image_id => 'ami-a5f38cf7', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
74
- %w[eu-west-1 64-bit ebs lucid ] => { :image_id => 'ami-ab4d67df', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
75
- %w[eu-west-1 32-bit ebs lucid ] => { :image_id => 'ami-a94d67dd', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
76
- %w[eu-west-1 64-bit instance lucid ] => { :image_id => 'ami-a54d67d1', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
77
- %w[eu-west-1 32-bit instance lucid ] => { :image_id => 'ami-cf4d67bb', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
78
- #
79
- %w[us-east-1 64-bit ebs lucid ] => { :image_id => 'ami-4b4ba522', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
80
- %w[us-east-1 32-bit ebs lucid ] => { :image_id => 'ami-714ba518', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
81
- %w[us-east-1 64-bit instance lucid ] => { :image_id => 'ami-fd4aa494', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
82
- %w[us-east-1 32-bit instance lucid ] => { :image_id => 'ami-2d4aa444', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
83
- #
84
- %w[us-west-1 64-bit ebs lucid ] => { :image_id => 'ami-d197c694', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
85
- %w[us-west-1 32-bit ebs lucid ] => { :image_id => 'ami-cb97c68e', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
86
- %w[us-west-1 64-bit instance lucid ] => { :image_id => 'ami-c997c68c', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
87
- %w[us-west-1 32-bit instance lucid ] => { :image_id => 'ami-c597c680', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
88
-
89
- #
90
- # Maverick (Ubuntu 10.10)
91
- #
92
- %w[ ap-southeast-1 64-bit ebs maverick ] => { :image_id => 'ami-32423c60', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
93
- %w[ ap-southeast-1 64-bit instance maverick ] => { :image_id => 'ami-12423c40', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
94
- %w[ ap-southeast-1 32-bit ebs maverick ] => { :image_id => 'ami-0c423c5e', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
95
- %w[ ap-southeast-1 32-bit instance maverick ] => { :image_id => 'ami-7c423c2e', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
96
- #
97
- %w[ eu-west-1 64-bit ebs maverick ] => { :image_id => 'ami-e59ca991', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
98
- %w[ eu-west-1 64-bit instance maverick ] => { :image_id => 'ami-1b9ca96f', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
99
- %w[ eu-west-1 32-bit ebs maverick ] => { :image_id => 'ami-fb9ca98f', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
100
- %w[ eu-west-1 32-bit instance maverick ] => { :image_id => 'ami-339ca947', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
101
- #
102
- %w[ us-east-1 64-bit ebs maverick ] => { :image_id => 'ami-cef405a7', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
103
- %w[ us-east-1 64-bit instance maverick ] => { :image_id => 'ami-08f40561', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
104
- %w[ us-east-1 32-bit ebs maverick ] => { :image_id => 'ami-ccf405a5', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
105
- %w[ us-east-1 32-bit instance maverick ] => { :image_id => 'ami-a6f504cf', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
106
- #
107
- %w[ us-west-1 64-bit ebs maverick ] => { :image_id => 'ami-af7e2eea', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
108
- %w[ us-west-1 64-bit instance maverick ] => { :image_id => 'ami-a17e2ee4', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
109
- %w[ us-west-1 32-bit ebs maverick ] => { :image_id => 'ami-ad7e2ee8', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
110
- %w[ us-west-1 32-bit instance maverick ] => { :image_id => 'ami-957e2ed0', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
111
-
112
- #
113
- # Natty (Ubuntu 11.04)
114
- #
115
- %w[ ap-northeast-1 32-bit ebs natty ] => { :image_id => 'ami-00b10501', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
116
- %w[ ap-northeast-1 32-bit instance natty ] => { :image_id => 'ami-f0b004f1', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
117
- %w[ ap-northeast-1 64-bit ebs natty ] => { :image_id => 'ami-02b10503', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
118
- %w[ ap-northeast-1 64-bit instance natty ] => { :image_id => 'ami-fab004fb', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
119
- #
120
- %w[ ap-southeast-1 32-bit ebs natty ] => { :image_id => 'ami-06255f54', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
121
- %w[ ap-southeast-1 32-bit instance natty ] => { :image_id => 'ami-72255f20', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
122
- %w[ ap-southeast-1 64-bit ebs natty ] => { :image_id => 'ami-04255f56', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
123
- %w[ ap-southeast-1 64-bit instance natty ] => { :image_id => 'ami-7a255f28', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
124
- #
125
- %w[ eu-west-1 32-bit ebs natty ] => { :image_id => 'ami-a4f7c5d0', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
126
- %w[ eu-west-1 32-bit instance natty ] => { :image_id => 'ami-fef7c58a', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
127
- %w[ eu-west-1 64-bit ebs natty ] => { :image_id => 'ami-a6f7c5d2', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
128
- %w[ eu-west-1 64-bit instance natty ] => { :image_id => 'ami-c0f7c5b4', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
129
- #
130
- %w[ us-east-1 32-bit ebs natty ] => { :image_id => 'ami-e358958a', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
131
- %w[ us-east-1 32-bit instance natty ] => { :image_id => 'ami-c15994a8', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
132
- %w[ us-east-1 64-bit ebs natty ] => { :image_id => 'ami-fd589594', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
133
- %w[ us-east-1 64-bit instance natty ] => { :image_id => 'ami-71589518', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
134
- #
135
- %w[ us-west-1 32-bit ebs natty ] => { :image_id => 'ami-43580406', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
136
- %w[ us-west-1 32-bit instance natty ] => { :image_id => 'ami-e95f03ac', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
137
- %w[ us-west-1 64-bit ebs natty ] => { :image_id => 'ami-4d580408', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
138
- %w[ us-west-1 64-bit instance natty ] => { :image_id => 'ami-a15f03e4', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
139
-
140
- #
141
- # Cluster Compute
142
- #
143
- # IMAGE ami-6d2ce204 205199409180/Globus Provision 0.4.AMI (Ubuntu 11.04 HVM) 205199409180 available public x86_64 machine ebs hvm xen
144
- #
145
- %w[ us-east-1 64-bit ebs natty-cc ] => { :image_id => 'ami-6d2ce204', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
146
-
147
- #
148
- # Oneiric (Ubuntu 11.10)
149
- #
150
- %w[ ap-northeast-1 32-bit ebs oneiric ] => { :image_id => 'ami-84902785', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
151
- %w[ ap-northeast-1 32-bit instance oneiric ] => { :image_id => 'ami-5e90275f', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
152
- %w[ ap-northeast-1 64-bit ebs oneiric ] => { :image_id => 'ami-88902789', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
153
- %w[ ap-northeast-1 64-bit instance oneiric ] => { :image_id => 'ami-7c90277d', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
154
- #
155
- %w[ ap-southeast-1 32-bit ebs oneiric ] => { :image_id => 'ami-0a327758', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
156
- %w[ ap-southeast-1 32-bit instance oneiric ] => { :image_id => 'ami-00327752', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
157
- %w[ ap-southeast-1 64-bit ebs oneiric ] => { :image_id => 'ami-0832775a', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
158
- %w[ ap-southeast-1 64-bit instance oneiric ] => { :image_id => 'ami-04327756', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
159
- #
160
- %w[ eu-west-1 32-bit ebs oneiric ] => { :image_id => 'ami-11f0cc65', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
161
- %w[ eu-west-1 32-bit instance oneiric ] => { :image_id => 'ami-4ff0cc3b', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
162
- %w[ eu-west-1 64-bit ebs oneiric ] => { :image_id => 'ami-1df0cc69', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
163
- %w[ eu-west-1 64-bit instance oneiric ] => { :image_id => 'ami-23f0cc57', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
164
- #
165
- %w[ us-east-1 32-bit ebs oneiric ] => { :image_id => 'ami-a562a9cc', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
166
- %w[ us-east-1 32-bit instance oneiric ] => { :image_id => 'ami-3962a950', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
167
- %w[ us-east-1 64-bit ebs oneiric ] => { :image_id => 'ami-bf62a9d6', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
168
- %w[ us-east-1 64-bit instance oneiric ] => { :image_id => 'ami-c162a9a8', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
169
- #
170
- %w[ us-west-1 32-bit ebs oneiric ] => { :image_id => 'ami-c9a1fe8c', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
171
- %w[ us-west-1 32-bit instance oneiric ] => { :image_id => 'ami-21a1fe64', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
172
- %w[ us-west-1 64-bit ebs oneiric ] => { :image_id => 'ami-cba1fe8e', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
173
- %w[ us-west-1 64-bit instance oneiric ] => { :image_id => 'ami-3fa1fe7a', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
174
- #
175
- %w[ us-west-2 32-bit ebs oneiric ] => { :image_id => 'ami-ea9a17da', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
176
- %w[ us-west-2 32-bit instance oneiric ] => { :image_id => 'ami-f49a17c4', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
177
- %w[ us-west-2 64-bit ebs oneiric ] => { :image_id => 'ami-ec9a17dc', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
178
- %w[ us-west-2 64-bit instance oneiric ] => { :image_id => 'ami-fe9a17ce', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
179
- })
180
-
181
- magic :availability_zones, Array, :default => ['us-east-1d']
182
- magic :backing, String, :default => 'ebs'
183
- magic :ec2_image_info, Hash, :default => Chef::Config[:ec2_image_info]
184
- magic :flavor, String, :default => 't1.micro'
185
- magic :image_name, String, :default => 'natty'
186
- magic :keypair, Whatever
187
- magic :monitoring, String
188
- magic :permanent, String
189
- magic :public_ip, String
190
- magic :region, String,
191
- :default => ->{ default_availability_zone.gsub(/^(\w+-\w+-\d)[a-z]/, '\1') if default_availability_zone }
192
- collection :security_groups, Ironfan::CloudDsl::SecurityGroup, :resolution => ->(f){ merge_resolve(f) }
193
- magic :ssh_user, String, :default => 'ubuntu'
194
- magic :ssh_identity_dir, String, :default => Chef::Config.ec2_key_dir
195
- magic :ssh_identity_file, String #, :default => "#{keypair}.pem"
196
- magic :subnet, String
197
- magic :user_data, Hash, :default => {}
198
- magic :validation_key, String, :default => IO.read(Chef::Config.validation_key) rescue ''
199
- magic :vpc, String
200
-
201
- def list_images
202
- ui.info("Available images:")
203
- ec2_image_info.each do |flavor_name, flavor|
204
- ui.info(" %-55s\t%s" % [flavor_name, flavor.inspect])
205
- end
206
- end
207
-
208
- def default_availability_zone
209
- availability_zones.first if availability_zones
210
- end
211
-
212
- # Bring the ephemeral storage (local scratch disks) online
213
- def mount_ephemerals(attrs={})
214
- 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
215
- 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
216
- 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
217
- 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
218
- end
219
-
220
- def image_info
221
- 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, virtualization].inspect})" ; {} )
222
- end
223
-
224
- # EC2 User data -- DNA typically used to bootstrap the machine.
225
- # @param [Hash] value -- when present, merged with the existing user data (overriding it)
226
- # @return the user_data hash
227
- def user_data(hsh={})
228
- result = read_attribute(:user_data)
229
- write_attribute(:user_data, result.merge!(hsh.to_hash)) unless hsh.empty?
230
- result
231
- end
232
-
233
- # Sets default root volume for AWS
234
- def defaults
235
- owner.volume(:root).receive!({
236
- :device => '/dev/sda1',
237
- :mount_point => '/',
238
- :mountable => false,
239
- })
240
- super
241
- end
242
-
243
- # The instance bitness, drawn from the compute flavor's info
244
- def bits
245
- flavor_info[:bits]
246
- end
247
-
248
- def virtualization
249
- flavor_info[:virtualization] || 'pv'
250
- end
251
-
252
- def flavor_info
253
- if flavor && (not FLAVOR_INFO.has_key?(flavor))
254
- ui.warn("Unknown machine image flavor '#{val}'")
255
- list_flavors
256
- return nil
257
- end
258
- FLAVOR_INFO[flavor]
259
- end
260
-
261
- def list_flavors
262
- ui.info("Available flavors:")
263
- FLAVOR_INFO.each do |flavor_name, flavor|
264
- ui.info(" #{flavor_name}\t#{flavor.inspect}")
265
- end
266
- end
267
-
268
- # code $/mo $/day $/hr CPU/$ Mem/$ mem cpu cores cpcore storage bits IO type name
269
- # t1.micro 15 0.48 .02 13 13 0.61 0.25 0.25 1 0 32 Low Micro Micro
270
- # m1.small 58 1.92 .08 13 21 1.7 1 1 1 160 32 Moderate Standard Small
271
- # m1.medium 116 3.84 .165 13 13 3.75 2 2 1 410 32 Moderate Standard Medium
272
- # c1.medium 120 3.96 .17 30 10 1.7 5 2 2.5 350 32 Moderate High-CPU Medium
273
- # m1.large 232 7.68 .32 13 23 7.5 4 2 2 850 64 High Standard Large
274
- # m2.xlarge 327 10.80 .45 14 38 17.1 6.5 2 3.25 420 64 Moderate High-Memory Extra Large
275
- # m1.xlarge 465 15.36 .64 13 23 15 8 4 2 1690 64 High Standard Extra Large
276
- # c1.xlarge 479 15.84 .66 30 11 7 20 8 2.5 1690 64 High High-CPU Extra Large
277
- # m2.2xlarge 653 21.60 .90 14 38 34.2 13 4 3.25 850 64 High High-Memory Double Extra Large
278
- # m2.4xlarge 1307 43.20 1.80 14 38 68.4 26 8 3.25 1690 64 High High-Memory Quadruple Extra Large
279
- # cc1.4xlarge 944 31.20 1.30 26 18 23 33.5 8 4.19 1690 64 10GB Compute Quadruple Extra Large
280
- # cc2.8xlarge 1742 57.60 2.40 37 25 60.5 88 16 5.50 3370 64 Very High 10GB Compute Eight Extra Large
281
- # cg1.4xlarge 1525 50.40 2.10 16 10 22 33.5 8 4.19 1690 64 Very High 10GB Cluster GPU Quadruple Extra Large
282
-
283
- FLAVOR_INFO = {
284
- '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 },
285
- 'm1.small' => { :price => 0.08, :bits => '64-bit', :ram => 1740, :cores => 1, :core_size => 1, :inst_disks => 1, :inst_disk_size => 160, :ephemeral_volumes => 1 },
286
- 'm1.medium' => { :price => 0.165, :bits => '32-bit', :ram => 3840, :cores => 2, :core_size => 1, :inst_disks => 1, :inst_disk_size => 410, :ephemeral_volumes => 1 },
287
- '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 },
288
- 'm1.large' => { :price => 0.32, :bits => '64-bit', :ram => 7680, :cores => 2, :core_size => 2, :inst_disks => 2, :inst_disk_size => 850, :ephemeral_volumes => 2 },
289
- 'm2.xlarge' => { :price => 0.45, :bits => '64-bit', :ram => 18124, :cores => 2, :core_size => 3.25, :inst_disks => 1, :inst_disk_size => 420, :ephemeral_volumes => 1 },
290
- 'c1.xlarge' => { :price => 0.64, :bits => '64-bit', :ram => 7168, :cores => 8, :core_size => 2.5, :inst_disks => 4, :inst_disk_size => 1690, :ephemeral_volumes => 4 },
291
- 'm1.xlarge' => { :price => 0.66, :bits => '64-bit', :ram => 15360, :cores => 4, :core_size => 2, :inst_disks => 4, :inst_disk_size => 1690, :ephemeral_volumes => 4 },
292
- 'm2.2xlarge' => { :price => 0.90, :bits => '64-bit', :ram => 35020, :cores => 4, :core_size => 3.25, :inst_disks => 2, :inst_disk_size => 850, :ephemeral_volumes => 2 },
293
- 'm2.4xlarge' => { :price => 1.80, :bits => '64-bit', :ram => 70041, :cores => 8, :core_size => 3.25, :inst_disks => 4, :inst_disk_size => 1690, :ephemeral_volumes => 4 },
294
- 'cc1.4xlarge' => { :price => 1.30, :bits => '64-bit', :ram => 23552, :cores => 8, :core_size => 4.19, :inst_disks => 4, :inst_disk_size => 1690, :ephemeral_volumes => 2, :placement_groupable => true, :virtualization => 'hvm' },
295
- 'cc1.8xlarge' => { :price => 2.40, :bits => '64-bit', :ram => 61952, :cores =>16, :core_size => 5.50, :inst_disks => 8, :inst_disk_size => 3370, :ephemeral_volumes => 4, :placement_groupable => true, :virtualization => 'hvm' },
296
- 'cg1.4xlarge' => { :price => 2.10, :bits => '64-bit', :ram => 22528, :cores => 8, :core_size => 4.19, :inst_disks => 4, :inst_disk_size => 1690, :ephemeral_volumes => 2, :placement_groupable => true, :virtualization => 'hvm' },
297
- }
298
- end
299
-
300
- class VirtualBox < Base
301
- # # These fields are probably nonsense in VirtualBox
302
- # magic :availability_zones, String
303
- # magic :backing, String
304
- # magic :default_availability_zone, String
305
- # magic :flavor_info, Array, :default => { :placement_groupable => false }
306
- # magic :keypair, Ironfan::PrivateKey
307
- # magic :monitoring, String
308
- # magic :permanent, String
309
- # magic :public_ip, String
310
- # magic :security_groups, Array, :default => { :keys => nil }
311
- # magic :subnet, String
312
- # magic :user_data, String
313
- # magic :validation_key, String
314
- # magic :vpc, String
315
-
316
- def initialize(*args)
317
- Chef::Log.warn("Several fields (e.g. - availability_zones, backing, mount_ephemerals, etc.) are nonsense in VirtualBox context")
318
- super(*args)
319
- end
320
- end
321
-
322
- end
323
- end