#!/usr/bin/perl
#
# This script is a component of Warewulf,
# http://www.runlevelzero.net/greg/warewulf
#
#########################################################################
#
# Copyright (c) 2003, The Regents of the University of California, through
# Lawrence Berkeley National Laboratory (subject to receipt of any
# required approvals from the U.S. Dept. of Energy).  All rights reserved.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# The GNU GPL Document can be found at:
# http://www.gnu.org/copyleft/gpl.html
#
#########################################################################
#
# Written and maintained by:
#       Greg Kurtzer, <gmkurtzer@lbl.gov>

BEGIN {
   push (@INC, "/usr/lib/warewulf/");
   push (@INC, "/usr/lib64/warewulf/");
}
use Warewulf;
use Getopt::Long;
use IO::Socket;
use strict;

Getopt::Long::Configure ("bundling");

my (
   $usage,
   $ready,
   $help,
   $mpi,
   $pvm,
   $down,
   $quiet,
   $mine,
   $entry,
   $value,
   $nodename,
   %nodestatus,
   %nodes,
   %master,
   %node_ips,
   $type,
   $out_ready,
   $out_notready,
   %node_access,
   %filter,
   @nodes_ready,
   @nodes_unavailable,
   @nodes_down,
   @nodes_unknown,
   $node_count,
   $banners,
   $i,
   $mastername,
   %config,
   $master,
   %masterinfo,
   $status,
   %nodes,
   $info,
);

$usage = "USAGE: $0 [options] [hostname]
  About:
    wwlist shows a list of the currently running nodes in the cluster. You 
    can use it to make a MPI or PVM machine file, or just get a list of the 
    nodes in the current ready position.
  Options:
   -m, --mpi        Output a MPI compatiable file for the node list
   -p, --pvm        Output a PVM compatiable file for the node list
   -s, --status     Only show nodes matching a particular status:
                     ready, down, unavailable, unknown
   -i, --info       Show node configuration information from config:
                     desc, vnfs, group name, user names
   -r, --ready      Only show nodes that are ready (shortcut for -s ready)
   -d, --down       Only show nodes that are _NOT_ ready (shortcut again)
   -q, --quiet      Only show nodes that are up with no extra verbage
   -h, --help       Show this banner

  This tool is part of the Warewulf cluster distribution
     http://warewulf-cluster.org/
";

GetOptions(
   'quiet|q'     => \$quiet,
   's|status=s'  => \$status,
   'mpi|m'       => \$mpi,
   'pvm|p'       => \$pvm,
   'ready|r'     => \$ready,
   'down|d'      => \$down,
   'i|info=s'    => \$info,
   'help|h'      => \$help,
);

if ( $ready ) {
   $status = "ready";
}
if ( $down ) {
   $status = "(down|unknown|unavailable)";
}

if ( $help ) {
   print $usage;
   exit;
}

if ( $quiet ) {
   # clean up output
   $banners = '1';
}

if ( $mpi and $pvm ) {
   die "You selected options that should not be mixed!\n" ;
}

%config = &client_conf();
if ( $ARGV[0] ) {
   $master = $ARGV[0];
} else {
   $master = $config{'warewulf master'};
}
%nodestatus = &node_status($master);
%filter = &users_filter();

if ( -f "/etc/warewulf/nodes.conf" ) {
   %nodes = &node_info();
}


if ( $mpi ) {
   chomp (my $master_hostname = `hostname`);
   print "# Master node\n";
   print "$master_hostname cpu=1\n\n";
} elsif ( $pvm ) {
   chomp (my $master_hostname = `hostname`);
   print "# Master node\n";
   print "$master_hostname\n\n";
}


foreach ( sort keys %nodestatus ) {
   if ( ! $filter{$_} and defined %filter ) {
      next;
   }
   if ( $nodestatus{$_}{NODESTATUS} eq 'READY' ) {
      push(@nodes_ready, $_);
   } elsif ( $nodestatus{$_}{NODESTATUS} eq 'DOWN' ) {
      push(@nodes_down, $_);
   } elsif ( $nodestatus{$_}{NODESTATUS} eq 'unavailable' ) {
      push(@nodes_unavailable, $_);
   } else {
      push(@nodes_unknown, $_);
   }
   $node_count++;
}

if ( @nodes_ready and ( ! $status or "ready" =~ /$status/i ) ) {
   print "# Nodes ready:\n" unless $banners;
   foreach (sort @nodes_ready ) {
      if ( $mpi ) {
         print "$_ cpu=$nodestatus{$_}{CPUCOUNT}\n";
      } elsif ( $pvm ) {
         for ($i=0; $i<=$nodestatus{$_}{CPUCOUNT}; $i++) {
            print "$_\n";
         }
      } else {
         if ( $info ) {
            print "$_\t", $nodes{$_}{$info}, "\n";
	 } else {
            print "$_\n";
	 }
      }
   }
   print "\n" unless $banners;
}
if ( @nodes_unavailable and ( ! $status or "unavailable" =~ /$status/i ) ) {
   print "# Nodes unavailable:\n" unless $banners;
   foreach (sort @nodes_unavailable ) {
      if ( $mpi or $pvm ) {
         print "#$_\n";
      } else {
         if ( $info ) {
            print "$_\t", $nodes{$_}{$info}, "\n";
	 } else {
            print "$_\n";
	 }
      }
   }
   print "\n" unless $banners;
}
if ( @nodes_down and ( ! $status or "down" =~ /$status/i ) ) {
   print "# Nodes down:\n" unless $banners;
   foreach (sort @nodes_down ) {
      if ( $mpi or $pvm ) {
         print "#$_\n";
      } else {
         if ( $info ) {
            print "$_\t", $nodes{$_}{$info}, "\n";
	 } else {
            print "$_\n";
	 }
      }
   }
   print "\n" unless $banners;
}
if ( @nodes_unknown and ( ! $status or "unknown" =~ /$status/i ) ) {
   print "# Nodes in unknown state:\n" unless $banners;
   foreach (sort @nodes_unknown ) {
      if ( $mpi or $pvm ) {
         print "#$_\n";
      } else {
         if ( $info ) {
            print "$_\t", $nodes{$_}{$info}, "\n";
	 } else {
            print "$_\n";
	 }
      }
   }
   print "\n" unless $banners;
}

exit;
