diff options
author | Holger Weiss <holger@zedat.fu-berlin.de> | 2010-03-18 00:34:14 +0100 |
---|---|---|
committer | Holger Weiss <holger@zedat.fu-berlin.de> | 2010-03-18 00:34:14 +0100 |
commit | e11b67f6200b994c6d8118948a36eb0ed43bec5a (patch) | |
tree | d6497188c156d65344f2269a1b606ce1d9583e26 /plugins | |
parent | f95cb118dee9fbaaba4e2c7bbbcf368f8d915d9a (diff) | |
download | monitoring-plugins-e11b67f6200b994c6d8118948a36eb0ed43bec5a.tar.gz |
Let check_ntp_peer check the number of truechimers
Add support for checking the number of usable time sources (i.e., the
number of peers which are classified as so-called "truechimers" by NTP's
intersection algorithm). The new "-m" and "-n" options allow for
specifying the according WARNING and CRITICAL thresholds (and thereby
activating the truechimers check), respectively.
Diffstat (limited to 'plugins')
-rw-r--r-- | plugins/check_ntp_peer.c | 72 | ||||
-rw-r--r-- | plugins/t/check_ntp.t | 24 |
2 files changed, 69 insertions, 27 deletions
diff --git a/plugins/check_ntp_peer.c b/plugins/check_ntp_peer.c index e8325bc8..d4689bc7 100644 --- a/plugins/check_ntp_peer.c +++ b/plugins/check_ntp_peer.c | |||
@@ -56,6 +56,9 @@ static char *scrit="-1:16"; | |||
56 | static short do_jitter=0; | 56 | static short do_jitter=0; |
57 | static char *jwarn="-1:5000"; | 57 | static char *jwarn="-1:5000"; |
58 | static char *jcrit="-1:10000"; | 58 | static char *jcrit="-1:10000"; |
59 | static short do_truechimers=0; | ||
60 | static char *twarn="0:"; | ||
61 | static char *tcrit="0:"; | ||
59 | static int syncsource_found=0; | 62 | static int syncsource_found=0; |
60 | static int li_alarm=0; | 63 | static int li_alarm=0; |
61 | 64 | ||
@@ -63,6 +66,7 @@ int process_arguments (int, char **); | |||
63 | thresholds *offset_thresholds = NULL; | 66 | thresholds *offset_thresholds = NULL; |
64 | thresholds *jitter_thresholds = NULL; | 67 | thresholds *jitter_thresholds = NULL; |
65 | thresholds *stratum_thresholds = NULL; | 68 | thresholds *stratum_thresholds = NULL; |
69 | thresholds *truechimer_thresholds = NULL; | ||
66 | void print_help (void); | 70 | void print_help (void); |
67 | void print_usage (void); | 71 | void print_usage (void); |
68 | 72 | ||
@@ -121,6 +125,7 @@ typedef struct { | |||
121 | #define OP_READVAR 0x02 | 125 | #define OP_READVAR 0x02 |
122 | /* In peer status bytes, bits 6,7,8 determine clock selection status */ | 126 | /* In peer status bytes, bits 6,7,8 determine clock selection status */ |
123 | #define PEER_SEL(x) ((ntohs(x)>>8)&0x07) | 127 | #define PEER_SEL(x) ((ntohs(x)>>8)&0x07) |
128 | #define PEER_TRUECHIMER 0x02 | ||
124 | #define PEER_INCLUDED 0x04 | 129 | #define PEER_INCLUDED 0x04 |
125 | #define PEER_SYNCSOURCE 0x06 | 130 | #define PEER_SYNCSOURCE 0x06 |
126 | 131 | ||
@@ -160,12 +165,12 @@ void print_ntp_control_message(const ntp_control_message *p){ | |||
160 | for(i=0;i<numpeers;i++){ | 165 | for(i=0;i<numpeers;i++){ |
161 | printf("\tpeer id %.2x status %.2x", | 166 | printf("\tpeer id %.2x status %.2x", |
162 | ntohs(peer[i].assoc), ntohs(peer[i].status)); | 167 | ntohs(peer[i].assoc), ntohs(peer[i].status)); |
163 | if (PEER_SEL(peer[i].status) >= PEER_INCLUDED){ | 168 | if(PEER_SEL(peer[i].status) >= PEER_SYNCSOURCE){ |
164 | if(PEER_SEL(peer[i].status) >= PEER_SYNCSOURCE){ | 169 | printf(" <-- current sync source"); |
165 | printf(" <-- current sync source"); | 170 | } else if(PEER_SEL(peer[i].status) >= PEER_INCLUDED){ |
166 | } else { | 171 | printf(" <-- current sync candidate"); |
167 | printf(" <-- current sync candidate"); | 172 | } else if(PEER_SEL(peer[i].status) >= PEER_TRUECHIMER){ |
168 | } | 173 | printf(" <-- outlyer, but truechimer"); |
169 | } | 174 | } |
170 | printf("\n"); | 175 | printf("\n"); |
171 | } | 176 | } |
@@ -194,7 +199,7 @@ setup_control_request(ntp_control_message *p, uint8_t opcode, uint16_t seq){ | |||
194 | * status is pretty much useless as syncsource_found is a global variable | 199 | * status is pretty much useless as syncsource_found is a global variable |
195 | * used later in main to check is the server was synchronized. It works | 200 | * used later in main to check is the server was synchronized. It works |
196 | * so I left it alone */ | 201 | * so I left it alone */ |
197 | int ntp_request(const char *host, double *offset, int *offset_result, double *jitter, int *stratum){ | 202 | int ntp_request(const char *host, double *offset, int *offset_result, double *jitter, int *stratum, int *num_truechimers){ |
198 | int conn=-1, i, npeers=0, num_candidates=0; | 203 | int conn=-1, i, npeers=0, num_candidates=0; |
199 | double tmp_offset = 0; | 204 | double tmp_offset = 0; |
200 | int min_peer_sel=PEER_INCLUDED; | 205 | int min_peer_sel=PEER_INCLUDED; |
@@ -209,6 +214,7 @@ int ntp_request(const char *host, double *offset, int *offset_result, double *ji | |||
209 | status = STATE_OK; | 214 | status = STATE_OK; |
210 | *offset_result = STATE_UNKNOWN; | 215 | *offset_result = STATE_UNKNOWN; |
211 | *jitter = *stratum = -1; | 216 | *jitter = *stratum = -1; |
217 | *num_truechimers = 0; | ||
212 | 218 | ||
213 | /* Long-winded explanation: | 219 | /* Long-winded explanation: |
214 | * Getting the sync peer offset, jitter and stratum requires a number of | 220 | * Getting the sync peer offset, jitter and stratum requires a number of |
@@ -261,11 +267,14 @@ int ntp_request(const char *host, double *offset, int *offset_result, double *ji | |||
261 | * at least some candidates. In the latter case we'll issue | 267 | * at least some candidates. In the latter case we'll issue |
262 | * a warning but go ahead with the check on them. */ | 268 | * a warning but go ahead with the check on them. */ |
263 | for (i = 0; i < npeers; i++){ | 269 | for (i = 0; i < npeers; i++){ |
264 | if (PEER_SEL(peers[i].status) >= PEER_INCLUDED){ | 270 | if(PEER_SEL(peers[i].status) >= PEER_TRUECHIMER){ |
265 | num_candidates++; | 271 | (*num_truechimers)++; |
266 | if(PEER_SEL(peers[i].status) >= PEER_SYNCSOURCE){ | 272 | if(PEER_SEL(peers[i].status) >= PEER_INCLUDED){ |
267 | syncsource_found=1; | 273 | num_candidates++; |
268 | min_peer_sel=PEER_SYNCSOURCE; | 274 | if(PEER_SEL(peers[i].status) >= PEER_SYNCSOURCE){ |
275 | syncsource_found=1; | ||
276 | min_peer_sel=PEER_SYNCSOURCE; | ||
277 | } | ||
269 | } | 278 | } |
270 | } | 279 | } |
271 | } | 280 | } |
@@ -413,6 +422,8 @@ int process_arguments(int argc, char **argv){ | |||
413 | {"scrit", required_argument, 0, 'C'}, | 422 | {"scrit", required_argument, 0, 'C'}, |
414 | {"jwarn", required_argument, 0, 'j'}, | 423 | {"jwarn", required_argument, 0, 'j'}, |
415 | {"jcrit", required_argument, 0, 'k'}, | 424 | {"jcrit", required_argument, 0, 'k'}, |
425 | {"twarn", required_argument, 0, 'm'}, | ||
426 | {"tcrit", required_argument, 0, 'n'}, | ||
416 | {"timeout", required_argument, 0, 't'}, | 427 | {"timeout", required_argument, 0, 't'}, |
417 | {"hostname", required_argument, 0, 'H'}, | 428 | {"hostname", required_argument, 0, 'H'}, |
418 | {"port", required_argument, 0, 'p'}, | 429 | {"port", required_argument, 0, 'p'}, |
@@ -424,7 +435,7 @@ int process_arguments(int argc, char **argv){ | |||
424 | usage ("\n"); | 435 | usage ("\n"); |
425 | 436 | ||
426 | while (1) { | 437 | while (1) { |
427 | c = getopt_long (argc, argv, "Vhv46qw:c:W:C:j:k:t:H:p:", longopts, &option); | 438 | c = getopt_long (argc, argv, "Vhv46qw:c:W:C:j:k:m:n:t:H:p:", longopts, &option); |
428 | if (c == -1 || c == EOF || c == 1) | 439 | if (c == -1 || c == EOF || c == 1) |
429 | break; | 440 | break; |
430 | 441 | ||
@@ -467,6 +478,14 @@ int process_arguments(int argc, char **argv){ | |||
467 | do_jitter=1; | 478 | do_jitter=1; |
468 | jcrit = optarg; | 479 | jcrit = optarg; |
469 | break; | 480 | break; |
481 | case 'm': | ||
482 | do_truechimers=1; | ||
483 | twarn = optarg; | ||
484 | break; | ||
485 | case 'n': | ||
486 | do_truechimers=1; | ||
487 | tcrit = optarg; | ||
488 | break; | ||
470 | case 'H': | 489 | case 'H': |
471 | if(is_host(optarg) == FALSE) | 490 | if(is_host(optarg) == FALSE) |
472 | usage2(_("Invalid hostname/address"), optarg); | 491 | usage2(_("Invalid hostname/address"), optarg); |
@@ -526,8 +545,16 @@ char *perfd_stratum (int stratum) | |||
526 | TRUE, 0, TRUE, 16); | 545 | TRUE, 0, TRUE, 16); |
527 | } | 546 | } |
528 | 547 | ||
548 | char *perfd_truechimers (int num_truechimers) | ||
549 | { | ||
550 | return perfdata ("truechimers", num_truechimers, "", | ||
551 | do_truechimers, (int)truechimer_thresholds->warning->end, | ||
552 | do_truechimers, (int)truechimer_thresholds->critical->end, | ||
553 | TRUE, 0, FALSE, 0); | ||
554 | } | ||
555 | |||
529 | int main(int argc, char *argv[]){ | 556 | int main(int argc, char *argv[]){ |
530 | int result, offset_result, stratum; | 557 | int result, offset_result, stratum, num_truechimers; |
531 | double offset=0, jitter=0; | 558 | double offset=0, jitter=0; |
532 | char *result_line, *perfdata_line; | 559 | char *result_line, *perfdata_line; |
533 | 560 | ||
@@ -544,6 +571,7 @@ int main(int argc, char *argv[]){ | |||
544 | set_thresholds(&offset_thresholds, owarn, ocrit); | 571 | set_thresholds(&offset_thresholds, owarn, ocrit); |
545 | set_thresholds(&jitter_thresholds, jwarn, jcrit); | 572 | set_thresholds(&jitter_thresholds, jwarn, jcrit); |
546 | set_thresholds(&stratum_thresholds, swarn, scrit); | 573 | set_thresholds(&stratum_thresholds, swarn, scrit); |
574 | set_thresholds(&truechimer_thresholds, twarn, tcrit); | ||
547 | 575 | ||
548 | /* initialize alarm signal handling */ | 576 | /* initialize alarm signal handling */ |
549 | signal (SIGALRM, socket_timeout_alarm_handler); | 577 | signal (SIGALRM, socket_timeout_alarm_handler); |
@@ -552,7 +580,7 @@ int main(int argc, char *argv[]){ | |||
552 | alarm (socket_timeout); | 580 | alarm (socket_timeout); |
553 | 581 | ||
554 | /* This returns either OK or WARNING (See comment preceeding ntp_request) */ | 582 | /* This returns either OK or WARNING (See comment preceeding ntp_request) */ |
555 | result = ntp_request(server_address, &offset, &offset_result, &jitter, &stratum); | 583 | result = ntp_request(server_address, &offset, &offset_result, &jitter, &stratum, &num_truechimers); |
556 | 584 | ||
557 | if(offset_result == STATE_UNKNOWN) { | 585 | if(offset_result == STATE_UNKNOWN) { |
558 | /* if there's no sync peer (this overrides ntp_request output): */ | 586 | /* if there's no sync peer (this overrides ntp_request output): */ |
@@ -564,6 +592,9 @@ int main(int argc, char *argv[]){ | |||
564 | result = max_state_alt(result, get_status(fabs(offset), offset_thresholds)); | 592 | result = max_state_alt(result, get_status(fabs(offset), offset_thresholds)); |
565 | } | 593 | } |
566 | 594 | ||
595 | if(do_truechimers) | ||
596 | result = max_state_alt(result, get_status(num_truechimers, truechimer_thresholds)); | ||
597 | |||
567 | if(do_stratum) | 598 | if(do_stratum) |
568 | result = max_state_alt(result, get_status(stratum, stratum_thresholds)); | 599 | result = max_state_alt(result, get_status(stratum, stratum_thresholds)); |
569 | 600 | ||
@@ -604,6 +635,10 @@ int main(int argc, char *argv[]){ | |||
604 | asprintf(&result_line, "%s, stratum=%i", result_line, stratum); | 635 | asprintf(&result_line, "%s, stratum=%i", result_line, stratum); |
605 | asprintf(&perfdata_line, "%s %s", perfdata_line, perfd_stratum(stratum)); | 636 | asprintf(&perfdata_line, "%s %s", perfdata_line, perfd_stratum(stratum)); |
606 | } | 637 | } |
638 | if (do_truechimers) { | ||
639 | asprintf(&result_line, "%s, truechimers=%i", result_line, num_truechimers); | ||
640 | asprintf(&perfdata_line, "%s %s", perfdata_line, perfd_truechimers(num_truechimers)); | ||
641 | } | ||
607 | printf("%s|%s\n", result_line, perfdata_line); | 642 | printf("%s|%s\n", result_line, perfdata_line); |
608 | 643 | ||
609 | if(server_address!=NULL) free(server_address); | 644 | if(server_address!=NULL) free(server_address); |
@@ -640,6 +675,10 @@ void print_help(void){ | |||
640 | printf (" %s\n", _("Warning threshold for jitter")); | 675 | printf (" %s\n", _("Warning threshold for jitter")); |
641 | printf (" %s\n", "-k, --jcrit=THRESHOLD"); | 676 | printf (" %s\n", "-k, --jcrit=THRESHOLD"); |
642 | printf (" %s\n", _("Critical threshold for jitter")); | 677 | printf (" %s\n", _("Critical threshold for jitter")); |
678 | printf (" %s\n", "-m, --twarn=THRESHOLD"); | ||
679 | printf (" %s\n", _("Warning threshold for number of usable time sources (\"truechimers\")")); | ||
680 | printf (" %s\n", "-n, --tcrit=THRESHOLD"); | ||
681 | printf (" %s\n", _("Critical threshold for number of usable time sources (\"truechimers\")")); | ||
643 | printf (_(UT_TIMEOUT), DEFAULT_SOCKET_TIMEOUT); | 682 | printf (_(UT_TIMEOUT), DEFAULT_SOCKET_TIMEOUT); |
644 | printf (_(UT_VERBOSE)); | 683 | printf (_(UT_VERBOSE)); |
645 | 684 | ||
@@ -668,6 +707,9 @@ void print_help(void){ | |||
668 | printf(" %s\n", _("(See Notes above for more details on thresholds formats):")); | 707 | printf(" %s\n", _("(See Notes above for more details on thresholds formats):")); |
669 | printf(" %s\n", ("./check_ntp_peer -H ntpserv -w 0.5 -c 1 -j -1:100 -k -1:200")); | 708 | printf(" %s\n", ("./check_ntp_peer -H ntpserv -w 0.5 -c 1 -j -1:100 -k -1:200")); |
670 | printf("\n"); | 709 | printf("\n"); |
710 | printf(" %s\n", _("Only check the number of usable time sources (\"truechimers\"):")); | ||
711 | printf(" %s\n", ("./check_ntp_peer -H ntpserv -m :5 -n :3")); | ||
712 | printf("\n"); | ||
671 | printf(" %s\n", _("Check only stratum:")); | 713 | printf(" %s\n", _("Check only stratum:")); |
672 | printf(" %s\n", ("./check_ntp_peer -H ntpserv -W 4 -C 6")); | 714 | printf(" %s\n", ("./check_ntp_peer -H ntpserv -W 4 -C 6")); |
673 | 715 | ||
diff --git a/plugins/t/check_ntp.t b/plugins/t/check_ntp.t index b71c8631..3eee6e17 100644 --- a/plugins/t/check_ntp.t +++ b/plugins/t/check_ntp.t | |||
@@ -34,9 +34,9 @@ my $hostname_invalid = getTestParameter( "NP_HOSTNAME_INVALID", | |||
34 | my $ntp_okmatch1 = '/^NTP\sOK:\sOffset\s-?[0-9]+(\.[0-9]+)?(e-[0-9]{2})?\ssecs/'; | 34 | my $ntp_okmatch1 = '/^NTP\sOK:\sOffset\s-?[0-9]+(\.[0-9]+)?(e-[0-9]{2})?\ssecs/'; |
35 | my $ntp_warnmatch1 = '/^NTP\sWARNING:\sOffset\s-?[0-9]+(\.[0-9]+)?(e-[0-9]{2})?\ssecs/'; | 35 | my $ntp_warnmatch1 = '/^NTP\sWARNING:\sOffset\s-?[0-9]+(\.[0-9]+)?(e-[0-9]{2})?\ssecs/'; |
36 | my $ntp_critmatch1 = '/^NTP\sCRITICAL:\sOffset\s-?[0-9]+(\.[0-9]+)?(e-[0-9]{2})?\ssecs/'; | 36 | my $ntp_critmatch1 = '/^NTP\sCRITICAL:\sOffset\s-?[0-9]+(\.[0-9]+)?(e-[0-9]{2})?\ssecs/'; |
37 | my $ntp_okmatch2 = '/^NTP\sOK:\sOffset\s-?[0-9]+(\.[0-9]+)?(e-[0-9]{2})?\ssecs,\sjitter=[0-9]+\.[0-9]+,\sstratum=[0-9]{1,2}/'; | 37 | my $ntp_okmatch2 = '/^NTP\sOK:\sOffset\s-?[0-9]+(\.[0-9]+)?(e-[0-9]{2})?\ssecs,\sjitter=[0-9]+\.[0-9]+,\sstratum=[0-9]{1,2},\struechimers=[0-9]+/'; |
38 | my $ntp_warnmatch2 = '/^NTP\sWARNING:\sOffset\s-?[0-9]+(\.[0-9]+)?(e-[0-9]{2})?\ssecs,\sjitter=[0-9]+\.[0-9]+,\sstratum=[0-9]{1,2}/'; | 38 | my $ntp_warnmatch2 = '/^NTP\sWARNING:\sOffset\s-?[0-9]+(\.[0-9]+)?(e-[0-9]{2})?\ssecs,\sjitter=[0-9]+\.[0-9]+,\sstratum=[0-9]{1,2},\struechimers=[0-9]+/'; |
39 | my $ntp_critmatch2 = '/^NTP\sCRITICAL:\sOffset\s-?[0-9]+(\.[0-9]+)?(e-[0-9]{2})?\ssecs,\sjitter=[0-9]+\.[0-9]+,\sstratum=[0-9]{1,2}/'; | 39 | my $ntp_critmatch2 = '/^NTP\sCRITICAL:\sOffset\s-?[0-9]+(\.[0-9]+)?(e-[0-9]{2})?\ssecs,\sjitter=[0-9]+\.[0-9]+,\sstratum=[0-9]{1,2},\struechimers=[0-9]+/'; |
40 | my $ntp_noresponse = '/^(CRITICAL - Socket timeout after 3 seconds)|(NTP CRITICAL: No response from NTP server)$/'; | 40 | my $ntp_noresponse = '/^(CRITICAL - Socket timeout after 3 seconds)|(NTP CRITICAL: No response from NTP server)$/'; |
41 | my $ntp_nosuchhost = '/^check_ntp.*: Invalid hostname/address - ' . $hostname_invalid . '/'; | 41 | my $ntp_nosuchhost = '/^check_ntp.*: Invalid hostname/address - ' . $hostname_invalid . '/'; |
42 | 42 | ||
@@ -90,21 +90,21 @@ foreach my $plugin (@PLUGINS2) { | |||
90 | SKIP: { | 90 | SKIP: { |
91 | skip "No NTP server defined", 1 unless $ntp_service; | 91 | skip "No NTP server defined", 1 unless $ntp_service; |
92 | $res = NPTest->testCmd( | 92 | $res = NPTest->testCmd( |
93 | "./$plugin -H $ntp_service -w 1000 -c 2000 -W 20 -C 21 -j 100000 -k 200000" | 93 | "./$plugin -H $ntp_service -w 1000 -c 2000 -W 20 -C 21 -j 100000 -k 200000 -m 1: -n 0:" |
94 | ); | 94 | ); |
95 | cmp_ok( $res->return_code, '==', 0, "$plugin: Good NTP result with jitter and stratum check" ); | 95 | cmp_ok( $res->return_code, '==', 0, "$plugin: Good NTP result with jitter, stratum, and truechimers check" ); |
96 | like( $res->output, $ntp_okmatch2, "$plugin: Output match OK with jitter and stratum" ); | 96 | like( $res->output, $ntp_okmatch2, "$plugin: Output match OK with jitter, stratum, and truechimers" ); |
97 | 97 | ||
98 | $res = NPTest->testCmd( | 98 | $res = NPTest->testCmd( |
99 | "./$plugin -H $ntp_service -w 1000 -c 2000 -W \\~:-1 -C 21 -j 100000 -k 200000" | 99 | "./$plugin -H $ntp_service -w 1000 -c 2000 -W \\~:-1 -C 21 -j 100000 -k 200000 -m 1: -n 0:" |
100 | ); | 100 | ); |
101 | cmp_ok( $res->return_code, '==', 1, "$plugin: Warning NTP result with jitter and stratum check" ); | 101 | cmp_ok( $res->return_code, '==', 1, "$plugin: Warning NTP result with jitter, stratum, and truechimers check" ); |
102 | like( $res->output, $ntp_warnmatch2, "$plugin: Output match WARNING with jitter and stratum" ); | 102 | like( $res->output, $ntp_warnmatch2, "$plugin: Output match WARNING with jitter, stratum, and truechimers" ); |
103 | 103 | ||
104 | $res = NPTest->testCmd( | 104 | $res = NPTest->testCmd( |
105 | "./$plugin -H $ntp_service -w 1000 -c 2000 -W 20 -C 21 -j 100000 -k \\~:-1" | 105 | "./$plugin -H $ntp_service -w 1000 -c 2000 -W 20 -C 21 -j 100000 -k \\~:-1 -m 1: -n 0:" |
106 | ); | 106 | ); |
107 | cmp_ok( $res->return_code, '==', 2, "$plugin: Critical NTP result with jitter and stratum check" ); | 107 | cmp_ok( $res->return_code, '==', 2, "$plugin: Critical NTP result with jitter, stratum, and truechimers check" ); |
108 | like( $res->output, $ntp_critmatch2, "$plugin: Output match CRITICAL with jitter and stratum" ); | 108 | like( $res->output, $ntp_critmatch2, "$plugin: Output match CRITICAL with jitter, stratum, and truechimers" ); |
109 | } | 109 | } |
110 | } | 110 | } |