openstudio-aws 0.7.0.alpha0 → 0.7.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.
@@ -1,5 +1,5 @@
1
1
  # *******************************************************************************
2
- # OpenStudio(R), Copyright (c) 2008-2016, Alliance for Sustainable Energy, LLC.
2
+ # OpenStudio(R), Copyright (c) 2008-2019, Alliance for Sustainable Energy, LLC.
3
3
  # All rights reserved.
4
4
  # Redistribution and use in source and binary forms, with or without
5
5
  # modification, are permitted provided that the following conditions are met:
@@ -156,12 +156,12 @@ class OpenStudioAwsInstance
156
156
  t = tag.split('=')
157
157
  if t.size != 2
158
158
  logger.error "Tag '#{t}' not defined or does not have an equal sign"
159
- fail "Tag '#{t}' not defined or does not have an equal sign"
159
+ raise "Tag '#{t}' not defined or does not have an equal sign"
160
160
  next
161
161
  end
162
- if %w(Name GroupUUID NumberOfProcessors Purpose UserID).include? t[0]
162
+ if ['Name', 'GroupUUID', 'NumberOfProcessors', 'Purpose', 'UserID'].include? t[0]
163
163
  logger.error "Tag name '#{t[0]}' is a reserved tag"
164
- fail "Tag name '#{t[0]}' is a reserved tag"
164
+ raise "Tag name '#{t[0]}' is a reserved tag"
165
165
  next
166
166
  end
167
167
 
@@ -238,7 +238,7 @@ class OpenStudioAwsInstance
238
238
  }
239
239
  }
240
240
  else
241
- fail 'do not know how to convert :worker instance to_os_hash. Use the os_aws.to_worker_hash method'
241
+ raise 'do not know how to convert :worker instance to_os_hash. Use the os_aws.to_worker_hash method'
242
242
  end
243
243
 
244
244
  logger.info("server info #{h}")
@@ -258,6 +258,10 @@ class OpenStudioAwsInstance
258
258
  @data.procs
259
259
  end
260
260
 
261
+ # Return the total number of processors that available to run simulations. Note that this method reduces
262
+ # the number of processors on the server node by a prespecified number.
263
+ # @param instance [string], AWS instance type string
264
+ # @return [int], total number of available processors
261
265
  def find_processors(instance)
