bosh_aws_cpi 1.2624.0 → 1.2640.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c1b37050bd67d039345b8b90bf88c0e868aacd3e
4
+ data.tar.gz: a28a34c9e788be45602aea0374f5c26341097b36
5
+ SHA512:
6
+ metadata.gz: 6e5a5175fa211acd62d96f28d206af92b92a8ed71e411560f20652f529a713c6a39889db9922668b43379edd4e724d0f4bfbfbca200a3eac2bdb79f0deda4d7c
7
+ data.tar.gz: f9c44f0e8cb3f1d9e5d4be9e27aecb38d7ae0ae5bf65890bb76a6d283d87de38ff69766ad14652291e68da2eedb3e164427799a9af6f20d82a1e6484756921b7
@@ -34,16 +34,8 @@ module Bosh::AwsCloud
34
34
 
35
35
  if resource_pool["spot_bid_price"]
36
36
  @logger.info("Launching spot instance...")
37
- security_group_ids = []
38
- @region.security_groups.each do |group|
39
- security_group_ids << group.security_group_id if @instance_params[:security_groups].include?(group.name)
40
- end
41
- spot_request_spec = create_spot_request_spec(instance_params, security_group_ids, resource_pool["spot_bid_price"])
42
- @logger.debug("Requesting spot instance with: #{spot_request_spec.inspect}")
43
- spot_instance_requests = @region.client.request_spot_instances(spot_request_spec)
44
- @logger.debug("Got spot instance requests: #{spot_instance_requests.inspect}")
45
-
46
- wait_for_spot_instance_request_to_be_active spot_instance_requests
37
+ spot_manager = Bosh::AwsCloud::SpotManager.new(@region)
38
+ @instance = spot_manager.create(instance_params, resource_pool["spot_bid_price"])
47
39
  else
48
40
  # Retry the create instance operation a couple of times if we are told that the IP
49
41
  # address is in use - it can happen when the director recreates a VM and AWS
@@ -76,50 +68,6 @@ module Bosh::AwsCloud
76
68
  instance
77
69
  end
78
70
 
79
- def create_spot_request_spec(instance_params, security_group_ids, spot_price) {
80
- spot_price: "#{spot_price}",
81
- instance_count: 1,
82
- valid_until: "#{(Time.now + 20*60).utc.iso8601}",
83
- launch_specification: {
84
- image_id: instance_params[:image_id],
85
- key_name: instance_params[:key_name],
86
- instance_type: instance_params[:instance_type],
87
- user_data: Base64.encode64(instance_params[:user_data]),
88
- placement: {
89
- availability_zone: instance_params[:availability_zone]
90
- },
91
- network_interfaces: [
92
- {
93
- subnet_id: instance_params[:subnet].subnet_id,
94
- groups: security_group_ids,
95
- device_index: 0,
96
- private_ip_address: instance_params[:private_ip_address]
97
- }
98
- ]
99
- }
100
- }
101
- end
102
-
103
- def wait_for_spot_instance_request_to_be_active(spot_instance_requests)
104
- # Query the spot request state until it becomes "active".
105
- # This can result in the errors listed below; this is normally because AWS has
106
- # been slow to update its state so the correct response is to wait a bit and try again.
107
- errors = [AWS::EC2::Errors::InvalidSpotInstanceRequestID::NotFound]
108
- Bosh::Common.retryable(sleep: instance_create_wait_time*2, tries: 20, on: errors) do |tries, error|
109
- @logger.warn("Retrying after expected error: #{error}") if error
110
- @logger.debug("Checking state of spot instance requests...")
111
- spot_instance_request_ids = spot_instance_requests[:spot_instance_request_set].map { |r| r[:spot_instance_request_id] }
112
- response = @region.client.describe_spot_instance_requests(:spot_instance_request_ids => spot_instance_request_ids)
113
- statuses = response[:spot_instance_request_set].map { |rr| rr[:state] }
114
- @logger.debug("Spot instance request states: #{statuses.inspect}")
115
- if statuses.all? { |s| s == 'active' }
116
- @logger.info("Spot request instances fulfilled: #{response.inspect}")
117
- instance_id = response[:spot_instance_request_set].map { |rr| rr[:instance_id] }[0]
118
- @instance = @region.instances[instance_id]
119
- end
120
- end
121
- end
122
-
123
71
  def terminate(instance_id, fast=false)
