Skip to content
This repository has been archived by the owner. It is now read-only.
Permalink
Browse files

Bug 1122657: Fixing logic to select gear for scaledown

  • Loading branch information...
abhgupta committed Jul 24, 2014
1 parent 13eda1b commit 023dfc859ca71b6579b71a670c016a6220ac4175
Showing with 45 additions and 24 deletions.
  1. +14 −6 broker/test/functional/application_test.rb
  2. +31 −18 controller/app/models/application.rb
@@ -168,14 +168,15 @@ def region_stubber
assert_not_equal true, app.ha
assert_equal 1, app.gears.count

app.make_ha
# scale up, get 1 more php instance
app.scale_by(app.group_instances.first._id, 1)
app.reload
assert_equal true, app.ha
assert_equal 2, app.gears.count
assert app.gears.all?{ |g| g.sparse_carts.length == 1 }
assert_equal 1, app.gears.inject(0){ |c, g| c + (g.sparse_carts.present? ? 1 : 0) }
assert_equal [app.component_instances.detect{ |i| i.cartridge.is_web_proxy? }._id], app.gears.map(&:sparse_carts).flatten.uniq

# scale up, get 1 more php instance
# make app ha and scale up, get 1 more php instance
app.make_ha
app.scale_by(app.group_instances.first._id, 1)
app.reload
assert_equal 3, app.gears.count
@@ -195,18 +196,25 @@ def region_stubber

app.scale_by(app.group_instances.first._id, -1)

# alter multiplier to 2, expect 4 new php gears
# alter multiplier to 2
stubs_config(:openshift, default_ha_multiplier: 2)
app.scale_by(app.group_instances.first._id, 3)
assert_equal 5, app.gears.count
assert_equal 2, app.gears.inject(0){ |c, g| c + (g.sparse_carts.present? ? 1 : 0) }
assert_equal 3, app.gears.inject(0){ |c, g| c + (g.sparse_carts.present? ? 1 : 0) }

# scale up, get 1 more haproxy instance
app.scale_by(app.group_instances.first._id, 1)
assert_equal 6, app.gears.count
assert_equal 3, app.gears.inject(0){ |c, g| c + (g.sparse_carts.present? ? 1 : 0) }

# scale down, haproxy instances should remain the same
app.scale_by(app.group_instances.first._id, -1)
assert_equal 5, app.gears.count
assert_equal 3, app.gears.inject(0){ |c, g| c + (g.sparse_carts.present? ? 1 : 0) }

# scale down, 1 haproxy instance should get removed
app.scale_by(app.group_instances.first._id, -1)
assert_equal 4, app.gears.count
assert_equal 2, app.gears.inject(0){ |c, g| c + (g.sparse_carts.present? ? 1 : 0) }

app.destroy_app
@@ -1991,37 +1991,49 @@ def calculate_gear_destroy_ops(ginst_id, gear_ids, additional_filesystem_gb)

def get_sparse_scaledown_gears(ginst, scale_down_factor)
scaled_gears = ginst.gears.select { |g| g.app_dns==false }
sparse_components = ginst.component_instances.select(&:is_sparse?)
sparse_components = ginst.all_component_instances.select(&:is_sparse?)
gi_overrides = group_instances_with_overrides.select {|o| o.instance._id == ginst._id}
specs ||= component_instances.map(&:to_component_spec)
gears = []
if sparse_components.length > 0
(scale_down_factor...0).each do |i|
# iterate through sparse components to see which ones need a definite scale-down
relevant_sparse_components = sparse_components.select do |ci|
min = ci.min rescue ci.get_component.scaling.min
multiplier = ci.multiplier rescue ci.get_component.scaling.multiplier
cur_sparse_gears = (ci.gears - gears)
cur_total_gears = (gi.gears - gears)
surplus_sparse_components = sparse_components.select do |ci|
comp_spec = nil
gi_overrides.each {|o| o.components.each {|c| comp_spec = c if c.cartridge_name == ci.cartridge_name}}
min = comp_spec.min_gears rescue ci.get_component.scaling.min
multiplier = comp_spec.multiplier rescue ci.get_component.scaling.multiplier
cur_sparse_gears = ( ci.gears - gears.select {|g| g.component_instances.include?(ci)} ).count
cur_total_gears = (ginst.gears - gears).count
status = false
if cur_sparse_gears <= min or multiplier<=0
if cur_sparse_gears <= min
status = false
# if the multiplier is -1, 0, or 1, then any gears that are in addition to the minimum value can be removed
elsif multiplier <= 1
status = true
else
status = cur_total_gears/(cur_sparse_gears*1.0)>multiplier ? false : true
# does removing a gear with this sparse cart still maintain the multiplier?
# ensuring a float arithmetic to make correct comparisons
status = (cur_total_gears -1) / ((cur_sparse_gears - 1) * 1.0) <= multiplier
end
status
end
# each of relevant_sparse_components want a gear removed that has them contained in the gear
# each of surplus_sparse_components want a gear removed that has them contained in the gear
# if its empty, then remove a gear which does not have any of sparse_components in them (non-sparse gears)
if relevant_sparse_components.length > 0
relevant_sparse_comp_ids = relevant_sparse_components.map { |sp_ci| ci._id }
gear = scaled_gears.find do |g|
(relevant_sparse_comp_ids - g.sparse_carts).empty?
end
else
gear = scaled_gears.find { |g| g.sparse_carts.empty? }
gear = nil
if surplus_sparse_components.length > 0
surplus_sparse_comp_ids = surplus_sparse_components.map(&:_id)
# try to find a gear that has all the (and only those) sparse carts that need to be scaled down
# doing a reverse on the gears list ensures that the last possible gear is picked for scaledown
gear = scaled_gears.reverse.find { |g| g.sparse_carts.sort == surplus_sparse_comp_ids.sort }
# if the above fails, try to find a gear that has sparse carts that are all part of those that need to be scaled down
gear = scaled_gears.reverse.find { |g| g.sparse_carts.count > 0 && (g.sparse_carts - surplus_sparse_comp_ids).empty? } if gear.nil?
end
# if a gear is not found, just try to find one without any sparse carts
gear = scaled_gears.reverse.find { |g| g.sparse_carts.empty? } if gear.nil?
if gear.nil?
# this may mean that some sparse_component's min limit is being violated
gear = scaled_gears.last
raise OpenShift::UserException.new("Cannot scale down by #{scale_down_factor.abs} as it violates the minimum gear restrictions for sparse cartridges.")
end
gears << gear
scaled_gears.delete(gear)
@@ -2057,7 +2069,8 @@ def add_sparse_cart?(index, sparse_carts_added_count, spec, is_scale_up)
return false if multiplier <= 0

# for max, and cases where multiplier has been changed in apps mid-life
should_be_sparse_cart_count = [total/multiplier, (max==-1 ? (total/multiplier) : max)].min
multiplier_gears = ( total / ( multiplier * 1.0 ) ).ceil
should_be_sparse_cart_count = [multiplier_gears, (max == -1 ? multiplier_gears : max)].min
return true if gears < should_be_sparse_cart_count

false

0 comments on commit 023dfc8

Please sign in to comment.
You can’t perform that action at this time.