knife-rightscale 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +15 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +201 -0
- data/README.md +191 -0
- data/Rakefile +32 -0
- data/knife-rightscale.gemspec +37 -0
- data/lib/chef/knife/rightscale_base.rb +113 -0
- data/lib/chef/knife/rightscale_cloud_list.rb +72 -0
- data/lib/chef/knife/rightscale_deployment_list.rb +70 -0
- data/lib/chef/knife/rightscale_image_list.rb +116 -0
- data/lib/chef/knife/rightscale_securitygroup_list.rb +78 -0
- data/lib/chef/knife/rightscale_server_create.rb +181 -0
- data/lib/chef/knife/rightscale_server_delete.rb +52 -0
- data/lib/chef/knife/rightscale_server_list.rb +73 -0
- data/lib/chef/knife/rightscale_servertemplate_list.rb +73 -0
- data/lib/knife-rightscale.rb +30 -0
- data/lib/knife-rightscale/version.rb +22 -0
- data/lib/right_api_provision.rb +92 -0
- data/lib/right_api_provision/api15.rb +372 -0
- data/lib/right_api_provision/exception.rb +23 -0
- data/lib/right_api_provision/provisioner.rb +139 -0
- data/lib/right_api_provision/version.rb +21 -0
- data/spec/chef/knife/rightscale_server_create_spec.rb +32 -0
- data/spec/right_api_provision/api15_spec.rb +203 -0
- data/spec/spec_helper.rb +20 -0
- data/test/create_server_test.rb +58 -0
- data/test/list_actions_test.rb +51 -0
- metadata +78 -0
@@ -0,0 +1,372 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Cary Penniman (<cary@rightscale.com>)
|
3
|
+
# Copyright:: Copyright (c) 2013 RightScale, Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
module RightApiProvision
|
20
|
+
class API15
|
21
|
+
|
22
|
+
attr_reader :client
|
23
|
+
|
24
|
+
def initialize
|
25
|
+
require "right_api_client"
|
26
|
+
end
|
27
|
+
|
28
|
+
def connection(email, password, account_id, api_url = nil)
|
29
|
+
begin
|
30
|
+
args = { :email => email, :password => password, :account_id => account_id }
|
31
|
+
@url = api_url
|
32
|
+
args[:api_url] = @url if @url
|
33
|
+
@connection ||= RightApi::Client.new(args)
|
34
|
+
#@logger = Logger.new(STDOUT)
|
35
|
+
#@logger.level = Logger::DEBUG
|
36
|
+
#@connection.log(@logger)
|
37
|
+
@client = @connection
|
38
|
+
rescue Exception => e
|
39
|
+
args.delete(:password) # don't log password
|
40
|
+
puts "ERROR: could not connect to RightScale API. Params: #{args.inspect}"
|
41
|
+
puts e.message
|
42
|
+
puts e.backtrace
|
43
|
+
raise e
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# If the cloud reports ssh keys, then we assume it requires them to launch
|
48
|
+
# servers.
|
49
|
+
def requires_ssh_keys?(cloud)
|
50
|
+
begin
|
51
|
+
cloud.show.ssh_keys
|
52
|
+
true
|
53
|
+
rescue RightApi::Exceptions::ApiException => e
|
54
|
+
false # assume cloud does not require them
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Find SSH key
|
59
|
+
#
|
60
|
+
# EC2 and Eucalyptus require an SSH key to launch a server. RightScale
|
61
|
+
# manages SSH keys for each user so just grabbing the first one is fine,
|
62
|
+
# however older configurations might relay on specific keys. You will
|
63
|
+
# need to grab the resource UUID from the RightScale dashboard for the key
|
64
|
+
# that you want to use.
|
65
|
+
def find_ssh_key_by_uuid_or_first(cloud, ssh_uuid = nil)
|
66
|
+
ssh_key = nil
|
67
|
+
if ssh_uuid
|
68
|
+
# grab specific ssh key
|
69
|
+
sshkey = find_resource(:ssh_keys, :by_resource_uid, uuid)
|
70
|
+
else
|
71
|
+
# grab first key found
|
72
|
+
keys = cloud.show.ssh_keys
|
73
|
+
ssh_key = keys.index.first if keys
|
74
|
+
end
|
75
|
+
ssh_key
|
76
|
+
end
|
77
|
+
|
78
|
+
# If the cloud reports security groups then we assume it requires them to launch
|
79
|
+
# servers.
|
80
|
+
def requires_security_groups?(cloud)
|
81
|
+
begin
|
82
|
+
cloud.show.security_groups
|
83
|
+
true
|
84
|
+
rescue RightApi::Exceptions::ApiException => e
|
85
|
+
false # assume cloud does not require them
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def user_data
|
90
|
+
@user_data ||= @server.show.current_instance(:view=>"extended").show.user_data
|
91
|
+
end
|
92
|
+
|
93
|
+
def data_request_url(userdata)
|
94
|
+
data_hash = {}
|
95
|
+
entry = userdata.split('&').select { |entry| entry =~ /RS_rn_auth/i }
|
96
|
+
raise "ERROR: user data token not found. " +
|
97
|
+
"Does your MCI have a provides:rs_agent_type=right_link tag?" unless entry
|
98
|
+
token = entry.first.split('=')[1]
|
99
|
+
"#{@url}/servers/data_injection_payload/#{token}"
|
100
|
+
end
|
101
|
+
|
102
|
+
def delete_server(name)
|
103
|
+
server = find_server_by_name(name)
|
104
|
+
server.terminate
|
105
|
+
begin
|
106
|
+
server_wait_for_state(server, "terminated")
|
107
|
+
rescue Exception => e
|
108
|
+
|
109
|
+
end
|
110
|
+
server.destroy
|
111
|
+
end
|
112
|
+
|
113
|
+
def list_servers(filter_by, filter_value)
|
114
|
+
list_resources(:servers, filter_by, filter_value)
|
115
|
+
end
|
116
|
+
|
117
|
+
def list_deployments(filter_by, filter_value)
|
118
|
+
list_resources(:deployments, filter_by, filter_value)
|
119
|
+
end
|
120
|
+
|
121
|
+
def list_clouds(filter_by, filter_value)
|
122
|
+
list_resources(:clouds, filter_by, filter_value)
|
123
|
+
end
|
124
|
+
|
125
|
+
def list_servertemplates(filter_by, filter_value)
|
126
|
+
list_resources(:server_templates, filter_by, filter_value)
|
127
|
+
end
|
128
|
+
|
129
|
+
def list_security_groups(cloud, filter_by, filter_value)
|
130
|
+
list_subresources(cloud, :security_groups, filter_by, filter_value)
|
131
|
+
end
|
132
|
+
|
133
|
+
def list_multi_cloud_images(server_template, filter_by, filter_value)
|
134
|
+
list_subresources(server_template, :multi_cloud_images, filter_by, filter_value)
|
135
|
+
end
|
136
|
+
|
137
|
+
def find_security_group_by_name(cloud, security_group_name)
|
138
|
+
find_cloud_resource(cloud, :security_groups, :by_name, security_group_name)
|
139
|
+
end
|
140
|
+
|
141
|
+
def find_server_by_name(name)
|
142
|
+
find_resource(:servers, :by_name, name)
|
143
|
+
end
|
144
|
+
|
145
|
+
def find_deployment_by_name(name)
|
146
|
+
find_resource(:deployments, :by_name, name)
|
147
|
+
end
|
148
|
+
|
149
|
+
# returns:: String if cloud is found, nil if not found
|
150
|
+
def find_cloud_by_name(name)
|
151
|
+
find_resource(:clouds, :by_name, name)
|
152
|
+
end
|
153
|
+
|
154
|
+
def find_mci_by_name(server_template, mci_name)
|
155
|
+
find_resource(:mcis, :by_name, name)
|
156
|
+
end
|
157
|
+
|
158
|
+
def find_servertemplate(name_or_id)
|
159
|
+
server_template = nil; id = nil; name = nil
|
160
|
+
|
161
|
+
# detect if user passed in a name or an id
|
162
|
+
# there is probably a cleaner way to do this, but I am lazy ATM.
|
163
|
+
begin
|
164
|
+
id = Integer(name_or_id)
|
165
|
+
rescue Exception => e
|
166
|
+
name = name_or_id # Cannot be case to integer, assume a name was passed
|
167
|
+
end
|
168
|
+
|
169
|
+
if name
|
170
|
+
# find ServerTemplate by name
|
171
|
+
st_list = list_resources(:server_templates, :by_name, name)
|
172
|
+
revisions = st_list.map { |st| st.revision }
|
173
|
+
|
174
|
+
# check for duplicate revisions
|
175
|
+
duplicates = (revisions.size != revisions.uniq.size)
|
176
|
+
raise "ERROR: Duplicate ServerTemplate with the name of '#{name}' detected " +
|
177
|
+
"in account -- there can be only one. Please fix via the RightScale dashboard and retry." if duplicates
|
178
|
+
|
179
|
+
# always use latest revision
|
180
|
+
latest_rev = revisions.sort.last
|
181
|
+
server_template = st_list.select { |st| st.revision == latest_rev}.first
|
182
|
+
else
|
183
|
+
# find ServerTemplate by id
|
184
|
+
server_template = @connection.server_templates.index(:id => id)
|
185
|
+
end
|
186
|
+
|
187
|
+
server_template
|
188
|
+
end
|
189
|
+
|
190
|
+
def create_deployment(name)
|
191
|
+
@connection.deployments.create(:deployment => { :name => name, :decription => "Created by the Vagrant"})
|
192
|
+
end
|
193
|
+
|
194
|
+
def destroy_deployment(deployment)
|
195
|
+
deployment.destroy
|
196
|
+
end
|
197
|
+
|
198
|
+
def create_server(deployment, server_template, mci, cloud, name, ssh_key = nil, groups = nil)
|
199
|
+
|
200
|
+
#TODO: mci param not used yet
|
201
|
+
|
202
|
+
# check params
|
203
|
+
unless st_href = server_template.show.href
|
204
|
+
raise "ERROR: ServerTemplate parameter not initialized properly"
|
205
|
+
end
|
206
|
+
|
207
|
+
unless d_href = deployment.show.href
|
208
|
+
raise "ERROR: Deployment parameter not initialized properly"
|
209
|
+
end
|
210
|
+
|
211
|
+
unless c_href = cloud.show.href
|
212
|
+
raise "ERROR: Deployment parameter not initialized properly"
|
213
|
+
end
|
214
|
+
|
215
|
+
if ssh_key
|
216
|
+
unless ssh_key_href = ssh_key.show.href
|
217
|
+
raise "ERROR: ssh_key parameter not initialized properly"
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
security_group_hrefs = nil
|
222
|
+
if groups
|
223
|
+
security_group_hrefs = []
|
224
|
+
groups.each do |group|
|
225
|
+
unless group_href = group.show.href
|
226
|
+
raise "ERROR: ssh_key parameter not initialized properly"
|
227
|
+
end
|
228
|
+
security_group_hrefs << group_href
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
instance_hash = {
|
233
|
+
:cloud_href => c_href,
|
234
|
+
:server_template_href => st_href
|
235
|
+
}
|
236
|
+
instance_hash[:ssh_key_href] = ssh_key_href if ssh_key
|
237
|
+
instance_hash[:security_group_hrefs] = security_group_hrefs if security_group_hrefs
|
238
|
+
|
239
|
+
|
240
|
+
# create server in deployment using specfied ST
|
241
|
+
server =
|
242
|
+
@connection.servers.create({
|
243
|
+
:server => {
|
244
|
+
:name => name,
|
245
|
+
:decription => "Created by the Vagrant",
|
246
|
+
:deployment_href => d_href,
|
247
|
+
:instance => instance_hash
|
248
|
+
}
|
249
|
+
})
|
250
|
+
end
|
251
|
+
|
252
|
+
def is_provisioned?(server)
|
253
|
+
server.show.api_methods.include?(:current_instance)
|
254
|
+
end
|
255
|
+
|
256
|
+
# @param(Hash) inputs Hash input name/value pairs i.e. { :name => "text:dummy"}
|
257
|
+
def launch_server(server, inputs = { :name => "text:dummy"})
|
258
|
+
server_name = server.show.name
|
259
|
+
server.launch(inputs) # TODO: parse inputs from Vagrantfile
|
260
|
+
# XXX: need to create a new server object after launch -- why? API bug?
|
261
|
+
find_server_by_name(server_name)
|
262
|
+
end
|
263
|
+
|
264
|
+
def terminate_server(server)
|
265
|
+
server.terminate
|
266
|
+
end
|
267
|
+
|
268
|
+
# Only use this *before* you launch the server
|
269
|
+
def set_server_inputs(server, inputs)
|
270
|
+
server.show.next_instance.show.inputs.multi_update({"inputs" => inputs})
|
271
|
+
end
|
272
|
+
|
273
|
+
def server_wait_for_state(server, target_state, delay = 10)
|
274
|
+
current_state = server_state(server)
|
275
|
+
while current_state != target_state
|
276
|
+
raise "Unexpected sever state: #{current_state}" if is_bad?(current_state)
|
277
|
+
puts "Server #{current_state}. Waiting for instance to be in #{target_state} state..."
|
278
|
+
sleep delay
|
279
|
+
current_state = server_state(server)
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
def set_bad_states(list_array)
|
284
|
+
@bad_states = list_array
|
285
|
+
end
|
286
|
+
|
287
|
+
def is_bad?(state)
|
288
|
+
@bad_states ||= []
|
289
|
+
@bad_states.select{|s| state =~ /#{s}/}.size > 0
|
290
|
+
end
|
291
|
+
|
292
|
+
def server_ready?(server)
|
293
|
+
server_state(server) == "operational"
|
294
|
+
end
|
295
|
+
|
296
|
+
def server_cloud_name(server)
|
297
|
+
instance = instance_from_server(server)
|
298
|
+
cloud = cloud_from_instance(instance)
|
299
|
+
cloud.show.name
|
300
|
+
end
|
301
|
+
|
302
|
+
def server_info(server)
|
303
|
+
server.show.current_instance.show(:view => 'extended')
|
304
|
+
end
|
305
|
+
|
306
|
+
private
|
307
|
+
|
308
|
+
def server_state(server)
|
309
|
+
instance_from_server(server).show.state
|
310
|
+
end
|
311
|
+
|
312
|
+
def instance_from_server(server)
|
313
|
+
server_data = server.show
|
314
|
+
if is_provisioned?(server)
|
315
|
+
begin
|
316
|
+
server_data.current_instance
|
317
|
+
rescue
|
318
|
+
server_data.next_instance
|
319
|
+
end
|
320
|
+
else
|
321
|
+
server_data.next_instance
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
def cloud_from_instance(instance)
|
326
|
+
instance.show.cloud
|
327
|
+
end
|
328
|
+
|
329
|
+
def find_resource(api_resource, filter_key, filter_value)
|
330
|
+
resource = nil
|
331
|
+
list = list_resources(api_resource, filter_key, filter_value)
|
332
|
+
raise "More than one #{api_resource} with the #{filter_key} of '#{filter_value}'. " +
|
333
|
+
"Please resolve via the RightScale dashboard and retry." if list.size > 1
|
334
|
+
resource = list.first unless list.empty?
|
335
|
+
resource
|
336
|
+
end
|
337
|
+
|
338
|
+
def list_resources(api_resource, filter_key, filter_value)
|
339
|
+
raise ArgumentError.new("api_resource must be a symbol") unless api_resource.kind_of?(Symbol)
|
340
|
+
key = filter_key.to_s.delete("by_") # convert :by_name to "name"
|
341
|
+
filter = {}
|
342
|
+
filter = {:filter => ["#{key}==#{filter_value}"]} if filter_value
|
343
|
+
list = @connection.send(api_resource).index(filter)
|
344
|
+
list
|
345
|
+
end
|
346
|
+
|
347
|
+
def index_resource(api_resource, index_key, index_value)
|
348
|
+
raise ArgumentError.new("api_resource must be a symbol") unless api_resource.kind_of?(Symbol)
|
349
|
+
arry = @connection.send(api_resource).index(index_key => index_value)
|
350
|
+
arry
|
351
|
+
end
|
352
|
+
|
353
|
+
def find_cloud_resource(cloud, api_resource, filter_key, filter_value)
|
354
|
+
resource = nil
|
355
|
+
list = list_subresources(cloud, api_resource, filter_key, filter_value)
|
356
|
+
raise "More than one #{api_resource} with the #{filter_key} of '#{filter_value}'. " +
|
357
|
+
"Please resolve via the RightScale dashboard and retry." if list.size > 1
|
358
|
+
resource = list.first unless list.empty?
|
359
|
+
resource
|
360
|
+
end
|
361
|
+
|
362
|
+
def list_subresources(api_resource, subresource, filter_key, filter_value)
|
363
|
+
raise ArgumentError.new("subresource must be a symbol") unless subresource.kind_of?(Symbol)
|
364
|
+
key = filter_key.to_s.delete("by_") # convert :by_name to "name"
|
365
|
+
filter = {}
|
366
|
+
filter = {:filter => ["#{key}==#{filter_value}"]} if filter_value
|
367
|
+
list = api_resource.show.send(subresource).index(filter)
|
368
|
+
list
|
369
|
+
end
|
370
|
+
|
371
|
+
end
|
372
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Cary Penniman (<cary@rightscale.com>)
|
3
|
+
# Copyright:: Copyright (c) 2013 RightScale, Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
module RightApiProvision
|
20
|
+
class RightApiProvisionException
|
21
|
+
# TODO
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,139 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Cary Penniman (<cary@rightscale.com>)
|
3
|
+
# Copyright:: Copyright (c) 2013 RightScale, Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
module RightApiProvision
|
20
|
+
class Provisioner
|
21
|
+
|
22
|
+
BAD_STATES_UP = [ "stranded", "terminated"]
|
23
|
+
|
24
|
+
def initialize(rightscale_api_object)
|
25
|
+
raise "ERROR: you must supply an valid RightScale API object" unless rightscale_api_object
|
26
|
+
@rsapi = rightscale_api_object
|
27
|
+
end
|
28
|
+
|
29
|
+
def provision(servertemplate,
|
30
|
+
server_name = "default",
|
31
|
+
cloud_name = "ec2",
|
32
|
+
deployment_name = "default",
|
33
|
+
inputs = nil,
|
34
|
+
ssh_key_uuid = nil,
|
35
|
+
security_groups = nil)
|
36
|
+
|
37
|
+
# fail if the requested cloud is not registered with RightScale account
|
38
|
+
@cloud = @rsapi.find_cloud_by_name(cloud_name)
|
39
|
+
raise "ERROR: cannot find a cloud named: '#{cloud_name}'. " +
|
40
|
+
"Please check the spelling of the 'cloud_name' parameter " +
|
41
|
+
"and verify the cloud is registered with " +
|
42
|
+
"your RightScale account?" unless @cloud
|
43
|
+
|
44
|
+
# Verify ssh key uuid, if required by cloud
|
45
|
+
if @rsapi.requires_ssh_keys?(@cloud)
|
46
|
+
@ssh_key = @rsapi.find_ssh_key_by_uuid_or_first(@cloud, ssh_key_uuid)
|
47
|
+
raise "ERROR: cannot find an ssh_key named: #{ssh_key_uuid}" unless @ssh_key
|
48
|
+
end
|
49
|
+
|
50
|
+
# Verify security group, if required by cloud
|
51
|
+
if @rsapi.requires_security_groups?(@cloud)
|
52
|
+
@sec_groups = []
|
53
|
+
security_groups ||= ["default"]
|
54
|
+
security_groups.each do |name|
|
55
|
+
group = @rsapi.find_security_group_by_name(@cloud, name)
|
56
|
+
raise "ERROR: cannot find an security group named: #{name}" unless group
|
57
|
+
@sec_groups << group
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# check for existing deployment and server in RightScale account
|
62
|
+
@deployment = @rsapi.find_deployment_by_name(deployment_name)
|
63
|
+
puts "Deployment '#{deployment_name}' #{@deployment ? "found." : "not found."}"
|
64
|
+
@server = @rsapi.find_server_by_name(server_name) if @deployment
|
65
|
+
puts "Server '#{server_name}' #{@server ? "found." : "not found."}"
|
66
|
+
|
67
|
+
if @server
|
68
|
+
# verify existing server is on the cloud we are requesting, if not fail.
|
69
|
+
actual_cloud_name = @rsapi.server_cloud_name(@server)
|
70
|
+
raise "ERROR: the server is in the '#{actual_cloud_name}' cloud, " +
|
71
|
+
"and not in the requested '#{cloud_name}' cloud.\n" +
|
72
|
+
"Please delete the server or pick and new server name." if cloud_name != actual_cloud_name
|
73
|
+
end
|
74
|
+
|
75
|
+
unless @deployment && @server
|
76
|
+
# we need to create a server, can we find the servertemplate?
|
77
|
+
@servertemplate = @rsapi.find_servertemplate(servertemplate)
|
78
|
+
raise "ERROR: cannot find ServerTemplate '#{servertemplate}'. Did you import it?\n" +
|
79
|
+
"Visit http://bit.ly/VnOiA7 for more info.\n\n" unless @servertemplate
|
80
|
+
# can we find the MCI?
|
81
|
+
#TODO: @mci = @rsapi.find_multicloudimage_by_name(@servertemplate, config.multi_cloud_image_name)
|
82
|
+
end
|
83
|
+
|
84
|
+
# create deployment and server as needed
|
85
|
+
unless @deployment
|
86
|
+
@deployment = @rsapi.create_deployment(deployment_name)
|
87
|
+
puts "Created deployment."
|
88
|
+
end
|
89
|
+
|
90
|
+
unless @server
|
91
|
+
@server = @rsapi.create_server(@deployment, @servertemplate, @mci, @cloud, server_name, @ssh_key, @sec_groups)
|
92
|
+
puts "Created server."
|
93
|
+
end
|
94
|
+
|
95
|
+
unless @rsapi.is_provisioned?(@server)
|
96
|
+
|
97
|
+
# setup any inputs
|
98
|
+
@rsapi.set_server_inputs(@server, inputs) if inputs
|
99
|
+
|
100
|
+
# launch server
|
101
|
+
puts "Launching server..."
|
102
|
+
@server = @rsapi.launch_server(@server, inputs)
|
103
|
+
@rsapi.set_bad_states(BAD_STATES_UP)
|
104
|
+
@rsapi.server_wait_for_state(@server, "booting", 30)
|
105
|
+
end
|
106
|
+
|
107
|
+
# if cloud_name == VAGRANT_CLOUD_NAME
|
108
|
+
# # Vagrant box: grab "Data request URL" from UserData
|
109
|
+
# user_data = @server.current_instance.show(:view => "full").user_data
|
110
|
+
# puts user_data.inspect
|
111
|
+
# @data_request_url = @rsapi.data_request_url(user_data)
|
112
|
+
# puts "Data Request URL: #{@data_request_url}"
|
113
|
+
# else
|
114
|
+
# @rsapi.server_wait_for_state(server_name, "operational", 30)
|
115
|
+
# end
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
def server_ready?
|
120
|
+
@rsapi.server_ready?(@server)
|
121
|
+
end
|
122
|
+
|
123
|
+
def wait_for_operational
|
124
|
+
@rsapi.set_bad_states(BAD_STATES_UP)
|
125
|
+
@rsapi.server_wait_for_state(@server, "operational", 30)
|
126
|
+
end
|
127
|
+
|
128
|
+
def server_info
|
129
|
+
info = @rsapi.server_info(@server)
|
130
|
+
while info.private_ip_addresses.empty?
|
131
|
+
puts "Waiting for cloud to provide IP address..."
|
132
|
+
sleep 30
|
133
|
+
info = @rsapi.server_info(@server)
|
134
|
+
end
|
135
|
+
info
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
139
|
+
end
|