diff options
author | Ton Voon <ton.voon@opsera.com> | 2010-06-17 10:16:43 +0100 |
---|---|---|
committer | tonvoon <ton.voon@opsera.com> | 2010-06-23 13:30:34 +0000 |
commit | 18f6835edaf7d640a2c9e476cb1babdbdadbfd9b (patch) | |
tree | ae11f40e48dc34658445c99012726f32bfb45c56 /plugins/check_snmp.c | |
parent | f61412478ceb7c821793c8356b936f64066508bf (diff) | |
download | monitoring-plugins-18f6835edaf7d640a2c9e476cb1babdbdadbfd9b.tar.gz |
Added state retention APIs. Implemented for check_snmp with --rate option.
See http://nagiosplugin.org/c-api-private for more details on the API.
Also updated check_snmp -l option to change the perfdata label.
Diffstat (limited to 'plugins/check_snmp.c')
-rw-r--r-- | plugins/check_snmp.c | 173 |
1 files changed, 157 insertions, 16 deletions
diff --git a/plugins/check_snmp.c b/plugins/check_snmp.c index 2bc6024f..bf210222 100644 --- a/plugins/check_snmp.c +++ b/plugins/check_snmp.c | |||
@@ -59,6 +59,10 @@ const char *email = "nagiosplug-devel@lists.sourceforge.net"; | |||
59 | 59 | ||
60 | #define MAX_OIDS 8 | 60 | #define MAX_OIDS 8 |
61 | 61 | ||
62 | /* Longopts only arguments */ | ||
63 | #define L_CALCULATE_RATE CHAR_MAX+1 | ||
64 | #define L_RATE_MULTIPLIER CHAR_MAX+2 | ||
65 | |||
62 | /* Gobble to string - stop incrementing c when c[0] match one of the | 66 | /* Gobble to string - stop incrementing c when c[0] match one of the |
63 | * characters in s */ | 67 | * characters in s */ |
64 | #define GOBBLE_TOS(c, s) while(c[0]!='\0' && strchr(s, c[0])==NULL) { c++; } | 68 | #define GOBBLE_TOS(c, s) while(c[0]!='\0' && strchr(s, c[0])==NULL) { c++; } |
@@ -131,12 +135,16 @@ char *delimiter; | |||
131 | char *output_delim; | 135 | char *output_delim; |
132 | char *miblist = NULL; | 136 | char *miblist = NULL; |
133 | int needmibs = FALSE; | 137 | int needmibs = FALSE; |
138 | int calculate_rate = 0; | ||
139 | int rate_multiplier = 1; | ||
140 | state_data *previous_state; | ||
141 | double previous_value[MAX_OIDS]; | ||
134 | 142 | ||
135 | 143 | ||
136 | int | 144 | int |
137 | main (int argc, char **argv) | 145 | main (int argc, char **argv) |
138 | { | 146 | { |
139 | int i, len, line; | 147 | int i, len, line, total_oids; |
140 | unsigned int bk_count = 0, dq_count = 0; | 148 | unsigned int bk_count = 0, dq_count = 0; |
141 | int iresult = STATE_UNKNOWN; | 149 | int iresult = STATE_UNKNOWN; |
142 | int result = STATE_UNKNOWN; | 150 | int result = STATE_UNKNOWN; |
@@ -154,6 +162,17 @@ main (int argc, char **argv) | |||
154 | char *th_crit=NULL; | 162 | char *th_crit=NULL; |
155 | char type[8] = ""; | 163 | char type[8] = ""; |
156 | output chld_out, chld_err; | 164 | output chld_out, chld_err; |
165 | char *previous_string=NULL; | ||
166 | char *ap=NULL; | ||
167 | char *state_string=NULL; | ||
168 | size_t response_length, current_length, string_length; | ||
169 | char *temp_string=NULL; | ||
170 | int is_numeric=0; | ||
171 | time_t current_time; | ||
172 | double temp_double; | ||
173 | time_t duration; | ||
174 | char *conv = "12345678"; | ||
175 | int is_counter=0; | ||
157 | 176 | ||
158 | setlocale (LC_ALL, ""); | 177 | setlocale (LC_ALL, ""); |
159 | bindtextdomain (PACKAGE, LOCALEDIR); | 178 | bindtextdomain (PACKAGE, LOCALEDIR); |
@@ -173,12 +192,33 @@ main (int argc, char **argv) | |||
173 | timeout_interval = DEFAULT_TIMEOUT; | 192 | timeout_interval = DEFAULT_TIMEOUT; |
174 | retries = DEFAULT_RETRIES; | 193 | retries = DEFAULT_RETRIES; |
175 | 194 | ||
195 | np_init( (char *) progname, argc, argv ); | ||
196 | |||
176 | /* Parse extra opts if any */ | 197 | /* Parse extra opts if any */ |
177 | argv=np_extra_opts (&argc, argv, progname); | 198 | argv=np_extra_opts (&argc, argv, progname); |
178 | 199 | ||
200 | np_set_args(argc, argv); | ||
201 | |||
179 | if (process_arguments (argc, argv) == ERROR) | 202 | if (process_arguments (argc, argv) == ERROR) |
180 | usage4 (_("Could not parse arguments")); | 203 | usage4 (_("Could not parse arguments")); |
181 | 204 | ||
205 | if(calculate_rate) { | ||
206 | if (!strcmp(label, "SNMP")) | ||
207 | label = strdup("SNMP RATE"); | ||
208 | time(¤t_time); | ||
209 | i=0; | ||
210 | previous_state = np_state_read(); | ||
211 | if(previous_state!=NULL) { | ||
212 | /* Split colon separated values */ | ||
213 | previous_string = strdup((char *) previous_state->data); | ||
214 | while((ap = strsep(&previous_string, ":")) != NULL) { | ||
215 | if(verbose>2) | ||
216 | printf("State for %d=%s\n", i, ap); | ||
217 | previous_value[i++]=strtod(ap,NULL); | ||
218 | } | ||
219 | } | ||
220 | } | ||
221 | |||
182 | /* Populate the thresholds */ | 222 | /* Populate the thresholds */ |
183 | th_warn=warning_thresholds; | 223 | th_warn=warning_thresholds; |
184 | th_crit=critical_thresholds; | 224 | th_crit=critical_thresholds; |
@@ -271,7 +311,10 @@ main (int argc, char **argv) | |||
271 | } | 311 | } |
272 | 312 | ||
273 | for (line=0, i=0; line < chld_out.lines; line++, i++) { | 313 | for (line=0, i=0; line < chld_out.lines; line++, i++) { |
274 | const char *conv = "%.0f"; | 314 | if(calculate_rate) |
315 | conv = "%.10g"; | ||
316 | else | ||
317 | conv = "%.0f"; | ||
275 | 318 | ||
276 | ptr = chld_out.line[line]; | 319 | ptr = chld_out.line[line]; |
277 | oidname = strpcpy (oidname, ptr, delimiter); | 320 | oidname = strpcpy (oidname, ptr, delimiter); |
@@ -286,21 +329,34 @@ main (int argc, char **argv) | |||
286 | /* Clean up type array - Sol10 does not necessarily zero it out */ | 329 | /* Clean up type array - Sol10 does not necessarily zero it out */ |
287 | bzero(type, sizeof(type)); | 330 | bzero(type, sizeof(type)); |
288 | 331 | ||
332 | is_counter=0; | ||
289 | /* We strip out the datatype indicator for PHBs */ | 333 | /* We strip out the datatype indicator for PHBs */ |
290 | if (strstr (response, "Gauge: ")) | 334 | if (strstr (response, "Gauge: ")) { |
291 | show = strstr (response, "Gauge: ") + 7; | 335 | show = strstr (response, "Gauge: ") + 7; |
292 | else if (strstr (response, "Gauge32: ")) | 336 | is_numeric++; |
337 | } | ||
338 | else if (strstr (response, "Gauge32: ")) { | ||
293 | show = strstr (response, "Gauge32: ") + 9; | 339 | show = strstr (response, "Gauge32: ") + 9; |
340 | is_numeric++; | ||
341 | } | ||
294 | else if (strstr (response, "Counter32: ")) { | 342 | else if (strstr (response, "Counter32: ")) { |
295 | show = strstr (response, "Counter32: ") + 11; | 343 | show = strstr (response, "Counter32: ") + 11; |
296 | strcpy(type, "c"); | 344 | is_numeric++; |
345 | is_counter=1; | ||
346 | if(!calculate_rate) | ||
347 | strcpy(type, "c"); | ||
297 | } | 348 | } |
298 | else if (strstr (response, "Counter64: ")) { | 349 | else if (strstr (response, "Counter64: ")) { |
299 | show = strstr (response, "Counter64: ") + 11; | 350 | show = strstr (response, "Counter64: ") + 11; |
300 | strcpy(type, "c"); | 351 | is_numeric++; |
352 | is_counter=1; | ||
353 | if(!calculate_rate) | ||
354 | strcpy(type, "c"); | ||
301 | } | 355 | } |
302 | else if (strstr (response, "INTEGER: ")) | 356 | else if (strstr (response, "INTEGER: ")) { |
303 | show = strstr (response, "INTEGER: ") + 9; | 357 | show = strstr (response, "INTEGER: ") + 9; |
358 | is_numeric++; | ||
359 | } | ||
304 | else if (strstr (response, "STRING: ")) { | 360 | else if (strstr (response, "STRING: ")) { |
305 | show = strstr (response, "STRING: ") + 8; | 361 | show = strstr (response, "STRING: ") + 8; |
306 | conv = "%.10g"; | 362 | conv = "%.10g"; |
@@ -345,14 +401,33 @@ main (int argc, char **argv) | |||
345 | 401 | ||
346 | iresult = STATE_DEPENDENT; | 402 | iresult = STATE_DEPENDENT; |
347 | 403 | ||
348 | /* Process this block for integer comparisons */ | 404 | /* Process this block for numeric comparisons */ |
349 | if (thlds[i]->warning || thlds[i]->critical) { | 405 | if (is_numeric) { |
350 | ptr = strpbrk (show, "0123456789"); | 406 | ptr = strpbrk (show, "0123456789"); |
351 | if (ptr == NULL) | 407 | if (ptr == NULL) |
352 | die (STATE_UNKNOWN,_("No valid data returned")); | 408 | die (STATE_UNKNOWN,_("No valid data returned")); |
353 | response_value[i] = strtod (ptr, NULL); | 409 | response_value[i] = strtod (ptr, NULL); |
354 | iresult = get_status(response_value[i], thlds[i]); | 410 | |
355 | asprintf (&show, conv, response_value[i]); | 411 | if(calculate_rate) { |
412 | if (previous_state!=NULL) { | ||
413 | duration = current_time-previous_state->time; | ||
414 | if(duration<=0) | ||
415 | die(STATE_UNKNOWN,_("Time duration between plugin calls is invalid")); | ||
416 | temp_double = (response_value[i]-previous_value[i])/duration; | ||
417 | /* Simple overflow catcher (same as in rrdtool, rrd_update.c) */ | ||
418 | if(is_counter) { | ||
419 | if(temp_double<(double)0.0) | ||
420 | temp_double+=(double)4294967296.0; /* 2^32 */ | ||
421 | if(temp_double<(double)0.0) | ||
422 | temp_double+=(double)18446744069414584320.0; /* 2^64-2^32 */; | ||
423 | } | ||
424 | iresult = get_status(temp_double, thlds[i]); | ||
425 | asprintf (&show, conv, temp_double); | ||
426 | } | ||
427 | } else { | ||
428 | iresult = get_status(response_value[i], thlds[i]); | ||
429 | asprintf (&show, conv, response_value[i]); | ||
430 | } | ||
356 | } | 431 | } |
357 | 432 | ||
358 | /* Process this block for string matching */ | 433 | /* Process this block for string matching */ |
@@ -380,6 +455,7 @@ main (int argc, char **argv) | |||
380 | } | 455 | } |
381 | 456 | ||
382 | /* Process this block for existence-nonexistence checks */ | 457 | /* Process this block for existence-nonexistence checks */ |
458 | /* TV: Should this be outside of this else block? */ | ||
383 | else { | 459 | else { |
384 | if (eval_method[i] & CRIT_PRESENT) | 460 | if (eval_method[i] & CRIT_PRESENT) |
385 | iresult = STATE_CRITICAL; | 461 | iresult = STATE_CRITICAL; |
@@ -393,7 +469,7 @@ main (int argc, char **argv) | |||
393 | result = max_state (result, iresult); | 469 | result = max_state (result, iresult); |
394 | 470 | ||
395 | /* Prepend a label for this OID if there is one */ | 471 | /* Prepend a label for this OID if there is one */ |
396 | if (nlabels > (size_t)1 && (size_t)i < nlabels && labels[i] != NULL) | 472 | if (nlabels >= (size_t)1 && (size_t)i < nlabels && labels[i] != NULL) |
397 | asprintf (&outbuff, "%s%s%s %s%s%s", outbuff, | 473 | asprintf (&outbuff, "%s%s%s %s%s%s", outbuff, |
398 | (i == 0) ? " " : output_delim, | 474 | (i == 0) ? " " : output_delim, |
399 | labels[i], mark (iresult), show, mark (iresult)); | 475 | labels[i], mark (iresult), show, mark (iresult)); |
@@ -409,7 +485,13 @@ main (int argc, char **argv) | |||
409 | ptr = NULL; | 485 | ptr = NULL; |
410 | strtod(show, &ptr); | 486 | strtod(show, &ptr); |
411 | if (ptr > show) { | 487 | if (ptr > show) { |
412 | strncat(perfstr, oidname, sizeof(perfstr)-strlen(perfstr)-1); | 488 | if (nlabels >= (size_t)1 && (size_t)i < nlabels && labels[i] != NULL) |
489 | temp_string=labels[i]; | ||
490 | else | ||
491 | temp_string=oidname; | ||
492 | if(calculate_rate) | ||
493 | asprintf(&temp_string,"%s-rate",temp_string); | ||
494 | strncat(perfstr, temp_string, sizeof(perfstr)-strlen(perfstr)-1); | ||
413 | strncat(perfstr, "=", sizeof(perfstr)-strlen(perfstr)-1); | 495 | strncat(perfstr, "=", sizeof(perfstr)-strlen(perfstr)-1); |
414 | len = sizeof(perfstr)-strlen(perfstr)-1; | 496 | len = sizeof(perfstr)-strlen(perfstr)-1; |
415 | strncat(perfstr, show, len>ptr-show ? ptr-show : len); | 497 | strncat(perfstr, show, len>ptr-show ? ptr-show : len); |
@@ -419,6 +501,44 @@ main (int argc, char **argv) | |||
419 | strncat(perfstr, " ", sizeof(perfstr)-strlen(perfstr)-1); | 501 | strncat(perfstr, " ", sizeof(perfstr)-strlen(perfstr)-1); |
420 | } | 502 | } |
421 | } | 503 | } |
504 | total_oids=i; | ||
505 | |||
506 | /* Save state data, as all data collected now */ | ||
507 | if(calculate_rate) { | ||
508 | string_length=1024; | ||
509 | state_string=malloc(string_length); | ||
510 | if(state_string==NULL) | ||
511 | die(STATE_UNKNOWN, _("Cannot malloc")); | ||
512 | |||
513 | current_length=0; | ||
514 | for(i=0; i<total_oids; i++) { | ||
515 | asprintf(&temp_string,"%.0f",response_value[i]); | ||
516 | if(temp_string==NULL) | ||
517 | die(STATE_UNKNOWN,_("Cannot asprintf()")); | ||
518 | response_length = strlen(temp_string); | ||
519 | if(current_length+response_length>string_length) { | ||
520 | string_length=current_length+1024; | ||
521 | state_string=realloc(state_string,string_length); | ||
522 | if(state_string==NULL) | ||
523 | die(STATE_UNKNOWN, _("Cannot realloc()")); | ||
524 | } | ||
525 | strcpy(&state_string[current_length],temp_string); | ||
526 | current_length=current_length+response_length; | ||
527 | state_string[current_length]=':'; | ||
528 | current_length++; | ||
529 | free(temp_string); | ||
530 | } | ||
531 | state_string[--current_length]='\0'; | ||
532 | if (verbose > 2) | ||
533 | printf("State string=%s\n",state_string); | ||
534 | |||
535 | /* This is not strictly the same as time now, but any subtle variations will cancel out */ | ||
536 | np_state_write_string(current_time, state_string ); | ||
537 | if(previous_state==NULL) { | ||
538 | /* Or should this be highest state? */ | ||
539 | die( STATE_OK, _("No previous data to calculate rate - assume okay" ) ); | ||
540 | } | ||
541 | } | ||
422 | 542 | ||
423 | printf ("%s %s -%s %s\n", label, state_text (result), outbuff, perfstr); | 543 | printf ("%s %s -%s %s\n", label, state_text (result), outbuff, perfstr); |
424 | if (mult_resp) printf ("%s", mult_resp); | 544 | if (mult_resp) printf ("%s", mult_resp); |
@@ -462,6 +582,8 @@ process_arguments (int argc, char **argv) | |||
462 | {"authpasswd", required_argument, 0, 'A'}, | 582 | {"authpasswd", required_argument, 0, 'A'}, |
463 | {"privpasswd", required_argument, 0, 'X'}, | 583 | {"privpasswd", required_argument, 0, 'X'}, |
464 | {"next", no_argument, 0, 'n'}, | 584 | {"next", no_argument, 0, 'n'}, |
585 | {"rate", no_argument, 0, L_CALCULATE_RATE}, | ||
586 | {"rate-multiplier", required_argument, 0, L_RATE_MULTIPLIER}, | ||
465 | {0, 0, 0, 0} | 587 | {0, 0, 0, 0} |
466 | }; | 588 | }; |
467 | 589 | ||
@@ -609,7 +731,6 @@ process_arguments (int argc, char **argv) | |||
609 | output_delim = strscpy (output_delim, optarg); | 731 | output_delim = strscpy (output_delim, optarg); |
610 | break; | 732 | break; |
611 | case 'l': /* label */ | 733 | case 'l': /* label */ |
612 | label = optarg; | ||
613 | nlabels++; | 734 | nlabels++; |
614 | if (nlabels >= labels_size) { | 735 | if (nlabels >= labels_size) { |
615 | labels_size += 8; | 736 | labels_size += 8; |
@@ -666,7 +787,15 @@ process_arguments (int argc, char **argv) | |||
666 | unitv[nunits - 1] = ptr; | 787 | unitv[nunits - 1] = ptr; |
667 | } | 788 | } |
668 | break; | 789 | break; |
669 | 790 | case L_CALCULATE_RATE: | |
791 | if(calculate_rate==0) | ||
792 | np_enable_state(NULL, 1); | ||
793 | calculate_rate = 1; | ||
794 | break; | ||
795 | case L_RATE_MULTIPLIER: | ||
796 | if(!is_integer(optarg)||(rate_multiplier=atoi(optarg)<=0)) | ||
797 | usage2(_("Rate multiplier must be a positive integer"),optarg); | ||
798 | break; | ||
670 | } | 799 | } |
671 | } | 800 | } |
672 | 801 | ||
@@ -905,6 +1034,8 @@ print_help (void) | |||
905 | printf (" %s\n", _("Warning threshold range(s)")); | 1034 | printf (" %s\n", _("Warning threshold range(s)")); |
906 | printf (" %s\n", "-c, --critical=THRESHOLD(s)"); | 1035 | printf (" %s\n", "-c, --critical=THRESHOLD(s)"); |
907 | printf (" %s\n", _("Critical threshold range(s)")); | 1036 | printf (" %s\n", _("Critical threshold range(s)")); |
1037 | printf (" %s\n", "--rate"); | ||
1038 | printf (" %s\n", _("Enable rate calculation. See 'Rate Calculation' below")); | ||
908 | 1039 | ||
909 | /* Tests Against Strings */ | 1040 | /* Tests Against Strings */ |
910 | printf (" %s\n", "-s, --string=STRING"); | 1041 | printf (" %s\n", "-s, --string=STRING"); |
@@ -914,7 +1045,7 @@ print_help (void) | |||
914 | printf (" %s\n", "-R, --eregi=REGEX"); | 1045 | printf (" %s\n", "-R, --eregi=REGEX"); |
915 | printf (" %s\n", _("Return OK state (for that OID) if case-insensitive extended REGEX matches")); | 1046 | printf (" %s\n", _("Return OK state (for that OID) if case-insensitive extended REGEX matches")); |
916 | printf (" %s\n", "-l, --label=STRING"); | 1047 | printf (" %s\n", "-l, --label=STRING"); |
917 | printf (" %s\n", _("Prefix label for output from plugin (default -s 'SNMP')")); | 1048 | printf (" %s\n", _("Prefix label for output from plugin (default -l 'SNMP')")); |
918 | 1049 | ||
919 | /* Output Formatting */ | 1050 | /* Output Formatting */ |
920 | printf (" %s\n", "-u, --units=STRING"); | 1051 | printf (" %s\n", "-u, --units=STRING"); |
@@ -945,6 +1076,16 @@ print_help (void) | |||
945 | printf (" %s\n", _("- All evaluation methods other than PR, STR, and SUBSTR expect that the value")); | 1076 | printf (" %s\n", _("- All evaluation methods other than PR, STR, and SUBSTR expect that the value")); |
946 | printf (" %s\n", _("returned from the SNMP query is an unsigned integer.")); | 1077 | printf (" %s\n", _("returned from the SNMP query is an unsigned integer.")); |
947 | 1078 | ||
1079 | printf("\n"); | ||
1080 | printf("%s\n", _("Rate Calculation:")); | ||
1081 | printf(" %s\n", _("In many places, SNMP returns counters that are only meaningful when")); | ||
1082 | printf(" %s\n", _("calculating the counter difference since the last check. check_snmp")); | ||
1083 | printf(" %s\n", _("saves the last state information in a file so that the rate can be")); | ||
1084 | printf(" %s\n", _("calculated. Use the --rate option to save state information. On the")); | ||
1085 | printf(" %s\n", _("first run, there will be no prior state - this will return with OK.")); | ||
1086 | printf(" %s\n", _("The state is uniquely determined by the arguments to the plugin, so")); | ||
1087 | printf(" %s\n", _("changing the arguments will create a new state file.")); | ||
1088 | |||
948 | printf (UT_SUPPORT); | 1089 | printf (UT_SUPPORT); |
949 | } | 1090 | } |
950 | 1091 | ||