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

#  or A1000
#  $Name: bld61_002 $ 
#  $Id: A3500FC.pm,v 1.6 2005/04/20 17:23:30 sbrooks Exp $


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


sub all_logic {
  my($hm, $report) = @_;
  my($ev, $ed, $pertains, $x ,$y, $contain, $sd);
  my($orep, $key);
  my($rep)     = $report->content;
  my($oreport) = PDM->getOldReport($report->fileKey);
  my($category) = $report->category();
  my($ucategory) = lc($category);
  my($id)        = $report->id('display');

  $key      = $report->id('deviceName');
  
  my($log)  = $report->log();
  if (!$key) {
     Debug->err(ERROR => "This $category ($id) cannot be identified");
     return;
  }
  CIM->version("1.1");
  $DB::single = 1;

  $hm->logEvent($log, $report, $key, undef, Message::SEVERITY_WARNING) if ($log);
  return if ($hm->connectionEvent($key, $report, {method => 1, threshold_severity => 0}));

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

  if (!$oreport || $audit  eq "YES" ) {  # new t300 or audit time.
     my($etype) = $audit eq "YES" ? "$ucategory.AuditEvent" : "$ucategory.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      => "$category:$key"    ],
                  [ TargetName  => $id     ],
                  [ EventId     => PDM->getEventSequence  ],
		  [ Description => "$title $ucategory called $id"],
                  [ Data        => $hm->serial($rep) ],
                         ]);


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

     $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);
     if ($audit) {  # dump stats.

        Grid->setCode("$ucategory.Statistics");
        $ev = CIM::Instance->new('NWS_Event', [
                  [ EventType   => "$ucategory.Statistics"  ],
		  [ Target      => "$category:$key"    ],
                  [ TargetName  => $id     ],
                  [ EventId     => PDM->getEventSequence  ],
                  [ Description => "Statistics about $ucategory with ID:$key:"],
                  [ Data        => Util->nnl($rep->toString('device_info.'))],
                         ]);

        $sd = Events->sourceDetector({ event => $ev});

        my($key1) = CIM::Key->new( ['NWS_System',
                   'Name'             =>  $rep->get('id.ctrl_id'),
                    CreationClassName => 'NWS_System']);

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

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

        PDM->saveMessage($ed);

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

  $hm->locationChangeEvent($report, $rep, $orep, $key);

  my($physicalFrame) = CIM::Key->new( ['CIM_PhysicalFrame',   # key of the frame
                        Tag               => $key,
                        CreationClassName => 'CIM_PhysicalFrame' ]);

  my $hck  =  $rep->get("device_info.healthck") ;
  my $ohck = $orep->get("device_info.healthck") ;

  if ($hck ne $ohck || ($rep eq $orep && $hck ne "Optimal") ) {
     my $desc0;
     if ($rep eq $orep) {
        $desc0 = "HealthCheck on '$key' is '$hck'";
     } else {
        $desc0 = "HealthCheck on '$key' changed from '$ohck' to '$hck'";
     }
     Grid->setCode("$ucategory.AlarmEvent.healthck");
     $hm->valueChangeEvent("device_info.healthck", "", $report, $key, $desc0, 
              ($hck eq "Optimal,"? 0:2), "healthck");
  }

  Grid->setCode("$ucategory.AlarmEvent.battery");

  $hm->mapValueChangeEvent($report, $orep, "A3500FC", "device_info.battery", "status", $id, $id, $key, "battery.status");

  my($CTRL) = $rep->get('controller.count');
# CONTROLLER (1)
# check if disks were replaced or their state has changed.

  my($comp);
  foreach $x ('a','b') {
     my($oserial, $nserial);
     if ($rep->get("controller.$x.device")) {
       $oserial =  $orep->get("device_info.$x.Vendor_ID") . "." . 
                   $orep->get("controller.$x.serial");
       $nserial = $rep->get("device_info.$x.Vendor_ID") . "." .
                  $rep->get("controller.$x.serial");
       $oserial = "" if ($oserial eq ".");
       $nserial = "" if ($nserial eq ".");

       $comp = "controller.$x";
       if ($oserial eq $nserial) {
          Grid->setCode("$ucategory.StateChangeEvent.controller");
          $hm->stateChangeEvent($comp, 'controller_status', $report, $rep, $orep, 'CIM_Card', $nserial, $key);
       } else {
          if ($oserial) {
            Grid->setCode("$ucategory.ComponentRemoveEvent.controller");
            $hm->removeCompEvent($comp,$physicalFrame,$report, $orep, 'CIM_Card',$oserial, $key);
          }
          if ($nserial) {
            my($part) = NWS::A3500FC->newController($rep, $comp, $category);
            Grid->setCode("$ucategory.ComponentInsertEvent.controller");
            $hm->insertCompEvent($comp,$physicalFrame, $report, $orep, $part, $nserial, $key);
          }
       }
     }
  }

# DISKS (9)
  for ($y=0; $y < $rep->get('disk.count'); $y++) {
      $comp = "disk.$y";
      my($nserial) = $rep->get("disk.$y.vendor") . "." . $rep->get("disk.$y.serial");
      my($oserial) = $orep->get("disk.$y.vendor"). "." . $orep->get("disk.$y.serial");
      $oserial = "" if ($oserial eq ".");
      $nserial = "" if ($nserial eq ".");
      if ($oserial eq $nserial) {
           Grid->setCode("$ucategory.StateChangeEvent.disk");
           $hm->stateChangeEvent($comp, 'disk_status', $report, $rep, $orep, 'CIM_PhysicalPackage', $nserial, $key);
      } else {
           if ($oserial) {
             Grid->setCode("$ucategory.ComponentRemoveEvent.disk");
             $hm->removeCompEvent($comp,$physicalFrame,$report, $orep, 'CIM_PhysicalPackage',$oserial, $key);
           }
           if ($nserial) {
             my($part) = NWS::A3500FC->newDiskDrive($rep, $comp, $category);
             Grid->setCode("$ucategory.ComponentInsertEvent.disk");
             $hm->insertCompEvent($comp,$physicalFrame, $report, $orep, $part, $nserial, $key);
           }
     }
  }

#  LUNS 

  my($INSERTS, $DELETES, $UPDATES) = $hm->idu_map($rep, $orep, "lun", "device");

  # $el = "device ctd", $comp = "lun.0"

  foreach my $el (keys %$DELETES) {
     my $comp = $DELETES->{$el};                       
     Grid->setCode("$category.ComponentRemoveEvent.lun");
     $hm->removeCompEvent($comp, $physicalFrame, $report, $orep, 'NWS_StorageVolume',
             $el , $key, { logicalDevice => 1});

  }
  foreach my $el (keys %$INSERTS) {
     my $comp = $INSERTS->{$el};
     Grid->setCode("$category.ComponentInsertEvent.lun");
     my $newvol = NWS::A3500FC->newVolume($rep, $comp, $category);
     $hm->insertCompEvent($comp, $physicalFrame, $report, $orep, $newvol,
             "$key.$comp", $key, { logicalDevice => 1});

  }
}
  

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

   $ostate = $orep->getState("$comp.state");
   $state  = $rep->getState("$comp.state");
   ($old, $new, $sev, $act) = 
         $map->transition("controller.state.$ostate", "controller.state.$state", $orep, $rep);
   return ($ostate, $state, $old, $new, $sev, $act);
}

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

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


# will return the state of the mentioned component and 0/1 for availability
# static method
# comp = 
#=controller.a
#=controller.b
#=disk.0
#=disk.1
#=disk.2
#=disk.3
#=disk.4
#=disk.5
#=disk.6
#=disk.7
#=disk.8
#=disk.9


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

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

   if ($comp =~ /controller/) {
      $state  = $rep->get("$comp.state");
      $new    = $map->get("controller.state.$state");
   } else {
      $state  = $rep->get("$comp.status");
      $new    = $map->get("disk.status.$state");
   }

   $new = ($new eq "1")? 1:0;

   return ($state, $new);

}


1;
