openstudio-aws 0.3.2 → 0.4.0.alpha1
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 +4 -4
- data/.gitignore +2 -2
- data/CHANGELOG.md +8 -3
- data/Gemfile +1 -1
- data/lib/openstudio/aws/aws.rb +109 -58
- data/lib/openstudio/aws/config.rb +16 -35
- data/lib/openstudio/aws/version.rb +1 -1
- data/lib/openstudio/core_ext/hash.rb +22 -0
- data/lib/openstudio/lib/ami_list.rb +29 -3
- data/lib/openstudio/lib/openstudio_aws_instance.rb +16 -14
- data/lib/openstudio/lib/openstudio_aws_logger.rb +1 -2
- data/lib/openstudio/lib/openstudio_aws_wrapper.rb +71 -23
- data/lib/openstudio/lib/openstudio_cloud_watch.rb +55 -0
- data/lib/openstudio/lib/server_script.sh.template +1 -19
- data/lib/openstudio/lib/worker_script.sh.template +8 -17
- data/lib/openstudio-aws.rb +4 -1
- data/openstudio-aws.gemspec +2 -2
- data/spec/aws_instances/aws_spec_api.rb +86 -58
- data/spec/openstudio-aws/ami_list_spec.rb +9 -0
- data/spec/openstudio-aws/aws_spec.rb +23 -1
- data/spec/openstudio-aws/aws_wrapper_spec.rb +3 -2
- data/spec/openstudio-aws/config_spec.rb +0 -44
- metadata +9 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0caae029f8b89a624ac2eae705dd9116f6fb73d6
|
4
|
+
data.tar.gz: 9027677347681dfda91f3b57bdf4266ec4da5822
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 92220c6aa21ced920173e584686c10546bc92bb2c2d5668dc911668ffd7fb5c38ea34e4c82793f329e2a0d37d19602667afb03a76c81224ac9bfb004244f815b
|
7
|
+
data.tar.gz: c8b09f832050cc296425ee4a08b1cb95fba8002dd151a794b0fab0895afdf8752b197da29e7a476148ebdb827ae6fc6bd25ce05227ebf66968b93327bd138d58
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,12 +1,17 @@
|
|
1
1
|
OpenStudio AWS Gem Change Log
|
2
2
|
==================================
|
3
3
|
|
4
|
-
Version 0.
|
4
|
+
Version 0.4.0.alpha1
|
5
5
|
-------------
|
6
6
|
* Add a stable JSON file that can be used to flag which versions of the server are stable (used by OpenStudio PAT).
|
7
|
+
* Remove all puts and replace with logger. This is required because OpenStudio PAT reads the result from the command line.
|
7
8
|
* Add the method `describe_availability_zones` to the root AWS class
|
8
|
-
*
|
9
|
-
*
|
9
|
+
* Add the method `total_instances_count` to the root AWS class
|
10
|
+
* Add method to list status of all instances in the group
|
11
|
+
* Add method to `delete_key_pair`
|
12
|
+
* Add launch time to the server data struct
|
13
|
+
* Add cloud watch class to calculate the cost
|
14
|
+
* Add save_directory to override the default path to save private keys and server configuration files
|
10
15
|
|
11
16
|
Version 0.3.1
|
12
17
|
-------------
|
data/Gemfile
CHANGED
data/lib/openstudio/aws/aws.rb
CHANGED
@@ -3,18 +3,29 @@ module OpenStudio
|
|
3
3
|
module Aws
|
4
4
|
VALID_OPTIONS = [
|
5
5
|
:proxy, :credentials, :ami_lookup_version, :openstudio_version,
|
6
|
-
:openstudio_server_version, :region, :ssl_verify_peer, :host, :url, :stable
|
6
|
+
:openstudio_server_version, :region, :ssl_verify_peer, :host, :url, :stable,
|
7
|
+
:save_directory
|
7
8
|
]
|
8
9
|
|
9
10
|
class Aws
|
11
|
+
include Logging
|
12
|
+
|
10
13
|
# Deprecate OS_AWS object
|
11
14
|
attr_reader :os_aws
|
12
15
|
attr_reader :default_amis
|
16
|
+
attr_reader :save_directory
|
13
17
|
|
14
18
|
# default constructor to create the AWS class that can spin up server and worker instances.
|
15
19
|
# options are optional with the following support:
|
16
20
|
# credentials => {:access_key_id, :secret_access_key, :region, :ssl_verify_peer}
|
17
21
|
# proxy => {:host => "192.168.0.1", :port => "8808", :username => "user", :password => "password"}}
|
22
|
+
# @param options [Hash]
|
23
|
+
# @option options [Boolean] :openstudio_version Version of OpenStudio in which to do the lookup for the server
|
24
|
+
# AMIs. This cannot be used in conjunction with the :openstudio_server_version.
|
25
|
+
# @option options [Boolean] :openstudio_server_version Version of OpenStudio Server in which to do the lookup for
|
26
|
+
# the server AMIs. This cannot be used in conjunction with the :openstudio_server_version
|
27
|
+
# @option options [Boolean] :stable (false) Find a stable version less than or equal to the version that is passed in the
|
28
|
+
# version field
|
18
29
|
def initialize(options = {})
|
19
30
|
invalid_options = options.keys - VALID_OPTIONS
|
20
31
|
if invalid_options.any?
|
@@ -25,9 +36,15 @@ module OpenStudio
|
|
25
36
|
defaults = {
|
26
37
|
ami_lookup_version: 1,
|
27
38
|
region: 'us-east-1',
|
28
|
-
ssl_verify_peer: false
|
39
|
+
ssl_verify_peer: false,
|
40
|
+
save_directory: '.'
|
29
41
|
}
|
30
42
|
options = defaults.merge(options)
|
43
|
+
logger.info "AWS initialized with the options: #{options.except(:credentials)}"
|
44
|
+
|
45
|
+
# set the save path
|
46
|
+
@save_directory = File.expand_path options[:save_directory]
|
47
|
+
FileUtils.mkdir_p @save_directory unless Dir.exist? @save_directory
|
31
48
|
|
32
49
|
# read in the config.yml file to get the secret/private key
|
33
50
|
if !options[:credentials]
|
@@ -53,19 +70,11 @@ module OpenStudio
|
|
53
70
|
else
|
54
71
|
proxy_uri = "https://#{options[:proxy][:host]}:#{options[:proxy][:port]}"
|
55
72
|
end
|
56
|
-
# TODO: remove this proxy_uri and make a method to format correctly
|
57
73
|
options[:proxy_uri] = proxy_uri
|
58
|
-
|
59
|
-
# TODO: do we need to escape a couple of the argument of username and password
|
60
|
-
|
61
|
-
# TODO: set some environment variables for system based proxy
|
62
74
|
end
|
63
75
|
|
64
|
-
# puts "Final options are: #{options.inspect}"
|
65
|
-
|
66
76
|
@os_aws = OpenStudioAwsWrapper.new(options)
|
67
|
-
|
68
|
-
@instances_filename = nil
|
77
|
+
@os_cloudwatch = OpenStudioCloudWatch.new(options)
|
69
78
|
|
70
79
|
# this will grab the default version of openstudio ami versions
|
71
80
|
# get the arugments for the AMI lookup
|
@@ -85,10 +94,10 @@ module OpenStudio
|
|
85
94
|
#
|
86
95
|
# end
|
87
96
|
|
88
|
-
# command line call to create a new instance. This should be more tightly integrated with
|
89
|
-
def create_server(options = {}
|
97
|
+
# command line call to create a new instance. This should be more tightly integrated with the os-aws.rb gem
|
98
|
+
def create_server(options = {})
|
90
99
|
defaults = {
|
91
|
-
instance_type: '
|
100
|
+
instance_type: 'm3.xlarge',
|
92
101
|
security_groups: [],
|
93
102
|
image_id: @default_amis[:server],
|
94
103
|
user_id: 'unknown_user',
|
@@ -129,7 +138,7 @@ module OpenStudio
|
|
129
138
|
@os_aws.private_key_file_name = options[:private_key_file_name]
|
130
139
|
else
|
131
140
|
# Save the private key if you did not pass in an already existing key_pair_name
|
132
|
-
@os_aws.save_private_key(
|
141
|
+
@os_aws.save_private_key(@save_directory)
|
133
142
|
end
|
134
143
|
|
135
144
|
server_options = {
|
@@ -141,22 +150,30 @@ module OpenStudio
|
|
141
150
|
|
142
151
|
# save the worker pem and public to the directory
|
143
152
|
# presently, this will always overwrite the worker key, is that okay? Is this really needed later?
|
144
|
-
@os_aws.save_worker_keys(
|
153
|
+
@os_aws.save_worker_keys(@save_directory)
|
145
154
|
|
146
155
|
# if instance_data[:ebs_volume_id]
|
147
156
|
# server_options[:ebs_volume_id] = instance_data[:ebs_volume_id]
|
148
157
|
# end
|
149
158
|
|
150
159
|
@os_aws.launch_server(options[:image_id], options[:instance_type], server_options)
|
160
|
+
end
|
151
161
|
|
152
|
-
|
153
|
-
|
154
|
-
|
162
|
+
# Write out to the terminal the connection information for the servers and workers
|
163
|
+
#
|
164
|
+
# @return [nil] Only prints to the screen. No return is expected
|
165
|
+
def print_connection_info
|
155
166
|
# Print out some debugging commands (probably work on mac/linux only)
|
156
167
|
puts ''
|
157
168
|
puts 'Server SSH Command:'
|
158
|
-
|
159
169
|
puts "ssh -i #{@os_aws.private_key_file_name} ubuntu@#{@os_aws.server.data[:dns]}"
|
170
|
+
if @os_aws.workers.size > 0
|
171
|
+
puts ''
|
172
|
+
puts 'Worker SSH Command:'
|
173
|
+
@os_aws.workers.each do |worker|
|
174
|
+
puts "ssh -i #{@os_aws.private_key_file_name} ubuntu@#{worker.data[:dns]}"
|
175
|
+
end
|
176
|
+
end
|
160
177
|
end
|
161
178
|
|
162
179
|
def create_workers(number_of_instances, options = {}, user_id = 'unknown_user')
|
@@ -176,7 +193,7 @@ module OpenStudio
|
|
176
193
|
}
|
177
194
|
options = defaults.merge(options)
|
178
195
|
|
179
|
-
# for backwards
|
196
|
+
# for backwards compatibility, still allow security_group
|
180
197
|
if options[:security_group]
|
181
198
|
warn 'Pass security_groups as an array instead of security_group. security_group will be deprecated in 0.4.0'
|
182
199
|
options[:security_groups] = [options[:security_group]]
|
@@ -189,10 +206,7 @@ module OpenStudio
|
|
189
206
|
|
190
207
|
fail "Can't create workers without a server instance running" if @os_aws.server.nil?
|
191
208
|
|
192
|
-
|
193
|
-
puts ''
|
194
|
-
puts 'No workers requested'
|
195
|
-
else
|
209
|
+
unless number_of_instances == 0
|
196
210
|
worker_options = {
|
197
211
|
user_id: options[:user_id],
|
198
212
|
tags: options[:tags],
|
@@ -205,19 +219,9 @@ module OpenStudio
|
|
205
219
|
# end
|
206
220
|
|
207
221
|
@os_aws.launch_workers(options[:image_id], options[:instance_type], number_of_instances, worker_options)
|
208
|
-
|
209
|
-
# Add the worker data to the JSON
|
210
|
-
save_cluster_json @instances_filename
|
211
|
-
|
212
|
-
puts ''
|
213
|
-
puts 'Worker SSH Command:'
|
214
|
-
@os_aws.workers.each do |worker|
|
215
|
-
puts "ssh -i #{@os_aws.private_key_file_name} ubuntu@#{worker.data[:dns]}"
|
216
|
-
end
|
217
222
|
end
|
218
223
|
|
219
|
-
|
220
|
-
puts 'Waiting for server/worker configurations'
|
224
|
+
logger.info 'Waiting for server/worker configurations'
|
221
225
|
|
222
226
|
@os_aws.configure_server_and_workers
|
223
227
|
end
|
@@ -232,8 +236,9 @@ module OpenStudio
|
|
232
236
|
end
|
233
237
|
|
234
238
|
# Save a JSON with information about the cluster that was configured.
|
239
|
+
#
|
235
240
|
# @param filename [String] Path and filename to save the JSON file
|
236
|
-
def
|
241
|
+
def save_cluster_info(filename)
|
237
242
|
File.open(filename, 'w') { |f| f << JSON.pretty_generate(cluster_info) }
|
238
243
|
end
|
239
244
|
|
@@ -242,29 +247,71 @@ module OpenStudio
|
|
242
247
|
@os_aws.describe_availability_zones
|
243
248
|
end
|
244
249
|
|
245
|
-
#
|
246
|
-
|
247
|
-
|
250
|
+
# Delete the key pair. Make sure that this happens at the end of whatever you are running, because you
|
251
|
+
# will not be able to connect to the instance after you do this.
|
252
|
+
def delete_key_pair
|
253
|
+
@os_aws.delete_key_pair
|
254
|
+
end
|
248
255
|
|
249
|
-
|
256
|
+
# Return the description of the instances in the GroupUUID
|
257
|
+
#
|
258
|
+
# @example Return Example
|
259
|
+
# [{:instance_id=>"i-45f924ac",
|
260
|
+
# :image_id=>"ami-845a54ec",
|
261
|
+
# :state=>{:code=>48, :name=>"terminated"},
|
262
|
+
# :private_dns_name=>"",
|
263
|
+
# :public_dns_name=>"",
|
264
|
+
# :state_transition_reason=>"User initiated (2015-06-01 21:50:40 GMT)",
|
265
|
+
# :key_name=>"os-key-pair-275a3bf436004c04a1a347ff36337f16",
|
266
|
+
# :ami_launch_index=>0,
|
267
|
+
# :product_codes=>[],
|
268
|
+
# :instance_type=>"m3.medium",
|
269
|
+
# :launch_time=>2015-06-01 21:13:18 UTC,
|
270
|
+
# :placement=>
|
271
|
+
# {:availability_zone=>"us-east-1e", :group_name=>"", :tenancy=>"default"},
|
272
|
+
# :monitoring=>{:state=>"disabled"},
|
273
|
+
# :state_reason=>
|
274
|
+
# {:code=>"Client.UserInitiatedShutdown",
|
275
|
+
# :message=>"Client.UserInitiatedShutdown: User initiated shutdown"},
|
276
|
+
# :architecture=>"x86_64",
|
277
|
+
# :root_device_type=>"ebs",
|
278
|
+
# :root_device_name=>"/dev/sda1",
|
279
|
+
# :block_device_mappings=>[],
|
280
|
+
# :virtualization_type=>"hvm",
|
281
|
+
# :client_token=>"",
|
282
|
+
# :tags=>
|
283
|
+
# [{:key=>"Purpose", :value=>"OpenStudioServer"},
|
284
|
+
# {:key=>"NumberOfProcessors", :value=>"1"},
|
285
|
+
# {:key=>"GroupUUID", :value=>"275a3bf436004c04a1a347ff36337f16"},
|
286
|
+
# {:key=>"Name", :value=>"OpenStudio-Server"},
|
287
|
+
# {:key=>"UserID", :value=>"unknown_user"}],
|
288
|
+
# :security_groups=>
|
289
|
+
# [{:group_name=>"openstudio-server-sg-v2.1", :group_id=>"sg-8740f3ea"}],
|
290
|
+
# :hypervisor=>"xen",
|
291
|
+
# :network_interfaces=>[],
|
292
|
+
# :ebs_optimized=>false}]
|
293
|
+
def describe_instances
|
294
|
+
@os_aws.describe_instances
|
250
295
|
end
|
251
296
|
|
252
|
-
#
|
253
|
-
def
|
254
|
-
|
255
|
-
|
297
|
+
# Return the list of all the instances that are running on the account in the availablity zone
|
298
|
+
def total_instances_count
|
299
|
+
@os_aws.total_instances_count
|
300
|
+
end
|
256
301
|
|
257
|
-
|
258
|
-
|
259
|
-
|
302
|
+
# Return the estimated cost for EC2 instances
|
303
|
+
def estimated_charges
|
304
|
+
@os_cloudwatch.estimated_charges
|
260
305
|
end
|
261
306
|
|
262
|
-
#
|
263
|
-
|
264
|
-
|
307
|
+
# Stop running instances
|
308
|
+
#
|
309
|
+
# @param group_id [String] The unique group identifier for the OpenStudio cluster.
|
310
|
+
# @param openstudio_instance_type [Symbol] The type of instance (:server or :worker)
|
311
|
+
def stop_instances(group_id, openstudio_instance_type)
|
312
|
+
instances = @os_aws.describe_running_instances(group_id, openstudio_instance_type.to_sym)
|
265
313
|
ids = instances.map { |k, _| k[:instance_id] }
|
266
314
|
|
267
|
-
puts "Stoping the following instances #{ids}"
|
268
315
|
resp = []
|
269
316
|
resp = @os_aws.stop_instances(ids).to_hash unless ids.empty?
|
270
317
|
resp
|
@@ -272,26 +319,30 @@ module OpenStudio
|
|
272
319
|
|
273
320
|
# @params(ids): array of instance ids
|
274
321
|
def terminate_instances(ids)
|
275
|
-
|
322
|
+
logger.info "Terminating the following instances #{ids}"
|
276
323
|
resp = []
|
277
324
|
resp = @os_aws.terminate_instances(ids).to_hash unless ids.empty?
|
278
325
|
resp
|
279
326
|
end
|
280
327
|
|
281
|
-
# Warning,
|
328
|
+
# Warning, this appears that it terminates all the instances
|
282
329
|
def terminate_instances_by_group_id(group_id)
|
330
|
+
fail "Group ID not defined" unless group_id
|
331
|
+
|
283
332
|
instances = @os_aws.describe_running_instances(group_id)
|
333
|
+
logger.info instances
|
284
334
|
ids = instances.map { |k, _| k[:instance_id] }
|
285
335
|
|
286
|
-
|
336
|
+
logger.info "Terminating the following instances #{ids}"
|
287
337
|
resp = []
|
288
338
|
resp = @os_aws.terminate_instances(ids).to_hash unless ids.empty?
|
339
|
+
|
289
340
|
resp[:terminating_instances].first[:current_state][:name] == 'shutting-down'
|
290
341
|
end
|
291
342
|
|
292
|
-
# Terminate the entire cluster
|
343
|
+
# Terminate the entire cluster based on the member variable's group_uuid.
|
293
344
|
def terminate
|
294
|
-
|
345
|
+
logger.info "Terminating any instance with GroupUUID: #{@os_aws.group_uuid}"
|
295
346
|
|
296
347
|
terminate_instances_by_group_id(@os_aws.group_uuid)
|
297
348
|
end
|
@@ -303,7 +354,7 @@ module OpenStudio
|
|
303
354
|
if h[:location] == 'AWS'
|
304
355
|
@os_aws.find_server(h)
|
305
356
|
else
|
306
|
-
|
357
|
+
logger.info "Instance file '#{filename}' does not have the location of 'AWS'"
|
307
358
|
return false
|
308
359
|
end
|
309
360
|
|
@@ -1,57 +1,38 @@
|
|
1
1
|
module OpenStudio
|
2
2
|
module Aws
|
3
3
|
class Config
|
4
|
-
include Logging
|
5
|
-
|
6
4
|
attr_accessor :access_key
|
7
5
|
attr_accessor :secret_key
|
8
6
|
|
9
7
|
def initialize(yml_config_file = nil)
|
10
|
-
|
11
|
-
@
|
12
|
-
@secret_key = ENV['AWS_SECRET_ACCESS_KEY'] if ENV['AWS_SECRET_ACCESS_KEY']
|
13
|
-
|
14
|
-
if @access_key && @secret_key && yml_config_file.nil?
|
15
|
-
logger.info 'Using AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY from environment variables'
|
16
|
-
else
|
17
|
-
# Otherwise read the file
|
18
|
-
logger.info 'Reading AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY from aws config file'
|
19
|
-
|
20
|
-
@yml_config_file = yml_config_file
|
21
|
-
@config = nil
|
22
|
-
|
23
|
-
@yml_config_file = File.join(File.expand_path('~'), 'aws_config.yml') if @yml_config_file.nil?
|
8
|
+
@yml_config_file = yml_config_file
|
9
|
+
@config = nil
|
24
10
|
|
11
|
+
if @yml_config_file.nil?
|
12
|
+
@yml_config_file = File.join(File.expand_path('~'), 'aws_config.yml')
|
25
13
|
unless File.exist?(@yml_config_file)
|
26
14
|
write_config_file
|
27
|
-
fail "Config
|
15
|
+
fail "No Config File in user home directory. A template has been added, please edit and save: #{@yml_config_file}"
|
28
16
|
exit 1
|
29
17
|
end
|
18
|
+
end
|
30
19
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
@access_key = @config[:access_key_id]
|
38
|
-
@secret_key = @config[:secret_access_key]
|
39
|
-
rescue
|
40
|
-
raise "Couldn't read config file #{@yml_config_file}. Delete file then recreate by rerunning script"
|
41
|
-
end
|
20
|
+
begin
|
21
|
+
@config = YAML.load(File.read(@yml_config_file))
|
22
|
+
@access_key = @config['access_key_id']
|
23
|
+
@secret_key = @config['secret_access_key']
|
24
|
+
rescue
|
25
|
+
raise "Couldn't read config file #{@yml_config_file}. Delete file then recreate by rerunning script"
|
42
26
|
end
|
43
27
|
end
|
44
28
|
|
45
29
|
private
|
46
30
|
|
47
31
|
def write_config_file
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
}
|
53
|
-
|
54
|
-
File.open(@yml_config_file, 'w') { |f| f << data.to_yaml }
|
32
|
+
File.open(@yml_config_file, 'w') do |f|
|
33
|
+
f << "access_key_id: YOUR_ACCESS_KEY_ID\n"
|
34
|
+
f << "secret_access_key: YOUR_SECRET_ACCESS_KEY\n"
|
35
|
+
end
|
55
36
|
end
|
56
37
|
end
|
57
38
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# From: https://github.com/rails/rails/blob/001b270611cd9cb653124775899bdbc2548333ab/activesupport/lib/active_support/core_ext/hash/except.rb
|
2
|
+
class Hash
|
3
|
+
# Returns a hash that includes everything but the given keys.
|
4
|
+
# hash = { a: true, b: false, c: nil}
|
5
|
+
# hash.except(:c) # => { a: true, b: false}
|
6
|
+
# hash # => { a: true, b: false, c: nil}
|
7
|
+
#
|
8
|
+
# This is useful for limiting a set of parameters to everything but a few known toggles:
|
9
|
+
# @person.update(params[:person].except(:admin))
|
10
|
+
def except(*keys)
|
11
|
+
dup.except!(*keys)
|
12
|
+
end
|
13
|
+
|
14
|
+
# Replaces the hash without the given keys.
|
15
|
+
# hash = { a: true, b: false, c: nil}
|
16
|
+
# hash.except!(:c) # => { a: true, b: false}
|
17
|
+
# hash # => { a: true, b: false }
|
18
|
+
def except!(*keys)
|
19
|
+
keys.each { |key| delete(key) }
|
20
|
+
self
|
21
|
+
end
|
22
|
+
end
|
@@ -21,6 +21,8 @@
|
|
21
21
|
# Class for managing the AMI ids based on the openstudio version and the openstudio-server version
|
22
22
|
|
23
23
|
class OpenStudioAmis
|
24
|
+
include Logging
|
25
|
+
|
24
26
|
VALID_OPTIONS = [
|
25
27
|
:openstudio_version, :openstudio_server_version, :host, :url, :stable
|
26
28
|
]
|
@@ -100,6 +102,7 @@ class OpenStudioAmis
|
|
100
102
|
json[version]
|
101
103
|
end
|
102
104
|
|
105
|
+
# Return the AMIs for the server and worker. Version 2 also does a lookup of the stable version
|
103
106
|
def get_ami_version_2
|
104
107
|
json = list
|
105
108
|
|
@@ -114,9 +117,29 @@ class OpenStudioAmis
|
|
114
117
|
elsif @options[:openstudio_version] != 'default'
|
115
118
|
if @options[:stable]
|
116
119
|
stable = json[:openstudio][@options[:openstudio_version].to_sym][:stable]
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
+
if stable
|
121
|
+
value = json[:openstudio][@options[:openstudio_version].to_sym][stable.to_sym]
|
122
|
+
amis = value[:amis]
|
123
|
+
else
|
124
|
+
logger.info "Could not find a stable version for OpenStudio version #{@options[:openstudio_version]}. "\
|
125
|
+
"Looking up older versions to find the latest stable." unless stable
|
126
|
+
|
127
|
+
json[:openstudio].each do |os_version, values|
|
128
|
+
next if os_version == :default
|
129
|
+
if values.key? :stable
|
130
|
+
# don't check versions newer than what we are requesting
|
131
|
+
next if os_version.to_s.to_version > @options[:openstudio_version].to_s.to_version
|
132
|
+
stable = json[:openstudio][os_version][:stable]
|
133
|
+
logger.info "Found a stable version for OpenStudio version #{os_version} with OpenStudio Server version #{stable}"
|
134
|
+
value = values[stable.to_sym]
|
135
|
+
amis = value[:amis]
|
136
|
+
|
137
|
+
break
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
fail "Could not find a stable version for openstudio version #{@options[:openstudio_version]}" unless amis
|
142
|
+
end
|
120
143
|
else
|
121
144
|
# return the default version (which is the latest)
|
122
145
|
default = json[:openstudio][@options[:openstudio_version].to_sym][:default]
|
@@ -126,6 +149,8 @@ class OpenStudioAmis
|
|
126
149
|
end
|
127
150
|
end
|
128
151
|
|
152
|
+
logger.info "AMI IDs are #{amis}" if amis
|
153
|
+
|
129
154
|
amis
|
130
155
|
end
|
131
156
|
|
@@ -138,6 +163,7 @@ class OpenStudioAmis
|
|
138
163
|
|
139
164
|
url = URI.parse(uri_str)
|
140
165
|
req = Net::HTTP::Get.new(url.path)
|
166
|
+
logger.info "Fetching AMI list from #{uri_str}"
|
141
167
|
response = Net::HTTP.start(url.host, url.port) { |http| http.request(req) }
|
142
168
|
case response
|
143
169
|
when Net::HTTPSuccess then
|
@@ -1,4 +1,3 @@
|
|
1
|
-
# NOTE: Do not modify this file as it is copied over. Modify the source file and rerun rake import_files
|
2
1
|
######################################################################
|
3
2
|
# Copyright (c) 2008-2014, Alliance for Sustainable Energy.
|
4
3
|
# All rights reserved.
|
@@ -36,7 +35,7 @@ class OpenStudioAwsInstance
|
|
36
35
|
@key_pair_name = key_pair_name
|
37
36
|
@security_groups = security_groups
|
38
37
|
@group_uuid = group_uuid.to_s
|
39
|
-
@init_timestamp = Time.now
|
38
|
+
@init_timestamp = Time.now # This is the timestamp and is typically just tracked for the server
|
40
39
|
@private_key = private_key
|
41
40
|
@private_key_file_name = private_key_file_name
|
42
41
|
@proxy = proxy
|
@@ -141,12 +140,12 @@ class OpenStudioAwsInstance
|
|
141
140
|
t = tag.split('=')
|
142
141
|
if t.size != 2
|
143
142
|
logger.error "Tag '#{t}' not defined or does not have an equal sign"
|
144
|
-
|
143
|
+
fail "Tag '#{t}' not defined or does not have an equal sign"
|
145
144
|
next
|
146
145
|
end
|
147
146
|
if %w(Name GroupUUID NumberOfProcessors Purpose UserID).include? t[0]
|
148
147
|
logger.error "Tag name '#{t[0]}' is a reserved tag"
|
149
|
-
|
148
|
+
fail "Tag name '#{t[0]}' is a reserved tag"
|
150
149
|
next
|
151
150
|
end
|
152
151
|
|
@@ -162,7 +161,7 @@ class OpenStudioAwsInstance
|
|
162
161
|
tags: aws_tags
|
163
162
|
)
|
164
163
|
rescue Aws::EC2::Errors::InvalidInstanceIDNotFound
|
165
|
-
sleep
|
164
|
+
sleep 5
|
166
165
|
retry unless (tries -= 1).zero?
|
167
166
|
end
|
168
167
|
|
@@ -270,6 +269,8 @@ class OpenStudioAwsInstance
|
|
270
269
|
processors = 1
|
271
270
|
if lookup.key?(instance)
|
272
271
|
processors = lookup[instance]
|
272
|
+
else
|
273
|
+
# logger.warn "Could not find the number of processors for instance type of #{instance}" if logger
|
273
274
|
end
|
274
275
|
|
275
276
|
if @openstudio_instance_type == :server
|
@@ -306,13 +307,13 @@ class OpenStudioAwsInstance
|
|
306
307
|
# port 22 might not be available immediately after the instance finishes launching
|
307
308
|
return if retries == 5
|
308
309
|
retries += 1
|
309
|
-
sleep
|
310
|
+
sleep 2
|
310
311
|
retry
|
311
312
|
rescue
|
312
313
|
# Unknown upload error, retry
|
313
314
|
return if retries == 5
|
314
315
|
retries += 1
|
315
|
-
sleep
|
316
|
+
sleep 2
|
316
317
|
retry
|
317
318
|
end
|
318
319
|
end
|
@@ -342,11 +343,11 @@ class OpenStudioAwsInstance
|
|
342
343
|
rescue Net::SSH::HostKeyMismatch => e
|
343
344
|
e.remember_host!
|
344
345
|
logger.info('key mismatch, retry')
|
345
|
-
sleep
|
346
|
+
sleep 2
|
346
347
|
retry
|
347
348
|
rescue SystemCallError, Timeout::Error => e
|
348
349
|
# port 22 might not be available immediately after the instance finishes launching
|
349
|
-
sleep
|
350
|
+
sleep 2
|
350
351
|
logger.info('SystemCallError, Waiting for SSH to become available')
|
351
352
|
retry
|
352
353
|
end
|
@@ -391,7 +392,7 @@ class OpenStudioAwsInstance
|
|
391
392
|
rescue SystemCallError, Timeout::Error => e
|
392
393
|
# port 22 might not be available immediately after the instance finishes launching
|
393
394
|
sleep 10
|
394
|
-
logger.info('Timeout. Perhaps there is a communication error to EC2? Will try again
|
395
|
+
logger.info('Timeout. Perhaps there is a communication error to EC2? Will try again')
|
395
396
|
retry
|
396
397
|
end
|
397
398
|
|
@@ -405,12 +406,12 @@ class OpenStudioAwsInstance
|
|
405
406
|
# port 22 might not be available immediately after the instance finishes launching
|
406
407
|
return if retries == 5
|
407
408
|
retries += 1
|
408
|
-
sleep
|
409
|
+
sleep 2
|
409
410
|
retry
|
410
411
|
rescue
|
411
412
|
return if retries == 5
|
412
413
|
retries += 1
|
413
|
-
sleep
|
414
|
+
sleep 2
|
414
415
|
retry
|
415
416
|
end
|
416
417
|
end
|
@@ -420,7 +421,7 @@ class OpenStudioAwsInstance
|
|
420
421
|
# store some of the data into a custom struct. The instance is the full description. The remaining fields are
|
421
422
|
# just easier accessors to the data in the raw request except for procs which is a custom request.
|
422
423
|
def create_struct(instance, procs)
|
423
|
-
instance_struct = Struct.new(:instance, :id, :ip, :dns, :procs, :availability_zone, :private_ip_address)
|
424
|
+
instance_struct = Struct.new(:instance, :id, :ip, :dns, :procs, :availability_zone, :private_ip_address, :launch_time)
|
424
425
|
s = instance_struct.new(
|
425
426
|
instance,
|
426
427
|
instance[:instance_id],
|
@@ -428,7 +429,8 @@ class OpenStudioAwsInstance
|
|
428
429
|
instance[:public_dns_name],
|
429
430
|
procs,
|
430
431
|
instance[:placement][:availability_zone],
|
431
|
-
instance[:private_ip_address]
|
432
|
+
instance[:private_ip_address],
|
433
|
+
instance[:launch_time]
|
432
434
|
)
|
433
435
|
|
434
436
|
# store some values into the member variables
|
@@ -1,6 +1,5 @@
|
|
1
|
-
# NOTE: Do not modify this file as it is copied over. Modify the source file and rerun rake import_files
|
2
1
|
######################################################################
|
3
|
-
# Copyright (c) 2008-
|
2
|
+
# Copyright (c) 2008-2015, Alliance for Sustainable Energy.
|
4
3
|
# All rights reserved.
|
5
4
|
#
|
6
5
|
# This library is free software; you can redistribute it and/or
|