#!/opt/SUNWstade/bin/perl -I/opt/SUNWstade/lib
#<copyright>
# ----------------------------------------------------------
# Sun Proprietary/Confidential Code
# Copyright 2001, Sun Microsystems, Inc. All rights reserved.
# ----------------------------------------------------------
#</copyright>

use System;
use POSIX ":sys_wait_h";
use Util;
use PDM::ConfigFile;
use Modules;
use Getopt::Std;
use strict;
use Process;
use InstallVerify;
use Data::Dumper;


#
# runs locally, started from the GUI.
#
my(%opts);

sub usage {
  print <<EOF;
Usage: $0   -s [status] 
                    -h <hostname>     will run $0 on this host
                    -M <module_list|ALL> 
                    -e <email|email|etc> 
                    -b [background, default is foreground] 
                    -l [display valid modules] 
                    -T [minutes to run, default is to run forever]
                    -N [number of tests instances to start per device type]
                    -p [print results of last run or check status of test]
EOF
}

if (!getopts("Ppblse:h:M:T:N:", \%opts)) {
    usage();
    exit(1);
}

System->set_rasport("7654");
System->set_home(System->home_dir());
my($renv, $devs, $hosts,$notifs) = PDM::ConfigFile->read;
System->set_renv($renv);

my $program_name = $0;
my $MODULES = $opts{M};
my $NUMIO = $opts{N};
my $EMAIL   = $opts{e};
my $PRINTERR = $opts{P};
my $ID      = "Install_Verify";
my $REPORTS;
my $ENDTIME;
my @CHILDREN;
my @VERIFYERS;

if($opts{N}){$NUMIO = $opts{N};}
else{$NUMIO=0;}

if($opts{T}) {$ENDTIME = ($opts{T}*60)+time+30 ;}
elsif($opts{T}==0) {undef($ENDTIME);}

if ($opts{l}) {
   &modules_list();
   exit;
}

if ($opts{s}) {
   my $st = Process->status($opts{h}, $ID);
   print "$st \n";
   exit;
}

if ($opts{p} || $opts{P}) {
  if ($opts{M}) {
    my $st = Process->status($opts{h}, $ID);
    if ($st =~ /^Done/){
       &printit($opts{h}, $ID, $opts{P});
    }elsif ($st =~ /^Running/){
       print "$0 is currently running.\n";
    }elsif ($st =~ /^Died/){
       print "$0 was aborted.\n";
       &printit($opts{h}, $ID, $opts{P});
    }
  }else{
    print "To print results of last run a module must be specified.\n"; 
    usage();
  }
  exit;
}

if( (!$opts{b}) && ($opts{h}) ){
  print "Unable to run $0 remotely in foreground.\n"; 
  print "Run $0 again with -b option\n"; 
  usage();
  exit 1;
}

if( (!$opts{T}) && ($opts{b}) ){
  print "Unable to run $0 in background with out a time limit.\n"; 
  print "Run $0 again with -T option\n"; 
  usage();
  exit 1;
}
  
my $done = 0;
if ($opts{M}) {
  my $st = Process->status($opts{h}, $ID);
  if ($st =~ /Running/) {
     print "$program_name already running!\n";
     exit(1);
  }
  my $opts = "-M \"$MODULES\" " if ($MODULES);
  $opts   .= "-e \"$EMAIL\" "   if ($EMAIL);
  $opts   .= "-T \"$opts{T}\" "   if ($opts{T});
  $opts   .= "-N \"$opts{N}\" "   if ($opts{N});
  my $TR=Process->run($opts{h},"Diags/bin/stresstest $opts", \&run, !$opts{b});
  $done = 1;
}

if (!$opts{b} ) {
  &printit($opts{h}, $ID, $opts{P});
}

if (!$done) {
  usage();
  exit(1);
}

sub modules_list {
  my $mods   = Modules->load("InstallVerify");
  print "Modules: \n";
  foreach my $x (@$mods) {
       print "$x|";
  }
  print "\n";
}

