root / plugins / synology / snmp__synology @ 7063330e
Historique | Voir | Annoter | Télécharger (5,63 ko)
| 1 |
#!/usr/bin/python |
|---|---|
| 2 |
# -*- coding: utf-8 -*- |
| 3 |
|
| 4 |
# Copyright (C) 2014 Johann Schmitz <johann@j-schmitz.net> |
| 5 |
# |
| 6 |
# This program is free software; you can redistribute it and/or modify |
| 7 |
# it under the terms of the GNU Library General Public License as published by |
| 8 |
# the Free Software Foundation; version 2 only |
| 9 |
# |
| 10 |
# This program is distributed in the hope that it will be useful, |
| 11 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 13 |
# GNU Library General Public License for more details. |
| 14 |
# |
| 15 |
# You should have received a copy of the GNU Library General Public License |
| 16 |
# along with this program; if not, write to the Free Software |
| 17 |
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
| 18 |
# |
| 19 |
|
| 20 |
""" |
| 21 |
=head1 NAME |
| 22 |
|
| 23 |
snmp__synology_ - Health and system status monitoring plugin for Synology NAS systems |
| 24 |
|
| 25 |
=head1 CONFIGURATION |
| 26 |
|
| 27 |
Make sure your Synology device is accessible via SNMP (e.g. via snmpwalk) and the munin-node |
| 28 |
has been configured correctly. |
| 29 |
|
| 30 |
=head1 MAGIC MARKERS |
| 31 |
|
| 32 |
#%# family=snmpauto |
| 33 |
#%# capabilities=snmpconf |
| 34 |
|
| 35 |
=head1 VERSION |
| 36 |
|
| 37 |
0.0.1 |
| 38 |
|
| 39 |
=head1 BUGS |
| 40 |
|
| 41 |
Open a ticket at https://github.com/ercpe/contrib if you find one. |
| 42 |
|
| 43 |
=head1 AUTHOR |
| 44 |
|
| 45 |
Johann Schmitz <johann@j-schmitz.net> |
| 46 |
|
| 47 |
=head1 LICENSE |
| 48 |
|
| 49 |
GPLv2 |
| 50 |
|
| 51 |
=cut |
| 52 |
""" |
| 53 |
|
| 54 |
import re |
| 55 |
import sys |
| 56 |
import os |
| 57 |
import logging |
| 58 |
|
| 59 |
from pysnmp.entity.rfc3413.oneliner import cmdgen |
| 60 |
|
| 61 |
disktable_id = '1.3.6.1.4.1.6574.2.1.1.2' |
| 62 |
disktable_model = '1.3.6.1.4.1.6574.2.1.1.3' |
| 63 |
disktable_temp = '1.3.6.1.4.1.6574.2.1.1.6' |
| 64 |
sys_temperature = '1.3.6.1.4.1.6574.1.2.0' |
| 65 |
|
| 66 |
|
| 67 |
class SynologySNMPClient(object): |
| 68 |
def __init__(self, host, port, community): |
| 69 |
self.hostname = host |
| 70 |
self.transport = cmdgen.UdpTransportTarget((host, int(port))) |
| 71 |
self.auth = cmdgen.CommunityData('test-agent', community)
|
| 72 |
self.gen = cmdgen.CommandGenerator() |
| 73 |
|
| 74 |
def _get_disks(self): |
| 75 |
disk_table = '1.3.6.1.4.1.6574.2.1' |
| 76 |
errorIndication, errorStatus, errorIndex, varBindTable = self.gen.bulkCmd( |
| 77 |
self.auth, |
| 78 |
self.transport, |
| 79 |
0, 24, |
| 80 |
disk_table) |
| 81 |
|
| 82 |
if errorIndication: |
| 83 |
logging.error("SNMP bulkCmd for devices failed: %s, %s, %s",
|
| 84 |
errorIndication, errorStatus, errorIndex) |
| 85 |
return |
| 86 |
|
| 87 |
devices = {}
|
| 88 |
for row in varBindTable: |
| 89 |
for oid, value in row: |
| 90 |
oid = str(oid) |
| 91 |
if not oid.startswith(disk_table): |
| 92 |
continue |
| 93 |
|
| 94 |
disk_id = oid[oid.rindex('.') + 1:]
|
| 95 |
|
| 96 |
values = devices.get(disk_id, [None, None, None]) |
| 97 |
if oid.startswith(disktable_id): |
| 98 |
values[0] = str(value).strip() |
| 99 |
if oid.startswith(disktable_model): |
| 100 |
values[1] = str(value).strip() |
| 101 |
if oid.startswith(disktable_temp): |
| 102 |
values[2] = int(value) |
| 103 |
devices[disk_id] = values |
| 104 |
|
| 105 |
for x in sorted(devices.keys()): |
| 106 |
yield tuple([x] + devices[x]) |
| 107 |
|
| 108 |
def _get_sys_temperature(self): |
| 109 |
errorIndication, errorStatus, errorIndex, varBindTable = self.gen.getCmd( |
| 110 |
self.auth, |
| 111 |
self.transport, |
| 112 |
sys_temperature) |
| 113 |
|
| 114 |
if errorIndication: |
| 115 |
logging.error("SNMP getCmd for %s failed: %s, %s, %s",
|
| 116 |
sys_temperature, errorIndication, errorStatus, errorIndex) |
| 117 |
return None |
| 118 |
|
| 119 |
return int(varBindTable[0][1]) |
| 120 |
|
| 121 |
def print_config(self): |
| 122 |
print("""multigraph synology_hdd_temperatures
|
| 123 |
host_name {hostname}
|
| 124 |
graph_title HDD temperatures on {hostname}
|
| 125 |
graph_vlabel Temperature in °C |
| 126 |
graph_args --base 1000 |
| 127 |
graph_category sensors |
| 128 |
graph_info HDD temperatures on {hostname}""".format(hostname=self.hostname))
|
| 129 |
|
| 130 |
for id, name, model, temp in self._get_disks(): |
| 131 |
print("""disk{disk_id}.info Temperature of {name} ({model})
|
| 132 |
disk{disk_id}.label {name} ({model})
|
| 133 |
disk{disk_id}.type GAUGE
|
| 134 |
disk{disk_id}.min 0""".format(disk_id=id, name=name, model=model))
|
| 135 |
|
| 136 |
print("""multigraph synology_sys_temperature
|
| 137 |
host_name {hostname}
|
| 138 |
graph_title System temperatures of {hostname}
|
| 139 |
graph_vlabel Temperature in °C |
| 140 |
graph_args --base 1000 |
| 141 |
graph_category sensors |
| 142 |
graph_info System temperature of {hostname}
|
| 143 |
sys_temp.info System temperature |
| 144 |
sys_temp.label Temperature |
| 145 |
sys_temp.type GAUGE |
| 146 |
sys_temp.min 0 |
| 147 |
""".format(hostname=self.hostname)) |
| 148 |
|
| 149 |
def execute(self): |
| 150 |
print("""multigraph synology_hdd_temperatures""")
|
| 151 |
for id, name, model, temp in self._get_disks(): |
| 152 |
print("""disk{disk_id}.value {temp}""".format(disk_id=id, temp=temp))
|
| 153 |
|
| 154 |
print("""multigraph synology_sys_temperature""")
|
| 155 |
print("sys_temp.value {temp}".format(temp=self._get_sys_temperature()))
|
| 156 |
|
| 157 |
|
| 158 |
host = None |
| 159 |
port = os.getenv('port', 161)
|
| 160 |
community = os.getenv('community', None)
|
| 161 |
debug = bool(os.getenv('MUNIN_DEBUG', os.getenv('DEBUG', 0)))
|
| 162 |
|
| 163 |
if debug: |
| 164 |
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)-7s %(message)s') |
| 165 |
|
| 166 |
try: |
| 167 |
match = re.search(r"^(?:|.*\/)snmp_([^_]+)_synology$", sys.argv[0]) |
| 168 |
host = match.group(1) |
| 169 |
match = re.search(r"^([^:]+):(\d+)$", host) |
| 170 |
if match is not None: |
| 171 |
host = match.group(1) |
| 172 |
port = match.group(2) |
| 173 |
except Exception as ex: |
| 174 |
logging.error("Caught exception: %s" % ex)
|
| 175 |
|
| 176 |
|
| 177 |
if "snmpconf" in sys.argv[1:]: |
| 178 |
print("require 1.3.6.1.4.1.6574.2.1.1")
|
| 179 |
sys.exit(0) |
| 180 |
else: |
| 181 |
if not (host and port and community): |
| 182 |
print("# Bad configuration. Cannot run with Host=%s, port=%s and community=%s"
|
| 183 |
% (host, port, community)) |
| 184 |
sys.exit(1) |
| 185 |
|
| 186 |
c = SynologySNMPClient(host, port, community) |
| 187 |
|
| 188 |
if "config" in sys.argv[1:]: |
| 189 |
c.print_config() |
| 190 |
else: |
| 191 |
c.execute() |
