package Inventory;
use strict;
use System;
use Agent::T3;
use Agent::6020;
use Agent::PS;
use Agent::NTC;
use Logic::SWITCH;
use Java::Discovery;

# $Id: Inventory.pm,v 1.46 2006/07/18 17:19:55 mckenney Exp $

use vars qw( $MASER $VMPATH $VM_TO $SYSTEM1HELP );

$MASER = ",6920,6940,"; 
$VMPATH = "/usr/bin/perl -U /opt/se6x20";
$VM_TO  = 2 * 60;
$SYSTEM1HELP = "SystemOneHelp";

sub goldenName {
  return System->get_home() . "/DATA/Inventory.golden";
}

sub log {
  my($class, $text) = @_;
  open(O, ">>" . System->get_home(). "/log/Service.log");
  my $date = Util->get_today();
  print O "$date\t$text\n";
  close(O);
}

sub writeInventory {
   my($inv, $file, $HTML, $skip_vmcfg) = @_;
   $file = $inv->goldenName() if (!$file);
   open(O, ">$file");
   require Data::Dumper;
   $Data::Dumper::Indent = 1;
   print O Data::Dumper::Dumper($inv);
   close(O);
   if (!$skip_vmcfg) {
      print "Running vmcfg...";
      print $HTML ? "<br>" : "\n";
      $inv->run_vmcfg($HTML);
   }
}

sub readInventory {
  my($class, $file) = @_;
  $file = $class->goldenName() if (!$file);

  if (open(O, $file)) {
     my @L = <O>; close(O);
     my $VAR1;
     eval "@L";
     return $VAR1;
  }
  return undef;
}

sub getKeys {
  my($inv) = @_;
  my %K;
  my $devs = $inv->{devices};
  foreach my $d (@$devs) {
     $K{$d->{key}} = $d;
  }
  return \%K;
}

sub deviceCount {
  my($inv) = @_;
  my $devs = $inv->{devices};
  return $#$devs + 1;
}


sub getDevices {
  my($inv) = @_;
  return $inv->{devices};
}

#  $inv = Inventory->read();
#  print $inv->toXML();

sub toXML {
  my($inv) = @_;
  
  my $out =<<EOF;
<?xml version=\"1.0\"?>
<!DOCTYPE inventory PUBLIC "-//Sun Microsystems//DTD XML Version 1.0//EN" "/opt/SUNWstade/System/Inventory.dtd">
<inventory>
  <created>$inv->{created}</created>
  <created2>$inv->{created2}</created2>
  <model>$inv->{model}</model>
  <solution>$inv->{solution}</solution>
EOF
  my $devs = $inv->{devices};
  foreach my $d (@$devs) {
     $out .= "  <device type=\"$d->{type}\">\n";
     my $att;
     foreach my $k (sort keys %$d) {
         if (index(",last_update,class,key,ip,name,wwn,", ",$k,") >= 0) {
            $out .= "    <$k>$d->{$k}</$k>\n";
         } elsif ($k ne "type" && $k ne "frus") {
            $att .= "    <attribute id=\"$k\">$d->{$k}</attribute>\n";
         }
     }
     $out .= $att;
     my $frus = $d->{frus};
     foreach my $f0 (sort keys %$frus) {
        my $f = $frus->{$f0};
        my $extra;
        foreach my $el ('loopVersion','ctlrVersion') {
          $extra .= " <$el>$f->{$el}</$el>" if (exists $f->{$el});
        }

        if (length($f->{serialNo}) > 1) {            # t3/t4
          $out .=<<EOF;
          <component type="$d->{type}">
            <fruId>$f0</fruId>
            <fruModel>$f->{model}</fruModel>
            <fruRevision>$f->{revision}</fruRevision>$extra
            <fruSerialNo>$f->{serialNo}</fruSerialNo>
            <fruVendor>$f->{vendor}</fruVendor>
          </component>
EOF
        } elsif (exists $f->{serialNumber}) {  # dsp
          my $rev = "$f->{hWRev}.$f->{pCBRev}" if ($f->{hWRev});
          $out .=<<EOF;
          <component type="$d->{type}">
            <fruId>$f0</fruId>
            <fruClass>$f->{class}</fruClass>
            <fruModel>$f->{partNumber}</fruModel>
            <fruRevision>$rev</fruRevision>$extra
            <fruSerialNo>$f->{serialNumber}</fruSerialNo>
            <fruState>$f->{state}</fruState>
            <fruVendor>SUN</fruVendor>
          </component>
EOF
        } elsif($f->{fruVendor}eq "Alpha Technologies") {# ps
          $out .="          <component type=\"$d->{type}\">
            <fruId>$f0</fruId>
            <fruModel>$f->{fruModel}</fruModel>
            <fruRevision>$f->{fruRevision}</fruRevision>$extra
            <fruSerialNo>$f->{fruSerialNo}</fruSerialNo>
            <fruVendor>$f->{fruVendor}</fruVendor>
          </component>\n";

        } else {                                   # sp
          $out .=<<EOF;
          <component type="$d->{type}">
            <fruId>$f0</fruId>
            <fruModel>$f->{model}</fruModel>
            <fruRevision>$f->{revision}</fruRevision>$extra
            <fruSerialNo>$f->{serialNo}</fruSerialNo>
            <fruVendor>SUN</fruVendor>
          </component>
EOF
        }
     }
     $out .= "  </device>\n";
    
  }
  $out .= "</inventory>\n";
  return $out;
}


