ganeti_client 0.0.7 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
data/README CHANGED
@@ -1,7 +1,5 @@
1
1
  == Todo
2
2
 
3
- 2. Add some error handling
4
- 3. Make some code improvements
5
3
  5. Improve this README with better docs
6
4
  6. Write tests!
7
5
 
@@ -16,16 +14,16 @@
16
14
 
17
15
  == Usage
18
16
 
19
- # the last parameter is a boolean (true|false) to indicate if you want to display the response.
20
- # this might be handy for debugging purposes
21
- client = GanetiClient::Client.new("your-host-and-port", "username", "password", boolean)
17
+ # Create a client instance
18
+ client = GanetiClient::Client.new("host:port", "username", "password")
22
19
 
23
20
  # now you should be able to access the api resources by using the client instance.
24
21
  # example:
25
22
  info = client.info_get
26
23
  => #<GanetiInfo:0x10151bb78>
27
24
 
28
- # most methods return an object. When you use .to_json on an object, you get the json object returned
25
+ # most methods return an object. When you use .to_json on an object, you get
26
+ # the json object returned
29
27
  # then you can see all the attributes available
30
28
  info.name
31
29
  => "hostname"
@@ -35,13 +33,14 @@
35
33
 
36
34
  1. Fork the project
37
35
  2. Add your changes
38
- 3. Write tests
36
+ 3. Write tests for your changes
39
37
  4. Send a pull request
40
38
 
41
39
 
42
40
  == Author
43
41
 
44
42
  Michaël Rigart
43
+ http://www.netronix.be
45
44
 
46
45
 
47
46
  == License
@@ -2,7 +2,8 @@
2
2
  #
3
3
  # The Client is mainly developed for usage with the Ganeti RAPI version 2
4
4
  #
5
- # The protocol used is JSON over HTTP designed afther the REST principle. HTTP Basic authentication as per RFC2617 is supported
5
+ # The protocol used is JSON over HTTP designed afther the REST principle. HTTP Basic authentication as per RFC2617 is
6
+ # supported
6
7
  #
7
8
  # A few generic refered parameter types and the values they allow:
8
9
  #
@@ -12,16 +13,21 @@
12
13
  # A few parameter mean the same thing accross all resources which implement it:
13
14
  #
14
15
  # bulk:
15
- # Bulk-mode means that for the resources which usually return just a list of child resources (e.g. /2/instances which returns just instance names),
16
- # the output will instead contain detailed data for all these subresources. This is more efficient than query-ing the sub-resources themselves.
16
+ # Bulk-mode means that for the resources which usually return just a list of child resources (e.g. /2/instances
17
+ # which returns just instance names),
18
+ # the output will instead contain detailed data for all these subresources. This is more efficient than query-ing
19
+ # the sub-resources themselves.
17
20
  #
18
21
  # dry-run:
19
- # The boolean dry-run argument, if provided and set, signals to Ganeti that the job should not be executed, only the pre-execution checks will be done.
20
- # This is useful in trying to determine (without guarantees though, as in the meantime the cluster state could have changed) if the operation
22
+ # The boolean dry-run argument, if provided and set, signals to Ganeti that the job should not be executed, only
23
+ # the pre-execution checks will be done.
24
+ # This is useful in trying to determine (without guarantees though, as in the meantime the cluster state could
25
+ # have changed) if the operation
21
26
  # is likely to succeed or at least start executing.
22
27
  #
23
28
  # force:
24
- # Force operation to continue even if it will cause the cluster to become inconsistent (e.g. because there are not enough master candidates).
29
+ # Force operation to continue even if it will cause the cluster to become inconsistent (e.g. because there are
30
+ # not enough master candidates).
25
31
  #
26
32
  # Author:: Michaël Rigart (mailto:michael@netronix.be)
27
33
  # Copyright:: Copyright (c) 2010 Michaël Rigart
@@ -32,7 +38,7 @@ module Ganeti
32
38
  # This class contains all active resources available in Ganeti RAPI
33
39
  class Client
34
40
 
35
- attr_accessor :host, :username, :password, :version, :show_response
41
+ attr_accessor :host, :username, :password, :version
36
42
 
37
43
  # Description:
38
44
  # Create the client object
@@ -41,18 +47,14 @@ module Ganeti
41
47
  # string host: hostname and port
42
48
  # string username: username that has access to RAPI
43
49
  # string password: password of the user provided
