]> arthur.barton.de Git - netdata.git/blob - node.d/snmp.node.js
converted from dos to unix
[netdata.git] / node.d / snmp.node.js
1 'use strict';
2
3 // This program will connect to one or more SNMP Agents
4
5 // example configuration in /etc/netdata/snmp.conf
6 /*
7 {
8         "enable_autodetect": false,
9         "update_every": 5,
10         "servers": [
11                 {
12                         "hostname": "10.11.12.8",
13                         "community": "public",
14                         "update_every": 10,
15                         "options": { "timeout": 10000 },
16                         "charts": {
17                                 "snmp_switch.bandwidth_port1": {
18                                         "title": "Switch Bandwidth for port 1",
19                                         "units": "kilobits/s",
20                                         "type": "area",
21                                         "priority": 1,
22                                         "dimensions": {
23                                                 "in": {
24                                                         "oid": "1.3.6.1.2.1.2.2.1.10.1",
25                                                         "algorithm": "incremental",
26                                                         "multiplier": 8,
27                                                         "divisor": 1024
28                                                 },
29                                                 "out": {
30                                                         "oid": "1.3.6.1.2.1.2.2.1.16.1",
31                                                         "algorithm": "incremental",
32                                                         "multiplier": -8,
33                                                         "divisor": 1024
34                                                 }
35                                         }
36                                 },
37                                 "snmp_switch.bandwidth_port2": {
38                                         "title": "Switch Bandwidth for port 2",
39                                         "units": "kilobits/s",
40                                         "type": "area",
41                                         "priority": 1,
42                                         "dimensions": {
43                                                 "in": {
44                                                         "oid": "1.3.6.1.2.1.2.2.1.10.2",
45                                                         "algorithm": "incremental",
46                                                         "multiplier": 8,
47                                                         "divisor": 1024
48                                                 },
49                                                 "out": {
50                                                         "oid": "1.3.6.1.2.1.2.2.1.16.2",
51                                                         "algorithm": "incremental",
52                                                         "multiplier": -8,
53                                                         "divisor": 1024
54                                                 }
55                                         }
56                                 }
57                         }
58                 }
59         ]
60 }
61 */
62
63 // You can also give ranges of charts like the following.
64 // This will append 1-24 to id, title, oid (on each dimension)
65 // so that 24 charts will be created.
66 /*
67 {
68         "enable_autodetect": false,
69         "update_every": 10,
70         "servers": [
71                 {
72                         "hostname": "10.11.12.8",
73                         "community": "public",
74                         "update_every": 10,
75                         "options": { "timeout": 20000 },
76                         "charts": {
77                                 "snmp_switch.bandwidth_port": {
78                                         "title": "Switch Bandwidth for port ",
79                                         "units": "kilobits/s",
80                                         "type": "area",
81                                         "priority": 1,
82                                         "multiply_range": [ 1, 24 ],
83                                         "dimensions": {
84                                                 "in": {
85                                                         "oid": "1.3.6.1.2.1.2.2.1.10",
86                                                         "algorithm": "incremental",
87                                                         "multiplier": 8,
88                                                         "divisor": 1024
89                                                 },
90                                                 "out": {
91                                                         "oid": "1.3.6.1.2.1.2.2.1.16",
92                                                         "algorithm": "incremental",
93                                                         "multiplier": -8,
94                                                         "divisor": 1024
95                                                 }
96                                         }
97                                 }
98                         }
99                 }
100         ]
101 }
102 */
103
104 var net_snmp = require('net-snmp');
105 var extend = require('extend');
106 var netdata = require('netdata');
107
108 if(netdata.options.DEBUG === true) netdata.debug('loaded ' + __filename + ' plugin');
109
110 netdata.processors.snmp = {
111         name: 'snmp',
112
113         process: function(service, callback) {
114                 if(typeof service.snmp_oids === 'undefined' || service.snmp_oids === null || service.snmp_oids.length === 0) {
115                         // this is the first time we see this service
116
117                         if(netdata.options.DEBUG === true)
118                                 netdata.debug(service.module.name + ': ' + service.name + ': preparing ' + this.name + ' OIDs');
119
120                         // build an index of all OIDs
121                         service.snmp_oids_index = {};
122                         for(var c in service.request.charts) {
123                                 // for each chart
124
125                                 if(netdata.options.DEBUG === true)
126                                         netdata.debug(service.module.name + ': ' + service.name + ': indexing ' + this.name + ' chart: ' + c);
127
128                                 for(var d in service.request.charts[c].dimensions) {
129                                         // for each dimension in the chart
130
131                                         if(netdata.options.DEBUG === true)
132                                                 netdata.debug(service.module.name + ': ' + service.name + ': indexing ' + this.name + ' chart: ' + c + ', dimension: ' + d + ', OID: ' + service.request.charts[c].dimensions[d].oid);
133
134                                         // link it to the point we need to set the value to
135                                         service.snmp_oids_index[service.request.charts[c].dimensions[d].oid] = service.request.charts[c].dimensions[d];
136
137                                         // and set the value to null
138                                         service.request.charts[c].dimensions[d].value = null;
139                                 }
140                         }
141                         if(netdata.options.DEBUG === true)
142                                 netdata.debug(service.module.name + ': ' + service.name + ': indexed ' + this.name + ' OIDs: ' + netdata.stringify(service.snmp_oids_index));
143
144                         // now create the array of OIDs needed by net-snmp
145                         service.snmp_oids = new Array();
146                         for(var o in service.snmp_oids_index)
147                                 service.snmp_oids.push(o);
148
149                         if(netdata.options.DEBUG === true)
150                                 netdata.debug(service.module.name + ': ' + service.name + ': final list of ' + this.name + ' OIDs: ' + netdata.stringify(service.snmp_oids));
151                 }
152
153                 if(service.snmp_oids.length === 0) {
154                         // no OIDs found for this service
155
156                         if(netdata.options.DEBUG === true)
157                                 service.error('no OIDs to process.');
158
159                         callback(null);
160                         return;
161                 }
162
163                 if(typeof service.snmp_session === 'undefined' || service.snmp_session === null) {
164                         // no SNMP session has been created for this service
165                         // the SNMP session is just the initialization of NET-SNMP
166
167                         if(netdata.options.DEBUG === true)
168                                 netdata.debug(service.module.name + ': ' + service.name + ': opening ' + this.name + ' session on ' + service.request.hostname + ' community ' + service.request.community + ' options ' + netdata.stringify(service.request.options));
169
170                         // create the SNMP session
171                         service.snmp_session = net_snmp.createSession (service.request.hostname, service.request.community, service.request.options);
172
173                         if(netdata.options.DEBUG === true)
174                                 netdata.debug(service.module.name + ': ' + service.name + ': got ' + this.name + ' session: ' + netdata.stringify(service.snmp_session));
175
176                         // if we later need traps, this is how to do it:
177                         //service.snmp_session.trap(net_snmp.TrapType.LinkDown, function(error) {
178                         //      if(error) console.error('trap error: ' + netdata.stringify(error));
179                         //});
180                 }
181
182                 // do it, get the SNMP values for the sessions we need
183                 service.snmp_session.get(service.snmp_oids, function(error, varbinds) {
184                         var ok = 0, failed = 0;
185
186                         if(error) {
187                                 service.error('Received error = ' + netdata.stringify(error) + ' varbinds = ' + netdata.stringify(varbinds));
188                         }
189                         else {
190                                 if(netdata.options.DEBUG === true)
191                                         netdata.debug(service.module.name + ': ' + service.name + ': got valid ' + service.module.name + ' response: ' + netdata.stringify(varbinds));
192
193                                 for(var i = 0; i < varbinds.length; i++) {
194                                         if(net_snmp.isVarbindError(varbinds[i])) {
195                                                 if(netdata.options.DEBUG === true)
196                                                         netdata.debug(service.module.name + ': ' + service.name + ': failed ' + service.module.name + ' get for OIDs ' + varbinds[i].oid);
197
198                                                 service.error('OID ' + varbinds[i].oid + ' gave error: ' + snmp.varbindError(varbinds[i]));
199                                                 service.snmp_oids_index[varbinds[i].oid].value = null;
200                                                 failed++;
201                                         }
202                                         else {
203                                                 if(netdata.options.DEBUG === true)
204                                                         netdata.debug(service.module.name + ': ' + service.name + ': found ' + service.module.name + ' value of OIDs ' + varbinds[i].oid + " = " + varbinds[i].value);
205
206                                                 service.snmp_oids_index[varbinds[i].oid].value = varbinds[i].value;
207                                                 ok++;
208                                         }
209                                 }
210
211                                 if(netdata.options.DEBUG === true)
212                                         netdata.debug(service.module.name + ': ' + service.name + ': finished ' + service.module.name + ' with ' + ok + ' successful and ' + failed + ' failed values');
213                         }
214                         
215                         callback((ok > 0)?{ ok: ok, failed: failed }:null);
216                 });
217         }
218 };
219
220 var snmp = {
221         name: __filename,
222         enable_autodetect: true,
223         update_every: 1,
224
225         charts: {},
226
227         processResponse: function(service, data) {
228                 if(data !== null) {
229                         if(service.added !== true)
230                                 service.commit();
231
232                         for(var c in service.request.charts) {
233                                 var chart = snmp.charts[c];
234
235                                 if(typeof chart === 'undefined') {
236                                         chart = service.chart(c, service.request.charts[c]);
237                                         snmp.charts[c] = chart;
238                                 }
239
240                                 service.begin(chart);
241                                 
242                                 for( var d in service.request.charts[c].dimensions )
243                                         if(service.request.charts[c].dimensions[d].value !== null)
244                                                 service.set(d, service.request.charts[c].dimensions[d].value);
245
246                                 service.end();
247                         }
248                 }
249         },
250
251         // module.serviceExecute()
252         // this function is called only from this module
253         // its purpose is to prepare the request and call
254         // netdata.serviceExecute()
255         serviceExecute: function(conf) {
256                 if(netdata.options.DEBUG === true)
257                         netdata.debug(this.name + ': snmp hostname: ' + conf.hostname + ', update_every: ' + conf.update_every);
258
259                 var service = netdata.service({
260                         name: conf.hostname,
261                         request: conf,
262                         update_every: conf.update_every,
263                         module: this,
264                         processor: netdata.processors.snmp
265                 });
266
267                 // multiply the charts, if required
268                 for(var c in service.request.charts) {
269                         if(netdata.options.DEBUG === true)
270                                 netdata.debug(this.name + ': snmp hostname: ' + conf.hostname + ', examining chart: ' + c);
271
272                         if(typeof service.request.charts[c].update_every === 'undefined')
273                                 service.request.charts[c].update_every = service.update_every;
274
275                         if(typeof service.request.charts[c].multiply_range !== 'undefined') {
276                                 var from = service.request.charts[c].multiply_range[0];
277                                 var to = service.request.charts[c].multiply_range[1];
278                                 var prio = service.request.charts[c].priority || 1;
279
280                                 while(from <= to) {
281                                         var id = c + from.toString();
282                                         var chart = extend(true, {}, service.request.charts[c]);
283                                         chart.title += from.toString();
284                                         chart.priority = prio++;
285                                         for(var d in chart.dimensions) {
286                                                 chart.dimensions[d].oid += '.' + from.toString();
287                                         }
288                                         service.request.charts[id] = chart;
289                                         from++;
290                                 }
291
292                                 delete service.request.charts[c];
293                         }
294                 }
295
296                 service.execute(this.processResponse);
297         },
298
299         configure: function(config) {
300                 var added = 0;
301
302                 if(typeof(config.servers) !== 'undefined') {
303                         var len = config.servers.length;
304                         while(len--) {
305                                 if(typeof config.servers[len].update_every === 'undefined')
306                                         config.servers[len].update_every = this.update_every;
307
308                                 this.serviceExecute(config.servers[len]);
309                                 added++;
310                         }
311                 }
312
313                 return added;
314         },
315
316         // module.update()
317         // this is called repeatidly to collect data, by calling
318         // service.execute()
319         update: function(service, callback) {
320                 service.execute(function(serv, data) {
321                         service.module.processResponse(serv, data);
322                         callback();
323                 });
324         },
325 };
326
327 module.exports = snmp;