sub findCurrentModel {
  my($class) = @_;
  my $inv = $class->readInventory();
  return $inv->{model};
}

sub readHostLines {
  my($class) = @_;

  if (open(O, "/etc/hosts")) {
    my @host_lines = <O>;
    close(O);
    return \@host_lines;
  } else {
    print "Error: Cannot read /etc/hosts, aborting \n";
    return undef;
  }
}

sub run_vmcfg {
  my($inv, $HTML) = @_;
  my($renv, $devs, $hosts,$notifs) = PDM::ConfigFile->read();
  my(%F, $errs, $info);

  my $devices = $inv->{devices};
  foreach my $r (@$devices) {

      next if ($r->{type} ne "6020");
      my $cool;
      require Service::Array;
      my $rc = Service::Array->add($r->{ipno});

      if ($rc) {
         $errs .= $rc;
         $errs .= $HTML ? "<br>" : "\n";
      } else {
         $errs .= $rc;
         $errs .= $HTML ? "<br>" : "\n";
         my($err, $rc) = $inv->run_vmcfg0($r->{ipno});
         if ($err) {
            $errs .= "Array $r->{ipno} ERROR: $err $err Check password";
            $errs .= $HTML ? "<br>" : "\n";
         } else {
            $info .= "Array $r->{ipno}: configured for use.";
            $info .= $HTML ? "<br>" : "\n";
         }
      }
  }
  print $info . $errs;
}

sub run_vmcfg0 {
  my ($class, $ip, $command, $type) = @_;

  $command = "configure" if (!$command);
  $type = "t4" if (!$type);

  my $array_p = System->getPassword("array");
  my $tell = (stat("/var/adm/messages"))[7];
  
  #print "vmcfg $command -t t4 -i $ip <br>";
  #print "$VMPATH/bin/vmcfg $command -t $type -i $ip -u root -p $array_p\n";
  my ($err, $rc, $error) = Util->run_command("$VMPATH/bin/vmcfg $command -t $type -i $ip -u root -p $array_p", "vmcfg", $VM_TO, 
     {           cache => 0, 
       display_command =>  "vmcfg $command -t $type -i $ip -u root -p x",
     });

  open(FILE_F1, "/var/adm/messages");
  seek(FILE_F1, $tell, 0);
  my ($trace, $line);
  for ($tell = tell(FILE_F1); $line = <FILE_F1>; $tell = tell(FILE_F1)) {
    $trace .= $line;
  }
  close(FILE_F1);

  return ("$err$error" , $rc, $trace);
}
  