44
- # boolean show_response: show response data (optional)
45
- def initialize(host, username, password, show_response = false)
50
+ def initialize(host, username, password)
46
51
  self.host = host
47
52
  self.username = username
48
53
  self.password = password
49
54
 
50
- self.show_response = show_response
51
-
52
55
  self.version = self.version_get
53
56
  end
54
57
 
55
-
56
58
  # Description:
57
59
  # Get the cluster information
58
60
  #
@@ -88,7 +90,8 @@ module Ganeti
88
90
  # Return:
89
91
  # array of all available instances. The array items contain a GanetiInstance object
90
92
  def instances_get(bulk = 0)
91
- url = get_url("instances", {"bulk" => bulk})
93
+ params = {"bulk" => bulk}
94
+ url = get_url("instances", params)
92
95
  response_body = send_request("GET", url)
93
96
 
94
97
  create_class("GanetiInstance")
@@ -101,8 +104,10 @@ module Ganeti
101
104
 
102
105
  # Description:
103
106
  # 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
107
+ # If the options bool dry-run argument is provided, the job will not be actually executed, only the
108
+ # pre-execution checks will be done.
109
+ # Query-ing the job result will return, in boty dry-run and normal case, the list of nodes selected for
110
+ # the instance
106
111
  #
107
112
  # Make sure the instance_name resolves!!
108
113
  #
@@ -112,9 +117,11 @@ module Ganeti
112
117
  # Example:
113
118
  # info = {
114
119
  # 'hypervisor' => 'kvm' , 'disk_template' => 'plain',
115
- # 'pnode' => 'node.netronix.be', 'instance_name' => 'vm1.netronix.be', 'os' => 'debootstrap+lucid',
120
+ # 'pnode' => 'node.netronix.be', 'instance_name' => 'vm1.netronix.be',
121
+ # 'os' => 'debootstrap+lucid',
116
122
  # 'name' => 'vm1.netronix.be',
117
- # 'vcpus' => '4', 'memory' => '4096', 'disks' => [25600],
123
+ # 'vcpus' => '4', 'memory' => '4096',
124
+ # 'disks' => [25600],
118
125
  # 'kernel-path' => '/boot/vmlinuz-2.6-kvmU'
119
126
  # }
120
127
  #
@@ -176,7 +183,8 @@ module Ganeti
176
183
  # Return:
177
184
  # string job id
178
185
  def instance_delete(name, dry_run = 0)
179
- url = get_url("instances/#{name}", {"dry-run" => dry_run})
186
+ params = {"dry-run" => dry_run}
187
+ url = get_url("instances/#{name}", params)
180
188
  response_body = send_request("DELETE", url)
181
189
 
182
190
  return response_body
@@ -193,7 +201,8 @@ module Ganeti
193
201
  # Return:
194
202
  # string job id
195
203
  def instance_get_info(name, static = 0)
196
- url = get_url("instances/#{name}/info", {"static" => static})
204
+ params = {"static" => static}
205
+ url = get_url("instances/#{name}/info", params)
197
206
  response_body = send_request("GET", url)
198
207
 
199
208
  return response_body
@@ -206,7 +215,8 @@ module Ganeti
206
215
  # type defines the reboot type.
207
216
  # soft is just a normal reboot, without terminating the hypervisor.
208
217
  # 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
218
+ # full is like hard but also recreates the configuration from ground up as if you would have done
219
+ # a gnt-instance shutdown and gnt-instance start on it
210
220
  #
211
221
  #
212
222
  # Parameters:
@@ -218,7 +228,8 @@ module Ganeti
218
228
  # Return:
219
229
  # string job id
220
230
  def instance_reboot(name, type = "soft", ignore_secondaries = 0, dry_run = 0)
221
- url = get_url("instances/#{name}/reboot", {"type" => type, "ignore_secondaries" => ignore_secondaries, "dry_run" => 0})
231
+ params = {"type" => type, "ignore_secondaries" => ignore_secondaries, "dry_run" => 0}
232
+ url = get_url("instances/#{name}/reboot", params)
222
233
  response_body = send_request("POST", url)
223
234
 
224
235
  return response_body
@@ -235,7 +246,8 @@ module Ganeti
235
246
  # Return:
236
247
  # string job id
237
248
  def instance_shutdown(name, dry_run = 0)
238
- url = get_url("instances/#{name}/shutdown", {"dry-run" => dry_run})
249
+ params = {"dry-run" => dry_run}
250
+ url = get_url("instances/#{name}/shutdown", params)
239
251
  response_body = send_request("PUT", url)