sub run {
  local $SIG{INT} = \&Stop;
  my $LOG    = System->get_home() . "/DATA/tmp/${ID}_log";
   
  Process->start($ID);
   
  my $include;
  unlink $LOG;
  my @M = split(/\|/, $MODULES);
  $MODULES =~ s/\s+//g;

  if ( !1 ) {
    open(O, ">>$LOG"); print O "$program_name is  done\n"; close(O);
    $include = "";
  }else{ 
    my $mods   = Modules->load("InstallVerify");
    my $match = 0;
    foreach my $x (@$mods) {
      if ($MODULES eq "ALL" || index(lc("|$MODULES|"), lc("|$x|")) >= 0) {
        $include .= " $x|";
        my $mod = "InstallVerify::$x";
        my $modInstance = $mod->new();
        push(@VERIFYERS, $modInstance) if($modInstance->canRun());
      }
    }
    TO->readTopo();
    foreach my $verification (@VERIFYERS) {
      if(my $pid=fork){#we are the parental
        push(@CHILDREN, $pid);
        next;
      }else{#We are the children, we are the world 
        my $db = $verification->RUN($NUMIO);
        exit;
      } 
    }
  } 
  my $report;
  my $result;
  while(!defined($ENDTIME) || time < $ENDTIME){
    sleep 1; #Nighty Night
    my $numrunning=0;
    foreach my $x (@VERIFYERS) {
      if($x->isRunning()){
        $numrunning++;
      }
    } #<\foreach>
    last if($numrunning == 0);
    sleep 1;
  } #<\while>
  my $textReport = StopIO_And_Generate_Report();
if ($EMAIL) {
  &emailit($opts{h}, $ID, $opts{P});
}
  return $textReport;
}

sub printit {
  my($host, $ID, $error_only) = @_;
  my $R = Process->read($host, $ID);
  print &textReport($R, $error_only);
}

sub emailit{
  my($host, $ID, $error_only) = @_;
  my $R = Process->read($host, $ID);
  my $text_report = textReport($R, $error_only);
  my $mailer = $renv->{mailer} || "/usr/bin/mail ";
  my($acronym) = $renv->{GSV_ACRONYM};
  my @emails= split(/\|/, $EMAIL);
  
  foreach my $email (@emails){
    Util->run_command("$mailer $email", "mail", 10,
           { data => "From: $renv->{GSV_ACRONYM}\n".
                     "Subject: Stress Test Report\n\n" .
                     "Run on $renv->{hostname} \n\n$text_report"});
  }
}

sub textReport {
  my($report, $error_only) = @_;
  my $title;
  my $result;
  my $mods;
  if($#VERIFYERS<0) {
    $mods   = Modules->load("InstallVerify");
    foreach my $mod (@$mods) {
      $mod = "InstallVerify::$mod";
    }
  }else{
    foreach my $vers (@VERIFYERS) {
      push(@$mods, ref($vers)); 
    }
  }
  foreach my $mod (@$mods) {
      my $R = Process->read($opts{h}, $mod);
      $result .=$mod->report($R);
  } 
  return "$title\n$result\n";
}

sub Stop{
  StopIO_And_Generate_Report();
}

sub StopIO_And_Generate_Report{
  $SIG{CHLD}= \&REAPER;        # keep the kids in thier graves
  foreach my $pid (@CHILDREN){ #Time to kill the kids.... redrum.. redrum..
    kill INT => $pid;
  }
  FOREVER:while(defined(@VERIFYERS)){
    my $numrunning =0;
    foreach my $x (@VERIFYERS) {
      if(!$x->isRunning()){
        $REPORTS->{$x->{TYPE}}=$x->report();
      }else{
        sleep 1;
        $numrunning++;
      }
    }
    if($numrunning == 0){
      last FOREVER;
    }
  }
  $REPORTS->{end_time}=time;
  Process->write($REPORTS, $ID);
  Process->done($ID);
  my $text_report = &textReport($REPORTS);
  return $text_report; 
}

sub REAPER{      # send the kids to thier graves
  my $corpse;
  while (($corpse = waitpid(-1, &WNOHANG))>0){
  }
}



