| 1 |
#!/usr/local/bin/perl -w |
| 2 |
|
| 3 |
$| = 1; |
| 4 |
|
| 5 |
use strict; |
| 6 |
use iscream::XMLParser; |
| 7 |
use IO::Socket; |
| 8 |
|
| 9 |
if (@ARGV != 2) { |
| 10 |
die "Usage: ihost.pl [i-scream client interface] [TCP port]\n"; |
| 11 |
} |
| 12 |
|
| 13 |
my($addr) = $ARGV[0]; |
| 14 |
my($cport) = $ARGV[1]; |
| 15 |
|
| 16 |
my($csock) = new IO::Socket::INET( |
| 17 |
PeerAddr => $addr, |
| 18 |
PeerPort => $cport, |
| 19 |
Proto => 'tcp' |
| 20 |
) or die "Cannot connect!"; |
| 21 |
|
| 22 |
if (!defined $csock) { |
| 23 |
print "ERROR: Could not connect to $addr:$cport.\n"; |
| 24 |
print "Please check that there is an i-scream server at this address.\n"; |
| 25 |
exit(1); |
| 26 |
} |
| 27 |
|
| 28 |
my($response); |
| 29 |
|
| 30 |
$response = <$csock>; |
| 31 |
if ($response && $response ne "PROTOCOL 1.1\n") { |
| 32 |
print "The i-scream server sent an unexpected protocol id: $response\n"; |
| 33 |
close($csock); |
| 34 |
exit(1); |
| 35 |
} |
| 36 |
|
| 37 |
print $csock "queuegrapher\n"; |
| 38 |
$response = <$csock>; |
| 39 |
if ($response && $response ne "OK\n") { |
| 40 |
print "Received unexpected response: $response\n"; |
| 41 |
close($csock); |
| 42 |
exit(1); |
| 43 |
} |
| 44 |
|
| 45 |
print $csock "SETHOSTLIST\n"; |
| 46 |
$response = <$csock>; |
| 47 |
if ($response && $response ne "OK\n") { |
| 48 |
print "Received odd response: $response\n"; |
| 49 |
close($csock); |
| 50 |
exit(1); |
| 51 |
} |
| 52 |
|
| 53 |
print $csock "_NULL_\n"; |
| 54 |
$response = <$csock>; |
| 55 |
if ($response && $response ne "OK\n") { |
| 56 |
print "Received odd response: $response\n"; |
| 57 |
close($csock); |
| 58 |
exit(1); |
| 59 |
} |
| 60 |
|
| 61 |
print $csock "STARTDATA\n"; |
| 62 |
$response = <$csock>; |
| 63 |
|
| 64 |
chop $response; |
| 65 |
print "Asked to connect to port $response on $addr, connecting...\n"; |
| 66 |
|
| 67 |
my($dport) = $response; |
| 68 |
|
| 69 |
my($dsock) = new IO::Socket::INET( |
| 70 |
PeerAddr => $addr, |
| 71 |
PeerPort => $dport, |
| 72 |
Proto => 'tcp' |
| 73 |
) or die "Cannot connect!"; |
| 74 |
|
| 75 |
if (!defined $dsock) { |
| 76 |
print "ERROR: Could not connect to $addr:$dport.\n"; |
| 77 |
print "Failure in communications.\n"; |
| 78 |
close($csock); |
| 79 |
exit(1); |
| 80 |
} |
| 81 |
|
| 82 |
while(1) { |
| 83 |
$response = <$dsock>; |
| 84 |
my($err, %xmlhash) = &iscream::XMLParser::parse($response); |
| 85 |
if($err) { |
| 86 |
print "SKIPPED (bad xml): $response"; |
| 87 |
} |
| 88 |
## -- mental note, think about ordering checks for optimal speed ;) |
| 89 |
# take a look to see if we have a shutdown packet... |
| 90 |
if(defined($xmlhash{"packet.attributes.shutdown"}) && $xmlhash{"packet.attributes.shutdown"} eq "true") { |
| 91 |
my($hash) = $xmlhash{"packet.attributes.hashCode"}; |
| 92 |
my($cmd) = "rm -f $hash\_*.rrd $hash*.png $hash.def"; |
| 93 |
print `$cmd`; |
| 94 |
print "$cmd\n"; |
| 95 |
next; |
| 96 |
} |
| 97 |
if($xmlhash{"packet.attributes.type"} eq "queueStat") { |
| 98 |
my($hash) = $xmlhash{"packet.attributes.hashCode"}; |
| 99 |
my($date) = $xmlhash{"packet.attributes.date"}; |
| 100 |
my($name) = $xmlhash{"packet.attributes.name"}; |
| 101 |
my($total) = $xmlhash{"packet.queue.attributes.total"}; |
| 102 |
my($i) = 0; |
| 103 |
while(defined $xmlhash{"packet.queue.attributes.queue$i"}) { |
| 104 |
if( ! -f "$hash\_$i.rrd" ) { |
| 105 |
print "making new database for $hash\_$i\n"; |
| 106 |
&makerrd($hash, $i, $date, $name); |
| 107 |
} |
| 108 |
my($size) = $xmlhash{"packet.queue.attributes.queue$i"}; |
| 109 |
my($cmd); |
| 110 |
# see if the queue has been removed |
| 111 |
if($size eq "[deleted]") { |
| 112 |
$cmd = "rm -f $hash\_$i.rrd"; |
| 113 |
# are there any other rrd's left? if not, cleanup! |
| 114 |
my($rrdcount) = `ls | grep $hash\_\\*.rrd | wc -l`; |
| 115 |
if($rrdcount == 0) { |
| 116 |
$cmd = $cmd . " && rm -f $hash.def $hash*.png"; |
| 117 |
} |
| 118 |
} |
| 119 |
else { |
| 120 |
$cmd = "rrdtool update $hash\_$i.rrd $date:$size:$total"; |
| 121 |
} |
| 122 |
print `$cmd`; |
| 123 |
print "$cmd\n"; |
| 124 |
++$i; |
| 125 |
} |
| 126 |
} |
| 127 |
else { |
| 128 |
print "SKIPPED: valid xml, but not a queueStat packet"; |
| 129 |
} |
| 130 |
} |
| 131 |
|
| 132 |
exit 0; |
| 133 |
|
| 134 |
sub makerrd() { |
| 135 |
my($name, $queuenum, $start, $comment) = @_; |
| 136 |
$start = $start - 15; |
| 137 |
my($init) = "rrdtool create $name\_$queuenum.rrd --start $start --step 15"; |
| 138 |
my($ds) = "DS:size:GAUGE:600:U:U DS:total:COUNTER:600:U:U"; |
| 139 |
# 3h in 15s samples 1d in 2m samples 1w in 15m samples 1m in 1hr samples |
| 140 |
my($rra1) = "RRA:AVERAGE:0.5:1:720 RRA:AVERAGE:0.5:8:720 RRA:AVERAGE:0.5:60:672 RRA:AVERAGE:0.5:240:744"; |
| 141 |
my($rra2) = "RRA:MAX:0.5:1:720 RRA:MAX:0.5:8:720 RRA:MAX:0.5:60:672 RRA:MAX:0.5:60:744"; |
| 142 |
my($cmd) = "$init $ds $rra1 $rra2"; |
| 143 |
print `$cmd`; |
| 144 |
print "$cmd\n"; |
| 145 |
print `echo "$comment" > $name.def`; |
| 146 |
} |