class Bosh::AwsCloud::SpotManager
Constants
- RETRY_COUNT
- TOTAL_WAIT_TIME_IN_SECONDS
Public Class Methods
new(region)
click to toggle source
# File lib/cloud/aws/spot_manager.rb, line 9 def initialize(region) @region = region @logger = Bosh::Clouds::Config.logger end
Public Instance Methods
create(instance_params, spot_bid_price)
click to toggle source
# File lib/cloud/aws/spot_manager.rb, line 14 def create(instance_params, spot_bid_price) @instance_params = instance_params spot_request_spec = create_spot_request_spec(instance_params, spot_bid_price) @logger.debug("Requesting spot instance with: #{spot_request_spec.inspect}") begin @spot_instance_requests = @region.client.request_spot_instances(spot_request_spec) @logger.debug("Got spot instance requests: #{@spot_instance_requests.inspect}") rescue => e raise Bosh::Clouds::VMCreationFailed.new(false), e.inspect end wait_for_spot_instance end
Private Instance Methods
cancel_pending_spot_requests()
click to toggle source
# File lib/cloud/aws/spot_manager.rb, line 113 def cancel_pending_spot_requests @logger.warn("Failed to create spot instance: #{@spot_instance_requests.inspect}. Cancelling request...") cancel_response = @region.client.cancel_spot_instance_requests( spot_instance_request_ids: spot_instance_request_ids ) @logger.warn("Spot cancel request returned: #{cancel_response.inspect}") end
create_spot_request_spec(instance_params, spot_price)
click to toggle source
# File lib/cloud/aws/spot_manager.rb, line 60 def create_spot_request_spec(instance_params, spot_price) spec = { spot_price: "#{spot_price}", instance_count: 1, launch_specification: { image_id: instance_params[:image_id], key_name: instance_params[:key_name], instance_type: instance_params[:instance_type], user_data: Base64.encode64(instance_params[:user_data]), placement: { availability_zone: instance_params[:availability_zone] }, network_interfaces: [ { subnet_id: instance_params[:subnet].subnet_id, device_index: 0, private_ip_address: instance_params[:private_ip_address] } ] } } security_groups = resolve_security_group_ids(instance_params[:security_groups]) unless security_groups.empty? spec[:launch_specification][:network_interfaces][0][:groups] = security_groups end if instance_params[:block_device_mappings] spec[:launch_specification][:block_device_mappings] = instance_params[:block_device_mappings] end spec end
fail_spot_creation(message)
click to toggle source
# File lib/cloud/aws/spot_manager.rb, line 103 def fail_spot_creation(message) @logger.warn(message) cancel_pending_spot_requests raise Bosh::Clouds::VMCreationFailed.new(false), message end
resolve_security_group_ids(security_group_names)
click to toggle source
# File lib/cloud/aws/spot_manager.rb, line 121 def resolve_security_group_ids(security_group_names) return [] unless security_group_names @region.security_groups.inject([]) do |security_group_ids, group| security_group_ids << group.security_group_id if security_group_names.include?(group.name) security_group_ids end end
spot_instance_request_ids()
click to toggle source
# File lib/cloud/aws/spot_manager.rb, line 109 def spot_instance_request_ids @spot_instance_requests[:spot_instance_request_set].map { |r| r[:spot_instance_request_id] } end
spot_instance_request_status()
click to toggle source
# File lib/cloud/aws/spot_manager.rb, line 93 def spot_instance_request_status @logger.debug('Checking state of spot instance requests...') response = @region.client.describe_spot_instance_requests( spot_instance_request_ids: spot_instance_request_ids ) status = response[:spot_instance_request_set][0] # There is only ever 1 @logger.debug("Spot instance request status: #{status.inspect}") status end
wait_for_spot_instance()
click to toggle source
# File lib/cloud/aws/spot_manager.rb, line 31 def wait_for_spot_instance instance = nil # Query the spot request state until it becomes "active". # This can result in the errors listed below; this is normally because AWS has # been slow to update its state so the correct response is to wait a bit and try again. errors = [AWS::EC2::Errors::InvalidSpotInstanceRequestID::NotFound] Bosh::Common.retryable(sleep: TOTAL_WAIT_TIME_IN_SECONDS/RETRY_COUNT, tries: RETRY_COUNT, on: errors) do |_, error| @logger.warn("Retrying after expected error: #{error}") if error status = spot_instance_request_status case status[:state] when 'failed' fail_spot_creation("VM spot instance creation failed: #{status.inspect}") when 'open' if status[:status] != nil && status[:status][:code] == 'price-too-low' fail_spot_creation("Cannot create VM spot instance because bid price is too low: #{status.inspect}. Reverting to creating ondemand instance") end when 'active' @logger.info("Spot request instances fulfilled: #{status.inspect}") instance = @region.instances[status[:instance_id]] end end instance rescue Bosh::Common::RetryCountExceeded fail_spot_creation("Timed out waiting for spot request #{@spot_instance_requests.inspect} to be fulfilled. Reverting to creating ondemand instance") end