262
266
  lookup = {
263
267
  'm3.medium' => 1,
@@ -296,11 +300,13 @@ class OpenStudioAwsInstance
296
300
  end
297
301
 
298
302
  if @openstudio_instance_type == :server
299
- # take out 4 of the processors for doing work with a max of 1 to work
300
- # 1 for server
303
+ # take out 5 of the processors for known processors.
304
+ # 1 for server/web
305
+ # 1 for queue (redis)
301
306
  # 1 for mongodb
302
- # 1 for child processes to download files
303
- processors = [processors - 4, 1].max # this is 2 for now because the current server decrements by 1 (which will be removed if 2.0-pre6)
307
+ # 1 for web-background
308
+ # 1 for rserve
309
+ processors = [processors - 5, 1].max
304
310
  end
305
311
 
306
312
  processors
@@ -321,19 +327,26 @@ class OpenStudioAwsInstance
321
327
 
322
328
  def upload_file(local_path, remote_path)
323
329
  retries = 0
330
+ ssh_options = {
331
+ proxy: get_proxy,
332
+ key_data: [@private_key]
333
+ }
334
+ ssh_options.delete_if { |_k, v| v.nil? }
324
335
  begin
325
- Net::SCP.start(@data.ip, @user, proxy: get_proxy, key_data: [@private_key]) do |scp|
336
+ Net::SCP.start(@data.ip, @user, ssh_options) do |scp|
326
337
  scp.upload! local_path, remote_path
327
338
  end
328
339
  rescue SystemCallError, Timeout::Error => e
329
340
  # port 22 might not be available immediately after the instance finishes launching
330
341
  return if retries == 5
342
+
331
343
  retries += 1
332
344
  sleep 2
333
345
  retry
334
- rescue
346
+ rescue StandardError
335
347
  # Unknown upload error, retry
336
348
  return if retries == 5
349
+
337
350
  retries += 1
338
351
  sleep 2
339
352
  retry
@@ -345,22 +358,30 @@ class OpenStudioAwsInstance
345
358
  def shell_command(command, load_env = true)
346
359
  logger.info("ssh_command #{command} with load environment #{load_env}")
347
360
  command = "source /etc/profile; source ~/.bash_profile; #{command}" if load_env
348
- Net::SSH.start(@data.ip, @user, proxy: get_proxy, key_data: [@private_key]) do |ssh|
361
+ ssh_options = {
362
+ proxy: get_proxy,
363
+ key_data: [@private_key]
364
+ }
365
+ ssh_options.delete_if { |_k, v| v.nil? }
366
+ Net::SSH.start(@data.ip, @user, ssh_options) do |ssh|
349
367
  channel = ssh.open_channel do |ch|
350
- ch.exec "#{command}" do |ch, success|
351
- fail "could not execute #{command}" unless success
368
+ ch.exec command.to_s do |ch, success|
369
+ raise "could not execute #{command}" unless success
370
+
352
371
  # "on_data" is called when the process wr_ites something to stdout
353
372
  ch.on_data do |_c, data|
354
373
  # $stdout.print data
355
- logger.info("#{data.inspect}")
374
+ logger.info(data.inspect.to_s)
356
375
  end
357
376
  # "on_extended_data" is called when the process writes something to s_tde_rr
358
377
  ch.on_extended_data do |_c, _type, data|
359
378
  # $stderr.print data
360
- logger.info("#{data.inspect}")
379
+ logger.info(data.inspect.to_s)
361
380
  end
362
381
  end
363
382
  end
383
+ ssh.loop
384
+ channel.wait
364
385
  end
365
386
  rescue Net::SSH::HostKeyMismatch => e
366
387
  e.remember_host!
@@ -378,13 +399,19 @@ class OpenStudioAwsInstance
378
399
  flag = 0
379
400
  while flag == 0
380
401
  logger.info("wait_command #{command}")
381
- Net::SSH.start(@data.ip, @user, proxy: get_proxy, key_data: [@private_key]) do |ssh|
402
+ ssh_options = {
403
+ proxy: get_proxy,
404
+ key_data: [@private_key]
405
+ }
406
+ ssh_options.delete_if { |_k, v| v.nil? }
407
+ Net::SSH.start(@data.ip, @user, ssh_options) do |ssh|
382
408
  channel = ssh.open_channel do |ch|
383
- ch.exec "#{command}" do |ch, success|
384
- fail "could not execute #{command}" unless success
409
+ ch.exec command.to_s do |ch, success|
410
+ raise "could not execute #{command}" unless success
411
+
385
412
  # "on_data" is called_ when the process writes something to stdout
386
413
  ch.on_data do |_c, data|
387
- logger.info("#{data.inspect}")
414
+ logger.info(data.inspect.to_s)
388
415
  if data.chomp == 'true'
389
416
  logger.info("wait_command #{command} is true")
390
417
  flag = 1
@@ -394,7 +421,7 @@ class OpenStudioAwsInstance
394
421
  end
395
422
  # "on_extended_data" is called when the process writes some_thi_ng to stderr
396
423
  ch.on_extended_data do |_c, _type, data|
397
- logger.info("#{data.inspect}")
424
+ logger.info(data.inspect.to_s)
398
425
  if data == 'true'
399
426
  logger.info("wait_command #{command} is true")
400
427
  flag = 1
@@ -404,6 +431,8 @@ class OpenStudioAwsInstance
404
431
  end
405
432
  end
406
433
  end
434
+ channel.wait
435
+ ssh.loop
407
436
  end
408
437
  end
409
438
  rescue Net::SSH::HostKeyMismatch => e
@@ -420,18 +449,25 @@ class OpenStudioAwsInstance
420
449
 
421
450
  def download_file(remote_path, local_path)
422
451
  retries = 0
452
+ ssh_options = {
453
+ proxy: get_proxy,
454
+ key_data: [@private_key]
455
+ }
456
+ ssh_options.delete_if { |_k, v| v.nil? }
423
457
  begin
424
- Net::SCP.start(@data.ip, @user, proxy: get_proxy, key_data: [@private_key]) do |scp|
458
+ Net::SCP.start(@data.ip, @user, ssh_options) do |scp|
425
459
  scp.download! remote_path, local_path
426
460
  end
427
461
  rescue SystemCallError, Timeout::Error => e
428
462
  # port 22 might not be available immediately after the instance finishes launching
429
463
  return if retries == 5
464
+
430
465
  retries += 1
431
466
  sleep 2
432
467
  retry
433
- rescue
468
+ rescue StandardError
434
469
  return if retries == 5
470
+
435
471
  retries += 1
436
472
  sleep 2
437
473
  retry
@@ -1,5 +1,5 @@
1
1
  # *******************************************************************************
2
- # OpenStudio(R), Copyright (c) 2008-2016, Alliance for Sustainable Energy, LLC.
2
+ # OpenStudio(R), Copyright (c) 2008-2019, Alliance for Sustainable Energy, LLC.
3
3
  # All rights reserved.
4
4
  # Redistribution and use in source and binary forms, with or without
5
5
  # modification, are permitted provided that the following conditions are met:
@@ -35,7 +35,7 @@
35
35
 
36
36
  require 'logger'
37
37
 
38
- # module for logging
38
+ # module for logging. The AWS log will be stored in the user's home directory under .aws.log.
39
39
  module Logging
40
40
  def logger
41
41
  @logger ||= Logging.logger_for(self.class.name)
@@ -1,5 +1,5 @@
1
1
  # *******************************************************************************
2
- # OpenStudio(R), Copyright (c) 2008-2016, Alliance for Sustainable Energy, LLC.
2
+ # OpenStudio(R), Copyright (c) 2008-2019, Alliance for Sustainable Energy, LLC.
3
3
  # All rights reserved.
4
4
  # Redistribution and use in source and binary forms, with or without
5
5
  # modification, are permitted provided that the following conditions are met:
@@ -48,10 +48,10 @@ class OpenStudioAwsWrapper
48
48
  attr_accessor :private_key_file_name
49
49
  attr_accessor :security_groups
50
50
 
51
- VALID_OPTIONS = [:proxy, :credentials]
51
+ VALID_OPTIONS = [:proxy, :credentials].freeze
52
52
 
53
53
  def initialize(options = {}, group_uuid = nil)
54
- @group_uuid = group_uuid || (SecureRandom.uuid).delete('-')
54
+ @group_uuid = group_uuid || SecureRandom.uuid.delete('-')
55
55
 
56
56
  @security_groups = []
57
57
  @key_pair_name = nil
@@ -75,20 +75,36 @@ class OpenStudioAwsWrapper
75
75
  @workers = []
76
76
 
77
77
  # store an instance variable with the proxy for passing to instances for use in scp/ssh
78
- @proxy = options[:proxy] ? options[:proxy] : nil
78
+ @proxy = options[:proxy] || nil
79
79
 
80
80
  # need to remove the prxoy information here
81
81
  @aws = Aws::EC2::Client.new(options[:credentials])
82
82
  end
83
83
 
84
+ # Calculate the number of processors for the server and workers. This is used to scale the docker stack
85
+ # appropriately.
86
+ # @param total_procs [int] Total number of processors that are available
87
+ def calculate_processors(total_procs)
88
+ max_requests = ((total_procs + 10) * 1.2).round
89
+ mongo_cores = (total_procs / 64.0).ceil
90
+ web_cores = (total_procs / 32.0).ceil
91
+ max_pool = 16 * web_cores
92
+ rez_mem = 512 * max_pool
93
+ # what is this +2 doing here
94
+ total_procs = total_procs - mongo_cores - web_cores + 2
95
+
96
+ [total_procs, max_requests, mongo_cores, web_cores, max_pool, rez_mem]
97
+ end
98
+
84
99
  def create_or_retrieve_default_security_group(tmp_name = 'openstudio-server-sg-v2.2', vpc_id = nil)
85
100
  group = @aws.describe_security_groups(filters: [{ name: 'group-name', values: [tmp_name] }])
86
101
  logger.info "Length of the security group is: #{group.data.security_groups.length}"
87
- if group.data.security_groups.length == 0
102
+ if group.data.security_groups.empty?
88
103
  logger.info 'security group not found --- will create a new one'
89
104
  if vpc_id
90
- r = @aws.create_security_group(group_name: tmp_name, description: "group dynamically created by #{__FILE__}",
91
- vpc_id: vpc_id)
105
+ r = @aws.create_security_group(
106
+ group_name: tmp_name, description: "group dynamically created by #{__FILE__}", vpc_id: vpc_id
107
+ )
92
108
  else
93
109
  r = @aws.create_security_group(group_name: tmp_name, description: "group dynamically created by #{__FILE__}")
94
110
  end
@@ -134,7 +150,7 @@ class OpenStudioAwsWrapper
134
150
  def total_instances_count
135
151
  resp = @aws.describe_instance_status
136
152
 
137
- availability_zone = resp.instance_statuses.length > 0 ? resp.instance_statuses.first.availability_zone : 'no_instances'
153
+ availability_zone = !resp.instance_statuses.empty? ? resp.instance_statuses.first.availability_zone : 'no_instances'
138
154
 
139
155
  { total_instances: resp.instance_statuses.length, region: @region, availability_zone: availability_zone }
140
156
  end
@@ -289,12 +305,12 @@ class OpenStudioAwsWrapper
289
305
  resp = nil
290
306
  begin
291
307
  resp = @aws.describe_key_pairs(key_names: [tmp_name]).data
292
- fail 'looks like there are 2 key pairs with the same name' if resp.key_pairs.size >= 2
293
- rescue
308
+ raise 'looks like there are 2 key pairs with the same name' if resp.key_pairs.size >= 2
309
+ rescue StandardError
294
310
  logger.info "could not find key pair '#{tmp_name}'"
295
311
  end
296
312
 
297
- if resp.nil? || resp.key_pairs.size == 0
313
+ if resp.nil? || resp.key_pairs.empty?
298
314
  # create the new key_pair
299
315
  # check if the key pair name exists
300
316
  # create a new key pair everytime
@@ -320,7 +336,7 @@ class OpenStudioAwsWrapper
320
336
  begin
321
337
  logger.info "Trying to delete key pair #{tmp_name}"
322
338
  resp = @aws.delete_key_pair(key_name: tmp_name)
323
- rescue
339
+ rescue StandardError
324
340
  logger.info "could not delete the key pair '#{tmp_name}'"
325
341
  end
326
342
 
@@ -335,7 +351,7 @@ class OpenStudioAwsWrapper
335
351
  logger.info "Found key of same name in user's home ssh folder #{filename}"
336
352
  # using the key in your home directory
337
353
  else
338
- fail "Could not find private key #{filename}" unless File.exist? filename
354
+ raise "Could not find private key #{filename}" unless File.exist? filename
339
355
  end
340
356
  end
341
357
 
@@ -360,9 +376,9 @@ class OpenStudioAwsWrapper
360
376
  logger.info "Saving server private key in #{@private_key_file_name}"
361
377
  File.open(@private_key_file_name, 'w') { |f| f << @private_key }
362
378
  logger.info 'Setting permissions of server private key to 0600'
363
- File.chmod(0600, @private_key_file_name)
379
+ File.chmod(0o600, @private_key_file_name)
364
380
  else
365
- fail "No private key found in which to persist with filename #{filename}"
381
+ raise "No private key found in which to persist with filename #{filename}"
366
382
  end
367
383
  end
368
384
 
@@ -372,7 +388,7 @@ class OpenStudioAwsWrapper
372
388
  logger.info "Saving worker private key in #{@worker_keys_filename}"
373
389
  File.open(@worker_keys_filename, 'w') { |f| f << @worker_keys.private_key }
374
390
  logger.info 'Setting permissions of worker private key to 0600'
375
- File.chmod(0600, @worker_keys_filename)
391
+ File.chmod(0o600, @worker_keys_filename)
376
392
 
377
393
  wk = "#{directory}/ec2_worker_key.pub"
378
394
  logger.info "Saving worker public key in #{wk}"
@@ -390,7 +406,7 @@ class OpenStudioAwsWrapper
390
406
 
391
407
  # replace the server_script.sh.template with the keys to add
392
408
 
393
- user_data = File.read(File.join(File.expand_path(File.dirname(__FILE__)), launch_options[:user_data_file]))
409
+ user_data = File.read(File.join(__dir__, launch_options[:user_data_file]))
394
410
  user_data.gsub!(/SERVER_HOSTNAME/, 'openstudio.server')
395
411
  user_data.gsub!(/WORKER_PRIVATE_KEY_TEMPLATE/, worker_keys.private_key.gsub("\n", '\\n'))
396
412
  user_data.gsub!(/WORKER_PUBLIC_KEY_TEMPLATE/, worker_keys.ssh_public_key)
@@ -400,8 +416,9 @@ class OpenStudioAwsWrapper
400
416
 
401
417
  # TODO: create the EBS volumes instead of the ephemeral storage - needed especially for the m3 instances (SSD)
402
418
 
403
- fail 'image_id is nil' unless image_id
404
- fail 'instance type is nil' unless instance_type
419
+ raise 'image_id is nil' unless image_id
420
+ raise 'instance type is nil' unless instance_type
421
+
405
422
  @server.launch_instance(image_id, instance_type, user_data, launch_options[:user_id], launch_options)
406
423
  end
407
424
 
@@ -415,7 +432,7 @@ class OpenStudioAwsWrapper
415
432
  }
