aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2020-03-05 11:39:29 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2020-03-05 11:39:29 +0200
commitd69e51f571a3277dff8d3d374521b5902e1a6e5c (patch)
tree2920bd0f29679ea9defcd7bbccf71eb311284234
parent2cd60c7e775b481332703d9674f02c68ab3b3e91 (diff)
downloadping903-d69e51f571a3277dff8d3d374521b5902e1a6e5c.tar.gz
ping903-d69e51f571a3277dff8d3d374521b5902e1a6e5c.tar.bz2
ping903q: improve output in Nagios mode; treat initial state as OK
New option -N is provided to treat the initial state as UNKNOWN as in previous versions.
-rw-r--r--doc/ping903q.120
-rw-r--r--src/ping903q.c83
2 files changed, 82 insertions, 21 deletions
diff --git a/doc/ping903q.1 b/doc/ping903q.1
index 5da343d..84bd850 100644
--- a/doc/ping903q.1
+++ b/doc/ping903q.1
@@ -13,7 +13,7 @@
.\"
.\" You should have received a copy of the GNU General Public License
.\" along with Ping903. If not, see <http://www.gnu.org/licenses/>.
-.TH PING903Q 1 "February 27, 2020" "PING903Q" "User Commands"
+.TH PING903Q 1 "March 5, 2020" "PING903Q" "User Commands"
.SH NAME
ping903q \- ping903 query tool
.SH SYNOPSIS
@@ -24,6 +24,7 @@ ping903q \- ping903 query tool
[\fIIP\fR]
.PP
\fBping903q\fR\
+ [\fB\-N\fR]\
[\fB\-f \fIFILE\fR]\
[\fB\-p \fIPREFIX\fR]\
[\fB\-R \fIREALM\fR]\
@@ -83,7 +84,7 @@ request, without sending unauthorized request first and consulting the
reply.
.SH EXIT CODE
When called with one argument, the program exits with code 0 (success)
-if the IP is alive and 2 otherwise.
+if the IP is alive, 2 if it is not, and 3 if the host status is unknown.
.PP
When called without arguments, the program exits with code 0 if all
monitored IP addresses are alive, 2 if none of them is reachable and 1
@@ -99,6 +100,16 @@ Warning condition.
.TP
.B 2
Critical condition.
+.TP
+.B 3
+Unknown. This code is returned in the following cases: (1) the host
+is not monitored by the
+.B ping903
+server, (2) the server replied with a HTTP code other than 200 or the
+reply was otherwise non-compliant, and (3) if the server has not
+yet collected enough data for that host and the command line option
+.B \-N
+was given.
.PP
In match mode, the program exits with code 0 if the requested host is
monitored by the server, and with code 2 if it is not.
@@ -155,6 +166,11 @@ arguments.
.PP
Other options valid in this mode:
.TP
+\fB\-N\fR
+By default hosts in initial state (i.e. for which no data has been
+collected) are treated as "OK" (exit status 0). This option changes
+the default to treat them as "UNKNOWN" (exit status 3).
+.TP
\fB\-p \fIPREFIX\fR
Supplies the prefix to be displayed before Nagios status string. The
default is "PING". The \fIPREFIX\fR string can contain the
diff --git a/src/ping903q.c b/src/ping903q.c
index 8323f44..64c17bb 100644
--- a/src/ping903q.c
+++ b/src/ping903q.c
@@ -35,6 +35,7 @@ static char *config_file = DEFAULT_CONFIG_FILE;
FILE *http;
int verbose;
int resolve_ip;
+int nodata_ok = 1;
char *nagios_prefix_format = "PING";
char const http_version[] = "HTTP/1.1";
char *cred_file_name;
@@ -754,6 +755,14 @@ print_host_status(struct json_value *obj, void *unused)
return alive ? EX_NAGIOS_OK : EX_NAGIOS_CRITICAL;
}
+static int
+unknown_host_status(char const *host, char const *msg)
+{
+ abend("%s: %s", host, msg);
+ return EX_NAGIOS_UNKNOWN;
+}
+
+
static char *
resolve_host(char const *name)
{
@@ -777,7 +786,9 @@ resolve_host(char const *name)
}
static void
-query_host(char const *name, int (*report)(struct json_value *, void *),
+query_host(char const *name,
+ int (*report)(struct json_value *, void *),
+ int (*unknown)(char const*, char const*),
void *report_data)
{
int rc;
@@ -800,21 +811,27 @@ query_host(char const *name, int (*report)(struct json_value *, void *),
}
http_resp_init(&resp);
http_query("GET", url, std_headers, &resp);
- if (resp.code != 200)
- abend("%s", resp.reason);
+ switch (resp.code) {
+ case 200:
+ break;
+ case 404:
+ exit(unknown(name, "host is not monitored"));
+ default:
+ exit(unknown(name, resp.reason));
+ }
hval = http_resp_get_header(&resp, "content-type");
if (!hval || strcmp(hval, "application/json")) {
- abend("missing or unsupported content type");
+ exit(unknown(name, "missing or unsupported content type"));
}
rc = json_parse_string(resp.content, &obj, &p);
if (rc != JSON_E_NOERR)
abend("%s near %s", json_strerror(rc), p);
if (obj->type == json_null)
- abend("%s (%s): host is not being monitored", name, ipstr);
+ exit(unknown(name, "host is not monitored"));
if (obj->type != json_object)
- abend("returned entity has wrong type");
+ exit(unknown(name, "returned entity has wrong type"));
exit(report(obj, report_data));
}
@@ -959,13 +976,13 @@ static inline int newstatus(int old, int new) {
return old > new ? old : new;
}
+/* Format initial prefix */
static void
-nagios_format_output(int status, double loss, double rta,
- struct nagios_check_data *cd, char const *name)
+nagios_format_prefix(char const *name, int status)
{
char *p;
size_t len;
- /* Format initial prefix */
+
p = nagios_prefix_format;
while (*p) {
len = strcspn(p, "%");
@@ -983,10 +1000,13 @@ nagios_format_output(int status, double loss, double rta,
}
}
printf(" %s ", status_str[status]);
- if (status == EX_NAGIOS_UNKNOWN) {
- printf("%s\n", "- waiting for data to arrive");
- return;
- }
+}
+
+static void
+nagios_format_output(int status, double loss, double rta,
+ struct nagios_check_data *cd, char const *name)
+{
+ nagios_format_prefix(name, status);
if (loss >= 100) {
printf("%s", "- Packet loss = 100%");
rta = cd->cth.round_trip;
@@ -1010,6 +1030,12 @@ nagios_check(struct json_value *obj, void *data)
jv = ejson_get(obj, "status", json_string);
if (strcmp(jv->v.s, "init") == 0) {
+ if (nodata_ok) {
+ status = EX_NAGIOS_OK;
+ nagios_format_prefix(name, status);
+ printf("- %s\n", "waiting for data to arrive");
+ return status;
+ }
status = EX_NAGIOS_UNKNOWN;
} else if (strcmp(jv->v.s, "invalid") == 0
|| json_object_get(obj, "stddev", &jv)) {
@@ -1031,14 +1057,24 @@ nagios_check(struct json_value *obj, void *data)
status = newstatus(status, EX_NAGIOS_WARNING);
}
nagios_format_output(status, loss, rta, cd, name);
- exit(status);
+ return status;
}
+
+static int
+nagios_unknown(char const *name, char const *msg)
+{
+ nagios_format_prefix(name, EX_NAGIOS_UNKNOWN);
+ printf("- %s\n", msg);
+ return EX_NAGIOS_UNKNOWN;
+}
+
void
usage(void)
{
printf("Usage: %s [-hrVv] [-f FILE] [HOST]\n", progname);
- printf(" or: %s -H HOST -c RTA,PCT%% -w RTA,PCT%%\n", progname);
+ printf(" or: %s [-N] [-p PREFIX] -H HOST -c RTA,PCT%% -w RTA,PCT%%\n",
+ progname);
printf(" or: %s -m HOST\n", progname);
printf("Query ping903 daemon.\n");
printf("\n");
@@ -1053,7 +1089,11 @@ usage(void)
printf(" -H HOST query statistics for this host\n");
printf(" -c RTA,PCT%% set critical threshold\n");
printf(" -w RTA,PCT%% set warning threshold\n");
- printf("\n(all three must be given in this mode)\n");
+ printf("\n (all three must be given in this mode)\n\n");
+ printf(" -N treat initial state as UNKNOWN, "
+ "instead of OK\n");
+ printf(" -p PREFIX prefix output with this string, "
+ "instead of the default \"PING\"\n");
printf("\nMatch mode:\n\n");
printf(" -m check whether HOST is monitored\n");
printf("\n");
@@ -1109,7 +1149,7 @@ main(int argc, char **argv)
exit(0);
}
}
- while ((c = getopt(argc, argv, "c:f:H:hmp:R:rVvw:")) != EOF) {
+ while ((c = getopt(argc, argv, "c:f:H:hNmp:R:rVvw:")) != EOF) {
switch (c) {
case 'c':
c_opt = optarg;
@@ -1125,6 +1165,9 @@ main(int argc, char **argv)
case 'h':
usage();
exit(0);
+ case 'N':
+ nodata_ok = 0;
+ break;
case 'm':
setmode(MODE_MATCH, c);
break;
@@ -1201,14 +1244,16 @@ main(int argc, char **argv)
case 0:
query_all();
case 1:
- query_host(argv[0], print_host_status, NULL);
+ query_host(argv[0],
+ print_host_status,
+ unknown_host_status, NULL);
default:
abend("bad number of arguments");
}
break;
case MODE_NAGIOS_CHECK:
- query_host(host, nagios_check, &chkdata);
+ query_host(host, nagios_check, nagios_unknown, &chkdata);
break;
case MODE_MATCH:

Return to:

Send suggestions and report system problems to the System administrator.