240
252
 
241
253
  return response_body
@@ -253,7 +265,8 @@ module Ganeti
253
265
  # Return:
254
266
  # string job id
255
267
  def instance_startup(name, force = 0, dry_run=0)
256
- url = get_url("instances/#{name}/startup", {"force" => force, "dry-run" => dry_run})
268
+ params = {"force" => force, "dry-run" => dry_run}
269
+ url = get_url("instances/#{name}/startup", params)
257
270
  response_body = send_request("PUT", url)
258
271
 
259
272
  return response_body
@@ -270,7 +283,8 @@ module Ganeti
270
283
  # Return:
271
284
  # string job id
272
285
  def instance_reinstall(name, os_name, nostartup = 0)
273
- url = get_url("instances/#{name}/reinstall", {"os" => os_name, "nostartup" => nostartup})
286
+ params = {"os" => os_name, "nostartup" => nostartup}
287
+ url = get_url("instances/#{name}/reinstall", params)
274
288
  response_body = send_request("POST", url)
275
289
 
276
290
  return response_body
@@ -278,9 +292,11 @@ module Ganeti
278
292
 
279
293
  # Description:
280
294
  # 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
295
+ # Takes the parameters mode (one of replace_on_primary, replace_on_secondary or replace_auto), disks
296
+ # (comma seperated list of disk indexes), remote_node and iallocator
282
297
  # 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
298
+ # mode is a mandatory parameter. replace_auto tries to determine the broken disk(s) on its own and
299
+ # replacing it
284
300
  #
285
301
  # Parameters:
286
302
  # string name: name of the instance
@@ -292,7 +308,8 @@ module Ganeti
292
308
  # Return:
293
309
  # string job id
294
310
  def instance_replace_disks(name, mode = "replace_auto", iallocator = "", remote_node = "", disks = "")
295
- url = get_url("instances/#{name}/replace-disks", {"mode" => mode, "iallocator" => iallocator, "remote_node" => remote_node, "disks" => disks})
311
+ params = {"mode" => mode, "iallocator" => iallocator, "remote_node" => remote_node, "disks" => disks}
312
+ url = get_url("instances/#{name}/replace-disks", params)
296
313
  response_body = send_request("POST", url)
297
314
 
298
315
  return response_body
@@ -300,7 +317,8 @@ module Ganeti
300
317
 
301
318
  # Description:
302
319
  # 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)
320
+ # Takes the bool parameter ignore_size. When set ignore the recorded size (useful for forcing activation
321
+ # when recoreded size is wrong)
304
322
  #
305
323
  # Parameters:
306
324
  # string name: name of the instance
@@ -309,7 +327,8 @@ module Ganeti
309
327
  # Return:
310
328
  # string job id
311
329
  def instance_activate_disks(name, ignore_size = 0)
312
- url = get_url("instances/#{name}/activate-disks", {"ignore_size" => ignore_size})
330
+ params = {"ignore_size" => ignore_size}
331
+ url = get_url("instances/#{name}/activate-disks", params)
313
332
  response_body = send_request("PUT", url)
314
333
 
315
334
  return response_body
@@ -357,7 +376,8 @@ module Ganeti
357
376
  # Return:
358
377
  # string job id
359
378
  def instance_create_tags(name, tags, dry_run = 0)
360
- url = get_url("instances/#{name}/tags", {'dry-run' => dry_run, 'tag' => tags})
379
+ params = {'dry-run' => dry_run, 'tag' => tags}
380
+ url = get_url("instances/#{name}/tags", params)
361
381
  response_body = send_request("PUT", url)
362
382
 
363
383
  return response_body
@@ -374,7 +394,8 @@ module Ganeti
374
394
  # Return:
375
395
  # string job id
376
396
  def instance_delete_tags(name, tags, dry_run = 0)
377
- url = get_url("instances/#{name}/tags", {'dry-run' => dry_run, 'tag' => tags})
397
+ params = {'dry-run' => dry_run, 'tag' => tags}
398
+ url = get_url("instances/#{name}/tags", params)
378
399
  response_body = send_request("DELETE", url)
379
400
 
380
401
  return response_body
@@ -409,43 +430,54 @@ module Ganeti
409
430
  # opstatus: OpCodes status as a list
410
431
  # opresult: OpCodes results as a list
411
432
  #
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:
433
+ # For a successful opcode, the opresult field corresponding to it will contain the raw result from its
434
+ # LogicalUnit. In case an opcode has failed, its element in the opresult list will be a list of two
435
+ # elements:
413
436
  # first element the error type (the Ganeti internal error name)