416
433
  launch_options = defaults.merge(launch_options)
417
434
 
418
- user_data = File.read(File.join(File.expand_path(File.dirname(__FILE__)), launch_options[:user_data_file]))
435
+ user_data = File.read(File.join(__dir__, launch_options[:user_data_file]))
419
436
  user_data.gsub!(/SERVER_IP/, @server.data.private_ip_address)
420
437
  user_data.gsub!(/SERVER_HOSTNAME/, 'openstudio.server')
421
438
  user_data.gsub!(/WORKER_PUBLIC_KEY_TEMPLATE/, worker_keys.ssh_public_key)
@@ -460,7 +477,7 @@ class OpenStudioAwsWrapper
460
477
  logger.info("ips #{ips}")
461
478
  @server.shell_command('chmod 664 /home/ubuntu/ip_addresses')
462
479
 
463
- mongoid = File.read(File.expand_path(File.dirname(__FILE__)) + '/mongoid.yml.template')
480
+ mongoid = File.read(__dir__ + '/mongoid.yml.template')
464
481
  mongoid.gsub!(/SERVER_IP/, @server.data.private_ip_address)
465
482
  file = Tempfile.new('mongoid.yml')
466
483
  file.write(mongoid)
@@ -494,14 +511,20 @@ class OpenStudioAwsWrapper
494
511
  worker_join_cmd = "#{File.read(swarm_file).strip} && echo \"true\""
