install windows 10 using ide disk and virtio.iso drivers
[gnt-info] / gnt-monitor
1 #!/usr/bin/perl
2 use warnings;
3 use strict;
4 use autodie;
5 use POSIX;
6 use Time::HiRes qw(time sleep);
7
8 my $DEBUG = $ENV{DEBUG} || 0;
9 my $INFLUX = $ENV{INFLUX} || 'http://10.80.3.89:8086/write?consistency=any&db=gnt';
10 my $INTERVAL = $ENV{INTERVAL} || 1;
11 my $DC = $ENV{DC};
12 my $RACK = $ENV{RACK};
13
14 my $node = `hostname -s`;
15 chomp $node;
16
17 my $location = '';
18 $location .= qq{,dc=$DC} if $DC;
19 $location .= qq{,rack=$RACK} if $RACK;
20
21 warn $0 = "gnt-monitor\@$node$location $INFLUX $INTERVAL $DEBUG";
22
23 use Data::Dump;
24 sub XXX { $DEBUG ? warn "XXX ",Data::Dump::dump( @_ ) : {} };
25
26 my $stat;
27 my $last;
28
29 while(1) {
30
31 my $skip;
32
33 my $begin_t = time();
34 my $t = int( time() * 1000_000_000 );
35
36 foreach my $instance ( glob '/var/run/ganeti/kvm-hypervisor/pid/*' ) {
37
38         open(my $fh, '<', $instance);
39         my $pid = <$fh>; chomp $pid;
40
41         $instance =~ s{^.*/}{};
42
43         if ( ! -d "/proc/$pid" ) {
44                 $skip->{$instance}++;
45                 XXX $skip;
46                 next;
47         }
48
49         my $vcpu = $last->{$instance}->{vcpu};
50
51         if ( ! $vcpu ) {
52                 foreach my $fd ( glob "/proc/$pid/fd/*" ) {
53                         $vcpu++ if -l $fd && readlink($fd) =~ m/kvm-vcpu/;
54                 }
55
56                 $last->{$instance}->{vcpu} = $vcpu;
57         }
58
59         # https://www.kernel.org/doc/Documentation/filesystems/proc.txt
60         open($fh, '<', "/proc/$pid/stat");
61         my $line = <$fh>; chomp $line;
62         my $gtime = (split(/\s+/,$line))[42]; # guest time of the task in jiffies
63
64         if ( my $last_gtime = $last->{$instance}->{gtime} ) {
65                 my $clock_ticks = POSIX::sysconf( &POSIX::_SC_CLK_TCK ); # clock ticks per second
66
67                 my $cpu = ( ( $gtime - $last_gtime ) * 100 ) / ( $clock_ticks * $vcpu ) / $INTERVAL;
68                 $stat->{$instance}->{cpu} = $cpu;
69                 $stat->{$instance}->{ticks} = ($gtime - $last_gtime) / $INTERVAL;
70         }
71
72         $last->{$instance}->{gtime} = $gtime;
73 }
74                 
75
76 foreach my $glob ( glob '/var/run/ganeti/instance-disks/*' ) {
77         my ( $instance, $disk ) = split(/:/,$glob,2);
78         $instance =~ s{^.*/}{};
79
80         next unless exists $stat->{$instance};
81
82         my $dev = readlink $glob;
83         $dev =~ s{^.*dev/}{};
84
85         if ( ! -e "/sys/class/block/$dev" ) {
86                 $skip->{$instance}++;
87                 XXX $skip;
88                 next;
89         }
90
91         open( my $fh, '<', "/sys/class/block/$dev/stat" );
92         my $v = <$fh>; chomp $v; $v =~ s/^\s+//;
93         my @s = split(/\s+/, $v );
94         # https://www.kernel.org/doc/Documentation/block/stat.txt
95         my $d = {
96                 read_io => $s[0] / $INTERVAL,
97                 read_bytes => $s[2] * 512 / $INTERVAL,
98                 read_wait => $s[3] / $INTERVAL,
99                 write_io => $s[4] / $INTERVAL,
100                 write_bytes => $s[6] * 512 / $INTERVAL,
101                 write_wait => $s[7] / $INTERVAL,
102         };
103         if ( my $l = $last->{$instance}->{disk}->[$disk] ) {
104                 my $delta;
105                 $delta->{$_} = $d->{$_} - $l->{$_} foreach keys %$d;
106                 $stat->{$instance}->{disk}->[$disk] = $delta;
107                 $stat->{$instance}->{disk}->[$disk]->{dev} = $dev;
108                 $stat->{$instance}->{disk}->[$disk]->{disk} = $disk;
109         }
110         $last->{$instance}->{disk}->[$disk] = $d;
111
112 }
113
114 foreach my $full_instance ( glob '/var/run/ganeti/kvm-hypervisor/nic/*' ) {
115         my $instance = $full_instance;
116         $instance =~ s{^.*/}{};
117         next unless exists $stat->{$instance};
118
119         foreach my $nic ( glob "$full_instance/*" ) {
120                 open(my $fh, '<', $nic);
121                 my $dev = <$fh>;
122
123                 next unless -e "/sys/class/net/$dev";
124
125                 $nic =~ s{^.*/}{};
126
127                 my $d;
128
129                 foreach my $f (qw( rx_bytes tx_bytes rx_packets tx_packets )) {
130                         open( my $fh, '<', "/sys/class/net/$dev/statistics/$f" );
131                         my $v = <$fh>; chomp $v;
132                         $d->{$f} = $v / $INTERVAL;
133                 }
134                 if ( my $l = $last->{$instance}->{nic}->[$nic] ) {
135                         $stat->{$instance}->{nic}->[$nic]->{$_} = $d->{$_} - $l->{$_} foreach keys %$d;
136                         $stat->{$instance}->{nic}->[$nic]->{dev} = $dev;
137                         if ( -e "/sys/class/net/$dev/master" ) {
138                                 my $vlan = readlink "/sys/class/net/$dev/master";
139                                 $vlan =~ s/^.*br//;
140                                 $stat->{$instance}->{nic}->[$nic]->{vlan} = $vlan;
141                         }
142                 }
143                 $last->{$instance}->{nic}->[$nic] = $d;
144
145         }
146 }
147
148 #XXX $stat;
149 #XXX $last;
150
151 sub dump4influx {
152         my $hash = shift;
153         my @v;
154         foreach my $k ( keys %$hash ) {
155                 my $v = $hash->{$k};
156                 my ( $d, $s ) = $v =~ m/^\d+(\.\d+)?$/i ? ( '',  ''  ) : # float
157                                                      ( '"' ,''  ) ; # string
158
159                 push @v, "$k=$d$v$d$s";
160         }
161         my $i = join(',', @v);
162         return $i;
163 }
164
165 open(my $fh, '>', '/dev/shm/gnt-monitor.influx');
166
167 foreach my $instance ( keys %$stat ) {
168
169         next if $skip->{$instance};
170
171         print $fh qq{ganeti_cpu,node=$node,instance=$instance$location cpu=$stat->{$instance}->{cpu},ticks=$stat->{$instance}->{ticks} $t\n};
172
173         foreach my $disk ( @{ $stat->{$instance}->{disk} } ) {
174                 print $fh qq{ganeti_disk,node=$node,instance=$instance$location },dump4influx( $disk ), " $t\n";
175         }
176
177         foreach my $nic ( @{ $stat->{$instance}->{nic} } ) {
178                 my $vlan = delete $nic->{vlan};
179                 $vlan = 0 unless defined $vlan;
180                 print $fh qq{ganeti_nic,node=$node,instance=$instance,vlan=${vlan}$location },dump4influx( $nic ), " $t\n";
181         }
182
183 }
184
185 close($fh);
186
187 if ( system( 'curl', '-s', '-XPOST', $INFLUX, '--data-binary', '@/dev/shm/gnt-monitor.influx' ) == 0 ) {
188 } else {
189         rename '/dev/shm/gnt-monitor.influx', '/dev/shm/gnt-monitor.influx.bug.' . scalar glob '/dev/shm/gnt-monitor.influx.bug.*';
190         warn "curl failed: $? $!";
191 }
192
193 my $dt = time() - $begin_t;
194 sleep $INTERVAL - $dt if $dt > 0 && $dt < $INTERVAL;
195 } #/while
196