# SAVE SNAPSHOT TO RASAGENT.conf
#
sub writeConfig {
   my($inv, $mode) = @_;
   my %F;
   # mode is append or write
   my($renv, $devs, $hosts,$notifs) = PDM::ConfigFile->read();
   if ($mode eq "append") {
     foreach my $d (@$devs) {
       $F{$d->{key}} = 1;
     }
   } elsif ($mode eq "write") { # new devs
     $devs = [];
   }
   my $add;
   my $devices = $inv->{devices};
   foreach my $r (@$devices) {
       next if ($F{$r->{key}});
       next if ($r->{type} eq "sp");
       $F{$r->{key}} = 1;
       my $no = $#$devs + 1;
       my $new = {};
       foreach my $el (keys %$r) {
         $new->{$el} = $r->{$el} if (substr($el,0,1) ne "_" && $el ne "frus");
       }
       $new->{_name} = "device" . $no;
       $new->{mgmtLevel} = "C";
       if ($r->{type} eq "t3") {
          $new->{userLabel} = Agent::T3->getUserLabel($new->{ctrl_model});
       }
       $new->{active} = "Y";
       push(@$devs, $new); $add++;
   }
   $renv->{cust_no}  = $inv->{serial_no} if ($inv->{serial_no});
   $renv->{solution} = $inv->{solution};
   $renv->{solution_model} = $inv->{model};
   $renv->{categories} = "sp|message|t3message|san";
   $renv->{categories} .= "|6020|dsp|t3|csm200|pseq|ntc";

   $renv->{t300logfile} = "/var/adm/messages.t3";

   $renv->{customer}     = "NWS_OPS" if (!$renv->{customer});
   $renv->{site_name}    = "ops"     if (!$renv->{site_name});
   $renv->{site_city}    = "Newark"  if (!$renv->{site_city});
   $renv->{site_zip}     = "98765"   if (!$renv->{site_zip});
   $renv->{site_country} = "USA"     if (!$renv->{site_country});
   $renv->{site_contact} = "ops"     if (!$renv->{site_contact});
   $renv->{site_email}   = "root\@localhost"    if (!$renv->{site_email});
   delete $renv->{role};
   $renv->{window}       = "B";

   $renv->{window}     = "N";
   $renv->{sun_help}   = $SYSTEM1HELP;
   $renv->{t300logfile}= &find_log();
   $renv->{dsp_logfile}= "/var/adm/messages.dsp";

   open(O, ">" . System->get_home() . "/DATA/start");
   close(O);
   $renv->{active} = "Y";

   my %new2;
   my %new3;

   my $sekey = $inv->{model} . "." . System->hostid();


   if ($add && !$F{$sekey}) { # add the rack itself
       my $ipno = Util->name2ip();
       my $no = $#$devs + 1;
       $new2{_name}   = "device" . $no;
       $new2{type}     = $inv->{solution};
       $new2{class}   = "storage.$inv->{solution}";
       $new2{name}     = $inv->{model} . "-" . $renv->{hostname};
       $new2{ip}       = $ipno;
       $new2{wwn}      = $sekey;
       $new2{key}      = $sekey;
       $new2{model}    = $inv->{model};
       $new2{mgmtLevel}= "DS";
       $new2{ipno}     = $ipno;
       $new2{active}   = "Y";
       $new2{time_added} = Util->get_today();
       push(@$devs, \%new2);

       my $no = $#$devs + 1;
       my $key = System->hostid();
       $new3{_name}   = "device" . $no;
       $new3{type}     = "sp";
       $new3{class}   = "storage.$inv->{solution}";
       $new3{name}     = $inv->{model} . "-" . $renv->{hostname};
       $new3{ip}       = $ipno;
       $new3{wwn}      = $key;
       $new3{key}      = $key;
       $new3{model}    = $inv->{model};
       $new3{mgmtLevel}= "DS";
       $new3{ipno}     = $ipno;
       $new3{active}   = "Y";
       $new3{time_added} = Util->get_today();

       push(@$devs, \%new3);

    }
    PDM::ConfigFile->write( $renv, $devs, $hosts, $notifs) if ($add);
}


sub find_log {
  my ($l,$file);
  if (open(OO, "/etc/syslog.conf")) {
     while ($l = <OO>) {
          if ($l =~ /^local7\.\w+\s+(.+)/) {
             $file = $1; last;
          }
     }
     close(OO);
  }
  return $file;
}

# Update snmp info.
# /opt/SUNWstade/snmp/share/snmp/sys.conf
# sysDescr=Sun StorEdge Solution 3900/6900
# sysObjectID=42.2.28.13.2

sub writeSnmpConfig {
   my($inv) = @_;
   my $solution = $inv->{solution};
   my $model    = $inv->{model};

   open(O, ">/opt/SUNWstade/snmp/share/snmp/sys.conf");
   print O "sysDescr=Sun StorEdge Solution $model\n";
   my $last = $solution eq "se" ? "1" : "2";
   print O "sysObjectID=42.2.28.13.$last\n";
   close(O);
}

#======================================================================

sub check_t3 {
  my($rc, $default_type, $trace_out, $golden, $short, $T,$ip, $ipno, $trace,
     $userLabel) = @_;
  my($next);
  my $warn;
  if (!$rc->{key} && !$rc->{wwn} && !$rc->{wwn2} && !$rc->{ctrl_model} ) {
     my $o = "  -> Error: Could not retrieve tokens from this array\n";
     $$trace_out .= $o; print $o;
     #next; 
  }
  if ($default_type ne $rc->{type}) {
     my $o = "  -> Warning : type is '$rc->{type}', should be '$default_type'\n";
     $warn++;
     $$trace_out .= $o; print $o;
  }
  if (!$rc->{key}) {
     my $o = "  -> Error: cannot find the serial# of this array\n";
     $$trace_out .= $o; print $o if ($trace);
  } 
  if (!$rc->{wwn}) {
     my $o = "  -> Error: cannot find the wwn of the first port of this array\n";
     $$trace_out .= $o; print $o if ($trace);
  } 
  if (!$rc->{wwn2}) {
     my $o = "  -> Error: cannot find the wwn of the second port of this array\n";
     $$trace_out .= $o; print $o if ($trace);
  } 
  if (!$rc->{wwn} || !$rc->{key}) {
     $next = 1;
  } else {
      my (%FRUS);
      if($T->{t3_cnt}){
         $T->{report_t3} .= " ,$ip";
      }else{
         $T->{report_t3} .= "$ip";
      }
      $T->{t3_cnt}++;
      foreach my $x (keys %$rc) {
           if (substr($x,0,4) eq "FRU.") { 
              my ($xx, $id, $name) = split(/\./, $x);
              $name = substr($name,3) if (substr($name,0,3) eq "fru");
              $name = lcfirst($name);
              $FRUS{$id}{$name} = $rc->{$x};
           }
      }
      my $time_a = Util->get_today();

      push(@$golden, bless({
            type => $rc->{type}, class => "storage.$rc->{type}",
            ip   => $ipno,
            ipno => $ipno,
            name => $ip,
            userLabel => $userLabel,
            key  => $rc->{key},
            units => $rc->{units},
            wwn  => $rc->{wwn},
            wwn2 => $rc->{wwn2},
            sysRevision => $rc->{"SYSTEM.sysRevision"},
            ctrl_model => $rc->{ctrl_model},
	    time_added => $time_a,
            frus   => \%FRUS },'Inv_dev') );

      my $o = "  -> found $rc->{type} ($ipno / $rc->{wwn}/$rc->{wwn2}\n\t\t$rc->{key}) \n";
      $trace_out .= $o; 
      print $o ;
  }
  return $warn;
}

