upcloud_api 1.3.0 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1b145630b5a65cce82856ed253d85e59a598814a
4
- data.tar.gz: c125d9477ddb35c16744cc2dbf87ea8c3efc61c5
3
+ metadata.gz: 6837056b4cff07402d608702a95d56d6be14ec38
4
+ data.tar.gz: 82526825eb93b43aef2160e3fc1ebcb5a689114d
5
5
  SHA512:
6
- metadata.gz: 4a09082fd8700233b8b14479d86c210b76b075549ddb955fb6f57f4efdb2af95530935607644dd990dc6e7663bea74986a78892fdd1bc8bbe4466ec837752ca9
7
- data.tar.gz: dbe49e4b6dc737786fb35217cb894e72375d3c17f7a1f9f5ecf9a63c4498771336d95b1755de68a672a465057930ff084eb50254e4bc5283e670af9ce7c67b74
6
+ metadata.gz: 3ff71fa95959d11049d3d55398fd17f8b84baf43600c6bf38990ae9ccf58ba5521b3b82d405a1691085257854caa0d90755421d2ec0a4d5734b72a06eb879819
7
+ data.tar.gz: 7a158330aff7be804d5a9f386bf6b0baff416ef6b176eb4e3521d0de512384b9381051fb77338f0f35c083f1259adb4a052921a5c734e138157dfa0fd597d970
@@ -1,3 +1,3 @@
1
1
  class UpcloudApi
2
- VERSION = "1.3.0"
2
+ VERSION = "1.5.0".freeze
3
3
  end
data/lib/upcloud_api.rb CHANGED
@@ -1,442 +1,534 @@
1
-
2
1
  require "timeout"
3
2
 
4
3
  require "httparty"
5
4
 
5
+ # Class to serve as a Ruby API for the UpCloud HTTP API
6
6
  class UpcloudApi
