ganeti_client 0.0.6 → 0.0.7
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/README +0 -3
- data/lib/ganeti_client/client.rb +351 -223
- metadata +4 -4
data/README
CHANGED
data/lib/ganeti_client/client.rb
CHANGED
@@ -34,13 +34,14 @@ module Ganeti
|
|
34
34
|
|
35
35
|
attr_accessor :host, :username, :password, :version, :show_response
|
36
36
|
|
37
|
-
#
|
37
|
+
# Description:
|
38
|
+
# Create the client object
|
38
39
|
#
|
39
40
|
# Parameters:
|
40
|
-
# host: hostname and port
|
41
|
-
# username: username that has access to RAPI
|
42
|
-
# password: password of the user provided
|
43
|
-
# show_response: show response data (optional)
|
41
|
+
# string host: hostname and port
|
42
|
+
# string username: username that has access to RAPI
|
43
|
+
# string password: password of the user provided
|
44
|
+
# boolean show_response: show response data (optional)
|
44
45
|
def initialize(host, username, password, show_response = false)
|
45
46
|
self.host = host
|
46
47
|
self.username = username
|
@@ -52,7 +53,8 @@ module Ganeti
|
|
52
53
|
end
|
53
54
|
|
54
55
|
|
55
|
-
#
|
56
|
+
# Description:
|
57
|
+
# Get the cluster information
|
56
58
|
#
|
57
59
|
# Return:
|
58
60
|
# GanetiInfo object
|
@@ -65,10 +67,11 @@ module Ganeti
|
|
65
67
|
return GanetiInfo.new(response_body)
|
66
68
|
end
|
67
69
|
|
68
|
-
#
|
70
|
+
# Description:
|
71
|
+
# Redistrite configuration to all nodes
|
69
72
|
#
|
70
73
|
# Return:
|
71
|
-
# job id
|
74
|
+
# string job id
|
72
75
|
def redistribute_config
|
73
76
|
url = get_url("redistribute-config")
|
74
77
|
response_body = send_request("PUT", url)
|
@@ -76,13 +79,14 @@ module Ganeti
|
|
76
79
|
return response_body
|
77
80
|
end
|
78
81
|
|
79
|
-
#
|
82
|
+
# Description:
|
83
|
+
# Get all instances on the cluster
|
80
84
|
#
|
81
85
|
# Parameters:
|
82
|
-
# bulk
|
86
|
+
# boolean bulk (optional)
|
83
87
|
#
|
84
88
|
# Return:
|
85
|
-
#
|
89
|
+
# array of all available instances. The array items contain a GanetiInstance object
|
86
90
|
def instances_get(bulk = 0)
|
87
91
|
url = get_url("instances", {"bulk" => bulk})
|
88
92
|
response_body = send_request("GET", url)
|
@@ -95,16 +99,17 @@ module Ganeti
|
|
95
99
|
return list
|
96
100
|
end
|
97
101
|
|
98
|
-
#
|
99
|
-
#
|
100
|
-
#
|
102
|
+
# Description:
|
103
|
+
# Create an instance
|
104
|
+
# If the options bool dry-run argument is provided, the job will not be actually executed, only the pre-execution checks will be done.
|
105
|
+
# Query-ing the job result will return, in boty dry-run and normal case, the list of nodes selected for the instance
|
101
106
|
#
|
102
|
-
#
|
107
|
+
# Make sure the instance_name resolves!!
|
103
108
|
#
|
104
|
-
#
|
105
|
-
#
|
109
|
+
# Build parameters dict, optional parameters need to be
|
110
|
+
# excluded to not cause issues with rapi.
|
106
111
|
#
|
107
|
-
#
|
112
|
+
# Example:
|
108
113
|
# info = {
|
109
114
|
# 'hypervisor' => 'kvm' , 'disk_template' => 'plain',
|
110
115
|
# 'pnode' => 'node.netronix.be', 'instance_name' => 'vm1.netronix.be', 'os' => 'debootstrap+lucid',
|
@@ -114,11 +119,11 @@ module Ganeti
|
|
114
119
|
# }
|
115
120
|
#
|
116
121
|
# Parameters:
|
117
|
-
# info: hash of data needed for the instance creation
|
118
|
-
# dry_run
|
122
|
+
# hash info: hash of data needed for the instance creation (see above)
|
123
|
+
# boolean dry_run (optional)
|
119
124
|
#
|
120
125
|
# Return:
|
121
|
-
# job_id
|
126
|
+
# string job_id
|
122
127
|
def instance_create(info, dry_run = 0)
|
123
128
|
params = {
|
124
129
|
'hypervisor' => info['hypervisor'], 'disk_template' => info['disk_template'],
|
@@ -144,10 +149,11 @@ module Ganeti
|
|
144
149
|
return response_body
|
145
150
|
end
|
146
151
|
|
147
|
-
#
|
152
|
+
# Description:
|
153
|
+
# Get instance specific information, similar to the bulk output from the instance list
|
148
154
|
#
|
149
155
|
# Parameters:
|
150
|
-
# name: name of the instance
|
156
|
+
# string name: name of the instance
|
151
157
|
#
|
152
158
|
# Return
|
153
159
|
# GanetiInstance object
|
@@ -160,14 +166,15 @@ module Ganeti
|
|
160
166
|
return GanetiInstance.new(response_body)
|
161
167
|
end
|
162
168
|
|
163
|
-
#
|
169
|
+
# Description:
|
170
|
+
# Delete a specific instance
|
164
171
|
#
|
165
172
|
# Parameters:
|
166
|
-
# name: name of the instance
|
167
|
-
# dry_run
|
173
|
+
# string name: name of the instance
|
174
|
+
# boolean dry_run (optional)
|
168
175
|
#
|
169
176
|
# Return:
|
170
|
-
# job id
|
177
|
+
# string job id
|
171
178
|
def instance_delete(name, dry_run = 0)
|
172
179
|
url = get_url("instances/#{name}", {"dry-run" => dry_run})
|
173
180
|
response_body = send_request("DELETE", url)
|
@@ -175,14 +182,16 @@ module Ganeti
|
|
175
182
|
return response_body
|
176
183
|
end
|
177
184
|
|
178
|
-
#
|
185
|
+
# Description:
|
186
|
+
# Get detailed information about an instance. Static parameter can be set to return only static information
|
187
|
+
# from the configuration without querying the instance's nodes
|
179
188
|
#
|
180
189
|
# Parameters:
|
181
|
-
# name: name of the instance
|
182
|
-
# static
|
190
|
+
# string name: name of the instance
|
191
|
+
# boolean: static (optional)
|
183
192
|
#
|
184
193
|
# Return:
|
185
|
-
# job id
|
194
|
+
# string job id
|
186
195
|
def instance_get_info(name, static = 0)
|
187
196
|
url = get_url("instances/#{name}/info", {"static" => static})
|
188
197
|
response_body = send_request("GET", url)
|
@@ -190,24 +199,24 @@ module Ganeti
|
|
190
199
|
return response_body
|
191
200
|
end
|
192
201
|
|
193
|
-
#
|
194
|
-
#
|
202
|
+
# Description:
|
203
|
+
# Reboot a specific instance
|
204
|
+
# The URI takes optional type=soft|hard|full and ignore_secondaries=0|1 parameters
|
195
205
|
#
|
196
|
-
#
|
197
|
-
#
|
198
|
-
#
|
199
|
-
#
|
206
|
+
# type defines the reboot type.
|
207
|
+
# soft is just a normal reboot, without terminating the hypervisor.
|
208
|
+
# hard means full shutdown (including terminating the hypervisor process) and startup again
|
209
|
+
# full is like hard but also recreates the configuration from ground up as if you would have don a gnt-instance shutdown and gnt-instance start on it
|
200
210
|
#
|
201
|
-
# it supports the dry-run argument
|
202
211
|
#
|
203
212
|
# Parameters:
|
204
|
-
# name: name of the instance
|
205
|
-
# type: soft|hard|full (optional)
|
206
|
-
# ignore_secondaries
|
207
|
-
# dry_run
|
213
|
+
# string name: name of the instance
|
214
|
+
# string type: soft|hard|full (optional)
|
215
|
+
# boolean ignore_secondaries (optional)
|
216
|
+
# boolean dry_run (optional)
|
208
217
|
#
|
209
218
|
# Return:
|
210
|
-
# job id
|
219
|
+
# string job id
|
211
220
|
def instance_reboot(name, type = "soft", ignore_secondaries = 0, dry_run = 0)
|
212
221
|
url = get_url("instances/#{name}/reboot", {"type" => type, "ignore_secondaries" => ignore_secondaries, "dry_run" => 0})
|
213
222
|
response_body = send_request("POST", url)
|
@@ -216,14 +225,15 @@ module Ganeti
|
|
216
225
|
end
|
217
226
|
|
218
227
|
|
219
|
-
#
|
228
|
+
# Description:
|
229
|
+
# Shutdown an instance
|
220
230
|
#
|
221
231
|
# Parameters:
|
222
|
-
# name: name of the instance
|
223
|
-
# dry_run
|
232
|
+
# string name: name of the instance
|
233
|
+
# boolean dry_run (optional)
|
224
234
|
#
|
225
235
|
# Return:
|
226
|
-
# job id
|
236
|
+
# string job id
|
227
237
|
def instance_shutdown(name, dry_run = 0)
|
228
238
|
url = get_url("instances/#{name}/shutdown", {"dry-run" => dry_run})
|
229
239
|
response_body = send_request("PUT", url)
|
@@ -231,16 +241,17 @@ module Ganeti
|
|
231
241
|
return response_body
|
232
242
|
end
|
233
243
|
|
234
|
-
#
|
235
|
-
#
|
244
|
+
# Description:
|
245
|
+
# Startup an instance
|
246
|
+
# The URI takes an optional force=1|0 parameter to start the instance even if secondary disks are failing
|
236
247
|
#
|
237
248
|
# Parameters:
|
238
|
-
# name: name of the instance
|
239
|
-
# force
|
240
|
-
# dry_run
|
249
|
+
# string name: name of the instance
|
250
|
+
# boolean force (optional)
|
251
|
+
# boolean dry_run (optional)
|
241
252
|
#
|
242
253
|
# Return:
|
243
|
-
# job id
|
254
|
+
# string job id
|
244
255
|
def instance_startup(name, force = 0, dry_run=0)
|
245
256
|
url = get_url("instances/#{name}/startup", {"force" => force, "dry-run" => dry_run})
|
246
257
|
response_body = send_request("PUT", url)
|
@@ -248,15 +259,16 @@ module Ganeti
|
|
248
259
|
return response_body
|
249
260
|
end
|
250
261
|
|
251
|
-
#
|
262
|
+
# Description:
|
263
|
+
# Install the operating system again
|
252
264
|
#
|
253
265
|
# Parameters:
|
254
|
-
# name: name of the instance
|
255
|
-
# os_name: name of the os
|
256
|
-
# nostartup
|
266
|
+
# string name: name of the instance
|
267
|
+
# string os_name: name of the os
|
268
|
+
# boolean nostartup (optional)
|
257
269
|
#
|
258
270
|
# Return:
|
259
|
-
# job id
|
271
|
+
# string job id
|
260
272
|
def instance_reinstall(name, os_name, nostartup = 0)
|
261
273
|
url = get_url("instances/#{name}/reinstall", {"os" => os_name, "nostartup" => nostartup})
|
262
274
|
response_body = send_request("POST", url)
|
@@ -264,20 +276,21 @@ module Ganeti
|
|
264
276
|
return response_body
|
265
277
|
end
|
266
278
|
|
267
|
-
#
|
268
|
-
#
|
269
|
-
#
|
270
|
-
#
|
279
|
+
# Description:
|
280
|
+
# Replaces disks on an instance
|
281
|
+
# Takes the parameters mode (one of replace_on_primary, replace_on_secondary or replace_auto), disks (comma seperated list of disk indexes), remote_node and iallocator
|
282
|
+
# Either remote_node or iallocator needs to be defined when using mode=replace_new_secondary
|
283
|
+
# mode is a mandatory parameter. replace_auto tries to determine the broken disk(s) on its own and replacing it
|
271
284
|
#
|
272
285
|
# Parameters:
|
273
|
-
# name: name of the instance
|
274
|
-
# mode replace_on_primary|replace_on_secondary|replace_auto (optional)
|
275
|
-
# ialllocator:
|
276
|
-
# remote_node:
|
277
|
-
# disks: comma seperated list of disk indexes
|
286
|
+
# string name: name of the instance
|
287
|
+
# string mode replace_on_primary|replace_on_secondary|replace_auto (optional)
|
288
|
+
# string ialllocator:
|
289
|
+
# string remote_node:
|
290
|
+
# string disks: comma seperated list of disk indexes
|
278
291
|
#
|
279
292
|
# Return:
|
280
|
-
# job id
|
293
|
+
# string job id
|
281
294
|
def instance_replace_disks(name, mode = "replace_auto", iallocator = "", remote_node = "", disks = "")
|
282
295
|
url = get_url("instances/#{name}/replace-disks", {"mode" => mode, "iallocator" => iallocator, "remote_node" => remote_node, "disks" => disks})
|
283
296
|
response_body = send_request("POST", url)
|
@@ -285,15 +298,16 @@ module Ganeti
|
|
285
298
|
return response_body
|
286
299
|
end
|
287
300
|
|
288
|
-
#
|
289
|
-
#
|
301
|
+
# Description:
|
302
|
+
# Activate disks on an instance
|
303
|
+
# Takes the bool parameter ignore_size. When set ignore the recorded size (useful for forcing activation when recoreded size is wrong)
|
290
304
|
#
|
291
305
|
# Parameters:
|
292
|
-
# name: name of the instance
|
293
|
-
# ignore_size
|
306
|
+
# string name: name of the instance
|
307
|
+
# boolean ignore_size (optional)
|
294
308
|
#
|
295
309
|
# Return:
|
296
|
-
# job id
|
310
|
+
# string job id
|
297
311
|
def instance_activate_disks(name, ignore_size = 0)
|
298
312
|
url = get_url("instances/#{name}/activate-disks", {"ignore_size" => ignore_size})
|
299
313
|
response_body = send_request("PUT", url)
|
@@ -301,13 +315,14 @@ module Ganeti
|
|
301
315
|
return response_body
|
302
316
|
end
|
303
317
|
|
304
|
-
#
|
318
|
+
# Description:
|
319
|
+
# Deactivate disks on an instance
|
305
320
|
#
|
306
321
|
# Parameters:
|
307
|
-
# name: name of the instance
|
322
|
+
# string name: name of the instance
|
308
323
|
#
|
309
324
|
# Return:
|
310
|
-
# job id
|
325
|
+
# string job id
|
311
326
|
def instance_deactivate_disks(name)
|
312
327
|
url = get_url("instances/#{name}/deactivate-disks")
|
313
328
|
response_body = send_request("PUT", url)
|
@@ -315,13 +330,15 @@ module Ganeti
|
|
315
330
|
return response_body
|
316
331
|
end
|
317
332
|
|
318
|
-
#
|
333
|
+
# Description:
|
334
|
+
# Returns a list of tags
|
335
|
+
#
|
319
336
|
#
|
320
337
|
# Parameters:
|
321
|
-
# name: name of the instance
|
338
|
+
# string name: name of the instance
|
322
339
|
#
|
323
340
|
# Return:
|
324
|
-
#
|
341
|
+
# array of tags
|
325
342
|
def instance_get_tags(name)
|
326
343
|
url = get_url("instances/#{name}/tags")
|
327
344
|
response_body = send_request("GET", url)
|
@@ -329,15 +346,16 @@ module Ganeti
|
|
329
346
|
return response_body
|
330
347
|
end
|
331
348
|
|
332
|
-
#
|
349
|
+
# Description:
|
350
|
+
# Add a set of tags
|
333
351
|
#
|
334
352
|
# Parameters:
|
335
|
-
# name: name of the instance
|
336
|
-
# tags: Array of tags
|
337
|
-
# dry_run
|
353
|
+
# string name: name of the instance
|
354
|
+
# array tags: Array of tags, tags are strings
|
355
|
+
# boolean dry_run (optional)
|
338
356
|
#
|
339
357
|
# Return:
|
340
|
-
# job id
|
358
|
+
# string job id
|
341
359
|
def instance_create_tags(name, tags, dry_run = 0)
|
342
360
|
url = get_url("instances/#{name}/tags", {'dry-run' => dry_run, 'tag' => tags})
|
343
361
|
response_body = send_request("PUT", url)
|
@@ -345,15 +363,16 @@ module Ganeti
|
|
345
363
|
return response_body
|
346
364
|
end
|
347
365
|
|
348
|
-
#
|
366
|
+
# Description:
|
367
|
+
# Delete (a) tag(s) on an instance
|
349
368
|
#
|
350
369
|
# Parameters:
|
351
|
-
# name: name of the instance
|
352
|
-
# tags: Array of tags
|
353
|
-
# dry_run
|
370
|
+
# string name: name of the instance
|
371
|
+
# array tags: Array of tags, tags are strings
|
372
|
+
# boolean dry_run (optional)
|
354
373
|
#
|
355
374
|
# Return:
|
356
|
-
# job id
|
375
|
+
# string job id
|
357
376
|
def instance_delete_tags(name, tags, dry_run = 0)
|
358
377
|
url = get_url("instances/#{name}/tags", {'dry-run' => dry_run, 'tag' => tags})
|
359
378
|
response_body = send_request("DELETE", url)
|
@@ -361,10 +380,11 @@ module Ganeti
|
|
361
380
|
return response_body
|
362
381
|
end
|
363
382
|
|
364
|
-
#
|
383
|
+
# Description:
|
384
|
+
# Returns a dictionary of jobs
|
365
385
|
#
|
366
386
|
# Return:
|
367
|
-
#
|
387
|
+
# array of GanetiJob objects
|
368
388
|
def jobs_get
|
369
389
|
url = get_url("jobs")
|
370
390
|
response_body = send_request("GET", url)
|
@@ -377,54 +397,61 @@ module Ganeti
|
|
377
397
|
return list
|
378
398
|
end
|
379
399
|
|
380
|
-
#
|
381
|
-
#
|
382
|
-
#
|
383
|
-
#
|
384
|
-
#
|
385
|
-
#
|
386
|
-
#
|
387
|
-
#
|
388
|
-
#
|
389
|
-
#
|
390
|
-
#
|
391
|
-
#
|
392
|
-
#
|
393
|
-
#
|
394
|
-
#
|
395
|
-
#
|
400
|
+
# Description:
|
401
|
+
# Individual job URI
|
402
|
+
# Return a job status
|
403
|
+
# Returns: a dictionary with job parameters
|
404
|
+
#
|
405
|
+
# The result includes:
|
406
|
+
# id: job ID as number
|
407
|
+
# status: current job status as a string
|
408
|
+
# ops: involved OpCodes as a list of dictionaries for each opcodes in the job
|
409
|
+
# opstatus: OpCodes status as a list
|
410
|
+
# opresult: OpCodes results as a list
|
411
|
+
#
|
412
|
+
# For a successful opcode, the opresult field corresponding to it will contain the raw result from its LogicalUnit. In case an opcode has failed, its element in the opresult list will be a list of two elements:
|
413
|
+
# first element the error type (the Ganeti internal error name)
|
414
|
+
# second element a list of either one or two elements:
|
415
|
+
# the first element is the textual error description
|
416
|
+
# the second element, if any, will hold an error classification
|
396
417
|
#
|
397
|
-
#
|
398
|
-
#
|
418
|
+
# The error classification is most useful for the OpPrereqError error type - these errors happen before the OpCode has started executing, so it’s possible to retry the
|
419
|
+
# OpCode without side effects. But whether it make sense to retry depends on the error classification:
|
399
420
|
#
|
400
|
-
#
|
401
|
-
#
|
421
|
+
# resolver_error
|
422
|
+
# Resolver errors. This usually means that a name doesn’t exist in DNS, so if it’s a case of slow DNS propagation the operation can be retried later.
|
402
423
|
#
|
403
|
-
#
|
404
|
-
#
|
424
|
+
# insufficient_resources
|
425
|
+
# Not enough resources (iallocator failure, disk space, memory, etc.). If the resources on the cluster increase, the operation might succeed.
|
405
426
|
#
|
406
|
-
#
|
407
|
-
#
|
427
|
+
# wrong_input
|
428
|
+
# Wrong arguments (at syntax level). The operation will not ever be accepted unless the arguments change.
|
408
429
|
#
|
409
|
-
#
|
410
|
-
#
|
430
|
+
# wrong_state
|
431
|
+
# Wrong entity state. For example, live migration has been requested for a down instance, or instance creation on an offline node. The operation can be retried once the resource has changed state.
|
411
432
|
#
|
412
|
-
#
|
413
|
-
#
|
433
|
+
# unknown_entity
|
434
|
+
# Entity not found. For example, information has been requested for an unknown instance.
|
414
435
|
#
|
415
|
-
#
|
416
|
-
#
|
436
|
+
# already_exists
|
437
|
+
# Entity already exists. For example, instance creation has been requested for an already-existing instance.
|
417
438
|
#
|
418
|
-
#
|
419
|
-
#
|
439
|
+
# resource_not_unique
|
440
|
+
# Resource not unique (e.g. MAC or IP duplication).
|
420
441
|
#
|
421
|
-
#
|
422
|
-
#
|
442
|
+
# internal_error
|
443
|
+
# Internal cluster error. For example, a node is unreachable but not set offline, or the ganeti node daemons are not working, etc. A gnt-cluster verify should be run.
|
423
444
|
#
|
424
|
-
#
|
425
|
-
#
|
445
|
+
# environment_error
|
446
|
+
# Environment error (e.g. node disk error). A gnt-cluster verify should be run.
|
426
447
|
#
|
427
|
-
#
|
448
|
+
# Note that in the above list, by entity we refer to a node or instance, while by a resource we refer to an instance’s disk, or NIC, etc.
|
449
|
+
#
|
450
|
+
# Parameters:
|
451
|
+
# string job_id
|
452
|
+
#
|
453
|
+
# Return:
|
454
|
+
# GanetiJob object
|
428
455
|
def job_get(job_id)
|
429
456
|
url = get_url("jobs/#{job_id}")
|
430
457
|
response_body = send_request("GET", url)
|
@@ -434,13 +461,14 @@ module Ganeti
|
|
434
461
|
return GanetiJob.new(response_body)
|
435
462
|
end
|
436
463
|
|
437
|
-
#
|
464
|
+
# Description:
|
465
|
+
# Cancel a not-yet-started job
|
438
466
|
#
|
439
467
|
# Parameters:
|
440
|
-
# job_id: id of a job
|
468
|
+
# string job_id: id of a job
|
441
469
|
#
|
442
470
|
# Return:
|
443
|
-
#
|
471
|
+
# string job id
|
444
472
|
def job_delete(job_id)
|
445
473
|
url = get_url("jobs/#{job_id}")
|
446
474
|
response_body = send_request("DELETE", url)
|
@@ -448,11 +476,15 @@ module Ganeti
|
|
448
476
|
return response_body
|
449
477
|
end
|
450
478
|
|
451
|
-
#
|
452
|
-
#
|
453
|
-
#
|
479
|
+
# Description:
|
480
|
+
# Nodes resource
|
481
|
+
# Returns a list of all nodes
|
482
|
+
#
|
483
|
+
# Parameters:
|
484
|
+
# boolean: bulk (optional)
|
454
485
|
#
|
455
|
-
#
|
486
|
+
# Return:
|
487
|
+
# array of GanetiNode objects
|
456
488
|
def nodes_get(bulk = 0)
|
457
489
|
url = get_url("nodes", {"bulk", bulk})
|
458
490
|
response_body = send_request("GET", url)
|
@@ -465,7 +497,14 @@ module Ganeti
|
|
465
497
|
return list
|
466
498
|
end
|
467
499
|
|
468
|
-
#
|
500
|
+
# Description:
|
501
|
+
# Returns information about a node
|
502
|
+
#
|
503
|
+
# Parameters:
|
504
|
+
# string name: name of the node
|
505
|
+
#
|
506
|
+
# Return:
|
507
|
+
# GanetiNode object
|
469
508
|
def node_get(name)
|
470
509
|
url = get_url("nodes/#{name}")
|
471
510
|
response_body = send_request("GET", url)
|
@@ -475,15 +514,17 @@ module Ganeti
|
|
475
514
|
return GanetiNode.new(response_body)
|
476
515
|
end
|
477
516
|
|
478
|
-
#
|
479
|
-
#
|
517
|
+
# Description:
|
518
|
+
# Evacuates all secondary instances off a node.
|
519
|
+
# To evacuate a node, either one of the iallocator or remote_node parameters must be passed:
|
480
520
|
#
|
481
|
-
#
|
482
|
-
#
|
483
|
-
#
|
521
|
+
# Parameters:
|
522
|
+
# string name: name of the node
|
523
|
+
# string iallocator:
|
524
|
+
# string remote_node:
|
484
525
|
#
|
485
526
|
# Return:
|
486
|
-
# job id
|
527
|
+
# string job id
|
487
528
|
def node_evaluate(name, iallocator = "", remote_node = "")
|
488
529
|
url = get_url("nodes/#{name}/evacuate", {"iallocator" => iallocator, "remote_node" => remote_node})
|
489
530
|
response_body = send_request("POST", url)
|
@@ -491,14 +532,16 @@ module Ganeti
|
|
491
532
|
return response_body
|
492
533
|
end
|
493
534
|
|
494
|
-
#
|
495
|
-
#
|
535
|
+
# Description:
|
536
|
+
# Migrates all primary instances of a node
|
537
|
+
# No parameters are required, but the bool parameter live can be set to use live migration (if available)
|
496
538
|
#
|
497
|
-
#
|
498
|
-
#
|
539
|
+
# Parameters:
|
540
|
+
# string name: name of the node
|
541
|
+
# boolean live (optional)
|
499
542
|
#
|
500
543
|
# Return:
|
501
|
-
# job id
|
544
|
+
# string job id
|
502
545
|
def node_migrate(name, live = 0)
|
503
546
|
url = get_url("nodes/#{name}/migrate", {"live" => live})
|
504
547
|
response_body = send_request("POST", url)
|
@@ -506,18 +549,23 @@ module Ganeti
|
|
506
549
|
return response_body
|
507
550
|
end
|
508
551
|
|
509
|
-
#
|
510
|
-
#
|
552
|
+
# Description:
|
553
|
+
# Get the node role
|
554
|
+
# Returns the current node role
|
555
|
+
#
|
511
556
|
#
|
512
|
-
#
|
513
|
-
#
|
557
|
+
# The rol is always one of the following:
|
558
|
+
# drained
|
559
|
+
# master
|
560
|
+
# master-candidate
|
561
|
+
# offline
|
562
|
+
# regular
|
563
|
+
#
|
564
|
+
# Parameters:
|
565
|
+
# string name: name of the node
|
514
566
|
#
|
515
|
-
#
|
516
|
-
#
|
517
|
-
# master
|
518
|
-
# master-candidate
|
519
|
-
# offline
|
520
|
-
# regular
|
567
|
+
# Return:
|
568
|
+
# node role as string
|
521
569
|
def node_get_role(name)
|
522
570
|
url = get_url("nodes/#{name}/role")
|
523
571
|
response_body = send_request("GET", url)
|
@@ -525,28 +573,47 @@ module Ganeti
|
|
525
573
|
return response_body
|
526
574
|
end
|
527
575
|
|
528
|
-
#
|
529
|
-
# the
|
530
|
-
#
|
576
|
+
# Description:
|
577
|
+
# Change the node role
|
578
|
+
# the request is a string which shoud be PUT to this URI. The result will be a job id
|
579
|
+
#
|
580
|
+
# The rol is always one of the following:
|
581
|
+
# drained
|
582
|
+
# master
|
583
|
+
# master-candidate
|
584
|
+
# offline
|
585
|
+
# regular
|
531
586
|
#
|
532
|
-
#
|
533
|
-
#
|
534
|
-
#
|
535
|
-
#
|
536
|
-
#
|
537
|
-
#
|
587
|
+
# Parameters:
|
588
|
+
# string name: name of the node
|
589
|
+
# string role: name of the new role
|
590
|
+
# boolean force (optional)
|
591
|
+
#
|
592
|
+
# Return:
|
593
|
+
# string job id
|
538
594
|
def node_change_role(name, role, force = 0)
|
539
595
|
url = get_url("nodes/#{name}/role", {"role" => role, "force" => force})
|
596
|
+
# This is again quirck in the RAPI. The string needs to have escaped
|
597
|
+
# quotes becouse of pythons "non-stric" JSON handling
|
598
|
+
# http://code.google.com/p/ganeti/issues/detail?id=118
|
599
|
+
body = "\"#{role}\""
|
540
600
|
response_body = send_request("PUT", url, body)
|
541
601
|
|
542
602
|
return response_body
|
543
603
|
end
|
544
604
|
|
545
|
-
#
|
546
|
-
#
|
547
|
-
#
|
605
|
+
# Description:
|
606
|
+
# Manages storage units on the node
|
607
|
+
# Requests a list of storage units on a node. Requires the parameters storage_type (one of file, lvm-pv or lvm-vg) and output_fields.
|
608
|
+
# The result will be a job id, using which the result can be retrieved
|
548
609
|
#
|
549
|
-
#
|
610
|
+
# Parameters:
|
611
|
+
# string name: name of the node
|
612
|
+
# string storage_type: name of the storage type
|
613
|
+
# string output_fields: fields it needs to return back
|
614
|
+
#
|
615
|
+
# Return:
|
616
|
+
# string job id
|
550
617
|
def node_get_storage(name, storage_type = "", output_fields = "")
|
551
618
|
url = get_url("nodes/#{name}/storage", {"storage_type" => storage_type, "output_fields" => output_fields})
|
552
619
|
response_body = send_request("GET", url)
|
@@ -554,11 +621,17 @@ module Ganeti
|
|
554
621
|
return response_body
|
555
622
|
end
|
556
623
|
|
557
|
-
#
|
558
|
-
#
|
559
|
-
#
|
624
|
+
# Description:
|
625
|
+
# Modify storage units on the node
|
626
|
+
# Mofifies parameters of storage units on the node. Requires the parameters storage_type (one of file, lvm-pv or lvm-vg) and name (name of the storage unit).
|
627
|
+
# Parameters can be passed additionally. Currently only allocatable (bool) is supported.
|
560
628
|
#
|
561
|
-
#
|
629
|
+
# Parameters:
|
630
|
+
# string name: name of the node
|
631
|
+
# string storage_unit_name: name of the storage unit
|
632
|
+
# boolean allocatable (optional)
|
633
|
+
# Return:
|
634
|
+
# string job id
|
562
635
|
def node_modify_storage(name, storage_unit_name, storage_type, allocatable = 0)
|
563
636
|
url = get_url("nodes/#{name}/storage/modify", {"name" => storage_unit_name, "storage_type" => storage_type, "allocatable" => allocatable})
|
564
637
|
response_body = send_request("PUT", url)
|
@@ -567,12 +640,16 @@ module Ganeti
|
|
567
640
|
end
|
568
641
|
|
569
642
|
|
570
|
-
#
|
643
|
+
# Description:
|
644
|
+
# Repairs a storage unit on the node. Requires the parameters storage_type (currently only lvm-vg can be repaired) and name (name of the storage unit).
|
571
645
|
#
|
572
|
-
#
|
646
|
+
# Parameters:
|
647
|
+
# string name: name of the node
|
648
|
+
# string storage_name: name of the storage
|
649
|
+
# string storage_type: name of the storage type
|
573
650
|
#
|
574
|
-
# Return
|
575
|
-
# job id
|
651
|
+
# Return:
|
652
|
+
# string job id
|
576
653
|
def node_repair_storage(name, storage_name, storage_type = "lvm-vg")
|
577
654
|
url = get_url("nodes/#{name}/storage/repair",{"storage_type" => storage_type, "name" => storage_name})
|
578
655
|
response_body = send_request("PUT", url)
|
@@ -581,17 +658,16 @@ module Ganeti
|
|
581
658
|
end
|
582
659
|
|
583
660
|
|
584
|
-
#
|
585
|
-
#
|
661
|
+
# Description:
|
662
|
+
# Manages per-node tags
|
663
|
+
# Returns a list of tags
|
586
664
|
#
|
587
|
-
# Example:
|
588
|
-
# ["tag1","tag2", "tag3"]
|
589
665
|
#
|
590
666
|
# Parameters:
|
591
|
-
# name: name of node
|
667
|
+
# string name: name of node
|
592
668
|
#
|
593
669
|
# Return:
|
594
|
-
# array of tags
|
670
|
+
# array of tags, the tags are string
|
595
671
|
def node_get_tags(name)
|
596
672
|
url = get_url("nodes/#{name}/tags")
|
597
673
|
response_body = send_request("GET", url)
|
@@ -599,18 +675,18 @@ module Ganeti
|
|
599
675
|
return response_body
|
600
676
|
end
|
601
677
|
|
602
|
-
#
|
603
|
-
#
|
604
|
-
#
|
678
|
+
# Description:
|
679
|
+
# Add a set of tags
|
680
|
+
# The request as a list of strings should be PUT to this URI.
|
605
681
|
#
|
606
|
-
# The result will be a job id
|
607
682
|
#
|
608
683
|
# Parameters:
|
609
|
-
# name: node name
|
610
|
-
# tags: Array of tags
|
684
|
+
# string name: node name
|
685
|
+
# array tags: Array of tags, tags are strings
|
686
|
+
# boolean dry_run (optional)
|
611
687
|
#
|
612
688
|
# Return:
|
613
|
-
# job id
|
689
|
+
# string job id
|
614
690
|
def node_create_tags(name, tags, dry_run = 0)
|
615
691
|
url = get_url("nodes/#{name}/tags", {"tag" => tags, "dry-run" => dry_run})
|
616
692
|
response_body = send_request("PUT", url)
|
@@ -618,18 +694,18 @@ module Ganeti
|
|
618
694
|
return response_body
|
619
695
|
end
|
620
696
|
|
621
|
-
#
|
622
|
-
#
|
623
|
-
#
|
697
|
+
# Description:
|
698
|
+
# Deletes tags
|
699
|
+
# In order to delete a set of tags, the DELETE request should be addressed to URI like:
|
700
|
+
# /tags?tag=[tag]&tag=[tag]
|
624
701
|
#
|
625
|
-
# It supports the dry-run argument
|
626
702
|
#
|
627
703
|
# Parameters:
|
628
|
-
# name: node name
|
629
|
-
# tags: Array of tags
|
704
|
+
# string name: node name
|
705
|
+
# array tags: Array of tags, tags are strings
|
630
706
|
#
|
631
707
|
# Return:
|
632
|
-
# job id
|
708
|
+
# string job id
|
633
709
|
def node_delete_tags(name, tags, dry_run = 0)
|
634
710
|
url = get_url("nodes/#{name}/tags", {"tag" => tags, "dry-run" => dry_run})
|
635
711
|
response_body = send_request("DELETE", url)
|
@@ -637,13 +713,15 @@ module Ganeti
|
|
637
713
|
return response_body
|
638
714
|
end
|
639
715
|
|
640
|
-
#
|
641
|
-
#
|
642
|
-
#
|
643
|
-
#
|
716
|
+
# Description:
|
717
|
+
# Returns a list of all OSes
|
718
|
+
# Can return error 500 in case of a problem. Since this is a costly operation for Ganeti 2.0, it is not recommented to execute it too often
|
719
|
+
#
|
720
|
+
# Example:
|
721
|
+
# ["debian-etch"]
|
644
722
|
#
|
645
|
-
#
|
646
|
-
#
|
723
|
+
# Return:
|
724
|
+
# array of os's, os is a string
|
647
725
|
def os_list_get
|
648
726
|
url = get_url("os")
|
649
727
|
response_body = send_request("GET", url)
|
@@ -651,14 +729,15 @@ module Ganeti
|
|
651
729
|
return response_body
|
652
730
|
end
|
653
731
|
|
654
|
-
#
|
655
|
-
#
|
732
|
+
# Description:
|
733
|
+
# Manages cluster tags
|
734
|
+
# Returns the cluster tags
|
656
735
|
#
|
657
|
-
#
|
658
|
-
#
|
736
|
+
# Example:
|
737
|
+
# ["tag1", "tag2", "tag3"]
|
659
738
|
#
|
660
739
|
# Return:
|
661
|
-
#
|
740
|
+
# array of tags, tags are strings
|
662
741
|
def tags_get
|
663
742
|
url = get_url("tags")
|
664
743
|
response_body = send_request("GET", url)
|
@@ -666,16 +745,17 @@ module Ganeti
|
|
666
745
|
return response_body
|
667
746
|
end
|
668
747
|
|
669
|
-
#
|
670
|
-
#
|
748
|
+
# Description:
|
749
|
+
# Adds a set of tags
|
750
|
+
# The request as a list of strings should be PUT to this URI. The result will be a job id
|
671
751
|
#
|
672
|
-
# It supports the dry-run argument
|
673
752
|
#
|
674
753
|
# Parameters
|
675
|
-
# tags: Array of tags
|
754
|
+
# array tags: Array of tags, tags are strings
|
755
|
+
# boolean dry_run (optional)
|
676
756
|
#
|
677
757
|
# Return:
|
678
|
-
# job id
|
758
|
+
# string job id
|
679
759
|
def tags_create(tags, dry_run = 0)
|
680
760
|
url = get_url("tags", {"tag" => tags, "dry-run" => dry_run})
|
681
761
|
response_body = send_request("PUT", url)
|
@@ -683,17 +763,18 @@ module Ganeti
|
|
683
763
|
return response_body
|
684
764
|
end
|
685
765
|
|
686
|
-
#
|
687
|
-
#
|
688
|
-
#
|
766
|
+
# Description:
|
767
|
+
# Deletes tags
|
768
|
+
# In order to delete a set of tags, the DELETE request should be addressed to URI like:
|
769
|
+
# /tags?tag=[tag]&tag=[tag]
|
689
770
|
#
|
690
|
-
# It supports the dry-run argument
|
691
771
|
#
|
692
772
|
# Parameters:
|
693
|
-
# tags: Array of tags
|
773
|
+
# array tags: Array of tags, tags are strings
|
774
|
+
# boolean dry_run (optional)
|
694
775
|
#
|
695
776
|
# Return:
|
696
|
-
# job id
|
777
|
+
# string job id
|
697
778
|
def tags_delete(tags, dry_run = 0)
|
698
779
|
url = get_url("tags", {"tag" => tags, "dry-run" => dry_run})
|
699
780
|
response_body = send_request("DELETE", url)
|
@@ -702,9 +783,13 @@ module Ganeti
|
|
702
783
|
end
|
703
784
|
|
704
785
|
|
705
|
-
#
|
706
|
-
#
|
707
|
-
#
|
786
|
+
# Description:
|
787
|
+
# The version resource
|
788
|
+
# This resource should be used to determine the remote API version and to adapt client accordingly
|
789
|
+
# Returns the remote API version. Ganeti 1.2 returns 1 and Ganeti 2.0 returns 2
|
790
|
+
#
|
791
|
+
# Return:
|
792
|
+
# string version number
|
708
793
|
def version_get
|
709
794
|
url = get_url("version")
|
710
795
|
response_body = send_request("GET", url)
|
@@ -715,6 +800,15 @@ module Ganeti
|
|
715
800
|
|
716
801
|
private
|
717
802
|
|
803
|
+
# Description:
|
804
|
+
# Create the authentication headers, base64 encoded for basic auth
|
805
|
+
#
|
806
|
+
# Parameters:
|
807
|
+
# string username
|
808
|
+
# string password
|
809
|
+
#
|
810
|
+
# Return:
|
811
|
+
# hash headers
|
718
812
|
def authenticate(username, password)
|
719
813
|
basic = Base64.encode64("#{username}:#{password}").strip
|
720
814
|
headers = {'Authorization' => "Basic #{basic}"}
|
@@ -722,6 +816,15 @@ module Ganeti
|
|
722
816
|
return headers
|
723
817
|
end
|
724
818
|
|
819
|
+
# Descriptions:
|
820
|
+
# Create the url for the resource with extra parameters appended to the end if needed
|
821
|
+
#
|
822
|
+
# Params:
|
823
|
+
# string path: path to the resource
|
824
|
+
# hash params: extra parameters (optional)
|
825
|
+
#
|
826
|
+
# Return:
|
827
|
+
# string url
|
725
828
|
def get_url(path, params = nil)
|
726
829
|
param_string = ""
|
727
830
|
|
@@ -742,6 +845,17 @@ module Ganeti
|
|
742
845
|
return url.chop
|
743
846
|
end
|
744
847
|
|
848
|
+
# Description:
|
849
|
+
# Using the net::http library to create an http object that sends a request to the appropriate resource
|
850
|
+
# The response is catched, parsed and returned
|
851
|
+
#
|
852
|
+
# Parameters:
|
853
|
+
# string method: action method (get, post, put, delete)
|
854
|
+
# string url: the path to the resource
|
855
|
+
# string body: extra body information that needs to be send to the resource
|
856
|
+
#
|
857
|
+
# Return:
|
858
|
+
# json response: the reponse from the resource
|
745
859
|
def send_request(method, url, body = nil)
|
746
860
|
uri = URI.parse(host)
|
747
861
|
|
@@ -763,6 +877,12 @@ module Ganeti
|
|
763
877
|
return JSON.parse(response_body).first
|
764
878
|
end
|
765
879
|
|
880
|
+
# Description:
|
881
|
+
# Create the appropriate Ganeti object if the class type does not exist yet.
|
882
|
+
# The specific Ganeti object inherits from a master object.
|
883
|
+
#
|
884
|
+
# Parameters:
|
885
|
+
# string class_name: name of the specific Ganeti object
|
766
886
|
def create_class(class_name)
|
767
887
|
unless(class_exists?(class_name))
|
768
888
|
klass = Class.new Ganeti::GanetiObject
|
@@ -770,6 +890,14 @@ module Ganeti
|
|
770
890
|
end
|
771
891
|
end
|
772
892
|
|
893
|
+
# Description:
|
894
|
+
# Check if a specific class exists in the current runtime
|
895
|
+
#
|
896
|
+
# Parameters:
|
897
|
+
# string class_name: name of the specific Ganeti object
|
898
|
+
#
|
899
|
+
# Return:
|
900
|
+
# boolean
|
773
901
|
def class_exists?(class_name)
|
774
902
|
klass = Module.const_get(class_name)
|
775
903
|
return klass.is_a?(Class)
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ganeti_client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 17
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 7
|
10
|
+
version: 0.0.7
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- "Micha\xC3\xABl Rigart"
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-08-
|
18
|
+
date: 2010-08-19 00:00:00 +02:00
|
19
19
|
default_executable:
|
20
20
|
dependencies: []
|
21
21
|
|