#======================================================================

sub check_whitney 
{
  my($rc, $default_type, $trace_out, $golden, $short, $T, $ip, $ipno, $trace,
     $userLabel, $COMPARE) = @_;
  my($next);
  my $warn;
  if (!$rc->{key} && !$rc->{wwn} && !$rc->{wwn2} && !$rc->{ctrl_model} ) 
  {
     my $o = "  -> Error: Could not retrieve data from this array\n";
     $$trace_out .= $o; print $o;
     #next; 
  }
  if ($default_type ne $rc->{type}) 
  {
     my $o = "  -> Warning : type is '$rc->{type}', should be '$default_type'\n";
     $warn++;
     $$trace_out .= $o; print $o;
  }
  if (!$rc->{key}) 
  {
     my $o = "  -> Error: cannot determine the key of this array\n";
     $$trace_out .= $o; print $o if ($trace);
  } 
  if (!$rc->{wwn}) 
  {
     my $o = "  -> Error: cannot find the node wwn of this array\n";
     $$trace_out .= $o; print $o if ($trace);
  } 
  if (!$rc->{wwns}) 
  {
     my $o = "  -> Error: cannot find the list of host facing wwns on this array\n";
     $$trace_out .= $o; print $o if ($trace);
  } 
  if (!$rc->{wwn} || !$rc->{key}) 
  {
     $next = 1;
  } 
  else 
  {
      # Don't add the array from the alternate ip address.
      foreach my $entry (@$golden)
      {
         if ($rc->{key} eq $entry->{key})
	 {
	    return;
	 }
      }
      $userLabel =~ s/alt//;
      # Make sure name is set to what it will be when all done.
      $rc->{name} = $userLabel;
      my (%FRUS);
      if($T->{whitney_cnt}){
         $T->{report_whitney} .= " ,$rc->{name}";
      }else{
         $T->{report_whitney} .= "$rc->{name}";
      }
      $T->{whitney_cnt}++;
      foreach my $x (keys %$rc) 
      {
           if (substr($x,0,4) eq "FRU.") 
           { 
              my ($xx, $id, $name) = split(/\./, $x);
              $name = substr($name,3) if (substr($name,0,3) eq "fru");
              $name = lcfirst($name);
	      # change "-" back to "."  (Tray.X.comp.Y)
	      $id =~ tr/-/\./;
              $FRUS{$id}{$name} = $rc->{$x};
           }
      }
      my $time_a = Util->get_today();
      

      # Use the ip numbers instead of the DNS name or patch pro gets
      # confused.
      push(@$golden, bless({
            type => $rc->{type}, class => "storage.$rc->{type}",
            ip   => $ipno,
            ipno => $ipno,
            name => $userLabel,
            userLabel => $userLabel,
            key  => $rc->{key},
            said => $rc->{said},
            altip => $rc->{altipno},
            altipno => $rc->{altipno},
            wwn  => $rc->{wwn},
            wwns => $rc->{wwns},
            units => $rc->{units},
            boardID => $rc->{boardID},
#            sysRevision => $rc->{"SYSTEM.sysRevision"},
#            ctrl_model => $rc->{ctrl_model},
	    time_added => $time_a,
            frus   => \%FRUS },'Inv_dev') );

      my $o = "  -> found $rc->{type} ($ipno / $rc->{wwn}/$rc->{wwn2}\n\t\t$rc->{key}) \n";
      $trace_out .= $o; 
      print $o ;

      if(!$COMPARE){
         $trace_out .= "Set array name to $userLabel\n";
         print "     Set array name to $userLabel\n";
         system("/opt/SUNWstade/sysbin/sys_admin name_array -a $ipno -n $userLabel >/dev/null");
	 $trace_out .= "Set port\n";
         print "     Set port\n";
         system("/opt/SUNWstade/sysbin/sys_admin set_port_type -a $ipno >/dev/null");
      }


  }
  return $warn;
}