495
512
  @workers.each { |worker| worker.wait_command(worker_join_cmd) }
496
513
  logger.info('All worker nodes have been added to the swarm. Setting environment variables and starting the cluster')
514
+ # e.g. 356 CPUs
515
+ # mongo cores = 6
516
+ # web cores = 12
517
+ # total procs = 340 (but should be 336)
497
518
  total_procs = @server.procs
498
519
  @workers.each { |worker| total_procs += worker.procs }
499
- max_requests = ((total_procs + 10) * 1.2).round
500
- mongo_cores = (total_procs / 64.0).ceil
501
- web_cores = (total_procs / 32.0).ceil
502
- max_pool = 16 * web_cores
503
- rez_mem = 512 * max_pool
504
- total_procs = total_procs - mongo_cores - web_cores + 2
520
+ total_procs, max_requests, mongo_cores, web_cores, max_pool, rez_mem = calculate_processors(total_procs)
521
+ logger.info('Processors allocations are:')
522
+ logger.info(" total_procs: #{total_procs}")
523
+ logger.info(" max_requests: #{max_requests}")
524
+ logger.info(" mongo_cores: #{mongo_cores}")
525
+ logger.info(" web_cores: #{web_cores}")
526
+ logger.info(" max_pool: #{max_pool}")
527
+ logger.info(" rez_mem: #{rez_mem}")
505
528
  @server.shell_command("sed -i -e 's/AWS_MAX_REQUESTS/#{max_requests}/g' /home/ubuntu/docker-compose.yml && echo \"true\"")
