Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Plugin to monitor temperatures of Synology systems via SNMP
- Loading branch information
Showing
1 changed file
with
188 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,188 @@ | ||
#!/usr/bin/python | ||
# -*- coding: utf-8 -*- | ||
|
||
# Copyright (C) 2014 Johann Schmitz <johann@j-schmitz.net> | ||
# | ||
# This program is free software; you can redistribute it and/or modify | ||
# it under the terms of the GNU Library General Public License as published by | ||
# the Free Software Foundation; version 2 only | ||
# | ||
# This program is distributed in the hope that it will be useful, | ||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
# GNU Library General Public License for more details. | ||
# | ||
# You should have received a copy of the GNU Library General Public License | ||
# along with this program; if not, write to the Free Software | ||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
# | ||
|
||
""" | ||
=head1 NAME | ||
snmp__synology_ - Health and system status monitoring plugin for Synology NAS systems | ||
=head1 CONFIGURATION | ||
Make sure your Synology device is accessible via SNMP (e.g. via snmpwalk) and the munin-node | ||
has been configured correctly. | ||
=head1 MAGIC MARKERS | ||
#%# family=snmpauto | ||
#%# capabilities=snmpconf | ||
=head1 VERSION | ||
0.0.1 | ||
=head1 BUGS | ||
Open a ticket at https://github.com/ercpe/contrib if you find one. | ||
=head1 AUTHOR | ||
Johann Schmitz <johann@j-schmitz.net> | ||
=head1 LICENSE | ||
GPLv2 | ||
=cut | ||
""" | ||
|
||
import re | ||
import sys | ||
import os | ||
import logging | ||
|
||
from pysnmp.entity.rfc3413.oneliner import cmdgen | ||
|
||
disktable_id = '1.3.6.1.4.1.6574.2.1.1.2' | ||
disktable_model = '1.3.6.1.4.1.6574.2.1.1.3' | ||
disktable_temp = '1.3.6.1.4.1.6574.2.1.1.6' | ||
sys_temperature = '1.3.6.1.4.1.6574.1.2.0' | ||
|
||
class SynologySNMPClient(object): | ||
def __init__(self, host, port, community): | ||
self.hostname = host | ||
self.transport = cmdgen.UdpTransportTarget((host, int(port))) | ||
self.auth = cmdgen.CommunityData('test-agent', community) | ||
self.gen = cmdgen.CommandGenerator() | ||
|
||
def _get_disks(self): | ||
disk_table = '1.3.6.1.4.1.6574.2.1' | ||
errorIndication, errorStatus, errorIndex, varBindTable = self.gen.bulkCmd( | ||
self.auth, | ||
self.transport, | ||
0, 24, | ||
disk_table) | ||
|
||
if errorIndication: | ||
logging.error("SNMP bulkCmd for devices failed: %s, %s, %s" % (errorIndication, errorStatus, errorIndex)) | ||
return | ||
|
||
devices = {} | ||
for row in varBindTable: | ||
for oid, value in row: | ||
oid = str(oid) | ||
if not oid.startswith(disk_table): | ||
continue | ||
|
||
disk_id = oid[oid.rindex('.')+1:] | ||
|
||
values = devices.get(disk_id, [None, None, None]) | ||
if oid.startswith(disktable_id): | ||
values[0] = str(value).strip() | ||
if oid.startswith(disktable_model): | ||
values[1] = str(value).strip() | ||
if oid.startswith(disktable_temp): | ||
values[2] = int(value) | ||
devices[disk_id] = values | ||
|
||
for x in sorted(devices.keys()): | ||
yield tuple([x] + devices[x]) | ||
|
||
def _get_sys_temperature(self): | ||
errorIndication, errorStatus, errorIndex, varBindTable = self.gen.getCmd( | ||
self.auth, | ||
self.transport, | ||
sys_temperature) | ||
|
||
if errorIndication: | ||
logging.error("SNMP getCmd for %s failed: %s, %s, %s" % (sys_temperature, errorIndication, errorStatus, errorIndex)) | ||
return None | ||
|
||
return int(varBindTable[0][1]) | ||
|
||
def print_config(self): | ||
print """multigraph synology_hdd_temperatures | ||
host_name {hostname} | ||
graph_title HDD temperatures on {hostname} | ||
graph_vlabel Temperature in °C | ||
graph_args --base 1000 | ||
graph_category system | ||
graph_info HDD temperatures on {hostname}""".format(hostname=self.hostname) | ||
|
||
for id, name, model, temp in self._get_disks(): | ||
print """disk{disk_id}.info Temperature of {name} ({model}) | ||
disk{disk_id}.label {name} ({model}) | ||
disk{disk_id}.type GAUGE | ||
disk{disk_id}.min 0""".format(disk_id=id, name=name, model=model) | ||
|
||
|
||
print """multigraph synology_sys_temperature | ||
host_name {hostname} | ||
graph_title System temperatures of {hostname} | ||
graph_vlabel Temperature in °C | ||
graph_args --base 1000 | ||
graph_category system | ||
graph_info System temperature of {hostname} | ||
sys_temp.info System temperature | ||
sys_temp.label Temperature | ||
sys_temp.type GAUGE | ||
sys_temp.min 0 | ||
""".format(hostname=self.hostname) | ||
|
||
def execute(self): | ||
print """multigraph synology_hdd_temperatures""" | ||
for id, name, model, temp in self._get_disks(): | ||
print """disk{disk_id}.value {temp}""".format(disk_id=id, temp=temp) | ||
|
||
print """multigraph synology_sys_temperature""" | ||
print "sys_temp.value {temp}".format(temp=self._get_sys_temperature()) | ||
|
||
|
||
host = None | ||
port = os.getenv('port', 161) | ||
community = os.getenv('community', None) | ||
debug = bool(os.getenv('MUNIN_DEBUG', os.getenv('DEBUG', 0))) | ||
|
||
if debug: | ||
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)-7s %(message)s') | ||
|
||
try: | ||
match = re.search("^(?:|.*\/)snmp_([^_]+)_synology$", sys.argv[0]) | ||
host = match.group(1) | ||
match = re.search("^([^:]+):(\d+)$", host) | ||
if match is not None: | ||
host = match.group(1) | ||
port = match.group(2) | ||
except Exception as ex: | ||
logging.error("Caught exception: %s" % ex) | ||
|
||
|
||
if "snmpconf" in sys.argv[1:]: | ||
print "require 1.3.6.1.4.1.6574.2.1.1" | ||
sys.exit(0) | ||
else: | ||
if not (host and port and community): | ||
print "# Bad configuration. Cannot run with Host=%s, port=%s and community=%s" % (host, port, community) | ||
sys.exit(1) | ||
|
||
c = SynologySNMPClient(host, port, community) | ||
|
||
if "config" in sys.argv[1:]: | ||
c.print_config() | ||
else: | ||
c.execute() |