Projet

Général

Profil

Paste
Télécharger au format
Statistiques
| Branche: | Révision:

root / plugins / ntp / ntp_peers @ 17f78427

Historique | Voir | Annoter | Télécharger (6 ko)

1
#!/usr/bin/perl -w
2
# -*- perl -*-
3

    
4
# Plugin to monitor offsets to multiple NTP peers.
5
# NB currently only works for IPv4 peers
6
#
7
# (c)2008 Chris Hastie: chris (at) oak (hyphen) wood (dot) co (dot) uk
8
#
9
# Updated to version 1.1 by;
10
# (c)2010 Uffe Norberg: uffe (dot) norberg (at) gmail (dot) com
11
#
12
# Parameters understood:
13
#
14
# 	config   (required)
15
# 	autoconf (optional - used by munin-node-configure)
16
#
17
# Config variables:
18
#
19
#       ntpq            - path to ntpq program
20
#       statedir        - directory in which to place state file
21
#       hostname_<key>  - override hostname for peer <key>. <key> is
22
#                         an IPv4 address with dots replaced by underscores.
23
#                         Useful for reference clocks, eg
24
#                         env.hostname_127_127_43_0  .GPS.
25
#
26
#
27
# This program is free software: you can redistribute it and/or modify
28
# it under the terms of the GNU General Public License as published by
29
# the Free Software Foundation, either version 3 of the License, or
30
# (at your option) any later version.
31
#
32
# This program is distributed in the hope that it will be useful,
33
# but WITHOUT ANY WARRANTY; without even the implied warranty of
34
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
35
# GNU General Public License for more details.
36
#
37
# You should have received a copy of the GNU General Public License
38
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
39
#
40
# Change log
41
# v1.0.0    2008-07-21        Chris Hastie
42
# initial release
43
#
44
# v1.1.0    2010-12-07	      Uffe Norberg
45
# - Changed default statedir to /var/lib/munin/plugin-state (Debian default)
46
# - Changed config output to make rrdtool draw finer lines in graph
47
# - Changed config output so that rrdtool draws milli- and microseconds correctly
48
#
49
#
50
# Magic markers - optional - used by installation scripts and
51
# munin-node-configure:
52

    
53
#%# family=contrib
54
#%# capabilities=autoconf
55

    
56

    
57
use strict;
58
use Socket;
59

    
60
my $NTPQ = $ENV{ntpq} || "ntpq";
61
my $COMMAND    =      "$NTPQ -np";
62

    
63
my $statedir = $ENV{statedir} || $ENV{MUNIN_PLUGSTATE};
64
my $statefile = "$statedir/ntp_peers.state";
65

    
66
# autoconf
67
if ($ARGV[0] and $ARGV[0] eq "autoconf") {
68
	`$NTPQ -c help >/dev/null 2>/dev/null`;
69
	if ($? eq "0") {
70
		if (`$NTPQ -np | wc -l` > 0) {
71
			print "yes\n";
72
			exit 0;
73
		} else {
74
			print "no (unable to list peers)\n";
75
			exit 1;
76
		}
77
	} else {
78
		print "no (ntpq not found)\n";
79
		exit 1;
80
	}
81
}
82

    
83
my %peers;
84

    
85
# retrieve cached list of IPs and hostnames
86
if (-f "$statefile") {
87
    open (IN, "$statefile") or exit 4;
88
    while (<IN>) {
89
      if (/^([0-9\.]+):(.*)$/) {
90
        $peers{$1}{'name'} = $2;
91
      }
92
    }
93
    close IN;
94
}
95

    
96

    
97
# do custom IP lookups
98
for my $key (map {/^hostname_(.+)/} keys %ENV) {
99
    my $ip = &desanitize_field($key);
100
    $peers{$ip}{'name'} = $ENV{"hostname_$key"}
101
}
102

    
103
# get data from ntpq
104
open(SERVICE, "$COMMAND |")
105
  or die("Could not execute '$COMMAND': $!");
