poolparty 1.4.4 → 1.4.5
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +3 -1
- data/VERSION.yml +1 -1
- data/examples/simple.rb +3 -1
- data/lib/cloud_providers/ec2/ec2.rb +9 -8
- data/lib/cloud_providers/ec2/helpers/elastic_auto_scaler.rb +124 -1
- data/lib/cloud_providers/remote_instance.rb +1 -1
- data/vendor/gems/amazon-ec2/lib/AWS/Autoscaling/autoscaling.rb +1 -1
- metadata +1 -1
data/README.rdoc
CHANGED
@@ -21,7 +21,9 @@ For instance, to start a basic cloud, let's write one:
|
|
21
21
|
cloud "app" do
|
22
22
|
instances 2..10
|
23
23
|
using :ec2
|
24
|
-
|
24
|
+
autoscale do
|
25
|
+
trigger :lower_threshold => 0.3, :upper_threshold => 1.0, :measure => :cpu
|
26
|
+
end
|
25
27
|
security_group do
|
26
28
|
authorize :from_port => 22, :to_port => 22
|
27
29
|
end
|
data/VERSION.yml
CHANGED
data/examples/simple.rb
CHANGED
@@ -8,7 +8,9 @@ pool "poolparty" do
|
|
8
8
|
cloud "simple" do
|
9
9
|
instances 1..3
|
10
10
|
using :ec2
|
11
|
-
autoscale
|
11
|
+
autoscale do
|
12
|
+
trigger :lower_threshold => 0.3, :upper_threshold => 1.0, :measure => :cpu
|
13
|
+
end
|
12
14
|
image_id "ami-ccf615a5" #alestic jaunty
|
13
15
|
availability_zones ['us-east-1b']
|
14
16
|
#TODO: accept array of hashes defining security group rules
|
@@ -87,7 +87,8 @@ module CloudProviders
|
|
87
87
|
puts " minimum_instances: #{minimum_instances}"
|
88
88
|
puts " maximum_instances: #{maximum_instances}"
|
89
89
|
puts " security_groups: #{security_group_names.join(", ")}"
|
90
|
-
puts "
|
90
|
+
puts " using keypair: #{keypair}"
|
91
|
+
puts " user: #{user}\n"
|
91
92
|
|
92
93
|
security_groups.each do |sg|
|
93
94
|
sg.run
|
@@ -98,19 +99,19 @@ module CloudProviders
|
|
98
99
|
puts " load balancer: #{lb.name}"
|
99
100
|
lb.run
|
100
101
|
end
|
101
|
-
end
|
102
|
-
|
102
|
+
end
|
103
|
+
|
104
|
+
if autoscalers.empty? # not using autoscaling
|
103
105
|
puts "---- live, running instances (#{nodes.size}) ----"
|
104
106
|
if nodes.size < minimum_instances
|
105
107
|
expansion_count = minimum_instances - nodes.size
|
106
|
-
puts "-----> expanding the cloud because the minimum_instances is not satisified:
|
108
|
+
puts "-----> expanding the cloud because the #{expansion_count} minimum_instances is not satisified: "
|
107
109
|
expand_by(expansion_count)
|
108
110
|
elsif nodes.size > maximum_instances
|
109
111
|
contraction_count = nodes.size - maximum_instances
|
110
|
-
puts "-----> contracting the cloud because the instances count exceeds the maximum_instances by #{contraction_count}"
|
112
|
+
puts "-----> contracting the cloud because the instances count exceeds the #{maximum_instances} maximum_instances by #{contraction_count}"
|
111
113
|
contract_by(contraction_count)
|
112
114
|
end
|
113
|
-
|
114
115
|
progress_bar_until("Waiting for the instances to be launched") do
|
115
116
|
reset!
|
116
117
|
running_nodes = nodes.select {|n| n.running? }
|
@@ -170,12 +171,12 @@ module CloudProviders
|
|
170
171
|
progress_bar_until("Waiting for node to launch...") do
|
171
172
|
wait_for_node(e)
|
172
173
|
end
|
173
|
-
all_nodes.
|
174
|
+
all_nodes.detect {|n| n.instance_id == e.instance_id }
|
174
175
|
end
|
175
176
|
|
176
177
|
def wait_for_node(instance)
|
177
178
|
reset!
|
178
|
-
inst = all_nodes.
|
179
|
+
inst = all_nodes.detect {|n| n.instance_id == instance.instance_id }
|
179
180
|
inst.running?
|
180
181
|
end
|
181
182
|
|
@@ -21,12 +21,18 @@ module CloudProviders
|
|
21
21
|
puts "Deleting old launch configuration: #{old_launch_configuration_name}"
|
22
22
|
as.delete_launch_configuration(:launch_configuration_name => old_launch_configuration_name)
|
23
23
|
end
|
24
|
-
|
24
|
+
end
|
25
|
+
|
26
|
+
triggers.each do |trigger|
|
27
|
+
trigger.run
|
25
28
|
end
|
26
29
|
end
|
27
30
|
|
28
31
|
# First, change the min_count to
|
29
32
|
def teardown
|
33
|
+
triggers.each do |trigger|
|
34
|
+
trigger.teardown
|
35
|
+
end
|
30
36
|
if autoscaling_groups.select {|n| n.name == name }.empty?
|
31
37
|
puts "Cloud #{cloud.name} autoscaling group does not exist"
|
32
38
|
else
|
@@ -292,7 +298,16 @@ module CloudProviders
|
|
292
298
|
describe_autoscaling_groups.DescribeAutoScalingGroupsResult.AutoScalingGroups.member
|
293
299
|
end
|
294
300
|
|
301
|
+
def trigger(*trigger_hashes)
|
302
|
+
trigger_hashes.each do |hsh, blk|
|
303
|
+
triggers << ElasticTrigger.new(name, hsh.merge(:cloud => cloud), &blk)
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
295
307
|
private
|
308
|
+
def triggers
|
309
|
+
@triggers ||= []
|
310
|
+
end
|
296
311
|
def reset!
|
297
312
|
@old_auto_scaling_group_name =
|
298
313
|
@new_auto_scaling_group_name =
|
@@ -301,4 +316,112 @@ module CloudProviders
|
|
301
316
|
cloud.reset!
|
302
317
|
end
|
303
318
|
end
|
319
|
+
class ElasticTrigger < Ec2Helper
|
320
|
+
default_options(
|
321
|
+
:measure => :cpu,
|
322
|
+
:period => 60,
|
323
|
+
:statistic => :average,
|
324
|
+
:unit => "Seconds",
|
325
|
+
:lower_threshold => 20,
|
326
|
+
:upper_threshold => 60,
|
327
|
+
:trigger_name => "CpuTrigger",
|
328
|
+
:lower_breach_scale_increment => -1,
|
329
|
+
:upper_breach_scale_increment => 1,
|
330
|
+
:breach_duration => 120
|
331
|
+
)
|
332
|
+
|
333
|
+
def measure_names
|
334
|
+
{:cpu => "CPUUtilization"}
|
335
|
+
end
|
336
|
+
|
337
|
+
def statistic_names
|
338
|
+
{:min => "Minimum", :max => "Maximum", :average => "Average", :sum => "Sum"}
|
339
|
+
end
|
340
|
+
|
341
|
+
def run
|
342
|
+
if autoscaling_triggers.empty?
|
343
|
+
create_autoscaling_trigger!
|
344
|
+
else
|
345
|
+
t = autoscaling_triggers.map do |hsh|
|
346
|
+
diff(hsh)
|
347
|
+
end.flatten
|
348
|
+
unless t.empty?
|
349
|
+
puts "Creating or updating trigger: #{trigger_name}"
|
350
|
+
create_autoscaling_trigger!
|
351
|
+
end
|
352
|
+
end
|
353
|
+
end
|
354
|
+
|
355
|
+
def teardown
|
356
|
+
autoscaling_triggers.each do |trigger|
|
357
|
+
puts "Deleting trigger: #{trigger[:trigger_name]}"
|
358
|
+
as.delete_trigger(:trigger_name => trigger[:trigger_name], :autoscaling_group_name => name)
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
def diff(hsh={})
|
363
|
+
[ :measure_name,
|
364
|
+
:period,
|
365
|
+
:statistic,
|
366
|
+
:lower_threshold,
|
367
|
+
:lower_breach_scale_increment,
|
368
|
+
:upper_threshold,
|
369
|
+
:upper_breach_scale_increment,
|
370
|
+
:unit,
|
371
|
+
:trigger_name].reject do |k|
|
372
|
+
hsh[k].to_s.capitalize == self.send(k).to_s.capitalize
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
376
|
+
private
|
377
|
+
|
378
|
+
def autoscaling_triggers
|
379
|
+
begin
|
380
|
+
as.describe_triggers(:autoscaling_group_name => name).DescribeTriggersResult.Triggers.member.map do |trigger|
|
381
|
+
{
|
382
|
+
:trigger_name => trigger["TriggerName"],
|
383
|
+
:statistic => trigger["Statistic"],
|
384
|
+
:status => trigger["Status"],
|
385
|
+
:lower_threshold => trigger["LowerThreshold"],
|
386
|
+
:created_time => trigger["CreatedTime"],
|
387
|
+
:measure_name => trigger["MeasureName"],
|
388
|
+
:upper_threshold => trigger["UpperThreshold"],
|
389
|
+
:lower_breach_scale_increment => trigger["LowerBreachScaleIncrement"],
|
390
|
+
:period => trigger["Period"],
|
391
|
+
:upper_breach_scale_increment => trigger["UpperBreachScaleIncrement"],
|
392
|
+
:breach_duration => trigger["BreachDuration"],
|
393
|
+
:dimensions => trigger["Dimensions"],
|
394
|
+
:unit => trigger["Unit"],
|
395
|
+
:autoscaling_group_name => trigger["AutoScalingGroupName"]
|
396
|
+
}
|
397
|
+
end
|
398
|
+
rescue Exception => e
|
399
|
+
[]
|
400
|
+
end
|
401
|
+
end
|
402
|
+
def create_autoscaling_trigger!
|
403
|
+
as.create_or_updated_scaling_trigger(
|
404
|
+
:autoscaling_group_name => name,
|
405
|
+
:dimensions => {:name => "AutoScalingGroupName", :value => name},
|
406
|
+
:measure_name => measure_name,
|
407
|
+
:period => "#{period}",
|
408
|
+
:trigger_name => trigger_name,
|
409
|
+
:statistic => (statistic_names[statistic] || statistic),
|
410
|
+
:unit => unit,
|
411
|
+
:breach_duration => breach_duration,
|
412
|
+
:lower_threshold => "#{lower_threshold}",
|
413
|
+
:lower_breach_scale_increment => "#{lower_breach_scale_increment}",
|
414
|
+
:upper_threshold => "#{upper_threshold}",
|
415
|
+
:upper_breach_scale_increment => "#{upper_breach_scale_increment}"
|
416
|
+
)
|
417
|
+
end
|
418
|
+
|
419
|
+
def measure_name
|
420
|
+
measure_names[measure] || measure
|
421
|
+
end
|
422
|
+
|
423
|
+
def trigger_name
|
424
|
+
"#{(measure_names[measure] || measure)}-#{name}" || name
|
425
|
+
end
|
426
|
+
end
|
304
427
|
end
|
@@ -112,7 +112,7 @@ module AWS
|
|
112
112
|
params["Dimensions.member.1.Name"] = options[:dimensions][:name]
|
113
113
|
params["Dimensions.member.1.Value"] = options[:dimensions][:value]
|
114
114
|
else
|
115
|
-
raise ArgumentError, "
|
115
|
+
raise ArgumentError, "Dimensions must be either an array or a hash"
|
116
116
|
end
|
117
117
|
params['MeasureName'] = options[:measure_name]
|
118
118
|
params['Statistic'] = options[:statistic]
|