sub check_dsp {
  my($rc, $default_type, $trace_out, $golden, $short, $T,$ip, $ipno, $trace,
     $userLabel) = @_;
  my($next);
  my $warn;

  if ($default_type ne $rc->{type}) {
     my $o = "  -> Warning : type is '$rc->{type}', should be '$default_type'\n";
     $warn++;
     $$trace_out .= $o; print $o;
  }
  if (!$rc->{key}) {
     my $o = "  -> Error: cannot find the serial# of this array\n";
     $$trace_out .= $o; print $o if ($trace);
  } 
  if (!$rc->{key}) {
     $next = 1;
  } else {
      my (%FRUS);
      if($T->{sve_cnt}){
         $T->{report_sve} .= " ,$ip";
      }else{
         $T->{report_sve} .= "$ip";
      }
        
      $T->{sve_cnt}++;
      foreach my $x (keys %$rc) {
           if (substr($x,0,4) eq "FRU.") { 
              my ($xx, $id, $name) = split(/\./, $x);
              $name = substr($name,3) if (substr($name,0,3) eq "fru");
              $name = lcfirst($name);
              $FRUS{$id}{$name} = $rc->{$x};
           }
      }
      my $time_a = Util->get_today();
      push(@$golden, bless({
            type      => $rc->{type}, 
            class     => "switch.$rc->{type}",
            ip        => $ipno,
            ipno      => $ipno,
            name      => $ip,
            userLabel => $userLabel,
            key       => $rc->{key},
            units     => $rc->{units},
            wwn         => $rc->{wwn},
            sysRevision => $rc->{"SYSTEM.sysRevision"},
	    time_added => $time_a,
            frus        => \%FRUS },
              'Inv_dev') );

      my $o = "  -> found $rc->{type} ($ipno / $rc->{wwn} / $rc->{key}) \n";
      $trace_out .= $o; 
      print $o ;
  }
  return $warn;
}




#########################################################################
#  MASERATI
#########################################################################

sub upgradeMaserati {
  my($class, $HTML) = @_;
  my($err, $inv) = $class->readMaserati($HTML);
  $inv->writeInventory(undef, $inv, 1);
  return 0;
}

sub read_versions {
  my($class) = @_;

  my $FIREWALL =  "/opt/SUNWsespfw/bin/get_version";
  my $NTC_V    =  "/opt/SUNWsespnc/bin/get_version";
  my($ntc_version, $fire_version);

  if (-x $FIREWALL) {
     $fire_version = `$FIREWALL`; chomp($fire_version);
     $fire_version =~ s/"//g;
  }
  if (-x $NTC_V) {
     $ntc_version  = `$NTC_V`;    chomp($ntc_version);
  }
  return ($ntc_version, $fire_version);
}