506
529
  @server.shell_command("sed -i -e 's/AWS_MONGO_CORES/#{mongo_cores}/g' /home/ubuntu/docker-compose.yml && echo \"true\"")
507
530
  @server.shell_command("sed -i -e 's/AWS_WEB_CORES/#{web_cores}/g' /home/ubuntu/docker-compose.yml && echo \"true\"")
@@ -509,7 +532,7 @@ class OpenStudioAwsWrapper
509
532
  @server.shell_command("sed -i -e 's/AWS_REZ_MEM/#{rez_mem}/g' /home/ubuntu/docker-compose.yml && echo \"true\"")
510
533
  @server.shell_command("sed -i -e 's/AWS_OS_SERVER_NUMBER_OF_WORKERS/#{total_procs}/g' /home/ubuntu/docker-compose.yml && echo \"true\"")
511
534
  @server.shell_command("echo '' >> /home/ubuntu/.env && echo \"true\"")
512
- @server.shell_command("docker stack deploy --compose-file docker-compose.yml osserver && echo \"true\"")
535
+ @server.shell_command('docker stack deploy --compose-file docker-compose.yml osserver && echo "true"')
513
536
  sleep 10
514
537
  logger.info('The OpenStudio Server stack has been started. Waiting for the server to become available.')
515
538
  @server.wait_command("while ( nc -zv #{@server.ip} 80 3>&1 1>&2- 2>&3- ) | awk -F \":\" '$3 != \" Connection refused\" {exit 1}'; do sleep 5; done && echo \"true\"")
