7 my $DEBUG = $ENV{DEBUG} || 0;
8 my $INFLUX = 'http://10.60.0.89:8186/write';
9 my $INTERVAL = $ENV{INTERVAL} || 1;
11 my $node = `hostname -s`;
15 sub XXX { $DEBUG ? warn "XXX ",Data::Dump::dump( @_ ) : {} };
24 foreach my $instance ( glob '/var/run/ganeti/kvm-hypervisor/pid/*' ) {
26 open(my $fh, '<', $instance);
27 my $pid = <$fh>; chomp $pid;
29 $instance =~ s{^.*/}{};
31 if ( ! -d "/proc/$pid" ) {
37 my $vcpu = $last->{$instance}->{vcpu};
40 foreach my $fd ( glob "/proc/$pid/fd/*" ) {
41 $vcpu++ if -l $fd && readlink($fd) =~ m/kvm-vcpu/;
44 $last->{$instance}->{vcpu} = $vcpu;
47 # https://www.kernel.org/doc/Documentation/filesystems/proc.txt
48 open($fh, '<', "/proc/$pid/stat");
49 my $line = <$fh>; chomp $line;
50 my $gtime = (split(/\s+/,$line))[42]; # guest time of the task in jiffies
52 if ( my $last_gtime = $last->{$instance}->{gtime} ) {
53 my $clock_ticks = POSIX::sysconf( &POSIX::_SC_CLK_TCK ); # clock ticks per second
55 my $cpu = ( ( $gtime - $last_gtime ) * 100 ) / ( $clock_ticks * $vcpu );
56 $stat->{$instance}->{cpu} = $cpu;
59 $last->{$instance}->{gtime} = $gtime;
63 foreach my $glob ( glob '/var/run/ganeti/instance-disks/*' ) {
64 my ( $instance, $disk ) = split(/:/,$glob,2);
65 $instance =~ s{^.*/}{};
67 next unless exists $stat->{$instance};
69 my $dev = readlink $glob;
72 if ( ! -e "/sys/class/block/$dev" ) {
78 open( my $fh, '<', "/sys/class/block/$dev/stat" );
79 my $v = <$fh>; chomp $v; $v =~ s/^\s+//;
80 my @s = split(/\s+/, $v );
81 # https://www.kernel.org/doc/Documentation/block/stat.txt
84 read_bytes => $s[2] * 512,
87 write_bytes => $s[6] * 512,
90 if ( my $l = $last->{$instance}->{disk}->[$disk] ) {
92 $delta->{$_} = $d->{$_} - $l->{$_} foreach keys %$d;
93 $stat->{$instance}->{disk}->[$disk] = $delta;
94 $stat->{$instance}->{disk}->[$disk]->{dev} = $dev;
95 $stat->{$instance}->{disk}->[$disk]->{disk} = $disk;
97 $last->{$instance}->{disk}->[$disk] = $d;
101 foreach my $full_instance ( glob '/var/run/ganeti/kvm-hypervisor/nic/*' ) {
102 my $instance = $full_instance;
103 $instance =~ s{^.*/}{};
104 next unless exists $stat->{$instance};
106 foreach my $nic ( glob "$full_instance/*" ) {
107 open(my $fh, '<', $nic);
110 next unless -e "/sys/class/net/$dev";
116 foreach my $f (qw( rx_bytes tx_bytes rx_packets tx_packets )) {
117 open( my $fh, '<', "/sys/class/net/$dev/statistics/$f" );
118 my $v = <$fh>; chomp $v;
121 if ( my $l = $last->{$instance}->{nic}->[$nic] ) {
122 $stat->{$instance}->{nic}->[$nic]->{$_} = $d->{$_} - $l->{$_} foreach keys %$d;
123 $stat->{$instance}->{nic}->[$nic]->{dev} = $dev;
124 if ( -e "/sys/class/net/$dev/master" ) {
125 my $vlan = readlink "/sys/class/net/$dev/master";
126 $vlan =~ s/^.*br/br/;
127 $stat->{$instance}->{nic}->[$nic]->{vlan} = $vlan;
130 $last->{$instance}->{nic}->[$nic] = $d;
138 open(my $fh, '>', '/dev/shm/ganeti-monitor.influx');
142 my $d = Data::Dump::dump( $hash );
143 $d =~ s/[\s\r\n]+//g;
144 $d =~ s/[\Q[]{}>\E]//g;
145 $d =~ s/=(\d+),/=$1i,/g;
150 foreach my $instance ( keys %$stat ) {
152 next if $skip->{$instance};
154 print $fh qq{cpu,node="$node",instance="$instance" cpu=}, $stat->{$instance}->{cpu}, "\n";
156 foreach my $disk ( @{ $stat->{$instance}->{disk} } ) {
157 print $fh qq{disk,node="$node",instance="$instance" },dump4influx( $disk ), "\n";
160 foreach my $nic ( @{ $stat->{$instance}->{nic} } ) {
161 print $fh qq{nic,node="$node",instance="$instance" },dump4influx( $nic ), "\n";
168 system q{curl -i -XPOST 'http://10.80.3.89:8086/write?db=ganeti' --data-binary '@/dev/shm/ganeti-monitor.influx'};