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

#  $Name: bld61_002 $ 
#  $Id: A5K.pm,v 1.4 2005/04/20 17:23:30 sbrooks Exp $


use base 'Health';
use NWS::A5K;
use Ilist;
use Message;
use Catalog;
use Report;
use Events;
use strict;
use Debug;
sub revision {'$Revision: 1.4 $'}



sub all_logic {
  my($hm, $report) = @_;
  my($ev, $ed, $pertains, $x ,$y, $contain, $sd);
  my($orep, $comp);
  $DB::single = 1;
  my($rep)     = $report->content;
  my($oreport) = PDM->getOldReport($report->fileKey);
  my $wwn      = $rep->{'id.wwn'};

  my($log)     = $report->log();
  my($id)      = $report->id("display");
  CIM->version("1.1");
  if (!$wwn) {
     Debug->err(ERROR => "This A5000 ($wwn) cannot be identified");
     return;
  }

  return if ( $hm->connectionEvent($wwn, $report, {method => 1, threshold_severity => 0} )); # return if cannot_connect

  my $freq  = System->get_renv()->{audit_freq} || 7;
  my $audit = System->get_audit() ? "YES" : Timer->isXdays("Audit$wwn", $freq);

  if (!$oreport || $audit  eq "YES" ) {  # new t300 or audit time.
     Agent::A5K->disks_display("*", $rep);  # add the disk details.

     my($etype) = $audit eq "YES" ? "a5k.AuditEvent" : "a5k.DiscoveryEvent";
     my($title) = $audit eq "YES" ? "Auditing a ":"Discovered a new ";
     my($dt)    = "A" if (!$audit);
     Grid->setCode($etype);
     $ev = CIM::Instance->new('NWS_Event', [
                  [ EventType   => $etype ],
                  [ Target      => "a5k:$wwn"   ],
                  [ TargetName  => $id    ],
                  [ EventId     => PDM->getEventSequence  ],
                  [ Description => "$title A5K called $id"],
                  [ Data        => $hm->serial($rep) ],
                         ]);

     $sd = Events->sourceDetector({ event => $ev , host => 1, rep => $rep});
      
     my($p) = NWS::A5K->newSystem($rep);

     $pertains = CIM::Instance->new('NWS_EventPertainsToSystem', [
                  [ Event       => $ev  ],
                  [ Element     => $p->[0] ],
                  [ DiscoveryType => $dt],
                    ]);

     my($monitors) = CIM::Instance->new('NWS_AgentMonitors', [
                  [ Agent       => $sd->[0]  ],
                  [ Element     => $p->[0] ],
                    ]);

     $ed = Message->new( { id        => $report->id,
                            instances => [$ev, @$sd, @$p, $monitors, $pertains ],
                            severity  => Message::SEVERITY_NORMAL });

     PDM->saveMessage($ed);

  } elsif (System->get_audit()) {
     Agent::A5K->disks_display("*", $rep);  # add the disk details.

  }
  $orep = ($oreport)? $oreport->content() : $rep; # same report if new disco.

  $hm->locationChangeEvent($report, $rep, $orep, $wwn);
  my($physicalFrame) = CIM::Key->new( ['CIM_PhysicalFrame', # frame key 
                       Tag               => $wwn,
                       CreationClassName => 'CIM_PhysicalFrame' ]);

  my($j);
  foreach my $slot ('disk_front','disk_rear') {
    for ($j=0; $j < 20; $j++) {
      last if (!$rep->get("disk_front.$j.exist"));#  no more disks
      my($comp) = "$slot.$j";
      my($oserial) = Util->rtrim($orep->get("$comp.wwn")) ;
      my($nserial) = Util->rtrim($rep->get("$comp.wwn")) ;
      if ($oserial eq $nserial) {
         Grid->setCode("a5k.StateChangeEvent.disk");
         $hm->stateEvent($comp, $report, $rep, $orep, 'CIM_PhysicalPackage', $nserial, $wwn);
      } else {
         if ($oserial) {
           if ($rep->{"$comp.status"} =~ /Bypassed/) {
              Grid->setCode("a5k.StateChangeEvent.disk");
              $hm->stateEvent($comp, $report, $rep, $orep, 'CIM_PhysicalPackage', $nserial, $wwn);
             
           } else {
             Grid->setCode("a5k.ComponentRemoveEvent.disk");
             $hm->removeCompEvent($comp,$physicalFrame, $report, $orep, 'CIM_PhysicalPackage',$oserial, $wwn);
           }
         }
         if ($nserial && $nserial !~ /^0+$/) {
           Agent::A5K->disks_display($comp, $rep);  # add the disk details.
          
           my($disk) = NWS::A5K->newDiskDrive($rep, $comp);
           Grid->setCode("a5k.ComponentInsertEvent.disk");
           $hm->insertCompEvent($comp,$physicalFrame, $report,  $orep, $disk, $nserial, $wwn);
         }
      }
    }
  }
  for ($j = 0; $j <= 2 ; $j++) {
    $comp = "power.$j";
    Grid->setCode("a5k.StateChangeEvent.power");
    $hm->stateEvent($comp, $report, $rep, $orep, 'CIM_PhysicalPackage', $comp, $wwn);
  }
  my($s1, $s2);
  foreach $j ('A','B') {
    $comp = "interface_board.$j";
    Grid->setCode("a5k.StateChangeEvent.interface.iboard");
    $hm->stateEvent($comp, $report, $rep, $orep, 'CIM_Card', "$wwn.$comp", $wwn);
    if (exists($rep->{"$comp.mpx.state"}))  {
       Grid->setCode("a5k.AlarmEvent.interface.mpx");
      $hm->mapValueChangeEvent($report, $orep, "A5K", $comp, "mpx.state", $id, $id, $wwn, "mpx.state");
    }

    for my $j1 ('0','1') {
      Grid->setCode("a5k.AlarmEvent.interface.gbic");
      $hm->mapValueChangeEvent($report, $orep, "A5K", "$comp.gbic$j1","status", $id, "$comp GBIC $j1", $wwn, "gbic.status");
    }
  }

# 'Non-CriticalFailure:YellowLEDison:FanspeedHi'

  for ($j=0; $j < 2; $j++) {
      $rep->{"fan.$j.status"} = "non_critical_failure" if ($rep->{"fan.$j.status"}  =~ /Non-CriticalF/);
      $orep->{"fan.$j.status"} = "non_critical_failure" if ($orep->{"fan.$j.status"}  =~ /Non-CriticalF/);
      Grid->setCode("a5k.AlarmEvent.backplane.fan");
      $hm->mapValueChangeEvent($report, $orep, "A5K", "fan.$j", "status", $id, $id, $wwn, "fan.status");
  }

  foreach $j ('front', 'rear') {
     Grid->setCode("a5k.AlarmEvent.backplane");
     $hm->mapValueChangeEvent($report, $orep, "A5K", "backplane.$j", "status", $id, $id, $wwn, "backplane.status");
  }
         

}


