show node information
[gnt-info] / gnt-i
1 #!/usr/bin/perl
2 use warnings;
3 use strict;
4 use autodie;
5
6 my $DEBUG = $ENV{DEBUG} || 0;
7
8 my $hostname = `hostname -s`;
9 chomp $hostname;
10
11 use Data::Dumper;
12 sub XXX { warn "XXX ",Dumper( @_ ) };
13
14 my $ssh = '';
15 if ( @ARGV ) {
16         $hostname = $ARGV[0];
17         $ssh = "ssh $hostname ";
18 }
19
20 # if prefixed with _ it will be hiddden from output, _args must be last!
21 my @ps_cols = qw( user pid pcpu pmem vsz cputime etimes _args);
22
23 sub ps_cols_all { map { my $t = $_; $t =~ s/^_//; $t } @ps_cols };
24 sub ps_cols_visible { grep { ! /^_/ } @ps_cols };
25
26 my $stat;
27 my $mac_to_name;
28
29 sub DD_hh_mm_ss {
30         my $t = shift;
31         # [[DD-]hh:]mm:ss.
32         my @f = reverse ( 24, 60, 60, 1 );
33         my @p = reverse split(/[-:]/, $t);
34         my $t_sec = 0;
35
36         for ( 0 .. $#p ) {
37                 my $i = $#p - $_;
38 #warn "### $i $p[$i] $f[$i]\n";
39                 $t_sec += $p[$i];
40                 $t_sec *= $f[$i];
41         }
42
43         warn "# DD-hh:mm:ss $t -> $t_sec\n";
44         return $t_sec;
45 }
46
47 my $cmd = 'ps --no-headers axwwo ' . join(',', ps_cols_all);
48 warn "## $cmd\n";
49 open(my $ps, '-|', $ssh . $cmd);
50 while(<$ps>) {
51         chomp;
52         s/^\s*//;
53
54         my %h;
55         @h{@ps_cols} = split(/\s+/, $_, $#ps_cols + 1);
56
57 #XXX 'h = ', \%h;
58         if ( $h{user} =~ m/gnt/ && $h{_args} =~ m/qemu.*-name\s+(\S+)/ ) {
59
60                 my $name = $1;
61                 $stat->{$name}->{$_} = $h{$_} foreach ps_cols_all;
62
63                 $stat->{$name}->{cputime_} = $stat->{$name}->{cputime} = DD_hh_mm_ss( $stat->{$name}->{cputime} );
64
65                 while ( $h{_args} =~ m/mac=([0-9a-fA-F:]+)/g ) {
66                         $mac_to_name->{$1} = $name;
67                 }
68
69         } else {
70 #               warn "## SKIP [$_]\n";
71                 $stat->{ '__' . $hostname }->{$_} += $h{$_} foreach qw( pcpu pmem vsz );
72                 
73         }
74
75 }
76
77 warn "# mac_to_name ", XXX( $mac_to_name );
78
79 open(my $ip, '-|', $ssh . 'ip -s -o link');
80 while(<$ip>) {
81         chomp;
82         if ( m/master\s+(\S+).+ether\s+([0-9a-fA-F:]+).+RX:\s+.+\\\s+(\d+).+TX:\s+.+\\\s+(\d+)/ ) {
83                 my ( $br, $mac, $rx, $tx ) = ( $1, $2, $3, $4 );
84                 if ( my $name = $mac_to_name->{$mac} ) {
85                         $stat->{$name}->{link}->{ $br } = [ $rx, $tx ];
86                 } else {
87                         warn "## SKIP MAC $mac [$_]\n" if $DEBUG;
88                 }
89         } else {
90                 warn "## SKIP $_\n" if $DEBUG;
91         }
92 }
93
94 warn "# stat = ", XXX( $stat );
95 XXX( @ps_cols );
96
97 my $lines;
98 sub push_line {
99         my @l = @_;
100         foreach my $i ( 0 .. $#l ) {
101                 my $len = length($l[$i]) || 0;
102                 $lines->{len}->[$i] ||= $len;
103                 $lines->{len}->[$i] = $len if $len > $lines->{len}->[$i];
104         }
105         push @{ $lines->{line} }, [ @l ];
106 }
107
108 push_line '#name', ps_cols_visible;
109
110 foreach my $name ( sort keys %$stat ) {
111 #       printf "%6.2f %6.2f %8d %6d %6s %s\n", ( map { $stat->{$name}->{$_} || '' } qw( pcpu pmem vsz pid user ) ), $name;
112 #       print join("\t", $name, map { $stat->{$name}->{$_} } ps_cols_visible ), "\n";
113         push_line( $name, map { $stat->{$name}->{$_} } ps_cols_visible );
114 }
115
116 XXX $lines;
117
118 my $fmt = join(' ', map { '%' . $_ . 's' } @{ $lines->{len} } ) . "\n";
119 warn "# fmt = [$fmt]";
120 foreach my $line ( @{ $lines->{line} } ) {
121         printf $fmt, @$line;
122 }