@@ -533,13 +556,14 @@ class OpenStudioAwsWrapper
533
556
  load_private_key(server_data_hash[:server][:private_key_file_name])
534
557
 
535
558
  logger.info "Finding the server for GroupUUID of #{group_uuid}"
536
- fail 'no GroupUUID defined either in member variable or method argument' if @group_uuid.nil?
559
+ raise 'no GroupUUID defined either in member variable or method argument' if @group_uuid.nil?
537
560
 
538
561
  # This should really just be a single call to describe running instances
539
562
  @server = nil
540
563
  resp = describe_running_instances(group_uuid, :server)
541
564
  if resp
542
- fail "more than one server running with group uuid of #{group_uuid} found, expecting only one" if resp.size > 1
565
+ raise "more than one server running with group uuid of #{group_uuid} found, expecting only one" if resp.size > 1
566
+
543
567
  resp = resp.first
544
568
  if !@server
545
569
  if resp
@@ -552,7 +576,7 @@ class OpenStudioAwsWrapper
552
576
 
553
577
  # set the key name from AWS if it isn't yet assigned
554
578
  logger.info 'Setting the keyname in the aws wrapper'
555
- @key_pair_name = resp[:key_name] unless @key_pair_name
579
+ @key_pair_name ||= resp[:key_name]
556
580
 
557
581
  @server = OpenStudioAwsInstance.new(@aws, :server, @key_pair_name, sg, @group_uuid, @private_key, @private_key_file_name, @proxy)
558
582
 
@@ -566,7 +590,7 @@ class OpenStudioAwsWrapper
566
590
  end
567
591
 
568
592
  # Find the worker instances.
569
- if @workers.size == 0
593
+ if @workers.empty?
570
594
  resp = describe_running_instances(group_uuid, :worker)
571
595
  if resp
572
596
  resp.each do |r|
@@ -742,7 +766,7 @@ class OpenStudioAwsWrapper
742
766
  elsif ami[:virtualization_type] == 'hvm'
743
767
  a[:amis][:cc2worker] = ami[:image_id]
744
768
  else
745
- fail "unknown virtualization_type in #{ami[:name]}"
769
+ raise "unknown virtualization_type in #{ami[:name]}"
746
770
  end
747
771
  elsif ami[:name] =~ /Server/
748
772
  a[:amis][:server] = ami[:image_id]
@@ -1,5 +1,5 @@
1
1
  # *******************************************************************************
