dnl $List(FREEBSD7): echo FREEBSD
dnl $List(FREEBSD6): echo FREEBSD
dnl $List(FREEBSD5): echo FREEBSD
dnl $List(FREEBSD4): echo FREEBSD
dnl $List(FREEBSD4): echo FREEBSD
dnl $List(FREEBSD3): echo FREEBSD3
dnl $List(HPUX9): echo HPUX
dnl $List(HPUX9): echo HPUX
dnl $List(SLACK): echo SLACK
dnl $List(LINUX): echo LINUX
dnl $List(AS2): echo LINUX
dnl $List(AS3): echo LINUX
dnl $List(AS4): echo LINUX
dnl $List(SUN5): echo SOL8
dnl $List(SOL8): echo SOL8
dnl $List(SOL9): echo SOL8
dnl $List(SOL10): echo SOL8
dnl $List(IBMR2): echo IBMR2
dnl $List(AIX): echo IBMR2
dnl $List(*): %;%.
changequote(,)dnl
#!/usr/bin/env perl
# $Id: tempstats.pl.host,v 1.7 2009/12/26 21:19:13 ksb Exp $
#
use lib '/usr/local/lib/sac/perl'.join('.', unpack('c*', $^V)),
	'/usr/local/lib/sac';

use strict;
use Socket;
use Getopt::Std;
use Sys::Hostname;
use POSIX qw(floor);
ifelse(HOSTTYPE HOSTOS,SUN5 20800,,use warnings;)

my($progname) = $0;
$progname ||= 'tempstats';
$progname = $1 if $progname =~ m,.*/(.+)$,o;

$ENV{'PATH'} .=":/usr/local/bin";

my (%opts);
getopts('vN:hH:p:S:T:O:Vxd', \%opts);
# ZZZ configure here if you want a default suffix added to your
# plain hostname
my($suffix) ||= $opts{'S'};	#  e.g. "prod", or "lab", or "test"
my($common) = $opts{'T'} ||= "fedex.com";
my($admindept) = $opts{'O'} ||= "sac"; # admin default department
my($debug)  = $opts{'v'}; #debug or verbose

# RRD update interval must be >= 10 sec, or we move the load too much --ksb
my($stall,$remainder);
# Under -p (persistant) we are a service run at boot, otherwise assume we
# are run from cron once a minute or so, or the command line -x to test.
if ($opts{'p'}) {
	if ($opts{'p'} < 10) {
		$opts{'p'} = 10;
	}
	$stall = $opts{'x'} ? 0 : floor(0.5+rand($opts{'p'}));
	$remainder = $opts{'p'}-$stall;
} else {
	$stall = $opts{'x'} ? 0 : floor(3.5+rand(55));
	$remainder = undef;
}

# get hostname: CONFIG for your domain, not  ".fedex.com" and ".sac"
my($host) = hostname();

ifdef(FORCE_LOCAL_DOMAIN,
	$host =~ m/([^.]*)\..*$/o and do {
	$host = $1;
};
$host .= "FORCE_LOCAL_DOMAIN";
,	$host =~ m/(.*)\.$common$/ and do {
	$host = $1;
	$host =~ m/(.*)\.$admindept$/ and do {
		$host = $1;
	};
};
)dnl

# If our hostname is not a FQDN under $common we might have to adjust the
# results from the above.  Or just force it on the command line with
# -N real-name.
$host .= ".$suffix" if ($suffix && $suffix ne $admindept);
$opts{'N'} ||= $opts{'n'};	# backwards compatibility with old Linix
$host = $opts{'N'} if ($opts{'N'});

my($peghost) = shift(@ARGV);
$peghost ||= $opts{'H'};	# backwards compatible with HPUX
my($pegport);
$peghost ||= 'peg.sac.fedex.com:31415';
if ($peghost =~ m/^([^:]+):([0-9]+)$/) {
	$pegport = $2;
	$peghost = $1;
}
if ($peghost =~ m/^:([0-9]+)$/) {
	$pegport = $1;
}
$pegport ||= 31415;

if ($opts{'V'}) {
	print "$progname: ", '$Id: tempstats.pl.host,v 1.7 2009/12/26 21:19:13 ksb Exp $', "\n",
		"update: $peghost:$pegport\n",
		"node: $host", ($opts{'N'} ? " [forced]": ''), "\n";
	if (defined($admindept) && defined($common)) {
		print "remove: admin \"$admindept\" after toplevel \"$common\"\n";
	} elsif (defined $common) {
		print "remove: toplevel \"$common\"\n";
	} elsif (defined $admindept) {
		print "squelch: admin \"$admindept\"\n";
	}
	if (defined($suffix) && (!defined $admindept || $suffix ne $admindept)) {
		print "add: suffix $suffix\n";
	}
	if (defined $remainder) {
		print "updates: every ", $stall+$remainder, ", at offset $stall\n";
	} else {
		print "update: once, stalling for $stall\n";
	}
	exit(0);
}

