openstudio-aws 0.1.7 → 0.1.8

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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +14 -13
  3. data/lib/openstudio-aws.rb +9 -7
  4. data/lib/openstudio/aws/aws.rb +53 -40
  5. data/lib/openstudio/aws/config.rb +0 -1
  6. data/lib/openstudio/aws/version.rb +2 -2
  7. data/lib/openstudio/lib/ami_list.rb +79 -0
  8. data/lib/openstudio/lib/openstudio_aws_instance.rb +138 -0
  9. data/lib/openstudio/lib/openstudio_aws_logger.rb +61 -0
  10. data/lib/openstudio/lib/openstudio_aws_methods.rb +232 -0
  11. data/lib/openstudio/lib/openstudio_aws_wrapper.rb +315 -0
  12. data/lib/openstudio/lib/os-aws.rb +77 -351
  13. data/spec/aws_instances/aws_spec_api.rb +70 -0
  14. data/spec/openstudio-aws/ami_list_spec.rb +37 -0
  15. data/spec/openstudio-aws/aws_methods_spec.rb +26 -0
  16. data/spec/openstudio-aws/lib_spec.rb +48 -0
  17. data/spec/reports/SPEC-OpenStudio-Aws-Aws-create-a-new-instance.xml +43 -0
  18. data/spec/reports/SPEC-OpenStudio-Aws-Aws-workers-before-server.xml +9 -0
  19. data/spec/reports/SPEC-OpenStudio-Aws-Aws.xml +7 -0
  20. data/spec/reports/SPEC-OpenStudio-Aws-Config-create-a-new-config.0.xml +9 -0
  21. data/spec/reports/SPEC-OpenStudio-Aws-Config-create-a-new-config.xml +9 -0
  22. data/spec/reports/SPEC-OpenStudio-Aws-Config.0.xml +7 -0
  23. data/spec/reports/SPEC-OpenStudio-Aws-Config.xml +7 -0
  24. data/spec/reports/SPEC-OpenStudioAmis-version-1.0.xml +13 -0
  25. data/spec/reports/SPEC-OpenStudioAmis-version-1.xml +13 -0
  26. data/spec/reports/SPEC-OpenStudioAmis.0.xml +7 -0
  27. data/spec/reports/SPEC-OpenStudioAmis.xml +7 -0
  28. data/spec/reports/SPEC-OpenStudioAwsMethods-processors.0.xml +11 -0
  29. data/spec/reports/SPEC-OpenStudioAwsMethods-processors.xml +11 -0
  30. data/spec/reports/SPEC-OpenStudioAwsMethods.0.xml +7 -0
  31. data/spec/reports/SPEC-OpenStudioAwsMethods.xml +7 -0
  32. data/spec/reports/SPEC-OpenStudioAwsWrapper-authenticated-session-availability.0.xml +11 -0
  33. data/spec/reports/SPEC-OpenStudioAwsWrapper-authenticated-session-availability.xml +11 -0
  34. data/spec/reports/SPEC-OpenStudioAwsWrapper-authenticated-session-new-instance.0.xml +9 -0
  35. data/spec/reports/SPEC-OpenStudioAwsWrapper-authenticated-session-new-instance.xml +9 -0
  36. data/spec/reports/SPEC-OpenStudioAwsWrapper-authenticated-session.0.xml +7 -0
  37. data/spec/reports/SPEC-OpenStudioAwsWrapper-authenticated-session.xml +7 -0
  38. data/spec/reports/SPEC-OpenStudioAwsWrapper-unauthenticated-session.0.xml +9 -0
  39. data/spec/reports/SPEC-OpenStudioAwsWrapper-unauthenticated-session.xml +9 -0
  40. data/spec/reports/SPEC-OpenStudioAwsWrapper.0.xml +7 -0
  41. data/spec/reports/SPEC-OpenStudioAwsWrapper.xml +7 -0
  42. metadata +70 -10
  43. data/lib/openstudio/aws/send_data.rb +0 -42
  44. data/spec/openstudio-aws/aws_spec.rb +0 -53
