diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2020-03-05 11:39:29 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2020-03-05 11:39:29 +0200 |
commit | d69e51f571a3277dff8d3d374521b5902e1a6e5c (patch) | |
tree | 2920bd0f29679ea9defcd7bbccf71eb311284234 | |
parent | 2cd60c7e775b481332703d9674f02c68ab3b3e91 (diff) | |
download | ping903-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.1 | 20 | ||||
-rw-r--r-- | src/ping903q.c | 83 |
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: |