7 my $DEBUG = $ENV{DEBUG} || 0;
8 my $INFLUX = $ENV{INFLUX} || 'http://10.80.3.89:8086/write?db=gnt';
9 my $INTERVAL = $ENV{INTERVAL} || 1;
11 my $RACK = $ENV{RACK};
13 my $node = `hostname -s`;
17 $location .= qq{,dc=$DC} if $DC;
18 $location .= qq{,rack=$RACK} if $RACK;
20 warn $0 = "gnt-monitor\@$node$location $INFLUX $INTERVAL $DEBUG";
23 sub XXX { $DEBUG ? warn "XXX ",Data::Dump::dump( @_ ) : {} };
32 foreach my $instance ( glob '/var/run/ganeti/kvm-hypervisor/pid/*' ) {
34 open(my $fh, '<', $instance);
35 my $pid = <$fh>; chomp $pid;
37 $instance =~ s{^.*/}{};
39 if ( ! -d "/proc/$pid" ) {
45 my $vcpu = $last->{$instance}->{vcpu};
48 foreach my $fd ( glob "/proc/$pid/fd/*" ) {
49 $vcpu++ if -l $fd && readlink($fd) =~ m/kvm-vcpu/;
52 $last->{$instance}->{vcpu} = $vcpu;
55 # https://www.kernel.org/doc/Documentation/filesystems/proc.txt
56 open($fh, '<', "/proc/$pid/stat");
57 my $line = <$fh>; chomp $line;
58 my $gtime = (split(/\s+/,$line))[42]; # guest time of the task in jiffies
60 if ( my $last_gtime = $last->{$instance}->{gtime} ) {
61 my $clock_ticks = POSIX::sysconf( &POSIX::_SC_CLK_TCK ); # clock ticks per second
63 my $cpu = ( ( $gtime - $last_gtime ) * 100 ) / ( $clock_ticks * $vcpu );
64 $stat->{$instance}->{cpu} = $cpu;
65 $stat->{$instance}->{ticks} = $gtime - $last_gtime;
68 $last->{$instance}->{gtime} = $gtime;
72 foreach my $glob ( glob '/var/run/ganeti/instance-disks/*' ) {
73 my ( $instance, $disk ) = split(/:/,$glob,2);
74 $instance =~ s{^.*/}{};
76 next unless exists $stat->{$instance};
78 my $dev = readlink $glob;
81 if ( ! -e "/sys/class/block/$dev" ) {
87 open( my $fh, '<', "/sys/class/block/$dev/stat" );
88 my $v = <$fh>; chomp $v; $v =~ s/^\s+//;
89 my @s = split(/\s+/, $v );
90 # https://www.kernel.org/doc/Documentation/block/stat.txt
93 read_bytes => $s[2] * 512,
96 write_bytes => $s[6] * 512,
99 if ( my $l = $last->{$instance}->{disk}->[$disk] ) {
101 $delta->{$_} = $d->{$_} - $l->{$_} foreach keys %$d;
102 $stat->{$instance}->{disk}->[$disk] = $delta;
103 $stat->{$instance}->{disk}->[$disk]->{dev} = $dev;
104 $stat->{$instance}->{disk}->[$disk]->{disk} = $disk;
106 $last->{$instance}->{disk}->[$disk] = $d;
110 foreach my $full_instance ( glob '/var/run/ganeti/kvm-hypervisor/nic/*' ) {
111 my $instance = $full_instance;
112 $instance =~ s{^.*/}{};
113 next unless exists $stat->{$instance};
115 foreach my $nic ( glob "$full_instance/*" ) {
116 open(my $fh, '<', $nic);
119 next unless -e "/sys/class/net/$dev";
125 foreach my $f (qw( rx_bytes tx_bytes rx_packets tx_packets )) {
126 open( my $fh, '<', "/sys/class/net/$dev/statistics/$f" );
127 my $v = <$fh>; chomp $v;
130 if ( my $l = $last->{$instance}->{nic}->[$nic] ) {
131 $stat->{$instance}->{nic}->[$nic]->{$_} = $d->{$_} - $l->{$_} foreach keys %$d;
132 $stat->{$instance}->{nic}->[$nic]->{dev} = $dev;
133 if ( -e "/sys/class/net/$dev/master" ) {
134 my $vlan = readlink "/sys/class/net/$dev/master";
136 $stat->{$instance}->{nic}->[$nic]->{vlan} = $vlan;
139 $last->{$instance}->{nic}->[$nic] = $d;
150 foreach my $k ( keys %$hash ) {
152 my ( $d, $s ) = $v =~ m/^\d+$/ ? ( '', 'i' ) :
153 $v =~ m/\w+/ ? ( '"', '' ) :
154 ( '' , '' ) ; # float
156 push @v, "$k=$d$v$d$s";
158 my $i = join(',', @v);
162 open(my $fh, '>', '/dev/shm/gnt-monitor.influx');
164 foreach my $instance ( keys %$stat ) {
166 next if $skip->{$instance};
168 print $fh qq{cpu,node=$node,instance=$instance$location cpu=$stat->{$instance}->{cpu},ticks=$stat->{$instance}->{ticks}\n};
170 foreach my $disk ( @{ $stat->{$instance}->{disk} } ) {
171 print $fh qq{disk,node=$node,instance=$instance$location },dump4influx( $disk ), "\n";
174 foreach my $nic ( @{ $stat->{$instance}->{nic} } ) {
175 my $vlan = delete $nic->{vlan};
176 print $fh qq{nic,node=$node,instance=$instance,vlan=${vlan}$location },dump4influx( $nic ), "\n";
183 if ( system( 'curl', '-XPOST', $INFLUX, '--data-binary', '@/dev/shm/gnt-monitor.influx' ) == 0 ) {
185 rename '/dev/shm/gnt-monitor.influx', '/dev/shm/gnt-monitor.influx.bug.' . scalar glob '/dev/shm/gnt-monitor.influx.bug.*';
186 warn "curl failed: $? $!";