01e6104dfeca8ff835c40e6c73c13cedac151328
[gnt-info] / gnt-monitor
1 #!/usr/bin/perl
2 use warnings;
3 use strict;
4 use autodie;
5 use POSIX;
6
7 my $DEBUG = $ENV{DEBUG} || 0;
8 my $INFLUX = 'http://10.60.0.89:8186/write';
9 my $INTERVAL = $ENV{INTERVAL} || 1;
10
11 my $node = `hostname -s`;
12 chomp $node;
13
14 use Data::Dump;
15 sub XXX { $DEBUG ? warn "XXX ",Data::Dump::dump( @_ ) : {} };
16
17 my $stat;
18 my $last;
19
20 while(1) {
21
22 foreach my $instance ( glob '/var/run/ganeti/kvm-hypervisor/pid/*' ) {
23
24         open(my $fh, '<', $instance);
25         my $pid = <$fh>; chomp $pid;
26
27         $instance =~ s{^.*/}{};
28
29         my $vcpu = $last->{$instance}->{vcpu};
30
31         if ( ! $vcpu ) {
32                 foreach my $fd ( glob "/proc/$pid/fd/*" ) {
33                         $vcpu++ if -l $fd && readlink($fd) =~ m/kvm-vcpu/;
34                 }
35
36                 $last->{$instance}->{vcpu} = $vcpu;
37         }
38
39         # https://www.kernel.org/doc/Documentation/filesystems/proc.txt
40         open($fh, '<', "/proc/$pid/stat");
41         my $line = <$fh>; chomp $line;
42         my $gtime = (split(/\s+/,$line))[42]; # guest time of the task in jiffies
43
44         if ( my $last_gtime = $last->{$instance}->{gtime} ) {
45                 my $clock_ticks = POSIX::sysconf( &POSIX::_SC_CLK_TCK ); # clock ticks per second
46
47                 my $cpu = ( ( $gtime - $last_gtime ) * 100 ) / ( $clock_ticks * $vcpu );
48                 $stat->{$instance}->{cpu} = $cpu;
49         }
50
51         $last->{$instance}->{gtime} = $gtime;
52 }
53                 
54
55 foreach my $glob ( glob '/var/run/ganeti/instance-disks/*' ) {
56         my ( $instance, $disk ) = split(/:/,$glob,2);
57         my $dev = readlink $glob;
58         $instance =~ s{^.*/}{};
59         $dev =~ s{^.*dev/}{};
60         open( my $fh, '<', "/sys/class/block/$dev/stat" );
61         my $v = <$fh>; chomp $v; $v =~ s/^\s+//;
62         my @s = split(/\s+/, $v );
63         # https://www.kernel.org/doc/Documentation/block/stat.txt
64         my $d = {
65                 read_io => $s[0],
66                 read_bytes => $s[2] * 512,
67                 read_wait => $s[3],
68                 write_io => $s[4],
69                 write_bytes => $s[6] * 512,
70                 write_wait => $s[7],
71         };
72         if ( my $l = $last->{$instance}->{disk}->[$disk] ) {
73                 my $delta;
74                 $delta->{$_} = $d->{$_} - $l->{$_} foreach keys %$d;
75                 $stat->{$instance}->{disk}->[$disk] = $delta;
76                 $stat->{$instance}->{disk}->[$disk]->{dev} = $dev;
77                 $stat->{$instance}->{disk}->[$disk]->{disk} = $disk;
78         }
79         $last->{$instance}->{disk}->[$disk] = $d;
80
81 }
82
83 foreach my $instance ( glob '/var/run/ganeti/kvm-hypervisor/nic/*' ) {
84         foreach my $nic ( glob "$instance/*" ) {
85                 open(my $fh, '<', $nic);
86                 my $dev = <$fh>;
87                 $nic =~ s{^.*/}{};
88                 $instance =~ s{^.*/}{};
89                 my $vlan = readlink "/sys/class/net/$dev/master";
90                 $vlan =~ s/^.*br/br/;
91
92                 my $d;
93
94                 foreach my $f (qw( rx_bytes tx_bytes rx_packets tx_packets )) {
95                         open( my $fh, '<', "/sys/class/net/$dev/statistics/$f" );
96                         my $v = <$fh>; chomp $v;
97                         $d->{$f} = $v;
98                 }
99                 if ( my $l = $last->{$instance}->{nic}->[$nic] ) {
100                         $stat->{$instance}->{nic}->[$nic]->{$_} = $d->{$_} - $l->{$_} foreach keys %$d;
101                         $stat->{$instance}->{nic}->[$nic]->{dev} = $dev;
102                         $stat->{$instance}->{nic}->[$nic]->{vlan} = $vlan;
103                 }
104                 $last->{$instance}->{nic}->[$nic] = $d;
105
106         }
107 }
108
109 XXX $stat;
110 #XXX $last;
111
112 open(my $fh, '>', '/dev/shm/ganeti-monitor.influx');
113
114 sub dump4influx {
115         my $hash = shift;
116         my $d = Data::Dump::dump( $hash );
117         $d =~ s/[\s\r\n]+//g;
118         $d =~ s/[\Q[]{}>\E]//g;
119         $d =~ s/=(\d+),/=$1i,/g;
120         $d =~ s/,+$//;
121         return $d;
122 }
123
124 foreach my $instance ( keys %$stat ) {
125         print $fh qq{cpu,node="$node",instance="$instance" cpu=}, $stat->{$instance}->{cpu}, "\n";
126
127         foreach my $disk ( @{ $stat->{$instance}->{disk} } ) {
128                 print $fh qq{disk,node="$node",instance="$instance" },dump4influx( $disk ), "\n";
129         }
130
131         foreach my $nic ( @{ $stat->{$instance}->{nic} } ) {
132                 print $fh qq{nic,node="$node",instance="$instance" },dump4influx( $nic ), "\n";
133         }
134
135 }
136
137 close($fh);
138
139 system q{curl -i -XPOST 'http://10.80.3.89:8086/write?db=ganeti' --data-binary '@/dev/shm/ganeti-monitor.influx'};
140
141
142 sleep $INTERVAL;
143 } #/while
144