#!/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>

use lib "/usr/lib/warewulf/", "/usr/lib64/warewulf/";
use Warewulf::Config;
use Getopt::Long;
use File::Path;
use IO::Socket;
use Net::hostent;

#use strict;

my %nodes;
my (
   $help,
   $dump,
   $dhcpd_template,
   $vnfs,
   $default,
   $debug,
);

my $usage = "USAGE: $0 [options]
  About:
    Management tool used to facilitate maintaince of the warewulf nodes

  Options:
    --info [node]   Display information about the node designation or nodename
    --sync/update   Update the node's user accounts, and node access rules
      --nonodes     Build the sync files, but don't do the actual node sync
    --help          Show this banner

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

GetOptions(
   'help'      => \$help,
   'sync'      => \$node_sync,
   'update'    => \$node_sync,
   'nonodes'   => \$node_sync_not,
   'info=s'    => \$get_node_info,
   'debug'     => \$debug
);

if ( $add_node_opts and $node_scan ) {
   die "Don't use --opts with --name options. Remove the --scan. ;)\n";
}

$| = '1';


$PORT = 9875;                  # pick something not in use

%group_info = &group_config();

if ( ! $group_info{"$add2_group"} and $add2_group ) {
   die "GROUP: $add2_group is not configured!\n";
}

sub gen_syncs {
   my %groups = &group_config();
   @scripts = glob("/usr/lib/warewulf/modules/sync_*");
   foreach $group ( keys %groups ) {
      $created = ();
      print "Generating syncs for [$group]\n";
      mkpath("/srv/vnfs/$groups{$group}{'vnfs'}/");
      foreach $module ( @scripts ) {
         chomp ($tmpdir = `$module $group`)
            or die "ERROR: Could not execute sync module: $module!\n";
         if ( ! $created ) {
            system("cd $tmpdir; tar -cf /srv/vnfs/$groups{$group}{'vnfs'}/synctree.tar . 2>/dev/null");
         } else {
            system("cd $tmpdir; tar -rf /srv/vnfs/$groups{$group}{'vnfs'}/synctree.tar . 2>/dev/null");
         }
         $created = "1";
         system("rm -rf $tmpdir");
      }
      system("gzip -9 -f /srv/vnfs/$groups{$group}{'vnfs'}/synctree.tar 2>/dev/null");
   }

}

sub sync_nodes {
   my %nodestatus = &node_status();
   my %nodes = &node_config();
   my %master = &master_config();
   foreach $node ( sort keys %nodes ) {
      #next if ( $nodes{$node}{"designation"} ne $node );
      if ( $nodestatus{$node}{'NODESTATUS'} eq 'READY' ) {
         $debug and warn "spawning update command on $node/$node:$nodes{$node}{'admin ipaddr'}\n";
         system("$master{'network'}{'rsh command'} $nodes{$node}{'admin ipaddr'} /wwtools/syncnode");
      } elsif ( $nodestatus{$node}{'NODESTATUS'} eq 'unavailable' ) {
         $debug and warn "spawning update command on $node/$node:$nodes{$node}{'admin ipaddr'}\n";
         system("$master{'network'}{'rsh command'} $nodes{$node}{'admin ipaddr'} /wwtools/syncnode");
      } elsif ( $nodestatus{$node}{'NODESTATUS'} eq 'ERROR' ) {
         $debug and warn "spawning update command on $node/$node:$nodes{$node}{'admin ipaddr'}\n";
         system("$master{'network'}{'rsh command'} $nodes{$node}{'admin ipaddr'} /wwtools/syncnode");
      } else {
         print "   $node: skipping, node down!\n";
      }
   }
}

