Projet

Général

Profil

Paste
Télécharger au format
Statistiques
| Branche: | Révision:

root / plugins / libvirt / libvirt @ 17f78427

Historique | Voir | Annoter | Télécharger (50,2 ko)

1
#!/usr/bin/perl -w
2
# $Id: libvirt 24900 2010-03-30 13:50:40Z espen $
3
#
4
# Copyright (C) 2010 Espen Braastad
5
#
6
# This program is free software; you can redistribute it and/or
7
# modify it under the terms of the GNU General Public License
8
# as published by the Free Software Foundation; version 2 dated June,
9
# 1991.
10
#
11
# This program is distributed in the hope that it will be useful,
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
# GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License
17
# along with this program; if not, write to the Free Software
18
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19
#
20
#
21
# This multigraph plugin monitors libvirt resource usage.
22
#
23
# Configuration variables:
24
#
25
#  General variables:
26
#   address         - to libvirt (default "xen:///")
27
#   username        - to libvirt (default: "")
28
#   password        - to libvirt (default: "")
29
#   tmpfile         - to cache values (default: "/var/lib/munin/plugin-state/libvirt")
30
#
31
#  Variables to enable or disable graphs:
32
#   show_cpu_used           - 1 to enable, 0 to disable [default = 1]
33
#   show_disk_traffic       - 1 to enable, 0 to disable [default = 1]
34
#   show_disk_utilization   - 1 to enable, 0 to disable [default = 1]
35
#   show_disk_latency       - 1 to enable, 0 to disable [default = 1]
36
#   show_memory_allocated   - 1 to enable, 0 to disable [default = 1]
37
#   show_network_traffic    - 1 to enable, 0 to disable [default = 1]
38
#   show_network_drops      - 1 to enable, 0 to disable [default = 1]
39
#
40
# Requirements:
41
#   RHEL5: perl-Sys-Virt.x86_64
42
#
43
# Revision 1.4 2010/03/30 espen
44
#  Added graphs for i/o utilization
45
#
46
# Revision 1.3 2010/03/29 espen
47
#  Added graphs for i/o latency
48
#
49
# Revision 1.2 2010/03/19 espen
50
#  Added support for enable/disable graphs from plugin-conf.d.
51
#  Added graphs for disk errors and network drops.
52
#
53
# Revision 1.1 2010/03/14 espen
54
#  Added support for monitoring network (bits) and disk (bytes) usage.
55
#
56
# Revision 1.0 2010/03/11 espen
57
#  Initial version. Support for cpu and memory per domain.
58
#
59
#%# family=auto
60
#%# capabilities=autoconf
61

    
62
use strict;
63
use XML::Twig;
64
use Sys::Virt;
65
use Sys::Virt::Domain;
66
use File::stat;
67
use Storable;
68
use Time::localtime;
69

    
70
my $address = $ENV{address} || "xen:///";
71
my $username = $ENV{username} || "";
72
my $password = $ENV{password} || "";
73
my $tmpfile = $ENV{tmpfile} || "$ENV{MUNIN_PLUGSTATE}/libvirt";
74
my $decimals=5;
75

    
76
my %show=();
77

    
78
# Reading values from plugin-conf.d or set defaults.
79
$show{'cpu_used'}         = $ENV{show_cpu_used} || 1;
80
$show{'disk_traffic'}     = $ENV{show_disk_traffic} || 1;
81
$show{'disk_utilization'} = $ENV{show_disk_utilization} || 1;
82
$show{'disk_latency'}     = $ENV{show_disk_latency} || 1;
83
$show{'disk_errors'}      = $ENV{show_disk_errors} || 1;
84
$show{'memory_allocated'} = $ENV{show_memory_allocated} || 1;
85
$show{'network_traffic'}  = $ENV{show_network_traffic} || 1;
86
$show{'network_drops'}    = $ENV{show_network_drops} || 1;
87

    
88
sub init() {
89
  my $type=undef;
90

    
91
  if ($ARGV[0] and $ARGV[0] eq "config"){
92
    $type="config";
93
  }
94
  if ($ARGV[0] and $ARGV[0] eq "autoconf"){
95
    &autoconf();
96
    exit;
97
  }
98
  if(!$ARGV[0]){
99
    $type="fetch";
100
  }
101

    
102
  if(!defined($type)){
103
    print "Argument not supported, see the howto.\n";
104
  }
105

    
106
  # Connecting to libvirt
107
  my $vmm=&connect();
108

    
109
  my @domains = $vmm->list_domains();
110

    
111
  my %hash=();
112

    
113
  my $node = $vmm->get_node_info();
114
  # 'model' => 'x86_64',
115
  # 'threads' => 2,
116
  # 'cores' => 4,
117
  # 'memory' => 33545216,
118
  # 'mhz' => 2261,
119
  # 'sockets' => 2,
120
  # 'nodes' => 1,
121
  # 'cpus' => 16
122

    
123
  foreach my $domain (@domains) {
124

    
125
    my $name                  = $domain->get_name();
126
    $hash{$name}{'name'}      = $name;
127
    $hash{$name}{'id'}        = $domain->get_id();
128
    $hash{$name}{'info'}      = $domain->get_info();
129
    $hash{$name}{'maxvcpus'}  = $domain->get_max_vcpus();
130
    $hash{$name}{'maxmem'}    = $domain->get_max_memory();
131
    $hash{$name}{'type'}      = $domain->get_os_type();
132
    $hash{$name}{'scheduler'} = $domain->get_scheduler_type();
133
    $hash{$name}{'xml'}       = parse_xml($domain->get_xml_description());
134
    $hash{$name}{'label'}     = clean_label($name);
135

    
136
    # Calculate cputime used in percent
137
    if(defined($hash{$name}{'info'}{'cpuTime'}) && defined($node->{'cpus'})){
138
      $hash{$name}{'info'}{'cpuPercentage'} = sprintf("%d",1.0e-7 * $hash{$name}{'info'}{'cpuTime'} / $node->{'cpus'});
139
    }
140

    
141
    # Calculate bytes
142
    if(defined($hash{$name}{'info'}{'memory'})){
143
      $hash{$name}{'info'}{'memory_bytes'} = 1024 * $hash{$name}{'info'}{'memory'};
144
    }
145

    
146
    # Extract network usage
147
    if(defined($hash{$name}{'xml'}{'devices'}{'interface'}{'bridge'})){
148
      my $vif_id=0;
149
      for my $vif (keys %{$hash{$name}{'xml'}{'devices'}{'interface'}{'bridge'}}){
150
        $hash{$name}{'devices'}{'network'}{$vif}=$domain->interface_stats($vif);
151

    
152
        # The interface number on this $VM. Will be used as ID later in labels
153
        $hash{$name}{'devices'}{'network'}{$vif}{'vif_id'}=$vif_id;
154
        $vif_id++;
155
      }
156
    }
157

    
158
    # Extract block device usage
159
    if(defined($hash{$name}{'xml'}{'devices'}{'disk'}{'block'})){
160
      for my $block (keys %{$hash{$name}{'xml'}{'devices'}{'disk'}{'block'}}){
161
        $hash{$name}{'devices'}{'block'}{$block}=$domain->block_stats($block);
162
      }
163
    }
164

    
165
    # Gather data later used to calculate latency and utilization
166
    if(defined($hash{$name}{'xml'}{'devices'}{'disk'}{'block'})){
167
      for my $block (keys %{$hash{$name}{'xml'}{'devices'}{'disk'}{'block'}}){
168
        if(defined($hash{$name}{'devices'}{'block'}{$block})){
169
          my $source_dev=$hash{$name}{'xml'}{'devices'}{'disk'}{'block'}{$block}{'source'};
170
          $hash{$name}{'devices'}{'block'}{$block}{'source'}{$source_dev}=read_diskstats($source_dev);
171
        }
172
      }
173
    }
174
  }
175

    
176
  my $prev_time=&get_prev_time($tmpfile);
177
  my $time=time();
178
  my $prev_state_ref=undef;
179

    
180
  # Cache the result to disk if we graphs that require cache are enabled
181
  if($show{'disk_latency'} == 1 || $show{'disk_utilization'} == 1){
182
    if(-e $tmpfile){
183
      $prev_state_ref=retrieve($tmpfile);
184
    }
185

    
186
    store(\%hash,$tmpfile);
187
  }
188

    
189
  #
190
  # Disk utilization
191
  #
192

    
193
  if($show{'disk_utilization'} == 1){
194

    
195
    #
196
    # Disk utilization, top level
197
    #
198

    
199
    if($type eq "config"){
200
      print "multigraph libvirt_disk_utilization\n";
201
      #print "graph_order rd wr\n";
202
      print "graph_title Disk utilization per domain in percent\n";
203
      print "graph_vlabel %\n";
204
      print "graph_category virtualization\n";
205
      print "graph_args -l 0 --base 1000 --upper-limit 100\n";
206
      #print "graph_width 550\n";
207

    
208
      for my $vm (sort keys %hash) {
209
        if(defined($hash{$vm}{'devices'}{'block'})){
210
          print $hash{$vm}{'label'} . ".label " . $hash{$vm}{'name'} . "\n";
211
          print $hash{$vm}{'label'} . ".info The maximum I/O utilization in percent on " . $hash{$vm}{'name'} . ". If the time spent for I/O is close to 1000 msec for a given second, the device is nearly 100% saturated. If the virtual machine have more than one disk, the value from the disk with the highest utilization is being shown.\n";
212
          print $hash{$vm}{'label'} . ".min 0\n";
213
          print $hash{$vm}{'label'} . ".draw LINE2\n";
214
        }
215
      }
216
      print "\n";
217

    
218
    } elsif($type eq "fetch"){
219
      print "multigraph libvirt_disk_utilization\n";
220
      for my $vm (sort keys %hash) {
221
        if(defined($hash{$vm}{'devices'}{'block'}) && defined($prev_state_ref->{$vm}->{'devices'}->{'block'})){
222

    
223
          my $utilization=0;
224

    
225
          for my $device (keys %{$hash{$vm}{'devices'}{'block'}}){
226

    
227
            if(defined($prev_state_ref->{$vm}->{'devices'}->{'block'}->{$device})){
228

    
229
              for my $source_device (keys %{$hash{$vm}{'devices'}{'block'}{$device}{'source'}}){
230

    
231
                for my $slave_device (keys %{$hash{$vm}{'devices'}{'block'}{$device}{'source'}{$source_device}{'slaves'}}){
232

    
233
                  my $prev_ms_spent_doing_io=$prev_state_ref->{$vm}->{'devices'}->{'block'}->{$device}->{'source'}->{$source_device}->{'slaves'}->{$slave_device}->{'io_ticks'};
234
                  my $cur_ms_spent_doing_io=$hash{$vm}{'devices'}{'block'}{$device}{'source'}{$source_device}{'slaves'}{$slave_device}{'io_ticks'};
235

    
236
                  if($cur_ms_spent_doing_io > $prev_ms_spent_doing_io){
237
                    my $ticks=$cur_ms_spent_doing_io-$prev_ms_spent_doing_io;
238
                    my $interval_ms=($time-$prev_time)*1000;
239
                    if($interval_ms > 0){
240
                      my $dev_utilization=($ticks/$interval_ms)*100;
241

    
242
                      # Will only print show the highest utilization on each VM on the top level graph
243
                      if($dev_utilization > $utilization){
244
                        $utilization=sprintf("%.${decimals}f",$dev_utilization);
245
                      }
246
                    }
247
                  }
248
                }
249
              }
250
            }
251
          }
252
          print $hash{$vm}{'label'} . ".value " . $utilization . "\n";
253
        }
254
      }
255
      print "\n";
256
    }
257

    
258
    #
259
    # Disk utilization, second level
260
    #
261

    
262
    for my $vm (sort keys %hash) {
263
      my $devices=0;
264
      if(defined($hash{$vm}{'devices'}{'block'})){
265
        for my $device (keys %{$hash{$vm}{'devices'}{'block'}}){
266
          $devices++;
267
        }
268
      }
269
      if($type eq "config"){
270
        print "multigraph libvirt_disk_utilization." . $hash{$vm}{'label'} . "\n";
271
        #print "graph_order rd wr\n";
272
        print "graph_title Disk utilization on " . $vm . " in percent\n";
273
        print "graph_vlabel %\n";
274
        print "graph_category virtualization\n";
275
        print "graph_args -l 0 --base 1000 --upper-limit 100\n";
276
        #print "graph_width 550\n";
277

    
278
        if($devices>0){
279
          if(defined($hash{$vm}{'devices'}{'block'})){
280
            for my $device (keys %{$hash{$vm}{'devices'}{'block'}}){
281
              print $hash{$vm}{'label'} . "_" . $device . ".label " . $device . "\n";
282
              print $hash{$vm}{'label'} . "_" . $device . ".info The maximum I/O utilization in percent on " . $device . ". If the time spent for I/O is close to 1000 msec for a given second, the device is nearly 100% saturated.\n";
283
              print $hash{$vm}{'label'} . "_" . $device . ".min 0\n";
284
              print $hash{$vm}{'label'} . "_" . $device . ".draw LINE2\n";
285
            }
286
          }
287
        }
288
        print "\n";
289

    
290
      } elsif($type eq "fetch"){
291
        if($devices > 0){
292
          print "multigraph libvirt_disk_utilization." . $hash{$vm}{'label'} . "\n";
293
          if(defined($hash{$vm}{'devices'}{'block'}) && defined($prev_state_ref->{$vm}->{'devices'}->{'block'})){
294

    
295
            for my $device (keys %{$hash{$vm}{'devices'}{'block'}}){
296

    
297
              my $utilization=0;
298

    
299
              if(defined($prev_state_ref->{$vm}->{'devices'}->{'block'}->{$device})){
300

    
301
                for my $source_device (keys %{$hash{$vm}{'devices'}{'block'}{$device}{'source'}}){
302

    
303
                  for my $slave_device (keys %{$hash{$vm}{'devices'}{'block'}{$device}{'source'}{$source_device}{'slaves'}}){
304

    
305
                    my $prev_ms_spent_doing_io=$prev_state_ref->{$vm}->{'devices'}->{'block'}->{$device}->{'source'}->{$source_device}->{'slaves'}->{$slave_device}->{'io_ticks'};
306
                    my $cur_ms_spent_doing_io=$hash{$vm}{'devices'}{'block'}{$device}{'source'}{$source_device}{'slaves'}{$slave_device}{'io_ticks'};
307

    
308
                    if($cur_ms_spent_doing_io > $prev_ms_spent_doing_io){
309
                      my $ticks=$cur_ms_spent_doing_io-$prev_ms_spent_doing_io;
310
                      my $interval_ms=($time-$prev_time)*1000;
311
                      if($interval_ms > 0){
312
                        my $dev_utilization=($ticks/$interval_ms)*100;
313
                        $utilization=sprintf("%.${decimals}f",$dev_utilization);
314
                      }
315
                    }
316
                  }
317
                }
318
              }
319
              print $hash{$vm}{'label'} . "_" . $device . ".value " . $utilization . "\n";
320
            }
321
          }
322
          print "\n";
323
        }
324
      }
325
    }
326
  }
327

    
328
  #
329
  # Disk latency
330
  #
331

    
332
  if($show{'disk_latency'} == 1){
333

    
334
    #
335
    # Disk latency, top level
336
    #
337

    
338
    if($type eq "config"){
339
      print "multigraph libvirt_disk_latency\n";
340
      #print "graph_order rd wr\n";
341
      print "graph_title Disk latency per domain in seconds\n";
342
      print "graph_args --base 1000\n";
343
      print "graph_vlabel read (-) / write (+)\n";
344
      print "graph_category virtualization\n";
345
      #print "graph_width 550\n";
346

    
347
      for my $vm (sort keys %hash) {
348
        if(defined($hash{$vm}{'devices'}{'block'})){
349

    
350
          # Will only graph the domains with one or more block device
351
          my $devices=0;
352
          for my $device (keys %{$hash{$vm}{'devices'}{'block'}}){
353
            $devices++;
354
          }
355
          if($devices > 0){
356
            print $hash{$vm}{'label'} . "_rd.label " . $hash{$vm}{'name'} . "_rd\n";
357
            print $hash{$vm}{'label'} . "_rd.info I/O latency in seconds on " . $hash{$vm}{'name'} . "\n";
358
            print $hash{$vm}{'label'} . "_rd.min 0\n";
359
            print $hash{$vm}{'label'} . "_rd.draw LINE2\n";
360
            print $hash{$vm}{'label'} . "_rd.graph no\n";
361

    
362
            print $hash{$vm}{'label'} . "_wr.label " . $hash{$vm}{'name'} . "\n";
363
            print $hash{$vm}{'label'} . "_wr.info I/O latency in seconds on " . $hash{$vm}{'name'} . "\n";
364
            print $hash{$vm}{'label'} . "_wr.min 0\n";
365
            print $hash{$vm}{'label'} . "_wr.draw LINE2\n";
366
            print $hash{$vm}{'label'} . "_wr.negative " . $hash{$vm}{'label'} . "_rd\n";
367
          }
368
        }
369
      }
370
      print "\n";
371

    
372
    } elsif($type eq "fetch"){
373
      print "multigraph libvirt_disk_latency\n";
374
      for my $vm (sort keys %hash) {
375
        if(defined($hash{$vm}{'devices'}{'block'}) && defined($prev_state_ref->{$vm}->{'devices'}->{'block'})){
376

    
377
          my $prev_total_time_spent_writing=0;
378
          my $prev_total_time_spent_reading=0;
379
          my $prev_total_ios_read=0;
380
          my $prev_total_ios_written=0;
381
          my $cur_total_time_spent_writing=0;
382
          my $cur_total_time_spent_reading=0;
383
          my $cur_total_ios_read=0;
384
          my $cur_total_ios_written=0;
385

    
386
          my $devices=0;
387

    
388
          for my $device (keys %{$hash{$vm}{'devices'}{'block'}}){
389
            $devices++;
390

    
391
            if(defined($prev_state_ref->{$vm}->{'devices'}->{'block'}->{$device})){
392

    
393
              for my $source_device (keys %{$hash{$vm}{'devices'}{'block'}{$device}{'source'}}){
394

    
395
                for my $slave_device (keys %{$hash{$vm}{'devices'}{'block'}{$device}{'source'}{$source_device}{'slaves'}}){
396

    
397
                  my $prev_time_spent_writing=$prev_state_ref->{$vm}->{'devices'}->{'block'}->{$device}->{'source'}->{$source_device}->{'slaves'}->{$slave_device}->{'write_ticks'};
398
                  my $prev_time_spent_reading=$prev_state_ref->{$vm}->{'devices'}->{'block'}->{$device}->{'source'}->{$source_device}->{'slaves'}->{$slave_device}->{'read_ticks'};
399
                  my $prev_ios_read=$prev_state_ref->{$vm}->{'devices'}->{'block'}->{$device}->{'source'}->{$source_device}->{'slaves'}->{$slave_device}->{'read_ios'};
400
                  my $prev_ios_written=$prev_state_ref->{$vm}->{'devices'}->{'block'}->{$device}->{'source'}->{$source_device}->{'slaves'}->{$slave_device}->{'write_ios'};
401

    
402
                  my $cur_time_spent_writing=$hash{$vm}{'devices'}{'block'}{$device}{'source'}{$source_device}{'slaves'}{$slave_device}{'write_ticks'};
403
                  my $cur_time_spent_reading=$hash{$vm}{'devices'}{'block'}{$device}{'source'}{$source_device}{'slaves'}{$slave_device}{'read_ticks'};
404
                  my $cur_ios_read=$hash{$vm}{'devices'}{'block'}{$device}{'source'}{$source_device}{'slaves'}{$slave_device}{'read_ios'};
405
                  my $cur_ios_written=$hash{$vm}{'devices'}{'block'}{$device}{'source'}{$source_device}{'slaves'}{$slave_device}{'write_ios'};
406

    
407
                  $prev_total_time_spent_writing+=$prev_time_spent_writing;
408
                  $prev_total_time_spent_reading+=$prev_time_spent_reading;
409
                  $prev_total_ios_read+=$prev_ios_read;
410
                  $prev_total_ios_written+=$prev_ios_written;
411

    
412
                  $cur_total_time_spent_writing+=$cur_time_spent_writing;
413
                  $cur_total_time_spent_reading+=$cur_time_spent_reading;
414
                  $cur_total_ios_read+=$cur_ios_read;
415
                  $cur_total_ios_written+=$cur_ios_written;
416
                }
417
              }
418
            }
419
          }
420

    
421
          my $read_latency=0;
422
          my $write_latency=0;
423

    
424
          if($prev_total_time_spent_reading > 0 && $prev_total_ios_read > 0 && ($cur_total_ios_read-$prev_total_ios_read) > 0){
425
            $read_latency=(($cur_total_time_spent_reading-$prev_total_time_spent_reading)/($cur_total_ios_read-$prev_total_ios_read))/1000;
426
          }
427

    
428
          if($prev_total_time_spent_writing > 0 && $prev_total_ios_written > 0 && ($cur_total_ios_written-$prev_total_ios_written) > 0){
429
            $write_latency=(($cur_total_time_spent_writing-$prev_total_time_spent_writing)/($cur_total_ios_written-$prev_total_ios_written))/1000;
430
          }
431

    
432
          if($devices > 0){
433
            print $hash{$vm}{'label'} . "_rd.value " . $read_latency . "\n";
434
            print $hash{$vm}{'label'} . "_wr.value " . $write_latency . "\n";
435
          }
436
        }
437
      }
438
      print "\n";
439
    }
440

    
441
    #
442
    # Disk latency, second level
443
    #
444

    
445
    for my $vm (sort keys %hash) {
446
      my $devices=0;
447
      for my $device (keys %{$hash{$vm}{'devices'}{'block'}}){
448
        $devices++;
449
      }
450
      if($devices > 0){
451
        if($type eq "config"){
452
          print "multigraph libvirt_disk_latency.$hash{$vm}{'label'}\n";
453
          #print "graph_order rd wr\n";
454
          print "graph_title Disk latency per vbd on $vm in seconds\n";
455
          print "graph_args --base 1000\n";
456
          print "graph_vlabel read (-) / write (+)\n";
457
          print "graph_category virtualization\n";
458
          #print "graph_width 550\n";
459

    
460
          if(defined($hash{$vm}{'devices'}{'block'})){
461
            for my $device (keys %{$hash{$vm}{'devices'}{'block'}}){
462

    
463
              print $hash{$vm}{'label'} . "_" . $device . "_rd.label " . $device . "_rd\n";
464
              print $hash{$vm}{'label'} . "_" . $device . "_rd.info I/O latency in seconds on " . $hash{$vm}{'name'} . ":" . $device . "\n";
465
              print $hash{$vm}{'label'} . "_" . $device . "_rd.min 0\n";
466
              print $hash{$vm}{'label'} . "_" . $device . "_rd.draw LINE2\n";
467
              print $hash{$vm}{'label'} . "_" . $device . "_rd.graph no\n";
468

    
469
              print $hash{$vm}{'label'} . "_" . $device . "_wr.label " . $device . "\n";
470
              print $hash{$vm}{'label'} . "_" . $device . "_wr.info I/O latency in seconds on " . $hash{$vm}{'name'} . ":" . $device . "\n";
471
              print $hash{$vm}{'label'} . "_" . $device . "_wr.min 0\n";
472
              print $hash{$vm}{'label'} . "_" . $device . "_wr.draw LINE2\n";
473
              print $hash{$vm}{'label'} . "_" . $device . "_wr.negative " . $hash{$vm}{'label'} . "_" . $device . "_rd\n";
474
            }
475
            print "\n";
476
          }
477

    
478
        } elsif($type eq "fetch"){
479
          print "multigraph libvirt_disk_latency.$hash{$vm}{'label'}\n";
480
          if(defined($hash{$vm}{'devices'}{'block'}) && defined($prev_state_ref->{$vm}->{'devices'}->{'block'})){
481
            for my $device (keys %{$hash{$vm}{'devices'}{'block'}}){
482

    
483
              if(defined($prev_state_ref->{$vm}->{'devices'}->{'block'}->{$device})){
484

    
485
                for my $source_device (keys %{$hash{$vm}{'devices'}{'block'}{$device}{'source'}}){
486

    
487
                  my $prev_total_time_spent_writing=0;
488
                  my $prev_total_time_spent_reading=0;
489
                  my $prev_total_ios_read=0;
490
                  my $prev_total_ios_written=0;
491
                  my $cur_total_time_spent_writing=0;
492
                  my $cur_total_time_spent_reading=0;
493
                  my $cur_total_ios_read=0;
494
                  my $cur_total_ios_written=0;
495

    
496
                  for my $slave_device (keys %{$hash{$vm}{'devices'}{'block'}{$device}{'source'}{$source_device}{'slaves'}}){
497

    
498
                    my $prev_time_spent_writing=$prev_state_ref->{$vm}->{'devices'}->{'block'}->{$device}->{'source'}->{$source_device}->{'slaves'}->{$slave_device}->{'write_ticks'};
499
                    my $prev_time_spent_reading=$prev_state_ref->{$vm}->{'devices'}->{'block'}->{$device}->{'source'}->{$source_device}->{'slaves'}->{$slave_device}->{'read_ticks'};
500
                    my $prev_ios_read=$prev_state_ref->{$vm}->{'devices'}->{'block'}->{$device}->{'source'}->{$source_device}->{'slaves'}->{$slave_device}->{'read_ios'};
501
                    my $prev_ios_written=$prev_state_ref->{$vm}->{'devices'}->{'block'}->{$device}->{'source'}->{$source_device}->{'slaves'}->{$slave_device}->{'write_ios'};
502

    
503
                    my $cur_time_spent_writing=$hash{$vm}{'devices'}{'block'}{$device}{'source'}{$source_device}{'slaves'}{$slave_device}{'write_ticks'};
504
                    my $cur_time_spent_reading=$hash{$vm}{'devices'}{'block'}{$device}{'source'}{$source_device}{'slaves'}{$slave_device}{'read_ticks'};
505
                    my $cur_ios_read=$hash{$vm}{'devices'}{'block'}{$device}{'source'}{$source_device}{'slaves'}{$slave_device}{'read_ios'};
506
                    my $cur_ios_written=$hash{$vm}{'devices'}{'block'}{$device}{'source'}{$source_device}{'slaves'}{$slave_device}{'write_ios'};
507

    
508
                    $prev_total_time_spent_writing+=$prev_time_spent_writing;
509
                    $prev_total_time_spent_reading+=$prev_time_spent_reading;
510
                    $prev_total_ios_read+=$prev_ios_read;
511
                    $prev_total_ios_written+=$prev_ios_written;
512

    
513
                    $cur_total_time_spent_writing+=$cur_time_spent_writing;
514
                    $cur_total_time_spent_reading+=$cur_time_spent_reading;
515
                    $cur_total_ios_read+=$cur_ios_read;
516
                    $cur_total_ios_written+=$cur_ios_written;
517
                  }
518

    
519
                  my $read_latency=0;
520
                  my $write_latency=0;
521

    
522
                  if($prev_total_time_spent_reading > 0 && $prev_total_ios_read > 0 && ($cur_total_ios_read-$prev_total_ios_read) > 0){
523
                    $read_latency=(($cur_total_time_spent_reading-$prev_total_time_spent_reading)/($cur_total_ios_read-$prev_total_ios_read))/1000;
524
                  }
525

    
526
                  if($prev_total_time_spent_writing > 0 && $prev_total_ios_written > 0 && ($cur_total_ios_written-$prev_total_ios_written) > 0){
527
                    $write_latency=(($cur_total_time_spent_writing-$prev_total_time_spent_writing)/($cur_total_ios_written-$prev_total_ios_written))/1000;
528
                  }
529

    
530
                  print $hash{$vm}{'label'} . "_" . $device . "_rd.value " . $read_latency . "\n";
531
                  print $hash{$vm}{'label'} . "_" . $device . "_wr.value " . $write_latency . "\n";
532

    
533
                }
534
              }
535
            }
536
          }
537
        }
538
        print "\n";
539
      }
540
    }
541
  }
542

    
543
  if($show{'disk_traffic'} == 1){
544

    
545
    #
546
    # Disk used, top level
547
    #
548

    
549
    if($type eq "config"){
550
      print "multigraph libvirt_disk\n";
551
      #print "graph_order rd wr\n";
552
      print "graph_title Disk traffic per domain in bytes\n";
553
      print "graph_args --base 1000\n";
554
      print "graph_vlabel bytes read (-) / written (+) per \${graph_period}\n";
555
      print "graph_category virtualization\n";
556
      #print "graph_width 550\n";
557

    
558
      for my $vm (sort keys %hash) {
559
        my $devices=0;
560
        if(defined($hash{$vm}{'devices'}{'block'})){
561
          for my $device (keys %{$hash{$vm}{'devices'}{'block'}}){
562
            $devices++;
563
          }
564
        }
565

    
566
        if($devices > 0){
567
          if(defined($hash{$vm}{'devices'}{'block'})){
568

    
569
            print $hash{$vm}{'label'} . "_rd_bytes.label " . $hash{$vm}{'name'} . "\n";
570
            print $hash{$vm}{'label'} . "_rd_bytes.type COUNTER\n";
571
            print $hash{$vm}{'label'} . "_rd_bytes.info The number of bytes read by " . $hash{$vm}{'name'} . "\n";
572
            print $hash{$vm}{'label'} . "_rd_bytes.min 0\n";
573
            print $hash{$vm}{'label'} . "_rd_bytes.draw LINE2\n";
574
            print $hash{$vm}{'label'} . "_rd_bytes.graph no\n";
575

    
576
            print $hash{$vm}{'label'} . "_wr_bytes.label " . $hash{$vm}{'name'} . "\n";
577
            print $hash{$vm}{'label'} . "_wr_bytes.type COUNTER\n";
578
            print $hash{$vm}{'label'} . "_wr_bytes.info The number of bytes written by " . $hash{$vm}{'name'} . "\n";
579
            print $hash{$vm}{'label'} . "_wr_bytes.min 0\n";
580
            print $hash{$vm}{'label'} . "_wr_bytes.draw LINE2\n";
581
            print $hash{$vm}{'label'} . "_wr_bytes.negative " . $hash{$vm}{'label'} . "_rd_bytes\n";
582
          }
583
        }
584
      }
585
      print "\n";
586

    
587
    } elsif($type eq "fetch"){
588
      print "multigraph libvirt_disk\n";
589
      for my $vm (sort keys %hash) {
590
        if(defined($hash{$vm}{'devices'}{'block'})){
591
          my $total_read=0;
592
          my $total_write=0;
593
          for my $device (keys %{$hash{$vm}{'devices'}{'block'}}){
594
            $total_read+=$hash{$vm}{'devices'}{'block'}{$device}{'rd_bytes'};
595
            $total_write+=$hash{$vm}{'devices'}{'block'}{$device}{'wr_bytes'};
596
          }
597
          print $hash{$vm}{'label'} . "_rd_bytes.value " . $total_read . "\n";
598
          print $hash{$vm}{'label'} . "_wr_bytes.value " . $total_write . "\n";
599
        }
600
      }
601
      print "\n";
602
    }
603

    
604
    #
605
    # Disk used, second level
606
    #
607

    
608
    for my $vm (sort keys %hash) {
609
      my $devices=0;
610
      if(defined($hash{$vm}{'devices'}{'block'})){
611
        for my $device (keys %{$hash{$vm}{'devices'}{'block'}}){
612
          $devices++;
613
        }
614
      }
615

    
616
      if($devices > 0){
617
        if(defined($hash{$vm}{'devices'}{'block'})){
618
          if($type eq "config"){
619
            print "multigraph libvirt_disk.bytes_" . $hash{$vm}{'label'} . "\n";
620
            #print "graph_order rd wr\n";
621
            print "graph_title Disk traffic for " . $hash{$vm}{'name'} . "\n";
622
            print "graph_args --base 1000\n";
623
            print "graph_vlabel bytes read (-) / written (+) per \${graph_period}\n";
624
            print "graph_category virtualization\n";
625
            #print "graph_width 550\n";
626

    
627
            for my $device (keys %{$hash{$vm}{'devices'}{'block'}}){
628
              print $device . "_rd_bytes.label " . $device . "_rd\n";
629
              print $device . "_rd_bytes.type COUNTER\n";
630
              print $device . "_rd_bytes.info The number of bytes read by " . $hash{$vm}{'name'} . "\n";
631
              print $device . "_rd_bytes.min 0\n";
632
              print $device . "_rd_bytes.graph no\n";
633

    
634
              print $device . "_wr_bytes.label " . $device . "\n";
635
              print $device . "_wr_bytes.type COUNTER\n";
636
              print $device . "_wr_bytes.info The number of bytes written by " . $hash{$vm}{'name'} . "\n";
637
              print $device . "_wr_bytes.min 0\n";
638
              print $device . "_wr_bytes.draw LINE2\n";
639
              print $device . "_wr_bytes.negative " . $device . "_rd_bytes\n";
640
            }
641
            print "\n";
642

    
643
          } elsif($type eq "fetch"){
644
            print "multigraph libvirt_disk.bytes_" . $hash{$vm}{'label'} . "\n";
645
            if(defined($hash{$vm}{'devices'}{'block'})){
646
              for my $device (keys %{$hash{$vm}{'devices'}{'block'}}){
647
                print $device . "_rd_bytes.value " . $hash{$vm}{'devices'}{'block'}{$device}{'rd_bytes'} . "\n";
648
                print $device . "_wr_bytes.value " . $hash{$vm}{'devices'}{'block'}{$device}{'wr_bytes'} . "\n";
649
              }
650
            }
651
            print "\n";
652
          }
653
        }
654
      }
655
    }
656
  }
657

    
658
  #
659
  # Disk errors
660
  #
661
  #  errs -> Some kind of error count
662

    
663

    
664
  if($show{'disk_errors'} == 1){
665

    
666
    #
667
    # Disk errors, top level
668
    #
669

    
670
    if($type eq "config"){
671
      print "multigraph libvirt_disk_errs\n";
672
      print "graph_title Disk errors per domain\n";
673
      print "graph_args --base 1000\n";
674
      print "graph_category virtualization\n";
675

    
676
      for my $vm (sort keys %hash) {
677
        if(defined($hash{$vm}{'devices'}{'block'})){
678
          my $devices=0;
679
          if(defined($hash{$vm}{'devices'}{'block'})){
680
            for my $device (keys %{$hash{$vm}{'devices'}{'block'}}){
681
              $devices++;
682
            }
683
          }
684
          if($devices > 0){
685
            print $hash{$vm}{'label'} . "_errs.label " . $hash{$vm}{'name'} . "\n";
686
            print $hash{$vm}{'label'} . "_errs.type COUNTER\n";
687
            print $hash{$vm}{'label'} . "_errs.info The number of errors by " . $hash{$vm}{'name'} . "\n";
688
            print $hash{$vm}{'label'} . "_errs.min 0\n";
689
            print $hash{$vm}{'label'} . "_errs.draw LINE2\n";
690
          }
691
        }
692
      }
693
      print "\n";
694

    
695
    } elsif($type eq "fetch"){
696
      print "multigraph libvirt_disk_errs\n";
697
      for my $vm (sort keys %hash) {
698
        if(defined($hash{$vm}{'devices'}{'block'})){
699
          my $errs=0;
700
          for my $device (keys %{$hash{$vm}{'devices'}{'block'}}){
701
            $errs+=$hash{$vm}{'devices'}{'block'}{$device}{'errs'};
702
          }
703
          print $hash{$vm}{'label'} . "_errs.value " . $errs . "\n";
704
        }
705
      }
706
      print "\n";
707
    }
708

    
709
    #
710
    # Disk errors, second level
711
    #
712

    
713
    for my $vm (sort keys %hash) {
714
      my $devices=0;
715
      if(defined($hash{$vm}{'devices'}{'block'})){
716
        for my $device (keys %{$hash{$vm}{'devices'}{'block'}}){
717
          $devices++;
718
        }
719
      }
720
      if($devices > 0){
721
        if(defined($hash{$vm}{'devices'}{'block'})){
722
          if($type eq "config"){
723
            print "multigraph libvirt_disk_errs." . $hash{$vm}{'label'} . "\n";
724
            print "graph_title Disk errors for " . $hash{$vm}{'name'} . "\n";
725
            print "graph_args --base 1000\n";
726
            print "graph_category virtualization\n";
727

    
728
            for my $device (keys %{$hash{$vm}{'devices'}{'block'}}){
729

    
730
              print $device . "_errs.label " . $device . "\n";
731
              print $device . "_errs.type COUNTER\n";
732
              print $device . "_errs.info The number of errors by " . $hash{$vm}{'name'} . " on defice " . $device . "\n";
733
              print $device . "_errs.min 0\n";
734
              print $device . "_errs.draw LINE2\n";
735
            }
736
            print "\n";
737

    
738
          } elsif($type eq "fetch"){
739
            print "multigraph libvirt_disk_errs." . $hash{$vm}{'label'} . "\n";
740
            if(defined($hash{$vm}{'devices'}{'block'})){
741
              for my $device (keys %{$hash{$vm}{'devices'}{'block'}}){
742
                print $device . "_errs.value " . $hash{$vm}{'devices'}{'block'}{$device}{'errs'} . "\n";
743
              }
744
            }
745
            print "\n";
746
          }
747
        }
748
      }
749
    }
750
  }
751

    
752
  #
753
  # Network used
754
  #
755

    
756
  if($show{'network_traffic'} == 1){
757

    
758
    #
759
    # Network used, top level
760
    #
761

    
762
    if($type eq "config"){
763
      print "multigraph libvirt_network\n";
764
      print "graph_title Network traffic per domain in bytes\n";
765
      print "graph_args --base 1000\n";
766
      print "graph_vlabel Bytes in (-) / out (+) per \${graph_period}\n";
767
      print "graph_category virtualization\n";
768
      #print "graph_width 550\n";
769

    
770
      for my $vm (sort keys %hash) {
771
        if(defined($hash{$vm}{'devices'}{'network'})){
772

    
773
          print $hash{$vm}{'label'} . "_rx_bytes.label " . $hash{$vm}{'name'} . "_rx\n";
774
          print $hash{$vm}{'label'} . "_rx_bytes.type DERIVE\n";
775
          print $hash{$vm}{'label'} . "_rx_bytes.info The number of bytes read by " . $hash{$vm}{'name'} . " in total.\n";
776
          print $hash{$vm}{'label'} . "_rx_bytes.min 0\n";
777
          print $hash{$vm}{'label'} . "_rx_bytes.draw LINE2\n";
778
          print $hash{$vm}{'label'} . "_rx_bytes.graph no\n";
779
          #print $hash{$vm}{'label'} . "_rx_bytes.cdef " . $hash{$vm}{'label'} . "_rx_bytes,8,*\n";
780

    
781
          print $hash{$vm}{'label'} . "_tx_bytes.label " . $hash{$vm}{'name'} . "\n";
782
          print $hash{$vm}{'label'} . "_tx_bytes.type DERIVE\n";
783
          print $hash{$vm}{'label'} . "_tx_bytes.info The number of bytes written by " . $hash{$vm}{'name'} . " in total.\n";
784
          print $hash{$vm}{'label'} . "_tx_bytes.min 0\n";
785
          print $hash{$vm}{'label'} . "_tx_bytes.draw LINE2\n";
786
          print $hash{$vm}{'label'} . "_tx_bytes.negative " . $hash{$vm}{'label'} . "_rx_bytes\n";
787
          #print $hash{$vm}{'label'} . "_tx_bytes.cdef " . $hash{$vm}{'label'} . "_tx_bytes,8,*\n";
788
        }
789
      }
790
      print "\n";
791

    
792
    } elsif($type eq "fetch"){
793
      print "multigraph libvirt_network\n";
794
      for my $vm (sort keys %hash) {
795
        if(defined($hash{$vm}{'devices'}{'network'})){
796
          my $read=0;
797
          my $write=0;
798
          for my $vif (keys %{$hash{$vm}{'devices'}{'network'}}){
799
            $read+=$hash{$vm}{'devices'}{'network'}{$vif}{'rx_bytes'};
800
            $write+=$hash{$vm}{'devices'}{'network'}{$vif}{'tx_bytes'};
801
          }
802
          print $hash{$vm}{'label'} . "_rx_bytes.value " . $read . "\n";
803
          print $hash{$vm}{'label'} . "_tx_bytes.value " . $write . "\n";
804
        }
805
      }
806
      print "\n";
807
    }
808

    
809
    #
810
    # Network used, second level
811
    #
812

    
813
    for my $vm (sort keys %hash) {
814
      if(defined($hash{$vm}{'devices'}{'network'})){
815
        if($type eq "config"){
816
          print "multigraph libvirt_network.bytes_" . $hash{$vm}{'label'} . "\n";
817
          print "graph_title Network traffic for " . $vm . "\n";
818
          print "graph_args --base 1000\n";
819
          print "graph_vlabel Bits in (-) / out (+) per \${graph_period}\n";
820
          print "graph_category virtualization\n";
821
          #print "graph_width 550\n";
822

    
823
          for my $vif (keys %{$hash{$vm}{'devices'}{'network'}}){
824
            my $vif_id=$hash{$vm}{'devices'}{'network'}{$vif}{'vif_id'};
825

    
826
            print "rx_bytes_" . $vif_id . ".label " . $vif . "_rx\n";
827
            print "rx_bytes_" . $vif_id . ".type DERIVE\n";
828
            print "rx_bytes_" . $vif_id . ".info The number of bytes read by " . $hash{$vm}{'name'} . "\n";
829
            print "rx_bytes_" . $vif_id . ".min 0\n";
830
            print "rx_bytes_" . $vif_id . ".graph no\n";
831
            print "rx_bytes_" . $vif_id . ".cdef rx_bytes_" . $vif_id . ",8,*\n";
832

    
833
            print "tx_bytes_" . $vif_id . ".label " . $vif . "\n";
834
            print "tx_bytes_" . $vif_id . ".type DERIVE\n";
835
            print "tx_bytes_" . $vif_id . ".info The number of bits written by " . $hash{$vm}{'name'} . "\n";
836
            print "tx_bytes_" . $vif_id . ".min 0\n";
837
            print "tx_bytes_" . $vif_id . ".draw LINE2\n";
838
            print "tx_bytes_" . $vif_id . ".negative rx_bytes_" . $vif_id . "\n";
839
            print "tx_bytes_" . $vif_id . ".cdef tx_bytes_" . $vif_id . ",8,*\n";
840
          }
841
          print "\n";
842

    
843
        } elsif($type eq "fetch"){
844
          print "multigraph libvirt_network.bytes_" . $hash{$vm}{'label'} . "\n";
845
          for my $vif (keys %{$hash{$vm}{'devices'}{'network'}}){
846
            my $vif_id=$hash{$vm}{'devices'}{'network'}{$vif}{'vif_id'};
847
            print "rx_bytes_" . $vif_id . ".value " . $hash{$vm}{'devices'}{'network'}{$vif}{'rx_bytes'} . "\n";
848
            print "tx_bytes_" . $vif_id . ".value " . $hash{$vm}{'devices'}{'network'}{$vif}{'tx_bytes'} . "\n";
849
          }
850
          print "\n";
851
        }
852
      }
853
    }
854
  }
855

    
856
  #
857
  # Network drops and errors
858
  #
859
  #  rx_drop -> Total packets drop at reception
860
  #  tx_drop -> Total packets dropped at transmission.
861

    
862
  if($show{'network_drops'} == 1){
863

    
864
    #
865
    # Network drops, top level
866
    #
867

    
868
    if($type eq "config"){
869
      print "multigraph libvirt_network_drop\n";
870
      print "graph_title Network packets dropped per domain\n";
871
      print "graph_args --base 1000\n";
872
      print "graph_vlabel Count in (-) / out (+) per \${graph_period}\n";
873
      print "graph_category virtualization\n";
874
      #print "graph_width 550\n";
875

    
876
      for my $vm (sort keys %hash) {
877
        if(defined($hash{$vm}{'devices'}{'network'})){
878

    
879
          print $hash{$vm}{'label'} . "_rx_drop.label " . $hash{$vm}{'name'} . "_rx\n";
880
          print $hash{$vm}{'label'} . "_rx_drop.type DERIVE\n";
881
          print $hash{$vm}{'label'} . "_rx_drop.info The number of packets dropped at reception by " . $hash{$vm}{'name'} . "\n";
882
          print $hash{$vm}{'label'} . "_rx_drop.min 0\n";
883
          print $hash{$vm}{'label'} . "_rx_drop.draw LINE2\n";
884
          print $hash{$vm}{'label'} . "_rx_drop.graph no\n";
885

    
886
          print $hash{$vm}{'label'} . "_tx_drop.label " . $hash{$vm}{'name'} . "\n";
887
          print $hash{$vm}{'label'} . "_tx_drop.type DERIVE\n";
888
          print $hash{$vm}{'label'} . "_tx_drop.info The number of packets dropped at transmission by " . $hash{$vm}{'name'} . "\n";
889
          print $hash{$vm}{'label'} . "_tx_drop.min 0\n";
890
          print $hash{$vm}{'label'} . "_tx_drop.draw LINE2\n";
891
          print $hash{$vm}{'label'} . "_tx_drop.negative " . $hash{$vm}{'label'} . "_rx_drop\n";
892
        }
893
      }
894
      print "\n";
895

    
896
    } elsif($type eq "fetch"){
897
      print "multigraph libvirt_network_drop\n";
898
      for my $vm (sort keys %hash) {
899
        if(defined($hash{$vm}{'devices'}{'network'})){
900
          my $rx_drop=0;
901
          my $tx_drop=0;
902
          for my $vif (keys %{$hash{$vm}{'devices'}{'network'}}){
903
            $rx_drop+=$hash{$vm}{'devices'}{'network'}{$vif}{'rx_drop'};
904
            $tx_drop+=$hash{$vm}{'devices'}{'network'}{$vif}{'tx_drop'};
905
          }
906

    
907
          print $hash{$vm}{'label'} . "_rx_drop.value " . $rx_drop . "\n";
908
          print $hash{$vm}{'label'} . "_tx_drop.value " . $tx_drop . "\n";
909

    
910
        }
911
      }
912
      print "\n";
913
    }
914

    
915
    #
916
    # Network drops, second level
917
    #
918

    
919
    for my $vm (sort keys %hash) {
920
      if(defined($hash{$vm}{'devices'}{'network'})){
921
        if($type eq "config"){
922
          print "multigraph libvirt_network_drop." . $hash{$vm}{'label'} . "\n";
923
          print "graph_title Network packeds dropped by " . $vm . "\n";
924
          print "graph_args --base 1000\n";
925
          print "graph_vlabel Count in (-) / out (+) per \${graph_period}\n";
926
          print "graph_category virtualization\n";
927
          #print "graph_width 550\n";
928

    
929
          for my $vif (keys %{$hash{$vm}{'devices'}{'network'}}){
930
            my $vif_id=$hash{$vm}{'devices'}{'network'}{$vif}{'vif_id'};
931

    
932
            print "rx_drop_" . $vif_id . ".label " . $vif . "_rx\n";
933
            print "rx_drop_" . $vif_id . ".type DERIVE\n";
934
            print "rx_drop_" . $vif_id . ".info The number of packets dropped by " . $hash{$vm}{'name'} . ", nic " . $vif_id . "\n";
935
            print "rx_drop_" . $vif_id . ".min 0\n";
936
            print "rx_drop_" . $vif_id . ".graph no\n";
937

    
938
            print "tx_drop_" . $vif_id . ".label " . $vif . "\n";
939
            print "tx_drop_" . $vif_id . ".type DERIVE\n";
940
            print "tx_drop_" . $vif_id . ".info The number of packets dropped by " . $hash{$vm}{'name'} . ", nic " . $vif_id . "\n";
941
            print "tx_drop_" . $vif_id . ".min 0\n";
942
            print "tx_drop_" . $vif_id . ".draw LINE2\n";
943
            print "tx_drop_" . $vif_id . ".negative rx_drop_" . $vif_id . "\n";
944
          }
945
          print "\n";
946

    
947
        } elsif($type eq "fetch"){
948
          print "multigraph libvirt_network_drop." . $hash{$vm}{'label'} . "\n";
949
          for my $vif (keys %{$hash{$vm}{'devices'}{'network'}}){
950
            my $vif_id=$hash{$vm}{'devices'}{'network'}{$vif}{'vif_id'};
951
            print "rx_drop_" . $vif_id . ".value " . $hash{$vm}{'devices'}{'network'}{$vif}{'rx_drop'} . "\n";
952
            print "tx_drop_" . $vif_id . ".value " . $hash{$vm}{'devices'}{'network'}{$vif}{'tx_drop'} . "\n";
953
          }
954
          print "\n";
955
        }
956
      }
957
    }
958
  }
959

    
960
  #
961
  # CPU used
962
  #
963

    
964
  if($show{'cpu_used'} == 1){
965

    
966
    #
967
    # CPU used, top level
968
    #
969

    
970
    if($type eq "config"){
971
      print "multigraph libvirt_cpu\n";
972
      print "graph_title Cpu time used per domain in percent\n";
973
      print "graph_args --base 1000 -r --lower-limit 0 --upper-limit 100\n";
974
      print "graph_category virtualization\n";
975
      #print "graph_width 550\n";
976

    
977
      my $draw="AREA";
978
      for my $vm (sort keys %hash) {
979
        print $hash{$vm}{'label'} . "_time.label " . $hash{$vm}{'name'} . "\n";
980
        print $hash{$vm}{'label'} . "_time.type DERIVE\n";
981
        print $hash{$vm}{'label'} . "_time.info The cpu time used by " . $hash{$vm}{'name'} . " in percent of the total available cpu time on the physical node.\n";
982
        print $hash{$vm}{'label'} . "_time.min 0\n";
983
        print $hash{$vm}{'label'} . "_time.draw $draw\n";
984
        $draw="STACK" if $draw eq "AREA";
985
      }
986
      print "\n";
987

    
988
    } elsif($type eq "fetch"){
989
      print "multigraph libvirt_cpu\n";
990
      for my $vm (sort keys %hash) {
991
        print $hash{$vm}{'label'} . "_time.value " . $hash{$vm}{'info'}{'cpuPercentage'} . "\n";
992
      }
993
      print "\n";
994
    }
995

    
996
    #
997
    # CPU used, second level (pr virtual machine)
998
    #
999

    
1000
    if($type eq "config"){
1001
      for my $vm (sort keys %hash) {
1002
        print "multigraph libvirt_cpu.vm_" . $hash{$vm}{'label'} . "\n";
1003
        print "graph_title Cpu time used by " . $hash{$vm}{'name'} . " in percent\n";
1004
        print "graph_args --base 1000\n";
1005
        print "graph_category virtualization\n";
1006
        #print "graph_width 550\n";
1007

    
1008
        print "time.label " . $hash{$vm}{'name'} . " (" . $hash{$vm}{'type'} . ")\n";
1009
        print "time.type DERIVE\n";
1010
        print "time.info The cpu time used by " . $hash{$vm}{'name'} . " in percent of the total available cpu time on the physical node. This domain has access to " . $hash{$vm}{'info'}{'nrVirtCpu'} . " VCPU(s) now, and $hash{$vm}{'maxvcpus'} at maximum. The scheduler for this domain is " . $hash{$vm}{'scheduler'} . ".\n";
1011
        print "time.min 0\n";
1012
        print "time.draw AREA\n";
1013
        print "\n";
1014
      }
1015

    
1016
    } elsif($type eq "fetch"){
1017
      for my $vm (sort keys %hash) {
1018
        print "multigraph libvirt_cpu.vm_" . $hash{$vm}{'label'} . "\n";
1019
        print "time.value " . $hash{$vm}{'info'}{'cpuPercentage'} . "\n";
1020
        print "\n";
1021
      }
1022
    }
1023
  }
1024

    
1025
  #
1026
  # Memory allocation
1027
  #
1028

    
1029
  if($show{'memory_allocated'} == 1){
1030

    
1031
    #
1032
    # Memory allocation, top level
1033
    #
1034

    
1035
    if($type eq "config"){
1036
      print "multigraph libvirt_mem\n";
1037
      print "graph_title Memory allocated per domain\n";
1038
      print "graph_args --base 1000\n";
1039
      print "graph_category virtualization\n";
1040
      #print "graph_width 550\n";
1041

    
1042
      my $draw="AREA";
1043
      for my $vm (sort keys %hash) {
1044
        print $hash{$vm}{'label'} . "_alloc.label " . $hash{$vm}{'name'} . "\n";
1045
        print $hash{$vm}{'label'} . "_alloc.type GAUGE\n";
1046
        print $hash{$vm}{'label'} . "_alloc.info Memory allocation per domain.\n";
1047
        print $hash{$vm}{'label'} . "_alloc.min 0\n";
1048
        print $hash{$vm}{'label'} . "_alloc.draw $draw\n";
1049
        $draw="STACK" if $draw eq "AREA";
1050
      }
1051
      print "\n";
1052

    
1053
    } elsif($type eq "fetch"){
1054
      print "multigraph libvirt_mem\n";
1055
      for my $vm (sort keys %hash) {
1056
        print $hash{$vm}{'label'} . "_alloc.value " . $hash{$vm}{'info'}{'memory_bytes'} . "\n";
1057
      }
1058
      print "\n";
1059
    }
1060

    
1061
    #
1062
    # Memory allocated, second level (pr virtual machine)
1063
    #
1064

    
1065
    if($type eq "config"){
1066
      for my $vm (sort keys %hash) {
1067
        print "multigraph libvirt_mem.vm_" . $hash{$vm}{'label'} . "\n";
1068
        print "graph_title Memory allocated to " . $hash{$vm}{'name'} . "\n";
1069
        print "graph_args --base 1000\n";
1070
        print "graph_category virtualization\n";
1071
        #print "graph_width 550\n";
1072

    
1073
        print "mem.label " . $hash{$vm}{'name'} . " (" . $hash{$vm}{'type'} . ")\n";
1074
        print "mem.type GAUGE\n";
1075
        print "mem.info Amount of memory allocated to " . $hash{$vm}{'name'} . ". The maximum amount of memory for this domain is " . $hash{$vm}{'maxmem'}/1024 . " MB.\n";
1076
        print "mem.min 0\n";
1077
        print "mem.draw AREA\n";
1078
        print "\n";
1079
      }
1080

    
1081
    } elsif($type eq "fetch"){
1082
      for my $vm (sort keys %hash) {
1083
        print "multigraph libvirt_mem.vm_" . $hash{$vm}{'label'} . "\n";
1084
        print "mem.value " . $hash{$vm}{'info'}{'memory_bytes'} . "\n";
1085
        print "\n";
1086
      }
1087
    }
1088
  }
1089
}
1090

    
1091
sub clean_label() {
1092
  my $label=shift;
1093
  $label =~ s/^[^A-Za-z_]/_/;
1094
  $label =~ s/[^A-Za-z0-9_]/_/g;
1095
  return $label;
1096
}
1097

    
1098
sub connect {
1099
  my $vmm = Sys::Virt->new(address => $address,
1100
                           auth => 1,
1101
                           credlist => [
1102
                             Sys::Virt::CRED_AUTHNAME,
1103
                             Sys::Virt::CRED_PASSPHRASE,
1104
                           ],
1105
                           callback =>
1106
         sub {
1107
               my $creds = shift;
1108

    
1109
               foreach my $cred (@{$creds}) {
1110
                  if ($cred->{type} == Sys::Virt::CRED_AUTHNAME) {
1111
                      $cred->{result} = $username;
1112
                  }
1113
                  if ($cred->{type} == Sys::Virt::CRED_PASSPHRASE) {
1114
                      $cred->{result} = $password;
1115
                  }
1116
               }
1117
               return 0;
1118
         });
1119
  return $vmm;
1120
}
1121

    
1122
sub autoconf {
1123
  my $vmm=&connect();
1124
  if($vmm){
1125
    my $node = $vmm->get_node_info();
1126
    if($node){
1127
      print "yes\n";
1128
      exit(0);
1129
    } else {
1130
      print "no (Unable to fetch node info)\n";
1131
      exit(1);
1132
    }
1133
  } else {
1134
    print "no (Unable to connect to libvirt)\n";
1135
    exit(1);
1136
  }
1137

    
1138
}
1139

    
1140
#
1141
# Function to extract information from xml and return a hash with the necessary information.
1142
# The logic is really ugly and should be improved.
1143
#
1144
sub parse_xml {
1145
  my $raw_xml=shift;
1146
  my %res=();
1147

    
1148
  use XML::Simple qw(:strict);
1149
  my $xs=XML::Simple->new;
1150
  my @a=$xs->XMLin($raw_xml,ForceArray => 1, KeyAttr => 'target');
1151

    
1152
  for (my $i=0 ; $i < scalar(@a) ; $i++){
1153
    # Hack to extract disk information and put it into the hash
1154
    # TODO: Improve
1155
    if(defined($a[$i]{'devices'}[0]{'disk'})){
1156

    
1157
      my $teller = 0;
1158
      my $fortsette = 1;
1159

    
1160
      while($fortsette){
1161
          if(  $a[$i]{'devices'}[0]{'disk'}[$teller] ){
1162
              my $type=$a[$i]{'devices'}[0]{'disk'}[$teller]{'type'};
1163
              my $source_dev=$a[$i]{'devices'}[0]{'disk'}[$teller]{'source'}[0]{'dev'};
1164
              my $target_bus=$a[$i]{'devices'}[0]{'disk'}[$teller]{'target'}[0]{'bus'};
1165
              my $target_dev=$a[$i]{'devices'}[0]{'disk'}[$teller]{'target'}[0]{'dev'};
1166

    
1167
              $res{'devices'}{'disk'}{$type}{$target_dev}{'source'}=$source_dev;
1168
              $res{'devices'}{'disk'}{$type}{$target_dev}{'bus'}=$target_bus;
1169
              $res{'devices'}{'disk'}{$type}{$target_dev}{'type'}=$type;
1170

    
1171
              $teller++;
1172
          }
1173
          else{
1174
              $fortsette = 0;
1175
          }
1176
      }
1177
    }
1178

    
1179
    # Hack to extract network information and put it into the hash
1180
    # TODO: Improve
1181
    if(defined($a[$i]{'devices'}[0]{'interface'})){
1182

    
1183
      my $teller = 0;
1184
      my $fortsette = 1;
1185

    
1186
      while($fortsette){
1187
          if(  $a[$i]{'devices'}[0]{'interface'}[$teller] ){
1188
              my $type=$a[$i]{'devices'}[0]{'interface'}[$teller]{'type'};
1189
              my $target=$a[$i]{'devices'}[0]{'interface'}[$teller]{'target'}[0]{'dev'};
1190
              my $bridge=$a[$i]{'devices'}[0]{'interface'}[$teller]{'source'}[0]{'bridge'};;
1191
              my $mac=$a[$i]{'devices'}[0]{'interface'}[$teller]{'mac'}[0]{'address'};;
1192

    
1193
              $res{'devices'}{'interface'}{$type}{$target}{'target'}=$target;
1194
              $res{'devices'}{'interface'}{$type}{$target}{'mac'}=$mac;
1195
              $res{'devices'}{'interface'}{$type}{$target}{'bridge'}=$bridge;
1196
              $teller++;
1197
          }
1198
          else{
1199
              $fortsette = 0;
1200
          }
1201
      }
1202
    }
1203
  }
1204

    
1205
  return \%res;
1206
}
1207

    
1208
sub read_diskstats{
1209
  my $dev=shift;
1210

    
1211
  my %res=();
1212

    
1213
  # Verify that $dev is a block device.
1214
  if(-b $dev){
1215
    # Read minor and major number
1216
    my $rdev = stat($dev)->rdev;
1217
    $res{'major'} = $rdev >> 8;
1218
    $res{'minor'} = $rdev & 0xff;
1219

    
1220
    # If major numer is 253, then proceed as dm-device
1221
    if($res{'major'} == 253){
1222

    
1223
      # check that the directory /sys/block/dm-$minor/ exists with a /slaves/ sub directory
1224
      if(-d "/sys/block/dm-" . $res{'minor'} . "/"){
1225
        if(-d "/sys/block/dm-" . $res{'minor'} . "/slaves/"){
1226

    
1227
          # see if /sys/block/dm-$minor/slaves/ has any slaves
1228
          opendir(DIR, "/sys/block/dm-" . $res{'minor'} . "/slaves/");
1229
          while(my $slave = readdir(DIR)){
1230

    
1231
            # Exclude directories (. and ..)
1232
            if($slave !~ m/^\.+$/){
1233

    
1234
              # Check if we have /sys/block/dm-$minor/slaves/$slave/stat
1235
              if(-f "/sys/block/dm-" . $res{'minor'} . "/slaves/" . $slave . "/stat"){
1236
                # Read the stat-file
1237
                open(FILE, "</sys/block/dm-" . $res{'minor'} . "/slaves/" . $slave . "/stat");
1238
                while (my $line = <FILE>) {
1239
                  #               1       2       3       4       5       6       7       8       9      10      11
1240
                  if($line =~ m/(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/){
1241

    
1242
                    # Name            units         description
1243
                    # ----            -----         -----------
1244
                    # read I/Os       requests      number of read I/Os processed
1245
                    # read merges     requests      number of read I/Os merged with in-queue I/O
1246
                    # read sectors    sectors       number of sectors read
1247
                    # read ticks      milliseconds  total wait time for read requests
1248
                    # write I/Os      requests      number of write I/Os processed
1249
                    # write merges    requests      number of write I/Os merged with in-queue I/O
1250
                    # write sectors   sectors       number of sectors written
1251
                    # write ticks     milliseconds  total wait time for write requests
1252
                    # in_flight       requests      number of I/Os currently in flight
1253
                    # io_ticks        milliseconds  total time this block device has been active
1254
                    # time_in_queue   milliseconds  total wait time for all requests
1255
                    #
1256
                    # Documentation fetched from http://www.mjmwired.net/kernel/Documentation/block/stat.txt
1257

    
1258
                    # store the output in the hash
1259
                    $res{'slaves'}{$slave}{'read_ios'}=$1;
1260
                    $res{'slaves'}{$slave}{'read_merges'}=$2;
1261
                    $res{'slaves'}{$slave}{'read_sectors'}=$3;
1262
                    $res{'slaves'}{$slave}{'read_ticks'}=$4;
1263
                    $res{'slaves'}{$slave}{'write_ios'}=$5;
1264
                    $res{'slaves'}{$slave}{'write_merges'}=$6;
1265
                    $res{'slaves'}{$slave}{'write_sectors'}=$7;
1266
                    $res{'slaves'}{$slave}{'write_ticks'}=$8;
1267
                    $res{'slaves'}{$slave}{'in_flight'}=$9;
1268
                    $res{'slaves'}{$slave}{'io_ticks'}=$10;
1269
                    $res{'slaves'}{$slave}{'time_in_queue'}=$11;
1270
                  }
1271
                }
1272
                close(FILE);
1273
              }
1274
            }
1275
          }
1276
          close(DIR);
1277
        }
1278
      }
1279
    }
1280
  }
1281

    
1282
  return \%res;
1283
}
1284

    
1285
# Return the timestamp of a file
1286
sub get_prev_time(){
1287
  my $tmpfile=shift;
1288

    
1289
  my $time=-1;
1290

    
1291
  if(-r $tmpfile){
1292
    $time = stat($tmpfile)->mtime;
1293
  }
1294

    
1295
  return $time;
1296
}
1297

    
1298
init();
1299

    
1300
# vim:syntax=perl