ganeti_client 0.0.6 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|