7
-
8
- # @param user [String] Upcloud API account
9
- # @param password [String] Upcloud API password
10
- def initialize user, password
11
- @user = user
12
- @password = password
13
- @auth = { username: @user, password: @password }
14
- end
15
-
16
- # Tests that authentication to Upcloud works.
17
- #
18
- # This is not required to use, as authentication is used
19
- # with HTTP basic auth with each request.
20
- #
21
- # Calls GET /1.2/server
22
- #
23
- # Returns true in success, false if not
24
- def login
25
- response = get "server"
26
- response.code == 200
27
- end
28
-
29
- # Returns available credits.
30
- #
31
- # Calls GET /1.2/acccount
32
- def account_information
33
- response = get "account"
34
- data = JSON.parse response.body
35
- data["acccount"]["credits"]
36
- end
37
-
38
- # Lists servers associated with the account
39
- #
40
- # Calls GET /1.2/server
41
- #
42
- # Returns array of servers with values
43
- # - zone
44
- # - core_number
45
- # - title
46
- # - hostname
47
- # - memory_amount
48
- # - uuid
49
- # - state
50
- def servers
51
- response = get "server"
52
- data = JSON.parse response.body
53
- data["servers"]["server"]
54
- end
55
-
56
- # Shows details of a server.
57
- #
58
- # Calls GET /1.2/server/#{uuid}
59
- #
60
- # @param uuid from UpcloudApi#servers
61
- def server_details uuid
62
- response = get "server/#{uuid}"
63
- data = JSON.parse response.body
64
- data
65
- end
66
-
67
- # Lists templates available from Upcloud
68
- #
69
- # Calls GET /1.2/storage/template
70
- def templates
71
- response = get "storage/template"
72
- data = JSON.parse response.body
73
- data
74
- end
75
-
76
- # Creates new server from template.
77
- #
78
- # Calls POST /1.2/server
79
- #
80
- # Storage devices should be array of hashes containing following data:
81
- #
82
- # {
83
- # "action" => "clone" # Can be "create", "clone" or "attach"
84
- # "storage" => template_uuid, # Should be passed only for "clone" or "attach"
85
- # "title" => disk_name # Name of the storage,
86
- # "tier" => "maxiops" # No sense using HDD any more
87
- # }
88
- #
89
- # Returns HTTParty response
90
- def create_server zone: "fi-hel1", title:, hostname:, core_number: 1, memory_amount: 1024, storage_devices:
91
- data = {
92
- "server" => {
93
- "zone" => zone,
94
- "title" => title,
95
- "hostname" => hostname,
96
- "core_number" => core_number,
97
- "memory_amount" => memory_amount,
98
- "storage_devices" => { "storage_device" => storage_devices }
99
- }
100
- }
101
-
102
- json = JSON.generate data
103
- response = post "server", json
104
-
105
- response
106
- end
107
-
108
- # Modifies existing server.
109
- #
110
- # In order to modify a server, the server must be stopped first.
111
- #
112
- # Calls PUT /1.2/server/#{uuid}
113
- #
114
- # @param server_uuid [String] UUID of the server that will be modified.
115
- # @param params [Hash] Hash of params that will be passed to be changed.
116
- def modify_server server_uuid, params
117
- data = { "server" => params }
118
- json = JSON.generate data
119
- response = put "server/#{server_uuid}", json
120
-
121
- response
122
- end
123
-
124
- # Deletes a server.
125
- #
126
- # In order to delete a server, the server must be stopped first.
127
- #
128
- # Calls DELETE /1.2/server/#{uuid}
129
- def delete_server server_uuid
130
- response = delete "server/#{server_uuid}"
131
-
132
- response
133
- end
134
-
135
- # Starts server that is shut down.
136
- #
137
- # Calls POST /1.2/server/#{uuid}/start
138
- #
139
- # @param server_uuid UUID of the server
140
- def start_server server_uuid
141
- response = post "server/#{server_uuid}/start"
142
-
143
- response
144
- end
145
-
146
- # Shuts down a server that is currently running
147
- #
148
- # Calls POST /1.2/server/#{uuid}/stop
149
- #
150
- # Hard shutdown means practically same as taking the power cable off from the computer.
151
- # Soft shutdown sends ACPI signal to the server, which should then automatically handle shutdown routines by itself.
152
- # If timeout is given, server will be forcibly shut down after the timeout has expired.
153
- #
154
- # @param server_uuid UUID of the server
155
- # @param type Type of the shutdown. Available types are :hard and :soft. Defaults to :soft.
156
- # @param timeout Time after server will be hard stopped if it didn’t close cleanly. Only affects :soft type.
157
- # @param asynchronous If false, this call will wait until the server has really stopped.
158
- #
159
- # Raises Timeout::Error in case server does not shut down in 300 seconds in non-asynchronous mode.
160
- def stop_server server_uuid, type: :soft, timeout: nil, asynchronous: false
161
- data = {
162
- "stop_server" => {
163
- "stop_type" => type.to_s
164
- }
165
- }
166
- data["stop_server"]["timeout"] = timeout unless timeout.nil?
167
-
168
- json = JSON.generate data
169
-
170
- response = post "server/#{server_uuid}/stop", json
171
-
172
- return response if asynchronous
173
-
174
- Timeout::timeout 300 do
175
- loop do
176
- details = server_details server_uuid
177
- return response if details["server"]["state"] == "stopped"
178
- end
179
- end
180
- end
181
-
182
- # Restarts down a server that is currently running
183
- #
184
- # Calls POST /1.2/server/#{uuid}/restart
185
- #
186
- # Hard shutdown means practically same as taking the power cable off from the computer.
187
- # Soft shutdown sends ACPI signal to the server, which should then automatically handle shutdown routines by itself.
188
- # If timeout is given, server will be forcibly shut down after the timeout has expired.
189
- #
190
- # @param server_uuid UUID of the server
191
- # @param type Type of the shutdown. Available types are :hard and :soft. Defaults to :soft.
192
- # @param timeout Time after server will be hard stopped if it didn’t close cleanly. Only affects :soft type.
193
- # @param timeout_action What will happen when timeout happens. :destroy hard stops the server and :ignore makes
194
- # server if timeout happens. Default is :ignore.
195
- def restart_server server_uuid, type: :soft, timeout: nil, timeout_action: :ignore
196
- data = {
197
- "stop_server" => {
198
- "stop_type" => type.to_s
199
- }
200
- }
201
- data["stop_server"]["timeout"] = timeout unless timeout.nil?
202
-
203
- json = JSON.generate data
204
-
205
- response = post "server/#{server_uuid}/restart", json
206
-
207
- response
208
- end
209
-
210
- # Lists all storages or storages matching to given type.
211
- #
212
- # Calls GET /1.2/storage or /1.2/storage/#{type}
213
- #
214
- # Available types:
215
- # - public
216
- # - private
217
- # - normal
218
- # - backup
219
- # - cdrom
220
- # - template
221
- # - favorite
222
- #
223
- # @param type Type of the storages to be returned on nil
224
- def storages type: nil
225
- response = get(type && "storage/#{type}" || "storage")
226
- data = JSON.parse response.body
227
- data
228
- end
229
-
230
- # Shows detailed information of single storage.
231
- #
232
- # Calls GET /1.2/storage/#{uuid}
233
- #
234
- # @param storage_uuid UUID of the storage
235
- def storage_details storage_uuid
236
- response = get "storage/#{storage_uuid}"
237
- data = JSON.parse response.body
238
- data
239
- end
240
-
241
- # Creates new storage.
242
- #
243
- # Calls POST /1.2/storage
244
- #
245
- # backup_rule should be hash with following attributes:
246
- # - interval # allowed values: daily / mon / tue / wed / thu / fri / sat / sun
247
- # - time # allowed values: 0000-2359
248
- # - retention # How many days backup will be kept. Allowed values: 1-1095
249
- #
250
- # @param size Size of the storage in gigabytes
251
- # @param tier Type of the disk. maxiops is SSD powered disk, other allowed value is "hdd"
252
- # @param title Name of the disk
253
- # @param zone Where the disk will reside. Needs to be within same zone with the server
254
- # @param backup_rule Hash of backup information. If not given, no backups will be automatically created.
255
- def create_storage size:, tier: "maxiops", title:, zone: "fi-hel1", backup_rule: nil
256
- data = {
257
- "storage" => {
258
- "size" => size,
259
- "tier" => tier,
260
- "title" => title,
261
- "zone" => zone,
262
- "backup_rule" => backup_rule
263
- }
264
- }
265
-
266
- json = JSON.generate data
267
-
268
- response = post "storage", json
269
-
270
- response
271
- end
272
-
273
- # Modifies existing storage.
274
- #
275
- # Calls PUT /1.2/storage/#{uuid}
276
- #
277
- # backup_rule should be hash with following attributes:
278
- # - interval # allowed values: daily / mon / tue / wed / thu / fri / sat / sun
279
- # - time # allowed values: 0000-2359
280
- # - retention # How many days backup will be kept. Allowed values: 1-1095
281
- #
282
- # @param storage_uuid UUID of the storage that will be modified
283
- # @param size Size of the storage in gigabytes
284
- # @param title Name of the disk
285
- # @param backup_rule Hash of backup information. If not given, no backups will be automatically created.
286
- def modify_storage storage_uuid, size:, title:, backup_rule: nil
287
- data = {
288
- "storage" => {
289
- "size" => size,
290
- "title" => title,
291
- "backup_rule" => backup_rule
292
- }
293
- }
294
-
295
- json = JSON.generate data
296
-
297
- response = put "storage/#{storage_uuid}", json
298
-
299
- response
300
- end
301
-
302
- # Clones existing storage.
303
- #
304
- # This operation is asynchronous.
305
- #
306
- # Calls POST /1.2/storage/#{uuid}/clone
307
- #
308
- # backup_rule should be hash with following attributes:
309
- # - interval # allowed values: daily / mon / tue / wed / thu / fri / sat / sun
310
- # - time # allowed values: 0000-2359
311
- # - retention # How many days backup will be kept. Allowed values: 1-1095
312
- #
313
- # @param storage_uuid UUID of the storage that will be modified
314
- # @param tier Type of the disk. maxiops is SSD powered disk, other allowed value is "hdd"
315
- # @param title Name of the disk
316
- # @param zone Where the disk will reside. Needs to be within same zone with the server
317
- def clone_storage storage_uuid, zone: "fi-hel1", title:, tier: "maxiops"
318
- data = {
319
- "storage" => {
320
- "zone" => zone,
321
- "title" => title,
322
- "tier" => tier
323
- }
324
- }
325
-
326
- json = JSON.generate data
327
-
328
- response = post "storage/#{storage_uuid}/clone", json
329
-
330
- response
331
- end
332
-
333
- # Attaches a storage to a server. Server must be stopped before the storage can be attached.
334
- #
335
- # Calls POST /1.2/server/#{server_uuid}/storage/attach
336
- #
337
- # Valid values for address are: ide[01]:[01] / scsi:0:[0-7] / virtio:[0-7]
338
- #
339
- # @param type Type of the disk. Valid values are "disk" and "cdrom".
340
- # @param address Address where the disk will be attached to. Defaults to next available address.
341
- # @param server_uuid UUID of the server where the disk will be attached to.
342
- # @param storage_uuid UUID of the storage that will be attached.
343
- def attach_storage type: "disk", address: nil, server_uuid:, storage_uuid:
344
- data = {
345
- "storage_device" => {
346
- "type" => type,
347
- "address" => address,
348
- "storage" => storage_uuid
349
- }
350
- }
351
-
352
- json = JSON.generate data
353
-
354
- response = post "server/#{server_uuid}/storage/attach", json
355
-
356
- response
357
- end
358
-
359
- # Detaches storage from a server. Server must be stopped before the storage can be detached.
360
- #
361
- # Calls POST /1.2/server/#{server_uuid}/storage/detach
362
- #
363
- # @param address Address where the storage that will be detached resides.
364
- def detach_storage address
365
- data = {
366
- "storage_device" => {
367
- "address" => address
368
- }
369
- }
370
-
371
- json = JSON.generate data
372
-
373
- response = post "server/#{server_uuid}/storage/detach", json
374
-
375
- response
376
- end
377
-
378
- # Creates backup from a storage.
379
- #
380
- # This operation is asynchronous.
381
- #
382
- # Calls /1.2/storage/#{uuid}/backup
383
- #
384
- # @param storage_uuid UUID of the storage to be cloned
385
- # @param title Name of the backup
386
- def create_backup storage_uuid, title:
387
- data = {
388
- "storage" => {
389
- "title" => title
390
- }
391
- }
392
-
393
- json = JSON.generate data
394
-
395
- response = post "storage/#{storage_uuid}/backup", json
396
-
397
- response
398
- end
399
-
400
- # Restores a backup.
401
- #
402
- # If the storage is attached to server, the server must first be stopped.
403
- #
404
- # Calls /1.2/storage/#{uuid}/restore.
405
- #
406
- # @param storage_uuid TODO: is this supposed to be UUID of the storage or the backup?
407
- def create_backup storage_uuid
408
- response = post "storage/#{storage_uuid}/restore"
409
-
410
- response
411
- end
412
-
413
- # Deletes a storage.
414
- #
415
- # The storage must be in "online" state and it must not be attached to any server.
416
- # Backups will not be deleted.
417
- #
418
- # @param storage_uuid UUID of the storage that will be deleted.
419
- def delete_storage storage_uuid
420
- response = delete "storage/#{storage_uuid}"
421
-
422
- response
423
- end
424
-
425
- private
426
-
427
- def get action
428
- HTTParty.get "https://api.upcloud.com/1.2/#{action}", basic_auth: @auth
429
- end
430
-
431
- def post action, body = ""
432
- HTTParty.post "https://api.upcloud.com/1.2/#{action}", basic_auth: @auth, body: body, headers: { "Content-Type" => "application/json" }
433
- end
434
-
435
- def put action, body = ""
436
- HTTParty.put "https://api.upcloud.com/1.2/#{action}", basic_auth: @auth, body: body, headers: { "Content-Type" => "application/json" }
7
+ # @param user [String] Upcloud API account
8
+ # @param password [String] Upcloud API password
9
+ def initialize(user, password)
10
+ @user = user
11
+ @password = password
12
+ @auth = { username: @user, password: @password }
13
+ end
14
+
15
+ # Tests that authentication to Upcloud works.
16
+ #
17
+ # This is not required to use, as authentication is used
18
+ # with HTTP basic auth with each request.
19
+ #
20
+ # Calls GET /1.2/server
21
+ #
22
+ # Returns true in success, false if not
23
+ def login
24
+ response = get "server"
25
+ response.code == 200
26
+ end
27
+
28
+ # Returns available server configurations.
29
+ #
30
+ # Calls GET /1.2/server_size
31
+ def server_configurations
32
+ response = get "server_size"
33
+ response["server_sizes"]["server_size"]
34
+ end
35
+
36
+ # Returns available credits.
37
+ #
38
+ # Calls GET /1.2/acccount
39
+ def account_information
40
+ response = get "account"
41
+ data = JSON.parse response.body
42
+ data["account"]["credits"]
43
+ end
44
+
45
+ # Lists servers associated with the account
46
+ #
47
+ # Calls GET /1.2/server
48
+ #
49
+ # Returns array of servers with values
50
+ # - zone
51
+ # - core_number
52
+ # - title
53
+ # - hostname
54
+ # - memory_amount
55
+ # - uuid
56
+ # - state
57
+ def servers
58
+ response = get "server"
59
+ data = JSON.parse response.body
60
+ data["servers"]["server"]
61
+ end
62
+
63
+ # Shows details of a server.
64
+ #
65
+ # Calls GET /1.2/server/#{uuid}
66
+ #
67
+ # @param uuid from UpcloudApi#servers
68
+ def server_details(uuid)
69
+ response = get "server/#{uuid}"
70
+ data = JSON.parse response.body
71
+ data
72
+ end
73
+
74
+ # Lists templates available from Upcloud
75
+ #
76
+ # Calls GET /1.2/storage/template
77
+ def templates
78
+ response = get "storage/template"
79
+ data = JSON.parse response.body
80
+ data
81
+ end
82
+
83
+ # Creates new server from template.
84
+ #
85
+ # Calls POST /1.2/server
86
+ #
87
+ # Storage devices should be array of hashes containing following data:
88
+ #
89
+ # {
90
+ # "action" => "clone" # Can be "create", "clone" or "attach"
91
+ # "storage" => template_uuid, # Should be passed only for "clone" or "attach"
92
+ # "title" => disk_name # Name of the storage,
93
+ # "tier" => "maxiops" # No sense using HDD any more
94
+ # }
95
+ #
96
+ # ip_addresses should be an array containing :public, :private and/or :ipv6. It defaults to
97
+ # :all, which means the server will get public IPv4, private IPv4 and public IPv6 addresses.
98
+ #
99
+ # Returns HTTParty response
100
+ def create_server(zone: "fi-hel1", title:, hostname:, core_number: 1,
101
+ memory_amount: 1024, storage_devices:, ip_addresses: :all)
102
+ data = {
103
+ "server" => {
104
+ "zone" => zone,
105
+ "title" => title,
106
+ "hostname" => hostname,
107
+ "core_number" => core_number,
108
+ "memory_amount" => memory_amount,
109
+ "storage_devices" => { "storage_device" => storage_devices }
110
+ }
111
+ }
112
+
113
+ if ip_addresses != :all
114
+ ips = []
115
+ ips << { "access" => "public", "family" => "IPv4" } if ip_addresses.include? :public
116
+ ips << { "access" => "private", "family" => "IPv4" } if ip_addresses.include? :private
117
+ ips << { "access" => "public", "family" => "IPv6" } if ip_addresses.include? :ipv6
118
+
119
+ data["server"]["ip_addresses"] = {}
120
+ data["server"]["ip_addresses"]["ip_address"] = ips
437
121
  end
