commit
This commit is contained in:
207
lib/Smokeping/probes/OpenSSHJunOSPing.pm
Normal file
207
lib/Smokeping/probes/OpenSSHJunOSPing.pm
Normal file
@@ -0,0 +1,207 @@
|
||||
package Smokeping::probes::OpenSSHJunOSPing;
|
||||
|
||||
=head1 301 Moved Permanently
|
||||
|
||||
This is a Smokeping probe module. Please use the command
|
||||
|
||||
C<smokeping -man Smokeping::probes::OpenSSHJunOSPing>
|
||||
|
||||
to view the documentation or the command
|
||||
|
||||
C<smokeping -makepod Smokeping::probes::OpenSSHJunOSPing>
|
||||
|
||||
to generate the POD document.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
|
||||
use base qw(Smokeping::probes::basefork);
|
||||
use Net::OpenSSH;
|
||||
use Carp;
|
||||
|
||||
my $e = "=";
|
||||
sub pod_hash {
|
||||
return {
|
||||
name => <<DOC,
|
||||
Smokeping::probes::OpenSSHJunOSPing - Juniper SSH JunOS Probe for SmokePing
|
||||
DOC
|
||||
description => <<DOC,
|
||||
Connect to Juniper JunOS via OpenSSH to run ping commands.
|
||||
This probe uses the "extended ping" of the Juniper JunOS. You have
|
||||
the option to specify which interface the ping is sourced from as well.
|
||||
DOC
|
||||
notes => <<DOC,
|
||||
${e}head2 JunOS configuration
|
||||
|
||||
The JunOS device should have a username/password configured, as well as
|
||||
the ability to connect to the VTY(s).
|
||||
|
||||
Make sure to connect to the remote host once from the command line as the
|
||||
user who is running smokeping. On the first connect ssh will ask to add the
|
||||
new host to its known_hosts file. This will not happen automatically so the
|
||||
script will fail to login until the ssh key of your juniper box is in the
|
||||
known_hosts file.
|
||||
|
||||
Some JunOS devices have a maximum of 5 VTYs available, so be careful not
|
||||
to hit a limit with the 'forks' variable.
|
||||
|
||||
${e}head2 Requirements
|
||||
|
||||
This module requires the L<Net::OpenSSH> and L<IO::Pty>.
|
||||
DOC
|
||||
authors => <<'DOC',
|
||||
Tobias Oetiker E<lt>tobi@oetiker.chE<gt>
|
||||
|
||||
based on L<Smokeping::probes::TelnetJunOSPing> by S H A N E<lt>shanali@yahoo.comE<gt>.
|
||||
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} ) {
|
||||
$self->{pingfactor} = 1000; # Gives us a good-guess default
|
||||
print "### assuming you are using an JunOS reporting in milliseconds\n";
|
||||
};
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub ProbeDesc($){
|
||||
my $self = shift;
|
||||
my $bytes = $self->{properties}{packetsize};
|
||||
my $ret = "Juniper JunOS - ICMP Echo Pings ($bytes Bytes";
|
||||
if (defined (my $tos = $self->{properties}{tos})){
|
||||
$ret = " tos $tos";
|
||||
}
|
||||
return $ret.")";
|
||||
}
|
||||
|
||||
sub pingone ($$){
|
||||
my $self = shift;
|
||||
my $target = shift;
|
||||
my $source = $target->{vars}{source};
|
||||
my $dest = $target->{vars}{host};
|
||||
my $psource = $target->{vars}{psource};
|
||||
my @output = ();
|
||||
my $login = $target->{vars}{junosuser};
|
||||
my $password = $target->{vars}{junospass};
|
||||
my $bytes = $self->{properties}{packetsize};
|
||||
my $tos = $self->{properties}{tos};
|
||||
my $pings = $self->pings($target);
|
||||
|
||||
# do NOT call superclass ... the ping method MUST be overridden
|
||||
my %upd;
|
||||
my @args = ();
|
||||
|
||||
my $ssh = Net::OpenSSH->new(
|
||||
$source,
|
||||
$login ? ( user => $login ) : (),
|
||||
$password ? ( password => $password ) : (),
|
||||
timeout => 60
|
||||
);
|
||||
if ($ssh->error) {
|
||||
warn "OpenSSHJunOSPing connecting $source: ".$ssh->error."\n";
|
||||
return undef;
|
||||
};
|
||||
my $tosadd = '';
|
||||
if ( defined $tos){
|
||||
$tosadd = " tos $tos";
|
||||
}
|
||||
if ( $psource ) {
|
||||
@output = $ssh->capture("ping $dest count $pings size $bytes source $psource$tosadd");
|
||||
} else {
|
||||
@output = $ssh->capture("ping $dest count $pings size $bytes$tosadd");
|
||||
}
|
||||
$ssh->system("quit");
|
||||
|
||||
my @times = ();
|
||||
for (@output){
|
||||
chomp;
|
||||
/^\d+ bytes from \S+[:,] icmp_seq=\d+ (?:ttl|hlim)=\d+ time=(\d+\.\d+) ms$/ and push @times,$1;
|
||||
}
|
||||
@times = map {sprintf "%.10e", $_ / $self->{pingfactor}} sort {$a <=> $b} @times;
|
||||
return @times;
|
||||
}
|
||||
|
||||
sub probevars {
|
||||
my $class = shift;
|
||||
return $class->_makevars($class->SUPER::probevars, {
|
||||
packetsize => {
|
||||
_doc => <<DOC,
|
||||
The (optional) packetsize option lets you configure the packetsize for
|
||||
the pings sent.
|
||||
DOC
|
||||
_default => 100,
|
||||
_re => '\d+',
|
||||
_sub => sub {
|
||||
my $val = shift;
|
||||
return "ERROR: packetsize must be between 12 and 64000"
|
||||
unless $val >= 12 and $val <= 64000;
|
||||
return undef;
|
||||
},
|
||||
},
|
||||
tos => {
|
||||
_doc => <<DOC,
|
||||
The (optional) type of service for the pings sent.
|
||||
DOC
|
||||
_sub => sub {
|
||||
my $val = shift;
|
||||
return "ERROR: tos must be 0-255"
|
||||
if $val and not ( $val =~ /^\d+$/ and int($val) <= 255);
|
||||
return undef;
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
sub targetvars {
|
||||
my $class = shift;
|
||||
return $class->_makevars($class->SUPER::targetvars, {
|
||||
_mandatory => [ 'junosuser', 'junospass', 'source' ],
|
||||
source => {
|
||||
_doc => <<DOC,
|
||||
The source option specifies the JunOS device that is going to run the ping commands. This
|
||||
address will be used for the ssh connection.
|
||||
DOC
|
||||
_example => "192.168.2.1",
|
||||
},
|
||||
psource => {
|
||||
_doc => <<DOC,
|
||||
The (optional) psource option specifies an alternate IP address or
|
||||
Interface from which you wish to source your pings from. Routers
|
||||
can have many many IP addresses, and interfaces. When you ping from a
|
||||
router you have the ability to choose which interface and/or which IP
|
||||
address the ping is sourced from. Specifying an IP/interface does not
|
||||
necessarily specify the interface from which the ping will leave, but
|
||||
will specify which address the packet(s) appear to come from. If this
|
||||
option is left out the JunOS Device will source the packet automatically
|
||||
based on routing and/or metrics. If this doesn't make sense to you
|
||||
then just leave it out.
|
||||
DOC
|
||||
_example => "192.168.2.129",
|
||||
},
|
||||
junosuser => {
|
||||
_doc => <<DOC,
|
||||
The junosuser option allows you to specify a username that has ping
|
||||
capability on the JunOS Device.
|
||||
DOC
|
||||
_example => 'user',
|
||||
},
|
||||
junospass => {
|
||||
_doc => <<DOC,
|
||||
The junospass option allows you to specify the password for the username
|
||||
specified with the option junosuser.
|
||||
DOC
|
||||
_example => 'password',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
1;
|
||||
Reference in New Issue
Block a user