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

#  ONLY RUNS AGAINST RACKS DISCOVERED AS SINGLE DEVICE

#  $Id: SE_MODULE.pm,v 1.18 2005/04/20 17:23:33 sbrooks Exp $

use base 'Health';
use NWS::SE;
use Ilist;
use Message;
use Catalog;
use Report;
use System;
use Events;
use strict;
use Debug;

sub revision {'$Revision: 1.18 $'}
#


sub all_logic {
  my($hm, $report) = @_;
  my($ev, $ed, $pertains, $x ,$y, $contain, $sd);
  my($orep, $key);
# DO NOTHING FOR NOW
  my $renv     = System->get_renv();

  #return if (!$renv->{include_se_device});

  my $rep      = $report->content;
  my $oreport  = PDM->getOldReport($report->fileKey);
  my($ip)      = $report->id('ip');
  $DB::single = 1;
  my $wwn      = $report->id('deviceName');
  my($id)      = $report->id('display');
  my $shortid  = $report->name();
  my $mgmtLevel = $report->value('id.mgmtLevel') || 'D';
  my $se        = $report->category();

  CIM->version("1.1");

  if ($hm->connectionEvent($wwn, $report, {method => 2, threshold_severity => 0} )) {  # IB / OOB
     return;
  }
  my $freq  = $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.
     my($etype) = $audit eq "YES" ? "$se.AuditEvent" : "$se.DiscoveryEvent";
     my($title) = $audit eq "YES" ? "Auditing":"Discovering";
     my($dt)    = "A" if (!$audit);
     Grid->setCode($etype);
     $ev = CIM::Instance->new('NWS_Event', [
                  [ EventType   => $etype  ],
                  [ Target      => "$se:$wwn"    ],
                  [ TargetName  => $id     ],
                  [ MgmtLevel   => $mgmtLevel],
                  [ SourceIP    => $ip     ],
                  [ EventId     => PDM->getEventSequence  ],
                  [ Description => "$title  $id"],
                         ]);

     $sd = Events->sourceDetector({ event => $ev , host => 1, rep => $rep});
      
     my($p) = NWS::SE->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',   # key of the frame
                        Tag               => $rep->get("id.wwn") ,
                        CreationClassName => 'CIM_PhysicalFrame' ]);

  #ALARMS ON NEW NON-EMPTY CORE FILES
  foreach my $el (keys %$rep) {
    if ($el =~ /^core\.(.+)/) {
       my $file = $1;
       if ($rep->{$el} > 0 && $orep->{$el} ne $rep->{$el}) {
          Grid->setCode("$se.AlarmEvent.core_file");
          $hm->alarmEvent("core_file", "", $report, $wwn,
            "New core file $file available for download in Storage A.D.E. UI", 2, "core_file", { mgmtLevel => "D" } );
       }
    }
  }


  # SEQUENCER EVENT
  # ON is good
  my $seq_status     = $rep->get('info.power_sequencer.status');
  my $seq_status_err = $rep->get('info.power_sequencer.error');
  my $oseq_status    = $orep->get('info.power_sequencer.status');
  if ($seq_status ne $oseq_status) {
    Grid->setCode("$se.AlarmEvent.power_sequencer");
    if ($seq_status eq "ERR_TIMEOUT"){
      Grid->setCode("$se.AlarmEvent.power_sequencer_timeout");
    }
    my $sev = $seq_status eq "ON" ? 0:2;
    $hm->alarmEvent("power_sequencer", "", $report, $wwn,
       "Power sequencer on $id changed from '$oseq_status' to '$seq_status' ".
       "($seq_status_err)", $sev, "power_sequencer",
           { mgmtLevel => "D" } );

  }
  
  # FC-EVENTS
  $hm->fcEvent($rep->{FC_COUNTERS}, $orep->{FC_COUNTERS});

  my $SLOTS  = $rep->get('info.slotTotal');
  my $OSLOTS = $orep->get('info.slotTotal');
  my($comp);
  my($okey, $nkey);
  my $MAX = ($SLOTS > $OSLOTS) ? $SLOTS : $OSLOTS;

  if ($renv->{solution} eq "N") {
    Grid->setCode("$se.StateChangeEvent.sp");
    $hm->sevStateEvent("slot.0", $report, $rep, $orep, 'NWS_Slot', $rep->get("slot.0.dev-key"), $wwn, {logical => 1, label => "The Service Processor of", display_comp => $rep->{"slot.0.dev-name"}  });
  }

