|
1 |
|
2 /* |
|
3 * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. |
|
4 * |
|
5 * U.S. Government Rights - Commercial software. Government users are subject to |
|
6 * the Sun Microsystems, Inc. standard license agreement and applicable |
|
7 * provisions of the FAR and its supplements. |
|
8 * |
|
9 * |
|
10 * This distribution may include materials developed by third parties. Sun, Sun |
|
11 * Microsystems, the Sun logo and Solaris are trademarks or registered |
|
12 * trademarks of Sun Microsystems, Inc. in the U.S. and other countries. |
|
13 * |
|
14 */ |
|
15 |
|
16 /* |
|
17 * Note: this file originally auto-generated by mib2c using : |
|
18 * mib2c.scalar.conf,v 1.5 2002/07/18 14:18:52 dts12 Exp $ |
|
19 */ |
|
20 |
|
21 /* |
|
22 * This Module implements all the nodes in health-monitor-mib.mib. |
|
23 * mib2c.scalar.conf is used to generate template for all nodes except the |
|
24 * hmDiskGroup mib2c.iterate.conf is used to generate template for |
|
25 * hmDiskGroup (which contains a Table) The two templates are merged so that |
|
26 * all the implementation for health-monitor-mib is present as one module. |
|
27 * Template functions are filled and new functions are added to do the |
|
28 * following: 1) Data Acquisition, 2) Automatic refresh, 3) trap generation, |
|
29 * 4) subscribe for thresholds from health_monitor.conf file. |
|
30 */ |
|
31 |
|
32 |
|
33 #include <net-snmp/net-snmp-config.h> |
|
34 #include <net-snmp/net-snmp-includes.h> |
|
35 #include <net-snmp/agent/net-snmp-agent-includes.h> |
|
36 #include "healthMonitor.h" |
|
37 #include <netdb.h> |
|
38 |
|
39 |
|
40 /* |
|
41 * DATA: Following are the variables in which data collected for various |
|
42 * nodes is stored. The values are refreshed every "refresh interval" |
|
43 * (default 60 seconds). The value stored in this variable is returned |
|
44 * whenever a "get" request comes. |
|
45 */ |
|
46 |
|
47 /* Data for SWAP node */ |
|
48 int swapavail_data, swapresv_data, swapalloc_data, swapused_data, |
|
49 swaptotal_data; |
|
50 |
|
51 /* Data for Kernel node */ |
|
52 ulong sum_smtx = 0; |
|
53 int ncpus; |
|
54 |
|
55 /* Data for NFS node */ |
|
56 double calls; |
|
57 int badcalls, retrans, badxids, timeouts, newcreds, badverfs, |
|
58 timers, nomem, cantsend, interrupts; |
|
59 char callsStr[8]; |
|
60 |
|
61 /* Data for CPU node */ |
|
62 int runque, waiting, swapque; |
|
63 |
|
64 /* Data for RAM node */ |
|
65 int handspread, scan; |
|
66 |
|
67 /* |
|
68 * Data for KMEM node . Only alloc_fail and mem_free are published through |
|
69 * the MIB |
|
70 */ |
|
71 int alloc, alloc_fail=0, buf_size, buf_avail, buf_total, buf_max; |
|
72 int mem_avail=0, mem_inuse=0, mem_free=0; |
|
73 |
|
74 /* |
|
75 * Data for DNLC node . hits, misses, hitrate and refrate are published |
|
76 * through the MIB. Rest of variables are temp data used for processing alarm |
|
77 * conditions. |
|
78 */ |
|
79 |
|
80 int firsttime = 1; |
|
81 int lasthits = 0; |
|
82 int lastmisses = 0; |
|
83 int prevhits = 0; |
|
84 int prevmisses = 0; |
|
85 long prevtime = 0; |
|
86 |
|
87 long hits, misses; |
|
88 long hitrate, refrate; |
|
89 |
|
90 /* |
|
91 * Data for diskGroup. We maintain the disk table in memory as a linked list |
|
92 * of hmDiskTable objects "head" points to the first memeber of the linked |
|
93 * list |
|
94 */ |
|
95 |
|
96 hmDiskTable *head; |
|
97 int diskCount; |
|
98 |
|
99 /* |
|
100 * Following are the variables that hold threshold's used to determine alarm |
|
101 * conditions. The variables are updated with threshold settings in |
|
102 * health_monitor.conf file, when module is initialized. |
|
103 */ |
|
104 |
|
105 /* Thresholds and States for SWAP node */ |
|
106 int threshold_swapavail_info = 500000, threshold_swapavail_warning = 100000, |
|
107 threshold_swapavail_error = 40000; |
|
108 |
|
109 int prev_SWAP_state = OK; |
|
110 int new_SWAP_state = OK; |
|
111 int SWAP_rule_state = NOTINIT; |
|
112 |
|
113 /* Thresholds for Kernel node */ |
|
114 ulong threshold_mutex_info = 200, threshold_mutex_warning = 500; |
|
115 |
|
116 int prev_mutex_state = OK; |
|
117 int new_mutex_state = OK; |
|
118 int Kernel_rule_state = NOTINIT; |
|
119 |
|
120 /* Thresholds for NFS node */ |
|
121 float threshold_mincalls = 0.1, threshold_badxids = 0.0, threshold_timeouts = 5.0; |
|
122 |
|
123 int prev_NFS_state = OK; |
|
124 int new_NFS_state = OK; |
|
125 int NFS_rule_state = NOTINIT; |
|
126 |
|
127 /* Thresholds for CPU node */ |
|
128 float threshold_cpuload_info = 1.0, threshold_cpuload_warning = 2.0, |
|
129 threshold_cpuload_error = 3.0; |
|
130 |
|
131 int prev_cpuload_state = OK; |
|
132 int new_cpuload_state = OK; |
|
133 int CPU_rule_state = NOTINIT; |
|
134 |
|
135 /* Thresholds for RAM node */ |
|
136 int threshold_restime_long = 600, threshold_restime_ok = 40, |
|
137 threshold_restime_error = 20; |
|
138 |
|
139 int prev_restime_state = OK; |
|
140 int new_restime_state = OK; |
|
141 int RAM_rule_state = NOTINIT; |
|
142 |
|
143 /* Thresholds for KMEM node */ |
|
144 int threshold_freemem_low = 1; |
|
145 int firstkmemerrs = 0, lastkmemerrs = 0; /* These must be Global |
|
146 * variables and |
|
147 * preserved across |
|
148 * invocation of |
|
149 * check_state_KMEM() |
|
150 * function */ |
|
151 |
|
152 int prev_kmem_state = OK; |
|
153 int new_kmem_state = OK; |
|
154 int KMEM_rule_state = NOTINIT; |
|
155 |
|
156 /* Thresholds for DNLC node */ |
|
157 |
|
158 float threshold_dnlc_active = 100.0, threshold_dnlc_warning = 80; |
|
159 |
|
160 int prev_dnlc_state = OK; |
|
161 int new_dnlc_state = OK; |
|
162 int DNLC_rule_state = NOTINIT; |
|
163 |
|
164 /* Thresholds for diskGroup */ |
|
165 |
|
166 long disk_busy_warning = 10.0, disk_busy_problem = 30.0, disk_svc_t_warning = 20.0, |
|
167 disk_svc_t_problem = 30.0; |
|
168 |
|
169 |
|
170 /* COMMON data variables */ |
|
171 |
|
172 u_char hostName[MAXHOSTNAMELEN], moduleName[15], statusOIDContext[5]; |
|
173 int hm_refresh_interval=60; |
|
174 time_t hm_prev_ref_time=1; |
|
175 time_t hm_prev_disk_ref=1; |
|
176 |
|
177 |
|
178 /** Initializes the healthMonitor module */ |
|
179 void |
|
180 init_healthMonitor(void) |
|
181 { |
|
182 |
|
183 int retCode; |
|
184 |
|
185 static oid hmSpinsOnMutexes_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 2, 1, 1, 0}; |
|
186 static oid hmTotProcInRunQueue_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 4, 1, 1, 0}; |
|
187 static oid hmTotRPCCalls_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 3, 1, 1, 0}; |
|
188 static oid hmUsedSwapSpace_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 1, 1, 4, 0}; |
|
189 static oid hmDNLCMisses_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 8, 1, 2, 0}; |
|
190 static oid hmReservedSwapSpace_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 1, 1, 2, 0}; |
|
191 static oid hmTotMemAllocFails_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 3, 1, 9, 0}; |
|
192 static oid hmAvailableSwapSpace_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 1, 1, 1, 0}; |
|
193 static oid hmDNLCHitRate_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 8, 1, 3, 0}; |
|
194 static oid hmDNLCHits_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 8, 1, 1, 0}; |
|
195 static oid hmAllocatedSwapSpace_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 1, 1, 3, 0}; |
|
196 static oid hmTotNumOfCPUs_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 2, 1, 2, 0}; |
|
197 static oid hmPageScanRate_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 6, 1, 2, 0}; |
|
198 static oid hmTimers_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 3, 1, 8, 0}; |
|
199 static oid hmTotBadRPCCalls_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 3, 1, 2, 0}; |
|
200 static oid hmDNLCRefRate_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 8, 1, 4, 0}; |
|
201 static oid hmTotSendFails_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 3, 1, 10, 0}; |
|
202 static oid hmTotFailedCallsBV_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 3, 1, 7, 0}; |
|
203 static oid hmTotNumOfAuthRefresh_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 3, 1, 6, 0}; |
|
204 static oid hmHandspread_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 6, 1, 1, 0}; |
|
205 static oid hmTotRPCRetransmissions_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 3, 1, 3, 0}; |
|
206 static oid hmKmemFreeMem_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 7, 1, 2, 0}; |
|
207 static oid hmTotBadRPCReplies_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 3, 1, 4, 0}; |
|
208 static oid hmKmemErrors_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 7, 1, 1, 0}; |
|
209 static oid hmTotProcReadyInSwap_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 4, 1, 3, 0}; |
|
210 static oid hmTotProcBlocked_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 4, 1, 2, 0}; |
|
211 static oid hmTotRPCCallsTimedOut_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 3, 1, 5, 0}; |
|
212 |
|
213 DEBUGMSGTL(("healthMonitor", "Initializing\n")); |
|
214 |
|
215 netsnmp_register_read_only_instance(netsnmp_create_handler_registration |
|
216 ("hmSpinsOnMutexes", |
|
217 get_hmSpinsOnMutexes, |
|
218 hmSpinsOnMutexes_oid, |
|
219 OID_LENGTH(hmSpinsOnMutexes_oid), |
|
220 HANDLER_CAN_RONLY)); |
|
221 netsnmp_register_read_only_instance(netsnmp_create_handler_registration |
|
222 ("hmTotProcInRunQueue", |
|
223 get_hmTotProcInRunQueue, |
|
224 hmTotProcInRunQueue_oid, |
|
225 OID_LENGTH(hmTotProcInRunQueue_oid), |
|
226 HANDLER_CAN_RONLY)); |
|
227 netsnmp_register_read_only_instance(netsnmp_create_handler_registration |
|
228 ("hmTotRPCCalls", |
|
229 get_hmTotRPCCalls, |
|
230 hmTotRPCCalls_oid, |
|
231 OID_LENGTH(hmTotRPCCalls_oid), |
|
232 HANDLER_CAN_RONLY)); |
|
233 netsnmp_register_read_only_instance(netsnmp_create_handler_registration |
|
234 ("hmUsedSwapSpace", |
|
235 get_hmUsedSwapSpace, |
|
236 hmUsedSwapSpace_oid, |
|
237 OID_LENGTH(hmUsedSwapSpace_oid), |
|
238 HANDLER_CAN_RONLY)); |
|
239 netsnmp_register_read_only_instance(netsnmp_create_handler_registration |
|
240 ("hmDNLCMisses", |
|
241 get_hmDNLCMisses, |
|
242 hmDNLCMisses_oid, |
|
243 OID_LENGTH(hmDNLCMisses_oid), |
|
244 HANDLER_CAN_RONLY)); |
|
245 netsnmp_register_read_only_instance(netsnmp_create_handler_registration |
|
246 ("hmReservedSwapSpace", |
|
247 get_hmReservedSwapSpace, |
|
248 hmReservedSwapSpace_oid, |
|
249 OID_LENGTH(hmReservedSwapSpace_oid), |
|
250 HANDLER_CAN_RONLY)); |
|
251 netsnmp_register_read_only_instance(netsnmp_create_handler_registration |
|
252 ("hmTotMemAllocFails", |
|
253 get_hmTotMemAllocFails, |
|
254 hmTotMemAllocFails_oid, |
|
255 OID_LENGTH(hmTotMemAllocFails_oid), |
|
256 HANDLER_CAN_RONLY)); |
|
257 netsnmp_register_read_only_instance(netsnmp_create_handler_registration |
|
258 ("hmAvailableSwapSpace", |
|
259 get_hmAvailableSwapSpace, |
|
260 hmAvailableSwapSpace_oid, |
|
261 OID_LENGTH(hmAvailableSwapSpace_oid), |
|
262 HANDLER_CAN_RONLY)); |
|
263 netsnmp_register_read_only_instance(netsnmp_create_handler_registration |
|
264 ("hmDNLCHitRate", |
|
265 get_hmDNLCHitRate, |
|
266 hmDNLCHitRate_oid, |
|
267 OID_LENGTH(hmDNLCHitRate_oid), |
|
268 HANDLER_CAN_RONLY)); |
|
269 netsnmp_register_read_only_instance(netsnmp_create_handler_registration |
|
270 ("hmDNLCHits", |
|
271 get_hmDNLCHits, |
|
272 hmDNLCHits_oid, |
|
273 OID_LENGTH(hmDNLCHits_oid), |
|
274 HANDLER_CAN_RONLY)); |
|
275 netsnmp_register_read_only_instance(netsnmp_create_handler_registration |
|
276 ("hmAllocatedSwapSpace", |
|
277 get_hmAllocatedSwapSpace, |
|
278 hmAllocatedSwapSpace_oid, |
|
279 OID_LENGTH(hmAllocatedSwapSpace_oid), |
|
280 HANDLER_CAN_RONLY)); |
|
281 netsnmp_register_read_only_instance(netsnmp_create_handler_registration |
|
282 ("hmTotNumOfCPUs", |
|
283 get_hmTotNumOfCPUs, |
|
284 hmTotNumOfCPUs_oid, |
|
285 OID_LENGTH(hmTotNumOfCPUs_oid), |
|
286 HANDLER_CAN_RONLY)); |
|
287 netsnmp_register_read_only_instance(netsnmp_create_handler_registration |
|
288 ("hmPageScanRate", |
|
289 get_hmPageScanRate, |
|
290 hmPageScanRate_oid, |
|
291 OID_LENGTH(hmPageScanRate_oid), |
|
292 HANDLER_CAN_RONLY)); |
|
293 netsnmp_register_read_only_instance(netsnmp_create_handler_registration |
|
294 ("hmTimers", |
|
295 get_hmTimers, |
|
296 hmTimers_oid, |
|
297 OID_LENGTH(hmTimers_oid), |
|
298 HANDLER_CAN_RONLY)); |
|
299 netsnmp_register_read_only_instance(netsnmp_create_handler_registration |
|
300 ("hmTotBadRPCCalls", |
|
301 get_hmTotBadRPCCalls, |
|
302 hmTotBadRPCCalls_oid, |
|
303 OID_LENGTH(hmTotBadRPCCalls_oid), |
|
304 HANDLER_CAN_RONLY)); |
|
305 netsnmp_register_read_only_instance(netsnmp_create_handler_registration |
|
306 ("hmDNLCRefRate", |
|
307 get_hmDNLCRefRate, |
|
308 hmDNLCRefRate_oid, |
|
309 OID_LENGTH(hmDNLCRefRate_oid), |
|
310 HANDLER_CAN_RONLY)); |
|
311 netsnmp_register_read_only_instance(netsnmp_create_handler_registration |
|
312 ("hmTotSendFails", |
|
313 get_hmTotSendFails, |
|
314 hmTotSendFails_oid, |
|
315 OID_LENGTH(hmTotSendFails_oid), |
|
316 HANDLER_CAN_RONLY)); |
|
317 netsnmp_register_read_only_instance(netsnmp_create_handler_registration |
|
318 ("hmTotFailedCallsBV", |
|
319 get_hmTotFailedCallsBV, |
|
320 hmTotFailedCallsBV_oid, |
|
321 OID_LENGTH(hmTotFailedCallsBV_oid), |
|
322 HANDLER_CAN_RONLY)); |
|
323 netsnmp_register_read_only_instance(netsnmp_create_handler_registration |
|
324 ("hmTotNumOfAuthRefresh", |
|
325 get_hmTotNumOfAuthRefresh, |
|
326 hmTotNumOfAuthRefresh_oid, |
|
327 OID_LENGTH(hmTotNumOfAuthRefresh_oid), |
|
328 HANDLER_CAN_RONLY)); |
|
329 netsnmp_register_read_only_instance(netsnmp_create_handler_registration |
|
330 ("hmHandspread", |
|
331 get_hmHandspread, |
|
332 hmHandspread_oid, |
|
333 OID_LENGTH(hmHandspread_oid), |
|
334 HANDLER_CAN_RONLY)); |
|
335 netsnmp_register_read_only_instance(netsnmp_create_handler_registration |
|
336 ("hmTotRPCRetransmissions", |
|
337 get_hmTotRPCRetransmissions, |
|
338 hmTotRPCRetransmissions_oid, |
|
339 OID_LENGTH(hmTotRPCRetransmissions_oid), |
|
340 HANDLER_CAN_RONLY)); |
|
341 netsnmp_register_read_only_instance(netsnmp_create_handler_registration |
|
342 ("hmKmemFreeMem", |
|
343 get_hmKmemFreeMem, |
|
344 hmKmemFreeMem_oid, |
|
345 OID_LENGTH(hmKmemFreeMem_oid), |
|
346 HANDLER_CAN_RONLY)); |
|
347 netsnmp_register_read_only_instance(netsnmp_create_handler_registration |
|
348 ("hmTotBadRPCReplies", |
|
349 get_hmTotBadRPCReplies, |
|
350 hmTotBadRPCReplies_oid, |
|
351 OID_LENGTH(hmTotBadRPCReplies_oid), |
|
352 HANDLER_CAN_RONLY)); |
|
353 netsnmp_register_read_only_instance(netsnmp_create_handler_registration |
|
354 ("hmKmemErrors", |
|
355 get_hmKmemErrors, |
|
356 hmKmemErrors_oid, |
|
357 OID_LENGTH(hmKmemErrors_oid), |
|
358 HANDLER_CAN_RONLY)); |
|
359 netsnmp_register_read_only_instance(netsnmp_create_handler_registration |
|
360 ("hmTotProcReadyInSwap", |
|
361 get_hmTotProcReadyInSwap, |
|
362 hmTotProcReadyInSwap_oid, |
|
363 OID_LENGTH(hmTotProcReadyInSwap_oid), |
|
364 HANDLER_CAN_RONLY)); |
|
365 netsnmp_register_read_only_instance(netsnmp_create_handler_registration |
|
366 ("hmTotProcBlocked", |
|
367 get_hmTotProcBlocked, |
|
368 hmTotProcBlocked_oid, |
|
369 OID_LENGTH(hmTotProcBlocked_oid), |
|
370 HANDLER_CAN_RONLY)); |
|
371 netsnmp_register_read_only_instance(netsnmp_create_handler_registration |
|
372 ("hmTotRPCCallsTimedOut", |
|
373 get_hmTotRPCCallsTimedOut, |
|
374 hmTotRPCCallsTimedOut_oid, |
|
375 OID_LENGTH(hmTotRPCCallsTimedOut_oid), |
|
376 HANDLER_CAN_RONLY)); |
|
377 |
|
378 |
|
379 /* Initialize Disk stuff */ |
|
380 |
|
381 /* here we initialize all the tables we're planning on supporting */ |
|
382 |
|
383 initialize_table_hmDiskTable(); |
|
384 |
|
385 |
|
386 /* |
|
387 * Additions to init function to register callbacks for tokens. Whenever |
|
388 * a token is encountered in health_monitor.conf file, the function |
|
389 * read_health_monitor_thresholds is called by the agent |
|
390 */ |
|
391 |
|
392 register_config_handler("health_monitor", "hm_refresh_interval", |
|
393 read_health_monitor_thresholds, NULL, NULL); |
|
394 |
|
395 register_config_handler("health_monitor", "threshold_swapavail_info", |
|
396 read_health_monitor_thresholds, NULL, NULL); |
|
397 |
|
398 register_config_handler("health_monitor", "threshold_swapavail_warning", |
|
399 read_health_monitor_thresholds, NULL, NULL); |
|
400 |
|
401 register_config_handler("health_monitor", "threshold_swapavail_error", |
|
402 read_health_monitor_thresholds, NULL, NULL); |
|
403 |
|
404 register_config_handler("health_monitor", "threshold_mutex_info", |
|
405 read_health_monitor_thresholds, NULL, NULL); |
|
406 |
|
407 register_config_handler("health_monitor", "threshold_mutex_warning", |
|
408 read_health_monitor_thresholds, NULL, NULL); |
|
409 |
|
410 register_config_handler("health_monitor", "threshold_mincalls", |
|
411 read_health_monitor_thresholds, NULL, NULL); |
|
412 |
|
413 register_config_handler("health_monitor", "threshold_badxids", |
|
414 read_health_monitor_thresholds, NULL, NULL); |
|
415 |
|
416 register_config_handler("health_monitor", "threshold_timeouts", |
|
417 read_health_monitor_thresholds, NULL, NULL); |
|
418 |
|
419 register_config_handler("health_monitor", "threshold_cpuload_info", |
|
420 read_health_monitor_thresholds, NULL, NULL); |
|
421 |
|
422 register_config_handler("health_monitor", "threshold_cpuload_warning", |
|
423 read_health_monitor_thresholds, NULL, NULL); |
|
424 |
|
425 register_config_handler("health_monitor", "threshold_cpuload_error", |
|
426 read_health_monitor_thresholds, NULL, NULL); |
|
427 |
|
428 register_config_handler("health_monitor", "threshold_restime_long", |
|
429 read_health_monitor_thresholds, NULL, NULL); |
|
430 |
|
431 register_config_handler("health_monitor", "threshold_restime_ok", |
|
432 read_health_monitor_thresholds, NULL, NULL); |
|
433 |
|
434 register_config_handler("health_monitor", "threshold_restime_error", |
|
435 read_health_monitor_thresholds, NULL, NULL); |
|
436 |
|
437 register_config_handler("health_monitor", "threshold_freemem_low", |
|
438 read_health_monitor_thresholds, NULL, NULL); |
|
439 |
|
440 register_config_handler("health_monitor", "threshold_dnlc_active", |
|
441 read_health_monitor_thresholds, NULL, NULL); |
|
442 |
|
443 register_config_handler("health_monitor", "threshold_dnlc_warning", |
|
444 read_health_monitor_thresholds, NULL, NULL); |
|
445 |
|
446 register_config_handler("health_monitor", "disk_busy_warning", |
|
447 read_health_monitor_thresholds, NULL, NULL); |
|
448 |
|
449 register_config_handler("health_monitor", "disk_busy_problem", |
|
450 read_health_monitor_thresholds, NULL, NULL); |
|
451 |
|
452 register_config_handler("health_monitor", "disk_svc_t_warning", |
|
453 read_health_monitor_thresholds, NULL, NULL); |
|
454 |
|
455 register_config_handler("health_monitor", "disk_svc_t_problem", |
|
456 read_health_monitor_thresholds, NULL, NULL); |
|
457 |
|
458 |
|
459 |
|
460 /* |
|
461 * Initialize data that's required in the trap - The hostname, |
|
462 * modulenaem, statusOIDContext |
|
463 */ |
|
464 |
|
465 retCode = gethostname((char *) hostName, MAXHOSTNAMELEN); |
|
466 if (retCode != 0) |
|
467 strcpy((char *) hostName, "null\0"); |
|
468 |
|
469 strcpy((char *) moduleName, "Health-Monitor\0"); |
|
470 |
|
471 strcpy((char *) statusOIDContext, "null\0"); |
|
472 |
|
473 |
|
474 snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_POST_READ_CONFIG, |
|
475 hm_post_read_config, NULL); |
|
476 |
|
477 |
|
478 } |
|
479 |
|
480 /** Initialize the hmDiskTable table by defining its contents and how it's structured */ |
|
481 void |
|
482 initialize_table_hmDiskTable(void) |
|
483 { |
|
484 static oid hmDiskTable_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 5, 1}; |
|
485 netsnmp_table_registration_info *table_info; |
|
486 netsnmp_handler_registration *my_handler; |
|
487 netsnmp_iterator_info *iinfo; |
|
488 |
|
489 /* create the table structure itself */ |
|
490 table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info); |
|
491 iinfo = SNMP_MALLOC_TYPEDEF(netsnmp_iterator_info); |
|
492 |
|
493 /* |
|
494 * if your table is read only, it's easiest to change the |
|
495 * HANDLER_CAN_RWRITE definition below to HANDLER_CAN_RONLY |
|
496 */ |
|
497 my_handler = netsnmp_create_handler_registration("hmDiskTable", |
|
498 hmDiskTable_handler, |
|
499 hmDiskTable_oid, |
|
500 OID_LENGTH(hmDiskTable_oid), |
|
501 HANDLER_CAN_RONLY); |
|
502 |
|
503 if (!my_handler || !table_info || !iinfo) |
|
504 return; /* mallocs failed */ |
|
505 |
|
506 /*************************************************** |
|
507 * Setting up the table's definition |
|
508 */ |
|
509 netsnmp_table_helper_add_indexes(table_info, |
|
510 ASN_OCTET_STR, /* index: hmDiskName */ |
|
511 0); |
|
512 |
|
513 table_info->min_column = 1; |
|
514 table_info->max_column = 5; |
|
515 |
|
516 /* iterator access routines */ |
|
517 iinfo->get_first_data_point = hmDiskTable_get_first_data_point; |
|
518 iinfo->get_next_data_point = hmDiskTable_get_next_data_point; |
|
519 |
|
520 iinfo->table_reginfo = table_info; |
|
521 |
|
522 /*************************************************** |
|
523 * registering the table with the master agent |
|
524 */ |
|
525 DEBUGMSGTL(("initialize_table_hmDiskTable", |
|
526 "Registering table hmDiskTable as a table iterator\n")); |
|
527 netsnmp_register_table_iterator(my_handler, iinfo); |
|
528 } |
|
529 |
|
530 int |
|
531 get_hmSpinsOnMutexes(netsnmp_mib_handler * handler, |
|
532 netsnmp_handler_registration * reginfo, |
|
533 netsnmp_agent_request_info * reqinfo, |
|
534 netsnmp_request_info * requests) |
|
535 { |
|
536 |
|
537 /* |
|
538 * We are never called for a GETNEXT if it's registered as a "instance", |
|
539 * as it's "magically" handled for us. |
|
540 */ |
|
541 |
|
542 /* |
|
543 * a instance handler also only hands us one request at a time, so we |
|
544 * don't need to loop over a list of requests; we'll only get one. |
|
545 */ |
|
546 |
|
547 switch (reqinfo->mode) { |
|
548 |
|
549 case MODE_GET: |
|
550 |
|
551 snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER, (u_char *) & sum_smtx, sizeof(sum_smtx)); |
|
552 break; |
|
553 |
|
554 |
|
555 default: |
|
556 /* we should never get here, so this is a really bad error */ |
|
557 return SNMP_ERR_GENERR; |
|
558 } |
|
559 |
|
560 return SNMP_ERR_NOERROR; |
|
561 } |
|
562 |
|
563 int |
|
564 get_hmTotProcInRunQueue(netsnmp_mib_handler * handler, |
|
565 netsnmp_handler_registration * reginfo, |
|
566 netsnmp_agent_request_info * reqinfo, |
|
567 netsnmp_request_info * requests) |
|
568 { |
|
569 /* |
|
570 * We are never called for a GETNEXT if it's registered as a "instance", |
|
571 * as it's "magically" handled for us. |
|
572 */ |
|
573 |
|
574 /* |
|
575 * a instance handler also only hands us one request at a time, so we |
|
576 * don't need to loop over a list of requests; we'll only get one. |
|
577 */ |
|
578 |
|
579 long runque_long; |
|
580 switch (reqinfo->mode) { |
|
581 |
|
582 case MODE_GET: |
|
583 |
|
584 runque_long = (long) runque; |
|
585 snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER, (u_char *) & runque_long, sizeof(runque_long)); |
|
586 break; |
|
587 |
|
588 |
|
589 default: |
|
590 /* we should never get here, so this is a really bad error */ |
|
591 return SNMP_ERR_GENERR; |
|
592 } |
|
593 |
|
594 return SNMP_ERR_NOERROR; |
|
595 } |
|
596 |
|
597 int |
|
598 get_hmTotRPCCalls(netsnmp_mib_handler * handler, |
|
599 netsnmp_handler_registration * reginfo, |
|
600 netsnmp_agent_request_info * reqinfo, |
|
601 netsnmp_request_info * requests) |
|
602 { |
|
603 /* |
|
604 * We are never called for a GETNEXT if it's registered as a "instance", |
|
605 * as it's "magically" handled for us. |
|
606 */ |
|
607 |
|
608 /* |
|
609 * a instance handler also only hands us one request at a time, so we |
|
610 * don't need to loop over a list of requests; we'll only get one. |
|
611 */ |
|
612 |
|
613 switch (reqinfo->mode) { |
|
614 |
|
615 case MODE_GET: |
|
616 snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR, (u_char *) callsStr, strlen(callsStr) ); |
|
617 break; |
|
618 |
|
619 |
|
620 default: |
|
621 /* we should never get here, so this is a really bad error */ |
|
622 return SNMP_ERR_GENERR; |
|
623 } |
|
624 |
|
625 return SNMP_ERR_NOERROR; |
|
626 } |
|
627 |
|
628 int |
|
629 get_hmUsedSwapSpace(netsnmp_mib_handler * handler, |
|
630 netsnmp_handler_registration * reginfo, |
|
631 netsnmp_agent_request_info * reqinfo, |
|
632 netsnmp_request_info * requests) |
|
633 { |
|
634 /* |
|
635 * We are never called for a GETNEXT if it's registered as a "instance", |
|
636 * as it's "magically" handled for us. |
|
637 */ |
|
638 |
|
639 /* |
|
640 * a instance handler also only hands us one request at a time, so we |
|
641 * don't need to loop over a list of requests; we'll only get one. |
|
642 */ |
|
643 |
|
644 long swapused_data_long; |
|
645 switch (reqinfo->mode) { |
|
646 |
|
647 case MODE_GET: |
|
648 |
|
649 swapused_data_long = (long)swapused_data; |
|
650 snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER, (u_char *) & swapused_data_long, sizeof(swapused_data_long)); |
|
651 break; |
|
652 |
|
653 |
|
654 default: |
|
655 /* we should never get here, so this is a really bad error */ |
|
656 return SNMP_ERR_GENERR; |
|
657 } |
|
658 |
|
659 return SNMP_ERR_NOERROR; |
|
660 } |
|
661 |
|
662 int |
|
663 get_hmDNLCMisses(netsnmp_mib_handler * handler, |
|
664 netsnmp_handler_registration * reginfo, |
|
665 netsnmp_agent_request_info * reqinfo, |
|
666 netsnmp_request_info * requests) |
|
667 { |
|
668 /* |
|
669 * We are never called for a GETNEXT if it's registered as a "instance", |
|
670 * as it's "magically" handled for us. |
|
671 */ |
|
672 |
|
673 /* |
|
674 * a instance handler also only hands us one request at a time, so we |
|
675 * don't need to loop over a list of requests; we'll only get one. |
|
676 */ |
|
677 |
|
678 switch (reqinfo->mode) { |
|
679 |
|
680 case MODE_GET: |
|
681 snmp_set_var_typed_value(requests->requestvb, ASN_UNSIGNED, (u_char *) & misses, sizeof(misses)); |
|
682 break; |
|
683 |
|
684 |
|
685 default: |
|
686 /* we should never get here, so this is a really bad error */ |
|
687 return SNMP_ERR_GENERR; |
|
688 } |
|
689 |
|
690 return SNMP_ERR_NOERROR; |
|
691 } |
|
692 |
|
693 int |
|
694 get_hmReservedSwapSpace(netsnmp_mib_handler * handler, |
|
695 netsnmp_handler_registration * reginfo, |
|
696 netsnmp_agent_request_info * reqinfo, |
|
697 netsnmp_request_info * requests) |
|
698 { |
|
699 /* |
|
700 * We are never called for a GETNEXT if it's registered as a "instance", |
|
701 * as it's "magically" handled for us. |
|
702 */ |
|
703 |
|
704 /* |
|
705 * a instance handler also only hands us one request at a time, so we |
|
706 * don't need to loop over a list of requests; we'll only get one. |
|
707 */ |
|
708 |
|
709 long swapresv_data_long; |
|
710 switch (reqinfo->mode) { |
|
711 |
|
712 case MODE_GET: |
|
713 |
|
714 swapresv_data_long = (long) swapresv_data; |
|
715 snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER, (u_char *) & swapresv_data_long, sizeof(swapresv_data_long)); |
|
716 break; |
|
717 |
|
718 |
|
719 default: |
|
720 /* we should never get here, so this is a really bad error */ |
|
721 return SNMP_ERR_GENERR; |
|
722 } |
|
723 |
|
724 return SNMP_ERR_NOERROR; |
|
725 } |
|
726 |
|
727 int |
|
728 get_hmTotMemAllocFails(netsnmp_mib_handler * handler, |
|
729 netsnmp_handler_registration * reginfo, |
|
730 netsnmp_agent_request_info * reqinfo, |
|
731 netsnmp_request_info * requests) |
|
732 { |
|
733 /* |
|
734 * We are never called for a GETNEXT if it's registered as a "instance", |
|
735 * as it's "magically" handled for us. |
|
736 */ |
|
737 |
|
738 /* |
|
739 * a instance handler also only hands us one request at a time, so we |
|
740 * don't need to loop over a list of requests; we'll only get one. |
|
741 */ |
|
742 |
|
743 long nomem_long; |
|
744 switch (reqinfo->mode) { |
|
745 |
|
746 case MODE_GET: |
|
747 |
|
748 nomem_long = (long) nomem; |
|
749 snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER, (u_char *) & nomem_long, sizeof(nomem_long)); |
|
750 break; |
|
751 |
|
752 |
|
753 default: |
|
754 /* we should never get here, so this is a really bad error */ |
|
755 return SNMP_ERR_GENERR; |
|
756 } |
|
757 |
|
758 return SNMP_ERR_NOERROR; |
|
759 } |
|
760 |
|
761 int |
|
762 get_hmAvailableSwapSpace(netsnmp_mib_handler * handler, |
|
763 netsnmp_handler_registration * reginfo, |
|
764 netsnmp_agent_request_info * reqinfo, |
|
765 netsnmp_request_info * requests) |
|
766 { |
|
767 /* |
|
768 * We are never called for a GETNEXT if it's registered as a "instance", |
|
769 * as it's "magically" handled for us. |
|
770 */ |
|
771 |
|
772 /* |
|
773 * a instance handler also only hands us one request at a time, so we |
|
774 * don't need to loop over a list of requests; we'll only get one. |
|
775 */ |
|
776 |
|
777 switch (reqinfo->mode) { |
|
778 |
|
779 long swapavail_data_long; |
|
780 |
|
781 case MODE_GET: |
|
782 |
|
783 swapavail_data_long = (long) swapavail_data; |
|
784 snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER, (u_char *) & swapavail_data_long, sizeof(swapavail_data_long)); |
|
785 break; |
|
786 |
|
787 |
|
788 default: |
|
789 /* we should never get here, so this is a really bad error */ |
|
790 return SNMP_ERR_GENERR; |
|
791 } |
|
792 |
|
793 return SNMP_ERR_NOERROR; |
|
794 } |
|
795 |
|
796 int |
|
797 get_hmDNLCHitRate(netsnmp_mib_handler * handler, |
|
798 netsnmp_handler_registration * reginfo, |
|
799 netsnmp_agent_request_info * reqinfo, |
|
800 netsnmp_request_info * requests) |
|
801 { |
|
802 /* |
|
803 * We are never called for a GETNEXT if it's registered as a "instance", |
|
804 * as it's "magically" handled for us. |
|
805 */ |
|
806 |
|
807 /* |
|
808 * a instance handler also only hands us one request at a time, so we |
|
809 * don't need to loop over a list of requests; we'll only get one. |
|
810 */ |
|
811 |
|
812 switch (reqinfo->mode) { |
|
813 |
|
814 case MODE_GET: |
|
815 snmp_set_var_typed_value(requests->requestvb, ASN_UNSIGNED, (u_char *) & hitrate, sizeof(hitrate)); |
|
816 break; |
|
817 |
|
818 |
|
819 default: |
|
820 /* we should never get here, so this is a really bad error */ |
|
821 return SNMP_ERR_GENERR; |
|
822 } |
|
823 |
|
824 return SNMP_ERR_NOERROR; |
|
825 } |
|
826 |
|
827 int |
|
828 get_hmDNLCHits(netsnmp_mib_handler * handler, |
|
829 netsnmp_handler_registration * reginfo, |
|
830 netsnmp_agent_request_info * reqinfo, |
|
831 netsnmp_request_info * requests) |
|
832 { |
|
833 /* |
|
834 * We are never called for a GETNEXT if it's registered as a "instance", |
|
835 * as it's "magically" handled for us. |
|
836 */ |
|
837 |
|
838 /* |
|
839 * a instance handler also only hands us one request at a time, so we |
|
840 * don't need to loop over a list of requests; we'll only get one. |
|
841 */ |
|
842 |
|
843 switch (reqinfo->mode) { |
|
844 |
|
845 case MODE_GET: |
|
846 snmp_set_var_typed_value(requests->requestvb, ASN_UNSIGNED, (u_char *) & hits, sizeof(hits)); |
|
847 break; |
|
848 |
|
849 |
|
850 default: |
|
851 /* we should never get here, so this is a really bad error */ |
|
852 return SNMP_ERR_GENERR; |
|
853 } |
|
854 |
|
855 return SNMP_ERR_NOERROR; |
|
856 } |
|
857 |
|
858 |
|
859 int |
|
860 get_hmAllocatedSwapSpace(netsnmp_mib_handler * handler, |
|
861 netsnmp_handler_registration * reginfo, |
|
862 netsnmp_agent_request_info * reqinfo, |
|
863 netsnmp_request_info * requests) |
|
864 { |
|
865 /* |
|
866 * We are never called for a GETNEXT if it's registered as a "instance", |
|
867 * as it's "magically" handled for us. |
|
868 */ |
|
869 |
|
870 /* |
|
871 * a instance handler also only hands us one request at a time, so we |
|
872 * don't need to loop over a list of requests; we'll only get one. |
|
873 */ |
|
874 |
|
875 long swapalloc_data_long; |
|
876 switch (reqinfo->mode) { |
|
877 |
|
878 case MODE_GET: |
|
879 |
|
880 swapalloc_data_long = (long) swapalloc_data; |
|
881 snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER, (u_char *) & swapalloc_data_long, sizeof(swapalloc_data_long)); |
|
882 break; |
|
883 |
|
884 |
|
885 default: |
|
886 /* we should never get here, so this is a really bad error */ |
|
887 return SNMP_ERR_GENERR; |
|
888 } |
|
889 |
|
890 return SNMP_ERR_NOERROR; |
|
891 } |
|
892 |
|
893 int |
|
894 get_hmTotNumOfCPUs(netsnmp_mib_handler * handler, |
|
895 netsnmp_handler_registration * reginfo, |
|
896 netsnmp_agent_request_info * reqinfo, |
|
897 netsnmp_request_info * requests) |
|
898 { |
|
899 |
|
900 /* |
|
901 * We are never called for a GETNEXT if it's registered as a "instance", |
|
902 * as it's "magically" handled for us. |
|
903 */ |
|
904 |
|
905 /* |
|
906 * a instance handler also only hands us one request at a time, so we |
|
907 * don't need to loop over a list of requests; we'll only get one. |
|
908 */ |
|
909 |
|
910 long ncpus_long; |
|
911 switch (reqinfo->mode) { |
|
912 |
|
913 case MODE_GET: |
|
914 |
|
915 ncpus_long = (long)ncpus; |
|
916 snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER, (u_char *) & ncpus_long, sizeof(ncpus_long)); |
|
917 break; |
|
918 |
|
919 |
|
920 default: |
|
921 /* we should never get here, so this is a really bad error */ |
|
922 return SNMP_ERR_GENERR; |
|
923 } |
|
924 |
|
925 return SNMP_ERR_NOERROR; |
|
926 } |
|
927 |
|
928 int |
|
929 get_hmPageScanRate(netsnmp_mib_handler * handler, |
|
930 netsnmp_handler_registration * reginfo, |
|
931 netsnmp_agent_request_info * reqinfo, |
|
932 netsnmp_request_info * requests) |
|
933 { |
|
934 /* |
|
935 * We are never called for a GETNEXT if it's registered as a "instance", |
|
936 * as it's "magically" handled for us. |
|
937 */ |
|
938 |
|
939 /* |
|
940 * a instance handler also only hands us one request at a time, so we |
|
941 * don't need to loop over a list of requests; we'll only get one. |
|
942 */ |
|
943 |
|
944 long scan_long; |
|
945 switch (reqinfo->mode) { |
|
946 |
|
947 case MODE_GET: |
|
948 |
|
949 scan_long = (long) scan; |
|
950 snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER, (u_char *) & scan_long, sizeof(scan_long)); |
|
951 break; |
|
952 |
|
953 |
|
954 default: |
|
955 /* we should never get here, so this is a really bad error */ |
|
956 return SNMP_ERR_GENERR; |
|
957 } |
|
958 |
|
959 return SNMP_ERR_NOERROR; |
|
960 } |
|
961 |
|
962 int |
|
963 get_hmTimers(netsnmp_mib_handler * handler, |
|
964 netsnmp_handler_registration * reginfo, |
|
965 netsnmp_agent_request_info * reqinfo, |
|
966 netsnmp_request_info * requests) |
|
967 { |
|
968 /* |
|
969 * We are never called for a GETNEXT if it's registered as a "instance", |
|
970 * as it's "magically" handled for us. |
|
971 */ |
|
972 |
|
973 /* |
|
974 * a instance handler also only hands us one request at a time, so we |
|
975 * don't need to loop over a list of requests; we'll only get one. |
|
976 */ |
|
977 |
|
978 long timers_long; |
|
979 switch (reqinfo->mode) { |
|
980 |
|
981 case MODE_GET: |
|
982 |
|
983 timers_long = (long) timers; |
|
984 snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER, (u_char *) & timers_long, sizeof(timers_long)); |
|
985 break; |
|
986 |
|
987 |
|
988 default: |
|
989 /* we should never get here, so this is a really bad error */ |
|
990 return SNMP_ERR_GENERR; |
|
991 } |
|
992 |
|
993 return SNMP_ERR_NOERROR; |
|
994 } |
|
995 |
|
996 int |
|
997 get_hmTotBadRPCCalls(netsnmp_mib_handler * handler, |
|
998 netsnmp_handler_registration * reginfo, |
|
999 netsnmp_agent_request_info * reqinfo, |
|
1000 netsnmp_request_info * requests) |
|
1001 { |
|
1002 /* |
|
1003 * We are never called for a GETNEXT if it's registered as a "instance", |
|
1004 * as it's "magically" handled for us. |
|
1005 */ |
|
1006 |
|
1007 /* |
|
1008 * a instance handler also only hands us one request at a time, so we |
|
1009 * don't need to loop over a list of requests; we'll only get one. |
|
1010 */ |
|
1011 |
|
1012 long badcalls_long; |
|
1013 switch (reqinfo->mode) { |
|
1014 |
|
1015 case MODE_GET: |
|
1016 |
|
1017 badcalls_long = (long) badcalls ; |
|
1018 snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER, (u_char *) & badcalls_long, sizeof(badcalls_long)); |
|
1019 break; |
|
1020 |
|
1021 |
|
1022 default: |
|
1023 /* we should never get here, so this is a really bad error */ |
|
1024 return SNMP_ERR_GENERR; |
|
1025 } |
|
1026 |
|
1027 return SNMP_ERR_NOERROR; |
|
1028 } |
|
1029 |
|
1030 int |
|
1031 get_hmDNLCRefRate(netsnmp_mib_handler * handler, |
|
1032 netsnmp_handler_registration * reginfo, |
|
1033 netsnmp_agent_request_info * reqinfo, |
|
1034 netsnmp_request_info * requests) |
|
1035 { |
|
1036 /* |
|
1037 * We are never called for a GETNEXT if it's registered as a "instance", |
|
1038 * as it's "magically" handled for us. |
|
1039 */ |
|
1040 |
|
1041 /* |
|
1042 * a instance handler also only hands us one request at a time, so we |
|
1043 * don't need to loop over a list of requests; we'll only get one. |
|
1044 */ |
|
1045 |
|
1046 switch (reqinfo->mode) { |
|
1047 |
|
1048 case MODE_GET: |
|
1049 snmp_set_var_typed_value(requests->requestvb, ASN_UNSIGNED, (u_char *) & refrate, sizeof(refrate)); |
|
1050 break; |
|
1051 |
|
1052 |
|
1053 default: |
|
1054 /* we should never get here, so this is a really bad error */ |
|
1055 return SNMP_ERR_GENERR; |
|
1056 } |
|
1057 |
|
1058 return SNMP_ERR_NOERROR; |
|
1059 } |
|
1060 |
|
1061 |
|
1062 int |
|
1063 get_hmTotSendFails(netsnmp_mib_handler * handler, |
|
1064 netsnmp_handler_registration * reginfo, |
|
1065 netsnmp_agent_request_info * reqinfo, |
|
1066 netsnmp_request_info * requests) |
|
1067 { |
|
1068 /* |
|
1069 * We are never called for a GETNEXT if it's registered as a "instance", |
|
1070 * as it's "magically" handled for us. |
|
1071 */ |
|
1072 |
|
1073 /* |
|
1074 * a instance handler also only hands us one request at a time, so we |
|
1075 * don't need to loop over a list of requests; we'll only get one. |
|
1076 */ |
|
1077 |
|
1078 long cantsend_long; |
|
1079 switch (reqinfo->mode) { |
|
1080 |
|
1081 case MODE_GET: |
|
1082 |
|
1083 cantsend_long = (long) cantsend; |
|
1084 snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER, (u_char *) & cantsend_long, sizeof(cantsend_long)); |
|
1085 break; |
|
1086 |
|
1087 |
|
1088 default: |
|
1089 /* we should never get here, so this is a really bad error */ |
|
1090 return SNMP_ERR_GENERR; |
|
1091 } |
|
1092 |
|
1093 return SNMP_ERR_NOERROR; |
|
1094 } |
|
1095 |
|
1096 int |
|
1097 get_hmTotFailedCallsBV(netsnmp_mib_handler * handler, |
|
1098 netsnmp_handler_registration * reginfo, |
|
1099 netsnmp_agent_request_info * reqinfo, |
|
1100 netsnmp_request_info * requests) |
|
1101 { |
|
1102 /* |
|
1103 * We are never called for a GETNEXT if it's registered as a "instance", |
|
1104 * as it's "magically" handled for us. |
|
1105 */ |
|
1106 |
|
1107 /* |
|
1108 * a instance handler also only hands us one request at a time, so we |
|
1109 * don't need to loop over a list of requests; we'll only get one. |
|
1110 */ |
|
1111 |
|
1112 long badxids_long; |
|
1113 switch (reqinfo->mode) { |
|
1114 |
|
1115 case MODE_GET: |
|
1116 |
|
1117 badxids_long = (long) badxids; |
|
1118 snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER, (u_char *) & badxids_long, sizeof(badxids_long)); |
|
1119 break; |
|
1120 |
|
1121 |
|
1122 default: |
|
1123 /* we should never get here, so this is a really bad error */ |
|
1124 return SNMP_ERR_GENERR; |
|
1125 } |
|
1126 |
|
1127 return SNMP_ERR_NOERROR; |
|
1128 } |
|
1129 |
|
1130 int |
|
1131 get_hmTotNumOfAuthRefresh(netsnmp_mib_handler * handler, |
|
1132 netsnmp_handler_registration * reginfo, |
|
1133 netsnmp_agent_request_info * reqinfo, |
|
1134 netsnmp_request_info * requests) |
|
1135 { |
|
1136 /* |
|
1137 * We are never called for a GETNEXT if it's registered as a "instance", |
|
1138 * as it's "magically" handled for us. |
|
1139 */ |
|
1140 |
|
1141 /* |
|
1142 * a instance handler also only hands us one request at a time, so we |
|
1143 * don't need to loop over a list of requests; we'll only get one. |
|
1144 */ |
|
1145 |
|
1146 long newcreds_long; |
|
1147 switch (reqinfo->mode) { |
|
1148 |
|
1149 case MODE_GET: |
|
1150 |
|
1151 newcreds_long = (long) newcreds; |
|
1152 snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER, (u_char *) & newcreds_long, sizeof(newcreds_long)); |
|
1153 break; |
|
1154 |
|
1155 |
|
1156 default: |
|
1157 /* we should never get here, so this is a really bad error */ |
|
1158 return SNMP_ERR_GENERR; |
|
1159 } |
|
1160 |
|
1161 return SNMP_ERR_NOERROR; |
|
1162 } |
|
1163 |
|
1164 int |
|
1165 get_hmHandspread(netsnmp_mib_handler * handler, |
|
1166 netsnmp_handler_registration * reginfo, |
|
1167 netsnmp_agent_request_info * reqinfo, |
|
1168 netsnmp_request_info * requests) |
|
1169 { |
|
1170 /* |
|
1171 * We are never called for a GETNEXT if it's registered as a "instance", |
|
1172 * as it's "magically" handled for us. |
|
1173 */ |
|
1174 |
|
1175 /* |
|
1176 * a instance handler also only hands us one request at a time, so we |
|
1177 * don't need to loop over a list of requests; we'll only get one. |
|
1178 */ |
|
1179 |
|
1180 long handspread_long; |
|
1181 switch (reqinfo->mode) { |
|
1182 |
|
1183 case MODE_GET: |
|
1184 |
|
1185 handspread_long = (long) handspread; |
|
1186 snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER, (u_char *) & handspread_long, sizeof(handspread_long)); |
|
1187 break; |
|
1188 |
|
1189 |
|
1190 default: |
|
1191 /* we should never get here, so this is a really bad error */ |
|
1192 return SNMP_ERR_GENERR; |
|
1193 } |
|
1194 |
|
1195 return SNMP_ERR_NOERROR; |
|
1196 } |
|
1197 |
|
1198 int |
|
1199 get_hmTotRPCRetransmissions(netsnmp_mib_handler * handler, |
|
1200 netsnmp_handler_registration * reginfo, |
|
1201 netsnmp_agent_request_info * reqinfo, |
|
1202 netsnmp_request_info * requests) |
|
1203 { |
|
1204 /* |
|
1205 * We are never called for a GETNEXT if it's registered as a "instance", |
|
1206 * as it's "magically" handled for us. |
|
1207 */ |
|
1208 |
|
1209 /* |
|
1210 * a instance handler also only hands us one request at a time, so we |
|
1211 * don't need to loop over a list of requests; we'll only get one. |
|
1212 */ |
|
1213 |
|
1214 long interrupts_long; |
|
1215 switch (reqinfo->mode) { |
|
1216 |
|
1217 case MODE_GET: |
|
1218 |
|
1219 interrupts_long = (long) interrupts; |
|
1220 snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER, (u_char *) & interrupts_long, sizeof(interrupts_long)); |
|
1221 break; |
|
1222 |
|
1223 |
|
1224 default: |
|
1225 /* we should never get here, so this is a really bad error */ |
|
1226 return SNMP_ERR_GENERR; |
|
1227 } |
|
1228 |
|
1229 return SNMP_ERR_NOERROR; |
|
1230 } |
|
1231 |
|
1232 int |
|
1233 get_hmKmemFreeMem(netsnmp_mib_handler * handler, |
|
1234 netsnmp_handler_registration * reginfo, |
|
1235 netsnmp_agent_request_info * reqinfo, |
|
1236 netsnmp_request_info * requests) |
|
1237 { |
|
1238 /* |
|
1239 * We are never called for a GETNEXT if it's registered as a "instance", |
|
1240 * as it's "magically" handled for us. |
|
1241 */ |
|
1242 |
|
1243 /* |
|
1244 * a instance handler also only hands us one request at a time, so we |
|
1245 * don't need to loop over a list of requests; we'll only get one. |
|
1246 */ |
|
1247 |
|
1248 long mem_free_long; |
|
1249 switch (reqinfo->mode) { |
|
1250 |
|
1251 case MODE_GET: |
|
1252 |
|
1253 mem_free_long = (long) mem_free; |
|
1254 snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER, (u_char *) & mem_free_long, sizeof(mem_free_long)); |
|
1255 break; |
|
1256 |
|
1257 |
|
1258 default: |
|
1259 /* we should never get here, so this is a really bad error */ |
|
1260 return SNMP_ERR_GENERR; |
|
1261 } |
|
1262 |
|
1263 return SNMP_ERR_NOERROR; |
|
1264 } |
|
1265 |
|
1266 int |
|
1267 get_hmTotBadRPCReplies(netsnmp_mib_handler * handler, |
|
1268 netsnmp_handler_registration * reginfo, |
|
1269 netsnmp_agent_request_info * reqinfo, |
|
1270 netsnmp_request_info * requests) |
|
1271 { |
|
1272 /* |
|
1273 * We are never called for a GETNEXT if it's registered as a "instance", |
|
1274 * as it's "magically" handled for us. |
|
1275 */ |
|
1276 |
|
1277 /* |
|
1278 * a instance handler also only hands us one request at a time, so we |
|
1279 * don't need to loop over a list of requests; we'll only get one. |
|
1280 */ |
|
1281 |
|
1282 long badverfs_long; |
|
1283 switch (reqinfo->mode) { |
|
1284 |
|
1285 case MODE_GET: |
|
1286 |
|
1287 badverfs_long = (long) badverfs; |
|
1288 snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER, (u_char *) & badverfs_long, sizeof(badverfs_long)); |
|
1289 break; |
|
1290 |
|
1291 |
|
1292 default: |
|
1293 /* we should never get here, so this is a really bad error */ |
|
1294 return SNMP_ERR_GENERR; |
|
1295 } |
|
1296 |
|
1297 return SNMP_ERR_NOERROR; |
|
1298 } |
|
1299 |
|
1300 int |
|
1301 get_hmKmemErrors(netsnmp_mib_handler * handler, |
|
1302 netsnmp_handler_registration * reginfo, |
|
1303 netsnmp_agent_request_info * reqinfo, |
|
1304 netsnmp_request_info * requests) |
|
1305 { |
|
1306 /* |
|
1307 * We are never called for a GETNEXT if it's registered as a "instance", |
|
1308 * as it's "magically" handled for us. |
|
1309 */ |
|
1310 |
|
1311 /* |
|
1312 * a instance handler also only hands us one request at a time, so we |
|
1313 * don't need to loop over a list of requests; we'll only get one. |
|
1314 */ |
|
1315 |
|
1316 long alloc_fail_long; |
|
1317 switch (reqinfo->mode) { |
|
1318 |
|
1319 case MODE_GET: |
|
1320 |
|
1321 alloc_fail_long = (long) alloc_fail; |
|
1322 snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER, (u_char *) & alloc_fail_long, sizeof(alloc_fail_long)); |
|
1323 break; |
|
1324 |
|
1325 |
|
1326 default: |
|
1327 /* we should never get here, so this is a really bad error */ |
|
1328 return SNMP_ERR_GENERR; |
|
1329 } |
|
1330 |
|
1331 return SNMP_ERR_NOERROR; |
|
1332 } |
|
1333 |
|
1334 int |
|
1335 get_hmTotProcReadyInSwap(netsnmp_mib_handler * handler, |
|
1336 netsnmp_handler_registration * reginfo, |
|
1337 netsnmp_agent_request_info * reqinfo, |
|
1338 netsnmp_request_info * requests) |
|
1339 { |
|
1340 /* |
|
1341 * We are never called for a GETNEXT if it's registered as a "instance", |
|
1342 * as it's "magically" handled for us. |
|
1343 */ |
|
1344 |
|
1345 /* |
|
1346 * a instance handler also only hands us one request at a time, so we |
|
1347 * don't need to loop over a list of requests; we'll only get one. |
|
1348 */ |
|
1349 |
|
1350 long swapque_long; |
|
1351 switch (reqinfo->mode) { |
|
1352 |
|
1353 case MODE_GET: |
|
1354 |
|
1355 swapque_long = (long) swapque; |
|
1356 snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER, (u_char *) & swapque_long, sizeof(swapque_long)); |
|
1357 break; |
|
1358 |
|
1359 |
|
1360 default: |
|
1361 /* we should never get here, so this is a really bad error */ |
|
1362 return SNMP_ERR_GENERR; |
|
1363 } |
|
1364 |
|
1365 return SNMP_ERR_NOERROR; |
|
1366 } |
|
1367 |
|
1368 int |
|
1369 get_hmTotProcBlocked(netsnmp_mib_handler * handler, |
|
1370 netsnmp_handler_registration * reginfo, |
|
1371 netsnmp_agent_request_info * reqinfo, |
|
1372 netsnmp_request_info * requests) |
|
1373 { |
|
1374 /* |
|
1375 * We are never called for a GETNEXT if it's registered as a "instance", |
|
1376 * as it's "magically" handled for us. |
|
1377 */ |
|
1378 |
|
1379 /* |
|
1380 * a instance handler also only hands us one request at a time, so we |
|
1381 * don't need to loop over a list of requests; we'll only get one. |
|
1382 */ |
|
1383 |
|
1384 long waiting_long; |
|
1385 switch (reqinfo->mode) { |
|
1386 |
|
1387 case MODE_GET: |
|
1388 |
|
1389 waiting_long = (long) waiting; |
|
1390 snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER, (u_char *) & waiting_long, sizeof(waiting_long)); |
|
1391 break; |
|
1392 |
|
1393 |
|
1394 default: |
|
1395 /* we should never get here, so this is a really bad error */ |
|
1396 return SNMP_ERR_GENERR; |
|
1397 } |
|
1398 |
|
1399 return SNMP_ERR_NOERROR; |
|
1400 } |
|
1401 |
|
1402 int |
|
1403 get_hmTotRPCCallsTimedOut(netsnmp_mib_handler * handler, |
|
1404 netsnmp_handler_registration * reginfo, |
|
1405 netsnmp_agent_request_info * reqinfo, |
|
1406 netsnmp_request_info * requests) |
|
1407 { |
|
1408 /* |
|
1409 * We are never called for a GETNEXT if it's registered as a "instance", |
|
1410 * as it's "magically" handled for us. |
|
1411 */ |
|
1412 |
|
1413 /* |
|
1414 * a instance handler also only hands us one request at a time, so we |
|
1415 * don't need to loop over a list of requests; we'll only get one. |
|
1416 */ |
|
1417 |
|
1418 long timeouts_long; |
|
1419 switch (reqinfo->mode) { |
|
1420 |
|
1421 case MODE_GET: |
|
1422 |
|
1423 timeouts_long = (long) timeouts; |
|
1424 snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER, (u_char *) & timeouts_long, sizeof(timeouts_long)); |
|
1425 break; |
|
1426 |
|
1427 |
|
1428 default: |
|
1429 /* we should never get here, so this is a really bad error */ |
|
1430 return SNMP_ERR_GENERR; |
|
1431 } |
|
1432 |
|
1433 return SNMP_ERR_NOERROR; |
|
1434 } |
|
1435 |
|
1436 |
|
1437 int hm_post_read_config(int a, int b, void *c, void *d) |
|
1438 { |
|
1439 |
|
1440 /* |
|
1441 * Refresh the HealthMonitor module data every 60 seconds. Every 60 |
|
1442 * seconds, the function refresh_all_HM_data is called automatically by |
|
1443 * the agent. Also, load data into nodes now by calling the refresh |
|
1444 * function once |
|
1445 */ |
|
1446 |
|
1447 construct_DISK_table(); |
|
1448 refresh_all_HM_data(0, NULL); |
|
1449 |
|
1450 snmp_alarm_register(hm_refresh_interval, SA_REPEAT, refresh_DISK_table, NULL); |
|
1451 snmp_alarm_register(hm_refresh_interval, SA_REPEAT, refresh_all_HM_data, NULL); |
|
1452 |
|
1453 } |
|
1454 |
|
1455 |
|
1456 |
|
1457 hmDiskTable * |
|
1458 get_first_node() |
|
1459 { |
|
1460 return head; |
|
1461 } |
|
1462 |
|
1463 /** returns the first data point within the hmDiskTable table data. |
|
1464 |
|
1465 Set the my_loop_context variable to the first data point structure |
|
1466 of your choice (from which you can find the next one). This could |
|
1467 be anything from the first node in a linked list, to an integer |
|
1468 pointer containing the beginning of an array variable. |
|
1469 |
|
1470 Set the my_data_context variable to something to be returned to |
|
1471 you later that will provide you with the data to return in a given |
|
1472 row. This could be the same pointer as what my_loop_context is |
|
1473 set to, or something different. |
|
1474 |
|
1475 The put_index_data variable contains a list of snmp variable |
|
1476 bindings, one for each index in your table. Set the values of |
|
1477 each appropriately according to the data matching the first row |
|
1478 and return the put_index_data variable at the end of the function. |
|
1479 */ |
|
1480 |
|
1481 netsnmp_variable_list * |
|
1482 hmDiskTable_get_first_data_point(void **my_loop_context, void **my_data_context, |
|
1483 netsnmp_variable_list * put_index_data, |
|
1484 netsnmp_iterator_info * mydata) |
|
1485 { |
|
1486 |
|
1487 netsnmp_variable_list *vptr; |
|
1488 |
|
1489 hmDiskTable *firstNode = get_first_node(); |
|
1490 if (!firstNode) { |
|
1491 return NULL; |
|
1492 } |
|
1493 *my_loop_context = firstNode; |
|
1494 *my_data_context = firstNode; |
|
1495 |
|
1496 vptr = put_index_data; |
|
1497 |
|
1498 snmp_set_var_value(vptr, (u_char *) firstNode->hmDiskName, strlen(firstNode->hmDiskName) /* XXX: length of |
|
1499 hmDiskName data */ ); |
|
1500 vptr = vptr->next_variable; |
|
1501 |
|
1502 return put_index_data; |
|
1503 } |
|
1504 |
|
1505 /** functionally the same as hmDiskTable_get_first_data_point, but |
|
1506 my_loop_context has already been set to a previous value and should |
|
1507 be updated to the next in the list. For example, if it was a |
|
1508 linked list, you might want to cast it and the return |
|
1509 my_loop_context->next. The my_data_context pointer should be set |
|
1510 to something you need later and the indexes in put_index_data |
|
1511 updated again. */ |
|
1512 |
|
1513 netsnmp_variable_list * |
|
1514 hmDiskTable_get_next_data_point(void **my_loop_context, void **my_data_context, |
|
1515 netsnmp_variable_list * put_index_data, |
|
1516 netsnmp_iterator_info * mydata) |
|
1517 { |
|
1518 |
|
1519 netsnmp_variable_list *vptr; |
|
1520 |
|
1521 hmDiskTable *nextNode = (hmDiskTable *) * my_loop_context; |
|
1522 |
|
1523 /* This check is not really required */ |
|
1524 if(!nextNode) { |
|
1525 snmp_log(LOG_DEBUG,"No data returned in get_next\n"); |
|
1526 return NULL; |
|
1527 } |
|
1528 |
|
1529 nextNode = nextNode->pNext; |
|
1530 |
|
1531 if (!nextNode) { |
|
1532 snmp_log(LOG_DEBUG,"No data returned in get_next\n"); |
|
1533 return NULL; |
|
1534 } |
|
1535 *my_loop_context = nextNode; |
|
1536 *my_data_context = nextNode; |
|
1537 |
|
1538 vptr = put_index_data; |
|
1539 |
|
1540 snmp_set_var_value(vptr, (u_char *) nextNode->hmDiskName /* XXX: hmDiskName data */ , strlen(nextNode->hmDiskName) /* XXX: length of |
|
1541 hmDiskName data */ ); |
|
1542 vptr = vptr->next_variable; |
|
1543 |
|
1544 return put_index_data; |
|
1545 } |
|
1546 |
|
1547 /** handles requests for the hmDiskTable table, if anything else needs to be done */ |
|
1548 int |
|
1549 hmDiskTable_handler( |
|
1550 netsnmp_mib_handler * handler, |
|
1551 netsnmp_handler_registration * reginfo, |
|
1552 netsnmp_agent_request_info * reqinfo, |
|
1553 netsnmp_request_info * requests) |
|
1554 { |
|
1555 |
|
1556 netsnmp_request_info *request; |
|
1557 netsnmp_table_request_info *table_info; |
|
1558 netsnmp_variable_list *var; |
|
1559 |
|
1560 hmDiskTable *data; |
|
1561 |
|
1562 for (request = requests; request; request = request->next) { |
|
1563 var = request->requestvb; |
|
1564 if (request->processed != 0) |
|
1565 continue; |
|
1566 |
|
1567 /* |
|
1568 * perform anything here that you need to do before each request is |
|
1569 * processed. |
|
1570 */ |
|
1571 |
|
1572 /* |
|
1573 * the following extracts the my_data_context pointer set in the loop |
|
1574 * functions above. You can then use the results to help return data |
|
1575 * for the columns of the hmDiskTable table in question |
|
1576 */ |
|
1577 data = (hmDiskTable *) netsnmp_extract_iterator_context(request); |
|
1578 if (data == NULL) { |
|
1579 if (reqinfo->mode == MODE_GET) { |
|
1580 netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHINSTANCE); |
|
1581 continue; |
|
1582 } |
|
1583 /* |
|
1584 * XXX: no row existed, if you support creation and this is a |
|
1585 * set, start dealing with it here, else continue |
|
1586 */ |
|
1587 } |
|
1588 /* extracts the information about the table from the request */ |
|
1589 table_info = netsnmp_extract_table_info(request); |
|
1590 /* table_info->colnum contains the column number requested */ |
|
1591 /* |
|
1592 * table_info->indexes contains a linked list of snmp variable |
|
1593 * bindings for the indexes of the table. Values in the list have |
|
1594 * been set corresponding to the indexes of the request |
|
1595 */ |
|
1596 if (table_info == NULL) { |
|
1597 continue; |
|
1598 } |
|
1599 switch (reqinfo->mode) { |
|
1600 /* |
|
1601 * the table_iterator helper should change all GETNEXTs into GETs |
|
1602 * for you automatically, so you don't have to worry about the |
|
1603 * GETNEXT case. Only GETs and SETs need to be dealt with here |
|
1604 */ |
|
1605 case MODE_GET: |
|
1606 switch (table_info->colnum) { |
|
1607 case COLUMN_HMDISKNAME: |
|
1608 snmp_set_var_typed_value(var, ASN_OCTET_STR, (u_char *) data->hmDiskName, strlen(data->hmDiskName)); |
|
1609 break; |
|
1610 |
|
1611 case COLUMN_HMDISKALIASNAME: |
|
1612 snmp_set_var_typed_value(var, ASN_OCTET_STR, (u_char *) data->hmDiskAliasName, strlen(data->hmDiskAliasName)); |
|
1613 break; |
|
1614 |
|
1615 case COLUMN_HMAVGWAITTRANSACTIONS: |
|
1616 snmp_set_var_typed_value(var, ASN_OCTET_STR, (u_char *) data->hmAvgWaitTransactions, strlen(data->hmAvgWaitTransactions)); |
|
1617 break; |
|
1618 |
|
1619 case COLUMN_HMDISKBUSYPCNT: |
|
1620 snmp_set_var_typed_value(var, ASN_OCTET_STR, (u_char *) data->hmDiskBusyPcnt, strlen(data->hmDiskBusyPcnt)); |
|
1621 break; |
|
1622 |
|
1623 case COLUMN_HMAVGDISKSVCTIME: |
|
1624 snmp_set_var_typed_value(var, ASN_OCTET_STR, (u_char *) data->hmAvgDiskSvcTime, strlen(data->hmAvgDiskSvcTime)); |
|
1625 break; |
|
1626 |
|
1627 default: |
|
1628 /* We shouldn't get here */ |
|
1629 snmp_log(LOG_ERR, "problem encountered in hmDiskTable_handler: unknown column\n"); |
|
1630 } |
|
1631 break; |
|
1632 |
|
1633 case MODE_SET_RESERVE1: |
|
1634 /* set handling... */ |
|
1635 |
|
1636 default: |
|
1637 snmp_log(LOG_ERR, "problem encountered in hmDiskTable_handler: unsupported mode\n"); |
|
1638 } |
|
1639 } |
|
1640 return SNMP_ERR_NOERROR; |
|
1641 } |
|
1642 |
|
1643 /* |
|
1644 * ***** |
|
1645 * New Functions that are added to the template generated by mib2c |
|
1646 * ***** |
|
1647 */ |
|
1648 |
|
1649 |
|
1650 /* |
|
1651 * The following refresh functions are called every 60 seconds. The data |
|
1652 * nodes are updated with latest data |
|
1653 */ |
|
1654 |
|
1655 void |
|
1656 refresh_SWAP_data() |
|
1657 { |
|
1658 |
|
1659 int code = 0; |
|
1660 |
|
1661 code = krgetswapusage(&swapavail_data, &swapresv_data, &swapalloc_data, &swapused_data, &swaptotal_data); |
|
1662 |
|
1663 /* |
|
1664 * code == -1 : Error in swapctl code == 0 : Success Can be verified |
|
1665 * using "swap -s" on shell |
|
1666 */ |
|
1667 |
|
1668 if (code != 0) { |
|
1669 snmp_log(LOG_ERR,"Health Monitor Module: errror getting SWAP info\n"); |
|
1670 swapavail_data = 0; |
|
1671 swapresv_data = 0; |
|
1672 swapalloc_data = 0; |
|
1673 swapused_data = 0; |
|
1674 } |
|
1675 } |
|
1676 |
|
1677 void |
|
1678 refresh_Kernel_data() |
|
1679 { |
|
1680 |
|
1681 int code = 0; |
|
1682 |
|
1683 code = krgetsmtx(&sum_smtx, &ncpus); |
|
1684 |
|
1685 if (code != 0) { |
|
1686 snmp_log(LOG_ERR,"Health Monitor Module: errror getting Kernel info\n"); |
|
1687 sum_smtx = 0; |
|
1688 ncpus = 0; |
|
1689 } |
|
1690 } |
|
1691 |
|
1692 void |
|
1693 refresh_NFS_data() |
|
1694 { |
|
1695 |
|
1696 int code = 0; |
|
1697 |
|
1698 code = krgetclientrpcdetail(&calls, &badcalls, &retrans, &badxids, &timeouts, &newcreds, &badverfs, &timers, &nomem, &cantsend); |
|
1699 |
|
1700 if (code != 0) { |
|
1701 snmp_log(LOG_ERR,"Health Monitor Module: errror getting NFS info\n"); |
|
1702 calls = 0; |
|
1703 badcalls = 0; |
|
1704 retrans = 0; |
|
1705 badxids = 0; |
|
1706 timeouts = 0; |
|
1707 newcreds = 0; |
|
1708 badverfs = 0; |
|
1709 timers = 0; |
|
1710 nomem = 0; |
|
1711 cantsend = 0; |
|
1712 } |
|
1713 |
|
1714 /* "calls" is defined as a "DisplayString" in the MIB. So, converting |
|
1715 * it to String |
|
1716 */ |
|
1717 |
|
1718 sprintf(callsStr, "%3.1f\0", calls); |
|
1719 } |
|
1720 |
|
1721 void |
|
1722 refresh_CPU_data() |
|
1723 { |
|
1724 |
|
1725 int code = 0; |
|
1726 |
|
1727 code = krgetprocdetail(&runque, &waiting, &swapque); |
|
1728 |
|
1729 if (code != 0) { |
|
1730 |
|
1731 snmp_log(LOG_ERR,"Health Monitor Module: errror getting CPU info\n"); |
|
1732 runque = 0; |
|
1733 waiting = 0; |
|
1734 swapque = 0; |
|
1735 } |
|
1736 } |
|
1737 |
|
1738 void |
|
1739 refresh_RAM_data() |
|
1740 { |
|
1741 |
|
1742 int code = 0; |
|
1743 |
|
1744 code = krgetramdetail(&handspread, &scan); |
|
1745 |
|
1746 if (code != 0) { |
|
1747 |
|
1748 snmp_log(LOG_ERR,"Health Monitor Module: errror getting RAM info\n"); |
|
1749 handspread = 0; |
|
1750 scan = 0; |
|
1751 |
|
1752 } |
|
1753 } |
|
1754 |
|
1755 void |
|
1756 refresh_KMEM_data() |
|
1757 { |
|
1758 |
|
1759 int code = 0; |
|
1760 char char_name[2] = "*\n"; |
|
1761 |
|
1762 /* char char_name='*'; */ |
|
1763 |
|
1764 /* The first argument of "*" requests sum of statistics of all caches */ |
|
1765 |
|
1766 code = krgetkmemdetail(char_name, &alloc, &alloc_fail, &buf_size, &buf_avail, &buf_total, &buf_max); |
|
1767 |
|
1768 if (code >= 0) |
|
1769 code = krgetmemusage(&mem_avail, &mem_inuse, &mem_free); |
|
1770 |
|
1771 if (code != 0) { |
|
1772 |
|
1773 snmp_log(LOG_ERR,"Health Monitor Module: errror getting KMEM info\n"); |
|
1774 alloc_fail = 0; |
|
1775 mem_free = 0; |
|
1776 |
|
1777 } |
|
1778 } |
|
1779 |
|
1780 void |
|
1781 refresh_DNLC_data() |
|
1782 { |
|
1783 |
|
1784 int code = 0; |
|
1785 long curtime; |
|
1786 |
|
1787 curtime = time(&curtime); |
|
1788 if (prevtime != curtime) { |
|
1789 |
|
1790 code = krgetncstatdetail(&hits, &misses); |
|
1791 |
|
1792 if (code != 0) { |
|
1793 |
|
1794 snmp_log(LOG_ERR,"Health Monitor Module: errror getting DNLC info\n"); |
|
1795 hits = 0; |
|
1796 misses = 0; |
|
1797 |
|
1798 } /* NOTE : Should we do below even if |
|
1799 * hits=0,misses=0 ? Yes, according to SunMC |
|
1800 * rule */ |
|
1801 if (firsttime == 1) { |
|
1802 firsttime = 0; |
|
1803 lasthits = hits; |
|
1804 lastmisses = misses; |
|
1805 } else { |
|
1806 lasthits = prevhits; |
|
1807 lastmisses = prevmisses; |
|
1808 } |
|
1809 |
|
1810 prevhits = hits; |
|
1811 prevmisses = misses; |
|
1812 |
|
1813 refrate = (hits - lasthits) + (misses - lastmisses); |
|
1814 if (refrate == 0) { |
|
1815 hitrate = 100; |
|
1816 } else { |
|
1817 hitrate = 100 * (hits - lasthits) / refrate; |
|
1818 refrate = refrate / (curtime - prevtime); |
|
1819 } |
|
1820 |
|
1821 prevtime = curtime; |
|
1822 } |
|
1823 } |
|
1824 |
|
1825 void |
|
1826 construct_DISK_table() |
|
1827 { |
|
1828 |
|
1829 hmDiskTable *prevPtr = NULL; |
|
1830 |
|
1831 char name[MAXNAMELEN]; |
|
1832 char alias[MAXNAMELEN]; |
|
1833 double rps, wps, tps, krps, kwps, kps, avw, avr; |
|
1834 double w_pct, r_pct, wserv, rserv, serv; |
|
1835 int code = 0; |
|
1836 |
|
1837 |
|
1838 /* set to 0 so that we can block any other refresh's */ |
|
1839 hm_prev_disk_ref = 0; |
|
1840 |
|
1841 /* Keeps track of number of disks */ |
|
1842 diskCount = 0; |
|
1843 |
|
1844 do { |
|
1845 |
|
1846 hmDiskTable *ptr = (hmDiskTable *) malloc(sizeof(hmDiskTable)); |
|
1847 |
|
1848 if ( ptr == NULL) { |
|
1849 snmp_log(LOG_DEBUG,"malloc failed when constructing DISK table in health monitor module \n"); |
|
1850 return; |
|
1851 } |
|
1852 |
|
1853 code = krgetdiskdetail(name, alias, &rps, &wps, &tps, &krps, &kwps, &kps, &avw, &avr); |
|
1854 |
|
1855 if (code < 0) { |
|
1856 /* Error occured during kstat read */ |
|
1857 snmp_log(LOG_ERR,"Health Monitor Module: errror getting disk info\n"); |
|
1858 return; |
|
1859 } |
|
1860 code = krgetdisksrv(name, alias, &w_pct, &r_pct, &wserv, &rserv, &serv); |
|
1861 |
|
1862 if (code < 0) { |
|
1863 /* Error occured during kstat read */ |
|
1864 snmp_log(LOG_ERR,"Health Monitor Module: errror getting disk info\n"); |
|
1865 return; |
|
1866 } |
|
1867 /* Allocate required memory to hold each disk data. */ |
|
1868 |
|
1869 ptr->hmDiskName = (char *) malloc(strlen(name) + 1); |
|
1870 ptr->hmDiskAliasName = (char *) malloc(strlen(alias) + 1); |
|
1871 ptr->hmAvgWaitTransactions = (char *) malloc(DISK_DATA_LEN); |
|
1872 ptr->hmDiskBusyPcnt = (char *) malloc(DISK_DATA_LEN); |
|
1873 ptr->hmAvgDiskSvcTime = (char *) malloc(DISK_DATA_LEN); |
|
1874 |
|
1875 if ( ptr->hmAvgDiskSvcTime == NULL) { |
|
1876 snmp_log(LOG_DEBUG,"malloc failed when constructing DISK table in health monitor module \n"); |
|
1877 return; |
|
1878 } |
|
1879 |
|
1880 strcpy(ptr->hmDiskName,name); |
|
1881 |
|
1882 strcpy(ptr->hmDiskAliasName,alias); |
|
1883 |
|
1884 sprintf(ptr->hmAvgWaitTransactions, "%3.1f\0", w_pct); |
|
1885 |
|
1886 sprintf(ptr->hmDiskBusyPcnt, "%3.1f\0", r_pct); |
|
1887 |
|
1888 sprintf(ptr->hmAvgDiskSvcTime, "%3.1f\0", serv); |
|
1889 |
|
1890 /* Set the state of Disk to OK. */ |
|
1891 |
|
1892 ptr->hmDiskState = OK; |
|
1893 |
|
1894 diskCount++; |
|
1895 ptr->pNext = NULL; |
|
1896 if (prevPtr == NULL) { |
|
1897 head = prevPtr = ptr; |
|
1898 } else { |
|
1899 |
|
1900 prevPtr->pNext = ptr; |
|
1901 prevPtr = ptr; |
|
1902 } |
|
1903 /* code is set to value 0 if there is more disk information */ |
|
1904 } while (code == 0); |
|
1905 |
|
1906 check_state_DISK(); |
|
1907 |
|
1908 /* set the time of first refresh */ |
|
1909 |
|
1910 time(&hm_prev_disk_ref); |
|
1911 |
|
1912 } |
|
1913 |
|
1914 |
|
1915 void |
|
1916 refresh_DISK_table(unsigned int clientreg, void *clientarg) |
|
1917 { |
|
1918 |
|
1919 char name[MAXNAMELEN]; |
|
1920 char alias[MAXNAMELEN]; |
|
1921 double rps, wps, tps, krps, kwps, kps, avw, avr; |
|
1922 double w_pct, r_pct, wserv, rserv, serv; |
|
1923 int code = 0; |
|
1924 hmDiskTable *headPtr; |
|
1925 hmDiskTable *ptr; |
|
1926 hmDiskTable *tailPtr, *p1, *p2; |
|
1927 |
|
1928 |
|
1929 time_t hm_current_time; |
|
1930 |
|
1931 /* Did the previous refresh really finish ?? |
|
1932 * This means that previous refresh is still in progress */ |
|
1933 if (hm_prev_disk_ref == 0) return; |
|
1934 |
|
1935 time(&hm_current_time); |
|
1936 |
|
1937 /* Did the previous refresh finish too close to start another refresh ??? |
|
1938 * This means that the previous refresh finished relatively closer to current time |
|
1939 * so, another refresh is not necessary. hm_prev_disk_ref is initialized to 1 |
|
1940 * during variable declaration. so, the first time refresh is called, it will always |
|
1941 * proceed. |
|
1942 */ |
|
1943 |
|
1944 if ( (hm_current_time - hm_prev_disk_ref) < (hm_refresh_interval / 4) ) return; |
|
1945 |
|
1946 /* set to 0 so that we can block any other refresh's */ |
|
1947 hm_prev_disk_ref = 0; |
|
1948 |
|
1949 diskCount=0; |
|
1950 |
|
1951 /* Set tailPtr to the last structure |
|
1952 * set "hmTraversed" to 0 for all disks |
|
1953 */ |
|
1954 |
|
1955 tailPtr = head; |
|
1956 while (tailPtr->pNext != NULL) { |
|
1957 tailPtr->hmTraversed=0; |
|
1958 tailPtr = tailPtr->pNext; |
|
1959 } |
|
1960 if(tailPtr != NULL) tailPtr->hmTraversed=0; |
|
1961 |
|
1962 do { |
|
1963 |
|
1964 int hit = 0; |
|
1965 code = krgetdiskdetail(name, alias, &rps, &wps, &tps, &krps, &kwps, &kps, &avw, &avr); |
|
1966 |
|
1967 if (code < 0) { |
|
1968 /* Error occured during kstat read */ |
|
1969 snmp_log(LOG_ERR,"Health Monitor Module: errror getting disk info\n"); |
|
1970 return; |
|
1971 } |
|
1972 code = krgetdisksrv(name, alias, &w_pct, &r_pct, &wserv, &rserv, &serv); |
|
1973 |
|
1974 if (code < 0) { |
|
1975 /* Error occured during kstat read */ |
|
1976 snmp_log(LOG_ERR,"Health Monitor Module: errror getting disk info\n"); |
|
1977 return; |
|
1978 } |
|
1979 |
|
1980 /* For each row in the table, refresh the data */ |
|
1981 |
|
1982 headPtr = head; |
|
1983 while ((headPtr != NULL) && (hit == 0)) { |
|
1984 |
|
1985 if (strncmp(headPtr->hmDiskName, name, strlen(name)) == 0) { |
|
1986 |
|
1987 /* |
|
1988 * This Disk is already part of the list. Just update the |
|
1989 * data |
|
1990 */ |
|
1991 |
|
1992 hit = 1; |
|
1993 |
|
1994 strcpy(headPtr->hmDiskAliasName,alias); |
|
1995 sprintf(headPtr->hmAvgWaitTransactions, "%3.1f\0", w_pct); |
|
1996 sprintf(headPtr->hmDiskBusyPcnt, "%3.1f\0", r_pct); |
|
1997 sprintf(headPtr->hmAvgDiskSvcTime, "%3.1f\0", serv); |
|
1998 |
|
1999 /* |
|
2000 * Don't change the hmDiskState here because existing |
|
2001 * diskState should be maintained |
|
2002 */ |
|
2003 |
|
2004 headPtr->hmTraversed=1; |
|
2005 |
|
2006 } |
|
2007 headPtr = headPtr->pNext; |
|
2008 |
|
2009 } /* End of while loop around each row */ |
|
2010 |
|
2011 if (hit != 1) { |
|
2012 |
|
2013 |
|
2014 /* A new Disk is found in this refresh cycle . How likely ? */ |
|
2015 |
|
2016 ptr = (hmDiskTable *) malloc(sizeof(hmDiskTable)); |
|
2017 |
|
2018 ptr->hmDiskName = (char *) malloc(strlen(name) + 1); |
|
2019 ptr->hmDiskAliasName = (char *) malloc(strlen(alias) + 1); |
|
2020 ptr->hmAvgWaitTransactions = (char *) malloc(DISK_DATA_LEN); |
|
2021 ptr->hmDiskBusyPcnt = (char *) malloc(DISK_DATA_LEN); |
|
2022 ptr->hmAvgDiskSvcTime = (char *) malloc(DISK_DATA_LEN); |
|
2023 |
|
2024 if ( ptr->hmAvgDiskSvcTime == NULL) { |
|
2025 snmp_log(LOG_DEBUG,"malloc failed when refreshing DISK table in health monitor module \n"); |
|
2026 return; |
|
2027 } |
|
2028 |
|
2029 strcpy(ptr->hmDiskName,name); |
|
2030 |
|
2031 strcpy(ptr->hmDiskAliasName,alias); |
|
2032 |
|
2033 sprintf(ptr->hmAvgWaitTransactions, "%3.1f\0", w_pct); |
|
2034 |
|
2035 sprintf(ptr->hmDiskBusyPcnt, "%3.1f\0", r_pct); |
|
2036 |
|
2037 sprintf(ptr->hmAvgDiskSvcTime, "%3.1f\0", serv); |
|
2038 |
|
2039 /* Set the state of Disk to OK. */ |
|
2040 |
|
2041 ptr->hmDiskState = OK; |
|
2042 |
|
2043 /* Set Traversed to 1 */ |
|
2044 |
|
2045 ptr->hmTraversed=1; |
|
2046 |
|
2047 |
|
2048 ptr->pNext = NULL; |
|
2049 |
|
2050 if (tailPtr == NULL) { |
|
2051 head = tailPtr = ptr; |
|
2052 } else { |
|
2053 |
|
2054 tailPtr->pNext = ptr; |
|
2055 tailPtr = ptr; |
|
2056 } |
|
2057 |
|
2058 } |
|
2059 diskCount++; |
|
2060 |
|
2061 } while (code == 0); |
|
2062 |
|
2063 /* Any disk that is not "touched" previously (i.e, has |
|
2064 * hmTraversal value of 0, means that it's a removed disk. |
|
2065 * Traverse through the whole list again and remove those |
|
2066 * entries from the list. |
|
2067 */ |
|
2068 |
|
2069 p1=head; |
|
2070 p2=head; |
|
2071 |
|
2072 while( p2 != NULL) { |
|
2073 |
|
2074 if (p2->hmTraversed == 0) { |
|
2075 |
|
2076 /* Take care of removing this disk */ |
|
2077 |
|
2078 if(p2->pNext != NULL) { |
|
2079 p1->pNext = p2->pNext; |
|
2080 free(p2); |
|
2081 p2=p1->pNext; |
|
2082 } else { |
|
2083 p1->pNext=NULL; |
|
2084 free(p2); |
|
2085 p2=NULL; |
|
2086 } |
|
2087 } else { |
|
2088 |
|
2089 /* Extend pointers by 1 step */ |
|
2090 |
|
2091 if(p2->pNext != NULL) { |
|
2092 |
|
2093 p1=p2; |
|
2094 p2=p2->pNext; |
|
2095 } else { |
|
2096 |
|
2097 p2=p2->pNext; |
|
2098 } |
|
2099 } |
|
2100 } |
|
2101 |
|
2102 |
|
2103 check_state_DISK(); |
|
2104 |
|
2105 time(&hm_prev_disk_ref); |
|
2106 |
|
2107 } |
|
2108 |
|
2109 /* |
|
2110 * Function: refresh_all_HM_data. This function collects the data for all |
|
2111 * nodes in the module and stores the data in the data variables. The |
|
2112 * function is called every "refresh-interval" automatically. After the data |
|
2113 * is refreshed, the alarm condition is checked and a trap is sent if the |
|
2114 * conditions are met. |
|
2115 */ |
|
2116 |
|
2117 void |
|
2118 refresh_all_HM_data(unsigned int clientreg, void *clientarg) |
|
2119 { |
|
2120 |
|
2121 time_t hm_current_time; |
|
2122 |
|
2123 /* Did the previous refresh really finish ?? |
|
2124 * This means that previous refresh is still in progress */ |
|
2125 if (hm_prev_ref_time == 0) return; |
|
2126 |
|
2127 time(&hm_current_time); |
|
2128 |
|
2129 /* Did the previous refresh finish too close to start another refresh ??? |
|
2130 * This means that the previous refresh finished relatively closer to current time |
|
2131 * so, another refresh is not necessary. hm_prev_ref_time is initialized to 1 |
|
2132 * during variable declaration. so, the first time refresh is called, it will always |
|
2133 * proceed. |
|
2134 */ |
|
2135 |
|
2136 /* printf("%u %u %u\n",hm_current_time, hm_prev_ref_time, hm_refresh_interval/4);*/ |
|
2137 if ( (hm_current_time - hm_prev_ref_time) < (hm_refresh_interval / 4) ) return; |
|
2138 |
|
2139 /* set to 0 so that we can block any other refresh's */ |
|
2140 hm_prev_ref_time = 0; |
|
2141 |
|
2142 /* refresh data for SWAP nodes and check alarm condition */ |
|
2143 |
|
2144 refresh_SWAP_data(); |
|
2145 hm_handle_rule(&SWAP_rule_state, &SWAP_rule); |
|
2146 |
|
2147 /* Acquire data for Kernel nodes */ |
|
2148 |
|
2149 refresh_Kernel_data(); |
|
2150 hm_handle_rule(&Kernel_rule_state, &Kernel_rule); |
|
2151 |
|
2152 /* Acquire data for NFS nodes */ |
|
2153 |
|
2154 refresh_NFS_data(); |
|
2155 hm_handle_rule(&NFS_rule_state, &NFS_rule); |
|
2156 |
|
2157 /* Acquire data for CPU nodes */ |
|
2158 |
|
2159 refresh_CPU_data(); |
|
2160 hm_handle_rule(&CPU_rule_state, &CPU_rule); |
|
2161 |
|
2162 /* Acquire data for RAM nodes */ |
|
2163 |
|
2164 refresh_RAM_data(); |
|
2165 hm_handle_rule(&RAM_rule_state, &RAM_rule); |
|
2166 |
|
2167 /* Acquire data for KMEM nodes */ |
|
2168 |
|
2169 refresh_KMEM_data(); |
|
2170 hm_handle_rule(&KMEM_rule_state, &KMEM_rule); |
|
2171 |
|
2172 /* Acquire data for DNLC nodes */ |
|
2173 |
|
2174 refresh_DNLC_data(); |
|
2175 hm_handle_rule(&DNLC_rule_state, &DNLC_rule); |
|
2176 |
|
2177 /* End of Data acquisition for HM module */ |
|
2178 |
|
2179 time(&hm_prev_ref_time); |
|
2180 |
|
2181 return; |
|
2182 |
|
2183 } |
|
2184 |
|
2185 /* |
|
2186 * Function: read_health_monitor_thresholds: This function is called whenever |
|
2187 * a registered token is encountered in health_monitor.conf file. The |
|
2188 * function simply stores the token's value in the appropriate threshold |
|
2189 * variable. |
|
2190 */ |
|
2191 |
|
2192 void |
|
2193 read_health_monitor_thresholds(const char *token, char *cptr) |
|
2194 { |
|
2195 |
|
2196 if (strcmp(token, "hm_refresh_interval") == 0) { |
|
2197 hm_refresh_interval = atoi(cptr); |
|
2198 } else if (strcmp(token, "threshold_swapavail_info") == 0) { |
|
2199 threshold_swapavail_info = atoi(cptr); |
|
2200 } else if (strcmp(token, "threshold_swapavail_warning") == 0) { |
|
2201 threshold_swapavail_warning = atoi(cptr); |
|
2202 } else if (strcmp(token, "threshold_swapavail_error") == 0) { |
|
2203 threshold_swapavail_error = atoi(cptr); |
|
2204 } else if (strcmp(token, "threshold_mutex_info") == 0) { |
|
2205 threshold_mutex_info = atol(cptr); |
|
2206 } else if (strcmp(token, "threshold_mutex_warning") == 0) { |
|
2207 threshold_mutex_warning = atol(cptr); |
|
2208 } else if (strcmp(token, "threshold_mincalls") == 0) { |
|
2209 threshold_mincalls = atof(cptr); |
|
2210 } else if (strcmp(token, "threshold_badxids") == 0) { |
|
2211 threshold_badxids = atof(cptr); |
|
2212 } else if (strcmp(token, "threshold_timeouts") == 0) { |
|
2213 threshold_timeouts = atof(cptr); |
|
2214 } else if (strcmp(token, "threshold_cpuload_info") == 0) { |
|
2215 threshold_cpuload_info = atof(cptr); |
|
2216 } else if (strcmp(token, "threshold_cpuload_warning") == 0) { |
|
2217 threshold_cpuload_warning = atof(cptr); |
|
2218 } else if (strcmp(token, "threshold_cpuload_error") == 0) { |
|
2219 threshold_cpuload_error = atof(cptr); |
|
2220 } else if (strcmp(token, "threshold_restime_long") == 0) { |
|
2221 threshold_restime_long = atoi(cptr); |
|
2222 } else if (strcmp(token, "threshold_restime_ok") == 0) { |
|
2223 threshold_restime_ok = atoi(cptr); |
|
2224 } else if (strcmp(token, "threshold_restime_error") == 0) { |
|
2225 threshold_restime_error = atoi(cptr); |
|
2226 } else if (strcmp(token, "threshold_freemem_low") == 0) { |
|
2227 threshold_freemem_low = atoi(cptr); |
|
2228 } else if (strcmp(token, "threshold_dnlc_active") == 0) { |
|
2229 threshold_dnlc_active = atof(cptr); |
|
2230 } else if (strcmp(token, "threshold_dnlc_warning") == 0) { |
|
2231 threshold_dnlc_warning = atof(cptr); |
|
2232 } else if (strcmp(token, "disk_busy_warning") == 0) { |
|
2233 disk_busy_warning = atol(cptr); |
|
2234 } else if (strcmp(token, "disk_busy_problem") == 0) { |
|
2235 disk_busy_problem = atol(cptr); |
|
2236 } else if (strcmp(token, "disk_svc_t_warning") == 0) { |
|
2237 disk_svc_t_warning = atol(cptr); |
|
2238 } else if (strcmp(token, "disk_svc_t_problem") == 0) { |
|
2239 disk_svc_t_problem = atol(cptr); |
|
2240 } else { |
|
2241 /* Do nothing */ |
|
2242 } |
|
2243 |
|
2244 |
|
2245 return; |
|
2246 } |
|
2247 |
|
2248 /* |
|
2249 * hm_handle_rule: |
|
2250 * |
|
2251 * arguments: rule_state = previous state of the rule rule = Function |
|
2252 * pointer to the actual rule |
|
2253 * |
|
2254 * This function first determines the new state of the rule by calling |
|
2255 * rule(CONDITION). |
|
2256 * |
|
2257 * In the switch loop, depending on the previous rule state (the rule_state) and |
|
2258 * new state, the rule function is again called appropriately. For example, |
|
2259 * if the previous state is INIT and the new state is > OK, then rule(OPEN) |
|
2260 * is called. |
|
2261 * |
|
2262 */ |
|
2263 |
|
2264 |
|
2265 void |
|
2266 hm_handle_rule(int *rule_state, int (*rule) (int)) |
|
2267 { |
|
2268 |
|
2269 int new_alarm_state; |
|
2270 |
|
2271 if (*rule_state == NOTINIT) { |
|
2272 *rule_state = INIT; |
|
2273 rule(INIT); |
|
2274 } |
|
2275 new_alarm_state = rule(CONDITION); |
|
2276 |
|
2277 switch (*rule_state) { |
|
2278 |
|
2279 case INIT: |
|
2280 if (new_alarm_state > OK) { |
|
2281 *rule_state = OPEN; |
|
2282 rule(OPEN); |
|
2283 } |
|
2284 return; |
|
2285 case OPEN: |
|
2286 if (new_alarm_state == OK) { |
|
2287 *rule_state = CLOSE; |
|
2288 rule(CLOSE); |
|
2289 } else { |
|
2290 *rule_state = CONTINUE; |
|
2291 rule(CONTINUE); |
|
2292 } |
|
2293 return; |
|
2294 case CONTINUE: |
|
2295 if (new_alarm_state == OK) { |
|
2296 *rule_state = CLOSE; |
|
2297 rule(CLOSE); |
|
2298 } else { |
|
2299 *rule_state = CONTINUE; |
|
2300 rule(CONTINUE); |
|
2301 } |
|
2302 return; |
|
2303 case CLOSE: |
|
2304 if (new_alarm_state > OK) { |
|
2305 *rule_state = OPEN; |
|
2306 rule(OPEN); |
|
2307 } |
|
2308 return; |
|
2309 } |
|
2310 |
|
2311 } |
|
2312 |
|
2313 |
|
2314 /* |
|
2315 * Function: send_trap : This function sends a *statusChange* trap with |
|
2316 * appropriate varbind's see SMA trap mib for detailed trap notification |
|
2317 * definition. |
|
2318 * |
|
2319 * hostname - Name of host on which alarm occured ; modulename - Name of the |
|
2320 * module generating the trap ; moduleContext - The context of the module, if |
|
2321 * any; statusOID - The trapoid; size - The size of trapoid (not included in |
|
2322 * the trap); status - status of the node; description - description of the |
|
2323 * trap; dvalue - value of the node on which trap occured; dtype - data type of |
|
2324 * the value |
|
2325 */ |
|
2326 |
|
2327 void |
|
2328 send_trap(u_char * hostname, u_char * modulename, u_char * moduleContext, oid * trapoid, int size, u_char * status, u_char * description, u_char * dvalue, int dtype) |
|
2329 { |
|
2330 |
|
2331 /* This is the notification type itself. This is statusChange trap */ |
|
2332 |
|
2333 oid notification_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 2, 4, 3, 0, 1}; |
|
2334 |
|
2335 size_t notification_oid_len = OID_LENGTH(notification_oid); |
|
2336 |
|
2337 /* |
|
2338 * In the notification, we have to assign our notification OID to the |
|
2339 * snmpTrapOID.0 object. Here is it's definition. |
|
2340 */ |
|
2341 |
|
2342 oid objid_snmptrap[] = {1, 3, 6, 1, 6, 3, 1, 1, 4, 1, 0}; |
|
2343 size_t objid_snmptrap_len = OID_LENGTH(objid_snmptrap); |
|
2344 |
|
2345 /* |
|
2346 * here is where we store the variables to be sent in the trap |
|
2347 */ |
|
2348 |
|
2349 netsnmp_variable_list *notification_vars = NULL; |
|
2350 |
|
2351 oid hostname_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 2, 4, 3, 1, 1, 0}; |
|
2352 |
|
2353 size_t hostname_oid_len = OID_LENGTH(hostname_oid); |
|
2354 |
|
2355 |
|
2356 oid modulename_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 2, 4, 3, 1, 2, 0}; |
|
2357 |
|
2358 size_t modulename_oid_len = OID_LENGTH(modulename_oid); |
|
2359 |
|
2360 |
|
2361 oid nodeoid_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 2, 4, 3, 1, 3, 0}; |
|
2362 |
|
2363 size_t nodeoid_oid_len = OID_LENGTH(nodeoid_oid); |
|
2364 |
|
2365 |
|
2366 oid moduleContext_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 2, 4, 3, 1, 4, 0}; |
|
2367 |
|
2368 size_t moduleContext_oid_len = OID_LENGTH(moduleContext_oid); |
|
2369 |
|
2370 |
|
2371 oid status_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 2, 4, 3, 1, 5, 0}; |
|
2372 |
|
2373 size_t status_oid_len = OID_LENGTH(status_oid); |
|
2374 |
|
2375 |
|
2376 oid description_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 2, 4, 3, 1, 6, 0}; |
|
2377 |
|
2378 size_t description_oid_len = OID_LENGTH(description_oid); |
|
2379 |
|
2380 oid dvalue_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 2, 4, 3, 1, 7, 0}; |
|
2381 |
|
2382 size_t dvalue_oid_len = OID_LENGTH(dvalue_oid); |
|
2383 |
|
2384 oid dtype_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 2, 4, 3, 1, 8, 0}; |
|
2385 |
|
2386 size_t dtype_oid_len = OID_LENGTH(dtype_oid); |
|
2387 |
|
2388 |
|
2389 /* |
|
2390 * add in the trap definition object |
|
2391 */ |
|
2392 |
|
2393 snmp_varlist_add_variable(¬ification_vars, |
|
2394 /* |
|
2395 * the snmpTrapOID.0 variable |
|
2396 */ |
|
2397 objid_snmptrap, objid_snmptrap_len, |
|
2398 /* |
|
2399 * value type is an OID |
|
2400 */ |
|
2401 ASN_OBJECT_ID, |
|
2402 /* |
|
2403 * value contents is our notification OID |
|
2404 */ |
|
2405 (u_char *) notification_oid, |
|
2406 /* |
|
2407 * size in bytes = oid length * sizeof(oid) |
|
2408 */ |
|
2409 notification_oid_len * sizeof(oid)); |
|
2410 |
|
2411 |
|
2412 /* |
|
2413 * if we wanted to insert additional objects, we'd do it here |
|
2414 */ |
|
2415 |
|
2416 |
|
2417 snmp_varlist_add_variable(¬ification_vars, |
|
2418 hostname_oid, hostname_oid_len, |
|
2419 /* |
|
2420 * value type is an OID |
|
2421 */ |
|
2422 ASN_OCTET_STR, |
|
2423 /* |
|
2424 * value contents is our notification OID |
|
2425 */ |
|
2426 (u_char *) hostname, |
|
2427 /* |
|
2428 * size in bytes = oid length * sizeof(oid) |
|
2429 */ |
|
2430 strlen((char *) hostname)); |
|
2431 |
|
2432 |
|
2433 snmp_varlist_add_variable(¬ification_vars, |
|
2434 modulename_oid, modulename_oid_len, |
|
2435 /* |
|
2436 * value type is an OID |
|
2437 */ |
|
2438 ASN_OCTET_STR, |
|
2439 /* |
|
2440 * value contents is our notification OID |
|
2441 */ |
|
2442 (u_char *) modulename, |
|
2443 /* |
|
2444 * size in bytes = oid length * sizeof(oid) |
|
2445 */ |
|
2446 strlen((char *) modulename)); |
|
2447 |
|
2448 |
|
2449 snmp_varlist_add_variable(¬ification_vars, |
|
2450 nodeoid_oid, nodeoid_oid_len, |
|
2451 /* |
|
2452 * value type is an OID |
|
2453 */ |
|
2454 ASN_OBJECT_ID, |
|
2455 /* |
|
2456 * value contents is our notification OID |
|
2457 */ |
|
2458 (u_char *) trapoid, |
|
2459 /* |
|
2460 * size in bytes = oid length * sizeof(oid) |
|
2461 */ |
|
2462 size * sizeof(oid)); |
|
2463 |
|
2464 |
|
2465 snmp_varlist_add_variable(¬ification_vars, |
|
2466 moduleContext_oid, moduleContext_oid_len, |
|
2467 /* |
|
2468 * value type is an OID |
|
2469 */ |
|
2470 ASN_OCTET_STR, |
|
2471 /* |
|
2472 * value contents is our notification OID |
|
2473 */ |
|
2474 (u_char *) moduleContext, |
|
2475 /* |
|
2476 * size in bytes = oid length * sizeof(oid) |
|
2477 */ |
|
2478 strlen((char *) moduleContext)); |
|
2479 |
|
2480 |
|
2481 snmp_varlist_add_variable(¬ification_vars, |
|
2482 status_oid, status_oid_len, |
|
2483 /* |
|
2484 * value type is an OID |
|
2485 */ |
|
2486 ASN_OCTET_STR, |
|
2487 /* |
|
2488 * value contents is our notification OID |
|
2489 */ |
|
2490 (u_char *) status, |
|
2491 /* |
|
2492 * size in bytes = oid length * sizeof(oid) |
|
2493 */ |
|
2494 strlen((char *) status)); |
|
2495 |
|
2496 |
|
2497 snmp_varlist_add_variable(¬ification_vars, |
|
2498 description_oid, description_oid_len, |
|
2499 /* |
|
2500 * value type is an OID |
|
2501 */ |
|
2502 ASN_OCTET_STR, |
|
2503 /* |
|
2504 * value contents is our notification OID |
|
2505 */ |
|
2506 (u_char *) description, |
|
2507 /* |
|
2508 * size in bytes = oid length * sizeof(oid) |
|
2509 */ |
|
2510 strlen((char *) description)); |
|
2511 |
|
2512 |
|
2513 snmp_varlist_add_variable(¬ification_vars, |
|
2514 dvalue_oid, dvalue_oid_len, |
|
2515 /* |
|
2516 * value type is an OID |
|
2517 */ |
|
2518 ASN_OCTET_STR, |
|
2519 /* |
|
2520 * value contents is our notification OID |
|
2521 */ |
|
2522 (u_char *) dvalue, |
|
2523 /* |
|
2524 * size in bytes = oid length * sizeof(oid) |
|
2525 */ |
|
2526 strlen((char *) dvalue)); |
|
2527 |
|
2528 |
|
2529 |
|
2530 snmp_varlist_add_variable(¬ification_vars, |
|
2531 dtype_oid, dtype_oid_len, |
|
2532 /* |
|
2533 * value type is an OID |
|
2534 */ |
|
2535 ASN_INTEGER, |
|
2536 /* |
|
2537 * value contents is our notification OID |
|
2538 */ |
|
2539 (u_char *) & dtype, |
|
2540 /* |
|
2541 * size in bytes = oid length * sizeof(oid) |
|
2542 */ |
|
2543 sizeof(dtype)); |
|
2544 |
|
2545 |
|
2546 /* SEND THE TRAP !!!! */ |
|
2547 |
|
2548 send_v2trap(notification_vars); |
|
2549 |
|
2550 /* |
|
2551 * free the created notification variable list |
|
2552 */ |
|
2553 |
|
2554 DEBUGMSGTL(("example_notification", "cleaning up\n")); |
|
2555 snmp_free_varbind(notification_vars); |
|
2556 |
|
2557 return; |
|
2558 |
|
2559 } |
|
2560 |
|
2561 /* |
|
2562 * Function: conv_alarm_state : This function returns appropriate charecter |
|
2563 * string for each integer alarm type |
|
2564 */ |
|
2565 |
|
2566 char * |
|
2567 conv_alarm_state(int state) |
|
2568 { |
|
2569 switch (state) { |
|
2570 case OK: |
|
2571 return "OK\0"; |
|
2572 case INFO: |
|
2573 return "INFO\0"; |
|
2574 case WARNING: |
|
2575 return "WARNING\0"; |
|
2576 case ERROR: |
|
2577 return "ERROR\0"; |
|
2578 default: |
|
2579 return "INVALID\0"; |
|
2580 } |
|
2581 } |
|
2582 |
|
2583 |
|
2584 |
|
2585 /* |
|
2586 * Function: SWAP_rule : This function checks the state of SWAP nodes and |
|
2587 * issues trap if necessary |
|
2588 */ |
|
2589 |
|
2590 int |
|
2591 SWAP_rule(int action) |
|
2592 { |
|
2593 |
|
2594 /* This is the OID of hmAvailableSwapSpace */ |
|
2595 oid trapoid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 1, 1, 1, 0}; |
|
2596 u_char status[8]; |
|
2597 u_char description[] = "Available Swap space on the system is low"; |
|
2598 int size; |
|
2599 u_char dvalue[15]; |
|
2600 /* The value of dtype is 1 here becuase swapavail_data is of "int" type */ |
|
2601 int dtype = 1; |
|
2602 |
|
2603 sprintf((char *) dvalue, "%d\0", swapavail_data); |
|
2604 size = sizeof(trapoid) / sizeof(oid); |
|
2605 |
|
2606 switch (action) { |
|
2607 |
|
2608 case CONDITION: |
|
2609 |
|
2610 /* |
|
2611 * Quite straightforward. Depending on the threshold that is crossed, |
|
2612 * assign the new state |
|
2613 */ |
|
2614 |
|
2615 if ((swapavail_data <= threshold_swapavail_info) && (swapavail_data > threshold_swapavail_warning)) { |
|
2616 new_SWAP_state = INFO; |
|
2617 return INFO; |
|
2618 } else if ((swapavail_data <= threshold_swapavail_warning) && (swapavail_data > threshold_swapavail_error)) { |
|
2619 new_SWAP_state = WARNING; |
|
2620 return WARNING; |
|
2621 } else if (swapavail_data <= threshold_swapavail_error) { |
|
2622 new_SWAP_state = ERROR; |
|
2623 return ERROR; |
|
2624 } |
|
2625 new_SWAP_state = OK; |
|
2626 return OK; |
|
2627 |
|
2628 case OPEN: |
|
2629 |
|
2630 strcpy((char *) status, conv_alarm_state(new_SWAP_state)); |
|
2631 send_trap(hostName, moduleName, statusOIDContext, trapoid, size, status, description, dvalue, dtype); |
|
2632 return 0; |
|
2633 |
|
2634 case INIT: |
|
2635 |
|
2636 return 0; |
|
2637 |
|
2638 case CONTINUE: |
|
2639 |
|
2640 strcpy((char *) status, conv_alarm_state(new_SWAP_state)); |
|
2641 if (new_SWAP_state > prev_SWAP_state) { |
|
2642 |
|
2643 /* Send trap */ |
|
2644 send_trap(hostName, moduleName, statusOIDContext, trapoid, size, status, description, dvalue, dtype); |
|
2645 prev_SWAP_state = new_SWAP_state; |
|
2646 |
|
2647 } |
|
2648 return 0; |
|
2649 |
|
2650 case CLOSE: |
|
2651 |
|
2652 strcpy((char *) status, conv_alarm_state(new_SWAP_state)); |
|
2653 send_trap(hostName, moduleName, statusOIDContext, trapoid, size, status, description, dvalue, dtype); |
|
2654 return 0; |
|
2655 |
|
2656 default: |
|
2657 |
|
2658 return 0; |
|
2659 } |
|
2660 |
|
2661 } |
|
2662 |
|
2663 /* |
|
2664 * Function: Kernel_rule : This function checks the state of Kernel nodes and |
|
2665 * issues trap if necessary |
|
2666 */ |
|
2667 |
|
2668 int |
|
2669 Kernel_rule(int action) |
|
2670 { |
|
2671 |
|
2672 int mutexrate; |
|
2673 |
|
2674 /* This is the OID of hmSpinsOnMutexes */ |
|
2675 oid trapoid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 2, 1, 1, 0}; |
|
2676 u_char status[8]; |
|
2677 u_char description[] = "Mutex contention rate is high , kernel overload \0"; |
|
2678 int size; |
|
2679 u_char dvalue[15]; |
|
2680 /* |
|
2681 * dtype is set to 1 because the hmSpinsOnMutexes node is defined as |
|
2682 * Integer32 in the mib |
|
2683 */ |
|
2684 int dtype = 1; |
|
2685 |
|
2686 sprintf((char *) dvalue, "%lu\0", sum_smtx); |
|
2687 size = sizeof(trapoid) / sizeof(oid); |
|
2688 |
|
2689 switch (action) { |
|
2690 |
|
2691 case CONDITION: |
|
2692 |
|
2693 if (ncpus == 0) { |
|
2694 /* this happens only during initialization */ |
|
2695 new_mutex_state = OK; |
|
2696 return OK; |
|
2697 } |
|
2698 mutexrate = sum_smtx / ncpus; |
|
2699 |
|
2700 /* Determine if there is a new Alarm state */ |
|
2701 |
|
2702 if (mutexrate < threshold_mutex_info) { |
|
2703 if (mutexrate == 0) { |
|
2704 |
|
2705 /* |
|
2706 * This is a change from existing rule. It makes more sense |
|
2707 * that if mutexrate is 0, then the state should be OK. i.e, |
|
2708 * no problems |
|
2709 */ |
|
2710 |
|
2711 new_mutex_state = OK; |
|
2712 return OK; |
|
2713 |
|
2714 } else { |
|
2715 new_mutex_state = INFO; |
|
2716 return INFO; |
|
2717 } |
|
2718 } else if (mutexrate < threshold_mutex_warning) { |
|
2719 new_mutex_state = WARNING; |
|
2720 return WARNING; |
|
2721 } else { |
|
2722 new_mutex_state = ERROR; |
|
2723 return WARNING; |
|
2724 } |
|
2725 |
|
2726 case OPEN: |
|
2727 |
|
2728 strcpy((char *) status, conv_alarm_state(new_mutex_state)); |
|
2729 send_trap(hostName, moduleName, statusOIDContext, trapoid, size, status, description, dvalue, dtype); |
|
2730 return 0; |
|
2731 |
|
2732 case INIT: |
|
2733 |
|
2734 return 0; |
|
2735 |
|
2736 case CONTINUE: |
|
2737 |
|
2738 strcpy((char *) status, conv_alarm_state(new_mutex_state)); |
|
2739 |
|
2740 if (new_mutex_state > prev_mutex_state) { |
|
2741 |
|
2742 /* Send trap */ |
|
2743 send_trap(hostName, moduleName, statusOIDContext, trapoid, size, status, description, dvalue, dtype); |
|
2744 prev_mutex_state = new_mutex_state; |
|
2745 |
|
2746 } |
|
2747 return 0; |
|
2748 |
|
2749 case CLOSE: |
|
2750 |
|
2751 strcpy((char *) status, conv_alarm_state(new_mutex_state)); |
|
2752 send_trap(hostName, moduleName, statusOIDContext, trapoid, size, status, description, dvalue, dtype); |
|
2753 return 0; |
|
2754 |
|
2755 default: |
|
2756 |
|
2757 return 0; |
|
2758 } |
|
2759 |
|
2760 } |
|
2761 |
|
2762 /* |
|
2763 * Function: NFS_rule : This function checks the state of NFS nodes and |
|
2764 * issues trap if necessary |
|
2765 */ |
|
2766 |
|
2767 int |
|
2768 NFS_rule(int action) |
|
2769 { |
|
2770 |
|
2771 float maxtimeout, maxbadxid; |
|
2772 |
|
2773 /* |
|
2774 * This is the OID of hmNFSClientRPCGroup. Note that this rule uses data |
|
2775 * from more than one node to determine the alarm state |
|
2776 */ |
|
2777 oid trapoid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 3, 1}; |
|
2778 u_char status[8]; |
|
2779 u_char description[] = "Bad Network or Server is slow. May need to increase timeout \0 "; |
|
2780 int size; |
|
2781 u_char dvalue[15]; |
|
2782 int dtype = 1; |
|
2783 |
|
2784 /* |
|
2785 * It's tricky which "value" should be put in dvalue field. More than one |
|
2786 * node's data is looked at to determine alarm state. |
|
2787 */ |
|
2788 sprintf((char *) dvalue, "%d\0", timeouts); |
|
2789 size = sizeof(trapoid) / sizeof(oid); |
|
2790 |
|
2791 switch (action) { |
|
2792 |
|
2793 case CONDITION: |
|
2794 |
|
2795 if (calls <= threshold_mincalls) { |
|
2796 /* |
|
2797 * This is a change from existing rule (which has INFO). It makes |
|
2798 * sense that no trap is sent when calls is < threshold_mincalls. |
|
2799 */ |
|
2800 |
|
2801 new_NFS_state = OK; |
|
2802 return OK; |
|
2803 } else { |
|
2804 maxtimeout = threshold_timeouts * calls / 100.0; |
|
2805 |
|
2806 if (timeouts < maxtimeout) { |
|
2807 |
|
2808 /* |
|
2809 * This is a change from existing rule (which has INFO). It |
|
2810 * makes sense that no trap is sent when timeouts is < |
|
2811 * maxtimeout |
|
2812 */ |
|
2813 |
|
2814 new_NFS_state = OK; |
|
2815 return OK; |
|
2816 |
|
2817 } else { |
|
2818 maxbadxid = threshold_badxids * timeouts / 100.0; |
|
2819 if ((maxtimeout <= timeouts) && (badxids <= maxbadxid)) { |
|
2820 new_NFS_state = WARNING; |
|
2821 return WARNING; |
|
2822 } else { |
|
2823 /* |
|
2824 * This will be the case when timeout >= maxtimeout AND |
|
2825 * badxids > maxbadxid |
|
2826 */ |
|
2827 new_NFS_state = ERROR; |
|
2828 return ERROR; |
|
2829 } |
|
2830 } |
|
2831 } |
|
2832 |
|
2833 case OPEN: |
|
2834 |
|
2835 strcpy((char *) status, conv_alarm_state(new_NFS_state)); |
|
2836 send_trap(hostName, moduleName, statusOIDContext, trapoid, size, status, description, dvalue, dtype); |
|
2837 return 0; |
|
2838 |
|
2839 case INIT: |
|
2840 |
|
2841 return 0; |
|
2842 |
|
2843 case CONTINUE: |
|
2844 |
|
2845 strcpy((char *) status, conv_alarm_state(new_NFS_state)); |
|
2846 if (new_NFS_state > prev_NFS_state) { |
|
2847 |
|
2848 /* Send trap */ |
|
2849 send_trap(hostName, moduleName, statusOIDContext, trapoid, size, status, description, dvalue, dtype); |
|
2850 prev_NFS_state = new_NFS_state; |
|
2851 |
|
2852 } |
|
2853 return 0; |
|
2854 |
|
2855 case CLOSE: |
|
2856 |
|
2857 strcpy((char *) status, conv_alarm_state(new_NFS_state)); |
|
2858 send_trap(hostName, moduleName, statusOIDContext, trapoid, size, status, description, dvalue, dtype); |
|
2859 return 0; |
|
2860 |
|
2861 default: |
|
2862 |
|
2863 return 0; |
|
2864 } |
|
2865 |
|
2866 } |
|
2867 |
|
2868 /* |
|
2869 * Function: CPU_rule : This function checks the state of CPU nodes and |
|
2870 * issues trap if necessary |
|
2871 */ |
|
2872 |
|
2873 int |
|
2874 CPU_rule(int action) |
|
2875 { |
|
2876 |
|
2877 /* This is the OID for hmTotProcInRunQueue */ |
|
2878 oid trapoid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 4, 1, 1, 0}; |
|
2879 u_char status[8]; |
|
2880 u_char description[] = "CPU overloaded \0"; |
|
2881 int size; |
|
2882 u_char dvalue[15]; |
|
2883 /* dtype is given a value of 1 because runque is of "int" type */ |
|
2884 int dtype = 1; |
|
2885 |
|
2886 float cpuload; |
|
2887 |
|
2888 sprintf((char *) dvalue, "%d\0", runque); |
|
2889 size = sizeof(trapoid) / sizeof(oid); |
|
2890 |
|
2891 switch (action) { |
|
2892 |
|
2893 case CONDITION: |
|
2894 |
|
2895 /* |
|
2896 * Added this If statement to existing rule. From Kernel_rule, it |
|
2897 * looks like ncpus may be 0 during initialization |
|
2898 */ |
|
2899 if (ncpus == 0) { |
|
2900 /* this happens only during initialization */ |
|
2901 new_cpuload_state = OK; |
|
2902 return OK; |
|
2903 } |
|
2904 cpuload = runque / ncpus; |
|
2905 |
|
2906 /* |
|
2907 * Quite straightforward. If the threshold is crossed, set the state |
|
2908 * accordingly |
|
2909 */ |
|
2910 |
|
2911 if (cpuload < threshold_cpuload_info) { |
|
2912 new_cpuload_state = OK; |
|
2913 return OK; |
|
2914 } else if (cpuload < threshold_cpuload_warning) { |
|
2915 new_cpuload_state = INFO; |
|
2916 return INFO; |
|
2917 } else if (cpuload < threshold_cpuload_error) { |
|
2918 new_cpuload_state = WARNING; |
|
2919 return WARNING; |
|
2920 } else { |
|
2921 new_cpuload_state = ERROR; |
|
2922 return ERROR; |
|
2923 } |
|
2924 |
|
2925 case OPEN: |
|
2926 |
|
2927 strcpy((char *) status, conv_alarm_state(new_cpuload_state)); |
|
2928 send_trap(hostName, moduleName, statusOIDContext, trapoid, size, status, description, dvalue, dtype); |
|
2929 return 0; |
|
2930 |
|
2931 case INIT: |
|
2932 |
|
2933 return 0; |
|
2934 |
|
2935 case CONTINUE: |
|
2936 |
|
2937 strcpy((char *) status, conv_alarm_state(new_cpuload_state)); |
|
2938 if (new_cpuload_state > prev_cpuload_state) { |
|
2939 |
|
2940 /* Send trap */ |
|
2941 send_trap(hostName, moduleName, statusOIDContext, trapoid, size, status, description, dvalue, dtype); |
|
2942 prev_cpuload_state = new_cpuload_state; |
|
2943 |
|
2944 } |
|
2945 return 0; |
|
2946 |
|
2947 case CLOSE: |
|
2948 |
|
2949 strcpy((char *) status, conv_alarm_state(new_cpuload_state)); |
|
2950 send_trap(hostName, moduleName, statusOIDContext, trapoid, size, status, description, dvalue, dtype); |
|
2951 return 0; |
|
2952 |
|
2953 default: |
|
2954 |
|
2955 return 0; |
|
2956 } |
|
2957 |
|
2958 } |
|
2959 |
|
2960 /* |
|
2961 * Function: RAM_rule : This function checks the state of RAM nodes and |
|
2962 * issues trap if necessary |
|
2963 */ |
|
2964 |
|
2965 int |
|
2966 RAM_rule(int action) |
|
2967 { |
|
2968 |
|
2969 /* |
|
2970 * This is the OID of hmRamMemoryPagingGroup. Note that this rule uses |
|
2971 * data from more than one node to determine the alarm state |
|
2972 */ |
|
2973 oid trapoid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 6, 1}; |
|
2974 u_char status[8]; |
|
2975 u_char description[] = "RAM shortage \0"; |
|
2976 int size; |
|
2977 u_char dvalue[15]; |
|
2978 |
|
2979 /* dtype is given a value of 1 because scan is of "int" type */ |
|
2980 int dtype = 1; |
|
2981 |
|
2982 float restime; |
|
2983 |
|
2984 /* |
|
2985 * It's tricky which "value" should be put in dvalue field. More than one |
|
2986 * node's data is looked at to determine alarm state. |
|
2987 */ |
|
2988 sprintf((char *) dvalue, "%d\0", scan); |
|
2989 |
|
2990 size = sizeof(trapoid) / sizeof(oid); |
|
2991 |
|
2992 switch (action) { |
|
2993 |
|
2994 case CONDITION: |
|
2995 |
|
2996 if (scan == 0) { |
|
2997 restime = threshold_restime_long; |
|
2998 } else { |
|
2999 restime = handspread / scan; |
|
3000 } |
|
3001 |
|
3002 if (restime > threshold_restime_long) { |
|
3003 restime = threshold_restime_long; |
|
3004 } |
|
3005 if (restime >= threshold_restime_long) { |
|
3006 /* This is a change from existing rule (which has INFO). */ |
|
3007 |
|
3008 new_restime_state = OK; |
|
3009 return OK; |
|
3010 } else { |
|
3011 if (restime > threshold_restime_ok) { |
|
3012 new_restime_state = INFO; |
|
3013 return INFO; |
|
3014 } else { |
|
3015 if (restime > threshold_restime_error) { |
|
3016 new_restime_state = WARNING; |
|
3017 return WARNING; |
|
3018 } else { |
|
3019 new_restime_state = ERROR; |
|
3020 return ERROR; |
|
3021 } |
|
3022 } |
|
3023 } |
|
3024 |
|
3025 case OPEN: |
|
3026 |
|
3027 strcpy((char *) status, conv_alarm_state(new_restime_state)); |
|
3028 send_trap(hostName, moduleName, statusOIDContext, trapoid, size, status, description, dvalue, dtype); |
|
3029 return 0; |
|
3030 |
|
3031 case INIT: |
|
3032 |
|
3033 return 0; |
|
3034 |
|
3035 case CONTINUE: |
|
3036 |
|
3037 strcpy((char *) status, conv_alarm_state(new_restime_state)); |
|
3038 if (new_restime_state > prev_restime_state) { |
|
3039 |
|
3040 /* Send trap */ |
|
3041 send_trap(hostName, moduleName, statusOIDContext, trapoid, size, status, description, dvalue, dtype); |
|
3042 prev_restime_state = new_restime_state; |
|
3043 |
|
3044 } |
|
3045 return 0; |
|
3046 |
|
3047 case CLOSE: |
|
3048 |
|
3049 strcpy((char *) status, conv_alarm_state(new_restime_state)); |
|
3050 send_trap(hostName, moduleName, statusOIDContext, trapoid, size, status, description, dvalue, dtype); |
|
3051 return 0; |
|
3052 |
|
3053 default: |
|
3054 |
|
3055 return 0; |
|
3056 } |
|
3057 |
|
3058 } |
|
3059 |
|
3060 /* |
|
3061 * Function: KMEM_rule : This function checks the state of KMEM nodes and |
|
3062 * issues trap if necessary |
|
3063 */ |
|
3064 |
|
3065 int |
|
3066 KMEM_rule(int action) |
|
3067 { |
|
3068 |
|
3069 /* |
|
3070 * This is the OID of hmKmemStatisticsGroup. Note that this rule uses |
|
3071 * data from more than one node to determine the alarm state |
|
3072 */ |
|
3073 oid trapoid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 7, 1}; |
|
3074 u_char status[8]; |
|
3075 u_char description[] = "Kernel Memory allocation errors \0"; |
|
3076 int size; |
|
3077 u_char dvalue[15]; |
|
3078 /* dtype is given a value of 1 because alloc_fail is of "int" type */ |
|
3079 int dtype = 1; |
|
3080 |
|
3081 int firsterrs, lasterrs; |
|
3082 |
|
3083 /* |
|
3084 * It's tricky which "value" should be put in dvalue field. More than one |
|
3085 * node's data is looked at to determine alarm state. |
|
3086 */ |
|
3087 sprintf((char *) dvalue, "%d\0", alloc_fail); |
|
3088 |
|
3089 size = sizeof(trapoid) / sizeof(oid); |
|
3090 |
|
3091 switch (action) { |
|
3092 |
|
3093 case CONDITION: |
|
3094 |
|
3095 /* This is a slightly confusing rule */ |
|
3096 |
|
3097 firsterrs = firstkmemerrs; |
|
3098 lasterrs = lastkmemerrs; |
|
3099 |
|
3100 if (alloc_fail == firsterrs) { |
|
3101 if (alloc_fail == 0) { |
|
3102 /* |
|
3103 * This is a change from existing rule (which has INFO). It |
|
3104 * makes sense that an OK state should be returned when |
|
3105 * alloc_fail is 0 |
|
3106 */ |
|
3107 new_kmem_state = OK; |
|
3108 return OK; |
|
3109 } else { |
|
3110 new_kmem_state = INFO; |
|
3111 return INFO; |
|
3112 } |
|
3113 } else { |
|
3114 if (alloc_fail == lasterrs) { |
|
3115 new_kmem_state = WARNING; |
|
3116 return WARNING; |
|
3117 } else { |
|
3118 new_kmem_state = ERROR; |
|
3119 lastkmemerrs = alloc_fail; |
|
3120 if (mem_free > threshold_freemem_low) { |
|
3121 /* |
|
3122 * Kernel memory allocation problem. The state is already |
|
3123 * set to ERROR. |
|
3124 */ |
|
3125 } else { |
|
3126 /* |
|
3127 * Kernel memory allocation problem. The state is already |
|
3128 * set to ERROR. |
|
3129 */ |
|
3130 } |
|
3131 return ERROR; |
|
3132 } |
|
3133 } |
|
3134 |
|
3135 case OPEN: |
|
3136 |
|
3137 firstkmemerrs = alloc_fail; |
|
3138 lastkmemerrs = alloc_fail; |
|
3139 strcpy((char *) status, conv_alarm_state(new_kmem_state)); |
|
3140 send_trap(hostName, moduleName, statusOIDContext, trapoid, size, status, description, dvalue, dtype); |
|
3141 return 0; |
|
3142 |
|
3143 case INIT: |
|
3144 |
|
3145 firstkmemerrs = 0; |
|
3146 lastkmemerrs = 0; |
|
3147 return 0; |
|
3148 |
|
3149 case CONTINUE: |
|
3150 |
|
3151 strcpy((char *) status, conv_alarm_state(new_kmem_state)); |
|
3152 if (new_kmem_state > prev_kmem_state) { |
|
3153 |
|
3154 /* Send trap */ |
|
3155 send_trap(hostName, moduleName, statusOIDContext, trapoid, size, status, description, dvalue, dtype); |
|
3156 prev_kmem_state = new_kmem_state; |
|
3157 |
|
3158 } |
|
3159 return 0; |
|
3160 |
|
3161 case CLOSE: |
|
3162 |
|
3163 strcpy((char *) status, conv_alarm_state(new_kmem_state)); |
|
3164 send_trap(hostName, moduleName, statusOIDContext, trapoid, size, status, description, dvalue, dtype); |
|
3165 return 0; |
|
3166 |
|
3167 default: |
|
3168 |
|
3169 return 0; |
|
3170 } |
|
3171 |
|
3172 } |
|
3173 |
|
3174 /* |
|
3175 * Function: DNLC_rule : This function checks the state of DNLC nodes and |
|
3176 * issues trap if necessary |
|
3177 */ |
|
3178 |
|
3179 int |
|
3180 DNLC_rule(int action) |
|
3181 { |
|
3182 |
|
3183 /* This is the OID for hmDNLCStatGroup */ |
|
3184 oid trapoid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 8, 1}; |
|
3185 u_char status[8]; |
|
3186 u_char description[] = "Poor DNLC Hit rate \0"; |
|
3187 int size; |
|
3188 u_char dvalue[15]; |
|
3189 /* dtype is given a value of 1 because hitrate is of "int" type */ |
|
3190 int dtype = 1; |
|
3191 |
|
3192 /* |
|
3193 * It's tricky which "value" should be put in dvalue field. More than one |
|
3194 * node's data is looked at to determine alarm state. |
|
3195 */ |
|
3196 sprintf((char *) dvalue, "%d\0", hitrate); |
|
3197 |
|
3198 size = sizeof(trapoid) / sizeof(oid); |
|
3199 |
|
3200 switch (action) { |
|
3201 |
|
3202 case CONDITION: |
|
3203 |
|
3204 /* |
|
3205 * Changed the rule from existing rule. Used OK instead of INFO when |
|
3206 * there is no problem |
|
3207 */ |
|
3208 |
|
3209 if (refrate < threshold_dnlc_active) { |
|
3210 new_dnlc_state = OK; |
|
3211 return OK; |
|
3212 } else { |
|
3213 if (hitrate > threshold_dnlc_warning) { |
|
3214 new_dnlc_state = OK; |
|
3215 return OK; |
|
3216 } else { |
|
3217 new_dnlc_state = WARNING; |
|
3218 return WARNING; |
|
3219 } |
|
3220 } |
|
3221 |
|
3222 |
|
3223 case OPEN: |
|
3224 |
|
3225 strcpy((char *) status, conv_alarm_state(new_dnlc_state)); |
|
3226 send_trap(hostName, moduleName, statusOIDContext, trapoid, size, status, description, dvalue, dtype); |
|
3227 return 0; |
|
3228 |
|
3229 case INIT: |
|
3230 |
|
3231 return 0; |
|
3232 |
|
3233 case CONTINUE: |
|
3234 |
|
3235 strcpy((char *) status, conv_alarm_state(new_dnlc_state)); |
|
3236 if (new_dnlc_state > prev_dnlc_state) { |
|
3237 |
|
3238 /* Send trap */ |
|
3239 send_trap(hostName, moduleName, statusOIDContext, trapoid, size, status, description, dvalue, dtype); |
|
3240 prev_dnlc_state = new_dnlc_state; |
|
3241 |
|
3242 } |
|
3243 return 0; |
|
3244 |
|
3245 case CLOSE: |
|
3246 |
|
3247 strcpy((char *) status, conv_alarm_state(new_dnlc_state)); |
|
3248 send_trap(hostName, moduleName, statusOIDContext, trapoid, size, status, description, dvalue, dtype); |
|
3249 return 0; |
|
3250 |
|
3251 default: |
|
3252 |
|
3253 return 0; |
|
3254 } |
|
3255 |
|
3256 } |
|
3257 |
|
3258 void |
|
3259 check_state_DISK() |
|
3260 { |
|
3261 |
|
3262 /* TRAP STUFF */ |
|
3263 |
|
3264 oid *trapoid; |
|
3265 u_char status[8]; |
|
3266 u_char description[] = "Disk Loaded \0"; |
|
3267 |
|
3268 /* |
|
3269 * A value of 12 is given to dtype because the diskName is of |
|
3270 * "DisplayString" type. Disk Name is used for dvalue because multiple |
|
3271 * values are used to determine trap state. No single value can be used |
|
3272 */ |
|
3273 |
|
3274 int dtype = 12; |
|
3275 |
|
3276 /* Maintain a pointer to diskTable called headPtr */ |
|
3277 |
|
3278 hmDiskTable *headPtr; |
|
3279 int nameSize; |
|
3280 headPtr = head; |
|
3281 |
|
3282 /* For each row in the table, determine if there is a new Alarm Condition */ |
|
3283 |
|
3284 while (headPtr != NULL) { |
|
3285 |
|
3286 /* For each disk, set the new state back to OK again */ |
|
3287 int new_disk_state = OK; |
|
3288 int i; |
|
3289 |
|
3290 long wait = atol(headPtr->hmAvgWaitTransactions); |
|
3291 long svcTime = atol(headPtr->hmAvgDiskSvcTime); |
|
3292 long busyTime = atol(headPtr->hmDiskBusyPcnt); |
|
3293 |
|
3294 /* For cases where busyTime < disk_busy_warning, svcTime < disk_svc_t_warning, |
|
3295 state is set to OK instead of INFO (as in existing rule); |
|
3296 */ |
|
3297 |
|
3298 if (busyTime < disk_busy_warning) { |
|
3299 new_disk_state = OK; |
|
3300 } else { |
|
3301 if (svcTime < disk_svc_t_warning) { |
|
3302 new_disk_state = OK; |
|
3303 } else { |
|
3304 if (disk_busy_problem <= busyTime) { |
|
3305 if ((disk_svc_t_warning <= svcTime) && (svcTime < disk_svc_t_problem)) { |
|
3306 new_disk_state = WARNING; |
|
3307 } else { |
|
3308 if (disk_svc_t_problem <= svcTime) { |
|
3309 new_disk_state = ERROR; |
|
3310 } |
|
3311 } |
|
3312 } else { |
|
3313 new_disk_state = WARNING; |
|
3314 } |
|
3315 } |
|
3316 |
|
3317 } |
|
3318 |
|
3319 nameSize = strlen(headPtr->hmDiskName); |
|
3320 |
|
3321 /* |
|
3322 * Compose the trap OID here. It is: |
|
3323 * 1.3.6.1.4.1.42.2.12.2.2.11.5.1.1.1.<size-of-index>.index |
|
3324 */ |
|
3325 |
|
3326 trapoid = malloc((16 * sizeof(oid)) + sizeof(oid) + (nameSize * sizeof(oid))); |
|
3327 |
|
3328 if ( trapoid == NULL) { |
|
3329 snmp_log(LOG_DEBUG,"malloc failed when constructing trapoid in health monitor module \n"); |
|
3330 return; |
|
3331 } |
|
3332 |
|
3333 trapoid[0] = 1; |
|
3334 trapoid[1] = 3; |
|
3335 trapoid[2] = 6; |
|
3336 trapoid[3] = 1; |
|
3337 trapoid[4] = 4; |
|
3338 trapoid[5] = 1; |
|
3339 trapoid[6] = 42; |
|
3340 trapoid[7] = 2; |
|
3341 trapoid[8] = 12; |
|
3342 trapoid[9] = 2; |
|
3343 trapoid[10] = 2; |
|
3344 trapoid[11] = 11; |
|
3345 trapoid[12] = 5; |
|
3346 trapoid[13] = 1; |
|
3347 trapoid[14] = 1; |
|
3348 trapoid[15] = 1; |
|
3349 |
|
3350 trapoid[16] = nameSize; |
|
3351 |
|
3352 for (i = 1; i <= nameSize; i++) { |
|
3353 trapoid[16 + i] = headPtr->hmDiskName[i - 1]; |
|
3354 } |
|
3355 |
|
3356 /* Depending on the new state, send trap if necessary */ |
|
3357 |
|
3358 if (new_disk_state > headPtr->hmDiskState) { |
|
3359 |
|
3360 /* Send trap */ |
|
3361 strcpy((char *) status, conv_alarm_state(new_disk_state)); |
|
3362 send_trap(hostName, moduleName, statusOIDContext, trapoid, 17 + nameSize, status, description, (u_char *) headPtr->hmDiskName, dtype); |
|
3363 headPtr->hmDiskState = new_disk_state; |
|
3364 |
|
3365 } else if (new_disk_state == headPtr->hmDiskState) { |
|
3366 |
|
3367 /* No Change in state .. Do nothing */ |
|
3368 |
|
3369 } else if (new_disk_state < headPtr->hmDiskState) { |
|
3370 |
|
3371 if (new_disk_state == OK) { |
|
3372 |
|
3373 /* Send OK trap */ |
|
3374 strcpy((char *) status, conv_alarm_state(new_disk_state)); |
|
3375 send_trap(hostName, moduleName, statusOIDContext, trapoid, 17 + nameSize, status, description, (u_char *) headPtr->hmDiskName, dtype); |
|
3376 headPtr->hmDiskState = OK; |
|
3377 |
|
3378 } |
|
3379 } |
|
3380 |
|
3381 headPtr = headPtr->pNext; |
|
3382 |
|
3383 } /* End of while loop that traverses each row */ |
|
3384 |
|
3385 |
|
3386 return; |
|
3387 |
|
3388 } |