124
72
  @instance = @region.instances[instance_id]
125
73
 
@@ -241,4 +189,4 @@ module Bosh::AwsCloud
241
189
 
242
190
  def instance_create_wait_time; 30; end
243
191
  end
244
- end
192
+ end
@@ -0,0 +1,127 @@
1
+ require "common/common"
2
+ require "time"
3
+
4
+ module Bosh::AwsCloud
5
+ class SpotManager
6
+ TOTAL_WAIT_TIME_IN_SECONDS = 300
7
+ RETRY_COUNT = 10
8
+
9
+ def initialize(region)
10
+ @region = region
11
+ @logger = Bosh::Clouds::Config.logger
12
+ end
13
+
14
+ def create(instance_params, spot_bid_price)
15
+ spot_request_spec = create_spot_request_spec(instance_params, spot_bid_price)
16
+ @logger.debug("Requesting spot instance with: #{spot_request_spec.inspect}")
17
+
18
+ begin
19
+ @spot_instance_requests = @region.client.request_spot_instances(spot_request_spec)
20
+ @logger.debug("Got spot instance requests: #{@spot_instance_requests.inspect}")
21
+ rescue => e
22
+ raise Bosh::Clouds::VMCreationFailed.new(false), e.inspect
23
+ end
24
+
25
+ request_spot_instance
26
+ end
27
+
28
+ private
29
+
30
+ def request_spot_instance
31
+ instance = nil
32
+
33
+ # Query the spot request state until it becomes "active".
34
+ # This can result in the errors listed below; this is normally because AWS has
35
+ # been slow to update its state so the correct response is to wait a bit and try again.
36
+ errors = [AWS::EC2::Errors::InvalidSpotInstanceRequestID::NotFound]
37
+ Bosh::Common.retryable(sleep: TOTAL_WAIT_TIME_IN_SECONDS/RETRY_COUNT, tries: RETRY_COUNT, on: errors) do |_, error|
38
+ @logger.warn("Retrying after expected error: #{error}") if error
39
+
40
+ status = spot_instance_request_status
41
+ case status[:state]
42
+ when 'failed'
43
+ fail_spot_creation("VM spot instance creation failed: #{status.inspect}")
44
+ when 'open'
45
+ if status[:status] != nil && status[:status][:code] == 'price-too-low'
46
+ fail_spot_creation("Cannot create VM spot instance because bid price is too low: #{status.inspect}")
47
+ end
48
+ when 'active'
49
+ @logger.info("Spot request instances fulfilled: #{status.inspect}")
50
+ instance = @region.instances[status[:instance_id]]
51
+ true
52
+ end
53
+ end
54
+
55
+ instance
56
+ rescue Bosh::Common::RetryCountExceeded
57
+ @logger.warn("Timed out waiting for spot request #{@spot_instance_requests.inspect} to be fulfilled")
58
+ cancel_pending_spot_requests
59
+ raise Bosh::Clouds::VMCreationFailed.new(true)
60
+ end
61
+
62
+ def create_spot_request_spec(instance_params, spot_price)
63
+ spec = {
64
+ spot_price: "#{spot_price}",
65
+ instance_count: 1,
66
+ launch_specification: {
67
+ image_id: instance_params[:image_id],
68
+ key_name: instance_params[:key_name],
69
+ instance_type: instance_params[:instance_type],
70
+ user_data: Base64.encode64(instance_params[:user_data]),
71
+ placement: {
72
+ availability_zone: instance_params[:availability_zone]
73
+ },
74
+ network_interfaces: [
75
+ {
76
+ subnet_id: instance_params[:subnet].subnet_id,
77
+ device_index: 0,
78
+ private_ip_address: instance_params[:private_ip_address]
79
+ }
80
+ ]
81
+ }
82
+ }
83
+ security_groups = resolve_security_group_ids(instance_params[:security_groups])
84
+ unless security_groups.empty?
85
+ spec[:launch_specification][:network_interfaces][0][:groups] = security_groups
86
+ end
87
+
88
+ spec
89
+ end
90
+
91
+ def spot_instance_request_status
92
+ @logger.debug('Checking state of spot instance requests...')
93
+ response = @region.client.describe_spot_instance_requests(
94
+ spot_instance_request_ids: spot_instance_request_ids
95
+ )
96
+ status = response[:spot_instance_request_set][0] # There is only ever 1
97
+ @logger.debug("Spot instance request status: #{status.inspect}")
98
+ status
99
+ end
100
+
101
+ def fail_spot_creation(message)
102
+ @logger.error(message)
103
+ cancel_pending_spot_requests
104
+ raise Bosh::Clouds::VMCreationFailed.new(false), message
105
+ end
106
+
107
+ def spot_instance_request_ids
108
+ @spot_instance_requests[:spot_instance_request_set].map { |r| r[:spot_instance_request_id] }
109
+ end
110
+
111
+ def cancel_pending_spot_requests
112
+ @logger.warn("Failed to create spot instance: #{@spot_instance_requests.inspect}. Cancelling request...")
113
+ cancel_response = @region.client.cancel_spot_instance_requests(
114
+ spot_instance_request_ids: spot_instance_request_ids
115
+ )
116
+ @logger.warn("Spot cancel request returned: #{cancel_response.inspect}")
117
+ end
118
+
119
+ def resolve_security_group_ids(security_group_names)
120
+ return [] unless security_group_names
121
+ @region.security_groups.inject([]) do |security_group_ids, group|
122
+ security_group_ids << group.security_group_id if security_group_names.include?(group.name)
123
+ security_group_ids
124
+ end
125
+ end
126
+ end
127
+ end
@@ -1,5 +1,5 @@
1
1
  module Bosh
