Class: CloudProviders::ElasticAutoScaler

Inherits:
Ec2Helper show all
Defined in:
lib/cloud_providers/ec2/helpers/elastic_auto_scaler.rb

Instance Attribute Summary

Attributes inherited from CloudProvider

#init_opts, #name

Instance Method Summary collapse

Methods inherited from Ec2Helper

#as, #ec2, #elb, #initialize, #pool, property, #rds

Methods inherited from CloudProvider

#after_initialized, #bootstrap_nodes!, #default_keypair_path, default_keypair_path, #initialize, #method_missing

Constructor Details

This class inherits a constructor from CloudProviders::Ec2Helper

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class CloudProviders::CloudProvider

Instance Method Details

#autoscaling_groupsObject



229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
# File 'lib/cloud_providers/ec2/helpers/elastic_auto_scaler.rb', line 229

def autoscaling_groups
  @autoscaling_groups ||= as.describe_autoscaling_groups.DescribeAutoScalingGroupsResult.AutoScalingGroups.member.map do |g|
    {
      :cooldown => g["Cooldown"],
      :desired_capacity => g["DesiredCapacity"],
      :created_time => g["CreatedTime"],
      :min_size => g["MinSize"],
      :max_size => g["MaxSize"],
      :load_balancer_names => (g["LoadBalancerNames"]["member"] rescue []),
      :availability_zones => (g["AvailabilityZones"]["member"] rescue []),
      :launch_configuration_name => g["LaunchConfigurationName"],
      :name => g["AutoScalingGroupName"],
      :instances => (g["Instances"]["member"] rescue []).map {|i|
        {:instance_id => i["InstanceId"],
        :state => i["LifecycleState"],
        :availability_zone => i["AvailabilityZone"]
      }}
    }
  end rescue []
end

#create_autoscaling_group!Object



176
177
178
179
180
181
182
183
184
185
186
# File 'lib/cloud_providers/ec2/helpers/elastic_auto_scaler.rb', line 176

def create_autoscaling_group!
  as.create_autoscaling_group({
    :autoscaling_group_name => name,
    :availability_zones => availability_zones,
    :launch_configuration_name => new_launch_configuration_name,
    :min_size => minimum_instances.to_s,
    :max_size => maximum_instances.to_s,
    :load_balancer_names => load_balancers.map {|lb| lb.name }
  })
  reset!
end

#create_launch_configuration!(lc = new_launch_configuration_name) ⇒ Object



135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/cloud_providers/ec2/helpers/elastic_auto_scaler.rb', line 135

def create_launch_configuration!(lc=new_launch_configuration_name)
  puts "-----> Creating launch configuration: #{new_launch_configuration_name} for #{proper_name}"
  begin
    @launch_configuration_name = lc
    as.create_launch_configuration({
      :launch_configuration_name => new_launch_configuration_name,
      :image_id => image_id,
      :instance_type => instance_type,
      :security_groups => parent.security_group_names,
      :key_name => keypair.to_s,
      :user_data => user_data,
      :kernel_id => kernel_id,
      :ramdisk_id => ramdisk_id,
      :block_device_mapping => block_device_mapping
    })
  rescue Exception => e
    puts <<-EOE
-----> There was an error: #{e.inspect} when creating the launch_configurations
    EOE
  ensure
    reset!
  end
end

#launch_configurationsObject



158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/cloud_providers/ec2/helpers/elastic_auto_scaler.rb', line 158

def launch_configurations
  begin
    @launch_configurations ||= as.describe_launch_configurations.DescribeLaunchConfigurationsResult.LaunchConfigurations.member.map do |a|
      {
        :name => a["LaunchConfigurationName"],
        :ramdisk_id => a["RamdiskId"],
        :image_id => a["ImageId"],
        :security_groups => (a["SecurityGroups"]["member"] rescue ["default"]),
        :created_time => a["CreatedTime"],
        :user_data => a["UserData"] || "",
        :key_name => a["KeyName"],
        :instance_type => a["InstanceType"]
      }
    end
  rescue Exception => e
    []
  end
end

#listObject

Convenience methods Return an array of hashes describing the autoscaling groups



297
298
299
# File 'lib/cloud_providers/ec2/helpers/elastic_auto_scaler.rb', line 297

def list
  describe_autoscaling_groups.DescribeAutoScalingGroupsResult.AutoScalingGroups.member
end

#new_auto_scaling_group_nameObject



279
280
281
# File 'lib/cloud_providers/ec2/helpers/elastic_auto_scaler.rb', line 279

