poolparty 1.6.8 → 1.6.9
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/Rakefile +12 -2
- data/VERSION.yml +2 -1
- data/bin/cloud +4 -1
- data/bin/cloud-run +2 -2
- data/bin/cloud-show +11 -10
- data/lib/cloud_providers/connections.rb +4 -2
- data/lib/cloud_providers/ec2/ec2.rb +58 -39
- data/lib/cloud_providers/ec2/ec2_instance.rb +50 -40
- data/lib/cloud_providers/ec2/helpers/authorize.rb +8 -3
- data/lib/cloud_providers/ec2/helpers/elastic_auto_scaler.rb +7 -4
- data/lib/cloud_providers/ec2/helpers/revoke.rb +5 -5
- data/lib/cloud_providers/ec2/helpers/security_group.rb +29 -32
- data/lib/cloud_providers/remote_instance.rb.orig +162 -0
- data/lib/core/object.rb +16 -1
- data/lib/keypair.rb +21 -21
- data/lib/poolparty/chef.rb +71 -6
- data/lib/poolparty/chef_client.rb +6 -2
- data/lib/poolparty/chef_solo.rb +18 -2
- data/lib/poolparty/cloud.rb +13 -0
- data/lib/poolparty/cloud.rb.orig +432 -0
- data/lib/poolparty/pool.rb +36 -2
- metadata +7 -12
data/Rakefile
CHANGED
|
@@ -14,7 +14,17 @@ require 'config/jeweler' # setup gem configuration
|
|
|
14
14
|
|
|
15
15
|
task :default => [:test, :cleanup_test]
|
|
16
16
|
desc "Update vendor directory and run tests"
|
|
17
|
-
|
|
17
|
+
|
|
18
|
+
namespace :poolparty do
|
|
19
|
+
namespace :vendor do
|
|
20
|
+
desc "Fetch all the submodules"
|
|
21
|
+
task :submodules do
|
|
22
|
+
`git submodule update`
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
task :vendor => ["poolparty:vendor:submodules"]
|
|
18
28
|
|
|
19
29
|
task :cleanup_test do
|
|
20
30
|
::FileUtils.rm_rf "/tmp/poolparty"
|
|
@@ -83,4 +93,4 @@ Rake::RDocTask.new do |rd|
|
|
|
83
93
|
rd.rdoc_files.include("README.rdoc", "lib/**/*.rb")
|
|
84
94
|
rd.rdoc_dir = "rdoc"
|
|
85
95
|
# rd.template = "hanaa"
|
|
86
|
-
end
|
|
96
|
+
end
|
data/VERSION.yml
CHANGED
data/bin/cloud
CHANGED
|
@@ -23,6 +23,7 @@ EOS
|
|
|
23
23
|
opt :debug, "Debug the output", :type => :boolean, :default => false
|
|
24
24
|
opt :very_debug, "Set very debug mode on", :type => :boolean, :default => false
|
|
25
25
|
opt :name, "Name of the working cloud", :type => String, :default => nil
|
|
26
|
+
opt :chef_task, "Name of chef task to execute", :type => String, :default => 'default'
|
|
26
27
|
|
|
27
28
|
before_run do |command|
|
|
28
29
|
# Setup testing/debugging
|
|
@@ -38,9 +39,11 @@ EOS
|
|
|
38
39
|
exit
|
|
39
40
|
end
|
|
40
41
|
|
|
42
|
+
pool.chef_step command[:chef_task].to_sym
|
|
43
|
+
|
|
41
44
|
@loaded_pool = pool
|
|
42
45
|
@loaded_clouds = command[:name] ? [pool.clouds[command[:name]]] : pool.clouds.map {|name,cld|cld}
|
|
43
|
-
if @loaded_clouds.
|
|
46
|
+
if @loaded_clouds.size == 0
|
|
44
47
|
puts "No clouds loaded. Check your clouds.rb or -n option"
|
|
45
48
|
exit
|
|
46
49
|
end
|
data/bin/cloud-run
CHANGED
data/bin/cloud-show
CHANGED
|
@@ -6,8 +6,8 @@ require 'git-style-binary/command'
|
|
|
6
6
|
|
|
7
7
|
GitStyleBinary.command do
|
|
8
8
|
@theme = :short
|
|
9
|
-
|
|
10
|
-
version "PoolParty #{$0} command"
|
|
9
|
+
|
|
10
|
+
version "PoolParty #{$0} command"
|
|
11
11
|
banner <<-EOS
|
|
12
12
|
Usage: #{$0} #{all_options_string}
|
|
13
13
|
|
|
@@ -20,7 +20,7 @@ EOS
|
|
|
20
20
|
run do |command|
|
|
21
21
|
|
|
22
22
|
@loaded_clouds.each do |cld|
|
|
23
|
-
|
|
23
|
+
|
|
24
24
|
msg = [
|
|
25
25
|
"Cloud: #{cld.name}",
|
|
26
26
|
"----------------------------",
|
|
@@ -29,11 +29,12 @@ EOS
|
|
|
29
29
|
"Maximum instances: #{cld.maximum_instances}",
|
|
30
30
|
"Running on: #{cld.cloud_provider.name}",
|
|
31
31
|
"Keypair: #{cld.keypair.basename}",
|
|
32
|
-
"Security group: #{cld.cloud_provider.security_group_names}",
|
|
33
|
-
"Availability zones: #{cld.cloud_provider.availability_zones}",
|
|
34
|
-
"User:
|
|
32
|
+
"Security group: #{cld.cloud_provider.security_group_names.join(', ')}",
|
|
33
|
+
"Availability zones: #{cld.cloud_provider.availability_zones.join(', ')}",
|
|
34
|
+
"User: #{cld.user}",
|
|
35
|
+
"Active recipes: #{cld.chef._recipes(cld.pool.chef_step).join ", " }"
|
|
35
36
|
]
|
|
36
|
-
|
|
37
|
+
|
|
37
38
|
if cld.load_balancers.size > 0
|
|
38
39
|
load_balancers = cld.cloud_provider.load_balancers.first.running_load_balancers.map {|a| a[:dns_name]}
|
|
39
40
|
msg << "Load balancers: #{load_balancers.join("\n\t\t\t")}"
|
|
@@ -45,10 +46,10 @@ EOS
|
|
|
45
46
|
|
|
46
47
|
msg << available.join("\n\t\t\t")
|
|
47
48
|
end
|
|
48
|
-
|
|
49
|
+
|
|
49
50
|
puts msg.flatten
|
|
50
|
-
|
|
51
|
+
|
|
51
52
|
end
|
|
52
|
-
|
|
53
|
+
|
|
53
54
|
end
|
|
54
55
|
end
|
|
@@ -108,7 +108,7 @@ module CloudProviders
|
|
|
108
108
|
rsync_opts += %q% --rsync-path="sudo rsync"% unless user=="root"
|
|
109
109
|
rsync_opts += %q% --exclude=.svn --exclude=.git --exclude=.cvs %
|
|
110
110
|
cmd_string = "rsync -L -e 'ssh #{ssh_options}' #{rsync_opts} #{opts[:source]} #{user}@#{host}:#{destination_path}"
|
|
111
|
-
out = system_run(cmd_string)
|
|
111
|
+
out = system_run(cmd_string, :quiet => true)
|
|
112
112
|
out
|
|
113
113
|
end
|
|
114
114
|
|
|
@@ -137,7 +137,9 @@ module CloudProviders
|
|
|
137
137
|
while (chunk = stdin.readpartial(opts[:sysread]))
|
|
138
138
|
buf << chunk
|
|
139
139
|
unless chunk.nil? || chunk.empty?
|
|
140
|
-
|
|
140
|
+
if not opts[:quiet]
|
|
141
|
+
$stdout.write(chunk) #if debugging? || verbose?
|
|
142
|
+
end
|
|
141
143
|
end
|
|
142
144
|
end
|
|
143
145
|
err = stderr.readlines
|
|
@@ -10,37 +10,39 @@ rescue LoadError
|
|
|
10
10
|
EOM
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
+
require 'pp'
|
|
14
|
+
|
|
13
15
|
module CloudProviders
|
|
14
16
|
class Ec2 < CloudProvider
|
|
15
17
|
# Set the aws keys from the environment, or load from /etc/poolparty/env.yml if the environment variable is not set
|
|
16
18
|
def self.default_access_key
|
|
17
19
|
ENV['EC2_ACCESS_KEY'] || load_keys_from_file[:access_key] || load_keys_from_credential_file[:access_key]
|
|
18
20
|
end
|
|
19
|
-
|
|
21
|
+
|
|
20
22
|
def self.default_secret_access_key
|
|
21
23
|
ENV['EC2_SECRET_KEY'] || load_keys_from_file[:secret_access_key] || load_keys_from_credential_file[:secret_access_key]
|
|
22
24
|
end
|
|
23
|
-
|
|
25
|
+
|
|
24
26
|
def self.default_private_key
|
|
25
27
|
ENV['EC2_PRIVATE_KEY'] || load_keys_from_file[:private_key]
|
|
26
28
|
end
|
|
27
|
-
|
|
29
|
+
|
|
28
30
|
def self.default_cert
|
|
29
31
|
ENV['EC2_CERT'] || load_keys_from_file[:cert]
|
|
30
32
|
end
|
|
31
|
-
|
|
33
|
+
|
|
32
34
|
def self.default_user_id
|
|
33
35
|
ENV['EC2_USER_ID'] || load_keys_from_file[:user_id]
|
|
34
36
|
end
|
|
35
|
-
|
|
37
|
+
|
|
36
38
|
def self.default_ec2_url
|
|
37
39
|
ENV['EC2_URL'] || load_keys_from_file[:ec2_url]
|
|
38
40
|
end
|
|
39
|
-
|
|
41
|
+
|
|
40
42
|
def self.default_s3_url
|
|
41
43
|
ENV['S3_URL'] || load_keys_from_file[:s3_url]
|
|
42
44
|
end
|
|
43
|
-
|
|
45
|
+
|
|
44
46
|
def self.default_cloud_cert
|
|
45
47
|
ENV['CLOUD_CERT'] || ENV['EUCALYPTUS_CERT'] || load_keys_from_file[:cloud_cert]
|
|
46
48
|
end
|
|
@@ -48,7 +50,7 @@ module CloudProviders
|
|
|
48
50
|
def self.default_credential_file
|
|
49
51
|
ENV['AWS_CREDENTIAL_FILE'] || load_keys_from_file[:credential_file]
|
|
50
52
|
end
|
|
51
|
-
|
|
53
|
+
|
|
52
54
|
# Load the yaml file containing keys. If the file does not exist, return an empty hash
|
|
53
55
|
def self.load_keys_from_file(filename="#{ENV["HOME"]}/.poolparty/aws", caching=true)
|
|
54
56
|
return @aws_yml if @aws_yml && caching==true
|
|
@@ -71,8 +73,8 @@ module CloudProviders
|
|
|
71
73
|
}
|
|
72
74
|
return {:access_key => @access_key, :secret_access_key => @secret_access_key}
|
|
73
75
|
end
|
|
74
|
-
|
|
75
|
-
|
|
76
|
+
|
|
77
|
+
|
|
76
78
|
default_options(
|
|
77
79
|
:instance_type => 'm1.small',
|
|
78
80
|
:availability_zones => ["us-east-1a"],
|
|
@@ -84,7 +86,7 @@ module CloudProviders
|
|
|
84
86
|
:secret_access_key => default_secret_access_key,
|
|
85
87
|
:ec2_url => default_ec2_url,
|
|
86
88
|
:s3_url => default_s3_url,
|
|
87
|
-
:credential_file
|
|
89
|
+
:credential_file => default_credential_file,
|
|
88
90
|
:min_count => 1,
|
|
89
91
|
:max_count => 1,
|
|
90
92
|
:user_data => '',
|
|
@@ -109,6 +111,7 @@ module CloudProviders
|
|
|
109
111
|
puts " maximum_instances: #{maximum_instances}"
|
|
110
112
|
puts " security_groups: #{security_group_names.join(", ")}"
|
|
111
113
|
puts " using keypair: #{keypair}"
|
|
114
|
+
puts " with user_data #{user_data.to_s[0..100]}"
|
|
112
115
|
puts " user: #{user}\n"
|
|
113
116
|
|
|
114
117
|
security_groups.each do |sg|
|
|
@@ -152,7 +155,7 @@ module CloudProviders
|
|
|
152
155
|
puts " autoscaler: #{a.name}"
|
|
153
156
|
puts "-----> The autoscaling groups will launch the instances"
|
|
154
157
|
a.run
|
|
155
|
-
|
|
158
|
+
|
|
156
159
|
progress_bar_until("Waiting for autoscaler to launch instances") do
|
|
157
160
|
reset!
|
|
158
161
|
running_nodes = nodes.select {|n| n.running? }
|
|
@@ -161,8 +164,8 @@ module CloudProviders
|
|
|
161
164
|
reset!
|
|
162
165
|
end
|
|
163
166
|
end
|
|
164
|
-
|
|
165
|
-
from_ports = security_groups.map {|a| a.authorizes.map {|t| t.from_port.to_i }.flatten }.flatten
|
|
167
|
+
|
|
168
|
+
from_ports = security_groups.map {|a| a.authorizes.map {|t| t.from_port.to_i }.flatten }.flatten
|
|
166
169
|
if from_ports.include?(22)
|
|
167
170
|
progress_bar_until("Waiting for the instances to be accessible by ssh") do
|
|
168
171
|
running_nodes = nodes.select {|n| n.running? }
|
|
@@ -172,20 +175,20 @@ module CloudProviders
|
|
|
172
175
|
accessible_count == running_nodes.size
|
|
173
176
|
end
|
|
174
177
|
end
|
|
175
|
-
|
|
178
|
+
|
|
176
179
|
assign_elastic_ips
|
|
177
180
|
cleanup_ssh_known_hosts!
|
|
178
181
|
puts "Attaching EBS volumes"
|
|
179
182
|
assign_ebs_volumes # Assign EBS volumes
|
|
180
183
|
end
|
|
181
|
-
|
|
184
|
+
|
|
182
185
|
def teardown
|
|
183
186
|
puts "------ Tearing down and cleaning up #{cloud.name} cloud"
|
|
184
187
|
unless autoscalers.empty?
|
|
185
188
|
puts "Tearing down autoscalers"
|
|
186
189
|
end
|
|
187
190
|
end
|
|
188
|
-
|
|
191
|
+
|
|
189
192
|
def expand_by(num=1)
|
|
190
193
|
e = Ec2Instance.run!({
|
|
191
194
|
:image_id => image_id,
|
|
@@ -208,7 +211,7 @@ module CloudProviders
|
|
|
208
211
|
end
|
|
209
212
|
all_nodes.detect {|n| n.instance_id == e.instance_id }
|
|
210
213
|
end
|
|
211
|
-
|
|
214
|
+
|
|
212
215
|
def decoded_user_data
|
|
213
216
|
if user_data
|
|
214
217
|
if File.file?(user_data)
|
|
@@ -218,13 +221,13 @@ module CloudProviders
|
|
|
218
221
|
end
|
|
219
222
|
end
|
|
220
223
|
end
|
|
221
|
-
|
|
224
|
+
|
|
222
225
|
def wait_for_node(instance)
|
|
223
226
|
reset!
|
|
224
227
|
inst = all_nodes.detect {|n| n.instance_id == instance.instance_id }
|
|
225
228
|
inst.running? if inst
|
|
226
229
|
end
|
|
227
|
-
|
|
230
|
+
|
|
228
231
|
def contract_by(num=1)
|
|
229
232
|
raise RuntimeError, "Contracting instances by #{num} will lower the number of instances below specified minimum" unless nodes.size - num > minimum_instances
|
|
230
233
|
num.times do |i|
|
|
@@ -235,9 +238,9 @@ module CloudProviders
|
|
|
235
238
|
end
|
|
236
239
|
reset!
|
|
237
240
|
end
|
|
238
|
-
|
|
241
|
+
|
|
239
242
|
def bootstrap_nodes!(tmp_path=nil)
|
|
240
|
-
unless security_groups.map {|a| a.authorizes.map {|t| t.from_port.to_i }.flatten }.flatten.include?(22)
|
|
243
|
+
unless security_groups.map {|a| a.authorizes.map {|t| t.from_port.to_i }.flatten }.flatten.include?(22)
|
|
241
244
|
warn "Cloud security_groups are not authorized for ssh. Cannot bootstrap."
|
|
242
245
|
return
|
|
243
246
|
end
|
|
@@ -250,18 +253,18 @@ module CloudProviders
|
|
|
250
253
|
node.run_chef!
|
|
251
254
|
end
|
|
252
255
|
end
|
|
253
|
-
|
|
256
|
+
|
|
254
257
|
def configure_nodes!(tmp_path=nil)
|
|
255
258
|
# removed duplicated code (now configure_nodes! invokes
|
|
256
259
|
# node.bootstrap_chef!, while old version did not, but I believe
|
|
257
260
|
# this is harmless)
|
|
258
|
-
bootstrap_nodes!(tmp_path)
|
|
261
|
+
bootstrap_nodes!(tmp_path)
|
|
259
262
|
|
|
260
263
|
ebs_volume_groups.each do |vol_grp|
|
|
261
264
|
vol_grp.verify_attachments nodes
|
|
262
265
|
end
|
|
263
266
|
end
|
|
264
|
-
|
|
267
|
+
|
|
265
268
|
def assign_elastic_ips
|
|
266
269
|
unless elastic_ips.empty?
|
|
267
270
|
unused_elastic_ip_addresses = ElasticIp.unused_elastic_ips(self).map {|i| i.public_ip }
|
|
@@ -299,11 +302,27 @@ module CloudProviders
|
|
|
299
302
|
def nodes
|
|
300
303
|
all_nodes.select {|i| i.in_service? }#describe_instances.select {|i| i.in_service? && security_groups.include?(i.security_groups) }
|
|
301
304
|
end
|
|
302
|
-
|
|
305
|
+
|
|
306
|
+
# === Description
|
|
307
|
+
#
|
|
308
|
+
# Return all the security groups of the instance that are prefixed with #poolparty.
|
|
309
|
+
#
|
|
310
|
+
# These are special security groups used only for tagging
|
|
311
|
+
#
|
|
312
|
+
# === Parameters
|
|
313
|
+
# instance - An ec2 instance as returned from describe_instances
|
|
314
|
+
def tags instance
|
|
315
|
+
instance.groupSet.item.collect{|g| g.groupId }.select {|s| s.start_with? "#poolparty"}
|
|
316
|
+
end
|
|
317
|
+
|
|
303
318
|
def all_nodes
|
|
304
|
-
@nodes ||= describe_instances.select {|i|
|
|
319
|
+
@nodes ||= describe_instances.select { |i|
|
|
320
|
+
!(security_group_names & tags(i)).empty?
|
|
321
|
+
}.sort {|a,b|
|
|
322
|
+
DateTime.parse(a.launchTime) <=> DateTime.parse(b.launchTime)
|
|
323
|
+
}
|
|
305
324
|
end
|
|
306
|
-
|
|
325
|
+
|
|
307
326
|
# Describe instances
|
|
308
327
|
# Describe the instances that are available on this cloud
|
|
309
328
|
# @params id (optional) if present, details about the instance
|
|
@@ -318,15 +337,15 @@ module CloudProviders
|
|
|
318
337
|
end
|
|
319
338
|
end.flatten
|
|
320
339
|
rescue AWS::InvalidClientTokenId => e # AWS credentials invalid
|
|
321
|
-
|
|
322
|
-
|
|
340
|
+
puts "Error contacting AWS: #{e}"
|
|
341
|
+
raise e
|
|
323
342
|
rescue Exception => e
|
|
324
343
|
[]
|
|
325
344
|
end
|
|
326
345
|
end
|
|
327
|
-
|
|
346
|
+
|
|
328
347
|
# Extras!
|
|
329
|
-
|
|
348
|
+
|
|
330
349
|
def block_device_mapping(o=[], given_name=cloud.proper_name )
|
|
331
350
|
@mappings ||= o
|
|
332
351
|
end
|
|
@@ -357,10 +376,10 @@ module CloudProviders
|
|
|
357
376
|
@ec2 ||= begin
|
|
358
377
|
AWS::EC2::Base.new( :access_key_id => access_key, :secret_access_key => secret_access_key )
|
|
359
378
|
rescue AWS::ArgumentError => e # AWS credentials missing?
|
|
360
|
-
|
|
361
|
-
|
|
379
|
+
puts "Error contacting AWS: #{e}"
|
|
380
|
+
raise e
|
|
362
381
|
rescue Exception => e
|
|
363
|
-
|
|
382
|
+
puts "Generic error #{e.class}: #{e}"
|
|
364
383
|
end
|
|
365
384
|
end
|
|
366
385
|
|
|
@@ -398,7 +417,7 @@ module CloudProviders
|
|
|
398
417
|
@ebs_volume_groups ||= []
|
|
399
418
|
end
|
|
400
419
|
|
|
401
|
-
# dsl method for EBS volumes. E.G.:
|
|
420
|
+
# dsl method for EBS volumes. E.G.:
|
|
402
421
|
# ebs_volumes do
|
|
403
422
|
# volumes "vol-001248ff", "vol-01ff4b85" # use existing volumes, not mandatory
|
|
404
423
|
# device "/dev/sdf"
|
|
@@ -412,7 +431,7 @@ module CloudProviders
|
|
|
412
431
|
def assign_ebs_volumes
|
|
413
432
|
ebs_volume_groups.each{|ebs_volume_group| ebs_volume_group.attach(nodes)}
|
|
414
433
|
end
|
|
415
|
-
|
|
434
|
+
|
|
416
435
|
def rds_instances
|
|
417
436
|
@rds_instances ||= []
|
|
418
437
|
end
|
|
@@ -447,13 +466,13 @@ module CloudProviders
|
|
|
447
466
|
# Read credentials from credential_file if one exists
|
|
448
467
|
def credential_file(file=nil)
|
|
449
468
|
unless file.nil?
|
|
450
|
-
dsl_options[:credential_file]=file
|
|
469
|
+
dsl_options[:credential_file]=file
|
|
451
470
|
dsl_options.merge!(Ec2.load_keys_from_credential_file(file))
|
|
452
471
|
else
|
|
453
472
|
fetch(:credential_file)
|
|
454
473
|
end
|
|
455
474
|
end
|
|
456
|
-
|
|
475
|
+
|
|
457
476
|
private
|
|
458
477
|
# Helper to get the options with self as parent
|
|
459
478
|
def sub_opts
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
module CloudProviders
|
|
2
2
|
class Ec2Instance < RemoteInstance
|
|
3
|
-
|
|
3
|
+
|
|
4
4
|
default_options(
|
|
5
5
|
:security_groups => [],
|
|
6
6
|
:private_ip => nil,
|
|
@@ -15,35 +15,41 @@ module CloudProviders
|
|
|
15
15
|
:instance_initiated_shutdown_behavior => nil,
|
|
16
16
|
:subnet_id => nil
|
|
17
17
|
)
|
|
18
|
-
|
|
18
|
+
|
|
19
19
|
def initialize(raw_response={})
|
|
20
20
|
@raw_response = raw_response
|
|
21
|
-
self.instance_id
|
|
22
|
-
self.security_groups
|
|
23
|
-
self.image_id
|
|
24
|
-
self.private_ip
|
|
25
|
-
self.dns_name
|
|
26
|
-
self.instance_type
|
|
27
|
-
self.public_ip
|
|
28
|
-
self.key_name
|
|
29
|
-
self.launch_time
|
|
30
|
-
self.availability_zones
|
|
31
|
-
self.status
|
|
32
|
-
self.block_device_mapping
|
|
33
|
-
self.
|
|
34
|
-
|
|
35
|
-
self.
|
|
21
|
+
self.instance_id = raw_response["instanceId"] rescue nil
|
|
22
|
+
self.security_groups = raw_response.groupSet.item.map{|sg| sg.groupId }.sort rescue nil
|
|
23
|
+
self.image_id = raw_response["imageId"] rescue nil
|
|
24
|
+
self.private_ip = raw_response["privateIpAddress"] rescue nil
|
|
25
|
+
self.dns_name = raw_response["dnsName"] rescue nil
|
|
26
|
+
self.instance_type = raw_response["instanceType"] rescue nil
|
|
27
|
+
self.public_ip = raw_response["ipAddress"] rescue nil
|
|
28
|
+
self.key_name = raw_response["keyName"] rescue nil
|
|
29
|
+
self.launch_time = raw_response["launchTime"] rescue nil
|
|
30
|
+
self.availability_zones = raw_response["placement"]["availabilityZone"] rescue nil
|
|
31
|
+
self.status = raw_response["instanceState"]["name"] rescue nil
|
|
32
|
+
self.block_device_mapping = raw_response["blockDeviceMapping"] rescue nil
|
|
33
|
+
self.subnet_id = raw_response["subnetId"] rescue nil
|
|
34
|
+
# disable_api_termination and instance_initiated_shutdown_behavior don't currently get returned in the request -- you'd need to later call describe_instance_attribute
|
|
35
|
+
self.disable_api_termination = raw_response["disableApiTermination"] rescue nil
|
|
36
|
+
self.instance_initiated_shutdown_behavior = raw_response["instanceInitiatedShutdownBehavior"] rescue nil
|
|
36
37
|
super
|
|
37
38
|
end
|
|
38
|
-
|
|
39
|
+
|
|
39
40
|
def keypair(n=nil)
|
|
40
|
-
@keypair
|
|
41
|
+
return @keypair if @keypair
|
|
42
|
+
@keypair = (cloud.keypair.basename == self.key_name) ? cloud.keypair : Keypair.new(self.key_name, cloud.keypair.extra_paths)
|
|
41
43
|
end
|
|
42
|
-
|
|
44
|
+
|
|
45
|
+
def security_group_names
|
|
46
|
+
security_groups.map{|a| a.to_s }
|
|
47
|
+
end
|
|
48
|
+
|
|
43
49
|
def zone
|
|
44
50
|
availability_zones.first
|
|
45
51
|
end
|
|
46
|
-
|
|
52
|
+
|
|
47
53
|
def reachable?
|
|
48
54
|
ping_port self.public_ip, 22
|
|
49
55
|
end
|
|
@@ -56,38 +62,42 @@ module CloudProviders
|
|
|
56
62
|
in_service? and
|
|
57
63
|
keypair and keypair.exists?
|
|
58
64
|
end
|
|
59
|
-
|
|
65
|
+
|
|
60
66
|
def in_service?
|
|
61
67
|
running?
|
|
62
68
|
end
|
|
63
|
-
|
|
69
|
+
|
|
64
70
|
def run!
|
|
65
|
-
r = cloud_provider.ec2.run_instances(
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
71
|
+
r = cloud_provider.ec2.run_instances(
|
|
72
|
+
:image_id => image_id,
|
|
73
|
+
:min_count => min_count,
|
|
74
|
+
:max_count => max_count,
|
|
75
|
+
:key_name => keypair.basename,
|
|
76
|
+
:security_group => cloud.security_group_names,
|
|
77
|
+
:user_data => user_data,
|
|
78
|
+
:instance_type => instance_type,
|
|
79
|
+
:availability_zone => availability_zone,
|
|
80
|
+
:block_device_mapping => block_device_mapping,
|
|
81
|
+
:disable_api_termination => disable_api_termination,
|
|
82
|
+
:instance_initiated_shutdown_behavior => instance_initiated_shutdown_behavior,
|
|
83
|
+
:base64_encoded => true)
|
|
75
84
|
r.instancesSet.item.map do |i|
|
|
76
85
|
inst_options = i.merge(r.merge(:cloud => cloud)).merge(cloud.cloud_provider.dsl_options)
|
|
77
86
|
Ec2Instance.new(inst_options)
|
|
78
87
|
end.first
|
|
79
88
|
end
|
|
80
89
|
def self.run!(hsh); new(hsh).run!; end
|
|
81
|
-
|
|
90
|
+
|
|
82
91
|
def terminate!
|
|
83
92
|
cloud_provider.ec2.terminate_instances(:instance_id => [self.instance_id])
|
|
84
93
|
cloud_provider.reset!
|
|
85
94
|
end
|
|
86
95
|
def self.terminate!(hsh={}); new(hsh).terminate!; end
|
|
87
|
-
|
|
96
|
+
|
|
88
97
|
# list of directories and files to exclude when bundling an instance
|
|
89
98
|
def rsync_excludes(array_of_abs_paths_to_exclude=nil)
|
|
90
|
-
array_of_abs_paths_to_exclude ||= %w
|
|
99
|
+
array_of_abs_paths_to_exclude ||= %w[
|
|
100
|
+
/sys
|
|
91
101
|
/proc
|
|
92
102
|
/dev/pts
|
|
93
103
|
/dev
|
|
@@ -99,8 +109,8 @@ module CloudProviders
|
|
|
99
109
|
/etc/ssh/moduli
|
|
100
110
|
/etc/udev/rules.d/70-persistent-net.rules
|
|
101
111
|
/etc/udev/rules.d/z25_persistent-net.rules
|
|
102
|
-
|
|
103
|
-
array_of_abs_paths_to_exclude.inject(''){|str, path| str<<"--exclude=#{path}"; str}
|
|
112
|
+
]
|
|
113
|
+
array_of_abs_paths_to_exclude.inject(''){|str, path| str << "--exclude=#{path}" ; str}
|
|
104
114
|
end
|
|
105
115
|
|
|
106
116
|
# create an image file and copy this instance to the image file.
|
|
@@ -138,7 +148,7 @@ module CloudProviders
|
|
|
138
148
|
scp ec2cert, "/mnt/bundle/"
|
|
139
149
|
scp cert, "/mnt/bundle/"
|
|
140
150
|
arch = self[:instanceType].match(/m1\.small|c1\.medium/) ? 'i386' : 'x86_64'
|
|
141
|
-
image = img ? img : make_image(opts)
|
|
151
|
+
image = img ? img : make_image(opts)
|
|
142
152
|
ssh "ec2-bundle-image #{image} -d /mnt/bundle -u #{self[:ownerId]} -k /mnt/bundle/pk-*.pem -c /tmp/cert-*.pem"
|
|
143
153
|
manifest = "/mnt/bundle/#{opts[:prefix]}.manifest.xml"
|
|
144
154
|
ssh "ec2-upload-bundle -a #{access_key} -s #{secret_access_key} -m #{manifest}"
|
|
@@ -146,6 +156,6 @@ module CloudProviders
|
|
|
146
156
|
ami = ami_str.grep(/ami-\w*/).first
|
|
147
157
|
return ami
|
|
148
158
|
end
|
|
149
|
-
|
|
159
|
+
|
|
150
160
|
end
|
|
151
161
|
end
|