package Agent::A3500FC;
#<copyright>
# ----------------------------------------------------------
# Sun Proprietary/Confidential Code
# Copyright 2001, Sun Microsystems, Inc. All rights reserved.
# ----------------------------------------------------------
#</copyright>


#  Works with A1000 and A3500fc

#  $Name: bld61_002 $ 
#  $Id: A3500FC.pm,v 1.6 2004/10/11 22:04:20 mckenney Exp $
use strict;
use Agent;
use base 'Agent';

use vars qw( %RAID);

sub isSelectable { "Sun A3500FC" }

sub revision {'$Revision: 1.6 $'}

sub type         { Report::CAT_A3500FC }

sub new {
  my($self) = Agent->new();

  bless ($self, 'Agent::A3500FC');
  return $self;
}


#
#  healthck -a asdas
#  Health Check Summary Information
#  da106_004:                Failed Drive Channel at Drive [5,0];[5,8]
#  da106_004:        
#  arraymon(1M)    drivutil(1M)  fwutil(1M)     lad(1M)
#  logutil (1M)    nvutil(1M)    parityck(1M)   raidutil(1M)
#  rdacutil(1M)    rmevent(4)    rmparams(4)    rmscript(1M)
#  storutil(1M)
#

sub getPortKey {
  my($class, $wwn, $port) = @_;
  my($VAR1);
  return "$wwn.$port";
}


sub RUN {
  my($agent, $static_list, $pass) = @_;
  my( $dev_name, $com, %SYS, $DIR);
  my( @devices, @all_dif, $timelapse);
  my($sys_xml, $state_xml, $raid, @a, $dev, $log_err, $lines);
  my($renv) = System->get_renv();

  $DB::single = 1;

  my $logfile  = $renv->{logfile};
  if ($logfile) {
    ($log_err, $lines) = $agent->read_log_file($logfile,'NEW');
    Debug->err('CANNOT_READ', $logfile) if ($log_err);
  }
  
  my($log_lines, $x) ;
  for ($x=0; $x <= $#$lines; $x++) {
      $log_lines .= $agent->read_thresholds(\$x, $lines);
  }

  my($dc) = 0;
  my($category);
  my $processed_list = [];

  foreach $dev ( $agent->deviceList($static_list) ) {
     next if ($dev->{active} eq "N"); 
     next if (!Util->isMineToMonitor($dev));
     $category = $dev->{type};
     my $wwn   = $dev->{key};
     my $problems = PDM->get_last_event();

     $dc++;
     if ($dc == 1) {
        $DIR = $agent->find_raid;
        if (!$DIR && !System->get_testMode) {
          Debug->errNoRepeat(LAD => "", 8);
          return;
        }
     }
     $dev_name = $dev->{name};
     Debug->print1("-> $dev->{type}: Reading device $wwn");
     if (!$wwn) {
        Debug->print2("No ctrl_id for $dev_name, skipping");
        next;
     }
     Timelapse->startDev( $dev);
     my($sys_report, $ctrl1, $ctrl2) = $agent->sonoma($dev_name, $DIR, $dev);

     if ($ctrl1 && "$dev->{type}.$ctrl1" ne $dev->{key}) {
        Debug->errNoRepeat(A3500_NEW_KEY => $dev->{key}, 24*7);
     }

     Timelapse->stopDev( $dev);

     my($id) = {
                deviceName=> $wwn,
                active    => $dev->{active},
                class     => $dev->{class},
                name      => $dev_name,
                display   => $wwn,
                category  => $category,
                ip        => "" ,
               };

     $sys_report = {} if (!$sys_report);
     $agent->copyDev($dev, $sys_report);
     my $new_rep;
     if ($sys_report) {
       #Discover->updateTopoDevice($dev, {report => $sys_report});
       if(!$sys_report->{'controller.a.serial'} && !$sys_report->{'controller.b.serial'})
       { 
          $new_rep = Report->new($id, $sys_report,$log_lines, Report::STATUS_CANNOT_CONNECT);
       }else{
          $sys_report->{'id.name'} = $dev_name;
          $sys_report->{"id.ipno"} = System->get_ipno();
          $sys_report->{'id.device'}  = $dev_name;
          $sys_report->{'id.ctrl_id'} = $wwn;
          $new_rep = Report->new($id, $sys_report, $log_lines);
       }
     } else {
       $new_rep = Report->new($id, $sys_report,$log_lines, Report::STATUS_CANNOT_CONNECT);
     }
     require Health::A3500FC;
     Health::A3500FC->all_logic($new_rep);
     PDM->saveReport($new_rep);

     my ($broke, $abort) = $agent->new_events($problems, $dev, 1);
     push(@$processed_list, $dev);
     last if ($broke && $pass == 1 || $abort);
     $log_lines = ""; # use only once
  }

  return $processed_list;
}

