rubiojr-pangea 0.1.20090403134419

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,6 @@
1
+ module Pangea
2
+ class LinkConnectError < Exception
3
+ end
4
+ class ProxyCallError < Exception
5
+ end
6
+ end
@@ -0,0 +1,675 @@
1
+ module Pangea
2
+
3
+ #
4
+ # Link is the connection to the hypervisor
5
+ #
6
+ # Every Link is associated to one host
7
+ #
8
+ class Link #:nodoc:
9
+
10
+ attr_reader :client, :sid, :url, :connected
11
+
12
+ def initialize(url, username='foo', password='bar')
13
+ @xmlrpc_url = url
14
+ @username = username
15
+ @password = password
16
+ end
17
+
18
+ def connect
19
+ #puts "hyperlinking to #{@xmlrpc_url}"
20
+ $stdout.flush
21
+ begin
22
+ @client = XMLRPC::Client.new2(@xmlrpc_url)
23
+ @session = @client.proxy('session')
24
+ @sid = @session.login_with_password(@username, @password)['Value']
25
+ @connected = true
26
+ rescue Exception => e
27
+ raise LinkConnectError.new("Error connecting to the hypervisor #{@xmlrpc_url} (#{e.message})")
28
+ end
29
+ end
30
+
31
+ end
32
+
33
+ #
34
+ # Base class for every Xen Object
35
+ #
36
+ # Do not use this class.
37
+ #
38
+ # There's no direct mapping to xen-api AFAIK
39
+ #
40
+ class XObject #:nodoc:
41
+
42
+ def initialize(link, ref)
43
+ @ref = ref
44
+ @link = link
45
+ @proxy_name = nil
46
+ end
47
+
48
+ def ref_call(method)
49
+ if @proxy.nil?
50
+ # first ref_call, init proxy
51
+ @proxy = @link.client.proxy(@proxy_name)
52
+ end
53
+ begin
54
+ return @proxy.send(method, @link.sid, @ref)['Value']
55
+ rescue Exception => e
56
+ raise ProxyCallError.new("Error sending request to proxy #{@proxy_name}. Link might be dead (#{e.message})")
57
+ end
58
+ end
59
+
60
+ #
61
+ # This is standard in every Xen Object
62
+ #
63
+ # Returns the unique identifier
64
+ #
65
+ def uuid
66
+ ref_call :get_uuid
67
+ end
68
+
69
+ end
70
+
71
+ #
72
+ # A Physical Host
73
+ #
74
+ # xen-api: Class host
75
+ #
76
+ # <tt>
77
+ # require 'pangea'
78
+ #
79
+ # host = Host.connect(\'http://xen.example.net', 'username', 'password')
80
+ # </tt>
81
+ #
82
+ class Host < XObject
83
+
84
+ def initialize(link, ref) #:nodoc:
85
+ super(link, ref)
86
+ @proxy_name = 'host'
87
+ end
88
+
89
+ #
90
+ # Returns the label of the Host (hostname)
91
+ #
92
+ def label
93
+ ref_call :get_name_label
94
+ end
95
+
96
+ #
97
+ # Get the list of resident virtual machines controlled
98
+ # by the hypervisor.
99
+ #
100
+ # Returns an Array of Pangea::VM objects
101
+ #
102
+ # xen-api: host.get_resident_VMs
103
+ #
104
+ def resident_vms
105
+ vms = []
106
+ ref_call(:get_resident_VMs).each do |vm|
107
+ vms << VM.new(@link, vm)
108
+ end
109
+ vms
110
+ end
111
+
112
+ #
113
+ # Get the list of resident virtual machines controlled
114
+ # by the hypervisor.
115
+ #
116
+ # Returns an Array of Pangea::HostCpu objects
117
+ #
118
+ # xen-api: host.get_host_cpus
119
+ #
120
+ def cpus
121
+ list = []
122
+ ref_call(:get_host_CPUs).each do |hcpu|
123
+ list << HostCpu.new(@link, hcpu)
124
+ end
125
+ list
126
+ end
127
+
128
+ #
129
+ # List some properties from the hypervisor:
130
+ #
131
+ # machine: Host Architecture
132
+ # Xen: Xen Version
133
+ # system: Host OS (i.e. Linux)
134
+ # release: Xen Kernel Version
135
+ # host: hostname
136
+ #
137
+ # Returns a Hash
138
+ #
139
+ # xen-api: host.get_software_version
140
+ #
141
+ def software_version
142
+ ref_call :get_software_version
143
+ end
144
+
145
+ #
146
+ # Get the Xen scheduling policy
147
+ #
148
+ # Returns a string
149
+ #
150
+ # xen-api: host.get_sched_policy
151
+ #
152
+ def sched_policy
153
+ ref_call :get_sched_policy
154
+ end
155
+
156
+ #
157
+ # Get the Pangea::HostMetrics object for this host
158
+ #
159
+ # xen-api: host.get_metrics
160
+ #
161
+ def metrics
162
+ HostMetrics.new(@link, ref_call(:get_metrics))
163
+ end
164
+
165
+ #
166
+ # Returns the list of networks available in this host
167
+ #
168
+ # If you are using a bridged network configuration
169
+ # ('network-script network-bridge' in xend-config.sxp), it will
170
+ # return an Array of Pangea::Network objects available in the host,
171
+ # one for each bridge available.
172
+ #
173
+ # There's no direct mapping to xen-api AFAIK
174
+ #
175
+ def networks
176
+ nets = []
177
+ p = @link.client.proxy( 'network' )
178
+ p.get_all(@link.sid)['Value'].each do |ref|
179
+ nets << Network.new(@link, ref)
180
+ end
181
+ nets
182
+ end
183
+
184
+ def to_s
185
+ "Label: #{label}\n" +
186
+ "UUID: #{uuid}\n" +
187
+ "Sched Policy: #{sched_policy}\n" +
188
+ "Xen Version: #{software_version['Xen']}"
189
+ end
190
+
191
+ #
192
+ # Connect to the Host xml-rpc server
193
+ #
194
+ # Returns a Pangea::Host object
195
+ #
196
+ # There's no direct mapping to xen-api
197
+ #
198
+ def self.connect(url, username, password)
199
+ @link = Link.new(url, username, password)
200
+ @link.connect
201
+ @ref = @link.client.call('host.get_all', @link.sid)['Value'][0]
202
+ Host.new(@link, @ref)
203
+ end
204
+
205
+ #
206
+ # Reconnect to the Host
207
+ #
208
+ # There's no direct mapping to xen-api
209
+ #
210
+ def reconnect
211
+ raise LinkConnectError.new("You need to connect at least once before reconnecting") if @link.nil?
212
+ @link.connect
213
+ @ref = @link.client.call('host.get_all', @link.sid)['Value'][0]
214
+ end
215
+
216
+ #
217
+ # Checks if the connection to the host xml-rpc server is alive
218
+ #
219
+ # There's no direct mapping to xen-api
220
+ #
221
+ def alive?
222
+ begin
223
+ ref_call :get_uuid
224
+ rescue Exception => e
225
+ #puts e.message
226
+ return false
227
+ end
228
+ true
229
+ end
230
+
231
+ end
232
+
233
+ #
234
+ # The metrics associated with a host
235
+ #
236
+ # xen-api: Class host_metrics
237
+ #
238
+ class HostMetrics < XObject
239
+
240
+ def initialize(link, ref) #:nodoc:
241
+ super(link, ref)
242
+ @proxy_name = 'host_metrics'
243
+ end
244
+
245
+ def memory_total
246
+ ref_call :get_memory_total
247
+ end
248
+
249
+ def memory_free
250
+ ref_call :get_memory_free
251
+ end
252
+
253
+ def to_s
254
+ "Total Memory: #{Pangea::Util.humanize_bytes(memory_total)}\n" +
255
+ "Free Memory: #{Pangea::Util.humanize_bytes(memory_free)}"
256
+ end
257
+
258
+ end
259
+
260
+ #
261
+ # A Physical CPU
262
+ #
263
+ # xen-api: Class host_cpu
264
+ #
265
+ class HostCpu < XObject
266
+
267
+ def initialize(link, ref) #:nodoc:
268
+ super(link, ref)
269
+ @proxy_name = 'host_cpu'
270
+ end
271
+
272
+ #
273
+ # xen-api: host_cpu.get_number
274
+ #
275
+ def number
276
+ ref_call :get_number
277
+ end
278
+
279
+ #
280
+ # xen-api: host_cpu.get_vendor
281
+ #
282
+ def vendor
283
+ ref_call :get_vendor
284
+ end
285
+
286
+ #
287
+ # xen-api: host_cpu.get_speed
288
+ #
289
+ # CPU Speed in MHz
290
+ #
291
+ def speed
292
+ ref_call :get_speed
293
+ end
294
+
295
+ #
296
+ # xen-api: host_cpu.get_modelname
297
+ #
298
+ # CPU Model
299
+ #
300
+ def model_name
301
+ ref_call :get_modelname
302
+ end
303
+
304
+ #
305
+ # xen-api: host_cpu.get_utilisation
306
+ #
307
+ # CPU Utilisation
308
+ #
309
+ def utilisation
310
+ ref_call :get_utilisation
311
+ end
312
+
313
+ end
314
+
315
+
316
+ #
317
+ # A Virtual Machine or Guest (DomU)
318
+ #
319
+ # xen-api: VM
320
+ #
321
+ class VM < XObject
322
+
323
+ def initialize(link, ref) #:nodoc:
324
+ super(link, ref)
325
+ @proxy_name = 'VM'
326
+ end
327
+
328
+ #
329
+ # VM Label (same one you see when you run 'xm list')
330
+ #
331
+ # xen-api: VM.get_name_label
332
+ #
333
+ def label
334
+ ref_call :get_name_label
335
+ end
336
+
337
+ #
338
+ # xen-api: VM.get_metrics
339
+ #
340
+ def metrics
341
+ VMMetrics.new(@link, ref_call(:get_metrics))
342
+ end
343
+
344
+ #
345
+ # xen-api: VM.get_guest_metrics
346
+ #
347
+ def guest_metrics
348
+ VMGuestMetrics.new(@link, ref_call(:get_guest_metrics))
349
+ end
350
+
351
+ #
352
+ # xen-api: VM.get_VIFs
353
+ #
354
+ def vifs
355
+ list = []
356
+ ref_call(:get_VIFs).each do |vif|
357
+ list << VIF.new(@link, vif)
358
+ end
359
+ list
360
+ end
361
+
362
+ #
363
+ # xen-api: VM.get_power_state
364
+ #
365
+ def power_state
366
+ ref_call :get_power_state
367
+ end
368
+
369
+ #
370
+ # xen-api: VM.get_memory_static_max
371
+ #
372
+ def max_mem
373
+ ref_call :get_memory_static_max
374
+ end
375
+
376
+ def dyn_max_mem
377
+ ref_call :get_memory_dynamic_max
378
+ end
379
+
380
+ def dyn_min_mem
381
+ ref_call :get_memory_dynamic_min
382
+ end
383
+
384
+ #
385
+ # xen-api: VM.get_memory_static_min
386
+ #
387
+ def min_mem
388
+ ref_call :get_memory_static_min
389
+ end
390
+
391
+ #
392
+ # xen-api: VM.get_resident_on
393
+ #
394
+ def resident_on
395
+ ref = ref_call(:get_resident_on)
396
+ Host.new(@link, ref)
397
+ end
398
+
399
+ #
400
+ # xen-api: VM.get_domid
401
+ #
402
+ def domid
403
+ (ref = ref_call :get_domid).to_i
404
+ end
405
+
406
+ #
407
+ # xen-api: VM.get_is_control_domain
408
+ #
409
+ def is_control_domain?
410
+ ref_call :get_is_control_domain
411
+ end
412
+
413
+ #
414
+ # xen-api: VM.get_auto_power_on
415
+ #
416
+ #def auto_power_on?
417
+ # puts ref_call :get_auto_power_on
418
+ #end
419
+
420
+ #
421
+ # xen-api: VM.get_actions_after_shutdown
422
+ #
423
+ def actions_after_shutdown
424
+ ref_call :get_actions_after_shutdown
425
+ end
426
+
427
+ #
428
+ # xen-api: VM.get_pv_kernel
429
+ #
430
+ def pv_kernel
431
+ ref_call :get_PV_kernel
432
+ end
433
+
434
+ #
435
+ # xen-api: VM.get_actions_after_reboot
436
+ #
437
+ def actions_after_reboot
438
+ ref_call :get_actions_after_reboot
439
+ end
440
+
441
+ #
442
+ # xen-api: VM.get_actions_after_crash
443
+ #
444
+ def actions_after_crash
445
+ ref_call :get_actions_after_crash
446
+ end
447
+
448
+ def to_s
449
+ eol = "\n"
450
+ "Label: #{label}" + eol +
451
+ "UUID: #{uuid}" + eol +
452
+ "Power State: #{power_state}" + eol +
453
+ "Mem: #{Util::humanize_bytes(dyn_min_mem)}" + eol +
454
+ "Max Mem: #{Util::humanize_bytes(max_mem)}" + eol
455
+ end
456
+
457
+ end
458
+
459
+
460
+ #
461
+ # Metrics reported by the guest (from 'inside' the guest)
462
+ #
463
+ # xen-api: Class VM_guest_metrics
464
+ #
465
+ class VMGuestMetrics < XObject
466
+ def initialize(link, ref) #:nodoc:
467
+ super(link, ref)
468
+ @proxy_name = 'VM_guest_metrics'
469
+ end
470
+ end
471
+
472
+ #
473
+ # Metrics associated with a VM
474
+ #
475
+ # xen-api class: VM_metrics
476
+ #
477
+ class VMMetrics < XObject
478
+
479
+ def initialize(link, ref) #:nodoc:
480
+ super(link, ref)
481
+ @proxy_name = 'VM_metrics'
482
+ end
483
+
484
+ #
485
+ # xen-api: VM_metrics.get_memory_actual
486
+ #
487
+ def memory_actual
488
+ ref_call :get_memory_actual
489
+ end
490
+
491
+ #
492
+ # xen-api: VM_metrics.get_VCPUs_number
493
+ # Number of cpus assigned to the domU
494
+ #
495
+ def vcpus_number
496
+ ref_call :get_VCPUs_number
497
+ end
498
+
499
+ #
500
+ # xen-api: VM_metrics.get_VCPUs_utilisation
501
+ #
502
+ # returns a hash
503
+ # {
504
+ # cpu0 => utilisation,
505
+ # cpu1 => utilization,
506
+ # ...
507
+ # }
508
+ #
509
+ def vcpus_utilisation
510
+ ref_call :get_VCPUs_utilisation
511
+ end
512
+
513
+ #
514
+ # xen-api: VM_metrics.get_state
515
+ #
516
+ def state
517
+ ref_call :get_state
518
+ end
519
+
520
+ #
521
+ # xen-api: VM_metrics.get_start_time
522
+ #
523
+ def start_time
524
+ (ref_call :get_start_time).to_time
525
+ end
526
+
527
+ #
528
+ # xen-api: VM_metrics.get_last_updated
529
+ #
530
+ def last_updated
531
+ (ref_call :get_last_updated).to_time
532
+ end
533
+
534
+ def to_s
535
+ vcpu_u = ""
536
+ vcpus_utilisation.each do |k, v|
537
+ vcpu_u += "#{k}: %0.2f\n" % (v * 100)
538
+ end
539
+ eol = "\n"
540
+ "[VM Metrics]" + eol +
541
+ "State: #{state}" + eol +
542
+ "Start Time: #{start_time}" + eol +
543
+ "Last Updated: #{last_updated}" + eol +
544
+ "VCPUs Utilisation:" + eol +
545
+ vcpu_u
546
+ end
547
+ end
548
+
549
+ class VIF < XObject
550
+
551
+ def initialize(link, ref) #:nodoc:
552
+ super(link, ref)
553
+ @proxy_name = 'VIF'
554
+ end
555
+
556
+ #
557
+ # xen-api: VIF.get_device
558
+ #
559
+ def device
560
+ ref_call :get_device
561
+ end
562
+
563
+ #
564
+ # xen-api: VIF.get_MAC
565
+ #
566
+ def mac
567
+ ref_call :get_MAC
568
+ end
569
+
570
+ #
571
+ # xen-api: VIF.get_metrics
572
+ #
573
+ def metrics
574
+ VIFMetrics.new(@link, ref_call(:get_metrics))
575
+ end
576
+
577
+ #
578
+ # xen-api: VIF.get_vm
579
+ #
580
+ def vm
581
+ VM.new(@link, ref_call(:get_VM))
582
+ end
583
+
584
+ #
585
+ # xen-api: VIF.get_network
586
+ # FIXME
587
+ #
588
+ #def network
589
+ # Network.new(@link, ref_call(:get_network), @link.client.proxy('network'))
590
+ #end
591
+
592
+ end
593
+
594
+ #
595
+ # Metrics associated with a virtual network device
596
+ #
597
+ # xen-api: Class VIF_metrics
598
+ #
599
+ class VIFMetrics < XObject
600
+
601
+ def initialize(link, ref) #:nodoc:
602
+ super(link, ref)
603
+ @proxy_name = 'VIF_metrics'
604
+ end
605
+
606
+ #
607
+ # VIF input Kbits/s
608
+ #
609
+ # xen-api: VIF_metrics.get_io_read_kbs
610
+ #
611
+ def io_read_kbs
612
+ ref_call :get_io_read_kbs
613
+ end
614
+
615
+ #
616
+ # VIF output Kbits/s
617
+ #
618
+ # xen-api: VIF_metrics.get_io_read_kbs
619
+ #
620
+ def io_write_kbs
621
+ ref_call :get_io_write_kbs
622
+ end
623
+ end
624
+
625
+ class Network < XObject
626
+ def initialize(link, ref) #:nodoc:
627
+ super(link, ref)
628
+ @proxy_name = 'network'
629
+ end
630
+
631
+ def label
632
+ ref_call :get_name_label
633
+ end
634
+
635
+ #
636
+ # Returns a string or nil if the gateway is not
637
+ # defined.
638
+ #
639
+ # xen-api: network.get_default_gateway
640
+ #
641
+ def default_gateway
642
+ gw = ref_call :get_default_gateway
643
+ return nil if gw.strip.chomp.empty?
644
+ gw
645
+ end
646
+
647
+ #
648
+ # Returns a string or nil if the netmask is not
649
+ # defined.
650
+ #
651
+ # xen-api: network.get_default_netmask
652
+ #
653
+ def default_netmask
654
+ nm = ref_call :get_default_netmask
655
+ return nil if nm.strip.chomp.empty?
656
+ gw
657
+ end
658
+
659
+ #
660
+ # Virtual Interfaces bridged to the network bridge
661
+ #
662
+ # xen-api: network.get_VIFs
663
+ #
664
+ def vifs
665
+ l = []
666
+ ref_call(:get_VIFs).each do |ref|
667
+ l << VIF.new(@link, ref)
668
+ end
669
+ l
670
+ end
671
+
672
+ end
673
+
674
+ end # module Pangea
675
+