#
# SLOTS
#
  for ($x = 1; $x < $MAX; $x++) {
     $comp = "slot.$x";
     $okey = $orep->get("$comp.dev-key");
     $nkey =  $rep->get("$comp.dev-key");
     my $type =  $rep->get("$comp.dev-type");

     if ($okey eq $nkey) {
         my $S = $nkey;
         Grid->setCode("$se.StateChangeEvent.$type");
         if ($renv->{solution} eq "N") {  # generate from outside the rack only
            $hm->sevStateEvent($comp, $report, $rep, $orep, 'NWS_Slot', $S, $wwn, 
              {logical => 1, label => "'" . $rep->get("$comp.dev-name") . "' on",
               display_comp => $rep->{"$comp.dev-name"}  });
         }
     } else {
         if ($okey) {
           Grid->setCode("$se.ComponentRemoveEvent.slot");
           $hm->removeCompEvent($comp,$physicalFrame, $report, $orep, 'CIM_Card',$okey, $wwn, {system => 1});
         }
         if ($nkey) {
           my($ctrl) = NWS::SE->newSlot($rep, $comp);
           Grid->setCode("$se.ComponentInsertEvent.slot");
           $hm->insertCompEvent($comp,$physicalFrame, $report, $orep, $ctrl, $nkey, $wwn, 
                    {system => 1, display_comp => $rep->{"$comp.dev-name"} });
         }
     }
  }

  for ($x=$SLOTS+1; $x < $OSLOTS; $x++) {
     $comp = "slot.$x";
     $okey = $orep->get("$comp.dev-key");
     Grid->setCode("$se.ComponentRemoveEvent.slot");
     $hm->removeCompEvent($comp,$physicalFrame, $report, $orep, 'CIM_Card',$okey, $wwn, 
                    {system => 1, display_comp => $orep->{"$comp.dev-name"} });
  }


  return if ($renv->{solution} ne "N"); # DON"T GENERATE ANY MORE EVENTS IF IN A RACK

# 
# PORTS
#
  for ($x = 0; $x < $rep->get("info.portTotal") ; $x++) {
      $comp = "fcPort.$x";
      if (exists($orep->{"$comp.status-avail"})) {
         my $exname = $rep->{"$comp.encName"};
         Grid->setCode("$se.StateChangeEvent.port");
         $hm->sevStateEvent($comp, $report, $rep, $orep, 'CIM_Card', $comp, $wwn, 
           {label => "External Port of $exname on "} );
      }
  }
  
# 
# LUNS
#
  my (%L, %OL);
  my $LUNS  =  $rep->get('info.lunTotal');
  my $OLUNS =  $rep->get('info.lunTotal');

  for ($x=1; $x <= $LUNS; $x++) {
     my $wwn    = $rep->get("lun.$x.lunWwn");
     my $status = $rep->get("lun.$x.lunStatus");
     my $name   = $rep->get("lun.$x.lunName");
     next if (!$wwn || $wwn =~ /^0*$/);
     $L{$wwn} = [$status, $name, $x];
  }
  for ($x=1; $x <= $OLUNS; $x++) {
     my $wwn    = $orep->get("lun.$x.lunWwn");
     my $status = $orep->get("lun.$x.lunStatus");
     my $name   = $orep->get("lun.$x.lunName");
     next if (!$wwn || $wwn =~ /^0*$/);
     $OL{$wwn} = [$status, $name, $x];
  }
  foreach my $wwn0 (keys %L) {
     my $w1  = $L{$wwn0};
     my $comp= "lun." . $w1->[2];
     if (exists($OL{$wwn0})) {
        my $w2  = $OL{$wwn0};
        my $st1 = $w1->[0];
        my $st2 = $w2->[0];
        if ($st1 ne $st2) {
           Grid->setCode("$se.AlarmEvent.lun");
           $hm->mapValueChangeEvent($report, $orep, uc($se), $comp, "lunStatus", $id, $id, $wwn, 
                      undef, { info => $w1->[1] } );
        }
     } else {
        my $lun = NWS::SE->newLun($rep, $comp);
        Grid->setCode("$se.ComponentInsertEvent.lun");
        $hm->insertCompEvent($comp, $physicalFrame, $report, $orep, $lun, $wwn0, $wwn, 
                              {logicalDevice => 1} );
     }
  }
  foreach my $wwn0 (keys %OL) {
     my $w1  = $OL{$wwn0};
     my $comp= "lun." . $w1->[2];
     if (!exists($L{$wwn0})) {
         Grid->setCode("$se.ComponentRemoveEvent.lun");
         $hm->removeCompEvent($comp, $physicalFrame, $report, $orep, 'NWS_StorageVolume', $wwn0, $wwn, {logicalDevice => 1});
     }
  }
}

  
sub status {
   my($hm, $rep, $orep, $comp) = @_;
   my @SEV = ('notice','warning','error','critical');

   my $osev =  $orep->get("$comp.status-sev") || 0;
   my $nsev =  $rep->get("$comp.status-sev") || 0;

   my $odetails = State->eventHash($orep->get("$comp.status-details"));
   my $ndetails = State->eventHash($rep->get("$comp.status-details"));

   my $ocaption = $odetails->{Caption};
   $ocaption = substr($ocaption,2) if ($ocaption =~ /^[MP]\./);

   my $ncaption = $ndetails->{Caption};
   $ncaption = substr($ncaption,2) if ($ncaption =~ /^[MP]\./);

   my $ocomp = $odetails->{Component} || $ocaption;
   my $ncomp = $ndetails->{Component} || $ncaption;
   my $otime = substr($orep->get("$comp.status-desc"), 0, 19);
   my $ntime = substr( $rep->get("$comp.status-desc"), 0, 19);

   my $old    = "$odetails->{Target}:$odetails->{EventType}:$ocomp:$SEV[$osev]:$otime";
   my $new    = "$ndetails->{Target}:$ndetails->{EventType}:$ncomp:$SEV[$nsev]:$ntime";

   my $oavail =  $orep->get("$comp.status-avail");
   my $navail =  $rep->get("$comp.status-avail");
   my $desc   =  $rep->get("$comp.status-desc");
   $desc = "is now in a normal state" if ($desc eq "OK");

   return ($old, $new, $osev, $nsev, $oavail, $navail, $desc);
}



1;