sub readMaserati {
  my($class, $short, $PREFIX, $trace, $HTML, $TO, $MODEL, $FILE, $COMPARE) = @_;
  my(%T, $trace_out);
  my $devcnt   = 1;
  my $golden = [];
  my $xml;
  $PREFIX = "192.168" if (!$PREFIX);
  my $alines = Inventory->readHostLines();
  my $lines;
  my $time_a = Util->get_today();


  if($FILE) {
    open(OO, ">/tmp/inventory_trace");
  }

  # Find ping able IPs
  my @lines;
  my $valid = 0;

  if(!$FILE) {
    print "<br>" if ($HTML);
    print "Find IP's that respond to ping\n";
  } else {
    print OO "<br>" if ($HTML);
    print OO "Find IP's that respond to ping\n";
  }
  my %iparray;
  my $listIps;
  foreach my $l (@$alines) {
    chop($l);
    last if ($l eq "#DONE");
    next if (substr($l,0,1) eq "#");
    my ($ipno, $ip, $rest) = split(/\s+/, $l);
    next if (!$ipno);
    next if ((substr($ipno,0,length($PREFIX) ) ne $PREFIX)&&($ip !~ /ntc/));
    $iparray{$ipno} = $ip if($listIps !~ /$ipno,/);
    $listIps .= "$ipno,"  if($listIps !~ /$ipno,/);
    
  }
  my @arr = split(/,/, $listIps);
  my $si = @arr;
  
  my $pointer = 0;
  my $sleep_ping = 3;
  while($pointer < $si){
     my $end = $pointer + 20;
     if($end > $si - 1){
       $end = $si - 1;
     }
     for (my $x = $pointer; $x <= $end; $x++) {
        my $ipno = $arr[$x];
	unlink("/tmp/ping_$x");
        my $comm = "/usr/sbin/ping $ipno $sleep_ping >/tmp/ping_$x 2>&1 ";
        system("$comm&");
     }
     sleep($sleep_ping + 1);

     for (my $x = $pointer; $x <= $end; $x++) {
        open(O, "/tmp/ping_$x");
        my $ret = <O>; 
	close(O);
        unlink("/tmp/ping_$x");
        chop($ret);
	if($ret =~ /is alive/){
	  # This is a good ip
	  my $ipnum = $arr[$x];
	  my $ipname = $iparray{$ipnum};
	  @lines[$valid] = "$ipnum $ipname  ";
	  $valid++;
	  if(!$FILE) {
             print "<br>" if ($HTML);
             print "$ipnum $ipname is alive\n";
          } else {
             print OO "<br>" if ($HTML);
             print OO "$ipnum $ipname is alive\n";
          }
	}
     }
     $pointer = $end +1;
  }


  if(!$FILE) {
    print "<br>" if ($HTML);
    print "\nProcess IP's that could be pinged\n\n";
  } else {
    print OO "<br>" if ($HTML);
    print OO "\nProcess IP's that could be pinged\n\n";
  }

  my $li;
  if (-x "/usr/bin/iam") {
     open(O, "/usr/bin/iam|");
     while ($li = <O>) {
        if ($li =~ /Sun StorEdge\(tm\)\s+(.*)/) {
           $MODEL = $1;
        }
     }
     close(O);
  }
  foreach my $l (@lines) {
    chop($l);
    my ($ipno, $ip, $rest) = split(/\s+/, $l);
    next if (!$ipno);
    next if ((substr($ipno,0,length($PREFIX) ) ne $PREFIX)&&($ip !~ /ntc/));
  
    my @X = split(/\./, $ipno);
    my $no = $X[3];
    my $version;
    if(!$FILE) {
      print "<br>" if ($HTML);
      print "$ip:\n";
    } else {
      print OO "<br>" if ($HTML);
      print OO "$ip:\n";
    }
    if ($X[2] == 0 && $no == 2) {  # sp
       my $key = "sp:" . System->hostid();
       my($build, $assembled) = System->read_release();
       my $hostinfo = System->hostinfo();
       my $model = System->model();
       
       if($MODEL eq "6920"){
       my ($ntc_version, $fire_version) = $class->read_versions();

       push(@$golden, bless({
            type => "sp", class => "server.sp",
            ip   => $ipno,
            ipno => $ipno,
            name => $ip,
            key  => $key,
            wwn  => $key,
            hostinfo => $hostinfo,
	    time_added => $time_a,
            sysRevision => $build,
            frus  => { $ip => {
                         vendor   => "SUN",
                         serialNo => $key,
                         model    => $model,
                         revision => $build, 
                        assembled => $assembled, 
                              },
                       "$ip-ntc" => {
                         vendor   => "Lantronix",
                         serialNo => "spcomp1",
                          model   => "scs400",
                         revision => $ntc_version,
                              },
                       "$ip-firewall" => {
                         vendor   => "NetGear",
                         serialNo => "spcomp2",
                          model   => "rp114",
                         revision => $fire_version,
                              },
          
                      }
             }, 'Inv_dev') );
       }else{
       push(@$golden, bless({
            type => "sp", class => "server.sp",
            ip   => $ipno,
            ipno => $ipno,
            name => $ip,
            key  => $key,
            wwn  => $key,
            hostinfo => $hostinfo,
            time_added => $time_a,
            sysRevision => $build,
            frus  => { $ip => {
                         vendor   => "SUN",
                         serialNo => $key,
                         model    => $model,
                         revision => $build,
                        assembled => $assembled,
                              },
                      }
             }, 'Inv_dev') );

       }
       my $o = "  -> found sp ($ipno) \n";
       $trace_out .= $o; 
       if(!$FILE) {
	 print $o ;
       } else {
	 print OO $o;
       }

    } elsif ($ip =~ /ntc/) { #NTC

      if($MODEL eq "6940"){
	 my $ntc = System->solution_sp();
	 $ntc .= "-ntc";
	 if($ntc =~ /new_sp/){
	    $ntc = "new_ntc";
	 }
	 if($ip !~ /$ntc/){
	   print "   Skipping $ip, looking for $ntc.\n";
	   next;
	 }
         my $rc = Agent::NTC->probe($ipno);
         if (!$rc->{err}){

	   
	   if($T{ntc_cnt}){
	     $T{report_ntc} .= " ,$ip";
	   }else{
	      $T{report_ntc} .= "$ip";
	   }
	   $T{ntc_cnt}++;

         push(@$golden, bless({
	    type => "ntc", class => "server.ntc",
	    ip	 => $ipno,
	    ipno => $ipno,
	    name => $ip,
	    key	 => $rc->{slcSystemSerialNo},
	    wwn	 => $rc->{slcSystemSerialNo},
	    time_added => $time_a,
	    sysRevision => $rc->{slcSystemFWRev},
	    frus  => { $ip => {
	    		 vendor	  => "Lantronix",
	    		 serialNo => $rc->{slcSystemSerialNo},
	    		 model	  => "SLC8",
	    		 revision => $rc->{slcSystemFWRev},
	                      },
	              }
	     }, 'Inv_dev') );
          }
       }else{
         # 6920 Only print out information to keep it the same as 6940
	 # The information was really saved when SP was discovered.
	 # fix bugID 6393273
	  my $ntc = System->hostname() . "-ntc";
	  if($ntc =~ /new_sp/){
	    $ntc = "new_ntc";
	  }
	  if($ip =~ /$ntc/){
             if (&ping($ip)) {
	        print "  -> found NTC at $ip\n";
		if($T{ntc_cnt}){
	           $T{report_ntc} .= " ,$ip";
	        }else{
	           $T{report_ntc} .= "$ip";
	        }
	        $T{ntc_cnt}++;


	     }
	  }else{
	     print "   Skipping $ip, looking for $ntc.\n";
	     next;
	  }

       }
    } elsif ($no >=100 && $no <= 105 ) { # PSX=1000
      my $rc = Agent::PS->probe("192.168.0.$no");
      if (!$rc->{err}){
	   $T{pseq_cnt}++;
	   $T{report_pseq} .= "$ip, ";


           push(@$golden, bless({
            type => "pseq", 
	    class => "power.sequencer",
            ip   => $ipno,
            ipno => $ipno,
            name => $ip,
            key  => "pseq.$ip",
            wwn  => "pseq.$ip",
            time_added => $time_a,
            sysRevision => $rc->{Sequencer_SW},
            frus  => { seqctlr=> {
                         fruVendor   => "Alpha Technologies",
                         fruModel    => "Sequencer_SW",
                         fruRevision => $rc->{Sequencer_SW}, 
                         fruSerialNo => "pseq_833566b8"
                       },
                       rmu=> {
                         fruVendor   => "Alpha Technologies",
                         fruModel    => "CXC_RMU_SW",
                         fruRevision => $rc->{CXC_RMU_SW},
                         fruSerialNo => "pseq_833566b8"
                       },
                    }
            }, 'Inv_dev'));
      }
    } elsif ($no == 10 ) { # PSX=1000
         if (!&ping($ipno)) {
             my $o = "  -> Warning: cannot ping $ipno \n";
             $o .= "     Device is not responding or not present in this configuration\n" ;
             $trace_out .= $o;
             if(!$FILE) {
	       print $o if ($trace);
	     } else {
	       print OO $o if ($trace);
	     }

             next;
         }

         $T{ve_cnt}++;
	 require Agent::DSP;
         my $rc  = Agent::DSP->getWWN($ipno, undef, $TO, 1);
         my $wwn = $rc->{wwn};
         if ($rc->{key}) {
             my $warn = &check_dsp($rc, "dsp", \$trace_out, $golden, 
                          $short, \%T, $ip, $ipno,  $trace, $rc->{userLabel});
             $T{warn} += $warn;

          } else {
             my $o = "  -> Error: cannot access DSP at $ip/$ipno $rc->{error} (remove password if present)\n";
             $trace_out .= $o; 
	     if(!$FILE) {
	       print $o;
	     } else {
	       print OO $o;
	     }
             $T{err}++ if($MODEL ne "6320");
	     next;
          }
  
    } 
    elsif ($no >= 40 && $no <= 97) 
    { 
       my $rc;

       if (&ping($ipno)) 
       {


	  # try 6140s - CSM-200s
          $rc = Agent::COMMON->getWWN($ipno, undef, $TO, 1, "csm200");

          if ($rc->{err})
          {
	     if(!$FILE) 
             {
	       print "ERROR on $ipno: $rc->{err}\n";
	     } 
             else 
             {
	       print OO "ERROR on $ipno: $rc->{err}\n";
	     }
	     $trace_out .= $rc->{err};         
          }
          if ($rc->{warn})
          {
	     if($rc->{warn} !~ /No csm200 type device found at/){

	        if(!$FILE) 
                {
	           print "$rc->{warn}\n";
	        } 
                else 
                {
	          print OO "$rc->{warn}\n";
	        }
	        $trace_out .= $rc->{warn};         
	     }
          }

          else
          {
             my $warn = &check_whitney($rc, "csm200", \$trace_out, $golden, $short, \%T,
                                       $ip, $ipno, $trace, $ip, $COMPARE);
             $T{warn} += $warn;
          }
	  if(!($rc->{warn} || $rc->{err})){
	    # No errors finding csm, must have found it.
	    # No reason to continue on.
	    next;
	  }



          # try 6020s       
          $rc = Agent::6020->getWWN($ipno, undef, $TO, 1);
	  if($rc->{err})
          {
	     if(!$FILE) 
             {
	        print "ERROR on $ipno: $rc->{err}\n";
	     } 
             else 
             {
	        print OO "ERROR on $ipno: $rc->{err}\n";
	     }

	     $trace_out .= $rc->{err};

	  }
          elsif ($rc->{warn})
          {
	     if($rc->{warn} !~ /No T3\/6020 type device found at/){
                if(!$FILE)
                {
                   print "$rc->{warn}\n";
                }
                else
                {
                   print OO "$rc->{warn}\n";
                }
                $trace_out .= $rc->{warn};
	     }
          }
          else
          {
             my $warn = &check_t3($rc, "6020", \$trace_out, $golden, $short, \%T,
                               $ip, $ipno, $trace, "Array");
             $T{warn} += $warn;
	  }

	  if($rc->{warn} || $rc->{err}){
	     # Had troubles finding csm and T3/6020
	     my $o = "  -> Warning: could ping $ipno but couldn't find a storage array.\n";
             $trace_out .= $o; 
	     if(!$FILE) 
             {
	        print $o if ($trace);
	     } 
             else 
             {
	        print OO $o if ($trace);
	     }
	  }
       } 
       else 
       {
          my $o = "  -> Warning: cannot ping $ipno \n";
          $o .= "     Device is not responding or not present in this configuration\n";
          $trace_out .= $o; 
	  if(!$FILE) 
          {
	    print $o if ($trace);
	  } 
          else 
          {
	    print OO $o if ($trace);
	  }
       }
           
    } 
   }
   my $date = Util->get_today();
   my $date2 = `date`;
   chop($date2);

   my $INV = { created => $date, 
           created2 => $date2, 
           solution => "se2",
              stats => \%T,
           devices  => $golden,
          };

   if(!$FILE) {
     close(OO);
   }

   bless($INV, 'Inventory');
   return ($trace_out, $INV);
}