2
2
  module AwsCloud
3
- VERSION = '1.2624.0'
3
+ VERSION = '1.2640.0'
4
4
  end
5
5
  end
data/lib/cloud/aws.rb CHANGED
@@ -32,6 +32,7 @@ require "cloud/aws/dynamic_network"
32
32
  require "cloud/aws/manual_network"
33
33
  require "cloud/aws/vip_network"
34
34
  require "cloud/aws/instance_manager"
35
+ require "cloud/aws/spot_manager"
35
36
  require "cloud/aws/tag_manager"
36
37
  require "cloud/aws/availability_zone_selector"
37
38
  require "cloud/aws/resource_wait"
metadata CHANGED
@@ -1,84 +1,74 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bosh_aws_cpi
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2624.0
5
- prerelease:
4
+ version: 1.2640.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - VMware
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2014-07-01 00:00:00.000000000 Z
11
+ date: 2014-07-08 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: aws-sdk
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
17
  - - '='
20
18
  - !ruby/object:Gem::Version
21
- version: 1.32.0
19
+ version: 1.44.0
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
24
  - - '='
28
25
  - !ruby/object:Gem::Version
29
- version: 1.32.0
26
+ version: 1.44.0
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: bosh_common
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
- - - ~>
31
+ - - "~>"
36
32
  - !ruby/object:Gem::Version
37
- version: 1.2624.0
33
+ version: 1.2640.0
38
34
  type: :runtime
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
- - - ~>
38
+ - - "~>"
44
39
  - !ruby/object:Gem::Version
45
- version: 1.2624.0
40
+ version: 1.2640.0
46
41
  - !ruby/object:Gem::Dependency
47
42
  name: bosh_cpi
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
- - - ~>
45
+ - - "~>"
52
46
  - !ruby/object:Gem::Version
53
- version: 1.2624.0
47
+ version: 1.2640.0
54
48
  type: :runtime
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
- - - ~>
52
+ - - "~>"
60
53
  - !ruby/object:Gem::Version
61
- version: 1.2624.0
54
+ version: 1.2640.0
62
55
  - !ruby/object:Gem::Dependency
63
56
  name: bosh-registry
