right_rackspace 0.0.0.1
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.
- data/History.txt +6 -0
- data/Manifest.txt +11 -0
- data/README.txt +46 -0
- data/Rakefile +24 -0
- data/lib/benchmark_fix.rb +39 -0
- data/lib/rackspace.rb +744 -0
- data/lib/rackspace_base.rb +528 -0
- data/lib/right_rackspace.rb +46 -0
- data/lib/support.rb +124 -0
- data/test/_test_credentials.rb +41 -0
- data/test/test_right_rackspace.rb +301 -0
- metadata +100 -0
data/lib/rackspace.rb
ADDED
@@ -0,0 +1,744 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2009 RightScale Inc
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
#
|
23
|
+
#
|
24
|
+
module Rightscale
|
25
|
+
module Rackspace
|
26
|
+
VERSION = '0.0.0.1'
|
27
|
+
|
28
|
+
# TODO: KD: Enable this feature when Packspace get rid of the caching issue
|
29
|
+
PAGINATION_ENABLED = false
|
30
|
+
|
31
|
+
# == Rightscale::Rackspace::Interface
|
32
|
+
#
|
33
|
+
# === Examples:
|
34
|
+
#
|
35
|
+
# # Create a handle
|
36
|
+
# rackspace = Rightscale::Rackspace::Interface::new('uw1...cct', '99b0...047d', :verbose_errors => true )
|
37
|
+
#
|
38
|
+
# # list images and flavors
|
39
|
+
# rackspace.list_images(:detaile => true)
|
40
|
+
# rackspace.list_flavors(:detaile => true)
|
41
|
+
#
|
42
|
+
# # launch a new server
|
43
|
+
# image_id = 8
|
44
|
+
# flavor_id = 4
|
45
|
+
# new_server = rackspace.create_server('my-awesome-server', image_id, flavor_id,
|
46
|
+
# :metadata => {
|
47
|
+
# 'metakey1' => 'metavalue1',
|
48
|
+
# 'metakey2' => 'metavalue2',
|
49
|
+
# 'metakey3' => 'metavalue3' },
|
50
|
+
# :personalities => {
|
51
|
+
# '/home/file1.txt' => 'ohoho!',
|
52
|
+
# '/home/file2.txt' => 'ahaha!',
|
53
|
+
# '/home/file3.rb' => 'puts "Olalah!"'}
|
54
|
+
#
|
55
|
+
# puts "New server password is: #{new_server['server']['adminPass']}"
|
56
|
+
#
|
57
|
+
# # change the server password
|
58
|
+
# rackspace.update_server(new_server['server']['id'], 'my_new_password')
|
59
|
+
#
|
60
|
+
# # "upgrade" the server
|
61
|
+
# new_flavor_id = 6
|
62
|
+
# rackspace.resize_server(new_server['server']['id'], new_flavor_id)
|
63
|
+
# rackspace.confirm_resized_server(new_server['server']['id'])
|
64
|
+
#
|
65
|
+
# # make an image from the server
|
66
|
+
# new_image = rackspace.create_image(new_server['server']['id'], 'my-awesome-image-0001')
|
67
|
+
#
|
68
|
+
# # make a hard reboot (power off)
|
69
|
+
# rackspace.reboot_server(new_server['server']['id'], :hard)
|
70
|
+
#
|
71
|
+
# # delete the server
|
72
|
+
# rackspace.delete_server(new_server['server']['id'])
|
73
|
+
#
|
74
|
+
# === RightRackspace gem caching usage (only list_xxx calls). This caching does not hit if any additional URL variables are set through :vars hash.
|
75
|
+
#
|
76
|
+
# # Create a handle
|
77
|
+
# rackspace = Rightscale::Rackspace::Interface::new('uw1...cct', '99b0...047d', :caching => true)
|
78
|
+
#
|
79
|
+
# # make a call. this fills the internal cache with the response and
|
80
|
+
# # a current timestamp
|
81
|
+
# old_list = rackspace.list_servers(:detail => true)
|
82
|
+
#
|
83
|
+
# # sleep a bit
|
84
|
+
# sleep 5
|
85
|
+
#
|
86
|
+
# # make another call
|
87
|
+
# begin
|
88
|
+
# new_list = rackspace.list_servers(:detail => true)
|
89
|
+
# rescue Rightscale::Rackspace::NoChange
|
90
|
+
# puts e.message #=> "Cached: '/servers/detail' has not changed since Thu, 09 Jul 2009 10:53:35 GMT."
|
91
|
+
# # extract the list of servers from internal cache
|
92
|
+
# new_list = rackspace.cache['/servers/detail'][:data]
|
93
|
+
# # the lists must be equal
|
94
|
+
# puts old_list == new_list
|
95
|
+
# end
|
96
|
+
#
|
97
|
+
# # non detailed list of servers
|
98
|
+
# rackspace.list_servers
|
99
|
+
# begin
|
100
|
+
# flavors = rackspace.list_servers
|
101
|
+
# rescue Rightscale::Rackspace::NoChange
|
102
|
+
# flavors = rackspace.cache['/servers'][:data]
|
103
|
+
# ens
|
104
|
+
#
|
105
|
+
# # this does not hit internal cache doe to the :vars.
|
106
|
+
# new_list = rackspace.list_servers(:detail => true, :vars => {'format' => 'json'})
|
107
|
+
#
|
108
|
+
# === Rackspace service caching usage:
|
109
|
+
#
|
110
|
+
# # Create a handle
|
111
|
+
# rackspace = Rightscale::Rackspace::Interface::new('uw1...cct', '99b0...047d')
|
112
|
+
#
|
113
|
+
# # 'if-modified-since' HTTP request header usage:
|
114
|
+
# last_request_time = Time.now - 3600
|
115
|
+
# begin
|
116
|
+
# rackspace.list_servers(:detail => true, :headers => { 'if-modified-since' => last_request_time })
|
117
|
+
# rescue Rightscale::Rackspace::NoChange => e
|
118
|
+
# # e.message can return one of the messages below:
|
119
|
+
# # - "Cached: '/servers/detail' has not changed since Thu, 09 Jul 2009 10:55:41 GMT."
|
120
|
+
# # - "NotModified: '/servers/detail' has not changed since Thu, 09 Jul 2009 10:55:41 GMT."
|
121
|
+
# # The first comes when we have cached response from Rackspace and it can be retreived as
|
122
|
+
# # rackspace.cache['/servers/detail'][:data]. The second one appears when the local
|
123
|
+
# # cache has no stored records for the request.
|
124
|
+
# puts e.message
|
125
|
+
# end
|
126
|
+
#
|
127
|
+
# # 'changes-since' URL variable usage:
|
128
|
+
# begin
|
129
|
+
# new_servers = rackspace.list_servers(:detail => true, :vars => { 'changes-since' => last_request_time })
|
130
|
+
# # show the changes at servers since last_request_time
|
131
|
+
# puts new_servers.inspect
|
132
|
+
# rescue Rightscale::Rackspace::NoChange => e
|
133
|
+
# puts e.message #=>
|
134
|
+
# "NotModified: '/flavors?changes-since=1247137435&limit=1000&offset=0' has not changed since the requested time."
|
135
|
+
# end
|
136
|
+
#
|
137
|
+
# === Callbacks:
|
138
|
+
#
|
139
|
+
# # On response calback
|
140
|
+
# on_response = Proc.new do |handle|
|
141
|
+
# puts ">> response headers: #{handle.last_response.to_hash.inspect}"
|
142
|
+
# end
|
143
|
+
#
|
144
|
+
# # On error calback
|
145
|
+
# on_error = Proc.new do |handle, error_message|
|
146
|
+
# puts ">> Error: #{error_message}"
|
147
|
+
# end
|
148
|
+
#
|
149
|
+
# # Create a handle
|
150
|
+
# rackspace = Rightscale::Rackspace::Interface::new('uw1...cct', '99b0...047d',
|
151
|
+
# :on_response => on_response,
|
152
|
+
# :on_error => on_error)
|
153
|
+
#
|
154
|
+
class Interface
|
155
|
+
|
156
|
+
# The login is executed automatically when one calls any othe API call.
|
157
|
+
# The only use case for this method is when one need to pass any custom
|
158
|
+
# headers or URL vars during a login process.
|
159
|
+
#
|
160
|
+
# rackspace.login #=> true
|
161
|
+
#
|
162
|
+
def login(opts={})
|
163
|
+
authenticate(opts)
|
164
|
+
end
|
165
|
+
|
166
|
+
# List all API versions supported by a Service Endpoint.
|
167
|
+
#
|
168
|
+
# rackspace.list_api_versions #=> {"versions"=>[{"id"=>"v1.0", "status"=>"BETA"}]}
|
169
|
+
#
|
170
|
+
# RightRackspace caching: yes, key: '/'
|
171
|
+
#
|
172
|
+
def list_api_versions(opts={})
|
173
|
+
api_or_cache(:get, "/", opts.merge(:no_service_path => true))
|
174
|
+
end
|
175
|
+
|
176
|
+
# Determine rate limits.
|
177
|
+
#
|
178
|
+
# rackspace.list_limits #=>
|
179
|
+
# {"limits"=>
|
180
|
+
# {"absolute"=>
|
181
|
+
# {"maxNumServers"=>25, "maxIPGroups"=>50, "maxIPGroupMembers"=>25},
|
182
|
+
# "rate"=>
|
183
|
+
# [{"regex"=>".*",
|
184
|
+
# "verb"=>"PUT",
|
185
|
+
# "URI"=>"*",
|
186
|
+
# "remaining"=>10,
|
187
|
+
# "unit"=>"MINUTE",
|
188
|
+
# "value"=>10,
|
189
|
+
# "resetTime"=>1246604596},
|
190
|
+
# {"regex"=>"^/servers",
|
191
|
+
# "verb"=>"POST",
|
192
|
+
# "URI"=>"/servers*",
|
193
|
+
# "remaining"=>1000,
|
194
|
+
# "unit"=>"DAY",
|
195
|
+
# "value"=>1000,
|
196
|
+
# "resetTime"=>1246604596}, ...]}}
|
197
|
+
#
|
198
|
+
#
|
199
|
+
def list_limits(opts={})
|
200
|
+
# # RightRackspace caching: yes, key: '/limits'
|
201
|
+
# api_or_cache(:get, "/limits", opts)
|
202
|
+
api(:get, "/limits", opts)
|
203
|
+
end
|
204
|
+
|
205
|
+
#--------------------------------
|
206
|
+
# Images
|
207
|
+
#--------------------------------
|
208
|
+
|
209
|
+
# List images. Options: :detail => false|true.
|
210
|
+
#
|
211
|
+
# # Get images list.
|
212
|
+
# rackspace.list_images #=>
|
213
|
+
# {"images"=>
|
214
|
+
# [{"name"=>"CentOS 5.2", "id"=>2},
|
215
|
+
# {"name"=>"Gentoo 2008.0", "id"=>3},
|
216
|
+
# {"name"=>"Debian 5.0 (lenny)", "id"=>4},
|
217
|
+
# ...}]}
|
218
|
+
#
|
219
|
+
# # Get the detailed images description.
|
220
|
+
# rackspace.list_images(:detail => true) #=>
|
221
|
+
# {"images"=>
|
222
|
+
# [{"name"=>"CentOS 5.2", "id"=>2, "status"=>"ACTIVE"},
|
223
|
+
# {"name"=>"Gentoo 2008.0",
|
224
|
+
# "id"=>3,
|
225
|
+
# "updated"=>"2007-10-24T12:52:03-05:00",
|
226
|
+
# "status"=>"ACTIVE"},
|
227
|
+
# {"name"=>"Debian 5.0 (lenny)", "id"=>4, "status"=>"ACTIVE"},
|
228
|
+
# {"name"=>"Fedora 10 (Cambridge)", "id"=>5, "status"=>"ACTIVE"},
|
229
|
+
# {"name"=>"CentOS 5.3", "id"=>7, "status"=>"ACTIVE"},
|
230
|
+
# {"name"=>"Ubuntu 9.04 (jaunty)", "id"=>8, "status"=>"ACTIVE"},
|
231
|
+
# {"name"=>"Arch 2009.02", "id"=>9, "status"=>"ACTIVE"},
|
232
|
+
# {"name"=>"Ubuntu 8.04.2 LTS (hardy)", "id"=>10, "status"=>"ACTIVE"},
|
233
|
+
# {"name"=>"Ubuntu 8.10 (intrepid)", "id"=>11, "status"=>"ACTIVE"},
|
234
|
+
# {"name"=>"Red Hat EL 5.3", "id"=>12, "status"=>"ACTIVE"},
|
235
|
+
# {"name"=>"Fedora 11 (Leonidas)", "id"=>13, "status"=>"ACTIVE"},
|
236
|
+
# {"name"=>"my-awesome-image-0001",
|
237
|
+
# "serverId"=>62844,
|
238
|
+
# "progress"=>100,
|
239
|
+
# "id"=>3226,
|
240
|
+
# "updated"=>"2009-07-07T01:20:48-05:00",
|
241
|
+
# "status"=>"ACTIVE",
|
242
|
+
# "created"=>"2009-07-07T01:17:16-05:00"}]}
|
243
|
+
#
|
244
|
+
# RightRackspace caching: yes, keys: '/images', '/images/detail'
|
245
|
+
#
|
246
|
+
def list_images(opts={})
|
247
|
+
api_or_cache(:get, detailed_path("/images", opts), opts.merge(:incrementally => PAGINATION_ENABLED))
|
248
|
+
end
|
249
|
+
|
250
|
+
# Incrementally list images.
|
251
|
+
#
|
252
|
+
# # list images by 3
|
253
|
+
# rackspace.incrementally_list_images(0, 3, :detail=>true) do |response|
|
254
|
+
# puts response.inspect
|
255
|
+
# true
|
256
|
+
# end
|
257
|
+
#
|
258
|
+
def incrementally_list_images(offset=nil, limit=nil, opts={}, &block)
|
259
|
+
incrementally_list_resources(:get, detailed_path("/images", opts), offset, limit, opts, &block)
|
260
|
+
end
|
261
|
+
|
262
|
+
# Get image data.
|
263
|
+
#
|
264
|
+
# rackspace.get_image(5) #=>
|
265
|
+
# {"image"=>{"name"=>"Fedora 10 (Cambridge)", "id"=>5, "status"=>"ACTIVE"}}
|
266
|
+
#
|
267
|
+
def get_image(image_id, opts={})
|
268
|
+
api(:get, "/images/#{image_id}", opts)
|
269
|
+
end
|
270
|
+
|
271
|
+
# Create a new image for the given server ID. Once complete, a new image will be
|
272
|
+
# available that can be used to rebuild or create servers. Specifying the same image name as an
|
273
|
+
# existing custom image replaces the image
|
274
|
+
#
|
275
|
+
# # create an image
|
276
|
+
# new_image = rackspace.create_image(62844, 'my-awesome-image-0001') #=>
|
277
|
+
# {"image"=>{"name"=>"my-awesome-image-0001", "serverId"=>62844, "id"=>3226}}
|
278
|
+
#
|
279
|
+
# # sleep a bit
|
280
|
+
# sleep 10
|
281
|
+
#
|
282
|
+
# # get the new image status
|
283
|
+
# rackspace.get_image(new_image['image']['id']) #=>
|
284
|
+
# {"image"=>
|
285
|
+
# {"name"=>"my-awesome-image-0001",
|
286
|
+
# "progress"=>78,
|
287
|
+
# "id"=>3226,
|
288
|
+
# "updated"=>"2009-07-07T01:20:16-05:00",
|
289
|
+
# "status"=>"SAVING",
|
290
|
+
# "created"=>"2009-07-07T01:16:51-05:00"}}
|
291
|
+
#
|
292
|
+
# # sleep more to make the new image active
|
293
|
+
# sleep 60
|
294
|
+
#
|
295
|
+
# # list all the images
|
296
|
+
# rackspace.list_images(:detail => true) #=>
|
297
|
+
# {"images"=>
|
298
|
+
# [{"name"=>"CentOS 5.2", "id"=>2, "status"=>"ACTIVE"},
|
299
|
+
# {"name"=>"Gentoo 2008.0",
|
300
|
+
# "id"=>3,
|
301
|
+
# "updated"=>"2007-10-24T12:52:03-05:00",
|
302
|
+
# "status"=>"ACTIVE"},
|
303
|
+
# {"name"=>"Debian 5.0 (lenny)", "id"=>4, "status"=>"ACTIVE"},
|
304
|
+
# {"name"=>"Fedora 10 (Cambridge)", "id"=>5, "status"=>"ACTIVE"},
|
305
|
+
# {"name"=>"CentOS 5.3", "id"=>7, "status"=>"ACTIVE"},
|
306
|
+
# {"name"=>"Ubuntu 9.04 (jaunty)", "id"=>8, "status"=>"ACTIVE"},
|
307
|
+
# {"name"=>"Arch 2009.02", "id"=>9, "status"=>"ACTIVE"},
|
308
|
+
# {"name"=>"Ubuntu 8.04.2 LTS (hardy)", "id"=>10, "status"=>"ACTIVE"},
|
309
|
+
# {"name"=>"Ubuntu 8.10 (intrepid)", "id"=>11, "status"=>"ACTIVE"},
|
310
|
+
# {"name"=>"Red Hat EL 5.3", "id"=>12, "status"=>"ACTIVE"},
|
311
|
+
# {"name"=>"Fedora 11 (Leonidas)", "id"=>13, "status"=>"ACTIVE"},
|
312
|
+
# {"name"=>"my-awesome-image-0001",
|
313
|
+
# "serverId"=>62844,
|
314
|
+
# "progress"=>100,
|
315
|
+
# "id"=>3226,
|
316
|
+
# "updated"=>"2009-07-07T01:20:48-05:00",
|
317
|
+
# "status"=>"ACTIVE",
|
318
|
+
# "created"=>"2009-07-07T01:17:16-05:00"}]}
|
319
|
+
#
|
320
|
+
#
|
321
|
+
def create_image(server_id, name, opts={})
|
322
|
+
body = { 'image' => { 'name' => name,
|
323
|
+
'serverId' => server_id } }
|
324
|
+
api(:post, "/images", opts.merge(:body => body.to_json))
|
325
|
+
end
|
326
|
+
|
327
|
+
#--------------------------------
|
328
|
+
# Flavors
|
329
|
+
#--------------------------------
|
330
|
+
|
331
|
+
# List flavors. Options: :detail => false|true.
|
332
|
+
#
|
333
|
+
# # Get list of flavors.
|
334
|
+
# rackspace.list_flavors #=>
|
335
|
+
# {"flavors"=>
|
336
|
+
# [{"name"=>"256 slice", "id"=>1},
|
337
|
+
# {"name"=>"512 slice", "id"=>2},
|
338
|
+
# {"name"=>"1GB slice", "id"=>3},
|
339
|
+
# ...}]}
|
340
|
+
#
|
341
|
+
# # Get the detailed flavors description.
|
342
|
+
# rackspace.list_flavors(:detail => true) #=>
|
343
|
+
# {"flavors"=>
|
344
|
+
# [{"name"=>"256 slice", "id"=>1, "ram"=>256, "disk"=>10},
|
345
|
+
# {"name"=>"512 slice", "id"=>2, "ram"=>512, "disk"=>20},
|
346
|
+
# {"name"=>"1GB slice", "id"=>3, "ram"=>1024, "disk"=>40},
|
347
|
+
# ...}]}
|
348
|
+
#
|
349
|
+
# # Get the most recent changes or Rightscale::Rackspace::NoChange.
|
350
|
+
# # (no RightRackspace gem caching)
|
351
|
+
# rackspace.list_flavors(:detail => true, :vars => {'changes-since'=>Time.now-3600}) #=>
|
352
|
+
#
|
353
|
+
# RightRackspace caching: yes, keys: '/flavors', '/flavors/detail'
|
354
|
+
#
|
355
|
+
def list_flavors(opts={})
|
356
|
+
api_or_cache(:get, detailed_path("/flavors", opts), opts.merge(:incrementally => PAGINATION_ENABLED))
|
357
|
+
end
|
358
|
+
|
359
|
+
# Incrementally list flavors.
|
360
|
+
#
|
361
|
+
# rackspace.incrementally_list_flavors(0,3) do |response|
|
362
|
+
# puts response.inspect
|
363
|
+
# true
|
364
|
+
# end
|
365
|
+
#
|
366
|
+
def incrementally_list_flavors(offset=nil, limit=nil, opts={}, &block)
|
367
|
+
incrementally_list_resources(:get, detailed_path("/flavors", opts), offset, limit, opts, &block)
|
368
|
+
end
|
369
|
+
|
370
|
+
# Get flavor data.
|
371
|
+
#
|
372
|
+
# rackspace.get_flavor(5) #=>
|
373
|
+
# {"flavor"=>{"name"=>"4GB slice", "id"=>5, "ram"=>4096, "disk"=>160}}
|
374
|
+
#
|
375
|
+
def get_flavor(flavor_id, opts={})
|
376
|
+
api(:get, "/flavors/#{flavor_id}", opts)
|
377
|
+
end
|
378
|
+
|
379
|
+
#--------------------------------
|
380
|
+
# Servers
|
381
|
+
#--------------------------------
|
382
|
+
|
383
|
+
# List servers. Options: :detail => false|true.
|
384
|
+
#
|
385
|
+
# rackspace.list_servers #=>
|
386
|
+
# {"servers"=>[{"name"=>"my-super-awesome-server-", "id"=>62844}]}
|
387
|
+
#
|
388
|
+
# rackspace.list_servers(:detail => true) #=>
|
389
|
+
# {"servers"=>
|
390
|
+
# [{"name"=>"my-super-awesome-server-",
|
391
|
+
# "addresses"=>
|
392
|
+
# {"public"=>["174.143.246.228"], "private"=>["10.176.134.157"]},
|
393
|
+
# "progress"=>100,
|
394
|
+
# "imageId"=>8,
|
395
|
+
# "metadata"=>{"data1"=>"Ohoho!", "data2"=>"Ehehe!"},
|
396
|
+
# "id"=>62844,
|
397
|
+
# "flavorId"=>3,
|
398
|
+
# "hostId"=>"fabfc1cebef6f1d7e4b075138dbd6b46",
|
399
|
+
# "status"=>"ACTIVE"}]
|
400
|
+
#
|
401
|
+
def list_servers(opts={})
|
402
|
+
api_or_cache(:get, detailed_path("/servers", opts), opts.merge(:incrementally => PAGINATION_ENABLED))
|
403
|
+
end
|
404
|
+
|
405
|
+
# Incrementally list servers.
|
406
|
+
#
|
407
|
+
# # list servers by 3
|
408
|
+
# rackspace.incrementally_list_servers(0, 3) do |response|
|
409
|
+
# puts response.inspect
|
410
|
+
# true
|
411
|
+
# end
|
412
|
+
#
|
413
|
+
def incrementally_list_servers(offset=nil, limit=nil, opts={}, &block)
|
414
|
+
incrementally_list_resources(:get, detailed_path("/servers", opts), offset, limit, opts, &block)
|
415
|
+
end
|
416
|
+
|
417
|
+
# Launch a new server.
|
418
|
+
# +Server_data+ is a hash of params params:
|
419
|
+
# Mandatory: :name, :image_id, :flavor_id
|
420
|
+
# Optional: :metadata, :personalities
|
421
|
+
#
|
422
|
+
# rackspace.create_server(
|
423
|
+
# :name => 'my-awesome-server',
|
424
|
+
# :image_id => 8,
|
425
|
+
# :flavor_id => 4,
|
426
|
+
# :metadata => { 'KD1' => 'XXXX1', 'KD2' => 'XXXX2'},
|
427
|
+
# :personalities => { '/home/1.txt' => 'woo-hoo',
|
428
|
+
# '/home/2.rb' => 'puts"Olalah!' }) #=>
|
429
|
+
# {"server"=>
|
430
|
+
# {"name"=>"my-awesome-server",
|
431
|
+
# "addresses"=>{"public"=>["174.143.56.6"], "private"=>["10.176.1.235"]},
|
432
|
+
# "progress"=>0,
|
433
|
+
# "imageId"=>8,
|
434
|
+
# "metadata"=>{"KD1"=>"XXXX1", "KD2"=>"XXXX2"},
|
435
|
+
# "adminPass"=>"my-awesome-server85lzHZ",
|
436
|
+
# "id"=>2290,
|
437
|
+
# "flavorId"=>4,
|
438
|
+
# "hostId"=>"19956ee1c79a57e481b652ddf818a569",
|
439
|
+
# "status"=>"BUILD"}}
|
440
|
+
#
|
441
|
+
def create_server(server_data, opts={} )
|
442
|
+
personality = server_data[:personalities].to_a.dup
|
443
|
+
personality.map! { |file, contents| { 'path'=> file, 'contents' => Base64.encode64(contents).chomp } }
|
444
|
+
body = {
|
445
|
+
'server' => {
|
446
|
+
'name' => server_data[:name],
|
447
|
+
'imageId' => server_data[:image_id],
|
448
|
+
'flavorId' => server_data[:flavor_id],
|
449
|
+
}
|
450
|
+
}
|
451
|
+
#body['server']['adminPass'] = server_data[:password] if server_data[:password]
|
452
|
+
body['server']['sharedIpGroupId'] = server_data[:shared_ip_group_id] if server_data[:shared_ip_group_id]
|
453
|
+
body['server']['metadata'] = server_data[:metadata] unless server_data[:metadata].blank?
|
454
|
+
body['server']['personality'] = personality unless personality.blank?
|
455
|
+
api(:post, "/servers", opts.merge(:body => body.to_json))
|
456
|
+
end
|
457
|
+
|
458
|
+
# Get a server data.
|
459
|
+
# rackspace.get_server(2290)
|
460
|
+
# {"server"=>
|
461
|
+
# {"name"=>"my-awesome-server",
|
462
|
+
# "addresses"=>{"public"=>["174.143.56.6"], "private"=>["10.176.1.235"]},
|
463
|
+
# "progress"=>100,
|
464
|
+
# "imageId"=>8,
|
465
|
+
# "metadata"=>{"KD1"=>"XXXX1", "KD2"=>"XXXX2"},
|
466
|
+
# "id"=>2290,
|
467
|
+
# "flavorId"=>4,
|
468
|
+
# "hostId"=>"19956ee1c79a57e481b652ddf818a569",
|
469
|
+
# "status"=>"ACTIVE"}}
|
470
|
+
#
|
471
|
+
def get_server(server_id, opts={})
|
472
|
+
api(:get, "/servers/#{server_id}", opts)
|
473
|
+
end
|
474
|
+
|
475
|
+
# Change server name and/or password.
|
476
|
+
# +Server_data+: :name, :password
|
477
|
+
#
|
478
|
+
# rackspace.update_server(2290, :password => '12345' ) #=> true
|
479
|
+
# rackspace.update_server(2290, :name => 'my-super-awesome-server', :password => '67890' ) #=> true
|
480
|
+
#
|
481
|
+
# P.S. the changes will appers in some seconds.
|
482
|
+
#
|
483
|
+
# P.P.S. changes server status: 'ACTIVE' -> 'PASSWORD'.
|
484
|
+
#
|
485
|
+
def update_server(server_id, server_data, opts={})
|
486
|
+
body = { 'server' => {} }
|
487
|
+
body['server']['name'] = server_data[:name] if server_data[:name]
|
488
|
+
body['server']['adminPass'] = server_data[:password] if server_data[:password]
|
489
|
+
api(:put, "/servers/#{server_id}", opts.merge(:body => body.to_json))
|
490
|
+
end
|
491
|
+
|
492
|
+
# Reboot a server.
|
493
|
+
#
|
494
|
+
# # Soft reboot
|
495
|
+
# rackspace.reboot_server(2290) #=> true
|
496
|
+
#
|
497
|
+
# # Hard reboot (power off)
|
498
|
+
# rackspace.reboot_server(2290, :hard) #=> true
|
499
|
+
#
|
500
|
+
def reboot_server(server_id, type = :soft, opts={})
|
501
|
+
body = { 'reboot' => { 'type' => type.to_s.upcase } }
|
502
|
+
api(:post, "/servers/#{server_id}/action", opts.merge(:body => body.to_json))
|
503
|
+
end
|
504
|
+
|
505
|
+
# The rebuild function removes all data on the server and replaces it with the specified image.
|
506
|
+
# Server id and IP addresses will remain the same.
|
507
|
+
#
|
508
|
+
# # rebuild a server
|
509
|
+
# rackspace.rebuild_server(62844, 3226) #=> true
|
510
|
+
#
|
511
|
+
# # watch for the progress
|
512
|
+
# rackspace.get_server(62844) #=>
|
513
|
+
# {"server"=>
|
514
|
+
# {"name"=>"my-super-awesome-server-",
|
515
|
+
# "addresses"=>{"public"=>["174.143.246.228"], "private"=>["10.176.134.157"]},
|
516
|
+
# "progress"=>65,
|
517
|
+
# "imageId"=>3226,
|
518
|
+
# "metadata"=>{"data1"=>"Ohoho!", "data2"=>"Ehehe!"},
|
519
|
+
# "id"=>62844,
|
520
|
+
# "flavorId"=>3,
|
521
|
+
# "hostId"=>"fabfc1cebef6f1d7e4b075138dbd6b46",
|
522
|
+
# "status"=>"REBUILD"}}
|
523
|
+
#
|
524
|
+
def rebuild_server(server_id, image_id, opts={})
|
525
|
+
body = { 'rebuild' => { 'imageId' => image_id } }
|
526
|
+
api(:post, "/servers/#{server_id}/action", opts.merge(:body => body.to_json))
|
527
|
+
end
|
528
|
+
|
529
|
+
# The resize function converts an existing server to a different flavor, in essence, scaling the server up
|
530
|
+
# or down. The original server is saved for a period of time to allow rollback if there is a problem. All
|
531
|
+
# resizes should be tested and explicitly confirmed, at which time the original server is removed. All
|
532
|
+
# resizes are automatically confirmed after 24 hours if they are not explicitly confirmed or reverted.
|
533
|
+
#
|
534
|
+
# rackspace.resize_server(2290, 3) #=> true
|
535
|
+
# rackspace.get_server(2290) #=>
|
536
|
+
# {"server"=>
|
537
|
+
# {"name"=>"my-awesome-server",
|
538
|
+
# "addresses"=>{"public"=>["174.143.56.6"], "private"=>["10.176.1.235"]},
|
539
|
+
# "progress"=>0,
|
540
|
+
# "imageId"=>8,
|
541
|
+
# "metadata"=>{"KD1"=>"XXXX1", "KD2"=>"XXXX2"},
|
542
|
+
# "id"=>2290,
|
543
|
+
# "flavorId"=>4,
|
544
|
+
# "hostId"=>"19956ee1c79a57e481b652ddf818a569",
|
545
|
+
# "status"=>"QUEUE_RESIZE"}}
|
546
|
+
#
|
547
|
+
def resize_server(server_id, flavor_id, opts={})
|
548
|
+
body = { 'resize' => { 'flavorId' => flavor_id } }
|
549
|
+
api(:post, "/servers/#{server_id}/action", opts.merge(:body => body.to_json))
|
550
|
+
end
|
551
|
+
|
552
|
+
# Confirm a server resize action.
|
553
|
+
#
|
554
|
+
# rackspace.confirm_resized_server(2290) #=> true
|
555
|
+
#
|
556
|
+
def confirm_resized_server(server_id, opts={})
|
557
|
+
body = { 'confirmResize' => nil }
|
558
|
+
api(:post, "/servers/#{server_id}/action", opts.merge(:body => body.to_json))
|
559
|
+
end
|
560
|
+
|
561
|
+
# Revert a server resize action.
|
562
|
+
#
|
563
|
+
# rackspace.revert_resized_server(2290) #=> true
|
564
|
+
#
|
565
|
+
def revert_resized_server(server_id, opts={})
|
566
|
+
body = { 'revertResize' => nil }
|
567
|
+
api(:post, "/servers/#{server_id}/action", opts.merge(:body => body.to_json))
|
568
|
+
end
|
569
|
+
|
570
|
+
#--------------------------------
|
571
|
+
# Server addresses
|
572
|
+
#--------------------------------
|
573
|
+
|
574
|
+
# Get server addresses.
|
575
|
+
#
|
576
|
+
# # get all addresses
|
577
|
+
# rackspace.list_addresses(62844) #=>
|
578
|
+
# {"addresses"=>{"public"=>["174.143.246.228"], "private"=>["10.176.134.157"]}}
|
579
|
+
#
|
580
|
+
# # get public addresses
|
581
|
+
# rackspace.list_addresses(62844, :public) #=>
|
582
|
+
# {"public"=>["174.143.246.228"]}
|
583
|
+
#
|
584
|
+
# # get private addresses
|
585
|
+
# rackspace.list_addresses(62844, :private) #=>
|
586
|
+
# {"private"=>["10.176.134.157"]}
|
587
|
+
#
|
588
|
+
# RightRackspace caching: no
|
589
|
+
def list_addresses(server_id, address_type=:all, opts={})
|
590
|
+
path = "/servers/#{server_id}/ips"
|
591
|
+
case address_type.to_s
|
592
|
+
when 'public' then path += "/public"
|
593
|
+
when 'private' then path += "/private"
|
594
|
+
end
|
595
|
+
api(:get, path, opts.merge(:incrementally => PAGINATION_ENABLED))
|
596
|
+
end
|
597
|
+
|
598
|
+
# Share an IP from an existing server in the specified shared IP group to another
|
599
|
+
# specified server in the same group.
|
600
|
+
#
|
601
|
+
# rackspace.share_ip_address(2296, 42, "174.143.56.6") #=> true
|
602
|
+
#
|
603
|
+
# rackspace.get_server(2290) #=>
|
604
|
+
# {"server"=>
|
605
|
+
# {"name"=>"my-awesome-server",
|
606
|
+
# "addresses"=>
|
607
|
+
# {"public"=>["174.143.56.6", "174.143.56.13"], "private"=>["10.176.1.235"]},
|
608
|
+
# "progress"=>100,
|
609
|
+
# "imageId"=>8,
|
610
|
+
# "metadata"=>{"KD1"=>"XXXX1", "KD2"=>"XXXX2"},
|
611
|
+
# "id"=>2290,
|
612
|
+
# "flavorId"=>3,
|
613
|
+
# "hostId"=>"1d5fa1271f57354d9e2861e848568eb3",
|
614
|
+
# "status"=>"SHARE_IP_NO_CONFIG"}}
|
615
|
+
#
|
616
|
+
def share_ip_address(server_id, shared_ip_group_id, address, configure_server=true, opts={})
|
617
|
+
body = {
|
618
|
+
'shareIp' => {
|
619
|
+
'sharedIpGroupId' => shared_ip_group_id,
|
620
|
+
'configureServer' => configure_server
|
621
|
+
}
|
622
|
+
}
|
623
|
+
api(:put, "/servers/#{server_id}/ips/public/#{address}", opts.merge(:body => body.to_json))
|
624
|
+
end
|
625
|
+
|
626
|
+
# Remove a shared IP address from the specified server
|
627
|
+
#
|
628
|
+
# rackspace.unshare_ip_address(2296, "174.143.56.6") #=> true
|
629
|
+
#
|
630
|
+
def unshare_ip_address(server_id, address, opts={})
|
631
|
+
body = { 'unshareIp' => { 'addr' => address } }
|
632
|
+
api(:delete, "/servers/#{server_id}/ips/public/#{address}", opts.merge(:body => body.to_json))
|
633
|
+
end
|
634
|
+
|
635
|
+
# Delete a server.
|
636
|
+
# Returns +true+ on success.
|
637
|
+
#
|
638
|
+
# rackspace.delete_server(2284) #=> true
|
639
|
+
#
|
640
|
+
def delete_server(server_id, opts={})
|
641
|
+
api(:delete, "/servers/#{server_id}", opts)
|
642
|
+
end
|
643
|
+
|
644
|
+
#--------------------------------
|
645
|
+
# Backup Schedules
|
646
|
+
#--------------------------------
|
647
|
+
|
648
|
+
# Get the backup schedule for the specified server.
|
649
|
+
#
|
650
|
+
# rackspace.get_backup_schedule(62844) #=>
|
651
|
+
# {"backupSchedule"=>{"weekly"=>"DISABLED", "enabled"=>false, "daily"=>"DISABLED"}}
|
652
|
+
#
|
653
|
+
def get_backup_schedule(server_id, opts={})
|
654
|
+
api(:get, "/servers/#{server_id}/backup_schedule", opts)
|
655
|
+
end
|
656
|
+
|
657
|
+
# Create a new backup schedule or updates an existing backup schedule for the specified server.
|
658
|
+
# +Schedule_data+ is a hash: :enabled, :daily, :weekly
|
659
|
+
#
|
660
|
+
# # set just a daily backup
|
661
|
+
# rackspace.update_backup_schedule(62844, {:enabled => true, :daily => "H_0400_0600"}) #=> true
|
662
|
+
#
|
663
|
+
# # set both the weekly and the daily schedules
|
664
|
+
# h.update_backup_schedule(62844, {:enabled => true, :daily => "H_0400_0600", :weekly => 'MONDAY'}) #=> true
|
665
|
+
#
|
666
|
+
# # disable (delete) the schedule
|
667
|
+
# h.update_backup_schedule(62844, {:enabled => false}) #=> true
|
668
|
+
#
|
669
|
+
# P.S. the changes may appear in some seconds
|
670
|
+
#
|
671
|
+
def update_backup_schedule(server_id, schedule_data={}, opts={})
|
672
|
+
body = { 'backupSchedule' => { 'enabled' => schedule_data[:enabled] ? true : false } }
|
673
|
+
daily = schedule_data[:daily].blank? ? 'DISABLED' : schedule_data[:daily].to_s.upcase
|
674
|
+
weekly = schedule_data[:weekly].blank? ? 'DISABLED' : schedule_data[:weekly].to_s.upcase
|
675
|
+
body['backupSchedule']['daily'] = daily
|
676
|
+
body['backupSchedule']['weekly'] = weekly
|
677
|
+
api(:post, "/servers/#{server_id}/backup_schedule", opts.merge(:body => body.to_json))
|
678
|
+
end
|
679
|
+
|
680
|
+
# Deletes the backup schedule for the specified server.
|
681
|
+
#
|
682
|
+
# h.delete_backup_schedule(62844) #=> true
|
683
|
+
#
|
684
|
+
# P.S. the changes may appear in some seconds
|
685
|
+
#
|
686
|
+
def delete_backup_schedule(server_id, opts={})
|
687
|
+
api(:delete, "/servers/#{server_id}/backup_schedule", opts)
|
688
|
+
end
|
689
|
+
|
690
|
+
#--------------------------------
|
691
|
+
# Shared IP Groups
|
692
|
+
#--------------------------------
|
693
|
+
|
694
|
+
# List shared IP groups. Options: :detail => false|true.
|
695
|
+
#
|
696
|
+
# RightRackspace caching: yes, keys: '/shared_ip_groups', '/shared_ip_groups/detail'
|
697
|
+
#
|
698
|
+
def list_shared_ip_groups(opts={})
|
699
|
+
api_or_cache(:get, detailed_path("/shared_ip_groups", opts), opts.merge(:incrementally => PAGINATION_ENABLED))
|
700
|
+
end
|
701
|
+
|
702
|
+
# Incrementally list IP groups.
|
703
|
+
#
|
704
|
+
# # list groups by 5
|
705
|
+
# rackspace.incrementally_list_shared_ip_groups(0, 5) do |x|
|
706
|
+
# puts x.inspect
|
707
|
+
# true
|
708
|
+
# end
|
709
|
+
#
|
710
|
+
def incrementally_list_shared_ip_groups(offset=nil, limit=nil, opts={}, &block)
|
711
|
+
incrementally_list_resources(:get, detailed_path("/shared_ip_groups", opts), offset, limit, opts, &block)
|
712
|
+
end
|
713
|
+
|
714
|
+
# Create a new shared IP group.
|
715
|
+
#
|
716
|
+
# rackspace.create_shared_ip_group('my_awesome_group', 2290) #=>
|
717
|
+
# {"sharedIpGroup"=>{"name"=>"my_awesome_group", "id"=>42}}
|
718
|
+
#
|
719
|
+
def create_shared_ip_group(name, server_id=nil, opts={})
|
720
|
+
body = { 'sharedIpGroup' => { 'name' => name } }
|
721
|
+
body['sharedIpGroup']['server'] = server_id unless server_id.blank?
|
722
|
+
api(:post, "/shared_ip_groups", opts.merge(:body => body.to_json))
|
723
|
+
end
|
724
|
+
|
725
|
+
# Get shared IP group data.
|
726
|
+
#
|
727
|
+
# rackspace.list_shared_ip_groups #=>
|
728
|
+
# {"sharedIpGroups"=>[{"name"=>"my_awesome_group", "id"=>42, "servers"=>[2290]}]}
|
729
|
+
#
|
730
|
+
def get_shared_ip_group(shared_ip_group_id, opts={})
|
731
|
+
api(:get, "/shared_ip_groups/#{shared_ip_group_id}", opts)
|
732
|
+
end
|
733
|
+
|
734
|
+
# Delete an IP group.
|
735
|
+
#
|
736
|
+
# rackspace.delete_shared_ip_group(42) #=> true
|
737
|
+
#
|
738
|
+
def delete_shared_ip_group(shared_ip_group_id, opts={})
|
739
|
+
api(:delete, "/shared_ip_groups/#{shared_ip_group_id}", opts)
|
740
|
+
end
|
741
|
+
|
742
|
+
end
|
743
|
+
end
|
744
|
+
end
|