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


#       "@(#)D2Health.pm 1.4     01/09/18 SMI"


use base 'Health';
use NWS::D2;
use Ilist;
use Message;
use Report;
use Events;
use strict;
use Debug;
sub revision {'$Revision: 1.5 $'}




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 $name     = $rep->{'id.name'};
  my $wwn      = $rep->{'id.wwn'};
  my $id       = "$name with serial:$wwn";

  CIM->version("1.1");
  if (!$wwn) {
     Debug->err(ERROR => "This D2 ($name) cannot be identified");
     return;
  }
  $wwn = "SUN.D2.$wwn";

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

  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 D2 or audit time.

     my($etype) = $audit eq "YES" ? "d2.AuditEvent" : "d2.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 ],
                  [ EventId     => PDM->getEventSequence  ],
                  [ Description => "$title D2 $id"],
                  [ Data        => $hm->serial($rep) ],
                         ]);

     $sd = Events->sourceDetector({ event => $ev , host => 1, rep => $rep});
      
     my($p) = NWS::D2->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);

  }
  $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               => "SUN.D2.$wwn",
                       CreationClassName => 'CIM_PhysicalFrame' ]);

  my($j, $s1, $s2);

  foreach my $comp ('midplane', 'esm.0', 'esm.1') {
      my($oserial) = Util->rtrim($orep->get("$comp.serial"));
      my($nserial) = Util->rtrim($rep->get("$comp.serial")) ;
      my $eg = $comp eq "midplane" ? "midplane" : "esm";
      if ($oserial ne $nserial) {
         if ($oserial) {
            Grid->setCode("d2.ComponentRemoveEvent.$eg"); # eg=midplane,esm
            $hm->removeCompEvent($comp,$physicalFrame, $report, $orep,
                        'CIM_PhysicalPackage',$oserial, $wwn);
         }
         if ($nserial) {
           my($disk) = NWS::D2->newSCSI($rep, $comp);
           Grid->setCode("d2.ComponentInsertEvent.$eg"); # midplane,esm
           $hm->insertCompEvent($comp,$physicalFrame, $report,  $orep, $disk, $nserial, $wwn);
         }
      }
      my $date = $rep->get("$comp.date");
      my $odate = $orep->get("$comp.date");
      if ($date ne $odate) {
          my $desc = "The revisionDate of $comp on $id changed from $odate to $date";
          Grid->setCode("d2.AlarmEvent.$eg.revision");
          $hm->valueChangeEvent("$comp.date", "", $report, $wwn, $desc, 1, "revision" );
      }
      my $rev = $rep->get("$comp.revision");
      my $orev = $orep->get("$comp.revision");
      if ($rev ne $orev) {
          my $desc = "'$comp.revision' on D2 $wwn changed from $orev to $rev";
          Grid->setCode("d2.AlarmEvent.$eg.revision");
          $hm->valueChangeEvent("$comp.revision", "", $report, $wwn, $desc, 1, "revision" );
      }
  }
  foreach my $esm (0,1) {
    for ($x=0; $x < $rep->get("slot.$esm.total"); $x++) {
      my $comp = "slot.$esm.$x";
      my($nserial) = "$wwn.$comp";
      Grid->setCode("d2.StateChangeEvent.esm");
      $hm->stateChangeEvent($comp, 'status', $report, $rep, $orep, 'CIM_PhysicalPackage', $nserial, $wwn);
    }
  }
  
  Grid->setCode("d2.AlarmEvent.power");
  for ($x=0; $x <= 1; $x++) {
    $hm->mapValueChangeEvent($report, $orep, "D2", "power.$x", "status", $id, "Power.$x $id", $wwn, "power.status");
  }

  Grid->setCode("d2.AlarmEvent.fan");
  for ($x=0; $x <= 1; $x++) {
    $hm->mapValueChangeEvent($report, $orep, "D2", "fan.$x", "status", $id, "Fan.$x $id", $wwn, "fan.status");
  }

  foreach my $esm (0,1) {
    if ($rep->get("slot.$esm.total") ne $orep->get("slot.$esm.total")) {
      my $desc = "The number of slots on $id changed from " . $orep->get("slot.$esm.total") . " to ".
               $rep->get("slot.$esm.total");
      Grid->setCode("d2.AlarmEvent.slot_count");
      $hm->valueChangeEvent("slot.$esm", "", $report, $wwn, $desc, 1, "slot_count" );
    }
  }

  foreach my $el ( 'temperature') {
    my $rev = $rep->get("info.$el");
    my $orev = $orep->get("info.$el") || '[undefined]';

    if ($rev ne $orev) {
      my $desc = "'$el' on D2 $id changed from $orev to $rev";
      Grid->setCode("d2.AlarmEvent.temperature");
      $hm->valueChangeEvent("info.$el", "", $report, $wwn, $desc, 1, "temperature" );
    }
  }


}

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

   $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);
}






1;