414
437
  # second element a list of either one or two elements:
415
438
  # the first element is the textual error description
416
439
  # the second element, if any, will hold an error classification
417
440
  #
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
441
+ # The error classification is most useful for the OpPrereqError error type - these errors happen before
442
+ # the OpCode has started executing, so it’s possible to retry the
419
443
  # OpCode without side effects. But whether it make sense to retry depends on the error classification:
420
444
  #
421
445
  # 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.
446
+ # Resolver errors. This usually means that a name doesn’t exist in DNS, so if it’s a case of
447
+ # slow DNS propagation the operation can be retried later.
423
448
  #
424
449
  # insufficient_resources
425
- # Not enough resources (iallocator failure, disk space, memory, etc.). If the resources on the cluster increase, the operation might succeed.
450
+ # Not enough resources (iallocator failure, disk space, memory, etc.). If the resources on the
451
+ # cluster increase, the operation might succeed.
426
452
  #
427
453
  # wrong_input
428
- # Wrong arguments (at syntax level). The operation will not ever be accepted unless the arguments change.
454
+ # Wrong arguments (at syntax level). The operation will not ever be accepted unless the arguments
455
+ # change.
429
456
  #
430
457
  # 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.
458
+ # Wrong entity state. For example, live migration has been requested for a down instance, or
459
+ # instance creation on an offline node. The operation can be retried once the resource has
460
+ # changed state.
432
461
  #
433
462
  # unknown_entity
434
463
  # Entity not found. For example, information has been requested for an unknown instance.
435
464
  #
436
465
  # already_exists
437
- # Entity already exists. For example, instance creation has been requested for an already-existing instance.
466
+ # Entity already exists. For example, instance creation has been requested for an
467
+ # already-existing instance.
438
468
  #
439
469
  # resource_not_unique
440
470
  # Resource not unique (e.g. MAC or IP duplication).
441
471
  #
442
472
  # 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.
473
+ # Internal cluster error. For example, a node is unreachable but not set offline, or the
474
+ # ganeti node daemons are not working, etc. A gnt-cluster verify should be run.
444
475
  #
445
476
  # environment_error
446
477
  # Environment error (e.g. node disk error). A gnt-cluster verify should be run.
447
478
  #
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.
479
+ # Note that in the above list, by entity we refer to a node or instance, while by a resource we refer
480
+ # to an instance’s disk, or NIC, etc.
449
481
  #
450
482
  # Parameters:
451
483
  # string job_id
@@ -486,7 +518,8 @@ module Ganeti
486
518
  # Return:
487
519
  # array of GanetiNode objects
488
520
  def nodes_get(bulk = 0)
489
- url = get_url("nodes", {"bulk", bulk})
521
+ params = {"bulk", bulk}
522
+ url = get_url("nodes", params)
490
523
  response_body = send_request("GET", url)
491
524
 
492
525
  create_class("GanetiNode")
@@ -526,8 +559,9 @@ module Ganeti
526
559
  # Return:
527
560
  # string job id
528
561
  def node_evaluate(name, iallocator = "", remote_node = "")
529
- url = get_url("nodes/#{name}/evacuate", {"iallocator" => iallocator, "remote_node" => remote_node})
530
- response_body = send_request("POST", url)
562
+ params = {"iallocator" => iallocator, "remote_node" => remote_node}
563
+ url = get_url("nodes/#{name}/evacuate", params)
564
+ response_body = send_request("POST", url)
531
565
 
532
566
  return response_body
533
567
  end
@@ -543,7 +577,8 @@ module Ganeti
543
577
  # Return:
544
578
  # string job id
545
579
  def node_migrate(name, live = 0)
546
- url = get_url("nodes/#{name}/migrate", {"live" => live})
580
+ params = {"live" => live}
581
+ url = get_url("nodes/#{name}/migrate", params)
547
582
  response_body = send_request("POST", url)
548
583
 
549
584
  return response_body
@@ -592,7 +627,8 @@ module Ganeti
592
627
  # Return:
593
628
  # string job id
594
629
  def node_change_role(name, role, force = 0)
595
- url = get_url("nodes/#{name}/role", {"role" => role, "force" => force})
630
+ params = {"role" => role, "force" => force}
631
+ url = get_url("nodes/#{name}/role", params)
596
632
  # This is again quirck in the RAPI. The string needs to have escaped