if ($opts{'h'}) {
	print "$progname: usage [-v] [-D] [-p delay] [-N node] [-O admin] [-S suffix] [-T toplevel] [peg][:port]\n",
		"$progname: -h|-V\n",
		"d	    list the sensors this host will report, and exit\n",
		"h	    output this brief help message, and exit\n",
		"N node	    use this node name, rather than our hostname\n",
		"O admin    set the administrators department suffix\n",
		"p delay    update persistantly, about every delay seconds\n",
		"S suffix   remove this suffix after toplevel, if present\n",
		"T toplevel remove this from the end of our hostname\n",
		"V	    output the standard version information\n",
		"x	    trace updates on stdout\n",
		"peg	    sample collection host, running rrdd\n",
		"port	    rrdd update port (otherwise $pegport)\n";
	exit(0);
}


sub mkUpdate {
my (%nowtemps,%maxtemps,%warntemps);
ifelse(yes,ifelse(HOSTTYPE,SUN5,yes,HOSTTYPE,SOL8,yes,HOSTTYPE,SOL9,yes,HOSTTYPE,SOL10,yes,no),
my $count = 0;
# we have to declare these up here since we have multiline records
my ($sens,$shutdown,$warning,$now);
# I know the below is the old style filehandle.  Stupid solaris8 makes me
# want to vom.	We should install a better perl than the one
# Sun provided on those hosts. -anderson
open (FH , "/usr/sbin/prtpicl -v -c temperature-sensor|") or die "could not open prtpicl : $!";
while (<FH>) {
	chomp;
	print "$_\n" if $debug;
	m,^ {2}([^: ]*?) , and do {
		$sens = $1;
		if ( $sens =~ /amb/io && $sens !~ m/[0-9]$/) {
			$sens .= $count+1 and $count+=1;
		} else {
			$count=0;
		}
		$sens= lc($sens);
		print ".$sens.\n" if $debug;
	};
	m,^ {2}:HighShutdownThreshold[^0-9]+?([0-9]+), and do {
		$shutdown=$1;
		$maxtemps{$sens} = $shutdown;
		print ".$sens. shutdown $shutdown\n" if $debug;
	};
	m,^ {2}:HighWarningThreshold[^0-9]+?([0-9]+), and do {
		$warning=$1;
		$warntemps{$sens} = $warning;
		print ".$sens. warning $warning\n" if $debug;
	};
	m,^ {2}:Temperature[^0-9]+?([0-9]+), and do {
		$now=$1;
		$nowtemps{$sens} = $now;
		print ".$sens. now $now\n" if $debug;
	};
}
close (FH);
, yes,ifelse(HOSTTYPE,FREEBSD,yes,HOSTTYPE,FREEBSD3,yes,HOSTTYPE,FREEBSD7,yes,HOSTTYPE,FREEBSD6,yes,HOSTTYPE,FREEBSD5,yes,HOSTTYPE,FREEBSD4,yes,no),
	print "we dont know how to do HOSTTYPE HOSTTYPEs yet";
	exit (1);
,HOSTTYPE,LINUX,
open (my $if, "op hpasmcli -s \"show temp\"|") or die "op failed to run";
while (<$if>) {
	next unless ($_ =~ /^#/);
	chomp;
	m,^#\d+\s+(\S*?)\s.*?(\d+)C/.*?(\d+)C/, and do {
		my $sens = "$1";
		my $now = $2;
		my $max = $3;
		$sens =~ s#\W##g;
		$sens =~ s#_##g;
		$sens = lc($sens);
		$nowtemps{$sens} = $now;
		$maxtemps{$sens} = $max;
		$warntemps{$sens} = $max-5; # we had to make this up, using suns 5degrees
		print "SENSOR:$sens, NOW:$now MAX:$max\n" if $debug;
	}
}
close($if);
)
my (@sensors) = keys(%nowtemps);
return(\%nowtemps,\%warntemps,\%maxtemps);
}


my ($nowtemp,$warntemp,$maxtemp) = &mkUpdate();

if ( scalar(keys %{$nowtemp}) < 1 ) {
	print STDERR "somehow we ran the programs to get the temps, but got no usable output.\n";
	print STDERR "No peg updates are being sent\n";
	exit (1);
}

my %nowtemps = %{$nowtemp};
my %warntemps = %{$warntemp};
my %maxtemps = %{$maxtemp};


my $trace="";
$opts{'x'} and $trace = "-x";
# Send to peg's rrdd, peg could move over time, so we look up up
my($update,$ipout,$proto,$sockaddr);
$proto = getprotobyname('udp');
socket(SOCKET, PF_INET, SOCK_DGRAM, $proto) ||
	die "socket: inet: $!";
while ($ipout = inet_aton($peghost)) {
	#sleep($stall);
	foreach my $sens (keys %nowtemps) {
		my $update = "update host/$host/app-temp-$sens.rrd -t curtemp:warn:max N:$nowtemps{$sens}:$warntemps{$sens}:$maxtemps{$sens}";
		if ($opts{'d'}) {
			$update =~ s/^\S*?\s//;
			$update =~ s/\s.*//;
			print "$update\n";
			next;
		}
		print $update, "\n" if ($opts{'x'});
		$sockaddr = sockaddr_in($pegport, $ipout);
		send(SOCKET, "00 ".$update, 0, $sockaddr);
	}
	last unless defined($remainder);
	sleep($remainder);
	next unless (0 == $stall);  # -x set stall to 0, recompute it
	$stall = floor(0.5+rand($opts{'p'}));
	$remainder = $opts{'p'}-$stall;
}
close(SOCKET);
exit(0);
changequote(`,')dnl
