openstudio-aws 0.3.2 → 0.4.0.alpha1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|