forked from abh/ntppool
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmonitor
executable file
·131 lines (97 loc) · 3.46 KB
/
monitor
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#!/usr/bin/env perl
use strict;
use Net::NTP 1.3;
use LWP;
use Time::HiRes;
use JSON qw(decode_json encode_json);
my $VERSION = "0.1";
$Net::NTP::TIMEOUT = 2;
# How often should the server be rechecked?
my $sleeptime = 120;
my $api_key = shift or die "$0 [api_key] [pool-server]\n";
my $pool_server = shift || "http://www.pool.ntp.org/monitor";
$pool_server .= '?api_key=' . $api_key;
my $verbose = 1;
# check if this machine has good time.
$Net::NTP::CLIENT_TIME_SEND = undef;
$Net::NTP::CLIENT_TIME_RECEIVE = undef;
my $mon_host = 'localhost';
my %pkt = eval { get_ntp_response($mon_host) };
if (!$pkt{'Stratum'} or $pkt{'Stratum'} == 0 or $pkt{'Stratum'} > 6) {
die "monitoring server not synchronized\n";
}
#use Data::Dump qw(pp);
#pp(\%pkt);
# TODO: check the offset, too, with "ntpdc -c loopinfo" or "ntpq -c rv";
# probably use the Capture::Tiny module to make it easy.
# See https://github.com/abh/ntppool/issues/11
# and if we're connected
$Net::NTP::CLIENT_TIME_SEND = undef;
$Net::NTP::CLIENT_TIME_RECEIVE = undef;
%pkt = eval { get_ntp_response('tick.ucla.edu'); };
if ($pkt{'Stratum'} == 0 or $pkt{'Stratum'} > 6) {
$Net::NTP::CLIENT_TIME_SEND = undef;
$Net::NTP::CLIENT_TIME_RECEIVE = undef;
%pkt = eval { get_ntp_response('clock-b.develooper.com'); };
if ($pkt{'Stratum'} == 0 or $pkt{'Stratum'} > 6) {
die "no time from ntp1 or clock-b\n";
}
}
sub catch_TERM {
exit(0);
}
$SIG{TERM} = \&catch_TERM;
my $ua = LWP::UserAgent->new;
$ua->agent("NTPPool-Monitor/$VERSION");
while(1) {
my $response = $ua->get($pool_server);
my $data = eval { decode_json($response->content) } || {};
my $err = $@;
if (!$response->is_success or $data->{error} or $err) {
die "$pool_server error: ", $response->status_line, "\n",
( $data->{error} ? "Server Response: " . $data->{error} . "\n" : () ),
( $err ? "Data decoding error: $err\n" . $response->content . "\n" : () );
}
die "Could not decode data" unless $data;
my @hosts = @{ $data->{servers} };
# If the server has nothing to do for us, come back later.
if (not @hosts) {
sleep $sleeptime;
next;
}
my @status;
for my $server (@hosts) {
$server =~ m/::/ and require IO::Socket::INET6;
my $status = { server => $server };
# try twice
for (my $i = 0; !defined($status->{offset}) and $i < 2; $i++) {
$Net::NTP::CLIENT_TIME_RECEIVE = undef;
my $time_then = Time::HiRes::time;
$Net::NTP::CLIENT_TIME_SEND = $time_then;
my %pkt = eval { get_ntp_response($server); };
my $time_now = Time::HiRes::time;
$status->{ts} = $time_now;
if (!$pkt{Stratum} or $!) {
$status->{no_response} = 1;
}
else {
delete $status->{no_response};
my $recv_org = $pkt{'Receive Timestamp'} - $time_now;
my $trans_dest = $pkt{'Transmit Timestamp'} - $time_then;
$status->{offset} = ($recv_org + $trans_dest) / 2;
$status->{stratum} = $pkt{Stratum};
}
}
push @status, $status;
}
print encode_json(\@status) . "\n";
$response = $ua->post($pool_server, Content_Type => 'application/json',
Content => encode_json({ version => 1, servers => \@status }));
die "$pool_server error:", $response->status_line unless $response->is_success;
my $data = decode_json($response->content);
if ($data->{warnings} && @{ $data->{warnings} }) {
for my $w (@{ $data->{warnings} }) {
print "WARNING: $w\n";
}
}
} # end mainloop