- fixed bugs 2855348 and 2860171

- added summary of results to ppping output
- added ppping support for multiple interfaces

git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@4161 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
This commit is contained in:
bp-sawyers 2009-09-17 18:23:42 +00:00
parent 97a32bf634
commit 83b000bf68
5 changed files with 247 additions and 125 deletions

View File

@ -8,29 +8,53 @@ BEGIN
{
$::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : -d '/opt/xcat' ? '/opt/xcat' : '/usr';
}
use strict;
use lib "$::XCATROOT/lib/perl";
use xCAT::Utils;
use POSIX qw(:signal_h :errno_h :sys_wait_h);
use IO::Socket::SSL;
use XML::Simple;
$XML::Simple::PREFERRED_PARSER='XML::Parser';
use Data::Dumper;
use IO::Handle;
use IO::Select;
use xCAT::Utils;
use Getopt::Long;
my $USAGE="Usage: pping [-i|--interface interface] noderange
pping -h|--help
pping -v|--version\n";
my $interface;
GetOptions("interface=s" => \$interface);
if(!GetOptions(
'h|help' => \$::HELP,
'v|version' => \$::VERSION,
'X|noexpand' => \$::NOEXPAND,
'interface=s' => \$interface))
{
print "$USAGE";
exit 1;
}
if ($::HELP) { print "$USAGE"; exit 0}
if ($::VERSION) {print xCAT::Utils->Version() . "\n"; exit 0}
my $xcathost='localhost:3001';
if ($ENV{XCATHOST}) {
$xcathost=$ENV{XCATHOST};
}
unless (@ARGV) {
print "Usage: pping [-i suffix] <noderange>\n";
print "$USAGE";
exit(1);
}
my $noderange = $ARGV[0];
my $client = IO::Socket::SSL->new(
my @nodes=();
if ($::NOEXPAND) { # this is when ppping is calling us and has already expanded the noderange
@nodes = split(/,/, $noderange);
}
else { # the normal case of the user running the cmd - expand the noderange using xcatd
my $client = IO::Socket::SSL->new(
PeerAddr=>$xcathost,
SSL_key_file=> xCAT::Utils->getHomeDir()."/.xcat/client-cred.pem",
SSL_cert_file=> xCAT::Utils->getHomeDir()."/.xcat/client-cred.pem",
@ -38,34 +62,39 @@ my $client = IO::Socket::SSL->new(
SSL_use_cert => 1,
#SSL_verify_mode => 1,
);
die "Connection failure: $!\n" unless ($client);
my %cmdref = (command => 'noderange', noderange => $noderange);
$SIG{ALRM} = sub { die "No response getting noderange" };
alarm(15);
print $client XMLout(\%cmdref,RootName=>'xcatrequest', NoAttr=>1, KeyAttr => []);
alarm(15);
my $response="";
my @nodes=();
while (<$client>) {
alarm(0);
$response .= $_;
if ($response =~ m/<\/xcatresponse>/) {
$rsp=XMLin($response, ForceArray => ['node']);
$response='';
if ($rsp->{warning}) {
printf "Warning: ".$rsp->{warning}."\n";
}
if ($rsp->{error}) {
die ("ERROR: ".$rsp->{error}."\n");
} elsif ($rsp->{node}) {
@nodes=@{$rsp->{node}};
}
if ($rsp->{serverdone}) {
last;
}
}
die "Connection failure: $!\n" unless ($client);
my %cmdref = (command => 'noderange', noderange => $noderange);
$SIG{ALRM} = sub { die "No response getting noderange" };
alarm(15);
print $client XMLout(\%cmdref,RootName=>'xcatrequest', NoAttr=>1, KeyAttr => []);
alarm(15);
my $response="";
while (<$client>) {
alarm(0);
$response .= $_;
if ($response =~ m/<\/xcatresponse>/) {
my $rsp=XMLin($response, ForceArray => ['node']);
$response='';
if ($rsp->{warning}) {
printf "Warning: ".$rsp->{warning}."\n";
}
if ($rsp->{error}) {
die ("ERROR: ".$rsp->{error}."\n");
} elsif ($rsp->{node}) {
@nodes=@{$rsp->{node}};
}
if ($rsp->{serverdone}) {
last;
}
}
}
close($client);
} # end of else that expands the noderange using xcatd
unless (scalar(@nodes)) {
exit 1;
}
close($client);
my $children = 0;
my $inputs = new IO::Select;
$SIG{CHLD} = sub { while (waitpid(-1,WNOHANG) > 0) { $children--; } };
@ -75,10 +104,6 @@ if ($interface) {
}
}
#exec "fping ".join(' ',@nodes). " 2> /dev/null";
unless (scalar(@nodes)) {
exit;
}
if (-x '/usr/bin/nmap' or -x '/usr/local/bin/nmap') {
nmap_pping();
exit;

View File

@ -14,8 +14,11 @@ BEGIN
# XCATROOT must be set for this script to work
$::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat';
}
use strict;
use lib "$::XCATROOT/lib/perl";
use xCAT::Utils;
use POSIX qw(:signal_h :errno_h :sys_wait_h);
use IO::Socket::SSL;
use XML::Simple;
if ($^O =~ /^linux/i) {
@ -24,25 +27,22 @@ if ($^O =~ /^linux/i) {
use Data::Dumper;
use IO::Handle;
use IO::Select;
use xCAT::Utils;
use Getopt::Long;
my $interface;
my $DEBUG = 0;
my $VERBOSE = 0;
my $HIERARCHY = 0;
my $USAGE="Usage: ppping [-i|--interface interface] [-d|--debug] [-v|--verbose] [-s|--serial] noderange
my $USAGE="Usage: ppping [-i|--interface interfaces] [-d|--debug] [-V|--verbose] [-q|--quiet] [-s|--serial] [-H|--hierarchical] noderange
ppping -h|--help
ppping -V|--version\n";
ppping -v|--version\n";
# Parse the options
if(!GetOptions(
'h|help' => \$::HELP,
'v|version' => \$::VERSION,
's|serial' => \$::SERIAL,
'd|debug' => \$DEBUG,
'V|verbose' => \$VERBOSE,
'H|hierarchical' => \$HIERARCHY,
'd|debug' => \$::DEBUG,
'V|verbose' => \$::VERBOSE,
'H|hierarchical' => \$::HIERARCHY,
'q|quiet' => \$::QUIET,
'interface=s' => \$interface))
{
print "$USAGE";
@ -54,8 +54,8 @@ if ($::VERSION) {print xCAT::Utils->Version() . "\n"; exit 0}
# A method to prefix and print debug information only if it is wanted.
sub debug {
$debug_text = shift;
if($DEBUG){
my $debug_text = shift;
if($::DEBUG){
print("---$debug_text");
}
}
@ -98,7 +98,7 @@ while (<$client>) {
alarm(0);
$response .= $_;
if ($response =~ m/<\/xcatresponse>/) {
$rsp=XMLin($response, ForceArray => ['node']);
my $rsp=XMLin($response, ForceArray => ['node']);
$response='';
if ($rsp->{warning}) {
printf "Warning: ".$rsp->{warning}."\n";
@ -117,30 +117,35 @@ close($client);
debug("[stop] - recieve nodes from xcatd\n");
debug("\@nodes LENGTH:" . scalar @nodes . "\n");
unless (scalar(@nodes)) {
exit 1;
}
my $children = 0;
my $inputs = new IO::Select;
$SIG{CHLD} = sub { while (waitpid(-1,WNOHANG) > 0) { $children--; } };
unless (scalar(@nodes)) {
exit;
}
## Use pping to determine which nodes are reachable
my @reachable_nodes=();
my @unreachable_nodes=();
debug("[start] - find unreachable nodes\n");
open (PPING, "$::XCATROOT/bin/pping ".join(',',@nodes). " 2> /dev/null|") or die("Cannot open pping-internal pipe: $!");
my $cmd = "$::XCATROOT/bin/pping ".join(',',@nodes). " --noexpand 2>&1";
debug("Running '$cmd'\n");
open (PPING, "$cmd |") or die("Cannot open ppinginternal pipe: $!");
while (<PPING>) {
if ($_ =~ / ping/) {
my @a_tmp=split(':', $_);
push(@reachable_nodes, $a_tmp[0]);
}
else {
elsif ($_ =~ /noping/) {
my @a_tmp=split(':', $_);
push(@unreachable_nodes, $a_tmp[0]);
}
else { print $_; } # probably an error msg, so just echo it
}
close(PPING);
# this next line seems to always have a non-zero $?, even if pping succeeded...
#if ($?) { die "Error in the pping command used to first test the nodes (exit code=" . ($?>>8) . ").\n"; }
debug("[stop] - find unreachable nodes\n");
## Dispose of the unreachable nodes now
@ -153,54 +158,91 @@ foreach(@unreachable_nodes) {
debug("[start] - deal with reachable nodes\n");
debug("REACHABLE_NODES:@reachable_nodes\n");
if (@reachable_nodes > 0) {
my $allnodes=join(',', @nodes);
if (@reachable_nodes == 0) { exit 1; }
# If verbose is set, take out the quiet flag
my $quiet = "-q";
if($VERBOSE){
$quiet = "";
}
# If hierarchical behavior is wanted, take out the bypass flag
my $bypass = "-B";
if($HIERARCHY){
$bypass = "";
}
my $i_string = "";
if($interface) {
$i_string = "-i $interface";
}
my $allnodes=join(',', @nodes);
# Note: even if verbose is not set, we still do not want to set the quiet flag because we want
# to count the pings that come back, unless they request fully quiet mode.
my $quiet = "";
if($::QUIET) { $quiet = "-q "; }
# If hierarchical behavior is wanted, take out the bypass flag
my $bypass = "-B";
if($::HIERARCHY){ $bypass = ""; }
my @interfaces;
if ($interface) { @interfaces = split(/,/, $interface); }
else { $interfaces[0] = ''; }
# Possible todo: this loop runs xdsh pping2 for each interface. An optimization could be to send all
# the interfaces to pping2 at once. But this would mix up all the ping responses and making it
# harder to tell what is going on.
foreach my $interf (@interfaces) {
my $i_string = $interf ? "-i $interf " : '';
## If the serial option was set, pping2 one reachable node at a time.
if ($::SERIAL) {
debug("SERIAL:$::SERIAL\n");
debug("[start] - xdsh to each reachable node\n");
foreach(@reachable_nodes) {
my $result;
my $command = "$::XCATROOT/bin/xdsh $_ $bypass -e $::XCATROOT/sbin/pping2 \"$i_string $quiet $allnodes\" 2>&1";
debug("Running \'$command\'\n");
$result=`$command`;
print "$result";
my $command = "$::XCATROOT/bin/xdsh $_ $bypass -s -e $::XCATROOT/sbin/pping2 \"$i_string$quiet$allnodes\" 2>&1";
debug("Running '$command'\n");
open (PPING2, "$command |") or die("Cannot open xdsh internal pipe: $!");
# Print out the result
my %numpings;
while (<PPING2>) {
output($_, \%numpings, $interf);
}
close(PPING2);
}
debug("[stop] - xdsh to each reachable node\n");
}
## If the serial option was not set, pping2 all the reachable nodes simultaneously.
else {
debug("SERIAL not set.\n");
debug("SERIAL not set.\n");
my $node_string=join(',', @reachable_nodes);
my $command = "$::XCATROOT/bin/xdsh $node_string $bypass -s -e $::XCATROOT/sbin/pping2 \"$i_string $quiet $allnodes\" 2> /dev/null|";
debug("Running \'$command\'\n");
open (PPING2, "$command") or die("Cannot open pping-internal pipe: $!");
# Print out the result
my $command = "$::XCATROOT/bin/xdsh $node_string $bypass -s -e $::XCATROOT/sbin/pping2 \"$i_string$quiet$allnodes\" 2>&1";
debug("Running '$command'\n");
open (PPING2, "$command |") or die("Cannot open xdsh internal pipe: $!");
# Print out the result
my %numpings;
while (<PPING2>) {
print "$_";
output($_, \%numpings, $interf);
}
close(PPING2);
close(PPING2);
}
}
debug("[stop] - deal with reachable nodes\n");
exit 0;
# Process the output if the xdsh pping2 commands
sub output {
my $line = shift;
my $numpings = shift;
my $interface = shift;
if ($line =~ /^\s*$/) { return; } # xdsh had a habit of adding an extra blank line in streaming mode
# In verbose mode we just echo everything. In quiet mode, the only thing that will come back
# from pping2 are the nopings, so we echo everything in that case too.
if ($::VERBOSE || $::QUIET) { print "$line"; return; }
# This is the default case in which pping2 will return both pings and nopings.
# We want to count the pings and display the nopings.
my $node;
if ( ($node) = $line =~ /^(\S+):.+:\s+ping$/) {
if (!($numpings->{$node}==-1)) {
$numpings->{$node}++;
# If we got pings for all the nodes then print success
if ($numpings->{$node} >= scalar(@nodes)) {
my $istr = $interface ? " on interface $interface" : '';
print "$node: pinged all nodes successfully$istr\n";
$numpings->{$node} = -1;
}
}
}
else {
print "$line";
if ( ($node) = $line =~ /^(\S+?):/) { $numpings->{$node} = -1; } # something beside ping, stop counting
}
}

View File

@ -1,11 +1,11 @@
=head1 NAME
B<pping> - parallel ping.
B<pping> - parallel ping the nodes.
=head1 SYNOPSIS
B<pping> [B<-q>] [B<-s>] [B<-i> I<interface>] I<noderange>
B<pping> [B<-i>|B<--interface> I<interface>] I<noderange>
B<pping> [B<-h>|B<--help>]
@ -14,42 +14,56 @@ B<pping> {B<-v>|B<--version>}
=head1 DESCRIPTION
B<pping> is a utility used to ping list of nodes in parallel.See noderange(3).
B<pping> will return an unsorted list of nodes with a ping or noping status. The list is actually sorted by first ping, unless -s is specified.
B<pping> front-ends ping and fping if available.
B<pping> is a utility used to ping a list of nodes in parallel.
B<pping> will return an unsorted list of nodes with a ping or noping status.
B<pping> front-ends nmap and fping if available.
This command does not support the xcatd client/server communication. It must be run on the management node.
=head1 OPTIONS
B<-q> quiet, only show noping nodes
=over 10
B<-s> Ping serially
=item B<-i>|B<--interface> I<interface>
B<-i interface> interface
An interface name that should be pinged instead of the interface represented by the nodename/hostname.
The following name resolution convention is assumed: an interface is reachable by the hostname <nodename>-<interface>. For example,
the ib2 interface on node3 has a hostname of node3-ib2.
B<-h | help> help
=item B<-h>|B<--help>
B<-v | version> version
Show usage information.
=item B<-v>|B<--version>
Display the installed version of xCAT.
=back
=head1 EXAMPLES
pping all
=over 3
blade7: ping
blade8: ping
blade9: ping
devmaster: ping
node4: ping
node2: noping
=item 1.
pping -q all
pping all
node2: noping
blade7: ping
blade8: ping
blade9: ping
devmaster: ping
node4: ping
node2: noping
=item 2.
pping all -i eth1
node2-eth1: noping
=back
=head1 SEE ALSO
L<psh(1)|psh.1>
L<psh(1)|psh.1>, L<noderange(3)|noderange.3>

View File

@ -1,57 +1,98 @@
=head1 NAME
B<ppping> - parallel ping between nodes in cluster.
B<ppping> - parallel ping from nodes to other nodes in the cluster.
=head1 SYNOPSIS
B<ppping> [B<-s>] [B<-i> I<interface>] I<noderange>
B<ppping> [B<-i>|B<--interface> I<interfaces>] [B<-d>|B<--debug>] [B<-V>|B<--verbose>] [B<-q>|B<--quiet>] [B<-s>|B<--serial>] [B<-H>|B<--hierarchical>] I<noderange>
B<ppping> [B<-h>|B<--help>]
B<pping> {B<-v>|B<--version>}
=head1 DESCRIPTION
B<ppping> is a utility used to test ping between nodes in the noderange.
B<ppping> will return an unsorted list of nodes with a noping status.
B<ppping> front-ends ping and fping if available.
B<ppping> is a utility used to test the connectivity between nodes in the noderange using ping.
By default, B<ppping> will return an unsorted list of the node pairs that are not able to ping each other, or a message that all nodes are pingable.
More or less output can be controlled by the -V and -q options.
B<ppping> front-ends B<pping> and B<xdsh>.
This command does not support the xcatd client/server communication. It must be run on the management node.
=head1 OPTIONS
=over 10
B<-s> Ping serially
=item B<-s>
B<-i interface> interface
Ping serially instead of in parallel.
B<-V | verbose> verbose
=item B<-i>|B<--interface> I<interfaces>
B<-H | hierarchical> Allow management node hierarchy
A comma separated list of network interface names that should be pinged instead of the interface represented by the nodename/hostname.
The following name resolution convention is assumed: an interface is reachable by the hostname <nodename>-<interface>. For example,
the ib2 interface on node3 has a hostname of node3-ib2.
B<-d | debug> Print debug information
If more than one interface is specified, each interface will be combined with the nodenames as described above and will be pinged in turn.
B<-h | help> help
=item B<-V>|B<--verbose>
B<-v | version> version
Display verbose output. The result of every ping attempt from every node will be displayed. Without this option, just a summary
of the successful pings are displayed, along with all of the unsuccessful pings.
=item B<-q>|B<--quiet>
Display minimum output: just the unsuccessful pings. This option has the effect that if all pings are successful, nothing is displayed.
But it also has the performance benefit that each node does not have to send successful ping info back to the management node.
=item B<-H>|B<--hierarchical>
Enable B<ppping> to run in hierarchical mode (i.e. through service nodes). By default, B<ppping> does not go through xcatd.
=item B<-d>|B<--debug>
Print debug information.
=item B<-h>|B<--help>
Show usage information.
=item B<-v>|B<--version>
Display the installed version of xCAT.
=back
=head1 EXAMPLES
ppping all
=over 3
blade7: node2: noping
blade8: node2: noping
blade9: node2: noping
devmaster: node2: noping
node2: noping
=item 1.
ppping all -q
blade7: node2: noping
blade8: node2: noping
blade9: node2: noping
devmaster: node2: noping
node2: noping
=item 2.
ppping node1,node2 -i ib0,ib1,ib2,ib3
node1: pinged all nodes successfully on interface ib0
node1: pinged all nodes successfully on interface ib1
node1: pinged all nodes successfully on interface ib2
node1: pinged all nodes successfully on interface ib3
node2: pinged all nodes successfully on interface ib0
node2: pinged all nodes successfully on interface ib1
node2: pinged all nodes successfully on interface ib2
node2: pinged all nodes successfully on interface ib3
=back
=head1 SEE ALSO
L<psh(1)|psh.1>, L<pping(1)|pping.1>

View File

@ -114,5 +114,5 @@ This command is part of the xCAT software product.
=head1 SEE ALSO
rinv(1)
L<rinv(1)|rinv.1>, L<rspconfig(1)|rspconfig.1>