2
- # OpenStudio(R), Copyright (c) 2008-2016, Alliance for Sustainable Energy, LLC.
2
+ # OpenStudio(R), Copyright (c) 2008-2019, Alliance for Sustainable Energy, LLC.
3
3
  # All rights reserved.
4
4
  # Redistribution and use in source and binary forms, with or without
5
5
  # modification, are permitted provided that the following conditions are met:
@@ -41,11 +41,11 @@ class OpenStudioCloudWatch
41
41
  attr_accessor :private_key_file_name
42
42
  attr_accessor :security_groups
43
43
 
44
- VALID_OPTIONS = [:proxy, :credentials]
44
+ VALID_OPTIONS = [:proxy, :credentials].freeze
45
45
 
46
46
  def initialize(options = {})
47
47
  # store an instance variable with the proxy for passing to instances for use in scp/ssh
48
- @proxy = options[:proxy] ? options[:proxy] : nil
48
+ @proxy = options[:proxy] || nil
49
49
 
50
50
  # need to remove the prxoy information here
51
51
  @aws = Aws::CloudWatch::Client.new(options[:credentials])
@@ -57,7 +57,8 @@ class OpenStudioCloudWatch
57
57
  resp = @aws.get_metric_statistics(
58
58
  dimensions: [
59
59
  { name: 'ServiceName', value: 'AmazonEC2' },
60
- { name: 'Currency', value: 'USD' }],
60
+ { name: 'Currency', value: 'USD' }
61
+ ],
61
62
  metric_name: 'EstimatedCharges',
62
63
  namespace: 'AWS/Billing',
63
64
  start_time: start_time.iso8601,
@@ -1,5 +1,5 @@
1
1
  # *******************************************************************************
2
- # OpenStudio(R), Copyright (c) 2008-2016, Alliance for Sustainable Energy, LLC.
2
+ # OpenStudio(R), Copyright (c) 2008-2019, Alliance for Sustainable Energy, LLC.
3
3
  # All rights reserved.
4
4
  # Redistribution and use in source and binary forms, with or without
5
5
  # modification, are permitted provided that the following conditions are met:
@@ -1,4 +1,4 @@
1
- lib = File.expand_path('../lib/', __FILE__)
1
+ lib = File.expand_path('lib', __dir__)
2
2
  $LOAD_PATH.unshift lib unless $LOAD_PATH.include?(lib)
3
3
 
4
4
  require 'openstudio/aws/version'
@@ -17,13 +17,13 @@ Gem::Specification.new do |s|
17
17
  s.required_ruby_version = '>= 2.0.0'
18
18
  s.required_rubygems_version = '>= 1.3.6'
19
19
 
20
- s.add_dependency 'net-scp', '~> 1.1'
20
+ s.add_dependency 'aws-sdk-core', '= 2.2.37'
21
+ s.add_dependency 'net-scp', '= 2.0.0'
21
22
  s.add_dependency 'net-ssh', '= 4.2.0'
22
- s.add_dependency 'aws-sdk-core', '= 2.2.26'
23
23
  s.add_dependency 'semantic', '~> 1.4'
24
- s.add_dependency 'sshkey', '~> 1.7'
24
+ s.add_dependency 'sshkey', '~> 2.0'
25
25
 
26
- s.add_development_dependency 'rake', '~> 10.4'
26
+ s.add_development_dependency 'rake', '~> 12.3'
27
27
 
28
28
  s.files = `git ls-files -z`.split("\x0")
29
29
  s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
