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

#  $Name:  $ 
#  $Id: MCDATA.pm,v 1.21 2006/05/19 08:14:10 gd201363 Exp $

use strict;
use Agent::SWITCH_Parent;
use base 'Agent::SWITCH_Parent';
use Net::Telnet;
use Util;
#Report::CAT_MCDATA

sub isSelectable {"McDATA"}

sub HEALTH {
  my($agent, $new_rep) = @_;
  require Health::MCDATA;
  Health::MCDATA->all_logic($new_rep);
}

sub revision {'$Revision: 1.21 $'}
sub new {
  my($self) = Agent->new();

  bless ($self, 'Agent::MCDATA');
  return $self;
}
use vars qw($ERR);


sub getWWN {
  my($class, $ip, $host, $TO) = @_;
  my $rc;
  $ERR = undef;
  if ($host) {
      $rc = Util::Http->getCommand($host, "Agent::MCDATA::WWN&ip=$ip&HTTP=1", $TO);
      if ($rc =~ /ERR/) {
         $ERR = $rc;
         return undef;
      } else {
         return substr($rc,4);
      }
  } else {
      return get_WWN({ip => $ip});
  }
}

sub get_WWN {
  my($q) = @_;
  my $ip = $q->{ip};
  my ($name, $wwn);
  my $DIR = System->get_home();
  my $MIBDIR = System->get_home() . "/snmp/share/snmp/mibs/mcdata";
  my $renv = System->get_renv();
  my $TO = $renv->{"timeout.snmp"} || 40;
  my $public = $renv->{'snmp.community'} || "public";
  my $OPT = "-v1 -c$public -r1 -t$TO -m$MIBDIR/fcfe.mib " . System->snmpopt();


  my $comm =   "$DIR/snmp/bin/snmpwalk $OPT $ip fcElementName";
  my($err,$id) = Util->run_command($comm, "getWWN", 2*$TO+5);

  if ($err){
    Debug->errNoRepeat( SNMP_SENSOR => $name , 8, "Run mcdata Command error: $err: $DIR/snmp/bin/snmpwalk $OPT $ip fcElementName");   
  }

  ($name, $wwn) = split(/ *= */, $id->[0]);
  $wwn = lc($wwn);
  $wwn =~ s/hex://; 
  $wwn =~ s/[ "]//g;

  if ($q->{HTTP}) {
    if ($wwn) {
      print "\nOK $wwn";
    } else {
      print "\nERR $err";
    }
  } else {
    return $wwn;
  }
}


sub getDevStatus {
  my($class, $dev) = @_;
  my %R;
  $ENV{LD_LIBRARY_PATH} = System->get_home() . "/bin/lib";
  my $OPT;
  my $ip = $dev->{ip} || $dev->{ipno};

  $ERR = $class->getStatusLinks($OPT, $dev, \%R);
  return ($ERR, \%R);
}


sub getStatusLinks {
  my($class, $OPT, $dev, $R) = @_;
  my($x, $err, $ports, $rem, $portids);
  my $DIR  = System->get_home() . "/snmp";
  my $MIBDIR  = System->get_home() . "/snmp/share/snmp/mibs/mcdata";
  my $renv  = System->get_renv();
  my $TO  = $renv->{'timeout.snmp'} || 10;
  my $public = $renv->{'snmp.community'} || "public";

  # Get number of ports
  my $ip = $dev->{ip} || $dev->{ipno};
  $R->{"port.count"} = $class->getnumports($ip, $dev);


   # Get port admin state and blade/port information
   #fcFxPortPhysAdminStatus.6.3 = online(1)
   #fcFxPortPhysAdminStatus.6.4 = online(1)
   #fcFxPortPhysAdminStatus.7.1 = online(1)
   #fcFxPortPhysAdminStatus.7.2 = online(1)

   $OPT = "-v1 -c$public -r1 -t$TO -m$MIBDIR/fcfe.mib " . System->snmpopt();
   my ($portinfo);
   ($err,$portinfo) = Util->run_command(
                 "$DIR/bin/snmpwalk $OPT $ip fcFxPortPhysAdminStatus ", 
                 "sanbox_version.txt", 2*$TO+5);

   if ($err){
     Debug->errNoRepeat( SNMP_SENSOR => $dev->{name} , 8, "Run mcdata Command error: $err: $DIR/bin/snmpwalk $OPT $ip fcFxPortPhysAdminStatus ");   
   }

   foreach my $l (@$portinfo) {
      if ($l =~ /^fcFxPortPhysAdminStatus.(\d+)\.(\d+) = (.+)/) {
	    my $value = $3;
	    my $blade = $1 - 1;
	    my $blade_port = $2 - 1;
	    my $gl_port = ($blade  * 4) + $blade_port;
            my $ix = index($value,"(");
            my $type = ($ix > 0) ? substr($value,0,$ix) : $value;
            $R->{"port.$gl_port.state.AdmStatus"} = $type;
	    # Save off blade and blade port info
	    $R->{"port.$gl_port.blade"} = $blade;
	    $R->{"port.$gl_port.blade_port"} = $blade_port;
      }
   }



  # get WWN of devices attached to port
  # first get an array of ports and there id's
  #/opt/SUNWstade/snmp/bin/snmpwalk -v1 -c$public -r1 -t10 -m /opt/SUNWstade/snmp/share/snmp/mibs/mcdata/fcmgmt.mib -OsQ  172.20.35.162 fcConnUnitLinkPortNumberX
  #fcConnUnitLinkPortNumberX.'..... ÌL........'.14 = 16
  #fcConnUnitLinkPortNumberX.'..... ÌL........'.15 = 17
  #fcConnUnitLinkPortNumberX.'..... ÌL........'.20 = 20
  #fcConnUnitLinkPortNumberX.'..... ÌL........'.21 = 21
  #fcConnUnitLinkPortNumberX.'..... ÌL........'.22 = 18
  #fcConnUnitLinkPortNumberX.'..... ÌL........'.23 = 19
  my($cmd);
  if ($dev->{oid} !~ /4369/) {

     $OPT = "-v1 -c$public -r1 -t$TO -m$MIBDIR/fcmgmt.mib " . System->snmpopt();
     $cmd = "fcConnUnitLinkPortNumberX";
  }else{
    $MIBDIR  = System->get_home() . "/snmp/share/snmp/mibs";
    $OPT = "-v1 -c$public -t$TO -r1 -M$MIBDIR -mall " . System->snmpopt() . "b";
    $cmd = "connUnitLinkPortNumberX";
  }   
  ($err,$portids) = Util->run_command(
                 "$DIR/bin/snmpwalk $OPT $ip $cmd", 
                 "sanbox_version.txt", 2*$TO+5);
   if ($err){
     Debug->errNoRepeat( SNMP_SENSOR => $dev->{name} , 8, "Run mcdata Command error: $err: $DIR/bin/snmpwalk $OPT $ip $cmd");   
   }

   my (@port_array);
   foreach my $l (@$portids) {
      if ($l =~ /^$cmd.+\.(\d+) = (\d+)/) {
	 $port_array[$1] = $2;
      }
   }

   # now get attached WWN's 
   #/opt/SUNWstade/snmp/bin/snmpwalk -v1 -c$public -r1 -t10 -m/opt/SUNWstade/snmp/share/snmp/mibs/mcdata/fcmgmt.mib -Os  172.20.35.162 fcConnUnitLinkPortWwnY
   #fcConnUnitLinkPortWwnY.'..... ÌL........'.14 =  Hex: 20 04 08 00 88 A0 4C 0E 
   #fcConnUnitLinkPortWwnY.'..... ÌL........'.15 =  Hex: 20 05 08 00 88 A0 4C 0E 
   #fcConnUnitLinkPortWwnY.'..... ÌL........'.20 =  Hex: 20 08 08 00 88 A0 4C 0E 
   #fcConnUnitLinkPortWwnY.'..... ÌL........'.21 =  Hex: 20 09 08 00 88 A0 4C 0E 
   #fcConnUnitLinkPortWwnY.'..... ÌL........'.22 =  Hex: 20 04 08 00 88 A0 28 EA 
   #fcConnUnitLinkPortWwnY.'..... ÌL........'.23 =  Hex: 20 05 08 00 88 A0 28 EA 
   if ($dev->{oid} !~ /4369/) {
     $cmd = "fcConnUnitLinkPortWwnY";
   }else{
     $cmd = "connUnitLinkPortWwnY";
   }   
   ($err,$portids) = Util->run_command(
                 "$DIR/bin/snmpwalk $OPT $ip $cmd", 
                 "sanbox_version.txt", 2*$TO+5);
   if ($err){
     Debug->errNoRepeat( SNMP_SENSOR => $dev->{name} , 8, "Run mcdata Command error: $err: $DIR/bin/snmpwalk $OPT $ip $cmd");   
   }

   foreach my $l (@$portids) {
      if ($l =~ /^$cmd.+\.(\d+) =  Hex: (.+)/) {
         my ($portindex) = $1;
	 my ($wwn) = $2;
	 $wwn =~ s/ //g;
         $R->{"port.$port_array[$portindex].link_wwn"} = lc(substr($wwn,0,16));
      }
   }

   # Get port information - Type, state and status
   #/opt/SUNWstade/snmp/bin/snmpwalk -v1 -c$public -r1 -t10 -m/opt/SUNWstade/snmp/share/snmp/mibs/mcdata/fcmgmt.mib -Os 172.20.35.162 fcConnUnitPortType
   #fcConnUnitPortType.'..... ÌL........'.1 = fPort(8)
   #fcConnUnitPortType.'..... ÌL........'.2 = fPort(8)
   #fcConnUnitPortType.'..... ÌL........'.3 = gPort(10)
   if ($dev->{oid} !~ /4369/) {
     $OPT = "-v1 -c$public -r3 -t$TO -m$MIBDIR/fcmgmt.mib " . System->snmpopt();
     $cmd = "fcConnUnitPort";

   }else{
     $MIBDIR  = System->get_home() . "/snmp/share/snmp/mibs";
     $OPT = "-v1 -c$public -t$TO -r1 -M$MIBDIR -mall " . System->snmpopt() . "b";
     $cmd = "connUnitPort";

   }
   foreach my $el ('Type','State','Status') {
     ($err,$portinfo) = Util->run_command(
                 "$DIR/bin/snmpwalk $OPT $ip $cmd$el", 
                 "sanbox_version.txt", 2*$TO+5);

    if($err){
      my $DIR1  = System->get_home() . "/log/mcdata.error$el";
      Util->dump($err, $DIR1);
     }

      foreach my $l (@$portinfo) {
         if ($l =~ /^$cmd$el.+\.(\d+) = (.+)/) {
	    my $portindex = $1 - 1;
	    my $value = $2;
            my $ix = index($value,"(");
            my $type = ($ix > 0) ? substr($value,0,$ix) : $value;
            $R->{"port.$portindex." . lc($el)} = $type;
	 }
      }
   }



   # Get port wwn's

   if ($dev->{oid} !~ /4369/) {
     $OPT = "-v1 -c$public -r1 -t$TO -m$MIBDIR/fcmgmt.mib " . System->snmpopt();
     $cmd = "fcConnUnitPortWwn";

   }else{
     $MIBDIR  = System->get_home() . "/snmp/share/snmp/mibs";
     $OPT = "-v1 -c$public -t$TO -r1 -M$MIBDIR -mall " . System->snmpopt() . "b";
     $cmd = "connUnitPortWwn";

   }
   

   ($err,$portids) = Util->run_command(
                 "$DIR/bin/snmpwalk $OPT $ip $cmd", 
                 "mcdata.txt", 2*$TO+5);
   if ($err){
     Debug->errNoRepeat( SNMP_SENSOR => $dev->{name} , 8, "Run mcdata Command error: $err: $DIR/bin/snmpwalk $OPT $ip $cmd");   
   }

   #fcConnUnitPortWwn.'..... L.........'.25 =  Hex: 20 1C 08 00 88 A0 4C 0E 
   #fcConnUnitPortWwn.'..... L.........'.26 =  Hex: 20 1D 08 00 88 A0 4C 0E 
   #fcConnUnitPortWwn.'..... L.........'.27 =  Hex: 20 1E 08 00 88 A0 4C 0E 

   foreach my $l (@$portids) {
      if ($l =~ /^$cmd.+\.(\d+) =  Hex: (.+)/) {
         my ($portindex) = $1 - 1;
	 my ($wwn) = $2;
	 $wwn =~ s/ //g;

         $R->{"port.$portindex.stats.Wwn"} = lc($wwn);
      }
   }

}

sub getnumports {
  my($class, $ip, $device) = @_;


  my $DIR  = System->get_home() . "/snmp";
  my $MIBDIR  = System->get_home() . "/snmp/share/snmp/mibs/mcdata";

  my $renv  = System->get_renv();
  my $TO  = $renv->{'timeout.snmp'} || 60;
  my $public = $renv->{'snmp.community'} || "public";
  my $cnt;
  $cnt = 0;
  # Get number of ports
  if ($device->{oid} !~ /4369/) {

     my $OPT  = "-v1 -c$public -r1 -t$TO -m$MIBDIR/ef-6000.mib " . System->snmpopt();
     my ($err,$ports) = Util->run_command(
                 "$DIR/bin/snmpwalk $OPT $ip Ef6000PortIndex", 
                 "sanbox_version.txt", 2*$TO+5);
     if ($err){
       Debug->errNoRepeat( SNMP_SENSOR => $device->{name} , 8, "Run mcdata Command error: $err: $DIR/bin/snmpwalk $OPT $ip Ef6000PortIndex");   
     }
     my $mycount  = $#$ports;
     return $mycount +1;
  }else{
    my $wwn = $device->{wwn};
    my $mibwwn = Util->wwn2mib($wwn);
    $DIR  = System->get_home() . "/snmp/bin";
    $MIBDIR  = System->get_home() . "/snmp/share/snmp/mibs";


    my $OPT = "-v1 -c$public -t$TO -r1 -M$MIBDIR -mall " . System->snmpopt() . "b";
    my ($err,$ports) = Util->run_command(
                 "$DIR/snmpwalk $OPT $device->{ip} connUnitNumports", 
                 "sanbox_version.txt", 2*$TO+5);
    if ($err){
       Debug->errNoRepeat( SNMP_SENSOR => $device->{name} , 8, "Run mcdata Command error: $err: $DIR/snmpwalk $OPT $device->{ipno} connUnitNumports");   
    }



    foreach my $l (@$ports) {
      if ($l =~ /$mibwwn/) {
         my(@a) = split(/ +\= */, $l);
         $cnt = $a[1];
         last;
      }
    }
    return $cnt;
  }
  # Should never hit
  return 0;

}

sub getStats {
  my($class, $OPT, $ip, $R, $dev) = @_;


  my $DIR  = System->get_home() . "/snmp";
  my $MIBDIR  = System->get_home() . "/snmp/share/snmp/mibs/mcdata";


  my $renv  = System->get_renv();
  my $TO  = $renv->{'timeout.snmp'} || 60;
  my $public = $renv->{'snmp.community'} || "public";

  my $OPTS    = "-v1 -c$public -r1 -t$TO -m$MIBDIR/fcfe.mib " . System->snmpopt();



    
  $R->{"port.count"} = $class->getnumports($ip, $dev);


  #Gettting stats take longer than most operations so increase time out.
  $TO = $TO + 30;
 

  my ($err5,$ports) = Util->run_command(
                 "$DIR/bin/snmpwalk $OPTS $ip fcFxPortErrorEntry", 
                 "sanbox_version.txt", 2*$TO+5);


  if ($err5) {
     Debug->print2("snmpwalk $ip fcFxPortErrorEntry: $err5");
     return undef;
  }
  my($ERR_LIST) = ",LinkFailures,SyncLosses,SigLosses,PrimSeqProtoErrors,InvalidTxWords,InvalidCrcs,DelimiterErrors,AddressIdErrors,LinkResetIns,LinkResetOuts,OlsOuts";
  #fcFxPortLinkFailures.1.1 = Counter32: 1
  #fcFxPortLinkFailures.1.2 = Counter32: 1
  #fcFxPortLinkFailures.2.1 = Counter32: 0
 
  my($x, $port, $name);
  foreach my $l (@$ports) {
		 #fcFxPortLinkFailures.2.1 = Counter32: 0
		 #fcFxPortLinkFailures.  2  .  1   = Counter32:   0
		 #fcFxPort(.+        ).(\d+).(\d+) = Counter32: (\d+)
     if ($l =~ /^fcFxPort(.+)\.(\d+)\.(\d+) = Counter32: (\d+)/){
        my $name    = $1;
	my $blade   = $2 - 1;
	my $blade_port = $3 - 1;
	my $gl_port = ($blade * 4) + $blade_port;
	my $value   = $4;

        if (index($ERR_LIST, ",$name,") >= 0) {
           $R->{"port.$gl_port.error.$name"} =  $value;
        } else {
           $R->{"port.$gl_port.stats.$name"} =  $value;
        }
     }
   }




	
}



sub getVersion {
  my($agent, $ip, $device) = @_;

  my $renv  = System->get_renv();
  my $DIR  = System->get_home() . "/snmp";
  my $MIBDIR  = System->get_home() . "/snmp/share/snmp/mibs/mcdata";
  my $TO  = $renv->{'timeout.snmp'} || 60;
  my $public = $renv->{'snmp.community'} || "public";
  my ($name);

  # Get version
  if ($device->{oid} !~ /4369/) {
     my $OPT = "-v1 -c$public -r1 -t$TO -m$MIBDIR/ef-6000.mib " . System->snmpopt();
     my($err_version,$version) = Util->run_command(
                 "$DIR/bin/snmpwalk $OPT $ip ef6000SysFirmwareVersion", 
                 "mcdata.txt", 2*$TO+5);

     if ($err_version) {
        $ERR = $err_version;
        return undef;
     } 
  
     my ($x, $y) = split(/\s*=\s*/, "@$version");
     if (substr($y,0,1) eq "\"") {
        $y = substr($y,1,-1);
     }
     if($y){
        return $y;
     }
  }else{
     # Could be 1620 mcdata switch
     my $wwn = $device->{wwn};
     my $mibwwn = Util->wwn2mib($wwn);
     my $public = $renv->{'snmp.community'} || "public";
     $DIR = System->get_home() . "/snmp/bin";
     $MIBDIR = System->get_home() . "/snmp/share/snmp/mibs";


     $ENV{LD_LIBRARY_PATH} = System->get_home() . "/snmp/lib";
     my $OPT  = "-v1 -c$public -r1 -t$TO -M$MIBDIR -mall " . System->snmpopt() . "b";
     my($err0,$version) = Util->run_command("$DIR/snmpwalk $OPT $ip connUnitRevsRevId.$mibwwn", 
                 "sanbox_version.txt", 2*$TO + 5);

     if ($err0){
       Debug->errNoRepeat( SNMP_SENSOR => $device->{name} , 8, "Run mcdata Command error: $err0: $DIR/snmpwalk $OPT $ip connUnitRevsRevId.$mibwwn");   
     }
     
     foreach my $l (@$version) {
        next if ($l !~ /$mibwwn/);
        if ($l =~ /RevsRevId/) {
           $l =~ /\.(\d+) = (.*)/;
           my $port = $1;
           $name = $2;
           $name =~ s/"//g;
           my $ix = index($name, " Hex:");
           $name = substr($name, 0, $ix) if ($ix > 0);
        } 
     } 
  }
  return $name;

}

sub INSTRUMENTATION {
  my($agent, $device) = @_;
  my(@s, %dev, $in, %info);
  my($connect_err, %C);
  my($port,  $config);

  return Report->readTest($device) if (System->get_testMode());

  my(%R);
  my($ip)    = $device->{ip};
  my(@counts, @stats, $stat, $x);
  my $DIR    = System->get_home() . "/snmp/bin";
#  my $MIBDIR    = System->get_home() . "/snmp/share/snmp/mibs:" . System->get_home() . "/snmp/share/snmp/mibs/mcdata";
  my $MIBDIR    = System->get_home() . "/snmp/share/snmp/mibs";
  my $renv   = System->get_renv();
  my $TO     = $renv->{'timeout.snmp'};
  $DB::single = 1;
  my $public = $renv->{'snmp.community'} || "public";
  my $wwn    = $device->{wwn};
  my $mibwwn = Util->wwn2mib($wwn);

  my $ping_to  = $renv->{'timeout.ping'} || 10;


  if (!Util->ping($ip, $ping_to)) {
     $R{'rc.error'} = "Cannot ping $ip";
     return \%R;
  }

  $R{"info.version"}   = $agent->getVersion($ip, $device);

  #Get system uptime
  my $OPT   = "-v1 -c$public -r1 -t$TO -M$MIBDIR -mall " . System->snmpopt();

  my($err8,$uptime) = Util->run_command("$DIR/snmpwalk $OPT $ip sysuptime ", 
                       "sanbox_version.txt", 2*$TO+5);

  if ($err8) {
    Debug->err(SNMP => "Cannot run snmp on $ip:$err8");
    $R{'rc.error'} = "snmp failed on $ip: $err8";
    return \%R;
  } elsif ($#$uptime < 0) {
    $R{'rc.error'} = "No answer from switch at $ip";
    return \%R;
  }
  Timelapse->startDev( $device);

  # get environmental DATA - Fans, power supplies 
  my($max) = 0;
  if ($device->{oid} !~ /4369/) {

     $OPT = "-v1 -c$public -t$TO -r1 -m$MIBDIR/mcdata/fcmgmt.mib " . System->snmpopt();
     my($err0,$sensors) = Util->run_command("$DIR/snmpwalk $OPT $ip connUnitSensor",
                       "mcdata.txt", 2*$TO+5);

     if ($err0) {
        $R{'rc.error'} = $err0;
        return \%R;

     } elsif ("@$sensors" =~ /Timeout:/) {
        $R{'rc.error'} = "@$sensors";
        return \%R;
     }


     # Parse the sensor data
     # First create an array of sensors types and index number
     my ($l);
     my (%CNT, @MAP);
     foreach my $x (@$sensors) {
        if($x =~ /fcConnUnitSensorType.+\.(\d+) = (.+)/){

           my $sensorIndex = $1;
           my $sensorType = $2;
           $max =  $sensorIndex if ($sensorIndex > $max);
           my $i = index($sensorType,"(");
           $sensorType = substr($sensorType,0,$i) if ($i > 0);
       
          
          $CNT{$sensorType}++;
          $MAP[$sensorIndex] = "$sensorType." . $CNT{$sensorType};
       }
     }

     # Now get sensor valus
     foreach my $x (@$sensors) {
        if($x =~ /fcConnUnitSensorStatus.+\.(\d+) = (.+)/){
           my $sensorIndex = $1;
           my $sensorValue = $2;
           my $i = index($sensorValue,"(");
           $sensorValue = substr($sensorValue,0,$i) if ($i > 0);
           my $ix2 = $MAP[$sensorIndex];
           $R{"sensor.$ix2.status"} = $sensorValue;

        }
        if($x =~ /fcConnUnitSensorName.+\.(\d+) = (.+)/){
           my $sensorIndex = $1;
           my $sensorValue = $2;
           my $i = index($sensorValue,"(");
           $sensorValue = substr($sensorValue,0,$i) if ($i > 0);
           if($sensorValue =~ /\(Bad hint ignored: 255t\) (.+)/){
              $sensorValue = $1;
           }
           my $ix2 = $MAP[$sensorIndex];
           $R{"sensor.$ix2.name"} = $sensorValue;

       }
     }

  }else{
    # 1620 mcdata switch
    my( @T, %CNT, @MAP);
    my($sensors, $err0);
    my $OPT    = "-v1 -c$public -r1 -t$TO -M$MIBDIR -mall " . System->snmpopt() . "b";

    foreach my $el ('Type','Status','Message','Name') {
       ($err0,$sensors) = Util->run_command("$DIR/snmpwalk $OPT $ip connUnitSensor$el.$mibwwn", 
                      "sensor1620.txt", 2*$TO+5);

       if ($err0 || $#$sensors < 0) {
          Debug->errNoRepeat( SNMP_SENSOR => $device->{name} , 8, "Run MCDATA Command error: $err0: $DIR/snmpwalk $OPT $ip connUnitSensor$el.$mibwwn");   
       }

       foreach my $x (@$sensors) {
          next if ($x !~ /$mibwwn/);
          $x =~ /(.*)\.(\d+) = (.*)/;
          my $name = $1; 
          my $ix   = $2; 
          my $val  = $3;
          $val =~ s/"//g;
          my $i = index($val,"(");
          $val = substr($val,0,$i) if ($i > 0);
          if ($el eq "Type") {
             $CNT{$val}++;
             $MAP[$ix] = "$val." . $CNT{$val};
          } else {
             my $ix2 = $MAP[$ix];
	     my $el1 = lc($el);
             $R{"sensor.$ix2.$el1"} = $val;
             $max = $ix if ($ix > $max);
          }
       }
     }
     # put options back to normal
     $OPT = "-v1 -c$public -t$TO -r1 -m$MIBDIR/mcdata/fcmgmt.mib " . System->snmpopt();

  }
  $R{"sensor.count"} = $max;

  # Save system uptime
  foreach my $x (@$uptime) {
     my(@a) = split(/\(/, $x);
     my(@b) = split(/\)/, $a[1]);
     $R{"system.uptime"} =  $b[0];
     $R{"system.calendar_uptime"} = $b[1];
  }


  
  $agent->getStats($OPT, $ip, \%R, $device);
  $agent->getStatusLinks($OPT, $device, \%R);
  $agent->getProductID($ip, \%R, $device);
  $agent->getSerialNum($ip, \%R, $device);

  if (index("|$renv->{categories}|", "|san|") >= 0 &&
        $device->isMineToMonitor() ) {
     $R{"FC_COUNTERS"} = $agent->FCfromDevice($device);
  }

  $agent->addIdentification(\%R);

  $R{"id.wwn"}         = Util->snmpWWN($ip);
  $R{"id.switch_type"} = "McDATA";
  $R{'rc.key'}         = $R{"id.wwn"};
  Timelapse->stopDev( $device);
  return \%R;
}


sub FCfromDevice {
  my($class, $dev) = @_;
  my (%X, @R, $x);
  my $renv = System->get_renv();
  my $ip = $dev->{ip} || $dev->{ipno};
  my ($inframes, $outframes);
  my $public = $renv->{'snmp.community'} || "public";

  my $DIR  = System->get_home() . "/snmp";
  my $MIBDIR  = System->get_home() . "/snmp/share/snmp/mibs/mcdata";
  my $TO  = $renv->{'timeout.snmp'} || 60;
    

  #Gettting stats take longer than most operations so increase time out.
  $TO = $TO + 30;
 

  # Get port indexes
  #/opt/SUNWstade/snmp/bin/snmpwalk -r 1 -t 10 -m /opt/SUNWstade/snmp/share/snmp/mibs/mcdata/fcfe.mib -Os  172.20.35.161 $public fcFxPortErrorModuleIndex
  #fcFxPortErrorModuleIndex.1.1 = 1
  #fcFxPortErrorModuleIndex.1.2 = 1
  #fcFxPortErrorModuleIndex.1.3 = 1
  #fcFxPortErrorModuleIndex.1.4 = 1
  #fcFxPortErrorModuleIndex.2.1 = 2
  #fcFxPortErrorModuleIndex.2.2 = 2
  #fcFxPortErrorModuleIndex.2.3 = 2

  my $OPT = "-v1 -c$public -r1 -t$TO -m$MIBDIR/fcfe.mib " . System->snmpopt();
  my($err4,$ports) = Util->run_command(
                 "$DIR/bin/snmpwalk $OPT $ip fcFxPortErrorModuleIndex", 
                 "mcdata.txt", 2*$TO+5, {cache => 0});


  if ($err4) {
     Debug->print2("snmpwalk $ip fcFxPortErrorModuleIndex: $err4");
     return undef;
  }

  
  my($err5,$errors) = Util->run_command(
                 "$DIR/bin/snmpwalk $OPT $ip fcFxPortErrorEntry", 
                 "sanbox_version.txt", 2*$TO+5, {cache => 0});


  if ($err5) {
     Debug->print2("snmpwalk $ip fcFxPortErrorEntry: $err5");
     return undef;
  }
  my($ERR_LIST) = ",LinkFailures,SyncLosses,SigLosses,PrimSeqProtoErrors,InvalidTxWords,InvalidCrcs,DelimiterErrors,AddressIdErrors,LinkResetIns,LinkResetOuts,OlsOuts";
  #fcFxPortLinkFailures.1.1 = Counter32: 1
  #fcFxPortLinkFailures.1.2 = Counter32: 1
  #fcFxPortLinkFailures.2.1 = Counter32: 0
 
  foreach my $l (@$errors) {
		 #fcFxPortLinkFailures.2.1 = Counter32: 0
		 #fcFxPortLinkFailures.  2  .  1   = Counter32:   0
		 #fcFxPort(.+        ).(\d+).(\d+) = Counter32: (\d+)
     if ($l =~ /^fcFxPort(.+)\.(\d+)\.(\d+) = Counter32: (\d+)/){
        my $name    = $1;
	my $blade   = $2 - 1;
	my $portnum = $3;
	my $value   = $4;
        if (index($ERR_LIST, ",$name,") >= 0) {
	   my $porthere = ($blade *4) + $portnum;
	   $R[$porthere]{$name} =  $value + 0;
        }
     }
   }


   # Get in and out Frames

   foreach my $type ('In','Out') {
      # Get all class Frames
      foreach my $class ('C1','C2','C3') {

         my($err5,$errors) = Util->run_command(
                 "$DIR/bin/snmpwalk $OPT $ip fcFxPort${class}${type}Frames", 
                 "mcdata.txt", 2*$TO+5, {cache => 0});


         if ($err5) {
            Debug->print2("snmpwalk $ip fcFxPort${class}${type}Frames: $err5");
            return undef;
         }
         #fcFxPortC1InFrames.7.2 = Counter32: 0
         #fcFxPortC1InFrames.8.1 = Counter32: 0
         foreach my $l (@$errors) {
	     my $name = $class . $type;
            if ($l =~ /^fcFxPort${class}${type}Frames\.(\d+)\.(\d+) = Counter32: (\d+)/){
	      my $blade   = $1 - 1;
	      my $portnum = $2;
	      my $value   = $3;
	      my $porthere = ($blade * 4) + $portnum;
	      my $frametype = $type . "frames";
	      $R[$porthere]{$frametype} +=  $value + 0;
            }
         }
      }# End each class
   }#End in out

  my ($portnum)  = 0;
  $portnum = $class->getnumports($ip, $dev);
  for ($x=0; $x < $portnum; $x++) {

      my $key = "|$dev->{key}|port.$x|switch";

      if (!defined($R[$x])){
         $X{$key} = (0) . "\t".
		    (0) . "\t".
		    (0) . "\t".
		    (0) . "\t".
		    (0) . "\t".
		    (0) . "\t".
                    (0) . "\t".
                    (0) ;

      }
      else{

      
         $X{$key} = ($R[$x]{'LinkFailures'}+0)       . "\t".
		    ($R[$x]{'SigLosses'}+0)          . "\t".
		    ($R[$x]{'PrimSeqProtoErrors'}+0) . "\t".
		    ($R[$x]{'InvalidCrcs'}+0)        . "\t".
		    ($R[$x]{'SyncLosses'}+0)         . "\t".
		    ($R[$x]{'InvalidTxWords'}+0)     . "\t".
                    ($R[$x]{'Inframes'}+0)           . "\t".
                    ($R[$x]{'Outframes'}+0) ;
     }

  }
  return {enc => {$dev->{wwn} => $dev->{name}} , data => \%X};
}


sub REPORT {
  my($class, $host, $r, $arg) = @_;

  my($out);
  my($v) = $r->{_value};

  my $last;
  $out = $class->reportHead("McDATA", $r, undef, $v->{"id.connect_errs"});

  my $port;

  my $header_line;
  my $fan_line;

  if($v->{"port.count"} < 33){
    $header_line = "<th>Port</th>";
  }else{
     $header_line = "<th>#</th><th>Slot- Port</th>";
  }
  my $pow;
  $pow = $v->{'sensor.powerSupply.1.status'};
  if($v->{'sensor.powerSupply.2.status'}){
     $pow .=  " / " . $v->{'sensor.powerSupply.2.status'};
  }
  my $fan;
  if(($v->{"port.count"}  == 24) || ($v->{"port.count"} == 12)){
    $fan_line = "<td colspan=2>&nbsp;</td>";
  }else{
     $fan = $v->{'sensor.fan.1.status'} . " / " . 
            $v->{'sensor.fan.2.status'} ;

     if($v->{'sensor.fan.3.status'}){
       $fan .= " / " .  $v->{'sensor.fan.3.status'};
     }

     $fan_line = "<td bgcolor=$Style::LIGHT align=right>Fan:</td>   <td>&nbsp;$fan</td>";
  }  

  $out .= "
     <tr><td bgcolor=$Style::LIGHT align=right>Name:</td> <td>&nbsp;$v->{'id.device_name'}</td>
         <td bgcolor=$Style::LIGHT align=right>IP:</td>   <td>&nbsp;$v->{'id.device_ip'}</td>
     <tr><td bgcolor=$Style::LIGHT align=right>Product:</td> <td>&nbsp;$v->{'id.productID'}</td>
         <td bgcolor=$Style::LIGHT align=right>WWN:</td>   <td>&nbsp;$v->{'id.wwn'}</td>
     <tr><td bgcolor=$Style::LIGHT align=right>Version:</td> <td colspan=3>&nbsp;$v->{'info.version'}</td>
     <tr><td bgcolor=$Style::LIGHT align=right>Power:</td> <td>&nbsp;$pow</td>
     $fan_line
     </table>
     <table border=1 width=95% bgcolor=white cellspacing=0 cellpadding=0>
     <tr bgcolor=$Style::LIGHT>
        $header_line
        <th>Admin/Port State</th>
	<th>Port Status</th>
        <th>Attached WWN</th>";
     for ($port=0; $port < $v->{"port.count"}; $port++) {

        my ($admstat);
	if($v->{"port.$port.state.AdmStatus"}){
	   $admstat = $v->{"port.$port.state.AdmStatus"};
	} else {
	   $admstat = "Uninstalled";
	}

        my $state = $v->{"port.$port.state"};
        my $bg = ($state eq "offline")? "bgcolor=#FFFFD0":"";

	my $blade;
	if(exists($v->{"port.$port.blade"})){
	   $blade = $v->{"port.$port.blade"};
	}else{
	   $blade = int($port / 4);
	}

	my $blade_port;
	if(exists($v->{"port.$port.blade_port"})){
	   $blade_port = $v->{"port.$port.blade_port"};
	}else{
	   $blade_port = $port%4;
	}

	my $attached_wwn;
	if(exists($v->{"port.$port.link_wwn"})){
	   $attached_wwn = $v->{"port.$port.link_wwn"};
	}else{
	   $attached_wwn = "Not Connected";
	}

	my $port_stat;
	if($admstat =~ /Uninstalled/){
	   $port_stat = "Not Installed";
	}else{
	   $port_stat = "$admstat-$state";
	}
	my $port_status = $v->{"port.$port.status"};
	my $bgps = ($port_status eq "warning")? "bgcolor=#FFFFD0":"";


	my $show_port;
	if($port >127){
	  $show_port = $port + 4;
	}else{
	  $show_port = $port;
	}
	   
	if($v->{"port.count"} < 33){
	   $out .= "<tr><td>&nbsp;$show_port</td>
                    <td $bg>&nbsp;$port_stat</td>
		    <td $bgps>$port_status </td>
                    <td>&nbsp;$attached_wwn</td>";

        }else{
           $out .= "<tr><td><center>&nbsp;$show_port</td>
	            <td><center>$blade-$blade_port</td>
		    <td $bg>&nbsp;$port_stat</td>
		    <td $bgps>&nbsp;$port_status </td>
		    <td>&nbsp;$attached_wwn</td>";
        }
     }
  $out .= "</table>&nbsp;<table border=1 cellspacing=0 width=95% bgcolor=white>";


  foreach my $el (sort keys %$v) {
     if($el =~ /id.device_telnet/ || substr($el,0,3) eq "rc."){
        #skip displaying password
        next;
     }
     if($el =~ /port\./){
      next;
     }
     next if (ref($v->{$el}) eq "HASH");
     my($a, $b) = split(/\./, $el);
     if ($a ne $last) {
        $out .= "<tr bgcolor=$Style::LIGHT><td colspan=2>&nbsp;<b>$a<th> <th></th></td>\n" if ($a);
        $last = $a;
     }

     $out .= "<tr><td>&nbsp;$el<td>&nbsp;$v->{$el}</td>";
  }
  $out .= "</table>";
  return $out;

}


sub getZones {
  my($class, $DIR, $s_ip, $V, $dev) = @_;
  my(%Z);
  my $totzones;
  $totzones = -1;
  my $MIBDIR  = System->get_home() . "/snmp/share/snmp/mibs/mcdata";
  my $err ;
  my $renv = System->get_renv();
  my $TO  = $renv->{'timeout.snmp'} || 60;
  my $public = $renv->{'snmp.community'} || "public";

   # Get my domain id
   my $mydomainid;
   my ($num_zones) = 0;
   my $OPT  = "-v1 -c$public -r1 -t$TO -m$MIBDIR/fcmgmt.mib " . System->snmpopt() . "e";

   my($err1,$id) = Util->run_command(
                 "$DIR/bin/snmpwalk $OPT $s_ip fcConnUnitDomainId", 
                 "mcdata.txt", 2*$TO+5);
   if ($err1){
     Debug->errNoRepeat( SNMP_SENSOR => $dev->{name} , 8, "Run mcdata Command error: $err1: $DIR/bin/snmpwalk $OPT $s_ip fcConnUnitDomainId");   
   }

   foreach my $l (@$id) {
      if ($l =~ /^fcConnUnitDomainId.+ =  Hex: .. .. (..)/) {
         $mydomainid = $1;
	 $mydomainid = int($mydomainid);
      }
   }


   # Get active member table
   $OPT = "-v1 -c$public -r1 -t$TO -m$MIBDIR/ef-6000.mib " . System->snmpopt() . "e";

   my($err2,$active_table) = Util->run_command(
                 "$DIR/bin/snmpwalk $OPT $s_ip ef6000ActiveMemberTable", 
                 "mcdata.txt", 2*$TO+5);
   if ($err2){
     Debug->errNoRepeat( SNMP_SENSOR => $dev->{name} , 8, "Run mcdata Command error: $err2: $DIR/bin/snmpwalk $OPT $s_ip ef6000ActiveZoneTable");   
   }

   my ($zone_number);
   foreach my $l (@$active_table) {
      if ($l =~ /^ef6000MemberZoneIndex\.(\d+)\.(\d+) = (\d+)/) {
         my $zone = $1;
	 my $index_of_zone = $2;
	 my $zone_number = $3;
	 $totzones = $zone_number if($zone_number > $num_zones);
	 $Z{"$zone.$index_of_zone.zone_number"} = $zone_number;

      }
      # find the indexes with this switches domain id


      if ($l =~ /^ef6000MemberDomainID\.(\d+)\.(\d+) = (\d+)/) {
         my $zone = $1;
	 my $index_of_zone = $2;
	 my $domain_id = $3;
	 if($mydomainid eq $domain_id){
	    $Z{"$zone.$index_of_zone.port"} = $domain_id;
	 }
      }
      # find the port numbers for this switch that are in zones
      if ($l =~ /^ef6000MemberPortNumber\.(\d+)\.(\d+) = (\d+)/) {
         my $zone = $1;
	 my $index_of_zone = $2;
	 my $port = $3;
	 if($Z{"$zone.$index_of_zone.port"}){
	    $Z{"$zone.$index_of_zone.zone_port"} = $port;
	    my ($zone_index) = $Z{"$zone.$index_of_zone.zone_number"};
	    $V->{"zone.hd.$zone_index.members"} .= "$port ";

	 }
      }

   }

   # Get zone names
    my($err2,$active_table) = Util->run_command(
                 "$DIR/bin/snmpwalk $OPT $s_ip ef6000ActiveZoneTable", 
                 "mcdata.txt", 2*$TO+5);
    if ($err2){
      Debug->errNoRepeat( SNMP_SENSOR => $dev->{name} , 8, "Run mcdata Command error: $err2: $DIR/bin/snmpwalk $OPT $s_ip ef6000ActiveZoneTable");   
    }

   my ($zone_number);
   foreach my $l (@$active_table) {
      if ($l =~ /^ef6000ZoneName\.(\d+) = (.*)/) {
	 my $index = $1;
	 my $zone_name = $2;
	 my $zoneindex = "zone" . $index . "name";
	 $V->{"zone.hd_name.$index.name"} = $zone_name;

      }
   }
   # end get zone names

  $V->{"zone.total"} = $totzones +1;
  return $err;

}





sub getModel {
  my($agent, $ip) = @_;

  return "McDATA";

}



sub getProductID {
  my($class, $ip, $R, $dev) = @_;


  my $DIR  = System->get_home() . "/snmp";
  my $MIBDIR  = System->get_home() . "/snmp/share/snmp/mibs/mcdata";


  my $renv  = System->get_renv();
  my $TO  = $renv->{'timeout.snmp'} || 60;
  my $public = $renv->{'snmp.community'} || "public";
  my $OPT = "-v1 -c$public -r1 -t$TO -m$MIBDIR/fcmgmt.mib " . System->snmpopt();
  my $cmd; 
    
  if ($dev->{oid} !~ /4369/) {
     $cmd = "fcConnUnitProduct";
  }else{
    $MIBDIR  = System->get_home() . "/snmp/share/snmp/mibs";
    $OPT = "-v1 -c$public -t$TO -r1 -M$MIBDIR -mall " . System->snmpopt() . "b";
    $cmd = "connUnitProduct";
  }

  


  my ($err,$product) = Util->run_command(
                 "$DIR/bin/snmpwalk $OPT $ip $cmd", 
                 "sanbox_version.txt", 2*$TO+5);


  if ($err) {
     Debug->print2("snmpwalk $ip $cmd: $err");
     return undef;
  }
  #/opt/SUNWstade/snmp/bin/snmpwalk -r 1 -t 10 -m /opt/SUNWstade/snmp/share/snmp/mibs/mcdata/fcmgmt.mib -Os  172.20.35.163 public fcConnUnitProduct
  #fcConnUnitProduct.'..... L.........' = ES-3232
  my($x, $port, $name);

  foreach my $l (@$product) {
     if ($l =~ /^$cmd.+ = (.+)/){
           $R->{"id.productID"} =  $1;
     }
   }

   if($R->{"id.productID"} =~ /\(Bad hint ignored: 255t\) "(.+)"/){
          $R->{"id.productID"} = $1;
   }

}
sub getSerialNum {
  my($class, $ip, $R, $dev) = @_;


  my $DIR  = System->get_home() . "/snmp";
  my $MIBDIR  = System->get_home() . "/snmp/share/snmp/mibs/mcdata";

  my $renv  = System->get_renv();
  my $TO  = $renv->{'timeout.snmp'} || 60;
  my $public = $renv->{'snmp.community'} || "public";
  my $name;

  if ($dev->{oid} !~ /4369/) {
  
     my $OPT = "-v1 -c$public -r1 -t$TO -m$MIBDIR/ef-6000.mib " . System->snmpopt();


     my ($err,$serial_num) = Util->run_command(
                 "$DIR/bin/snmpwalk $OPT $ip ef6000SysSerialNum", 
                 "sanbox_version.txt", 2*$TO+5);


     if ($err) {
        Debug->print2("snmpwalk $OPT $ip ef6000SysSerialNum: $err");
        return undef;
     }
     #/opt/SUNWstade/snmp/bin/snmpwalk -r 1 -t 10 -m /opt/SUNWstade/snmp/share/snmp/mibs/mcdata/fcmgmt.mib -Os  172.20.35.163 $public fcConnUnitProduct
     #fcConnUnitProduct.'..... L.........' = ES-3232
     my($x, $port, $name);

     foreach my $l (@$serial_num) {
        if ($l =~ /^ef6000SysSerialNum.+ = "(.+)"/){
           $R->{"id.serial_num"} =  $1;
        }
     }
  }else{
    # 1620 switch

     my $wwn = $dev->{wwn};
     my $mibwwn = Util->wwn2mib($wwn);
     my $public = $renv->{'snmp.community'} || "public";
     $DIR = System->get_home() . "/snmp/bin";
     $MIBDIR = System->get_home() . "/snmp/share/snmp/mibs";


     $ENV{LD_LIBRARY_PATH} = System->get_home() . "/snmp/lib";
     my $OPT  = "-v1 -c$public -r1 -t$TO -M$MIBDIR -mall " . System->snmpopt() . "b";
     my($err0,$version) = Util->run_command("$DIR/snmpwalk $OPT $ip connUnitSn", 
                 "sn.txt", 2*$TO + 5);
     if ($err0){
       Debug->errNoRepeat( SNMP_SENSOR => $dev->{name} , 8, "Run mcdata Command error: $err0: $DIR/snmpwalk $OPT $ip connUnitSn");   
     }

     
     foreach my $l (@$version) {
        next if ($l !~ /$mibwwn/);
        if ($l =~ /connUnitSn/) {
           $l =~ /\.(\d+) = (.*)/;
           my $port = $1;
           $name = $2;
           $name =~ s/"//g;
           my $ix = index($name, " Hex:");
           $name = substr($name, 0, $ix) if ($ix > 0);
        } 
     } 

    $R->{"id.serial_num"} =  $name;
  }      

}
1;