sub validateMaserati {
  my($inv, $MODEL, $trace) = @_;
  my ($prefix, $suffix, $trace_out, $model);

  my $T = $inv->{stats};

  if ($T->{sve_cnt} != 1){
    my $o = "  -> Error: Wrong number of DSP's ($T->{sve_cnt}) found for $MODEL! \n";
    $trace_out .= $o; print $o;
    $T->{err}++;
  }
  if (($T->{t3_cnt} == 0) && ($T->{whitney_cnt} == 0)){
    my $o = "  -> Warning: No Storage Array found! \n";
    $trace_out .= $o; print $o;
    #$T->{err}++;
  }
  
  if ($MODEL eq "6940" && $T->{pseq_cnt} < 1) {
     my $o = "  -> Error: No Power Sequencer found for $MODEL! \n";
    $trace_out .= $o; print $o;
    $T->{err}++;
  }

  if ($T->{ntc_cnt} < 1) {
     my $o = "  -> Error: No NTC found for $MODEL! \n";
    $trace_out .= $o; print $o;
    $T->{err}++;
  }

  if ($T->{pseq_cnt} > 1) {
    $model = "6940";
  }else{
    $model = "6920";
  }
    
  if (0 && ($MODEL && $MODEL ne $model)) {
     my $o = "ERRORS: Model proposed ($MODEL) is different than discovered model ($model)\n";
     $trace_out .= $o; print $o;
     $T->{err}++;
  }
  $inv->{model} = $model;
  $T->{sve_cnt} += 0;

  my $w_info = "|Warn(s) : $T->{warn}\n" if ($T->{warn});


  my $summary =<<EOF;

=====================================
|     Configuration Summary         |
-------------------------------------
|  Model : $model, Requested = $MODEL
EOF

if ($T->{t3_cnt}) {
$summary .=<<EOF;
|  Arrays: $T->{t3_cnt}
|          $T->{report_t3}
EOF
}

if ($T->{whitney_cnt}) {
$summary .=<<EOF;
|  Arrays: $T->{whitney_cnt}
|          $T->{report_whitney}
EOF
}
  

if ($T->{sve_cnt}) {
    $summary .=<<EOF;
|  DSPs  : $T->{sve_cnt}
|          $T->{report_sve}
EOF
}

  $summary .=<<EOF;
| $w_info
=====================================

EOF

  return ($T->{err}, $trace_out, $summary);
}




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

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

