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

#  $Name:  $ 
#  $Id: MCDATA.pm,v 1.4 2004/10/27 22:43:22 mckenney Exp $


use base 'Health';
use NWS::MCDATA;
use Ilist;
use Message;
use Report;
use Catalog;
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, $key);
  my($rep)     = $report->content;
  my($oreport) = PDM->getOldReport($report->fileKey);
  my($ip)      = $report->id('ip');
  my($name)    = $report->name;
  my $wwn      = $report->id('deviceName');
  my($id)      = $report->id('display');
  my($log)     = $report->log();
  if (!$wwn) {
     Debug->errNoRepeat(T3_NO_KEY => $ip, 24, "Switch ($name/$ip) cannot be identified");
     return;
  }

  CIM->version("1.1");
  $DB::single = 1;

  return if ($hm->connectionEvent($wwn, $report, {method => 2} ));
  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 MCDATA or audit time.
     my($etype) = $audit eq "YES" ? "mcdata.AuditEvent" : "mcdata.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      => "mcdata:$wwn" ],
                  [ TargetName  => $id  ],
                  [ SourceIP    => $ip  ],
                  [ EventId     => PDM->getEventSequence  ],
                  [ Description => "$title McDATA Switch called $id"],
                  [ Data        => $hm->serial($rep) ],
                         ]);

     $sd = Events->sourceDetector({ event => $ev , host => 1, rep => $rep});
      
     my($p) = NWS::MCDATA->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);
     if ($audit) {  # dump stats.

        Grid->setCode("mcdata.Statistics");
        $ev = CIM::Instance->new('NWS_Event', [
                  [ EventType   => 'mcdata.Statistics'  ],
                  [ Target      => "mcdata:$wwn" ],
                  [ TargetName  => $id  ],
                  [ SourceIP    => $ip  ],
                  [ EventId     => PDM->getEventSequence  ],
                  [ Description => "Statistics about McDATA Switch $id :"],
                  [ Data        => Util->nnl($rep->toStringP('port.\d+.stats'))],
                         ]);

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

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

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

        $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.

  #
  # check sensors for changes
  #
  my($type, $status, $ostatus, $val, $oval);
  foreach my $el ('fan', 'powerSupply') {
    for ($x=1; $x <= 20; $x++) {
      $type    = $rep->get("sensor.$el.$x.status");
      last if (!$type);
      if ($el eq "fan") {
         Grid->setCode("mcdata.AlarmEvent.fan");
      } else {
         Grid->setCode("mcdata.AlarmEvent.power");
      }
      $hm->mapValueChangeEvent($report, $orep, "MCDATA", "sensor.$el.$x", "status", $id, $id, $wwn, "sensor.$el.status");
    }
  }

  return if (!$oreport); # We want to return if there was no old report but we wanted
                         # to at least check the original state of the sensors.



  $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' ]);

  my($PORTS) = $rep->get('port.count');
  $hm->fcEvent($rep->{FC_COUNTERS}, $orep->{FC_COUNTERS});

# check if port state has changed
# 'port.0.state.AdmStatus' => 'online',

  my($comp);
  for ($x=0; $x <= $PORTS; $x++) {
     $comp = "port.$x"; # . sprintf("%3.3d", $x);
     Grid->setCode("mcdata.StateChangeEvent.port");
     my $extra;
     if (exists $rep->{"$comp.state.AdmStatus"}) {
        $extra = "Admin-Status is '" . $rep->{"$comp.state.AdmStatus"} . "'";
     }
     $hm->stateChangeEvent($comp, 'status', $report, $rep, $orep, 'CIM_Card', "$wwn.$comp", $wwn,
                   {info => $extra});
  }




  Grid->setCode("mcdata.AlarmEvent.port.statistics");
  $hm->portStatEvents($report, $PORTS, $rep, $orep);

  # Check switch up time
  my($olduptime) = $orep->get("system.uptime");
  my($newuptime) = $rep->get("system.uptime");
  my($oldcuptime) = $orep->get("system.calendar_uptime");
  my($newcuptime) = $rep->get("system.calendar_uptime");

  if ($olduptime > $newuptime) {

     # Check for counter wrap
     # There is a bug where the counter will wrap every 49.7 days
     # which is = 429496729 ticks, back this up by 49.0 days to
     # 423360000 
     if(($olduptime > 423360000) && ($olduptime < 429496729)){
       # skip as this could have been a counter wrap with the bug
     }elsif($olduptime >4286304000){
       # Skip as this is within a day of a counter wrap without the bug
     }else{
        # Else send the alert
        Grid->setCode("mcdata.AlarmEvent.system_reboot");
        $hm->valueChangeEvent("system.uptime", "",$report, $wwn, 
           "Switch uptime decreased on $id from $oldcuptime to $newcuptime", 0, "system_reboot");
     }
  }

      
}

  
sub status {
   my($hm, $rep, $orep, $comp) = @_;
   my($map) = PDM->getDeviceStateMap("mcdata.availability");
   Debug->print3("mcdata: $comp");

   my($status)  = $rep->getState("$comp.state");
   my($ostatus) = $orep->getState("$comp.state");
   $status = $ostatus if ($status eq '[undefined]');
   $status      =~ s/\(\d+\)$//;
   $ostatus     =~ s/\(\d+\)$//;

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

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

}


1;