def new_auto_scaling_group_name
  @new_auto_scaling_group_name ||= "#{name}#{used_autoscaling_group_id.zero? ? 1 : 0}"
end

#new_launch_configuration_nameObject

Temporary names so we can create and recreate launch_configurations



263
264
265
# File 'lib/cloud_providers/ec2/helpers/elastic_auto_scaler.rb', line 263

def new_launch_configuration_name
  @new_launch_configuration_name ||= "#{name}#{used_launched_config_id.zero? ? 1 : 0}"
end

#old_auto_scaling_group_nameObject



283
284
285
# File 'lib/cloud_providers/ec2/helpers/elastic_auto_scaler.rb', line 283

def old_auto_scaling_group_name
  @old_auto_scaling_group_name ||= "#{name}#{used_autoscaling_group_id.zero? ? 0 : 1}"
end

#old_launch_configuration_nameObject



266
267
268
# File 'lib/cloud_providers/ec2/helpers/elastic_auto_scaler.rb', line 266

def old_launch_configuration_name
  @old_launch_configuration_name ||= "#{name}#{used_launched_config_id.zero? ? 0 : 1}"
end

#runObject



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/cloud_providers/ec2/helpers/elastic_auto_scaler.rb', line 7

def run      
  if should_create_autoscaling_group?
    puts "Creating autoscaling group"
    create_launch_configuration!
    create_autoscaling_group!
  else
    puts "-----> Checking for launch configuration named: #{old_launch_configuration_name}"
    if should_create_launch_configuration?
      create_launch_configuration!
    elsif should_update_launch_configuration? || should_update_autoscaling_group?
      update_launch_configuration!
      
      puts "Updating autoscaling group"
      update_autoscaling_group!
      puts "Deleting old launch configuration: #{old_launch_configuration_name}"
      as.delete_launch_configuration(:launch_configuration_name => old_launch_configuration_name)
    end
  end
  
  triggers.each do |trigger|
    trigger.run
  end
end

#scaling_activitiesObject



249
250
251
252
253
254
255
256
257
258
259
260
261
# File 'lib/cloud_providers/ec2/helpers/elastic_auto_scaler.rb', line 249

def scaling_activities
  @scaling_activities ||= as.describe_scaling_activities(:autoscaling_group_name => name).DescribeScalingActivitiesResult.Activities.member.map do |action|
    {
      :cause        => action["Cause"],
      :progress     => action["Progress"].to_i,
      :activity_id  => action["ActivityId"],
      :description  => action["Description"],
      :status_code  => action["StatusCode"],
      :complete     => action["StatusCode"] == "Pending" ? false : true,
      :start_time   => action["StartTime"]
    }
  end rescue []
end

#should_create_autoscaling_group?Boolean

Returns:

  • (Boolean)


93
94
95
96
97
98
99
100
101
# File 'lib/cloud_providers/ec2/helpers/elastic_auto_scaler.rb', line 93

def should_create_autoscaling_group?
  known = autoscaling_groups.select {|ag| ag.name == cloud.proper_name }
  if known.empty?
    true
  else
    puts "Autoscaling group already defined...: #{name}"
    false
  end
end

#should_create_launch_configuration?Boolean

Returns:

  • (Boolean)


102
103
104
105
106
107
108
109
# File 'lib/cloud_providers/ec2/helpers/elastic_auto_scaler.rb', line 102