438
122
 
439
- def delete action, body = ""
440
- HTTParty.delete "https://api.upcloud.com/1.2/#{action}", basic_auth: @auth, headers: { "Content-Type" => "application/json" }
123
+ json = JSON.generate data
124
+ response = post "server", json
125
+ response
126
+ end
127
+
128
+ # Modifies existing server.
129
+ #
130
+ # In order to modify a server, the server must be stopped first.
131
+ #
132
+ # Calls PUT /1.2/server/#{uuid}
133
+ #
134
+ # @param server_uuid [String] UUID of the server that will be modified.
135
+ # @param params [Hash] Hash of params that will be passed to be changed.
136
+ def modify_server(server_uuid, params)
137
+ data = { "server" => params }
138
+ json = JSON.generate data
139
+ response = put "server/#{server_uuid}", json
140
+
141
+ response
142
+ end
143
+
144
+ # Deletes a server.
145
+ #
146
+ # In order to delete a server, the server must be stopped first.
147
+ #
148
+ # Calls DELETE /1.2/server/#{uuid}
149
+ def delete_server(server_uuid)
150
+ response = delete "server/#{server_uuid}"
151
+
152
+ response
153
+ end
154
+
155
+ # Starts server that is shut down.
156
+ #
157
+ # Calls POST /1.2/server/#{uuid}/start
158
+ #
159
+ # @param server_uuid UUID of the server
160
+ def start_server(server_uuid)
161
+ response = post "server/#{server_uuid}/start"
162
+
163
+ response
164
+ end
165
+
166
+ # Shuts down a server that is currently running
167
+ #
168
+ # Calls POST /1.2/server/#{uuid}/stop
169
+ #
170
+ # Hard shutdown means practically same as taking the power cable
171
+ # off from the computer. Soft shutdown sends ACPI signal to the server,
172
+ # which should then automatically handle shutdown routines by itself.
173
+ # If timeout is given, server will be forcibly shut down after the
174
+ # timeout has expired.
175
+ #
176
+ # @param server_uuid UUID of the server
177
+ # @param type Type of the shutdown. Available types are :hard and :soft.
178
+ # Defaults to :soft.
179
+ # @param timeout Time after server will be hard stopped if it did not
180
+ # close cleanly. Only affects :soft type.
181
+ # @param asynchronous If false, this call will wait until the server
182
+ # has really stopped.
183
+ #
184
+ # Raises Timeout::Error in case server does not shut down in 300
185
+ # seconds in non-asynchronous mode.
186
+ def stop_server(server_uuid, type: :soft, timeout: nil, asynchronous: false)
187
+ data = {
188
+ "stop_server" => {
189
+ "stop_type" => type.to_s
190
+ }
191
+ }
192
+ data["stop_server"]["timeout"] = timeout unless timeout.nil?
193
+
194
+ json = JSON.generate data
195
+
196
+ response = post "server/#{server_uuid}/stop", json
197
+
198
+ return response if asynchronous
199
+
200
+ Timeout.timeout 300 do
201
+ loop do
202
+ details = server_details server_uuid
203
+ return response if details["server"].nil?
204
+ return response if details["server"]["state"] == "stopped"
205
+ end
441
206
  end
