-
Notifications
You must be signed in to change notification settings - Fork 0
/
snmp2graphite.py
executable file
·144 lines (131 loc) · 5.8 KB
/
snmp2graphite.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#!/usr/bin/env python
# This program runs as a daemon, collects switch/router interface counter data, and sends
# the metrics to Graphite. It also serves a simple HTTP service that organizes links for
# the interfaces it monitors, as to create a dashboard of graphs without needing to browse
# and click through the Graphite UI or laboriously create your own dashboards for hundreds
# of interfaces.
# User Variables:
# PER_SECOND Display value perSecond? Default is per INTERVAL (requires patch or graphite>0.10)
# SNMP_COMMUNITY Set this to the SNMPv2 community used to pull stats from your network gear
# CARBON_SERVER The hostname/IP used to address your Carbon-Cache
# CARBON_PORT The TCP port to which metrics will be sent
# GRAPHITE_SERVER The hostname for the Graphite server that will appear in Dashboards
# GRAPHITE_PREFIX The Graphite node path under which these metrics will be stored (must end with ".")
# WEB_SERVER_HOST The IP address(es) that will serve Dashboard pages
# WEB_SERVER_PORT The TCP port that will serve Dashboard pages
# IFACE_EXCEPT A list of strings, for which any interface containing these will not be graphed
# HOST_LIST Hostnames of routers/switches to poll
import os
import netsnmp
import time
import socket
import threading
import cherrypy
INTERVAL = 60
SNMP_VERSION = 2
# /USER VARIABLES/
PER_SECOND = 1
SNMP_COMMUNITY = "my_community"
CARBON_SERVER = "carbon_server"
CARBON_PORT = 2003
GRAPHITE_SERVER = "graphite_server"
GRAPHITE_PREFIX = "network.switches."
WEB_SERVER_HOST = "0.0.0.0"
WEB_SERVER_PORT = 8111
IFACE_EXCEPT = [ "Vlan", "Null", ".0", "bme", "vcp", "lsi", "dsc", "lo0", "vlan", "tap", "gre", "ipip", "pime", "pimd", "mtun" ]
HOST_LIST = [ "router1", "switch1", "linux-box1" ]
port_list = {} #this is dynamic
for hn in HOST_LIST:
port_list[hn] = []
cherrypy.config.update({'server.socket_host': WEB_SERVER_HOST,
'server.socket_port': WEB_SERVER_PORT,
})
class BaseCP(object):
@cherrypy.expose
def default(self,*args,**kwargs):
try:
args[0]
except:
html_body = ""
html_top = "<html><head><title>Switch Graphs</title></head><body>"
for x in HOST_LIST:
html_body+="<a href=\"http://" + cherrypy.request.headers['Host'] + "/" + x + "\">" + x + "</a><br>"
html_end = "</body></html>"
return html_top + html_body + html_end
try:
port_list[args[0]]
except:
return "host not found"
else:
html_body = ""
html_top = "<html><head><title>" + args[0] + "</title></head><body>"
for x in port_list[args[0]]:
if (PER_SECOND == 0):
html_body+="<img src=\"http://" + GRAPHITE_SERVER + "/render?target=nonNegativeDerivative%28" + GRAPHITE_PREFIX + args[0] + ".if." + x + "-*,18446744073709551615%29&from=-60min&height=200&width=600\">"
if (PER_SECOND == 1):
html_body+="<img src=\"http://" + GRAPHITE_SERVER + "/render?target=perSecond%28" + GRAPHITE_PREFIX + args[0] + ".if." + x + "-*%29&from=-60min&height=200&width=600\">"
html_end = "</body></html>"
return html_top + html_body + html_end
def schedule_collect(interval, collector, hst, vrs, comm, num_runs = 0):
if num_runs != 1:
threading.Timer(interval, schedule_collect, [interval, collector, hst, vrs, comm, 0 if num_runs == 0 else num_runs-1]).start()
collector(hst, vrs, comm)
def do_collect(hst, vrs, comm):
port_list[hst] = []
sock = socket.socket()
try:
sock.connect( (CARBON_SERVER,CARBON_PORT) )
except:
traceback.print_exc()
now = int(time.time())
args = {
"Version": SNMP_VERSION,
"DestHost": hst,
"Community": comm
}
sess = netsnmp.Session (**args)
INDEX_POS = 0
MIB_ROOT = "ifIndex"
MIB_CURR = MIB_ROOT
RESULTS = {}
while (MIB_ROOT == MIB_CURR):
vars = netsnmp.VarList(netsnmp.Varbind(MIB_CURR,INDEX_POS))
vals = sess.getbulk(0,16,vars)
for i in vars:
if (i.tag == MIB_CURR):
KEY = i.iid
RESULTS[KEY] = i
INDEX_POS = int(vars[-1].iid)
MIB_CURR = vars[-1].tag
for idx in RESULTS:
descr, oper, cin, cout = netsnmp.snmpget(
netsnmp.Varbind("IF-MIB::ifDescr", idx),
netsnmp.Varbind("IF-MIB::ifOperStatus", idx),
netsnmp.Varbind("IF-MIB::ifHCInOctets", idx),
netsnmp.Varbind("IF-MIB::ifHCOutOctets", idx),
**args)
assert(descr is not None and
cin is not None and
cout is not None)
if descr == "lo":
continue
if oper != "1":
continue
skip = 0
for term in IFACE_EXCEPT:
if term in descr:
skip = 1
if skip == 0:
descr = descr.replace("/","-")
descr = descr.replace("SuperBlade Gigabit Switch BMB-GEM-003, Port #","port-")
port_list[hst].append(descr)
graphiteMessage = GRAPHITE_PREFIX + "%s.if.%s-%s %s %d\n" % (hst,descr,"in",cin,now)
sock.sendall(graphiteMessage)
graphiteMessage = GRAPHITE_PREFIX + "%s.if.%s-%s %s %d\n" % (hst,descr,"out",cout,now)
sock.sendall(graphiteMessage)
sock.close()
for myhost in HOST_LIST:
schedule_collect(INTERVAL, do_collect, myhost, SNMP_VERSION, SNMP_COMMUNITY, 0)
if __name__ == "__main__":
serverThread = threading.Thread(target = cherrypy.quickstart(BaseCP()))
serverThread.start()