597
633
  # quotes becouse of pythons "non-stric" JSON handling
598
634
  # http://code.google.com/p/ganeti/issues/detail?id=118
@@ -604,7 +640,8 @@ module Ganeti
604
640
 
605
641
  # Description:
606
642
  # 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.
643
+ # Requests a list of storage units on a node. Requires the parameters storage_type (one of file, lvm-pv
644
+ # or lvm-vg) and output_fields.
608
645
  # The result will be a job id, using which the result can be retrieved
609
646
  #
610
647
  # Parameters:
@@ -615,7 +652,8 @@ module Ganeti
615
652
  # Return:
616
653
  # string job id
617
654
  def node_get_storage(name, storage_type = "", output_fields = "")
618
- url = get_url("nodes/#{name}/storage", {"storage_type" => storage_type, "output_fields" => output_fields})
655
+ params = {"storage_type" => storage_type, "output_fields" => output_fields}
656
+ url = get_url("nodes/#{name}/storage", params)
619
657
  response_body = send_request("GET", url)
620
658
 
621
659
  return response_body
@@ -623,7 +661,8 @@ module Ganeti
623
661
 
624
662
  # Description:
625
663
  # 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).
664
+ # Mofifies parameters of storage units on the node. Requires the parameters storage_type (one of file,
665
+ # lvm-pv or lvm-vg) and name (name of the storage unit).
627
666
  # Parameters can be passed additionally. Currently only allocatable (bool) is supported.
628
667
  #
629
668
  # Parameters:
@@ -633,7 +672,8 @@ module Ganeti
633
672
  # Return:
634
673
  # string job id
635
674
  def node_modify_storage(name, storage_unit_name, storage_type, allocatable = 0)
636
- url = get_url("nodes/#{name}/storage/modify", {"name" => storage_unit_name, "storage_type" => storage_type, "allocatable" => allocatable})
675
+ params = {"name" => storage_unit_name, "storage_type" => storage_type, "allocatable" => allocatable}
676
+ url = get_url("nodes/#{name}/storage/modify", params)
637
677
  response_body = send_request("PUT", url)
638
678
 
639
679
  return response_body
@@ -641,7 +681,8 @@ module Ganeti
641
681
 
642
682
 
643
683
  # 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).
684
+ # Repairs a storage unit on the node. Requires the parameters storage_type (currently only lvm-vg can
685
+ # be repaired) and name (name of the storage unit).
645
686
  #
646
687
  # Parameters:
647
688
  # string name: name of the node
@@ -651,7 +692,8 @@ module Ganeti
651
692
  # Return:
652
693
  # string job id
653
694
  def node_repair_storage(name, storage_name, storage_type = "lvm-vg")
654
- url = get_url("nodes/#{name}/storage/repair",{"storage_type" => storage_type, "name" => storage_name})
695
+ params = {"storage_type" => storage_type, "name" => storage_name}
696
+ url = get_url("nodes/#{name}/storage/repair", params)
655
697
  response_body = send_request("PUT", url)
656
698
 
657
699
  return response_body
@@ -688,7 +730,8 @@ module Ganeti
688
730
  # Return:
689
731
  # string job id
690
732
  def node_create_tags(name, tags, dry_run = 0)
691
- url = get_url("nodes/#{name}/tags", {"tag" => tags, "dry-run" => dry_run})
733
+ params = {"tag" => tags, "dry-run" => dry_run}
734
+ url = get_url("nodes/#{name}/tags", params)
692
735
  response_body = send_request("PUT", url)
693
736
 
694
737
  return response_body
@@ -707,7 +750,8 @@ module Ganeti
707
750
  # Return:
708
751
  # string job id
709
752
  def node_delete_tags(name, tags, dry_run = 0)
710
- url = get_url("nodes/#{name}/tags", {"tag" => tags, "dry-run" => dry_run})
753
+ params = {"tag" => tags, "dry-run" => dry_run}
754
+ url = get_url("nodes/#{name}/tags", params)
711
755
  response_body = send_request("DELETE", url)
712
756
 
713
757
  return response_body
@@ -715,7 +759,8 @@ module Ganeti
715
759
 
716
760
  # Description:
717
761
  # 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
762
+ # Can return error 500 in case of a problem. Since this is a costly operation for Ganeti 2.0, it is
763
+ # not recommented to execute it too often
719
764
  #
720
765
  # Example:
721
766
  # ["debian-etch"]