@@ -1,7 +1,42 @@
1
+ # *******************************************************************************
2
+ # OpenStudio(R), Copyright (c) 2008-2019, Alliance for Sustainable Energy, LLC.
3
+ # All rights reserved.
4
+ # Redistribution and use in source and binary forms, with or without
5
+ # modification, are permitted provided that the following conditions are met:
6
+ #
7
+ # (1) Redistributions of source code must retain the above copyright notice,
8
+ # this list of conditions and the following disclaimer.
9
+ #
10
+ # (2) Redistributions in binary form must reproduce the above copyright notice,
11
+ # this list of conditions and the following disclaimer in the documentation
12
+ # and/or other materials provided with the distribution.
13
+ #
14
+ # (3) Neither the name of the copyright holder nor the names of any contributors
15
+ # may be used to endorse or promote products derived from this software without
16
+ # specific prior written permission from the respective party.
17
+ #
18
+ # (4) Other than as required in clauses (1) and (2), distributions in any form
19
+ # of modifications or other derivative works may not use the "OpenStudio"
20
+ # trademark, "OS", "os", or any other confusingly similar designation without
21
+ # specific prior written permission from Alliance for Sustainable Energy, LLC.
22
+ #
23
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER, THE UNITED STATES
27
+ # GOVERNMENT, OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28
+ # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29
+ # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30
+ # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31
+ # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32
+ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
33
+ # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
+ # *******************************************************************************
35
+
1
36
  require 'spec_helper'
2
37
 
3
- SERVER_AMI = 'ami-e0b38888'
4
- WORKER_AMI = 'ami-a8bc87c0'
38
+ SERVER_AMI = 'ami-e0b38888'.freeze
39
+ WORKER_AMI = 'ami-a8bc87c0'.freeze
5
40
 
6
41
  describe OpenStudio::Aws::Aws do
7
42
  context 'create a new instance' do
@@ -383,7 +418,7 @@ describe OpenStudio::Aws::Aws do
383
418
 
384
419
  shell = @aws.server.shell_command('df -h | grep /dev/xvdb.*/mnt')
385
420
  expect(shell).not_to be_nil
386
- expect(shell).to eq /\/dev\/xvdb.*\/mnt/
421
+ expect(shell).to eq %r{/dev/xvdb.*/mnt}
387
422
  ensure
388
423
  @aws.terminate_instances_by_group_id(h[:group_id])
389
424
  end
@@ -1,3 +1,38 @@
1
+ # *******************************************************************************
2
+ # OpenStudio(R), Copyright (c) 2008-2019, Alliance for Sustainable Energy, LLC.
3
+ # All rights reserved.
4
+ # Redistribution and use in source and binary forms, with or without
5
+ # modification, are permitted provided that the following conditions are met:
6
+ #
7
+ # (1) Redistributions of source code must retain the above copyright notice,
8
+ # this list of conditions and the following disclaimer.
9
+ #
10
+ # (2) Redistributions in binary form must reproduce the above copyright notice,
11
+ # this list of conditions and the following disclaimer in the documentation
12
+ # and/or other materials provided with the distribution.
13
+ #
14
+ # (3) Neither the name of the copyright holder nor the names of any contributors
15
+ # may be used to endorse or promote products derived from this software without
16
+ # specific prior written permission from the respective party.
17
+ #
18
+ # (4) Other than as required in clauses (1) and (2), distributions in any form
19
+ # of modifications or other derivative works may not use the "OpenStudio"
20
+ # trademark, "OS", "os", or any other confusingly similar designation without
21
+ # specific prior written permission from Alliance for Sustainable Energy, LLC.
22
+ #
23
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER, THE UNITED STATES
27
+ # GOVERNMENT, OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28
+ # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29
+ # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30
+ # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31
+ # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32
+ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
33
+ # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
+ # *******************************************************************************
35
+
1
36
  require 'spec_helper'
2
37
 
3
38
  describe OpenStudioAmis do
@@ -29,11 +64,20 @@ describe OpenStudioAmis do
29
64
  end
30
65
 
31
66
  context 'version 2' do
32
-
33
67
  it 'should fail when trying to find a stable version for older releases' do
34
68
  a = OpenStudioAmis.new(2, openstudio_version: '1.5.0', stable: true)
35
69
 
36
70
  expect { a.get_amis }.to raise_error(/Could not find a stable version for openstudio version 1.5.0/)
37
71
  end
38
72
  end
73
+
74
+ context 'version 3' do
75
+ it 'should fail when trying to find a stable version for older releases' do
76
+ a = OpenStudioAmis.new(3, openstudio_version: '2.8.0', stable: true)
77
+
78
+ puts a.inspect
79
+
80
+ expect { a.get_amis }.to raise_error(/Currently the openstudio_version lookup is not supported in v3/)
81
+ end
82
+ end
39
83
  end