@@ -0,0 +1,61 @@
1
+ # NOTE: Do not modify this file as it is copied over. Modify the source file and rerun rake import_files
2
+ ######################################################################
3
+ # Copyright (c) 2008-2014, Alliance for Sustainable Energy.
4
+ # All rights reserved.
5
+ #
6
+ # This library is free software; you can redistribute it and/or
7
+ # modify it under the terms of the GNU Lesser General Public
8
+ # License as published by the Free Software Foundation; either
9
+ # version 2.1 of the License, or (at your option) any later version.
10
+ #
11
+ # This library is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
+ # Lesser General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Lesser General Public
17
+ # License along with this library; if not, write to the Free Software
18
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
+ ######################################################################
20
+
21
+ ######################################################################
22
+ # == Synopsis
23
+ #
24
+ # Uses the aws-sdk gem to communicate with AWS
25
+ #
26
+ # == Usage
27
+ #
28
+ # ruby aws.rb access_key secret_key us-east-1 EC2 launch_server "{\"instance_type\":\"t1.micro\"}"
29
+ #
30
+ # ARGV[0] - Access Key
31
+ # ARGV[1] - Secret Key
32
+ # ARGV[2] - Region
33
+ # ARGV[3] - Service (e.g. "EC2" or "CloudWatch")
34
+ # ARGV[4] - Command (e.g. "launch_server")
35
+ # ARGV[5] - Optional json with parameters associated with command
36
+ #
37
+ ######################################################################
38
+
39
+ require 'logger'
40
+
41
+ # module for logging
42
+ module Logging
43
+ def logger
44
+ @logger ||= Logging.logger_for(self.class.name)
45
+ end
46
+
47
+ # Use a hash class-ivar to cache a unique Logger per class:
48
+ @loggers = {}
49
+
50
+ class << self
51
+ def logger_for(classname)
52
+ @loggers[classname] ||= configure_logger_for(classname)
53
+ end
54
+
55
+ def configure_logger_for(classname)
56
+ logger = Logger.new(File.expand_path("~/.aws.log"))
57
+ logger.progname = classname
58
+ logger
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,232 @@
1
+ # NOTE: Do not modify this file as it is copied over. Modify the source file and rerun rake import_files
2
+ ######################################################################
3
+ # Copyright (c) 2008-2014, Alliance for Sustainable Energy.
4
+ # All rights reserved.
5
+ #
6
+ # This library is free software; you can redistribute it and/or
7
+ # modify it under the terms of the GNU Lesser General Public
8
+ # License as published by the Free Software Foundation; either
9
+ # version 2.1 of the License, or (at your option) any later version.
10
+ #
11
+ # This library is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
+ # Lesser General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Lesser General Public
17
+ # License along with this library; if not, write to the Free Software
18
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
+ ######################################################################
20
+
21
+ ######################################################################
22
+ # == Synopsis
23
+ #
24
+ # Methods module for openstudio aws
25
+ #
26
+ # == Usage
27
+ #
28
+ # Inside the class in which this file is included make sure to implement the following
29
+ #
30
+ # Member Variables:
31
+ # private_key : the in memory private key
32
+ # logger : logger class in which to write log messages
33
+ #
34
+ ######################################################################
35
+
36
+ module OpenStudioAwsMethods
37
+ def find_processors(instance)
38
+ lookup = {
39
+ "m3.xlarge" => 4,
40
+ "m3.2xlarge" => 8,
41
+ "m1.small" => 1,
42
+ "m1.medium" => 1,
43
+ "m1.large" => 2,
44
+ "m1.xlarge" => 4,
45
+ "c3.large" => 2,
46
+ "c3.xlarge" => 4,
47
+ "c3.2xlarge" => 8,
48
+ "c3.4xlarge" => 16,
49
+ "c3.8xlarge" => 16,
50
+ "c1.medium" => 2,
51
+ "c1.xlarge" => 8,
52
+ "cc2.8xlarge" => 16,
53
+ "g2.2xlarge" => 8,
54
+ "cg1.4xlarge" => 16,
55
+ "m2.xlarge" => 2,
56
+ "m2.2xlarge" => 4,
57
+ "m2.4xlarge" => 8,
58
+ "cr1.8xlarge" => 16,
59
+ "hi1.4xlarge" => 16,
60
+ "hs1.8xlarge" => 16,
61
+ "t1.micro" => 1,
62
+ }
63
+
64
+ processors = 1
65
+ if lookup.has_key?(instance)
66
+ processors = lookup[instance]
67
+ else
68
+ #logger.warn "Could not find the number of processors for instance type of #{instance}" if logger
69
+ end
70
+
71
+ processors
72
+ end
73
+
74
+
75
+ def upload_file(host, local_path, remote_path)
76
+ retries = 0
77
+ begin
78
+ Net::SCP.start(host, 'ubuntu', :key_data => [@private_key]) do |scp|
79
+ scp.upload! local_path, remote_path
80
+ end
81
+ rescue SystemCallError, Timeout::Error => e
82
+ # port 22 might not be available immediately after the instance finishes launching
83
+ return if retries == 5
84
+ retries += 1
85
+ sleep 1
86
+ retry
87
+ rescue
88
+ # Unknown upload error, retry
89
+ return if retries == 5
90
+ retries += 1
91
+ sleep 1
92
+ retry
93
+ end
94
+ end
95
+
96
+
97
+ def send_command(host, command)
98
+ #retries = 0
99
+ begin
100
+ output = ''
101
+ Net::SSH.start(host, 'ubuntu', :key_data => [@private_key]) do |ssh|
102
+ response = ssh.exec!(command)
103
+ output += response if !response.nil?
104
+ end
105
+ return output
106
+ rescue Net::SSH::HostKeyMismatch => e
107
+ e.remember_host!
108
+ # key mismatch, retry
109
+ #return if retries == 5
110
+ #retries += 1
111
+ sleep 1
112
+ retry
113
+ rescue Net::SSH::AuthenticationFailed
114
+ error(-1, "Incorrect private key")
115
+ rescue SystemCallError, Timeout::Error => e
116
+ # port 22 might not be available immediately after the instance finishes launching
117
+ #return if retries == 5
118
+ #retries += 1
119
+ sleep 1
120
+ retry
121
+ rescue Exception => e
122
+ puts e.message
123
+ puts e.backtrace.inspect
124
+ end
125
+ end
126
+
127
+ #======================= send command ======================#
128
+ # Send a command through SSH Shell to an instance.
129
+ # Need to pass instance object and the command as a string.
130
+ def shell_command(host, command)
131
+ begin
132
+ @logger.info("ssh_command #{command}")
133
+ Net::SSH.start(host, 'ubuntu', :key_data => [@private_key]) do |ssh|
134
+ channel = ssh.open_channel do |ch|
135
+ ch.exec "#{command}" do |ch, success|
136
+ raise "could not execute #{command}" unless success
137
+
138
+ # "on_data" is called when the process writes something to stdout
139
+ ch.on_data do |c, data|
140
+ #$stdout.print data
141
+ @logger.info("#{data.inspect}")
142
+ end
143
+
144
+ # "on_extended_data" is called when the process writes something to stderr
145
+ ch.on_extended_data do |c, type, data|
146
+ #$stderr.print data
147
+ @logger.info("#{data.inspect}")
148
+ end
149
+ end
150
+ end
151
+ end
152
+ rescue Net::SSH::HostKeyMismatch => e
153
+ e.remember_host!
154
+ @logger.info("key mismatch, retry")
155
+ sleep 1
156
+ retry
157
+ rescue SystemCallError, Timeout::Error => e
158
+ # port 22 might not be available immediately after the instance finishes launching
159
+ sleep 1
160
+ @logger.info("Not Yet")
161
+ retry
162
+ end
163
+ end
164
+
165
+ def wait_command(host, command)
166
+ begin
167
+ flag = 0
168
+ while flag == 0 do
169
+ @logger.info("wait_command #{command}")
170
+ Net::SSH.start(host, 'ubuntu', :key_data => [@private_key]) do |ssh|
171
+ channel = ssh.open_channel do |ch|
172
+ ch.exec "#{command}" do |ch, success|
173
+ raise "could not execute #{command}" unless success
174
+
175
+ # "on_data" is called when the process writes something to stdout
176
+ ch.on_data do |c, data|
177
+ @logger.info("#{data.inspect}")
178
+ if data.chomp == "true"
179
+ @logger.info("wait_command #{command} is true")
180
+ flag = 1
181
+ else
182
+ sleep 5
183
+ end
184
+ end
185
+
186
+ # "on_extended_data" is called when the process writes something to stderr
187
+ ch.on_extended_data do |c, type, data|
188
+ @logger.info("#{data.inspect}")
189
+ if data == "true"
190
+ @logger.info("wait_command #{command} is true")
191
+ flag = 1
192
+ else
193
+ sleep 5
194
+ end
195
+ end
196
+ end
197
+ end
198
+ end
199
+ end
200
+ rescue Net::SSH::HostKeyMismatch => e
201
+ e.remember_host!
202
+ @logger.info("key mismatch, retry")
203
+ sleep 5
204
+ retry
205
+ rescue SystemCallError, Timeout::Error => e
206
+ # port 22 might not be available immediately after the instance finishes launching
207
+ sleep 5
208
+ @logger.info("Not Yet")
209
+ retry
210
+ end
211
+ end
212
+
213
+ def download_file(host, remote_path, local_path)
214
+ retries = 0
215
+ begin
216
+ Net::SCP.start(host, 'ubuntu', :key_data => [@private_key]) do |scp|
217
+ scp.download! remote_path, local_path
218
+ end
219
+ rescue SystemCallError, Timeout::Error => e
220
+ # port 22 might not be available immediately after the instance finishes launching
221
+ return if retries == 5
222
+ retries += 1
223
+ sleep 1
224
+ retry
225
+ rescue
226
+ return if retries == 5
227
+ retries += 1
228
+ sleep 1
229
+ retry
230
+ end
231
+ end
232
+ end
@@ -0,0 +1,315 @@
1
+ # NOTE: Do not modify this file as it is copied over. Modify the source file and rerun rake import_files
2
+ ######################################################################
3
+ # Copyright (c) 2008-2014, Alliance for Sustainable Energy.
4
+ # All rights reserved.
5
+ #
6
+ # This library is free software; you can redistribute it and/or
7
+ # modify it under the terms of the GNU Lesser General Public
8
+ # License as published by the Free Software Foundation; either
9
+ # version 2.1 of the License, or (at your option) any later version.
10
+ #
11
+ # This library is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
+ # Lesser General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Lesser General Public
17
+ # License along with this library; if not, write to the Free Software
18
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
+ ######################################################################
20
+
21
+ ######################################################################
22
+ # == Synopsis
23
+ #
24
+ # Uses the aws-sdk gem to communicate with AWS
25
+ #
26
+ # == Usage
27
+ #
28
+ # ruby aws.rb access_key secret_key us-east-1 EC2 launch_server "{\"instance_type\":\"t1.micro\"}"
29
+ #
30
+ # ARGV[0] - Access Key
31
+ # ARGV[1] - Secret Key
32
+ # ARGV[2] - Region
33
+ # ARGV[3] - Service (e.g. "EC2" or "CloudWatch")
34
+ # ARGV[4] - Command (e.g. "launch_server")
35
+ # ARGV[5] - Optional json with parameters associated with command
36
+ #
37
+ ######################################################################
38
+
39
+ require_relative 'openstudio_aws_logger'
40
+
41
+ class OpenStudioAwsWrapper
42
+ include Logging
43
+
44
+ attr_reader :group_uuid
45
+ attr_reader :security_group_name
46
+ attr_reader :key_pair_name
47
+ attr_reader :server
48
+ attr_reader :workers
49
+
50
+ def initialize(credentials = nil, group_uuid = nil)
51
+ @group_uuid = group_uuid || Time.now.to_i.to_s
52
+
53
+ @security_group_name = nil
54
+ @key_pair_name = nil
55
+ @private_key = nil
56
+ @server = nil
57
+ @workers = []
58
+
59
+ # If you already set the credentials in another script in memory, then you won't have to do it here, but
60
+ # it won't hurt if you do
61
+ Aws.config = credentials if credentials
62
+ @aws = Aws::EC2.new
63
+ end
64
+
65
+ def create_or_retrieve_security_group(sg_name = nil)
66
+ tmp_name = sg_name || 'openstudio-server-sg-v1'
67
+ group = @aws.describe_security_groups({:filters => [{:name => 'group-name', :values => [tmp_name]}]})
68
+ logger.info "Length of the security group is: #{group.data.security_groups.length}"
69
+ if group.data.security_groups.length == 0
70
+ logger.info "server group not found --- will create a new one"
71
+ @aws.create_security_group({:group_name => tmp_name, :description => "group dynamically created by #{__FILE__}"})
72
+ @aws.authorize_security_group_ingress(
73
+ {
74
+ :group_name => tmp_name,
75
+ :ip_permissions => [
76
+ {:ip_protocol => 'tcp', :from_port => 1, :to_port => 65535, :ip_ranges => [:cidr_ip => "0.0.0.0/0"]}
77
+ ]
78
+ }
79
+ )
80
+ @aws.authorize_security_group_ingress(
81
+ {
82
+ :group_name => tmp_name,
83
+ :ip_permissions => [
84
+ {:ip_protocol => 'icmp', :from_port => -1, :to_port => -1, :ip_ranges => [:cidr_ip => "0.0.0.0/0"]
85
+ }
86
+ ]
87
+ }
88
+ )
89
+
90
+ # reload group information
91
+ group = @aws.describe_security_groups({:filters => [{:name => 'group-name', :values => [tmp_name]}]})
92
+ end
93
+ @security_group_name = group.data.security_groups.first.group_name
94
+ logger.info("server_group #{group.data.security_groups.first.group_name}")
95
+ end
96
+
97
+ def describe_availability_zones
98
+ resp = @aws.describe_availability_zones
99
+ map = []
100
+ resp.data.availability_zones.each do |zn|
101
+ map << zn.to_hash
102
+ end
103
+
104
+ {:availability_zone_info => map}
105
+ end
106
+
107
+ def describe_availability_zones_json
108
+ describe_availability_zones.to_json
109
+ end
110
+
111
+ def describe_total_instances
112
+ resp = @aws.describe_instance_status
113
+
114
+ region = resp.instance_statuses.length > 0 ? resp.instance_statuses.first.availability_zone : "no_instances"
115
+ {:total_instances => resp.instance_statuses.length, :region => region}
116
+ end
117
+
118
+ def describe_total_instances_json
119
+ describe_total_instances.to_json
120
+ end
121
+
122
+ # return all of the running instances, or filter by the group_uuid & instance type
123
+ def describe_running_instances(group_uuid = nil, openstudio_instance_type = nil)
124
+
125
+ resp = nil
126
+ if group_uuid
127
+ resp = @aws.describe_instances(
128
+ {
129
+ :filters => [
130
+ {:name => "instance-state-code", :values => [0.to_s, 16.to_s]}, #running or pending
131
+ {:name => "tag-key", :values => ["GroupUUID"]},
132
+ {:name => "tag-value", :values => [group_uuid.to_s]} # todo: how to check for the server versions
133
+ #{:name => "tag-value", :values => [group_uuid.to_s, "OpenStudio#{@openstudio_instance_type.capitalize}"]}
134
+ #{:name => "tag:key=value", :values => ["GroupUUID=#{group_uuid.to_s}"]}
135
+ ]
136
+ }
137
+ )
138
+ else
139
+ # todo: need to restrict this to only the current user
140
+ resp = @aws.describe_instances()
141
+ end
142
+
143
+ instance_data = nil
144
+ if resp
145
+ if resp.reservations.length > 0
146
+ resp = resp.reservations.first
147
+ if resp.instances
148
+ instance_data = []
149
+ resp.instances.each do |i|
150
+ instance_data << i.to_hash
151
+ end
152
+
153
+
154
+ end
155
+ else
156
+ logger.info "no running instances found"
157
+ end
158
+ end
159
+
160
+ instance_data
161
+ end
162
+
163
+ def create_or_retrieve_key_pair(key_pair_name = nil, private_key_file = nil)
164
+ tmp_name = key_pair_name || "os-key-pair-#{@group_uuid}"
165
+
166
+ # the describe_key_pairs method will raise an expection if it can't find the keypair, so catch it
167
+ resp = nil
168
+ begin
169
+ resp = @aws.describe_key_pairs({:key_names => [tmp_name]}).data
170
+ raise "looks like there are 2 key pairs with the same name" if resp.key_pairs.size >= 2
171
+ rescue
172
+ logger.info "could not find key pair '#{tmp_name}'"
173
+ end
174
+
175
+ if resp.nil? || resp.key_pairs.size == 0
176
+ # create the new key_pair
177
+ # check if the key pair name exists
178
+ # create a new key pair everytime
179
+ keypair = @aws.create_key_pair({:key_name => tmp_name})
180
+
181
+ # save the private key to memory (which can later be persisted via the save_private_key method)
182
+ @private_key = keypair.data.key_material
183
+ @key_pair_name = keypair.data.key_name
184
+ else
185
+ logger.info "found existing keypair #{resp.key_pairs.first}"
186
+ @key_pair_name = resp.key_pairs.first[:key_name]
187
+
188
+ if File.exists(private_key_file)
189
+ @private_key = File.read(private_key_file, 'r')
190
+ else
191
+ # should we raise?
192
+ logger.error "Could not find the private key file to load from #{private_key_file}"
193
+ end
194
+ end
195
+
196
+ logger.info("create key pair: #{@key_pair_name}")
197
+ end
198
+
199
+ def save_private_key(filename)
200
+ if @private_key
201
+ File.open(filename, 'w') { |f| f << @private_key }
202
+ File.chmod(0600, filename)
203
+ else
204
+ logger.error "no private key found in which to persist"
205
+ end
206
+ end
207
+
208
+ def launch_server(image_id, instance_type)
209
+ user_data = File.read(File.expand_path(File.dirname(__FILE__))+'/server_script.sh')
210
+ @server = OpenStudioAwsInstance.new(@aws, :server, @key_pair_name, @security_group_name, @group_uuid, @private_key)
211
+ @server.launch_instance(image_id, instance_type, user_data)
212
+ end
213
+
214
+ def launch_workers(image_id, instance_type, num)
215
+ user_data = File.read(File.expand_path(File.dirname(__FILE__))+'/worker_script.sh.template')
216
+ user_data.gsub!(/SERVER_IP/, @server.data.ip)
217
+ user_data.gsub!(/SERVER_HOSTNAME/, 'master')
218
+ user_data.gsub!(/SERVER_ALIAS/, '')
219
+ logger.info("worker user_data #{user_data.inspect}")
220
+
221
+ # thread the launching of the workers
222
+ threads = []
223
+ num.times do
224
+ @workers << OpenStudioAwsInstance.new(@aws, :worker, @key_pair_name, @security_group_name, @group_uuid, @private_key)
225
+ threads << Thread.new do
226
+ @workers.last.launch_instance(image_id, instance_type, user_data)
227
+ end
228
+ end
229
+ threads.each { |t| t.join }
230
+
231
+ # todo: do we need to have a flag if the worker node is successful?
232
+ # todo: do we need to check the current list of running workers?
233
+ end
234
+
235
+ # blocking method that waits for servers and workers to be fully configured (i.e. execution of user_data has
236
+ # occured on all nodes)
237
+ def configure_server_and_workers
238
+ #todo: add a timeout here!
239
+ logger.info("waiting for server user_data to complete")
240
+ @server.wait_command(@server.data.ip, '[ -e /home/ubuntu/user_data_done ] && echo "true"')
241
+ @logger.info("waiting for worker user_data to complete")
242
+ @workers.each { |worker| worker.wait_command(worker.data.ip, '[ -e /home/ubuntu/user_data_done ] && echo "true"') }
243
+
244
+ ips = "master|#{@server.data.ip}|#{@server.data.dns}|#{@server.data.procs}|ubuntu|ubuntu\n"
245
+ @workers.each { |worker| ips << "worker|#{worker.data.ip}|#{worker.data.dns}|#{worker.data.procs}|ubuntu|ubuntu|true\n" }
246
+ file = Tempfile.new('ip_addresses')
247
+ file.write(ips)
248
+ file.close
249
+ upload_file(@server.data.ip, file.path, 'ip_addresses')
250
+ file.unlink
251
+ logger.info("ips #{ips}")
252
+ @server.shell_command(@server.data.ip, 'chmod 664 /home/ubuntu/ip_addresses')
253
+ @server.shell_command(@server.data.ip, '~/setup-ssh-keys.sh')
254
+ @server.shell_command(@server.data.ip, '~/setup-ssh-worker-nodes.sh ip_addresses')
255
+
256
+ mongoid = File.read(File.expand_path(File.dirname(__FILE__))+'/mongoid.yml.template')
257
+ mongoid.gsub!(/SERVER_IP/, @server.data.ip)
258
+ file = Tempfile.new('mongoid.yml')
259
+ file.write(mongoid)
260
+ file.close
261
+ @server.upload_file(@server.data.ip, file.path, '/mnt/openstudio/rails-models/mongoid.yml')
262
+ @workers.each { |worker| worker.upload_file(worker.data.ip, file.path, '/mnt/openstudio/rails-models/mongoid.yml') }
263
+ file.unlink
264
+
265
+ # Does this command crash it?
266
+ @server.shell_command(@server.data.ip, 'chmod 664 /mnt/openstudio/rails-models/mongoid.yml')
267
+ @workers.each { |worker| worker.shell_command(worker.data.ip, 'chmod 664 /mnt/openstudio/rails-models/mongoid.yml') }
268
+
269
+ true
270
+ end
271
+
272
+ # method to query the amazon api to find the server (if it exists), based on the group id
273
+ # if it is found, then it will set the @server member variable.
274
+ # Note that the information around keys and security groups is pulled from the instance information.
275
+ def find_server(group_uuid = nil)
276
+ group_uuid = group_uuid || @group_uuid
277
+
278
+ logger.info "finding the server for groupid of #{group_uuid}"
279
+ raise "no group uuid defined either in member variable or method argument" if group_uuid.nil?
280
+
281
+ resp = describe_running_instances(group_uuid, :server)
282
+ if resp
283
+ raise "more than one server running with group uuid of #{group_uuid} found, expecting only one" if resp.size > 1
284
+ resp = resp.first
285
+ if !@server
286
+ logger.info "Server found and loading data into object [instance id is #{resp[:instance_id]}]"
287
+ @server = OpenStudioAwsInstance.new(@aws, :server, resp[:key_name], resp[:security_groups].first[:group_name], group_uuid, @private_key)
288
+ @server.load_instance_data(resp)
289
+ else
290
+ logger.info "Server instance is already defined with instance #{resp[:instance_id]}"
291
+ end
292
+ else
293
+ raise "could not find a running server instance"
294
+ end
295
+ end
296
+
297
+ def to_os_worker_hash
298
+ worker_hash = []
299
+ @workers.each { |worker|
300
+ worker_hash.push({
301
+ :id => worker.data.id,
302
+ :ip => 'http://' + worker.data.ip,
303
+ :dns => worker.data.dns,
304
+ :procs => worker.data.procs
305
+ })
306
+ }
307
+
308
+ out = {:workers => worker_hash}
309
+ logger.info out
310
+
311
+ out
312
+ end
313
+
314
+
315
+ end