@@ -757,7 +802,8 @@ module Ganeti
757
802
  # Return:
758
803
  # string job id
759
804
  def tags_create(tags, dry_run = 0)
760
- url = get_url("tags", {"tag" => tags, "dry-run" => dry_run})
805
+ params = {"tag" => tags, "dry-run" => dry_run}
806
+ url = get_url("tags", params)
761
807
  response_body = send_request("PUT", url)
762
808
 
763
809
  return response_body
@@ -776,7 +822,8 @@ module Ganeti
776
822
  # Return:
777
823
  # string job id
778
824
  def tags_delete(tags, dry_run = 0)
779
- url = get_url("tags", {"tag" => tags, "dry-run" => dry_run})
825
+ params = {"tag" => tags, "dry-run" => dry_run}
826
+ url = get_url("tags", params)
780
827
  response_body = send_request("DELETE", url)
781
828
 
782
829
  return response_body
@@ -811,9 +858,7 @@ module Ganeti
811
858
  # hash headers
812
859
  def authenticate(username, password)
813
860
  basic = Base64.encode64("#{username}:#{password}").strip
814
- headers = {'Authorization' => "Basic #{basic}"}
815
-
816
- return headers
861
+ return {'Authorization' => "Basic #{basic}"}
817
862
  end
818
863
 
819
864
  # Descriptions:
@@ -853,28 +898,54 @@ module Ganeti
853
898
  # string method: action method (get, post, put, delete)
854
899
  # string url: the path to the resource
855
900
  # string body: extra body information that needs to be send to the resource
856
- #
857
- # Return:
858
- # json response: the reponse from the resource
859
- def send_request(method, url, body = nil)
901
+ def send_request(method, url, body = nil, headers = {})
902
+ raise ArgumentError, 'only GET, POST, PUT and DELETE methods are supported' unless %w[GET POST PUT DELETE].include?(method.to_s)
903
+ raise ArgumentError, 'headers must be a hash' unless headers.is_a?(Hash)
904
+
860
905
  uri = URI.parse(host)
861
906
 
862
907
  http = Net::HTTP.new(uri.host, uri.port)
863
908
  http.use_ssl = (uri.scheme == "http")? false : true
909
+
910
+ headers.merge!({'User-Agent' => 'Ruby Ganeti RAPI Client'})
911
+ headers.merge!(authenticate(self.username, self.password))
912
+
913
+ begin
914
+ response = http.send_request(method, url, body, headers)
915
+ rescue => e
916
+ puts "Error sending request"
917
+ puts e.message
918
+ else
919
+ case response
920
+ when Net::HTTPSuccess
921
+ parse_response(response.body.strip)
922
+ else
923
+ response.instance_eval { class << self; attr_accessor :body_parsed; end }
924
+ begin; response.body_parsed = parse_response(response.body); rescue; end
925
+ response.error! # raises exception corresponding to http error Net::XXX
926
+ end
927
+ end
928
+ end
864
929
 
865
- headers = {}
866
- headers = authenticate(self.username, self.password)
867
-
868
- response = http.send_request(method, url, body, headers)
869
-
870
-
871
- puts "Response #{response.code} #{response.message}: #{response.body}" if self.show_response
872
930
 
931
+ # Description:
932
+ # TEST
933
+ #
934
+ # Parameters:
935
+ # string response_body
936
+ #
937
+ # Return:
938
+ # json response: the reponse from the resource
939
+ def parse_response(response_body)
873
940
  # adding workaround becouse Google seems to operate on 'non-strict' JSON format
874
941
  # http://code.google.com/p/ganeti/issues/detail?id=117
875
- response_body = '['+response.body.strip+']'
942
+ begin
943
+ response_body = JSON.parse(response_body)
944
+ rescue
945
+ response_body = JSON.parse('['+response_body+']').first
946
+ end
876
947
 
877
- return JSON.parse(response_body).first
948
+ return response_body
878
949
  end
879
950
 
880
951
  # Description:
data/lib/ganeti_client.rb CHANGED
@@ -33,6 +33,4 @@ require 'ganeti_client/ganeti_object'
33
33
 
34
34
 
35
35
  module Ganeti
36
-
37
-
38
36
  end
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: 17
4
+ hash: 15
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 7
10
- version: 0.0.7
9
+ - 8
10
+ version: 0.0.8
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-19 00:00:00 +02:00
18
+ date: 2010-08-20 00:00:00 +02:00
19
19
  default_executable:
20
20
  dependencies: []
21
21