sub read_thresholds {
  my($agent,$x, $array) = @_;

  my($line) = $array->[$$x];
  my($out);

  if ($line =~ /controller.*A3500.*recommended firmware version/) {
     $out .= $agent->log_inc('CTRL_FIRM', $line);
  }

  return $out;
}

sub log_inc {
  my($agent, $type, $mline) = @_;
  my($data, $thr, $th, $val, $t1, $today, $hrs);

  my(@m) = split(/ +/, $mline);
  my($date) = "$m[0] $m[1] $m[2]";
  my($info) = "$m[3] $m[4] $m[5] $m[6]";
  $info =~ s/"/ /g;
  my($level, $cnt, $desc, $mins) = Thresholds->test('a3500',$type, 0,1);

  my($tx) = "Received $cnt $desc messages";
  $tx .= " in $mins mins" if ($mins);
  if ($level eq "W") {
     return "WARN\t$date\t$tx\t$info\n";
  } elsif ($level eq "E") {
     return "ERR\t$date\t$tx\t$info\n";
  }
}




sub sonoma {
  my($agent, $dev_name, $DIR, $device) = @_;
  my(%SYS, $in, $found, $l, $id, $value, $x, $ix, $s, $l1, @b, $k, $xx);
  $DIR =  $agent->find_raid() if (!$DIR);

  if (System->get_testMode()) {
     my $testrep = Report->readTest($device);
     return ($testrep);
  }

  my($lun_cnt) = 0;
  my $renv = System->get_renv();
  my($TO) = $renv->{'timeout.rm6'};
  my(@SER, $err, $com, $health);

   ($err,$health) = Util->run_command( "$DIR/healthck $dev_name", "lad.txt", $TO);
   my($hinfo);
   if ("@$health" =~ /Module selected could not be found/) {
       Debug->info('NO_A35_DEVICE', $dev_name);
       return ();
   }
   my $flag1;
   for ($x=1; $x < $#$health; $x++) {
      if ($health->[$x] =~ /$dev_name: +([^,]*)/) {
         $SYS{"device_info.healthck"} .= $1 . ",";
      }
   }
   $SYS{"device_info.battery.status"} = ($SYS{"device_info.healthck"} =~ /Failed Battery/) ? "Failed":"OK";

   ($err,$com) = Util->run_command( "$DIR/lad", "lad.txt", $TO);

   my(%X);
   if ("@$com" =~ /No RAID devices found/) {
       Debug->info('NO_A35_RAID_DEVICE', $dev_name);

       return ();
   }
   for ($x=0; $x <= $#$com; $x++) {
      my(@a) = split(/\s+/, $com->[$x]);
      $X{$a[0]} = $a[1];
   }

# RDACUTIL (only once per enclosure)

   ($err,$com) = Util->run_command(
       "$DIR/rdacutil -i $dev_name", "rdacutil.txt", $TO);
   $in = "";
   $s = $com->[1];
   $ix = index($s, ":");
   $SYS{'device_info.mode'} = Util->trim(substr($s,$ix+1));
   my(@devices) ;

   for ($x=2; $x <= $#$com; $x++) {
      $l = $com->[$x];
      if ($l =~ / +(.*) +controller ([^\(]+) \((\w+)\) +units: (.*)/) {
        $SYS{"controller.count"}++;
        $SYS{"controller.$2.state"} = Util->rtrim($1);
        $SYS{"controller.$2.units"}   = Util->trim($4);
        $SYS{"controller.$2.device"}  = $3;
        $SYS{"controller.$2.serial"}  = $X{$3};
        push(@devices, $3);
        push(@SER,  $X{$3});
#        $SYS{"controller.$2.id"}      = $2;
      }
   }

   for ($xx=0; $xx <= $#devices; $xx++) {
     my($devName) = $devices[$xx];
     my($devAB) = ($xx==0) ? "a":"b";

#  RAIDUTIL  (run on each device)
     my($err,$com) = Util->run_command( 
       "$DIR/raidutil -c $devName -B -i", "raidutil.txt", $TO);

     if ($err || "$com->[0] $com->[1]" =~ /No RAID devices found/) {
        Debug->print2("Error: $err / $com->[0]");
	Debug->info('A35_RAIDUTIL_DEVICE', $devName);

        return ();
     }
     $in = ""; $found = 0;

     foreach $l (@$com) {
        if ($l =~ /LUNs found/) {      
            $in = "lun"; $found = 1;
            $l =~ /found on (.+)\./;
            my($vol) = $1;
            $SYS{'id.vol'} = $vol;

        } elsif ($l =~ /Battery age is (.*)/) {
            $SYS{"device_info.$devAB.battery"} = $1;
            $in = "info";
        } elsif ($l =~ /succeeded!/) {
            $in = "";
        } elsif ($in eq "lun") {
            $l =~ /LUN (\d+) +RAID (\d+) +(\d.*)/;
            $SYS{"lun.$1.raid"} = $2;
            $SYS{"lun.$1.size"} = $3;
            $lun_cnt = $1 if ($1 > $lun_cnt);
        } elsif ($in eq "info") {
            if (length($l) > 0) {
               $id = Util->rtrim(substr($l,0,17));
               $value = Util->rtrim(substr($l,18));
               $id =~ s/ /_/g;
               $SYS{"device_info.$devAB.$id"} = $value;
            }
        }
     }
     $SYS{"lun.count"} = $lun_cnt+1;
     

# DRIVUTIL -L (per enclusure)
    if (!$flag1 && $devName =~ /c\d+t\d+d\d+/) {  # only on the first one
       $flag1 = 1;
       my($err,$com) = Util->run_command(
       "$DIR/drivutil -l $devName", "drivutil_l.txt", $TO);

       for ($x=5; $x <= $#$com; $x++) {
         $l = $com->[$x];
         $l =~ /  (\d+) +(\d+) +(\w+) +(\d+) +(\d+) +(.*)/;
         $SYS{"lun.$1.group"}      = $2;
         $SYS{"lun.$1.device"}     = $3;
         $SYS{"lun.$1.raid_level"} = $4;
         $SYS{"lun.$1.capacity"}   = $5;
         $SYS{"lun.$1.status"}   = Util->rtrim($6);
#         $SYS{"lun.$1.id"}         = $1;
       }

# DRIVUTIL -i (per enclusure)
#Location  Capacity   Status         Vendor  Product          Firmware     Serial
#            (MB)                              ID             Version      Number
#[1,0]     34732      Optimal        SEAGATE ST136403LSUN36G  034A         LT0418

       ($err,$com) = Util->run_command(
       "$DIR/drivutil -i $dev_name", "drivutil_i.txt", $TO);

       my($no) = 0;
       for ($x=6; $x <= $#$com; $x++) {
         $l = $com->[$x];
         next if (substr($l,0,1) ne "[");
         $SYS{"disk.$no.group"}    = Util->rtrim(substr($l,0,9));
         $SYS{"disk.$no.capacity"} = Util->rtrim(substr($l,10,9));
         $SYS{"disk.$no.status"}   = Util->rtrim(substr($l,21,11));

#         $SYS{"disk.$no.id"}       = $no;
         $SYS{"disk.$no.vendor"}           = Util->rtrim(substr($l,36,7));
         $SYS{"disk.$no.product_id"}       = Util->rtrim(substr($l,44,16));
         $SYS{"disk.$no.firmware_version"} = Util->rtrim(substr($l,61,12));
         $SYS{"disk.$no.serial"}           = Util->trim(substr($l,74));
         $no++;
       }
       $SYS{"disk.count"}   = $no;
     
# DRIVUTIL -D (per enclusure)
       ($err,$com) = Util->run_command(
       "$DIR/drivutil -d $dev_name", "drivutil_d.txt", $TO);

       foreach $l (@$com) {
         if ($l =~ /(Hot Spare)/ || $l =~ /(Group +\d+):/) {
           $k = $1; $k =~ s/ +/_/;
           $SYS{"drive_grouping.$k"} = Util->trim(substr($l,11));
         }
       }
     }
   }

   $agent->addIdentification(\%SYS);
  
   Debug->dump('a3500Config', \%SYS);
   return (\%SYS, $SER[0], $SER[1]);
          
}

sub find_raid {
  my($agent) = @_;
  my($DIR);

  if (!System->get_testMode() ) {
    if (-d "/usr/lib/osa/bin") {
       $DIR = "/usr/lib/osa/bin";
    } elsif (-d "/usr/sbin/osa") {
       $DIR = "/usr/sbin/osa";
    } else {
       return undef;
    }
  }
  return $DIR;
}

sub FRUS {
  my($class, $r, $name) = @_;
  my($v) = $r->{_value};
  my (@FRUS, $x);
  my $devtype = $r->category();

  foreach $x ('a','b') {
      my $comp = "controller.$x";
      push(@FRUS,[$name, $devtype, "controller","controller.$x",
        "N/A", 
      	"N/A", 
      	"N/A", 
      	"N/A", 
      	$v->{"$comp.state"}]
      	);
  }

  my $total = $v->{"disk.count"} ||10;
  for ($x=0; $x <= $total; $x++) {
      if ($v->{"disk.$x.product_id"}) {
          push(@FRUS, [$name, $devtype, "disk","disk.$x",
                  $v->{"disk.$x.vendor"},
                  $v->{"disk.$x.product_id"},
                  $v->{"disk.$x.serial"},
                  $v->{"disk.$x.firmware_version"},
                  $v->{"disk.$x.status"}]
               );
      }
  }

  return \@FRUS;

}

#
#   $cnt = 0;
#   no tableCnt: separate report.
#   with tableCnt: many device in same table.
#   $agent->REPORT($host, $report, {tableCnt => \$cnt};

sub REPORT {
  my($class, $host, $r, $arg) = @_;
  my($out); 

  my($name) = $r->name();
  $out = $class->reportHead("A3500FC", $r);
  $out .= "</table>";
  
  my($v) = $r->value();

  my($tableCnt) = $arg->{tableCnt};
  if (!$tableCnt || $$tableCnt == 0) {
    $out .= "<table border=1 cellspacing=0 cellpadding=1 width=100% bgcolor=white>";
  }
  my $ck = $v->{'device_info.healthck'};
  if ($ck =~ /Failed/ || $ck =~ /Offline/) {
     $ck = "<font color=red><b>$ck";
  }
  $out .= "
  <tr><td colspan=6>
  <table border=0 cellspacing=1 bgcolor=#F0F0F0>
   <tr> <td bgcolor=$Style::LIGHT align=right><b>Name:</td><td>$r->{_id}{name} </td>
        <td bgcolor=$Style::LIGHT align=right><b>Serial#:</td><td>$v->{'controller.a.serial'} $v->{'controller.b.serial'}</td>
   <tr>
        <td bgcolor=$Style::LIGHT align=right><b>Revision:</td><td>$v->{'device_info.a.Product_Revision'}</td>
        <td bgcolor=$Style::LIGHT align=right><b>Firmware:</td><td>$v->{'device_info.a.Firmware_Level'}</td>
   <tr>
        <td bgcolor=$Style::LIGHT><b>HealthCk:</td><td colspan=3>$ck</td>
   </table>
   </td>
   <tr><td></td>
  <tr bgcolor=$Style::LIGHT>
    <th><font color=black>Type</th>
    <th><font color=black>Identification</th>
    <th><font color=black>Comp#</th>
    <th><font color=black>Status</th>
    <th><font color=black>Ports</th>
    <th><font color=black>Revision</th>
   ";

#  my($mon) = &mon('a3k',$name);

  my($d, $x, $comp, $b, $status, $serial, $ports, $rev);
  my($cnt)= 0;
  foreach $x ('a','b') {
      $comp = "controller.$x";
      $status = $v->{"$comp.state"};
      $b = ($v->{"$comp.state"} eq "Active")? "":"<font color=red>";
      $serial = $v->{"$comp.device"};
      $out .= 
           "<tr><td><center>Controller</td>
           <td>&nbsp;$serial</td>
           <td><center>$x</td>
           </td><td>$b$status&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td>\n";

      $cnt++;
  }
  my $disk_count = $v->{"disk.count"} ||9;
  for ($x=0; $x < $disk_count; $x++ ){
      $comp = "disk.$x";
      $status = $v->{"$comp.status"};
      $b = ($v->{"$comp.status"} eq "Optimal")? "":"<font color=red>";
      $serial = $v->{"$comp.product_id"} . "/ " . $v->{"$comp.serial"};
      $ports = $v->{"$comp.group"};

      $rev = $v->{"$comp.firmware_version"};
      $out .=  
           "<tr><td><center>Disk</td>
           <td><small>$serial&nbsp;</td>
           <td><center>$x&nbsp;</td>
           </td><td>$b$status&nbsp;</td><td>$ports&nbsp;</td><td>$rev&nbsp;</td>\n";
      $cnt++;
  }
  $out .= "
  <tr><td></td>
  <tr bgcolor=$Style::LIGHT>
    <th><font color=black>Luns</th>
    <th><font color=black>Identification</th>
    <th><font color=black>Comp#</th>
    <th><font color=black>Status</th>
    <th><font color=black>Raid</th>
    <th><font color=black>Size</th>
     ";
  for ($x=0; $x<= 10; $x++ ){
      $comp = "lun.$x";
      $serial = $v->{"$comp.device"};
      $status = $v->{"$comp.status"};
      next if (!$status);
      my $raid   = $v->{"$comp.raid_level"};
      my $size   = $v->{"$comp.capacity"};
      $b = ($status eq "Optimal")? "":"<font color=red>";
      $out .=  
           "<tr><td><center>Lun-$x".
           "<td>$serial".
           "<td><center>$x</td>".
           "</td><td>$b$status&nbsp;</td><td>$raid</td><td>$size</td>\n";
   }


  if (!$tableCnt) {
    $out .= "</table>";
  }
  return $out;
}

1;