def should_create_launch_configuration?
  known = launch_configurations.select {|lc| lc.name =~ /#{name}/ }
  if known.empty?
    true
  else
    false
  end
end

#should_update_autoscaling_group?Boolean

Returns:

  • (Boolean)


188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
# File 'lib/cloud_providers/ec2/helpers/elastic_auto_scaler.rb', line 188

def should_update_autoscaling_group?
  known = autoscaling_groups.select {|lc| lc.name =~ /#{name}/ }
  if known.empty?
    true
  else
    differences = known.map do |k|
      hsh = {
        :min_size => minimum_instances.to_s, :max_size => maximum_instances.to_s,
        :availability_zones => availability_zones,
        :launch_configuration_name => old_launch_configuration_name
      }
      hsh.merge!(:cooldown => cooldown.to_s) if cooldown
      
      t = hsh.diff(k, :cooldown,
                      :min_size,
                      :max_size, 
                      :availability_zones, 
                      :launch_configuration_name)
      t.empty? ? nil : t
    end.reject {|a| a.nil? }
    if differences.empty?
      false
    else
      puts "-----> Recreating the autoscaling group as details have changed: #{differences.inspect}"
      true
    end
  end
end

#should_update_launch_configuration?Boolean

Returns:

  • (Boolean)


110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/cloud_providers/ec2/helpers/elastic_auto_scaler.rb', line 110

def should_update_launch_configuration?
  known = launch_configurations.select {|lc| lc.name =~ /#{name}/ }
  if known.empty?
    true
  else
    differences = known.map do |k|
      t = k.diff({
        :image_id => image_id,
        :instance_type => instance_type,
        :security_groups => parent.security_group_names.flatten,
        :key_name => keypair.to_s,
        :user_data => user_data,
        }, :user_data, :image_id, :instance_type, :security_groups, :key_name)
      t.empty? ? nil : t
    end.reject {|a| a.nil? }
    if differences.empty?
      false
    else
      true
    end
  end
end

#teardownObject

First, change the min_count to



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/cloud_providers/ec2/helpers/elastic_auto_scaler.rb', line 32

def teardown
  triggers.each do |trigger|
    trigger.teardown
  end
  if autoscaling_groups.select {|n| n.name == name }.empty?
    puts "Cloud #{cloud.name} autoscaling group does not exist"
  else
    self.minimum_instances = 0
    self.maximum_instances = 0
    @new_launch_configuration_name = old_launch_configuration_name
    puts "Updating autoscaling group: #{@new_launch_configuration_name}"
    update_autoscaling_group!
    puts "Terminating nodes in autoscaling group: #{name}"
    reset!
    # cloud.nodes.each {|n| n.terminate! }
    delete_autoscaling_group!
    delete_launch_configuration!
    puts ""
  end
end

#trigger(*trigger_hashes) ⇒ Object



301
302
303
304
305
# File 'lib/cloud_providers/ec2/helpers/elastic_auto_scaler.rb', line 301

def trigger(*trigger_hashes)
  trigger_hashes.each do |hsh, blk|
    triggers << ElasticTrigger.new(name, hsh.merge(:cloud => cloud), &blk)
  end
end

#update_autoscaling_group!Object



217
218
219
220
221
222
223
224
225
226
227
# File 'lib/cloud_providers/ec2/helpers/elastic_auto_scaler.rb', line 217

def update_autoscaling_group!
  as.update_autoscaling_group(
    :autoscaling_group_name => name,
    :availability_zones => availability_zones.first, # TODO: Figure out how to support multiple availability_zones
    :launch_configuration_name => new_launch_configuration_name,
    :min_size => minimum_instances.to_s,
    :max_size => maximum_instances.to_s,
    :cooldown => cooldown.to_s,
    :load_balancer_names => load_balancers.map {|lb| lb.name }
  )
end

#update_launch_configuration!Object



132
133
134
# File 'lib/cloud_providers/ec2/helpers/elastic_auto_scaler.rb', line 132

def update_launch_configuration!
  create_launch_configuration!
end

#used_autoscaling_group_idObject



287
288
289
290
291
292
293
# File 'lib/cloud_providers/ec2/helpers/elastic_auto_scaler.rb', line 287

def used_autoscaling_group_id
  return @used_autoscaling_group_id if @used_autoscaling_group_id
  used_autoscaling_groups = launch_configurations.map {|hsh| hsh[:name] =~ /#{name}/ ? hsh[:name] : nil }.reject {|a| a.nil?}
  used_autoscaling_group_id = used_autoscaling_groups.map {|a| a.gsub(/#{name}/, '').to_i }.reject {|a| a.zero? }.first
  used_autoscaling_group_id = 0 if used_autoscaling_group_id.nil?
  @used_autoscaling_group_id ||= used_autoscaling_group_id
end

#used_launched_config_idObject

Compute the next configuration launch id. We’ll be cycling through the usage of 0 and 1 Here we are just looking for which one that is, either zero or 1



271
272
273
274
275
276
277
# File 'lib/cloud_providers/ec2/helpers/elastic_auto_scaler.rb', line 271

def used_launched_config_id
  return @used_launched_config_id if @used_launched_config_id
  used_configuration_names = launch_configurations.map {|hsh| hsh[:name] =~ /#{name}/ ? hsh[:name] : nil }.reject {|a| a.nil?}
  used_launched_config_id = used_configuration_names.map {|a| a.gsub(/#{name}/, '').to_i }.reject {|a| a.zero? }.first
  used_launched_config_id = 0 if used_launched_config_id.nil?
  @used_launched_config_id = used_launched_config_id
end