www.ryanbowlby.com

(dev|web)ops | security | biking | soap box

Munin plugins – fan speed & temperature

1 Comment

I’ve gone graph crazy with Munin! After configuring the usual plugins I went searching for ones that graph fan speed and chassis temperature on Dell hardware. Unfortunately, the one I did find was too quick and dirty and so I went ahead and made them myself

Requirements

These plugins are compatible with Dell servers and require Dell’s Openmanage software be installed, specifically the omreport utility. The plugins expect to find omreport, or a symlink, in /usr/sbin. The omreport utility makes use of information under /proc and as such may need to be run as root on some systems. The two plugins are actually just one script that outputs the correct data depending on the filename (dell_fans, dell_temps).

Installation

  • Verify omreport is installed and available in /usr/sbin. Alternatively, modify the path in the script.
  • Verify OMSA services are running
srvadmin-services.sh status
  • Download and install the plugin into Munin’s libdir as dell_fans and dell_temps.
https://github.com/rbowlby/munin-dell.git
  • Create the munin config file with the necessary options to run the plugin as root.
cat <<EOF > /etc/munin/plugin-conf.d/dell
[dell*]
user root
group root
EOF
  • Verify the plugin works as expected
munin-run --debug /etc/munin/plugins/dell_fans
munin-run --debug /etc/munin/plugins/dell_temps
  • Restart munin and verify the node can fetch the data correctly
/etc/init.d/munin-node restart
echo -e "fetch dell_fans" | nc localhost 4949

#!/usr/bin/env python
"""
USAGE

    dell_changeme [config] [autoconfig]

    Copy script to two files: dell_fans and dell_temps.
    Example: cat dell_changeme | tee dell_fans > dell_temps

DESCRIPTION

    A Munin plugin to graph the fan speeds and chassis temperatures of Dell
    hardware. Requires Dell's OpenManage software, specifically omreport. OMSA
    services must be started prior to plugins use. Script expects omreport to
    be in /usr/bin/, you may need to add a symlink.

    omreport accesses the proc filesystem and as such this plugin must be ran
    as root. Alternatively, you could modify script to use sudoers, or setuid.

    To run script as root add the following lines to munin's plugin-conf.d dir.

    [dell*]
    user root
    group root

    Troubleshooting info: http://www.ryanbowlby.com/infotech/munin-plugin-dell/

AUTHOR

    Ryan Bowlby

LICENSE

    This script is in the public domain, free from copyrights or restrictions.
"""
# Magic markers (optional) - used by munin-node-configure:
#
#%# family=auto
#%# capabilities=autoconf

import sys
import subprocess as sp

class Statistics(object):
    """A base class that runs omreport and prints the filtered results."""

    def __init__(self, command):
        self.command = command.split()
        self.data = sp.Popen(self.command,stdout=sp.PIPE).stdout.readlines()
        self.count = 0
        # Make sure omreport returns at least one sensor block.
        for item in self.data:
            if (item.startswith("Probe Name") or item.startswith("Reading")
               or item.startswith("Statistic") or item.startswith("Location")):
                self.count += 1
        if self.count < 2:             raise ValueError("No output from omreport. Is OMSA running?")     def print_omreport_results(self):         """Prints names and values for each sensor."""         self.count = 0         for item in self.data:             if "Reading" in item:                 # Extract variable length integer.                 self.value = float(item.split(":")[1].split()[0])                 print "%s_%s.value %s" % (self.command[-1], self.count, self.value)                 self.count += 1     def print_config_dynamic(self):         """Prints Munin config data with "label" values from omreport data."""         self.name = []         for item in self.data:             if ("Probe Name" in item and not "System Board System Level" in item):                 self.name.append(item.split(":")[1].replace("RPM","").strip())             if ("System Board System Level" in item):                 self.name.append('System Power Consumption (Watts)')             if ("Current" in item) and ("PS" in item):                 self.name.append(item.split(":")[1].strip() + ' (Amps)')             if "Energy Consumption" in item:                  self.name.append(item.split(":")[1].strip() + ' (KWh)')             if "System Peak Power" in item:                  self.name.append(item.split(":")[1].strip() + ' (Watts)')             if "System Peak Amperage" in item:                  self.name.append(item.split(":")[1].strip() + ' (Amps)')         for index, item in enumerate(self.name):             print "%s_%s.label %s" % (self.command[-1], index, item) class PowerConsumption(Statistics):     """A subclass that includes the Munin "config" output."""     def __init__(self, command):         Statistics.__init__(self, command)     def print_config(self):         print "graph_title Dell Power Consumption Information"         print "graph_args --base 1000 -l 0"         print "graph_vlabel Energy (W / KWh / A)"         print "graph_category Chassis"         print "graph_info This graph shows the system's overall power consumption."         print "graph_period second"         # Print remaining non-static values.         self.print_config_dynamic() class FanSpeed(Statistics):     """A subclass that includes the Munin "config" output."""     def __init__(self, command):         Statistics.__init__(self, command)     def print_config(self):         print "graph_title Dell Fan Speeds"         print "graph_args --base 1000 -l 0"         print "graph_vlabel speed (RPM)"         print "graph_category Chassis"         print "graph_info This graph shows the speed in RPM of all fans."         print "graph_period second"         # Print remaining non-static values.         self.print_config_dynamic() class ChassisTemps(Statistics):     """A subclass that includes the Munin "config" output."""     def __init__(self, command):         Statistics.__init__(self, command)     def print_config(self):         print "graph_title Dell Temperature Readings"         print "graph_args --base 1000 -l 0"         print "graph_vlabel Temp in Degrees Celsius"         print "graph_category Chassis"         print "graph_info This graph shows the temperature for all sensors."         print "graph_period second"         # Print remaining non-static values.         self.print_config_dynamic() if __name__ == '__main__':     omreport = '/usr/sbin/omreport'     try:         if "fans" in sys.argv[0]:             cmd = omreport + " chassis fans"             omdata = FanSpeed(cmd)         elif "temps" in sys.argv[0]:             cmd = omreport + " chassis temps"             omdata = ChassisTemps(cmd)         elif "power" in sys.argv[0]:             cmd = omreport + " chassis pwrmonitoring"             omdata = PowerConsumption(cmd)         else:             print >> sys.stderr, "Change filename to openmanage_fans / openmanage_temps / openmanage_power."
            sys.exit(1)
    except (OSError, ValueError), e:
        # omreport returns 0 results if OMSA services aren't started.
        print >> sys.stderr, "Error running '%s', %s" % (cmd, e)
        sys.exit(1)

    # Munin populates sys.argv[1] with "" (an empty argument), let's remove it.
    sys.argv = [x for x in sys.argv if x]

    if len(sys.argv) > 1:
        if sys.argv[1].lower() == "autoconf":
            # omreport ran earlier, since we got this far autoconf is good.
            print "true"
        elif sys.argv[1].lower() == "config":
            omdata.print_config()
    else:
        omdata.print_omreport_results()

Hope someone else can make use of this!

About these ads

One thought on “Munin plugins – fan speed & temperature

  1. Thanks!!!!! very nice.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.