bosh_aws_cpi 1.2624.0 → 1.2640.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: []