diff --git a/xCAT-client/bin/pping b/xCAT-client/bin/pping index e75c43692..0c59acf3e 100755 --- a/xCAT-client/bin/pping +++ b/xCAT-client/bin/pping @@ -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] \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; diff --git a/xCAT-client/bin/ppping b/xCAT-client/bin/ppping index f1bcff1d9..a90c34c44 100755 --- a/xCAT-client/bin/ppping +++ b/xCAT-client/bin/ppping @@ -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 () { 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 () { + 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 () { - 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 + } +} diff --git a/xCAT-client/pods/man1/pping.1.pod b/xCAT-client/pods/man1/pping.1.pod index 261024cd3..0df9262c7 100644 --- a/xCAT-client/pods/man1/pping.1.pod +++ b/xCAT-client/pods/man1/pping.1.pod @@ -1,11 +1,11 @@ =head1 NAME -B - parallel ping. +B - parallel ping the nodes. =head1 SYNOPSIS -B [B<-q>] [B<-s>] [B<-i> I] I +B [B<-i>|B<--interface> I] I B [B<-h>|B<--help>] @@ -14,42 +14,56 @@ B {B<-v>|B<--version>} =head1 DESCRIPTION -B is a utility used to ping list of nodes in parallel.See noderange(3). -B 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 front-ends ping and fping if available. +B is a utility used to ping a list of nodes in parallel. +B will return an unsorted list of nodes with a ping or noping status. +B 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 -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 -. 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 +L, L diff --git a/xCAT-client/pods/man1/ppping.1.pod b/xCAT-client/pods/man1/ppping.1.pod index cb5099df0..10683dae5 100644 --- a/xCAT-client/pods/man1/ppping.1.pod +++ b/xCAT-client/pods/man1/ppping.1.pod @@ -1,57 +1,98 @@ =head1 NAME -B - parallel ping between nodes in cluster. +B - parallel ping from nodes to other nodes in the cluster. =head1 SYNOPSIS -B [B<-s>] [B<-i> I] I +B [B<-i>|B<--interface> I] [B<-d>|B<--debug>] [B<-V>|B<--verbose>] [B<-q>|B<--quiet>] [B<-s>|B<--serial>] [B<-H>|B<--hierarchical>] I B [B<-h>|B<--help>] B {B<-v>|B<--version>} - =head1 DESCRIPTION -B is a utility used to test ping between nodes in the noderange. -B will return an unsorted list of nodes with a noping status. -B front-ends ping and fping if available. +B is a utility used to test the connectivity between nodes in the noderange using ping. +By default, B 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 front-ends B and B. 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 -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 -. 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 to run in hierarchical mode (i.e. through service nodes). By default, B 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, L - diff --git a/xCAT-client/pods/man1/rflash.1.pod b/xCAT-client/pods/man1/rflash.1.pod index 50300fb4b..4c85fd14d 100644 --- a/xCAT-client/pods/man1/rflash.1.pod +++ b/xCAT-client/pods/man1/rflash.1.pod @@ -114,5 +114,5 @@ This command is part of the xCAT software product. =head1 SEE ALSO -rinv(1) +L, L