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

use strict;
use System;
use Getopt::Std;
use Util;
use Util::Http;
use Agent::VE;
use Agent::T3;

my $local_p = $INC[0];
my $ix  = rindex($local_p, "/");
my $DIR = substr($local_p,0,$ix);

use PDM::ConfigFile;

my $GOLDEN = "/var$DIR/DATA/Solution.golden";
my(%opts);
my $LIST   = ",3910,3960,6910,6960,3900SL,6910SL,6960SL,";

my $T3TO = 30;  # timeout getting t3 tokens

sub usage {
   print "\n  config_solution -m <expected model> -i <ip_prefix> -p <ve password> -h\n";
   print "      -h  : help \n";
   print "      -p <password>  : VE password \n";
   print "      -i <ip_prefix>  : enter a different subnet prefix, default is ifconfig for dmfe1\n";
   print "      -m <expected model> \n";
   print "     Example: config_solution -m 6910 -i 192.168.0 \n";
   print "     Models : $LIST \n";
}

if (!getopts("i:m:shp:", \%opts)) {
    print "Invalid arguments \n";
    usage();   
    exit(1);
}

if ($opts{h}) {
   usage();
   exit(1);
}

my $PASS   = $opts{p} || "";

my $PREFIX = $opts{i} || Util->ipPrefix(System->ifconfig("dmfe1"));

my $MODEL  = uc($opts{m});
if (!$MODEL) {
  while (index($LIST, ",$MODEL,") < 0) {
     print "Valid models: $LIST\n" if ($MODEL);
     print "Enter Model (q=quit): ";
     $MODEL = <>;
     chop($MODEL);
     $MODEL = uc($MODEL);
     exit(1) if ($MODEL eq "Q");
  }
}

if (index($LIST, ",$MODEL,") < 0 ) {
   print "Error: Invalid model! \n";
   usage();
   exit(1);
}

open(O, "$DIR/System/config");
my $version = <O>;
$version =~ s/version=//;
close(O);

my $HOME = substr($local_p,0,$ix);
System->set_home($HOME);

if (!open(O,"/etc/hosts")) {
  print "Error: Cannot read /etc/hosts, aborting \n";
  exit(1);
}
my $golden;
my $notifs;
my $hostname = System->hostname();


my $model;
my $devs = "";
my $short = $hostname;
my $ix = index($short, ".");
if ($ix > 0) {
  $short = substr($short,0,$ix);
}
my $err = 0;

my $devcnt = 1;
my($l);
my $sw_ports = 0;
my $sw_cnt   = 0;
my $ve_cnt   = 0;
my $t3_cnt   = 0;
my ($report_sw, $report_t3, $report_ve);


while ($l = <O>) {
  chop($l);
  next if (substr($l,0,1) eq "#");
  my ($ipno, $ip, $rest) = split(/\s+/, $l);
  next if (substr($ipno,0,length($PREFIX) ) ne $PREFIX);

  my $no = substr($ipno,-2);
  print "$ip: \n";
  if ($no >= 20 && $no <= "23") { # vicom
       next if (!&ping($ipno));
       $ve_cnt++;
       my $wwn = Agent::VE->getWWN($ipno, undef, 20, $PASS);
       my $login = ($no <= 21)? "v1":"v2";
       my $init  = ($no == 20 || $no == 22)? "I00001" : "I00002";
       if (length($wwn) > 10) {
         $report_ve .= "$ip, ";
         $golden .= "\n[device$devcnt]\ntype=ve\nclass=switch.ve\nip=$ipno\nipno=$ipno\nname=$short-$ip\nwwn=$wwn\nlogin=$login\ninitiator=$init\n";
         $devcnt++;
         print "  -> found VE ($ip / $ipno / $wwn) \n";

       } else {
         print "  -> Error: cannot find wwn of VEs at $ip/$ipno \n";
         $err++; next;
       }



  } elsif ($no >= 40 && $no <= 54) { # T3
     if (&ping($ipno)) {
        my($key, $wwn1, $wwn2, $ctrl_model) = Agent::T3->getWWN($ipno);
        if (!$key) {
           print "  -> Error: cannot find the serial# of this T3 \n";
        } 
        if (!$wwn1) {
           print "  -> Error: cannot find the wwn of the first port of this T3 \n";
        } 
        if (!$wwn2) {
           print "  -> Error: cannot find the wwn of the second port of this T3 \n";
        } 
        if (!$wwn1) {
           $err++; next;
        } else {
            $report_t3 .= "$ip, ";
            $t3_cnt++;
            $golden .= "\n[device$devcnt]\ntype=t3\nclass=storage.t3\nip=$ipno\nipno=$ipno\nname=$short-$ip\nwwn=$wwn1\nwwn2=$wwn2\nkey=$key\nctrl_model=$ctrl_model\n";
            $devcnt++;
            print "  -> found T3 ($ipno / $wwn1/$wwn2/\n\t\t$key) \n";
        }

     } else {
        print "  -> Warning: cannot ping $ipno \n";
        print "     Device is not responding or not present in this configuration\n";
     }
         
  } elsif ($no >= 30 && $no <= 33) { # switch
     if (&ping($ipno)) {
        my $wwn = &switchWWN($ipno);
        if (!$wwn) {
           print "  -> Error: cannot find the wwn of $ipno \n";
           $err++;
        } else {
            if (!$sw_ports) {
              $sw_ports = &switchPorts($ipno);
              if ($sw_ports != 16 && $sw_ports != 8) {
                  print "  -> switch $ipno, invalid # ports: $sw_ports\n";
                  $err++;
              }
            }
            $report_sw .= "$ip, ";
            $sw_cnt++;
            $golden .= "\n[device$devcnt]\ntype=switch\nclass=switch.switch\nip=$ipno\nipno=$ipno\nname=$short-$ip\nwwn=$wwn\n";
            $devcnt++;
            print "  -> found Switch ($ipno / $wwn) \n";
        }

     } else {
        print "  -> Warning: cannot ping $ipno \n";
     }
  }
}