207
+ end
208
+
209
+ # Restarts a server that is currently running
210
+ #
211
+ # Calls POST /1.2/server/#{uuid}/restart
212
+ #
213
+ # Hard shutdown means practically same as taking the power cable
214
+ # off from the computer. Soft shutdown sends ACPI signal to the server,
215
+ # which should then automatically handle shutdown routines by itself.
216
+ # If timeout is given, server will be forcibly shut down after the
217
+ # timeout has expired.
218
+ #
219
+ # @param server_uuid UUID of the server
220
+ # @param type Type of the shutdown. Available types are :hard and :soft.
221
+ # Defaults to :soft.
222
+ # @param timeout Time after server will be hard stopped if it did not
223
+ # close cleanly. Only affects :soft type.
224
+ # @param timeout_action What will happen when timeout happens.
225
+ # :destroy hard stops the server and :ignore stops the operation
226
+ # if timeout happens. Default is :ignore.
227
+ def restart_server(server_uuid, type: :soft, timeout: nil,
228
+ timeout_action: :ignore)
229
+ data = {
230
+ "restart_server" => {
231
+ "stop_type" => type.to_s,
232
+ "timeout_action" => timeout_action
233
+ }
234
+ }
235
+ data["restart_server"]["timeout"] = timeout unless timeout.nil?
236
+
237
+ json = JSON.generate data
238
+
239
+ response = post "server/#{server_uuid}/restart", json
240
+
241
+ response
242
+ end
243
+
244
+ # Lists all storages or storages matching to given type.
245
+ #
246
+ # Calls GET /1.2/storage or /1.2/storage/#{type}
247
+ #
248
+ # Available types:
249
+ # - public
250
+ # - private
251
+ # - normal
252
+ # - backup
253
+ # - cdrom
254
+ # - template
255
+ # - favorite
256
+ #
257
+ # @param type Type of the storages to be returned on nil
258
+ def storages(type: nil)
259
+ response = get(type && "storage/#{type}" || "storage")
260
+ data = JSON.parse response.body
261
+ data
262
+ end
263
+
264
+ # Shows detailed information of single storage.
265
+ #
266
+ # Calls GET /1.2/storage/#{uuid}
267
+ #
268
+ # @param storage_uuid UUID of the storage
269
+ def storage_details(storage_uuid)
270
+ response = get "storage/#{storage_uuid}"
271
+ data = JSON.parse response.body
272
+ data
273
+ end
274
+
275
+ # Creates new storage.
276
+ #
277
+ # Calls POST /1.2/storage
278
+ #
279
+ # backup_rule should be hash with following attributes:
280
+ # - interval # allowed values: daily / mon / tue / wed / thu / fri / sat / sun
281
+ # - time # allowed values: 0000-2359
282
+ # - retention # How many days backup will be kept. Allowed values: 1-1095
283
+ #
284
+ # @param size Size of the storage in gigabytes
285
+ # @param tier Type of the disk. maxiops is SSD powered disk, other
286
+ # allowed value is "hdd"
287
+ # @param title Name of the disk
288
+ # @param zone Where the disk will reside. Needs to be within same zone
289
+ # with the server
290
+ # @param backup_rule Hash of backup information. If not given, no
291
+ # backups will be automatically created.
292
+ def create_storage(size:, tier: "maxiops", title:, zone: "fi-hel1",
293
+ backup_rule: nil)
294
+ data = {
295
+ "storage" => {
296
+ "size" => size,
297
+ "tier" => tier,
298
+ "title" => title,
299
+ "zone" => zone
300
+ }
301
+ }
302
+ data["storage"]["backup_rule"] = backup_rule unless backup_rule.nil?
303
+
304
+ json = JSON.generate data
305
+ response = post "storage", json
306
+
307
+ response
308
+ end
309
+
310
+ # Modifies existing storage.
311
+ #
312
+ # Calls PUT /1.2/storage/#{uuid}
313
+ #
314
+ # backup_rule should be hash with following attributes:
315
+ # - interval # allowed values: daily / mon / tue / wed / thu / fri / sat / sun
316
+ # - time # allowed values: 0000-2359
317
+ # - retention # How many days backup will be kept. Allowed values: 1-1095
318
+ #
319
+ # @param storage_uuid UUID of the storage that will be modified
320
+ # @param size Size of the storage in gigabytes
321
+ # @param title Name of the disk
322
+ # @param backup_rule Hash of backup information. If not given, no
323
+ # backups will be automatically created.
324
+ def modify_storage(storage_uuid, size:, title:, backup_rule: nil)
325
+ data = {
326
+ "storage" => {
327
+ "size" => size,
328
+ "title" => title
329
+ }
330
+ }
331
+ data["storage"]["backup_rule"] = backup_rule unless backup_rule.nil?
332
+
333
+ json = JSON.generate data
334
+
335
+ response = put "storage/#{storage_uuid}", json
336
+
337
+ response
338
+ end
339
+
340
+ # Clones existing storage.
341
+ #
342
+ # This operation is asynchronous.
343
+ #
344
+ # Calls POST /1.2/storage/#{uuid}/clone
345
+ #
346
+ # @param storage_uuid UUID of the storage that will be modified
347
+ # @param tier Type of the disk. maxiops is SSD powered disk, other
348
+ # allowed value is "hdd"
349
+ # @param title Name of the disk
350
+ # @param zone Where the disk will reside. Needs to be within same zone
351
+ # with the server
352
+ def clone_storage(storage_uuid, zone: "fi-hel1", title:, tier: "maxiops")
353
+ data = {
354
+ "storage" => {
355
+ "zone" => zone,
356
+ "title" => title,
357
+ "tier" => tier
358
+ }
359
+ }
360
+
361
+ json = JSON.generate data
362
+
363
+ response = post "storage/#{storage_uuid}/clone", json
364
+
365
+ response
366
+ end
367
+
368
+ # Templatizes existing storage.
369
+ #
370
+ # This operation is asynchronous.
371
+ #
372
+ # Calls POST /1.2/storage/#{uuid}/templatize
373
+ #
374
+ # @param storage_uuid UUID of the storage that will be templatized
375
+ # @param title Name of the template storage
376
+ def templatize_storage(storage_uuid, title:)
377
+ data = {
378
+ "storage" => {
379
+ "title" => title
380
+ }
381
+ }
382
+
383
+ json = JSON.generate data
384
+
385
+ response = post "storage/#{storage_uuid}/templatize", json
386
+
387
+ response
388
+ end
389
+
390
+ # Attaches a storage to a server. Server must be stopped before the
391
+ # storage can be attached.
392
+ #
393
+ # Calls POST /1.2/server/#{server_uuid}/storage/attach
394
+ #
395
+ # Valid values for address are: ide[01]:[01] / scsi:0:[0-7] / virtio:[0-7]
396
+ #
397
+ # @param server_uuid UUID of the server where the disk will be attached to.
398
+ # @param storage_uuid UUID of the storage that will be attached.
399
+ # @param type Type of the disk. Valid values are "disk" and "cdrom".
400
+ # @param address Address where the disk will be attached to. Defaults
401
+ # to next available address.
402
+ def attach_storage(server_uuid, storage_uuid:, type: "disk", address: nil)
403
+ data = {
404
+ "storage_device" => {
405
+ "type" => type,
406
+ "storage" => storage_uuid
407
+ }
408
+ }
409
+ data["storage_device"]["address"] = address unless address.nil?
410
+
411
+ json = JSON.generate data
412
+
413
+ response = post "server/#{server_uuid}/storage/attach", json
414
+
415
+ response
416
+ end
417
+
418
+ # Detaches storage from a server. Server must be stopped before the
419
+ # storage can be detached.
420
+ #
421
+ # Calls POST /1.2/server/#{server_uuid}/storage/detach
422
+ #
423
+ # @param server_uuid UUID of the server from which to detach the storage.
424
+ # @param address Address where the storage that will be detached resides.
425
+ def detach_storage(server_uuid, address:)
426
+ data = {
427
+ "storage_device" => {
428
+ "address" => address
429
+ }
430
+ }
431
+
432
+ json = JSON.generate data
433
+
434
+ response = post "server/#{server_uuid}/storage/detach", json
435
+
436
+ response
437
+ end
438
+
439
+ # Creates backup from a storage.
440
+ #
441
+ # This operation is asynchronous.
442
+ #
443
+ # Calls /1.2/storage/#{uuid}/backup
444
+ #
445
+ # @param storage_uuid UUID of the storage to be backed-up
446
+ # @param title Name of the backup
447
+ def create_backup(storage_uuid, title:)
448
+ data = {
449
+ "storage" => {
450
+ "title" => title
451
+ }
452
+ }
453
+
454
+ json = JSON.generate data
455
+
456
+ response = post "storage/#{storage_uuid}/backup", json
457
+
458
+ response
459
+ end
460
+
461
+ # Restores a backup.
462
+ #
463
+ # If the storage is attached to server, the server must first be stopped.
464
+ #
465
+ # Calls /1.2/storage/#{backup_uuid}/restore.
466
+ #
467
+ # @param backup_uuid UUID of the backup
468
+ def restore_backup(backup_uuid)
469
+ response = post "storage/#{backup_uuid}/restore"
470
+
471
+ response
472
+ end
473
+
474
+ # Adds storage to favorites
475
+ #
476
+ # Calls POST /1.2/storage/#{storage_uuid}/favorite.
477
+ #
478
+ # @param storage_uuid UUID of the storage to be included in favorites
479
+ def favorite_storage(storage_uuid)
480
+ response = post "storage/#{storage_uuid}/favorite"
481
+
482
+ response
483
+ end
484
+
485
+ # Removes storage to favorites
486
+ #
487
+ # Calls POST /1.2/storage/#{storage_uuid}/favorite.
488
+ #
489
+ # @param storage_uuid UUID of the storage to be removed from favorites
490
+ def defavorite_storage(storage_uuid)
491
+ response = delete "storage/#{storage_uuid}/favorite"
492
+
493
+ response
494
+ end
495
+
496
+ # Deletes a storage.
497
+ #
498
+ # The storage must be in "online" state and it must not be attached to
499
+ # any server.
500
+ # Backups will not be deleted.
501
+ #
502
+ # @param storage_uuid UUID of the storage that will be deleted.
503
+ def delete_storage(storage_uuid)
504
+ response = delete "storage/#{storage_uuid}"
505
+
506
+ response
507
+ end
508
+
509
+ private
510
+
511
+ def get(action)
512
+ HTTParty.get "https://api.upcloud.com/1.2/#{action}", basic_auth: @auth
513
+ end
514
+
515
+ def post(action, body = "")
516
+ HTTParty.post "https://api.upcloud.com/1.2/#{action}",
517
+ basic_auth: @auth,
518
+ body: body,
519
+ headers: { "Content-Type" => "application/json" }
520
+ end
521
+
522
+ def put(action, body = "")
523
+ HTTParty.put "https://api.upcloud.com/1.2/#{action}",
524
+ basic_auth: @auth,
525
+ body: body,
526
+ headers: { "Content-Type" => "application/json" }
527
+ end
528
+
529
+ def delete(action)
530
+ HTTParty.delete "https://api.upcloud.com/1.2/#{action}",
531
+ basic_auth: @auth,
532
+ headers: { "Content-Type" => "application/json" }
533
+ end
442
534
  end
metadata CHANGED
@@ -1,14 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: upcloud_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samu Voutilainen
8
+ - Mika Katara
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2015-05-13 00:00:00.000000000 Z
12
+ date: 2016-04-22 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: httparty
@@ -53,7 +54,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
53
54
  version: '0'
54
55
  requirements: []
55
56
  rubyforge_project:
56
- rubygems_version: 2.4.6
57
+ rubygems_version: 2.4.8
57
58
  signing_key:
58
59
  specification_version: 4
59
60
  summary: Implementation of Upcloud API for VPS management