sub status {
   my($hm, $rep, $orep, $comp) = @_;
   my($map) = PDM->getDeviceStateMap("a5k.availability");
   my($state, $ostate, $status, $ostatus, $old, $new, $sev, $act);

   if ($comp =~ /disk/) { # disk have state and status
     $state   = $rep->getState("$comp.state");
     $ostate  = $orep->getState("$comp.state");
     $status  = $rep->getState("$comp.status");
     $ostatus = $orep->getState("$comp.status");

     ($old, $new, $sev, $act) = $map->transition("disk.status.$ostatus-$ostate",
                                       "disk.status.$status-$state", $orep, $rep);

     return ("$ostatus-$ostate", "$status-$state", $old, $new, $sev, $act);

   } elsif ($comp =~ /interface_board/) {
     $status  = $rep->getState("$comp.status");
     $ostatus = $orep->getState("$comp.status");
     ($old, $new, $sev, $act) = $map->transition("interface_board.status.$ostatus", "interface_board.status.$status", $orep, $rep);

     return ($ostatus, $status, $old, $new, $sev, $act);
   } elsif ($comp =~ /power/) {
     $status  = $rep->getState("$comp.status");
     $ostatus = $orep->getState("$comp.status");
     ($old, $new, $sev, $act) = $map->transition("power.status.$ostatus", "power.status.$status", $orep, $rep);
     return ($ostatus, $status, $old, $new, $sev, $act);

   } else {
     $status  = $rep->getState("$comp.status");
     $ostatus = $orep->getState("$comp.status");
     ($old, $new, $sev, $act) = $map->transition("status.$ostatus", "status.$status", $orep, $rep);
     return ($ostatus, $status, $old, $new, $sev, $act);
   }
}


#
# static method
# returns status-state and 0/1
#   disk_front.0
#   disk_front.1
#   disk_front.2
#   disk_front.3
#   disk_front.4
#   disk_front.5
#   disk_front.6
#   disk_front.7
#   disk_front.8
#   disk_front.9
#   disk_front.10
#   disk_rear.0
#   disk_rear.1
#   disk_rear.2
#   disk_rear.3
#   disk_rear.4
#   disk_rear.5
#   disk_rear.6
#   disk_rear.7
#   disk_rear.8
#   disk_rear.9
#   disk_rear.10
#   power.0
#   power.1
#   power.2
#   interface_board.A
#   interface_board.B



sub compStatus {
   my($hm, $rep, $orep, $comp) = @_;

   my($map) = PDM->getDeviceStateMap("a5k.availability");
   my($state, $status, $new);

   if ($comp =~ /disk/) { # disk have state and status
     $state   = $rep->get("$comp.state");
     $status  = $rep->get("$comp.status");

     $new = $map->get("disk.status.$status") . $map->get("disk.state.$state");

     $new = ($new eq "11")? 1:0;
     return ("$status-$state", $new);

   } else {
     $status  = $rep->get("$comp.status");
     $new = $map->get("status.$status");

     return ($status, $new);
   }
}
   


1;
