openstudio-aws 0.1.7 → 0.1.8

Sign up to get free protection for your applications and to get access to all the features.
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