my ($prefix, $suffix);


if (substr($MODEL,0,2) eq "39" && $ve_cnt > 0) {
  print "  -> Error: Found $ve_cnt ve, but model is $MODEL!\n";
  $err++;
}

if (($MODEL eq "6910" && $ve_cnt != 2) ||
    ($MODEL eq "6960" && $ve_cnt != 4)) { 
  print "  -> Error: Wrong number of VE($ve_cnt) found for $MODEL! \n";
  $err++;
}
if ($t3_cnt == 0) {
  print "  -> Error: No T3 found! \n";
  $err++;
}

if ($sw_ports != 16 && substr($MODEL,2,2) eq "60") {
  print "  -> Error: Model $MODEL need 16 port switches! \n";
  $err++;
}

if ($sw_ports != 8 && substr($MODEL,2,2) eq "10") {
  print "  -> Error: Model $MODEL need 8 port switches! \n";
  $err++;
}
my $sw1 = 2;
my $sw2 = 4;
if ($MODEL =~ /SL/) {
   $sw1 -= 2;
   $sw2 -= 2;
}
if ((substr($MODEL,0,2) eq "39" && $sw_cnt != $sw1) ||
    (substr($MODEL,0,2) eq "69" && $sw_cnt != $sw2)) {
  print "  -> Error: Wrong number of switches ($sw_cnt) for a $MODEL \n";
  $err++;

}

$suffix = "XX";
if ($sw_ports == 16) {
   $suffix = "60";
} elsif ($sw_ports == 8) {
   $suffix = "10";
} elsif ($sw_cnt == 0) {
   $suffix = "00";
}
my $sl;
if ($ve_cnt) {
  $prefix = "69";
  $sl = "SL" if ($sw_cnt == 2);
} else {
  $prefix = "39";
  $sl = "SL" if ($sw_cnt == 0);
}
$model = $prefix . $suffix . $sl;
   
if ($MODEL && $MODEL ne $model) {
   print "ERRORS: Model proposed ($MODEL) is different than discovered model ($model)\n";
   $err++;
}

print "-------------------------------------\n";
print "      Configuration Summary   \n";
print "-------------------------------------\n";
print "|  Model : $model, Requested = $MODEL \n";
print "|  Switch: $sw_cnt * $sw_ports ports  \n";
print "|        : $report_sw\n";
print "|  T3s   : $t3_cnt \n";
print "|        : $report_t3\n";
print "|  VEs   : $ve_cnt \n";
print "|        : $report_ve\n";
print "-------------------------------------\n";

if ($err) {
   print "ERRORS FOUND: Snapshot cannot be saved! \n";
   if (-f $GOLDEN) {
     rename $GOLDEN, "$GOLDEN.last";
   }
   exit(1);

} else {
   print "NO ERRORS FOUND!\n";
   &save_golden();
   print "Snapshot $GOLDEN saved! \n";
} 

print "Done. \n\n";

sub save_golden {
   open(O, ">$GOLDEN");
   print O "#Solution Golden Snapshot\n";
   my $date = Util->get_today();
   print O "created=$date\n";
   print O "created2=" . `date` . "\n";
   print O "model=$model\n";
   print O $golden;
   close(O);
}

sub switchPorts {
  my($ip) = @_;
  my @l = `$DIR/bin/sanbox chassis_status $ip`;
  if ("@l" =~ /Ports:\s+(\d+)/) {
     return $1;
  } else {
     return undef;
  }
}


sub switchWWN {
  my($ip) = @_;

  my @l = `$DIR/bin/sanbox version $ip`;
  if ("@l" =~ /WWN:\s+([0-9a-f]+)/) {
      return $1;
  } else {
      return undef;
  }
}

sub ping {
  my($ip) = @_;

  open(PING, "/usr/sbin/ping $ip 3|");
  my $ans = <PING>; close(PING);
  if ($ans =~ /is alive/) {
     return 1;
  } else {
     return 0;
  }
}


