right_flexiscale 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +4 -0
- data/Manifest.txt +13 -0
- data/README.txt +78 -0
- data/Rakefile +49 -0
- data/lib/api/Flexiscale API.rb +513 -0
- data/lib/api/Flexiscale APIAddons.rb +228 -0
- data/lib/api/Flexiscale APIDriver.rb +315 -0
- data/lib/api/Flexiscale APIMappingRegistry.rb +597 -0
- data/lib/api/benchmark_fix.rb +39 -0
- data/lib/api/right_flexiscale_api.rb +819 -0
- data/lib/right_flexiscale.rb +42 -0
- data/test/test_helper.rb +6 -0
- data/test/test_right_flexiscale.rb +140 -0
- metadata +77 -0
@@ -0,0 +1,39 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2007 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
|
+
|
25
|
+
|
26
|
+
# A hack because there's a bug in add! in Benchmark::Tms
|
27
|
+
module Benchmark #:nodoc:
|
28
|
+
class Tms #:nodoc:
|
29
|
+
def add!(&blk)
|
30
|
+
t = Benchmark::measure(&blk)
|
31
|
+
@utime = utime + t.utime
|
32
|
+
@stime = stime + t.stime
|
33
|
+
@cutime = cutime + t.cutime
|
34
|
+
@cstime = cstime + t.cstime
|
35
|
+
@real = real + t.real
|
36
|
+
self
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,819 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2008-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
|
+
require 'Flexiscale APIDriver'
|
25
|
+
require 'Flexiscale APIAddons'
|
26
|
+
require 'logger'
|
27
|
+
|
28
|
+
module Rightscale
|
29
|
+
|
30
|
+
class FlexiscaleError < RuntimeError
|
31
|
+
end
|
32
|
+
|
33
|
+
class FlexiscaleBenchmarkingBlock # :nodoc:
|
34
|
+
attr_accessor :service
|
35
|
+
def initialize
|
36
|
+
# Benchmark::Tms instance for service (Ec2, S3, or SQS) access benchmarking.
|
37
|
+
@service = Benchmark::Tms.new()
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Simple connection errors handler
|
42
|
+
class FlexiscaleConnectionHandler
|
43
|
+
# Number of times to retry the request after encountering the first error
|
44
|
+
HTTP_CONNECTION_RETRY_COUNT = 3
|
45
|
+
# Length of the post-error probationary period during which all requests will fail
|
46
|
+
HTTP_CONNECTION_RETRY_DELAY = 15
|
47
|
+
|
48
|
+
@@params = { :http_connection_retry_count => HTTP_CONNECTION_RETRY_COUNT,
|
49
|
+
:http_connection_retry_delay => HTTP_CONNECTION_RETRY_DELAY,
|
50
|
+
:exception => FlexiscaleError,
|
51
|
+
:retriable_errors => [ 'Timeout::Error',
|
52
|
+
'Errno::ECONNREFUSED',
|
53
|
+
'Errno::ETIMEDOUT',
|
54
|
+
'OpenSSL::SSL::SSLError',
|
55
|
+
'SocketError' ],
|
56
|
+
:relogin_on_errors => [ 'InvalidCredentials',
|
57
|
+
'Your credentials are unsuitable or missing']
|
58
|
+
}
|
59
|
+
# Params accessor:
|
60
|
+
#
|
61
|
+
# Rightscale::FlexiscaleConnectionHandler.params[:http_connection_retry_count] = 5
|
62
|
+
# Rightscale::FlexiscaleConnectionHandler.params[:retriable_errors] << 'MyAwesomeExceptionClassName'
|
63
|
+
#
|
64
|
+
def self.params
|
65
|
+
@@params
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
@@errors = []
|
71
|
+
|
72
|
+
def self.reset_errors # :nodoc:
|
73
|
+
@@errors = []
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.add_retriable_error(exception) # :nodoc:
|
77
|
+
@@errors << [Time.now.utc, exception]
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.errors_count # :nodoc:
|
81
|
+
@@errors.size
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.last_error # :nodoc:
|
85
|
+
@@errors.empty? ? nil : @@errors.last.last
|
86
|
+
end
|
87
|
+
|
88
|
+
def self.last_error_time # :nodoc:
|
89
|
+
@@errors.empty? ? nil : @@errors.last.first
|
90
|
+
end
|
91
|
+
|
92
|
+
# Error is assumed as retriable if it's class name is equal to error message or
|
93
|
+
# error message includes on of @@params[:retriable_errors] stamps
|
94
|
+
def self.is_error_retriable?(e) # :nodoc:
|
95
|
+
@@params[:retriable_errors].include?(e.class.name) ||
|
96
|
+
@@params[:retriable_errors].find { |partial_message| e.message[/#{partial_message}/] }
|
97
|
+
end
|
98
|
+
|
99
|
+
def self.is_relogin_error?(e) # :nodoc:
|
100
|
+
@@params[:relogin_on_errors].include?(e.class.name) ||
|
101
|
+
@@params[:relogin_on_errors].find { |partial_message| e.message[/#{partial_message}/] }
|
102
|
+
end
|
103
|
+
|
104
|
+
# Check the amount of connection errors and raise if it exceeds max value
|
105
|
+
def self.check_retries_and_raise_if_required # :nodoc:
|
106
|
+
if errors_count >= @@params[:http_connection_retry_count] &&
|
107
|
+
last_error_time + @@params[:http_connection_retry_delay] > Time.now
|
108
|
+
warning = ("Re-raising same error: #{last_error.message} " +
|
109
|
+
"-- error count: #{errors_count}, error age: #{Time.now.to_i - @@errors.first.first.to_i}")
|
110
|
+
#
|
111
|
+
yield(warning) if block_given?
|
112
|
+
#
|
113
|
+
exception = @@params[:exception] ? @@params[:exception].new(last_error.message) : last_error
|
114
|
+
raise exception
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# Perform a retry on low level (connection) errors or raise on high level (flexiscale API)
|
119
|
+
def self.process_exception(e = nil) # :nodoc:
|
120
|
+
e ||= $!
|
121
|
+
if is_error_retriable?(e) || is_relogin_error?(e)
|
122
|
+
add_retriable_error(e)
|
123
|
+
yield(e, "#{self.last_error.class.name}: request failure count: #{self.errors_count}, exception: '#{e.message}'") if block_given?
|
124
|
+
elsif e.is_a?(Interrupt)
|
125
|
+
# raise Interrupt guys: Ctrl/C etc.
|
126
|
+
# PS I check for Interrupt after :retriable_errors check just because some of :retriable_errors list are also
|
127
|
+
# Interrupt guys (Timeouts for example). So we break only if the interrupt is not in :retriable_errors list.
|
128
|
+
raise e
|
129
|
+
else
|
130
|
+
# Convert SOAP::FaultError to Rightscale::FlexiscaleError
|
131
|
+
if e.is_a?(SOAP::FaultError)
|
132
|
+
e = FlexiscaleError.new(e.message)
|
133
|
+
# Create a backtrace stack from a scratch if it is abcent...
|
134
|
+
# It does not show the exact point of error but a stack of methods at least.
|
135
|
+
# (not sure why but SOAP::FaultError has backtrace empty, may be due to threads usage)
|
136
|
+
e.set_backtrace(caller(0)) unless e.backtrace && !e.backtrace.empty?
|
137
|
+
# log and raise error
|
138
|
+
end
|
139
|
+
yield(e, false) if block_given?
|
140
|
+
raise e
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
# = Rightscale::FlexiscaleApi -- RightScale Flexiscale interface
|
146
|
+
# The Rightscale::FlexiscaleApi class provides a complete interface to Flexiscale's
|
147
|
+
# Web service.
|
148
|
+
# For explanations of the semantics
|
149
|
+
# of each call, please refer to Flexiscale's documentation at
|
150
|
+
# https://api.flexiscale.com
|
151
|
+
#
|
152
|
+
# Examples:
|
153
|
+
#
|
154
|
+
# flexiscale = Rightscale::FlexiscaleApi.new(username, password)
|
155
|
+
#
|
156
|
+
# # get servers list
|
157
|
+
# servers = flexiscale.list_servers
|
158
|
+
#
|
159
|
+
# # OS images
|
160
|
+
# images = flexiscale.list_operating_system_images
|
161
|
+
#
|
162
|
+
# # create a new server
|
163
|
+
# image = flexiscale.list_operating_system_images.first
|
164
|
+
# package = flexiscale.list_packages.first
|
165
|
+
# vlan = flexiscale.list_vlans.first
|
166
|
+
# server_id = flexiscale.create_server('my_awesome_server', package[:fxs_id], 1, 1024, 20, image[:fxs_id], vlan[:fxs_id])
|
167
|
+
#
|
168
|
+
# # launch a server
|
169
|
+
# job_id = flexiscale.start_server('my_awesome_server')
|
170
|
+
#
|
171
|
+
# # reboot
|
172
|
+
# job_id = flexiscale.reboot_server('my_awesome_server')
|
173
|
+
#
|
174
|
+
# # stop and destroy server
|
175
|
+
# job_id = flexiscale.stop_server('my_awesome_server')
|
176
|
+
#
|
177
|
+
# if flexiscale.wait_for_jobs(job_id)
|
178
|
+
# flexiscale.destroy_server('my_awesome_server')
|
179
|
+
# end
|
180
|
+
#
|
181
|
+
# Error handling: all operations raise an Rightscale::FlexiscaleError in case
|
182
|
+
# of problems.
|
183
|
+
#
|
184
|
+
class FlexiscaleApi
|
185
|
+
attr_reader :params
|
186
|
+
attr_reader :logged_in
|
187
|
+
attr_reader :username
|
188
|
+
attr_reader :password
|
189
|
+
attr_reader :api
|
190
|
+
attr_reader :last_raw_response
|
191
|
+
|
192
|
+
@@bench = FlexiscaleBenchmarkingBlock.new
|
193
|
+
def self.bench_service # :nodoc:
|
194
|
+
@@bench.service
|
195
|
+
end
|
196
|
+
|
197
|
+
FLEXISCALE_WSDL = "https://api.flexiscale.com/current/Flexiscale.wsdl"
|
198
|
+
|
199
|
+
SERVER_STOP_SHUTDOWN = 1
|
200
|
+
SERVER_STOP_POWEROFF = 2
|
201
|
+
|
202
|
+
DEFAULT_HTTP_CONNECT_TIMEOUT = 60
|
203
|
+
DEFAULT_HTTP_RECEIVE_TIMEOUT = 300
|
204
|
+
|
205
|
+
# Create a new interface to Flexiscale API.
|
206
|
+
# If _username_ or/and _password_ are undefined then
|
207
|
+
# ENV['FLEXISCALE_USERNAME'] and ENV['FLEXISCALE_PASSWORD'] are used.
|
208
|
+
#
|
209
|
+
# - params: :raw_response - return SOAP objects as is
|
210
|
+
# :logger - logger object (STDOUT is used by default)
|
211
|
+
# :skip_logging - log nothing
|
212
|
+
#
|
213
|
+
# flexiscale = Rightscale::FlexiscaleApi.new(username, password)
|
214
|
+
# flexiscale.list_packages #=> [{:fxs_id => 12345,
|
215
|
+
# :name => "package"}]
|
216
|
+
#
|
217
|
+
# flexiscale = Rightscale::FlexiscaleApi.new(username, password, :raw_response=>true) #=>
|
218
|
+
# flexiscale.list_packages #=> [#<FlexiScale::Package:0xb78a1904
|
219
|
+
# @package_id = 12345,
|
220
|
+
# @package_name = "package">]
|
221
|
+
#
|
222
|
+
def initialize(username=nil, password=nil, params={})
|
223
|
+
@username = username || ENV['FLEXISCALE_USERNAME']
|
224
|
+
@password = password || ENV['FLEXISCALE_PASSWORD']
|
225
|
+
@params = params
|
226
|
+
# vars initialization
|
227
|
+
@params[:logger] ||= Logger.new(STDOUT)
|
228
|
+
@logged_in = false
|
229
|
+
@last_raw_response = nil
|
230
|
+
# create a new interface
|
231
|
+
@api = ::FlexiScale::FlexiScale.new
|
232
|
+
@api.wiredump_dev = STDERR if $DEBUG
|
233
|
+
# timeouts: 1 min for connection establishment and
|
234
|
+
# 5 min for wait_for_jobs
|
235
|
+
@api.options["protocol.http.connect_timeout"] = DEFAULT_HTTP_CONNECT_TIMEOUT
|
236
|
+
@api.options["protocol.http.receive_timeout"] = DEFAULT_HTTP_RECEIVE_TIMEOUT
|
237
|
+
# @api.options["protocol.http.send_timeout"]
|
238
|
+
end
|
239
|
+
|
240
|
+
def log(message, level=:info) # :nodoc:
|
241
|
+
unless @params[:skip_logging]
|
242
|
+
message = "#{self.class.name}: #{message}"
|
243
|
+
@params[:logger].__send__(level, message)
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
def log_error(e, level=:error) # :nodoc:
|
248
|
+
unless @params[:skip_logging]
|
249
|
+
trace = e.backtrace.join("\n")
|
250
|
+
message = "#{e.class.name}: #{e.message}\n#{trace}"
|
251
|
+
@params[:logger].__send__(level, message)
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
def internal_login(username=nil, password=nil) # :nodoc:
|
256
|
+
@username = username if username
|
257
|
+
@password = password if password
|
258
|
+
@logged_in = false
|
259
|
+
@api.login(@username, @password)
|
260
|
+
@logged_in = true
|
261
|
+
end
|
262
|
+
|
263
|
+
# Request Flexiscale.
|
264
|
+
# Performs a retry on login problems (timeouts etc).
|
265
|
+
# - params: :no_login - do not auto login
|
266
|
+
#
|
267
|
+
def perform_request(params={}, &block) # :nodoc:
|
268
|
+
loop do
|
269
|
+
result = nil
|
270
|
+
# Check retries count. And raise an exception if we run into permanent failure
|
271
|
+
# Block is called before exception to log an event.
|
272
|
+
FlexiscaleConnectionHandler.check_retries_and_raise_if_required do |warning|
|
273
|
+
log warning, :warn
|
274
|
+
end
|
275
|
+
# perform a request
|
276
|
+
begin
|
277
|
+
# login if required
|
278
|
+
if !params[:no_login] && !@logged_in
|
279
|
+
@@bench.service.add! do
|
280
|
+
internal_login
|
281
|
+
end
|
282
|
+
end
|
283
|
+
# call the block of code is passed
|
284
|
+
if block
|
285
|
+
@@bench.service.add! do
|
286
|
+
result = @last_raw_response = block.call
|
287
|
+
end
|
288
|
+
end
|
289
|
+
# reset errors list
|
290
|
+
FlexiscaleConnectionHandler.reset_errors
|
291
|
+
# convert a result to a handy format
|
292
|
+
if result.class.name[/^FlexiScale::/] && !@params[:raw_response]
|
293
|
+
result = result.to_handy_hash
|
294
|
+
end
|
295
|
+
return result
|
296
|
+
|
297
|
+
rescue Exception => exception
|
298
|
+
# Log the errors we got and increaze the errors count.
|
299
|
+
# +retriable_message+ is set when we get a low level connection error (and retry is to be performed).
|
300
|
+
# If +retriable_message+ is not set - the err is a high level one and it will be reraised as FlexiscaleError.
|
301
|
+
# Any case the block of code is used just to log an event.
|
302
|
+
FlexiscaleConnectionHandler.process_exception(exception) do |e, retriable_message|
|
303
|
+
log(retriable_message, :warn) if retriable_message
|
304
|
+
if FlexiscaleConnectionHandler.is_relogin_error?(e)
|
305
|
+
@logged_in = false
|
306
|
+
log('Internal logout performed.', :warn)
|
307
|
+
end
|
308
|
+
end
|
309
|
+
end
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
#----------------------------------------
|
314
|
+
# FLEXISCALE_API
|
315
|
+
#----------------------------------------
|
316
|
+
|
317
|
+
#----------------------------------------
|
318
|
+
# Miscellaneous
|
319
|
+
#----------------------------------------
|
320
|
+
|
321
|
+
# Loging into the API. Returns +true+ on success.
|
322
|
+
# If _username_ and/or _password_ are not specified then previously defined values are used.
|
323
|
+
#
|
324
|
+
# https://api.flexiscale.com/current/doc/login.html
|
325
|
+
def login(username=nil, password=nil)
|
326
|
+
@logged_in = false
|
327
|
+
@username = username if username
|
328
|
+
@password = password if password
|
329
|
+
# without a block perform_request just logs in
|
330
|
+
perform_request
|
331
|
+
true
|
332
|
+
end
|
333
|
+
|
334
|
+
# Logout of the API.
|
335
|
+
#
|
336
|
+
# https://api.flexiscale.com/current/doc/login.html
|
337
|
+
def logout
|
338
|
+
@logged_in = false
|
339
|
+
perform_request(:no_login=>true) do
|
340
|
+
@api.logout
|
341
|
+
end
|
342
|
+
end
|
343
|
+
|
344
|
+
# List packages. Returns an array of packages.
|
345
|
+
# _List_ is an array of ids.
|
346
|
+
#
|
347
|
+
# flexiscale.list_packages #=>
|
348
|
+
# [{:fxs_id => 12345,
|
349
|
+
# :name => "package"}]
|
350
|
+
#
|
351
|
+
# https://api.flexiscale.com/current/doc/list_packages.html
|
352
|
+
def list_packages(*list)
|
353
|
+
perform_request do
|
354
|
+
@api.listPackages(list.flatten)
|
355
|
+
end
|
356
|
+
end
|
357
|
+
|
358
|
+
#----------------------------------------
|
359
|
+
# Servers
|
360
|
+
#----------------------------------------
|
361
|
+
|
362
|
+
# List servers. Returns an array of servers.
|
363
|
+
# _List_ is an array of servers names.
|
364
|
+
#
|
365
|
+
# flexiscale.list_servers #=>
|
366
|
+
# [{:memory => 512,
|
367
|
+
# :processors => 1,
|
368
|
+
# :fxs_id => 1343,
|
369
|
+
# :image_id => 27,
|
370
|
+
# :image_name => "Ubuntu 8.04 LTS",
|
371
|
+
# :initial_password => "0000000000000000\n",
|
372
|
+
# :name => "my_awesome_server",
|
373
|
+
# :uptime => 0,
|
374
|
+
# :modified => false,
|
375
|
+
# :status => "stopped"
|
376
|
+
# :fxs_status => "5",
|
377
|
+
# :package_id => 12345,
|
378
|
+
# :disks => [2285],
|
379
|
+
# :disk_capacity => 20480,
|
380
|
+
# :ip_addresses => ["92.60.121.68"],
|
381
|
+
# :network_interfaces => [778]}, ... ]
|
382
|
+
#
|
383
|
+
# https://api.flexiscale.com/current/doc/list_servers.html
|
384
|
+
def list_servers(*list)
|
385
|
+
perform_request do
|
386
|
+
@api.listServers(list.flatten)
|
387
|
+
end
|
388
|
+
end
|
389
|
+
|
390
|
+
# Create a server. Returns a new +server_id+.
|
391
|
+
# (_Memory_ in MB, _disk_capacity_ in GB)
|
392
|
+
#
|
393
|
+
# flexiscale.create_server('my_awesome_server', 12345, 1, 512, 20, 27, 1552) #=> 1343
|
394
|
+
#
|
395
|
+
# https://api.flexiscale.com/current/doc/create_server.html
|
396
|
+
def create_server(server_name, package_id, processors, memory, disk_capacity, operating_system_image_id, vlan_id)
|
397
|
+
image = FlexiScale::OperatingSystemImage.new(operating_system_image_id)
|
398
|
+
server = FlexiScale::Server.new(nil, server_name, nil, package_id, processors, memory, image, disk_capacity)
|
399
|
+
vlan = FlexiScale::Vlan.new(vlan_id)
|
400
|
+
perform_request do
|
401
|
+
@api.createServer(server, vlan)
|
402
|
+
end
|
403
|
+
end
|
404
|
+
|
405
|
+
# Modify server params. Returns a modified server data.
|
406
|
+
# Note: a stop_start_server request will need to be sent after the modification
|
407
|
+
# have been made which will reboot the server and apply the changes
|
408
|
+
#
|
409
|
+
# flexiscale.modify_server(1343, 1, 1024) #=>
|
410
|
+
# {:memory => 1024,
|
411
|
+
# :processors => 1,
|
412
|
+
# :fxs_id => 1343,
|
413
|
+
# :image_id => 27,
|
414
|
+
# :image_name => "Ubuntu 8.04 LTS",
|
415
|
+
# :initial_password => "0000000000000000\n",
|
416
|
+
# :name => "my_awesome_server",
|
417
|
+
# :uptime => 0,
|
418
|
+
# :modified => false,
|
419
|
+
# :status => "stopped"
|
420
|
+
# :fxs_status => "5",
|
421
|
+
# :package_id => 12345,
|
422
|
+
# :disks => [2285],
|
423
|
+
# :disk_capacity => 20480,
|
424
|
+
# :ip_addresses => ["92.60.121.68"],
|
425
|
+
# :network_interfaces => [778]}
|
426
|
+
#
|
427
|
+
# https://api.flexiscale.com/current/doc/modify_server.html
|
428
|
+
def modify_server(server_id, processors, memory)
|
429
|
+
server = FlexiScale::Server.new(server_id, nil, nil, nil, processors, memory)
|
430
|
+
perform_request do
|
431
|
+
@api.modifyServer(server)
|
432
|
+
end
|
433
|
+
end
|
434
|
+
|
435
|
+
# Start a server.
|
436
|
+
# The response is returned as a integer which is the job number of the request,
|
437
|
+
# this can be looked up using _wait_for_jobs_ and _list_jobs_.
|
438
|
+
#
|
439
|
+
# flexiscale.start_server('my_awesome_server') #=> 11034
|
440
|
+
#
|
441
|
+
# https://api.flexiscale.com/current/doc/start_server.html
|
442
|
+
def start_server(server_name, notes='')
|
443
|
+
perform_request do
|
444
|
+
@api.startServer(server_name, notes)
|
445
|
+
end
|
446
|
+
end
|
447
|
+
|
448
|
+
# Reboot a server.
|
449
|
+
# The response is returned as a integer which is the job number of the request,
|
450
|
+
# this can be looked up using _wait_for_jobs_ and _list_jobs_.
|
451
|
+
#
|
452
|
+
# flexiscale.reboot_server('my_awesome_server') #=> 11035
|
453
|
+
#
|
454
|
+
# https://api.flexiscale.com/current/doc/reboot_server.html
|
455
|
+
def reboot_server(server_name, notes='')
|
456
|
+
perform_request do
|
457
|
+
@api.rebootServer(server_name, notes)
|
458
|
+
end
|
459
|
+
end
|
460
|
+
|
461
|
+
# Stop a server.
|
462
|
+
# The response is returned as a integer which is the job number of the request,
|
463
|
+
# this can be looked up using _wait_for_jobs_ and _list_jobs_.
|
464
|
+
#
|
465
|
+
# - method: (:shutdown || Rightscale::FlexiscaleApi::SERVER_STOP_SHUTDOWN) ||
|
466
|
+
# (:poweroff || Rightscale::FlexiscaleApi::SERVER_STOP_POWEROFF)
|
467
|
+
#
|
468
|
+
# flexiscale.stop_server('my_awesome_server') #=> 11036
|
469
|
+
#
|
470
|
+
# https://api.flexiscale.com/current/doc/stop_server.html
|
471
|
+
def stop_server(server_name, method=:shutdown, notes='')
|
472
|
+
perform_request do
|
473
|
+
case method.to_s
|
474
|
+
when 'shutdown', SERVER_STOP_SHUTDOWN.to_s then @api.stopServer(server_name, SERVER_STOP_SHUTDOWN, notes)
|
475
|
+
when 'poweroff', SERVER_STOP_POWEROFF.to_s then @api.stopServer(server_name, SERVER_STOP_POWEROFF, notes)
|
476
|
+
end
|
477
|
+
end
|
478
|
+
end
|
479
|
+
|
480
|
+
# Stop and Restart an existing server.
|
481
|
+
# The response is returned as a integer which is the job number of the request,
|
482
|
+
# this can be looked up using _wait_for_jobs_ and _list_jobs_.
|
483
|
+
#
|
484
|
+
# flexiscale.stop_start_server('my_awesome_server') #=> 11037
|
485
|
+
#
|
486
|
+
# https://api.flexiscale.com/current/doc/stop_start_server.html
|
487
|
+
def stop_start_server(server_name, notes='')
|
488
|
+
perform_request do
|
489
|
+
@api.stopStartServer(server_name, notes)
|
490
|
+
end
|
491
|
+
end
|
492
|
+
|
493
|
+
# Destroy a server. Returns +true+ if OK.
|
494
|
+
#
|
495
|
+
# flexiscale.destroy_server('my_awesome_server') #=> true
|
496
|
+
#
|
497
|
+
# https://api.flexiscale.com/current/doc/delete_server.html
|
498
|
+
def destroy_server(server_name)
|
499
|
+
perform_request do
|
500
|
+
@api.destroyServer(server_name)
|
501
|
+
end
|
502
|
+
true
|
503
|
+
end
|
504
|
+
|
505
|
+
#----------------------------------------
|
506
|
+
# Disk Management
|
507
|
+
#----------------------------------------
|
508
|
+
|
509
|
+
# List disks. Returns an array of disks.
|
510
|
+
# _List_ is an array of ids.
|
511
|
+
#
|
512
|
+
# flexiscale.list_disks #=>
|
513
|
+
# [{:capacity => 20,
|
514
|
+
# :server_id => 1322,
|
515
|
+
# :usage => 0.03,
|
516
|
+
# :name => "Server 1322 Operating System",
|
517
|
+
# :locked => 0,
|
518
|
+
# :package_id => 12345,
|
519
|
+
# :fxs_id => 2262}, ... ]
|
520
|
+
#
|
521
|
+
# https://api.flexiscale.com/current/doc/list_disks.html
|
522
|
+
def list_disks(*list)
|
523
|
+
perform_request do
|
524
|
+
@api.listDisks(list.flatten)
|
525
|
+
end
|
526
|
+
end
|
527
|
+
|
528
|
+
#----------------------------------------
|
529
|
+
# Jobs
|
530
|
+
#----------------------------------------
|
531
|
+
|
532
|
+
# List jobs. Returns an array of jobs.
|
533
|
+
# _List_ is an array of ids.
|
534
|
+
#
|
535
|
+
# flexiscale.list_jobs #=>
|
536
|
+
# [{:fxs_status => 2,
|
537
|
+
# :status => "completed",
|
538
|
+
# :started_at => Fri Jun 13 13:21:27 UTC 2008,
|
539
|
+
# :description => "start_virtual_server",
|
540
|
+
# :finished_at => Fri Jun 13 13:23:42 UTC 2008,
|
541
|
+
# :type_id => 1322,
|
542
|
+
# :notes => "kd-from-home-via-api",
|
543
|
+
# :fxs_id => 10928,
|
544
|
+
# :parent_job => 0}, ... ]
|
545
|
+
#
|
546
|
+
# https://api.flexiscale.com/current/doc/list_jobs.html
|
547
|
+
def list_jobs(*list)
|
548
|
+
perform_request do
|
549
|
+
@api.ListJobs(list.flatten)
|
550
|
+
end
|
551
|
+
end
|
552
|
+
|
553
|
+
# List running jobs. Returns an array of running jobs.
|
554
|
+
# _List_ is an array of ids.
|
555
|
+
#
|
556
|
+
# flexiscale.list_running_jobs #=> []
|
557
|
+
#
|
558
|
+
# https://api.flexiscale.com/current/doc/list_running_jobs.html
|
559
|
+
def list_running_jobs
|
560
|
+
perform_request do
|
561
|
+
@api.listRunningJobs
|
562
|
+
end
|
563
|
+
end
|
564
|
+
|
565
|
+
# Wait for jobs completion.
|
566
|
+
# The command returns a boolean value, if +true+ all jobs have been completed
|
567
|
+
# successfully, if +false+ one or more jobs failed.
|
568
|
+
# _List_ is an array of ids.
|
569
|
+
#
|
570
|
+
# flexiscale.wait_for_jobs(1132, 1133) #=> true
|
571
|
+
#
|
572
|
+
# For a long wait tasks you may need to increase
|
573
|
+
# @api.options["protocol.http.receive_timeout"]. The default value is
|
574
|
+
# DEFAULT_HTTP_RECEIVE_TIMEOUT
|
575
|
+
#
|
576
|
+
# https://api.flexiscale.com/current/doc/wait_for_jobs.html
|
577
|
+
def wait_for_jobs(*list)
|
578
|
+
perform_request do
|
579
|
+
@api.wait_for_jobs(list.flatten)
|
580
|
+
end
|
581
|
+
end
|
582
|
+
|
583
|
+
# List a filtered jobs. Returns an array of jobs.
|
584
|
+
# - order_by: :status || :job_id || :type_id || :started || :finished || :description || :parent_job
|
585
|
+
# - direction: :asc || :desc
|
586
|
+
#
|
587
|
+
# flexiscale.filter(100, :status, :desc ) #=>
|
588
|
+
# [{:fxs_status => 2,
|
589
|
+
# :status => "completed",
|
590
|
+
# :started_at => Fri Jun 13 13:21:27 UTC 2008,
|
591
|
+
# :description => "start_virtual_server",
|
592
|
+
# :finished_at => Fri Jun 13 13:23:42 UTC 2008,
|
593
|
+
# :type_id => 1322,
|
594
|
+
# :notes => "kd-from-home-via-api",
|
595
|
+
# :fxs_id => 10928,
|
596
|
+
# :parent_job => 0}, ... ]
|
597
|
+
#
|
598
|
+
# https://api.flexiscale.com/current/doc/filter_jobs.html
|
599
|
+
def filter_jobs(limit=50, order_by=:status, direction=:asc)
|
600
|
+
perform_request do
|
601
|
+
@api.filterJobs(limit, order_by.to_s, direction.to_s.upcase)
|
602
|
+
end
|
603
|
+
end
|
604
|
+
|
605
|
+
#----------------------------------------
|
606
|
+
# Operating Systems
|
607
|
+
#----------------------------------------
|
608
|
+
|
609
|
+
# List available operating system images.
|
610
|
+
#
|
611
|
+
# flexiscale.list_operating_system_images #=>
|
612
|
+
# [{:fxs_id=>1, :name=>"Centos 5"},
|
613
|
+
# {:fxs_id=>3, :name=>"Centos 4"},
|
614
|
+
# {:fxs_id=>4, :name=>"Windows Server 2003 Standard"},
|
615
|
+
# {:fxs_id=>6, :name=>"Debian 4.0 (Etch)"},
|
616
|
+
# {:fxs_id=>15, :name=>"Centos 5 64 Bit"},
|
617
|
+
# {:fxs_id=>16, :name=>"Ubuntu 6.06 LTS"},
|
618
|
+
# {:fxs_id=>17, :name=>"Windows Server 2003 Standard 64 Bit"},
|
619
|
+
# {:fxs_id=>18, :name=>"Debian 4.0 64 Bit (Etch)"},
|
620
|
+
# {:fxs_id=>27, :name=>"Ubuntu 8.04 LTS"}]
|
621
|
+
#
|
622
|
+
# https://api.flexiscale.com/current/doc/list_operating_system_images.html
|
623
|
+
def list_operating_system_images
|
624
|
+
perform_request do
|
625
|
+
@api.listOperatingSystemImages
|
626
|
+
end
|
627
|
+
end
|
628
|
+
|
629
|
+
#----------------------------------------
|
630
|
+
# Network Management
|
631
|
+
#----------------------------------------
|
632
|
+
|
633
|
+
# List network interfaces. Returns an array of nics.
|
634
|
+
# _List_ is an array of ids.
|
635
|
+
#
|
636
|
+
# flexiscale.list_network_interfaces #=>
|
637
|
+
# [{:server_id => 1322,
|
638
|
+
# :fxs_id => 749,
|
639
|
+
# :vlan_id => 552,
|
640
|
+
# :mac_address => "00:0f:4b:22:cb:0c"}, ... ]
|
641
|
+
#
|
642
|
+
# https://api.flexiscale.com/current/doc/list_nics.html
|
643
|
+
def list_network_interfaces(*list)
|
644
|
+
perform_request do
|
645
|
+
@api.listNetworkInterfaces(list.flatten)
|
646
|
+
end
|
647
|
+
end
|
648
|
+
|
649
|
+
# List vlans. Returns an array of vlans.
|
650
|
+
# _List_ is an array of ids.
|
651
|
+
#
|
652
|
+
# flexiscale.list_vlans #=>
|
653
|
+
# [{:fxs_id => 552,
|
654
|
+
# :name => "Cust15608VLAN1"}]
|
655
|
+
#
|
656
|
+
# https://api.flexiscale.com/current/doc/list_servers.html
|
657
|
+
def list_vlans(*list)
|
658
|
+
perform_request do
|
659
|
+
@api.listVlans(list.flatten)
|
660
|
+
end
|
661
|
+
end
|
662
|
+
|
663
|
+
# List IpBlocks. Returns an array of ip_blocks.
|
664
|
+
# _List_ is an array of ids.
|
665
|
+
#
|
666
|
+
# flexiscale.list_ip_blocks #=>
|
667
|
+
# [{:block_type => 29,
|
668
|
+
# :end_ip => "92.60.120.70",
|
669
|
+
# :fxs_id => 404,
|
670
|
+
# :customer_vlan_id => 552,
|
671
|
+
# :start_ip => "92.60.120.60"}]
|
672
|
+
#
|
673
|
+
# https://api.flexiscale.com/current/doc/list_ip_blocks.html
|
674
|
+
def list_ip_blocks(*list)
|
675
|
+
perform_request do
|
676
|
+
@api.listIpBlocks(list.flatten)
|
677
|
+
end
|
678
|
+
end
|
679
|
+
|
680
|
+
#----------------------------------------
|
681
|
+
# Billing Management
|
682
|
+
#----------------------------------------
|
683
|
+
|
684
|
+
# List debit items.
|
685
|
+
#
|
686
|
+
# - item_type: :virtual_server || :vlan || :disk_space
|
687
|
+
#
|
688
|
+
# flexiscale.list_debit_items(:virtual_server, 1322) #=>
|
689
|
+
# [{:description => "1 Hour of uptime for server kd test 1",
|
690
|
+
# :type_id => 1322,
|
691
|
+
# :item_value => 1.0,
|
692
|
+
# :item_cost => 0.05,
|
693
|
+
# :fxs_id => 738858,
|
694
|
+
# :debit_id => 415192,
|
695
|
+
# :timestamp => Fri Jun 13 16:45:04 +0400 2008,
|
696
|
+
# :item_type => "virtual_server"}]
|
697
|
+
#
|
698
|
+
# https://api.flexiscale.com/current/doc/list_debit_items.html
|
699
|
+
def list_debit_items(item_type, type_id, start_date=nil, end_date=nil)
|
700
|
+
perform_request do
|
701
|
+
@api.listDebitItems(item_type.to_s, type_id,
|
702
|
+
start_date && start_date.to_i, end_date && end_date.to_i)
|
703
|
+
end
|
704
|
+
end
|
705
|
+
|
706
|
+
# List debits.
|
707
|
+
#
|
708
|
+
# https://api.flexiscale.com/current/doc/list_debits.html
|
709
|
+
def list_debits(start_date=nil, end_date=nil)
|
710
|
+
perform_request do
|
711
|
+
@api.listDebits(start_date && start_date.to_i, end_date && end_date.to_i)
|
712
|
+
end
|
713
|
+
end
|
714
|
+
|
715
|
+
# List credits.
|
716
|
+
#
|
717
|
+
# https://api.flexiscale.com/current/doc/list_credits.html
|
718
|
+
def list_credits(start_date=nil, end_date=nil)
|
719
|
+
perform_request do
|
720
|
+
@api.listCredits(start_date && start_date.to_i, end_date && end_date.to_i)
|
721
|
+
end
|
722
|
+
end
|
723
|
+
|
724
|
+
#----------------------------------------
|
725
|
+
# Firewalls (flexiscale beta)
|
726
|
+
#----------------------------------------
|
727
|
+
|
728
|
+
# List firewalls.
|
729
|
+
#
|
730
|
+
# https://api.flexiscale.com/current/doc/list_firewalls.html
|
731
|
+
def list_firewalls(*list)
|
732
|
+
perform_request do
|
733
|
+
@api.listFirewalls(list.flatten)
|
734
|
+
end
|
735
|
+
end
|
736
|
+
|
737
|
+
# List firewall rulles.
|
738
|
+
# - direction: nil || :in || :out
|
739
|
+
#
|
740
|
+
# https://api.flexiscale.com/current/doc/list_firewall_rules.html
|
741
|
+
def list_firewall_rules(firewall_id, direction=nil)
|
742
|
+
perform_request do
|
743
|
+
@api.listFirewallRules(firewall_id, direction && direction.to_s.upcase)
|
744
|
+
end
|
745
|
+
end
|
746
|
+
|
747
|
+
# List firewall protocols.
|
748
|
+
#
|
749
|
+
# flexiscale.list_firewall_protocols #=>
|
750
|
+
# [{:fxs_id=>0, :name=>"Any"},
|
751
|
+
# {:fxs_id=>6, :name=>"TCP"},
|
752
|
+
# {:fxs_id=>17, :name=>"UDP"},
|
753
|
+
# {:fxs_id=>1, :name=>"ICMP"},
|
754
|
+
# {:fxs_id=>41, :name=>"GRE"},
|
755
|
+
# {:fxs_id=>50, :name=>"IPSEC-ESP"},
|
756
|
+
# {:fxs_id=>51, :name=>"IPSEC-AH"},
|
757
|
+
# {:fxs_id=>115, :name=>"L2TP"}]
|
758
|
+
#
|
759
|
+
# https://api.flexiscale.com/current/doc/list_firewall_protocols.html
|
760
|
+
def list_firewall_protocols
|
761
|
+
perform_request do
|
762
|
+
@api.listFirewallProtocols
|
763
|
+
end
|
764
|
+
end
|
765
|
+
|
766
|
+
# List ICMP protocols.
|
767
|
+
#
|
768
|
+
# flexiscale.list_icmp_protocols #=>
|
769
|
+
# [{:fxs_id=>0, :description=>"Echo Reply"},
|
770
|
+
# {:fxs_id=>8, :description=>"Echo"},
|
771
|
+
# {:fxs_id=>3, :description=>"Destination Unreachable"},
|
772
|
+
# {:fxs_id=>4, :description=>"Source Quench"},
|
773
|
+
# {:fxs_id=>5, :description=>"Redirect"},
|
774
|
+
# {:fxs_id=>6, :description=>"Alternate Host Address"},
|
775
|
+
# {:fxs_id=>9, :description=>"Router Advertisement"},
|
776
|
+
# {:fxs_id=>10, :description=>"Router Solicitation"},
|
777
|
+
# {:fxs_id=>11, :description=>"Time Exceeded"},
|
778
|
+
# {:fxs_id=>12, :description=>"Parameter Problem"},
|
779
|
+
# {:fxs_id=>13, :description=>"Timestamp"},
|
780
|
+
# {:fxs_id=>14, :description=>"Timestamp Reply"},
|
781
|
+
# {:fxs_id=>15, :description=>"Information Request"},
|
782
|
+
# {:fxs_id=>16, :description=>"Information Reply"},
|
783
|
+
# {:fxs_id=>17, :description=>"Address Mask Request"},
|
784
|
+
# {:fxs_id=>18, :description=>"Address Mask Reply"}]
|
785
|
+
#
|
786
|
+
# https://api.flexiscale.com/current/doc/list_icmp_protocols.html
|
787
|
+
def list_icmp_protocols
|
788
|
+
perform_request do
|
789
|
+
@api.listIcmpProtocols
|
790
|
+
end
|
791
|
+
end
|
792
|
+
|
793
|
+
# List firewall templates.
|
794
|
+
#
|
795
|
+
# flexiscale.list_firewall_templates #=>
|
796
|
+
# [{:fxs_id=>1, :name=>"Linux Web Server", :default_policy=>"REJECT"},
|
797
|
+
# {:fxs_id=>2, :name=>"Windows Web Server", :default_policy=>"REJECT"},
|
798
|
+
# {:fxs_id=>3, :name=>"Linux Email Server", :default_policy=>"REJECT"}]
|
799
|
+
#
|
800
|
+
# https://api.flexiscale.com/current/doc/list_firewall_templates.html
|
801
|
+
def list_firewall_templates(*list)
|
802
|
+
perform_request do
|
803
|
+
@api.listFirewallTemplates(list.flatten)
|
804
|
+
end
|
805
|
+
end
|
806
|
+
|
807
|
+
# List firewall template rules.
|
808
|
+
# - direction: nil || :in || :out
|
809
|
+
#
|
810
|
+
# https://api.flexiscale.com/current/doc/list_firewall_template_rules.html
|
811
|
+
def list_firewall_template_rules(firewall_template_id, direction=nil)
|
812
|
+
perform_request do
|
813
|
+
@api.listFirewallTemplateRules(firewall_template_id, direction && direction.to_s.upcase)
|
814
|
+
end
|
815
|
+
end
|
816
|
+
|
817
|
+
end
|
818
|
+
|
819
|
+
end
|