summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Smokeping/probes/NFSping.pm192
1 files changed, 192 insertions, 0 deletions
diff --git a/lib/Smokeping/probes/NFSping.pm b/lib/Smokeping/probes/NFSping.pm
new file mode 100644
index 0000000..778abf3
--- /dev/null
+++ b/lib/Smokeping/probes/NFSping.pm
@@ -0,0 +1,192 @@
+package Smokeping::probes::NFSping;
+
+=head1 301 Moved Permanently
+
+This is a Smokeping probe module. Please use the command
+
+C<smokeping -man Smokeping::probes::NFSping>
+
+to view the documentation or the command
+
+C<smokeping -makepod Smokeping::probes::NFSping>
+
+to generate the POD document.
+
+=cut
+
+use strict;
+use base qw(Smokeping::probes::base);
+use IPC::Open3;
+use Symbol;
+use Carp;
+
+sub pod_hash {
+ return {
+ name => <<DOC,
+Smokeping::probes::NFSping - NFSping Probe for SmokePing
+DOC
+ description => <<DOC,
+Integrates NFSping as a probe into smokeping. The variable B<binary> must
+point to your copy of the NFSping program.
+
+NFSping can be downloaded from:
+
+L<https://github.com/mprovost/NFSping>
+
+In B<blazemode>, NFSping sends one more ping than requested, and discards
+the first RTT value returned as it's likely to be an outlier.
+
+DOC
+ authors => <<'DOC',
+Tobias Oetiker <tobi@oetiker.ch>
+Matt Provost <mprovost@termcap.net>
+DOC
+ }
+}
+
+sub new($$$)
+{
+ my $proto = shift;
+ my $class = ref($proto) || $proto;
+ my $self = $class->SUPER::new(@_);
+
+ # no need for this if we run as a cgi
+ unless ( $ENV{SERVER_SOFTWARE} ) {
+ my $binary = join(" ", $self->binary);
+ my $testhost = $self->testhost;
+ my $return = `$binary -C 1 $testhost 2>&1`;
+ croak "ERROR: nfsping ('$binary -C 1 $testhost') could not be run: $return"
+ if $return =~ m/not found/;
+
+ if ($return =~ m/([0-9.]+)\sms\s+.*\n.*\n.*:\s+([0-9.]+)/ and $1 > 0){
+ $self->{pingfactor} = 1000 * $2/$1;
+ if ($1 != $2){
+ warn "### nfsping seems to report in ", $2/$1, " milliseconds (old version?)";
+ }
+ } else {
+ $self->{pingfactor} = 1000; # Gives us a good-guess default
+ warn "### assuming you are using an nfsping copy reporting in milliseconds\n";
+ }
+ };
+
+ return $self;
+}
+
+sub ProbeDesc{
+ return "NFSping";
+}
+
+# derived class (ie. RemoteNFSping) can override this
+sub binary {
+ my $self = shift;
+ return $self->{properties}{binary};
+}
+
+# derived class (ie. NFSping6) can override this
+sub testhost {
+ return "localhost";
+}
+
+sub ping ($){
+ my $self = shift;
+ # do NOT call superclass ... the ping method MUST be overwriten
+
+ # increment the internal 'rounds' counter
+ $self->increment_rounds_count;
+
+ my %upd;
+ my $inh = gensym;
+ my $outh = gensym;
+ my $errh = gensym;
+ # pinging nothing is pointless
+ return unless @{$self->addresses};
+ my @params = () ;
+ push @params, "-t" . int(1000 * $self->{properties}{timeout}) if $self->{properties}{timeout};
+ push @params, "-i" . int(1000 * $self->{properties}{mininterval});
+ push @params, "-p" . int(1000 * $self->{properties}{hostinterval}) if $self->{properties}{hostinterval};
+
+ my $pings = $self->pings;
+ if (($self->{properties}{blazemode} || '') eq 'true'){
+ $pings++;
+ }
+ my @cmd = (
+ $self->binary,
+ #'-C', $pings, '-q','-B1','-r1',
+ '-C', $pings, '-q',
+ @params,
+ @{$self->addresses});
+ $self->do_debug("Executing @cmd");
+ my $pid = open3($inh,$outh,$errh, @cmd);
+ $self->{rtts}={};
+ while (<$errh>){
+ chomp;
+ $self->do_debug("Got nfsping output: '$_'");
+ next unless /^\S+\s+:\s+[-\d\.]/; #filter out error messages from nfsping
+ my @times = split /\s+/;
+ my $ip = shift @times;
+ next unless ':' eq shift @times; #drop the colon
+ if (($self->{properties}{blazemode} || '') eq 'true'){
+ shift @times;
+ }
+ @times = map {sprintf "%.10e", $_ / $self->{pingfactor}} sort {$a <=> $b} grep /^\d/, @times;
+ map { $self->{rtts}{$_} = [@times] } @{$self->{addrlookup}{$ip}} ;
+ }
+ waitpid $pid,0;
+ close $inh;
+ close $outh;
+ close $errh;
+}
+
+sub probevars {
+ my $class = shift;
+ return $class->_makevars($class->SUPER::probevars, {
+ _mandatory => [ 'binary' ],
+ binary => {
+ _sub => sub {
+ my ($val) = @_;
+ return undef if $ENV{SERVER_SOFTWARE}; # don't check for nfsping presence in cgi mode
+ return "ERROR: NFSping 'binary' does not point to an executable"
+ unless -f $val and -x _;
+ return undef;
+ },
+ _doc => "The location of your nfsping binary.",
+ _example => '/usr/local/bin/nfsping',
+ },
+ blazemode => {
+ _re => '(true|false)',
+ _example => 'true',
+ _doc => "Send an extra ping and then discard the first answer since the first is bound to be an outlier.",
+
+ },
+ timeout => {
+ _re => '(\d*\.)?\d+',
+ _example => 1.5,
+ _doc => <<DOC,
+The nfsping "-t" parameter, but in (possibly fractional) seconds rather than
+milliseconds, for consistency with other Smokeping probes.
+DOC
+ },
+ hostinterval => {
+ _re => '(\d*\.)?\d+',
+ _example => 1.5,
+ _doc => <<DOC,
+The nfsping "-p" parameter, but in (possibly fractional) seconds rather than
+milliseconds, for consistency with other Smokeping probes. This
+parameter sets the time that nfsping waits between successive packets
+to an individual target.
+DOC
+ },
+ mininterval => {
+ _re => '(\d*\.)?\d+',
+ _example => .001,
+ _default => .01,
+ _doc => <<DOC,
+The nfsping "-i" parameter, but in (probably fractional) seconds rather than
+milliseconds, for consistency with other Smokeping probes. This is the
+interval between pings to successive targets.
+DOC
+ },
+ });
+}
+
+1;