xcat-core/xCAT-server/lib/xcat/plugins/nodestat.pm
2009-04-04 01:19:06 +00:00

204 lines
5.0 KiB
Perl

package xCAT_plugin::nodestat;
use strict;
use warnings;
use Socket;
use IO::Handle;
use Getopt::Long;
my $stat;
my %portservices;
sub handled_commands {
return {
nodestat => 'nodestat',
};
}
sub installer_query {
my $node = shift;
my $destport = 3001;
my $socket;
my $text = "";
my $proto = getprotobyname('tcp');
socket($socket,PF_INET,SOCK_STREAM,$proto) || return 0;
my $addr = gethostbyname($node);
my $sin = sockaddr_in($destport,$addr);
connect($socket,$sin) || return 0;
print $socket "stat \n";
$socket->flush;
while (<$socket>) {
$text.=$_;
}
$text =~ s/\n.*//;
return $text;
close($socket);
}
sub getstat {
my $response = shift;
$stat = $response->{node}->[0]->{data}->[0];
}
#-------------------------------------------------------
=head3 preprocess_request
Check and setup for hierarchy
=cut
#-------------------------------------------------------
sub preprocess_request
{
my $req = shift;
my $cb = shift;
my %sn;
if ($req->{_xcatdest}) { return [$req]; } #exit if preprocessed
my $nodes = $req->{node};
my $service = "xcat";
my @requests;
if ($nodes){
# find service nodes for requested nodes
# build an individual request for each service node
my $sn = xCAT::Utils->get_ServiceNode($nodes, $service, "MN");
# build each request for each service node
foreach my $snkey (keys %$sn)
{
my $reqcopy = {%$req};
$reqcopy->{node} = $sn->{$snkey};
$reqcopy->{'_xcatdest'} = $snkey;
push @requests, $reqcopy;
}
}
else
{ # non node options like -h
@ARGV=();
my $args=$req->{arg};
if ($args) {
@ARGV = @{$args};
} else {
&usage($cb);
return(1);
}
# parse the options
Getopt::Long::Configure("posix_default");
Getopt::Long::Configure("no_gnu_compat");
Getopt::Long::Configure("bundling");
if (!GetOptions(
'h|help' => \$::HELP,
'v|version' => \$::VERSION))
{
&usage($cb);
return(1);
}
if ($::HELP) {
&usage($cb);
return(0);
}
if ($::VERSION) {
my $version = xCAT::Utils->Version();
my $rsp={};
$rsp->{data}->[0] = "$version";
xCAT::MsgUtils->message("I", $rsp, $cb);
return(0);
}
}
return \@requests;
return 0;
}
sub process_request {
my $request = shift;
my $callback = shift;
my $doreq = shift;
%portservices = (
'22' => 'ssh',
'15002' => 'pbs',
'8002' => 'xend',
);
my @livenodes;
my @nodes = @{$request->{node}};
my %unknownnodes;
foreach (@nodes) {
$unknownnodes{$_}=1;
my $packed_ip = undef;
$packed_ip = gethostbyname($_);
if( !defined $packed_ip) {
my %rsp;
$rsp{name}=[$_];
$rsp{data} = [ "Please make sure $_ exists in /etc/hosts or DNS" ];
$callback->({node=>[\%rsp]});
}
}
my $node;
my $fping;
my $ports = join ',',keys %portservices;
my %deadnodes;
foreach (@nodes) {
$deadnodes{$_}=1;
}
open($fping,"nmap -p $ports ".join(' ',@nodes). " 2> /dev/null|") or die("Can't start nmap: $!");
my $currnode='';
my $port;
my $state;
my %states;
my %rsp;
while (<$fping>) {
if (/Interesting ports on ([^ ]*) /) {
$currnode=$1;
unless ($deadnodes{$1}) {
foreach (keys %deadnodes) {
if ($currnode =~ /^$_\./) {
$currnode = $_;
last;
}
}
}
delete $deadnodes{$currnode};
} elsif ($currnode) {
if (/^MAC/) {
$rsp{name}=[$currnode];
my $status = join ',',sort keys %states ;
unless ($status or $status = installer_query($currnode)) { #pingable, but no *clue* as to what the state may be
$doreq->({command=>['nodeset'],
node=>[$currnode],
arg=>['stat']},
\&getstat);
$status= 'ping '.$stat;
}
$rsp{data} = [ $status ];
$callback->({node=>[\%rsp]});
$currnode="";
%states=();
next;
}
if (/^PORT/) { next; }
($port,$state) = split;
if ($port =~ /^(\d*)\// and $state eq 'open') {
$states{$portservices{$1}}=1;
}
}
}
foreach $currnode (sort keys %deadnodes) {
$rsp{name}=[$currnode];
$rsp{data} = [ 'noping' ];
$callback->({node=>[\%rsp]});
}
}
sub usage
{
my $cb=shift;
my $rsp={};
$rsp->{data}->[0]= "Usage:";
$rsp->{data}->[1]= " nodestat [noderange]";
$rsp->{data}->[2]= " nodestat [-h|--help|-v|--version]";
xCAT::MsgUtils->message("I", $rsp, $cb);
}
1;