ganeti_client 0.0.7 → 0.0.8

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 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