[Nagiosplug-checkins] SF.net SVN: nagiosplug:[2203] nagiosplug/trunk

dermoth at users.sourceforge.net dermoth at users.sourceforge.net
Thu May 28 14:13:18 CEST 2009


Revision: 2203
          http://nagiosplug.svn.sourceforge.net/nagiosplug/?rev=2203&view=rev
Author:   dermoth
Date:     2009-05-28 12:13:17 +0000 (Thu, 28 May 2009)

Log Message:
-----------
check_snmp: Make use of standard threshold functions

	This patch makes use of standard threshold functions. This allows using
	doubles as thresholds.

	Since SNMP supports only integers, double precision numbers are only
	printed when parsed from a STRING type.

	In addition, support for printing properly Timeticks type has been added,
	and the code has been thoroughly cleaned.

From: Thomas Guyot-Sionnest <dermoth at aei.ca>

Modified Paths:
--------------
    nagiosplug/trunk/NEWS
    nagiosplug/trunk/lib/utils_base.h
    nagiosplug/trunk/plugins/check_snmp.c
    nagiosplug/trunk/plugins/t/check_snmp.t

Modified: nagiosplug/trunk/NEWS
===================================================================
--- nagiosplug/trunk/NEWS	2009-05-27 05:40:16 UTC (rev 2202)
+++ nagiosplug/trunk/NEWS	2009-05-28 12:13:17 UTC (rev 2203)
@@ -37,6 +37,7 @@
 	check_http: Add SSL/TLS hostname extension support (SNI) - (#1939022 - Joe Presbrey)
 	Fixed wrong perfdata label for output traffic in check_mrtgtraf (#2654308 - Gavin Williams)
 	Fixed check_by_ssh interpretation of quotes in -C parameter (#1985246, #2268675)
+	check_snmp now supports standard threshold ranges and doubles (floating numbers) in thresholds
 
 1.4.13 25th Sept 2008
 	Fix Debian bug #460097: check_http --max-age broken (Hilko Bengen)

Modified: nagiosplug/trunk/lib/utils_base.h
===================================================================
--- nagiosplug/trunk/lib/utils_base.h	2009-05-27 05:40:16 UTC (rev 2202)
+++ nagiosplug/trunk/lib/utils_base.h	2009-05-28 12:13:17 UTC (rev 2203)
@@ -35,6 +35,9 @@
 int check_range(double, range *);
 int get_status(double, thresholds *);
 
+/* All possible characters in a threshold range */
+#define NP_THRESHOLDS_CHARS "0123456789.:@~"
+
 char *np_escaped_string (const char *);
 
 void die (int, const char *, ...) __attribute__((noreturn,format(printf, 2, 3)));

Modified: nagiosplug/trunk/plugins/check_snmp.c
===================================================================
--- nagiosplug/trunk/plugins/check_snmp.c	2009-05-27 05:40:16 UTC (rev 2202)
+++ nagiosplug/trunk/plugins/check_snmp.c	2009-05-28 12:13:17 UTC (rev 2203)
@@ -53,33 +53,14 @@
 #define CRIT_PRESENT 1
 #define CRIT_STRING 2
 #define CRIT_REGEX 4
-#define CRIT_GT 8
-#define CRIT_LT 16
-#define CRIT_GE 32
-#define CRIT_LE 64
-#define CRIT_EQ 128
-#define CRIT_NE 256
-#define CRIT_RANGE 512
-#define WARN_PRESENT 1024
-#define WARN_STRING 2048
-#define WARN_REGEX 4096
-#define WARN_GT 8192
-#define WARN_LT 16384
-#define WARN_GE 32768
-#define WARN_LE 65536
-#define WARN_EQ 131072
-#define WARN_NE 262144
-#define WARN_RANGE 524288
+#define WARN_PRESENT 8
+#define WARN_STRING 16
+#define WARN_REGEX 32
 
 #define MAX_OIDS 8
-#define MAX_DELIM_LENGTH 8
 
 int process_arguments (int, char **);
 int validate_arguments (void);
-char *clarify_message (char *);
-int check_num (int);
-int llu_getll (unsigned long long *, char *);
-int llu_getul (unsigned long long *, char *);
 char *thisarg (char *str);
 char *nextarg (char *str);
 void print_usage (void);
@@ -89,7 +70,6 @@
 char regex_expect[MAX_INPUT_BUFFER] = "";
 regex_t preg;
 regmatch_t pmatch[10];
-char timestamp[10] = "";
 char errbuf[MAX_INPUT_BUFFER] = "";
 char perfstr[MAX_INPUT_BUFFER] = "| ";
 int cflags = REG_EXTENDED | REG_NOSUB | REG_NEWLINE;
@@ -122,15 +102,12 @@
 int numauthpriv = 0;
 int verbose = FALSE;
 int usesnmpgetnext = FALSE;
-unsigned long long lower_warn_lim[MAX_OIDS];
-unsigned long long upper_warn_lim[MAX_OIDS];
-unsigned long long lower_crit_lim[MAX_OIDS];
-unsigned long long upper_crit_lim[MAX_OIDS];
-unsigned long long response_value[MAX_OIDS];
-int check_warning_value = FALSE;
-int check_critical_value = FALSE;
+char *warning_thresholds = NULL;
+char *critical_thresholds = NULL;
+thresholds *thlds[MAX_OIDS];
+double response_value[MAX_OIDS];
 int retries = 0;
-unsigned long long eval_method[MAX_OIDS];
+int eval_method[MAX_OIDS];
 char *delimiter;
 char *output_delim;
 char *miblist = NULL;
@@ -140,7 +117,7 @@
 int
 main (int argc, char **argv)
 {
-	int i = 0;
+	int i;
 	int iresult = STATE_UNKNOWN;
 	int result = STATE_UNKNOWN;
 	int return_code = 0;
@@ -152,6 +129,8 @@
 	char *outbuff;
 	char *ptr = NULL;
 	char *show = NULL;
+	char *th_warn=NULL;
+	char *th_crit=NULL;
 	char type[8] = "";
 	output chld_out, chld_err;
 
@@ -163,7 +142,6 @@
 	unitv = malloc (unitv_size);
 	for (i = 0; i < MAX_OIDS; i++)
 		eval_method[i] = CHECK_UNDEF;
-	i = 0;
 
 	label = strdup ("SNMP");
 	units = strdup ("");
@@ -171,7 +149,6 @@
 	outbuff = strdup ("");
 	delimiter = strdup (" = ");
 	output_delim = strdup (DEFAULT_OUTPUT_DELIMITER);
-	/* miblist = strdup (DEFAULT_MIBLIST); */
 	timeout_interval = DEFAULT_TIMEOUT;
 	retries = DEFAULT_RETRIES;
 
@@ -181,6 +158,28 @@
 	if (process_arguments (argc, argv) == ERROR)
 		usage4 (_("Could not parse arguments"));
 
+	/* Populate the thresholds */
+	th_warn=warning_thresholds;
+	th_crit=critical_thresholds;
+	for (i=0; i<numoids; i++) {
+		char *w = th_warn ? strndup(th_warn, strcspn(th_warn, ",")) : NULL;
+		char *c = th_crit ? strndup(th_crit, strcspn(th_crit, ",")) : NULL;
+		/* Skip empty thresholds, while avoiding segfault */
+		set_thresholds(&thlds[i],
+		               w ? strpbrk(w, NP_THRESHOLDS_CHARS) : NULL,
+		               c ? strpbrk(c, NP_THRESHOLDS_CHARS) : NULL);
+		if (w) {
+			th_warn=strchr(th_warn, ',');
+			if (th_warn) th_warn++;
+			free(w);
+		}
+		if (c) {
+			th_crit=strchr(th_crit, ',');
+			if (th_crit) th_crit++;
+			free(c);
+		}
+	}
+
 	/* Create the command array to execute */
 	if(usesnmpgetnext == TRUE) {
 		snmpcmd = strdup (PATH_TO_SNMPGETNEXT);
@@ -251,6 +250,8 @@
 	}
 
 	for (i = 0; i < chld_out.lines; i++) {
+		const char *conv = "%.0f";
+
 		ptr = chld_out.line[i];
 		oidname = strpcpy (oidname, ptr, delimiter);
 		response = strstr (ptr, delimiter);
@@ -274,32 +275,25 @@
 		}
 		else if (strstr (response, "INTEGER: "))
 			show = strstr (response, "INTEGER: ") + 9;
-		else if (strstr (response, "STRING: "))
+		else if (strstr (response, "STRING: ")) {
 			show = strstr (response, "STRING: ") + 8;
+			conv = "%.10g";
+		}
+		else if (strstr (response, "Timeticks: "))
+			show = strstr (response, "Timeticks: ");
 		else
 			show = response;
 
 		iresult = STATE_DEPENDENT;
 
 		/* Process this block for integer comparisons */
-		if (eval_method[i] & CRIT_GT ||
-		    eval_method[i] & CRIT_LT ||
-		    eval_method[i] & CRIT_GE ||
-		    eval_method[i] & CRIT_LE ||
-		    eval_method[i] & CRIT_EQ ||
-		    eval_method[i] & CRIT_NE ||
-		    eval_method[i] & WARN_GT ||
-		    eval_method[i] & WARN_LT ||
-		    eval_method[i] & WARN_GE ||
-		    eval_method[i] & WARN_LE ||
-		    eval_method[i] & WARN_EQ ||
-		    eval_method[i] & WARN_NE) {
+		if (thlds[i]->warning || thlds[i]->critical) {
 			ptr = strpbrk (show, "0123456789");
 			if (ptr == NULL)
 				die (STATE_UNKNOWN,_("No valid data returned"));
-			response_value[i] = strtoul (ptr, NULL, 10);
-			iresult = check_num (i);
-			asprintf (&show, "%llu", response_value[i]);
+			response_value[i] = strtod (ptr, NULL);
+			iresult = get_status(response_value[i], thlds[i]);
+			asprintf (&show, conv, response_value[i]);
 		}
 
 		/* Process this block for string matching */
@@ -363,9 +357,6 @@
 		}
 	}
 
-/* 	if (nunits == 1 || i == 1) */
-/* 		printf ("%s %s -%s %s\n", label, state_text (result), outbuff, units); */
-/* 	else */
 	printf ("%s %s -%s %s \n", label, state_text (result), outbuff, perfstr);
 
 	return result;
@@ -488,27 +479,11 @@
 			break;
 
 	/* Test parameters */
-		case 'c':									/* critical time threshold */
-			if (strspn (optarg, "0123456789:,") < strlen (optarg))
-				usage2 (_("Invalid critical threshold"), optarg);
-			for (ptr = optarg; ptr && jj < MAX_OIDS; jj++) {
-				if (llu_getll (&lower_crit_lim[jj], ptr) == 1)
-					eval_method[jj] |= CRIT_LT;
-				if (llu_getul (&upper_crit_lim[jj], ptr) == 1)
-					eval_method[jj] |= CRIT_GT;
-				(ptr = index (ptr, ',')) ? ptr++ : ptr;
-			}
+		case 'c':									/* critical threshold */
+			critical_thresholds = optarg;
 			break;
-		case 'w':									/* warning time threshold */
-			if (strspn (optarg, "0123456789:,") < strlen (optarg))
-				usage2 (_("Invalid warning threshold"), optarg);
-			for (ptr = optarg; ptr && ii < MAX_OIDS; ii++) {
-				if (llu_getll (&lower_warn_lim[ii], ptr) == 1)
-					eval_method[ii] |= WARN_LT;
-				if (llu_getul (&upper_warn_lim[ii], ptr) == 1)
-					eval_method[ii] |= WARN_GT;
-				(ptr = index (ptr, ',')) ? ptr++ : ptr;
-			}
+		case 'w':									/* warning threshold */
+			warning_thresholds = optarg;
 			break;
 		case 'e': /* PRELIMINARY - may change */
 		case 'E': /* PRELIMINARY - may change */
@@ -758,117 +733,6 @@
 
 
 
-char *
-clarify_message (char *msg)
-{
-	int i = 0;
-	int foo;
-	char tmpmsg_c[MAX_INPUT_BUFFER];
-	char *tmpmsg = (char *) &tmpmsg_c;
-	tmpmsg = strcpy (tmpmsg, msg);
-	if (!strncmp (tmpmsg, " Hex:", 5)) {
-		tmpmsg = strtok (tmpmsg, ":");
-		while ((tmpmsg = strtok (NULL, " "))) {
-			foo = strtol (tmpmsg, NULL, 16);
-			/* Translate chars that are not the same value in the printers
-			 * character set.
-			 */
-			switch (foo) {
-			case 208:
-				{
-					foo = 197;
-					break;
-				}
-			case 216:
-				{
-					foo = 196;
-					break;
-				}
-			}
-			msg[i] = foo;
-			i++;
-		}
-		msg[i] = 0;
-	}
-	return (msg);
-}
-
-
-
-int
-check_num (int i)
-{
-	int result;
-	result = STATE_OK;
-	if (eval_method[i] & WARN_GT && eval_method[i] & WARN_LT &&
-			lower_warn_lim[i] > upper_warn_lim[i]) {
-		if (response_value[i] <= lower_warn_lim[i] &&
-				response_value[i] >= upper_warn_lim[i]) {
-			result = STATE_WARNING;
-		}
-	}
-	else if
-		((eval_method[i] & WARN_GT && response_value[i] > upper_warn_lim[i]) ||
-		 (eval_method[i] & WARN_GE && response_value[i] >= upper_warn_lim[i]) ||
-		 (eval_method[i] & WARN_LT && response_value[i] < lower_warn_lim[i]) ||
-		 (eval_method[i] & WARN_LE && response_value[i] <= lower_warn_lim[i]) ||
-		 (eval_method[i] & WARN_EQ && response_value[i] == upper_warn_lim[i]) ||
-		 (eval_method[i] & WARN_NE && response_value[i] != upper_warn_lim[i])) {
-		result = STATE_WARNING;
-	}
-
-	if (eval_method[i] & CRIT_GT && eval_method[i] & CRIT_LT &&
-			lower_crit_lim[i] > upper_crit_lim[i]) {
-		if (response_value[i] <= lower_crit_lim[i] &&
-				response_value[i] >= upper_crit_lim[i]) {
-			result = STATE_CRITICAL;
-		}
-	}
-	else if
-		((eval_method[i] & CRIT_GT && response_value[i] > upper_crit_lim[i]) ||
-		 (eval_method[i] & CRIT_GE && response_value[i] >= upper_crit_lim[i]) ||
-		 (eval_method[i] & CRIT_LT && response_value[i] < lower_crit_lim[i]) ||
-		 (eval_method[i] & CRIT_LE && response_value[i] <= lower_crit_lim[i]) ||
-		 (eval_method[i] & CRIT_EQ && response_value[i] == upper_crit_lim[i]) ||
-		 (eval_method[i] & CRIT_NE && response_value[i] != upper_crit_lim[i])) {
-		result = STATE_CRITICAL;
-	}
-
-	return result;
-}
-
-
-
-int
-llu_getll (unsigned long long *ll, char *str)
-{
-	char tmp[100];
-	if (strchr (str, ':') == NULL)
-		return 0;
-	if (strchr (str, ',') != NULL && (strchr (str, ',') < strchr (str, ':')))
-		return 0;
-	if (sscanf (str, "%llu%[:]", ll, tmp) == 2)
-		return 1;
-	return 0;
-}
-
-
-
-int
-llu_getul (unsigned long long *ul, char *str)
-{
-	char tmp[100];
-	if (sscanf (str, "%llu%[^,]", ul, tmp) == 1)
-		return 1;
-	if (sscanf (str, ":%llu%[^,]", ul, tmp) == 1)
-		return 1;
-	if (sscanf (str, "%*u:%llu%[^,]", ul, tmp) == 1)
-		return 1;
-	return 0;
-}
-
-
-
 /* trim leading whitespace
 	 if there is a leading quote, make sure it balances */
 
@@ -973,10 +837,10 @@
 	printf ("    %s\n", _("to be the data that should be used in the evaluation."));
 
 	/* Tests Against Integers */
-	printf (" %s\n", "-w, --warning=INTEGER_RANGE(s)");
-	printf ("    %s\n", _("Range(s) which will not result in a WARNING status"));
-	printf (" %s\n", "-c, --critical=INTEGER_RANGE(s)");
-	printf ("    %s\n", _("Range(s) which will not result in a CRITICAL status"));
+	printf (" %s\n", "-w, --warning=THRESHOLD(s)");
+	printf ("    %s\n", _("Warning threshold range(s)"));
+	printf (" %s\n", "-c, --critical=THRESHOLD(s)");
+	printf ("    %s\n", _("Critical threshold range(s)"));
 
 	/* Tests Against Strings */
 	printf (" %s\n", "-s, --string=STRING");
@@ -1010,16 +874,8 @@
 	printf (" %s\n", _("- Multiple OIDs may be indicated by a comma- or space-delimited list (lists with"));
 	printf ("   %s\n", _("internal spaces must be quoted) [max 8 OIDs]"));
 
-	printf (" %s\n", _("- Ranges are inclusive and are indicated with colons. When specified as"));
-	printf ("   %s\n", _("'min:max' a STATE_OK will be returned if the result is within the indicated"));
-	printf ("   %s\n", _("range or is equal to the upper or lower bound. A non-OK state will be"));
-	printf ("   %s\n", _("returned if the result is outside the specified range."));
+	printf(" -%s", _(UT_THRESHOLDS_NOTES));
 
-	printf (" %s\n", _("- If specified in the order 'max:min' a non-OK state will be returned if the"));
-	printf ("   %s\n", _("result is within the (inclusive) range."));
-
-	printf (" %s\n", _("- Upper or lower bounds may be omitted to skip checking the respective limit."));
-	printf (" %s\n", _("- Bare integers are interpreted as upper limits."));
 	printf (" %s\n", _("- When checking multiple OIDs, separate ranges by commas like '-w 1:10,1:,:20'"));
 	printf (" %s\n", _("- Note that only one string and one regex may be checked at present"));
 	printf (" %s\n", _("- All evaluation methods other than PR, STR, and SUBSTR expect that the value"));

Modified: nagiosplug/trunk/plugins/t/check_snmp.t
===================================================================
--- nagiosplug/trunk/plugins/t/check_snmp.t	2009-05-27 05:40:16 UTC (rev 2202)
+++ nagiosplug/trunk/plugins/t/check_snmp.t	2009-05-28 12:13:17 UTC (rev 2203)
@@ -8,7 +8,7 @@
 use Test::More;
 use NPTest;
 
-my $tests = 34;
+my $tests = 44;
 plan tests => $tests;
 my $res;
 
@@ -44,7 +44,7 @@
 	like( $res->output, "/check_snmp: Invalid SNMP version - 3c/" );
 
 	SKIP: {
-		skip "no snmp host defined", 20 if ( ! $host_snmp );
+		skip "no snmp host defined", 30 if ( ! $host_snmp );
 
 		$res = NPTest->testCmd( "./check_snmp -H $host_snmp -C $snmp_community -o system.sysUpTime.0 -w 1: -c 1:");
 		cmp_ok( $res->return_code, '==', 0, "Exit OK when querying uptime" ); 
@@ -85,6 +85,33 @@
 		$res = NPTest->testCmd( "./check_snmp -H $host_snmp -C $snmp_community -o host.hrStorage.hrMemorySize.0,host.hrSystem.hrSystemProcesses.0 -w 1:,1: -c 1:,1:");
 		cmp_ok( $res->return_code, '==', 0, "Exit OK when querying hrMemorySize and hrSystemProcesses");
 		like($res->output, '/^SNMP OK - \d+ \d+/', "String contains hrMemorySize and hrSystemProcesses");
+
+		$res = NPTest->testCmd( "./check_snmp -H $host_snmp -C $snmp_community -o host.hrSWRun.hrSWRunTable.hrSWRunEntry.hrSWRunIndex.1 -w \@:0 -c \@0");
+		cmp_ok( $res->return_code, '==', 0, "Exit OK with inside-range thresholds");
+		like($res->output, '/^SNMP OK - 1\s.*$/', "String matches SNMP OK and output format");
+
+		$res = NPTest->testCmd( "./check_snmp -H $host_snmp -C $snmp_community -o enterprises.ucdavis.laTable.laEntry.laLoad.3");
+		$res->output =~ m/^SNMP OK - (\d+\.\d{2})\s.*$/;
+		my $lower = $1 - 0.05;
+		my $higher = $1 + 0.05;
+		$res = NPTest->testCmd( "./check_snmp -H $host_snmp -C $snmp_community -o enterprises.ucdavis.laTable.laEntry.laLoad.3 -w $lower -c $higher");
+		cmp_ok( $res->return_code, '==', 1, "Exit WARNING with fractionnal arcuments");
+
+		$res = NPTest->testCmd( "./check_snmp -H $host_snmp -C $snmp_community -o system.sysUpTime.0,host.hrSWRun.hrSWRunTable.hrSWRunEntry.hrSWRunIndex.1 -w ,:0 -c ,:2");
+		cmp_ok( $res->return_code, '==', 1, "Exit WARNING on 2nd threshold");
+		like($res->output, '/^SNMP WARNING - Timeticks:\s\(\d+\)\s.*,\s.*\s\*1\*\s.*$/', "First OID returned as string, 2nd checked for thresholds");
+
+		$res = NPTest->testCmd( "./check_snmp -H $host_snmp -C $snmp_community -o host.hrSWRun.hrSWRunTable.hrSWRunEntry.hrSWRunIndex.1 -w '' -c ''");
+		cmp_ok( $res->return_code, '==', 0, "Empty thresholds doesn't crash");
+
+		$res = NPTest->testCmd( "./check_snmp -H $host_snmp -C $snmp_community -o host.hrStorage.hrMemorySize.0,host.hrSystem.hrSystemProcesses.0 -w ,,1 -c ,,2");
+		cmp_ok( $res->return_code, '==', 0, "Skipping first two thresholds on 2 OID check");
+		like($res->output, '/^SNMP OK - \d+ \w+ \d+\s.*$/', "Skipping first two thresholds, result printed rather than parsed");
+
+		$res = NPTest->testCmd( "./check_snmp -H $host_snmp -C $snmp_community -o host.hrStorage.hrMemorySize.0,host.hrSystem.hrSystemProcesses.0 -w ,, -c ,,");
+		cmp_ok( $res->return_code, '==', 0, "Skipping all thresholds");
+		like($res->output, '/^SNMP OK - \d+ \w+ \d+\s.*$/', "Skipping all thresholds, result printed rather than parsed");
+
 	}
 
 	SKIP: {


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Commits mailing list