64
57
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
58
  requirements:
67
- - - ~>
59
+ - - "~>"
68
60
  - !ruby/object:Gem::Version
69
- version: 1.2624.0
61
+ version: 1.2640.0
70
62
  type: :runtime
71
63
  prerelease: false
72
64
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
65
  requirements:
75
- - - ~>
66
+ - - "~>"
76
67
  - !ruby/object:Gem::Version
77
- version: 1.2624.0
68
+ version: 1.2640.0
78
69
  - !ruby/object:Gem::Dependency
79
70
  name: httpclient
80
71
  requirement: !ruby/object:Gem::Requirement
81
- none: false
82
72
  requirements:
83
73
  - - '='
84
74
  - !ruby/object:Gem::Version
@@ -86,7 +76,6 @@ dependencies:
86
76
  type: :runtime
87
77
  prerelease: false
88
78
  version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
79
  requirements:
91
80
  - - '='
92
81
  - !ruby/object:Gem::Version
@@ -94,28 +83,27 @@ dependencies:
94
83
  - !ruby/object:Gem::Dependency
95
84
  name: yajl-ruby
96
85
  requirement: !ruby/object:Gem::Requirement
97
- none: false
98
86
  requirements:
99
- - - ! '>='
87
+ - - ">="
100
88
  - !ruby/object:Gem::Version
101
89
  version: 0.8.2
102
90
  type: :runtime
103
91
  prerelease: false
104
92
  version_requirements: !ruby/object:Gem::Requirement
105
- none: false
106
93
  requirements:
107
- - - ! '>='
94
+ - - ">="
108
95
  - !ruby/object:Gem::Version
109
96
  version: 0.8.2
110
- description: ! 'BOSH AWS CPI
111
-
112
- 03f604'
97
+ description: |-
98
+ BOSH AWS CPI
99
+ 986896
113
100
  email: support@cloudfoundry.com
114
101
  executables:
115
102
  - bosh_aws_console
116
103
  extensions: []
117
104
  extra_rdoc_files: []
118
105
  files:
106
+ - README.md
119
107
  - bin/bosh_aws_console
120
108
  - lib/bosh_aws_cpi.rb
121
109
  - lib/cloud/aws.rb
@@ -130,6 +118,7 @@ files:
130
118
  - lib/cloud/aws/network.rb
131
119
  - lib/cloud/aws/network_configurator.rb
132
120
  - lib/cloud/aws/resource_wait.rb
121
+ - lib/cloud/aws/spot_manager.rb
133
122
  - lib/cloud/aws/stemcell.rb
134
123
  - lib/cloud/aws/stemcell_creator.rb
135
124
  - lib/cloud/aws/stemcell_finder.rb
@@ -137,33 +126,28 @@ files:
137
126
  - lib/cloud/aws/version.rb
138
127
  - lib/cloud/aws/vip_network.rb
139
128
  - scripts/stemcell-copy.sh
140
- - README.md
141
129
  homepage: https://github.com/cloudfoundry/bosh
142
130
  licenses:
143
131
  - Apache 2.0
132
+ metadata: {}
144
133
  post_install_message:
145
134
  rdoc_options: []
146
135
  require_paths:
147
136
  - lib
148
137
  required_ruby_version: !ruby/object:Gem::Requirement
149
- none: false
150
138
  requirements:
151
- - - ! '>='
139
+ - - ">="
152
140
  - !ruby/object:Gem::Version
153
141
  version: 1.9.3
154
142
  required_rubygems_version: !ruby/object:Gem::Requirement
155
- none: false
156
143
  requirements:
157
- - - ! '>='
144
+ - - ">="
158
145
  - !ruby/object:Gem::Version
159
146
  version: '0'
160
- segments:
161
- - 0
162
- hash: 3736547469633169504
163
147
  requirements: []
164
148
  rubyforge_project:
165
- rubygems_version: 1.8.23.2
149
+ rubygems_version: 2.2.2
166
150
  signing_key:
167
- specification_version: 3
151
+ specification_version: 4
168
152
  summary: BOSH AWS CPI
169
153
  test_files: []