AppController/djinn.rb
# Searches through the requests to scale up and down each application in this
# AppScale deployment, and determines if machines need to be terminated due
# to excess capacity.
#
# Args:
#   all_scaling_votes: A Hash that maps each appid (a String) to the votes
#     received to scale the app up or down (an Array of Strings).
# Returns:
#   An Integer that indicates how many nodes were added to this AppScale
#   deployment. A negative number indicates that that many nodes were
#   removed from this AppScale deployment.
Searches through the requests to scale up and down each application in this
AppScale deployment, and determines if machines need to be terminated due
to excess capacity.

A Hash that maps each appid (a String) to the votes
received to scale the app up or down (an Array of Strings).
Returns:
An Integer that indicates how many nodes were added to this AppScale
deployment. A negative number indicates that that many nodes were
removed from this AppScale deployment.
Searches through the requests to scale up and down each application in this AppScale deployment and determines if machines need to be terminated due to excess capacity . A Hash that maps each appid ( a String ) to the votes received to scale the app up or down ( an Array of Strings ) . Returns : An Integer that indicates how many nodes were added to this AppScale deployment . A negative number indicates that that many nodes were removed from this AppScale deployment .
def examine_scale_down_requests(all_scaling_votes)
    unless is_cloud?
      Djinn.log_debug("Not scaling down VMs, because we aren't in a cloud.")
      return 0
    end
    if @nodes.length <= Integer(@options['min_images']) or @nodes.length <= 1
      Djinn.log_debug("Not scaling down VMs right now, as we are at the " +
        "minimum number of nodes the user wants to use.")
      return 0
    end
    @apps_loaded.each { |appid|
      scale_ups = all_scaling_votes[appid].select { |vote| vote == "scale_up" }
      if scale_ups.length > 0
        Djinn.log_debug("Not scaling down VMs, because app #{appid} wants to scale" +
          " up.")
        return 0
      end
    }
    scale_down_threshold_reached = false
    @apps_loaded.each { |appid|
      scale_downs = all_scaling_votes[appid].select { |vote| vote == "scale_down" }
      if scale_downs.length > 0
        Djinn.log_info("Got a vote to scale down app #{appid}, so " +
          "considering removing VMs.")
        scale_down_threshold_reached = true
      end
    }
    unless scale_down_threshold_reached
      Djinn.log_debug("Not scaling down VMs right now, as not enough nodes have " +
        "requested it.")
      return 0
    end
    if Time.now.to_i - @last_scaling_time < (SCALEDOWN_THRESHOLD *
            SCALE_TIME_MULTIPLIER * DUTY_CYCLE)
      Djinn.log_info("Not scaling down VMs right now, as we recently scaled " +
        "up or down.")
      return 0
    end
    node_to_remove = nil
    @nodes.each { |node|
      if node.jobs == ["memcache", "taskqueue_slave", "appengine"]
        Djinn.log_info("Removing node #{node}")
        node_to_remove = node
        break
      end
    }
    if node_to_remove.nil?
      Djinn.log_warn("Tried to scale down but couldn't find a node to remove.")
      return 0
    end
    remove_node_from_local_and_zookeeper(node_to_remove.public_ip)
    @app_info_map.each { |app_id, info|
      if info['appengine'].nil?
        next
      end
      info['appengine'].each { |location|
        host, port = location.split(":")
        if host == node_to_remove.private_ip
          remove_appserver_from_haproxy(app_id, host, port, @@secret)
          delete_instance_from_dashboard(app_id, "#{host}:#{port}")
        end
      }
    }
    imc = InfrastructureManagerClient.new(@@secret)
    begin
      imc.terminate_instances(@options, node_to_remove.instance_id)
    rescue FailedNodeException
      Djinn.log_warn("Failed to call terminate_instances")
    end
    @last_scaling_time = Time.now.to_i
    return -1
  end
def examine_scale_down_requests ( all_scaling_votes ) unless is_cloud? Djinn . log_debug ( "Not scaling down VMs, because we aren't in a cloud." ) return 0 end if @nodes . length <= Integer ( @options [ 'min_images' ] ) or @nodes . length <= 1 Djinn . log_debug ( "Not scaling down VMs right now, as we are at the " + "minimum number of nodes the user wants to use." ) return 0 end @apps_loaded . each { | appid | scale_ups = all_scaling_votes [ appid ] . select { | vote | vote == "scale_up" } if scale_ups . length > 0 Djinn . log_debug ( "Not scaling down VMs, because app #{appid} wants to scale" + " up." ) return 0 end } scale_down_threshold_reached = false @apps_loaded . each { | appid | scale_downs = all_scaling_votes [ appid ] . select { | vote | vote == "scale_down" } if scale_downs . length > 0 Djinn . log_info ( "Got a vote to scale down app #{appid}, so " + "considering removing VMs." ) scale_down_threshold_reached = true end } unless scale_down_threshold_reached Djinn . log_debug ( "Not scaling down VMs right now, as not enough nodes have " + "requested it." ) return 0 end if Time . now . to_i - @last_scaling_time < ( SCALEDOWN_THRESHOLD * SCALE_TIME_MULTIPLIER * DUTY_CYCLE ) Djinn . log_info ( "Not scaling down VMs right now, as we recently scaled " + "up or down." ) return 0 end node_to_remove = nil @nodes . each { | node | if node . jobs == [ "memcache" , "taskqueue_slave" , "appengine" ] Djinn . log_info ( "Removing node #{node}" ) node_to_remove = node break end } if node_to_remove . nil? Djinn . log_warn ( "Tried to scale down but couldn't find a node to remove." ) return 0 end remove_node_from_local_and_zookeeper ( node_to_remove . public_ip ) @app_info_map . each { | app_id , info | if info [ 'appengine' ] . nil? next end info [ 'appengine' ] . each { | location | host , port = location . split ( ":" ) if host == node_to_remove . private_ip remove_appserver_from_haproxy ( app_id , host , port , @@secret ) delete_instance_from_dashboard ( app_id , "#{host}:#{port}" ) end } } imc = InfrastructureManagerClient . new ( @@secret ) begin imc . terminate_instances ( @options , node_to_remove . instance_id ) rescue FailedNodeException Djinn . log_warn ( "Failed to call terminate_instances" ) end @last_scaling_time = Time . now . to_i return - 1 end
Searches through the requests to scale up and down each application in this
AppScale deployment, and determines if machines need to be terminated due
to excess capacity.
Searches through the requests to scale up and down each application in this AppScale deployment and determines if machines need to be terminated due to excess capacity .
# First, only scale down in cloud environments. # Second, only consider scaling down if nobody wants to scale up. # Third, only consider scaling down if we get two votes to scale down on # the same app, just like we do for scaling up. # Also, don't scale down if we just scaled up or down. # Finally, find a node to remove and remove it.
all_scaling_votes
<not_specific>