sub show_node_info {
   my ( $node, @NULL ) = @_;
   my %nodestatus = &node_status();
   my %nodes = &node_config();
   my %master = &master_config();
   if ( ! $nodes{$node} ) {
      die "That node is not configured!\n";
   }
   print "\n                       === NODE CONFIGIRATION ===\n\n";
   printf("   Node name: %-20.20s\n", $node);
   printf(" Description: %-66.66s\n", $nodes{$node}{"group desc"});
   printf("  Node group: %-20.20s             VNFS: %-20.20s\n", 
         $nodes{$node}{"group"}, $nodes{$node}{"vnfs"});
   printf("      Kernel: %-20.20s         wwinitrd: %-20.20s\n", 
         $nodes{$node}{"kernel image"}, $nodes{$node}{"wwinitrd image"});
   printf("    Boot MAC: %s       Secondary MAC: %-20.20s\n", 
         $nodes{$node}{"hardware addr"}, $nodes{$node}{"hardware addr2"});
   printf("       Users: %-66.66s\n", $nodes{$node}{"user names"});
   printf(" User Groups: %-66.66s\n", $nodes{$node}{"user groups"});
   print "\n                      === NETWORK CONFIGURATION ===\n\n";
   printf("   Admin dev: %-5s         Admin address: %s/%s\n",
         $nodes{$node}{"admin device"}, $nodes{$node}{'admin ipaddr'},
         $master{"network"}{"admin netmask"});
   printf("     SFS dev: %-5s           SFS address: %s/%s\n",
         $nodes{$node}{"sharedfs device"}, $nodes{$node}{'sharedfs ipaddr'},
         $master{"network"}{"sharedfs netmask"});
   printf(" Cluster dev: %-5s       Cluster address: %s/%s\n",
         $nodes{$node}{"cluster device"}, $nodes{$node}{'cluster ipaddr'},
         $master{"network"}{"cluster netmask"});

   if ( ! $nodestatus{$node} or $nodestatus{$node}{"LASTCONTACT"} eq "never" ) {
      print "\n$node has not checked in with warewulfd yet!\n\n";
      exit;
   } else {
      if ( $nodestatus{$node}{"NODESTATUS"} ne "READY" ) {
         print "\n              === NODE HAS BEEN UNREACHABLE FOR $nodestatus{$node}{LASTCONTACT} seconds===\n";
         print "                content displayed is from last known state\n\n";
      } else {
         print "\n                       === CURRENT NODE STATS ===\n\n";
      }
      printf(" Kernel Version: %-20.20s                     ARCH: %8.15s\n",
            $nodestatus{$node}{"RELEASE"}, $nodestatus{$node}{"MACHINE"});
      printf("       Load Avg:     %2.2f    Processes:       %-6.6s    Uptime: %7dh\n",
            $nodestatus{$node}{"LOADAVG"}, $nodestatus{$node}{"PROCS"}, $nodestatus{$node}{"UPTIME"}*24);
      printf("       CPU Util: %7.5s%%    CPU COUNT:   %6.6s     CPU CLOCK:  %7.7s\n",
            $nodestatus{$node}{"CPUUTIL"}, $nodestatus{$node}{"CPUCOUNT"}, $nodestatus{$node}{"CPUCLOCK"});
      printf("       MEM Util: %7.5s%%     MEM USED: %7.7sM     MEM Avail: %7.7sM\n",
            $nodestatus{$node}{"MEMPERCENT"}, $nodestatus{$node}{"MEMUSED"}, $nodestatus{$node}{"MEMAVAIL"});
      printf("      SWAP Util: %7.5s%%    SWAP USED: %7.7sM    SWAP Avail: %7.7sM\n",
            $nodestatus{$node}{"SWAPPERCENT"}, $nodestatus{$node}{"SWAPUSED"}, $nodestatus{$node}{"SWAPAVAIL"});
      printf("   IP Transmits:  %7.10s                          IP Recieves:  %7.10s\n",
            $nodestatus{$node}{"NETTRANSMIT"}, $nodestatus{$node}{"NETRECIEVE"});



   }

}

if ( $node_add ) {
   &pxe_update(0);
   &node_add();
} elsif ( $node_sync ) {
   &gen_syncs();
   if ( ! $node_sync_not ) {
      &sync_nodes();
   }
} elsif ( $get_node_info ) {
   &show_node_info($get_node_info);
} else {
   print "$usage\n";
}