106

    
107
while (<SERVICE>) {
108
    if (/^[-+*#](\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})(\s+\S+){7}\s+(\S+)/) {
109
      my $name  = &lookupname($1);
110
      $peers{$1}{'value'} = $3;
111
    }
112
}
113
close(SERVICE);
114

    
115
# config
116
if ($ARGV[0] and $ARGV[0] eq 'config') {
117
  print "graph_title NTP peer offsets\n";
118
  print "graph_args --base 1000 --vertical-label seconds --lower-limit 0\n";
119
#  print "graph_vlabel ms\n";
120
  print "graph_category time\n";
121
  print "graph_info Offset (in ms) to the server's NTP peers\n";
122
  print "graph_order ";
123
  foreach my $key (sort by_name keys %peers) {
124
    print &sanitize_field($peers{$key}{'name'}) . " ";
125
  }
126
  print "\n";
127
  foreach my $peer (keys %peers) {
128
    print &sanitize_field($peers{$peer}{'name'}) . ".label " . $peers{$peer}{'name'} . "\n";
129
    print &sanitize_field($peers{$peer}{'name'}) . ".draw " . "LINE" . "\n";
130
    print &sanitize_field($peers{$peer}{'name'}) . ".cdef " . &sanitize_field($peers{$peer}{'name'}) . ",1000,/" . "\n";
131
  }
132
  exit 0;
133
}
134

    
135
# send output
136
foreach my $peer (keys %peers) {
137
  print &sanitize_field($peers{$peer}{'name'}) . ".value " . &getpeeroffset($peer) . "\n";
138
}
139

    
140
# save list of peer IPs and hostnames
141
if(-l $statefile) {
142
	die("$statefile is a symbolic link, refusing to touch it.");
143
}
144
open (OUT, ">$statefile") or exit 4;
145
foreach my $i (keys %peers) {
146
  print OUT "$i:" . $peers{$i}{'name'} .  "\n";
147
}
148
close OUT;
149

    
150
# sorts by hostname
151
sub by_name {
152
	return $peers{$a}{'name'} cmp $peers{$b}{'name'};
153
}
154

    
155
# create a valid munin field name from the hostname
156
sub sanitize_field () {
157
  my $field = shift;
158

    
159
  # replace illegal characters with an underscore
160
  $field =~ s/[^A-Za-z0-9_]/_/g;
161
  # prepend an underscore if name starts with a number
162
  $field =~ s/^([^A-Za-z_])/_$1/;
163

    
164
  # truncate to 19 characters
165
  if (length($field) > 19) {
166
    $field = substr($field, 0, 19);
167
  }
168
  return $field
169
}
170

    
171
# get an IP address from the underscore escaped
172
# value of env.hostname_<key>
173
sub desanitize_field () {
174
  my $field = shift;
175
  $field =~ s/_/\./g;
176
  return $field
177
}
178

    
179
# lookup hostnames
180
sub lookupname () {
181
  my $ip = shift;
182
  # have we already got it?
183
  if ($peers{$ip}{'name'}) {
184
    return $peers{$ip}{'name'};
185
  }
186
  # else look it up
187
  my $iaddr = inet_aton($ip);
188
  my $name  = gethostbyaddr($iaddr, AF_INET) || $ip;
189
  # add to cache
190
  $peers{$ip}{'name'} = $name;
191
  return $name;
192
}
193

    
194
# returns the offset, or U if it is undefined
195
sub getpeeroffset() {
196
  my $ip = shift;
197
  my $rtn = 'U';
198
  if (exists($peers{$ip}{'value'})) {
199
    $rtn = $peers{$ip}{'value'};
200
  }
201
  return $rtn
202
}
203

    
204
=pod
205

    
206
=head1 Description
207

    
208
ntp_peers - A munin plugin to monitor offsets to multiple NTP peers and
209
graph them on a single graph
210

    
211
=head1 Parameters understood:
212

    
213
  config   (required)
214
  autoconf (optional - used by munin-node-configure)
215

    
216
=head1 Configuration variables:
217

    
218
All configuration parameters are optional
219

    
220
  ntpq            - path to ntpq program
221
  statedir        - directory in which to place state file
222
  hostname_<key>  - override hostname for peer <key>. <key> is
223
                    an IPv4 address with dots replaced by underscores.
224
                    Useful for reference clocks, eg
225
                    env.hostname_127_127_43_0  .GPS.
226

    
227
=head1 Known issues
228

    
229
ntp_peers will not monitor IPv6 peers
230

    
231
=cut