#!/bin/bash
# -*- sh -*-

: << =cut

=head1 NAME

ipmi_ - Plugin to monitor temperature, fan speed, watts or volts using IPMI

=head1 CONFIGURATION

=head2 ENVIRONMENT VARIABLES

This plugin does not use environment variables

=head2 WILDCARD PLUGIN

This plugin should be linked as ipmi_temp, ipmi_fans, ipmi_power or ipmi_volts,
and will show either temperatures, fan speeds, watts or volts based on its link
name.

=head1 NOTE

WARNING: Munin has a 10 second default timeout on plugins.  On some
hosts ipmitool takes longer than that to probe all your hardware.  In
this case this plugin us unusable.

=head1 AUTHOR

Nicolai Langfeldt <janl@linpro.no>

Modified by Mathieu Gauthier-Pilote <mgauthier@evolix.ca> from Evolix to return amp values as well (2024/04).

=head1 LICENSE

Donated to the public domain by Nicolai Langfeldt (janl@linpro.no)

=head1 MAGIC MARKERS

 #%# family=auto
 #%# capabilities=autoconf suggest

=cut

#### Parse commandline to determine what the job is

CONFIG=no

case $1 in
    autoconf)
	type -p ipmitool &>/dev/null ||
	  { echo 'no (missing ipmitool command)' && exit 0; }

	ipmitool sensor &>/dev/null ||
	  { echo 'no (unable to access IPMI device)' && exit 0; }

	echo yes
        exit 0
	;;
    suggest) echo fans
             echo temp
             echo power
             echo volts
             echo amp
             exit 0;;
    config)  CONFIG=config;;
esac

case $0 in
    *_temp) MEASURE=temp;;
    *_fans) MEASURE=fans;;
    *_power) MEASURE=power;;
    *_volts) MEASURE=volts;;
    *_amp) MEASURE=amp;;
    *) echo "Please invoke as ipmi_temp, ipmi_fans, ipmi_power ipmi_volts or ipmi_amp" >&2
       exit 1;;
esac

export CONFIG MEASURE

#### Work is done in this awk script

ipmitool sensor | gawk -F'|' '
BEGIN {
    FANS = "";
    TEMPS = "";
    POWER = "";
    VOLTS = "";
    AMP = "";
    CFANS = "graph_title Fan speeds based on IPMI\ngraph_vlabel RPM or %\ngraph_category Sensors\n";
    CTEMPS = "graph_title Machine temperature based on IPMI\ngraph_vlabel Degrees celcius\ngraph_category Sensors\n";
    CPOWER = "graph_title Power usage based on IPMI\ngraph_vlabel W\ngraph_category Sensors\n";
    CVOLTS = "graph_title Volts based on IPMI\ngraph_vlabel V\ngraph_category Sensors\n";
    CAMP = "graph_title Amps based on IPMI\ngraph_vlabel A\ngraph_category Sensors\n";
}

# Remove extraneous spaces to make output prettyer
{ gsub(/\t/," "); gsub(/ +/," "); gsub(/ +\|/,"|"); gsub(/\| +/,"|") }

# Skip lines with 0x0 in first column
/^[^|]+\|0x0\|/ { next; };

# Skip lines with na in first column
/^[^|]+\|na\|/ { next; };

# Parse temperatures
/degrees C/ {
	NAME=THING=$1;
	gsub(/[^A-Za-z0-9]/,"",NAME);
	TEMP=$2;

	# Find unique name
	while (NAMES[NAME] >= 1) {
	    NAME=sprintf("%si",NAME);
	}
	NAMES[NAME]=1;

	WARN=$8;
	CRIT=$9;

	TEMPS = sprintf("%s%s.value %s\n",TEMPS,NAME,TEMP);
	CTEMPS = sprintf("%s%s.label %s\n",CTEMPS,NAME,THING);

	if (CRIT !~ /na/) {
		CTEMPS = sprintf("%s%s.critical 0:%s\n",CTEMPS,NAME,CRIT);
	}

	if (WARN !~ /na/) {
		CTEMPS = sprintf("%s%s.warning 0:%s\n",CTEMPS,NAME,WARN);
	}
}

/(RPM|^Fan.*percent)/ {
        NAME=THING=$1;
	gsub(/[^A-Za-z0-9]/,"",NAME);
	SPEED=$2;

	# Find unique name
	while (NAMES[NAME] >= 1) {
	    NAME=sprintf("%si",NAME);
	}
	NAMES[NAME]=1;

	FANS = sprintf("%s%s.value %s\n",FANS,NAME,SPEED);
	CFANS = sprintf("%s%s.label %s\n",CFANS,NAME,THING);

	OK=$4;

	MIN=$6;
	if (MIN !~ /na/) {
		CFANS = sprintf("%s%s.warning %s:\n",CFANS,NAME,MIN);
	}
}

/Watts/ {
    NAME=THING=$1;
    gsub(/[^A-Za-z0-9]/,"",NAME);
    WATTS=$2;

    # Find unique name
    while (NAMES[NAME] >= 1) {
        NAME=sprintf("%si",NAME);
    }
    NAMES[NAME]=1;

    POWER = sprintf("%s%s.value %s\n",POWER,NAME,WATTS);
    CPOWER = sprintf("%s%s.label %s\n",CPOWER,NAME,THING);
}

/Volts/ {
    NAME=THING=$1
    gsub(/[^A-Za-z0-9]/,"",NAME);
    VOLTS_SENSOR=$2;

    # Find unique name
    while (NAMES[NAME] >= 1) {
        NAME=sprintf("%si",NAME);
    }
    NAMES[NAME]=1;

    VOLTS = sprintf("%s%s.value %s\n",VOLTS,NAME,VOLTS_SENSOR);
    CVOLTS = sprintf("%s%s.label %s\n",CVOLTS,NAME,THING);
}

/Amps/ {
    NAME=THING=$1
    gsub(/[^A-Za-z0-9]/,"",NAME);
    AMPS=$2;

    # Find unique name
    while (NAMES[NAME] >= 1) {
        NAME=sprintf("%si",NAME);
    }
    NAMES[NAME]=1;

    AMP = sprintf("%s%s.value %s\n",AMP,NAME,AMPS);
    CAMP = sprintf("%s%s.label %s\n",CAMP,NAME,THING);
}

END {
    if (ENVIRON["MEASURE"] == "temp") {
        VALUE=TEMPS;
        CONFIG=CTEMPS;
    } else if (ENVIRON["MEASURE"] == "power") {
        VALUE=POWER;
        CONFIG=CPOWER;
    } else if (ENVIRON["MEASURE"] == "volts") {
        VALUE=VOLTS;
        CONFIG=CVOLTS;
    } else if (ENVIRON["MEASURE"] == "amp") {
        VALUE=AMP;
        CONFIG=CAMP;
    } else {
        VALUE=FANS;
        CONFIG=CFANS;
    }
    if (ENVIRON["CONFIG"] == "config")
        printf "%s",CONFIG;
    else
        printf "%s",VALUE;
}
'

# vim: syntax=sh ts=4 et
