#!/usr/bin/perl

=head1 NAME

cmc_tc_sensor_ - Wildcard plugin for monitoring CMC temperature sensors via SNMP

=head1 CONFIGURATION

This is a wildcard plugin.  The plugin link name prefix (after the final "_")
should be a hostname to contact via SNMP.

This plugin does not use configuration environment variables.

=head1 AUTHOR

Unknown author

=head1 LICENSE

GPLv2

=head1 BUGS

Possibly misnamed. Candidate to be snmp__cmctcsensor_

=head1 MAGIC MARKERS

 #%# family=contrib
 #%# capabilities=suggest

=cut

use strict;
use warnings;
use FindBin qw ($Bin $Script);
use Net::SNMP;
use Data::Dumper;
use vars qw ($configure $suggest $sensor_unit $sensor_index %sensor);

# Quit if run without specified sensors
unless ($0 =~ /_\d+_\d+$/ || ($ARGV[0] && $ARGV[0] eq "suggest")) {
    print "Need sensor spesification symlinked in file name.\n";
    print "Hint: $0 suggest\n";
    exit 1;
}

# To configure
if ($ARGV[0] && $ARGV[0] eq "config") {
    $configure = 1;
}

# 'suggest' creates proper symlinks.
if ($ARGV[0] && $ARGV[0] eq "suggest") {
    $suggest = 1;
}

# Find variable
if ($0 =~ /^.*\_(\d+)\_(\d+)$/) {
    $sensor_unit = $1;
    $sensor_index = $2;
}

my $host = ($ENV{'hostname'} || '127.0.0.1');
my $comm = ($ENV{'communitystring'} || 'public');

my ($session, $error) = Net::SNMP->session(
					   -hostname  => $host,
					   -community => $comm,
					   -port      => 161,
					   -version   => 'snmpv1',
					   );
if (!defined ($session)) {
    printf ("ERROR: %s.\n", $error);
    exit 1;
} else {
    if (($configure && $sensor_unit && $sensor_index) || $suggest) {
        my %properties = (
                          1 => 'index',
                          2 => 'type',
                          3 => 'desc',
                          4 => 'status',
                          5 => 'value',
                          6 => 'high',
                          7 => 'low',
                          8 => 'warn',
                          );

	# TODO: Fill out more from MIB
	my %sensor_types = (
                            1  => 'not available',
                            10 => 'temperature',
                            );

	if ($configure) {
	    # .1.3.6.1.4.1.2606.4.2.3.5.2.1.x.1
	    #                 unit -^       ^ ^- index
	    #                               `- property

	    my $baseoid = "1.3.6.1.4.1.2606.4.2." . (2 + $sensor_unit) . ".5.2.1";
	    if (defined (my $response = $session->get_table ($baseoid))) {
		while (my ($oid, $value) = each (%$response)) {
		    my $prop_id = undef;
		    if ($oid =~ /(?:\d+\.){13}(\d+)(?:\.\d+){1}/) {
			$prop_id = $1;
		    }
		    (my $j = $oid) =~ s/^.*\.(\d)$/$1/;
		    if ($j == $sensor_index) {
			my $prop = $properties{$prop_id};
			# print "Sensor: $sensor_unit \t Prop: $prop \t Index: $sensor_index \t Value: $value\n";
			$sensor{$sensor_unit}->{$sensor_index}->{$prop} = $value;
		    }
		}
		my $sensor_name = "sensor_" . $sensor_unit . "_" . $sensor_index;
		my $type = $sensor{$sensor_unit}->{$sensor_index}->{'type'};
		print "graph_title Sensor ${sensor_unit}\/${sensor_index}\n";
		print "graph_args --base 1000 -l 0\n";
		print "graph_category sensors\n";

		if ($sensor_types{$type} eq "temperature") {
		    # Find thermometer scale (Celsius or Fahrenheit);
		    my $temp_scale_oid = "1.3.6.1.4.1.2606.4.3.1.1.0";
		    my %temp_scales = (
				       1 => "Celsius",
				       2 => "Fahrenheit",
				       );
		    if (defined (my $response = $session->get_request ($temp_scale_oid))) {
			my (undef, $scale) = each (%$response);
			print "graph_label Degrees $temp_scales{$scale}\n";
			print "graph_vlabel Degrees $temp_scales{$scale}\n";
		    }
		}
		print "$sensor_name\.label " . $sensor{$sensor_unit}->{$sensor_index}->{'desc'} . "\n";
		print "$sensor_name\.warning " .  $sensor{$sensor_unit}->{$sensor_index}->{'low'} . ":" . $sensor{$sensor_unit}->{$sensor_index}->{'warn'} . "\n";
		print "$sensor_name\.critical " .  $sensor{$sensor_unit}->{$sensor_index}->{'low'} . ":" . $sensor{$sensor_unit}->{$sensor_index}->{'high'} . "\n";
	    }
	} elsif ($suggest) {
	    # Find number of connected CMC units
	    my $num_units_oid = '1.3.6.1.4.1.2606.4.2.2.0';
	    my $num_units = $session->get_request ($num_units_oid)->{$num_units_oid};

	    # .1.3.6.1.4.1.2606.4.2.3.5.2.1.1.1
	    #                       ^- 2 + $unit_no

	    for (my $i = 1; $i <= $num_units; $i++) {

		# Walk each table
		my $baseoid = "1.3.6.1.4.1.2606.4.2." . (2 + $i) . ".5.2.1";

		# Find properties and values
		# We only traverse the OID tree once per sensor,
		# to reduce number of SNMP GET requests.

		if (defined (my $response = $session->get_table ($baseoid))) {
		    while (my ($oid, $value) = each (%$response)) {
			my $prop_id = undef;
			if ($oid =~ /(?:\d+\.){13}(\d+)(?:\.\d+){1}/) {
			    $prop_id = $1;
			}
			my $prop = $properties{$prop_id};
			(my $j = $oid) =~ s/^(?:\d+\.)*(\d+)$/$1/g;
			# print "Sensor: $i \t Prop: $prop \t Index: $j \t Value: $value\n";
			$sensor{$i}->{$j}->{$prop} = $value;
		    }
		} else {
		    print $session->error, "\n";;
		}
	    }

	    # Now, traverse the sensor tree(s)
	    while (my ($key, $val) = each (%sensor)) {
		while (my ($key2, $val2) = each (%$val)) {
		    # Check if sensor is available (value == 4)
		    if ($sensor{$key}->{$key2}->{'status'} == 4) {
			my $filename = "/etc/munin/plugins/cmc-tc_sensor_" . $key . "_" . $key2;
			`ln -s $Bin\/$Script $filename`;
		    }
		}
	    }
	}
    } else {
	if (defined ($session)) {
	    # Go directly to the OID we want
	    my $oid = "1.3.6.1.4.1.2606.4.2." . (2 + $sensor_unit) . ".5.2.1.5." . $sensor_index;
	    my $value = $session->get_request ($oid)->{$oid};

	    # Show values
	    print "sensor_" . $sensor_unit . "_" . $sensor_index . ".value $value\n";
	}
    }

    $session->close();
}
exit 0;