package Inv_dev;


sub frus {
   my($dev) = @_;
   return $dev->{frus};
}

sub info {
   my($dev, $val) = @_;
   if (exists $dev->{$val}) {
      return $dev->{$val};
   }
   return undef;
}

sub serialString {
  my($dev, $fru) = @_;

  if (index("t3,6120,6020,", $dev->{type}) >= 0) {
     return "$fru->{vendor} / $fru->{model} / $fru->{serialNo}";
  } elsif ($dev->{type} eq "dsp") {
     my $v = "SUN" if ($fru->{partNumber});
     return "$v / $fru->{partNumber} / $fru->{serialNumber}";
  } elsif ($dev->{type} eq "sp") {
     return "$fru->{vendor} / $fru->{model} / $fru->{serialNo}";
  } 
}

sub revisionString {
  my($dev, $fru) = @_;

  if (index("6020,6120" ,$dev->{type}) >= 0) {
     my $rev = "$fru->{ctrlVersion}$fru->{loopVersion}";
     $rev .= "/ " if ($rev);
     $rev .= $fru->{revision};
     return $rev;
  } elsif ($dev->{type} eq "dsp") {
     return "$fru->{hWRev} / $fru->{pCBRev}";

  } elsif ($dev->{type} eq "sp") {
     return $fru->{revision};
  }
}

     


1;
