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

#  $Name:  $ 
#  $Id: MCDATA.pm,v 1.7 2002/08/15 22:14:31 mckenney Exp $

use strict;
use Agent;
use base 'Agent';
use Net::Telnet;
use Util;

sub isSelectable {"McDATA"}

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

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

  
sub RUN {
  my($agent,$ras_flag) = @_;
  my(%DONE, $HBA, $logfile, $r, @results);
  my( @all_connect_errors);
  my( @lux_dif, $dif, $xml, @all_dif);
  my($ev, @stats, $id, $log_lines, $sdt, $pdm);
  $pdm = $agent->{pdm};
  my($renv) = System->get_renv();

  $DB::single=1;
  Timelapse->start(ref($agent));

  my($today) = Util->today("YMDH");
  my($dc) = 0;

  foreach my $device ( $agent->deviceList()) {

    $dc++;
    Debug->print1("-> McDATA: Reading device $device->{name}: $device->{ip}");

    if (!$device->{ip}) {
        Debug->err( 'IP_NOT_FOUND',"Switch at $device->{name}" );
        next;
    }

    my($connect_errs, $wwn, $report) = $agent->read_mcdata($device);
    $wwn = lc($wwn);
    if ($wwn && $wwn ne $device->{wwn}) {
       Debug->errNoRepeat(SWITCH_NEWIP => $device->{ipno}, 24, "wwn of McDATA $device->{ipno} changed from $device->{wwn} to $wwn");
    }

    $id = {   accessName  => $device->{name},
              deviceName  => $device->{wwn},
              active      => $device->{active},
              display     => "$device->{name} (ip=$device->{ip})",
              class       => $device->{class},
              name        => $device->{name},
              category    => Report::CAT_MCDATA,
              ip          => $device->{ip},
           };

    $report = {} if (!$report);
    $agent->copyDev($device, $report);

    $device->{ipno} = Util->name2ip($device->{ip});
    $report->{"id.name"} = $device->{name};
    $report->{"id.ip"}   = $device->{ip};
    $report->{"id.ipno"} = $device->{ipno};

    if ($connect_errs || !$wwn) {
        $report->{'id.connect_errs'} = $connect_errs;
        $pdm->saveReport(
          Report->new($id, $report , [], Report::STATUS_CANNOT_CONNECT));

    } else {
        $pdm->saveReport(Report->new($id, $report , $log_lines));
    }
  }
  Debug->print2("  No devices found") if (!$dc);

  Timelapse->stop(ref($agent));
}

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 $comm =   "$DIR/snmp/bin/snmpwalk -r 0 -t 10 -m $DIR/snmp/share/snmp/mibs/mcdata/fcfe.mib -Os $ip public fcElementName";
  my($err,$id) = Util->run_command($comm, "getWWN", 10);

  ($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->{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($renv) = System->get_renv();
  my($TO) = $renv->{'timeout.snmp'} || 10;
  
 
  my($MIBS) = $DIR . "/share/snmp/mibs/mcdata";

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


   # 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 = "-r 0 -t $TO -m $MIBS/fcfe.mib -Os ";
   my ($portinfo);
   ($err,$portinfo) = Util->run_command(
                 "$DIR/bin/snmpwalk $OPT $dev->{ipno} public fcFxPortPhysAdminStatus ", 
                 "sanbox_version.txt", $TO+5);


   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 = substr($value,0,$ix);
            $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 -r 0 -t 10 -m /opt/SUNWstade/snmp/share/snmp/mibs/mcdata/fcmgmt.mib -Os  172.20.35.162 public 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

  $OPT = "-r 0 -t $TO -m $MIBS/fcmgmt.mib -Os ";
  ($err,$portids) = Util->run_command(
                 "$DIR/bin/snmpwalk $OPT $dev->{ipno} public fcConnUnitLinkPortNumberX", 
                 "sanbox_version.txt", $TO+5);
   my (@port_array);
   foreach my $l (@$portids) {
      if ($l =~ /^fcConnUnitLinkPortNumberX.+\.(\d+) = (\d+)/) {
	 $port_array[$1] = $2;

      }
   }

   # now get attached WWN's 
   #/opt/SUNWstade/snmp/bin/snmpwalk -r 0 -t 10 -m /opt/SUNWstade/snmp/share/snmp/mibs/mcdata/fcmgmt.mib -Os  172.20.35.162 public 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 
   ($err,$portids) = Util->run_command(
                 "$DIR/bin/snmpwalk $OPT $dev->{ipno} public fcConnUnitLinkPortWwnY", 
                 "sanbox_version.txt", $TO+5);
   foreach my $l (@$portids) {
      if ($l =~ /^fcConnUnitLinkPortWwnY.+\.(\d+) =  Hex: (.+)/) {
         my ($portindex) = $1;
	 my ($wwn) = $2;
	 $wwn =~ s/ //g;

         $R->{"port.$port_array[$portindex].link_wwn"} = lc($wwn);
      }
   }

   # Get port information - Type, state and status
   #/opt/SUNWstade/snmp/bin/snmpwalk -r 0 -t 10 -m /opt/SUNWstade/snmp/share/snmp/mibs/mcdata/fcmgmt.mib -Os  172.20.35.162 public fcConnUnitPortType
   #fcConnUnitPortType.'..... ÌL........'.1 = fPort(8)
   #fcConnUnitPortType.'..... ÌL........'.2 = fPort(8)
   #fcConnUnitPortType.'..... ÌL........'.3 = gPort(10)

   $OPT = "-r 0 -t $TO -m $MIBS/fcmgmt.mib -Os ";
   foreach my $el ('Type','State','Status') {

     ($err,$portinfo) = Util->run_command(
                 "$DIR/bin/snmpwalk $OPT $dev->{ipno} public fcConnUnitPort$el", 
                 "sanbox_version.txt", $TO+5);

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



   # Get port wwn's
   $OPT = "-r 0 -t $TO -m $MIBS/fcmgmt.mib -Os ";

   ($err,$portids) = Util->run_command(
                 "$DIR/bin/snmpwalk $OPT $dev->{ipno} public fcConnUnitPortWwn", 
                 "mcdata.txt", $TO+5);

   #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 =~ /^fcConnUnitPortWwn.+\.(\d+) =  Hex: (.+)/) {
         my ($portindex) = $1 - 1;
	 my ($wwn) = $2;
	 $wwn =~ s/ //g;

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

}

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


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

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

  # Get number of ports
  my($OPT) = "-r 0 -t $TO -m $MIBS/ef-6000.mib -Os  ";
  my ($err,$ports) = Util->run_command(
                 "$DIR/bin/snmpwalk $OPT $ip public Ef6000PortIndex", 
                 "sanbox_version.txt", $TO+5);
  my $mycount  = $#$ports;

  return $mycount +1;
}

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


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


  my($renv) = System->get_renv();
  my($TO) = $renv->{'timeout.snmp'} || 60;
    
  $R->{"port.count"} = $class->getnumports($ip);


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


  my ($err5,$ports) = Util->run_command(
                 "$DIR/bin/snmpwalk $OPT $ip public fcFxPortErrorEntry", 
                 "sanbox_version.txt", $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) = @_;

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

  # Get version
  my $OPT = "-r 0 -t $TO -m $MIBS/ef-6000.mib -Os ";
  my($err_version,$version) = Util->run_command(
                 "$DIR/bin/snmpwalk $OPT $ip public ef6000SysFirmwareVersion", 
                 "mcdata.txt", $TO+5);

  if ($err_version) {
     $ERR = $err_version;
     return undef;
  } else {
     my ($x, $y) = split(/\s*=\s*/, "@$version");
     if (substr($y,0,1) eq "\"") {
        $y = substr($y,1,-1);
     }
     return $y;
  }

}

sub read_mcdata {
  my($agent, $device) = @_;
  my(@s, %dev, $in, %info);
  my($connect_err, %C);
  my($port,  $config);
  my(%R);
  my($ip)    = $device->{ip};
  my(@counts, @stats, $stat, $x);
  my($DIR)   = System->get_home() . "/snmp/bin";
  my($renv)  = System->get_renv();
  my($TO)    = $renv->{'timeout.snmp'};

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

  my ($OPT);

  # get environmental DATA - Fans, power supplies 
  $OPT = "-t $TO -r 0 -m $MIBS/fcmgmt.mib -Os ";
  my($err0,$sensors) = Util->run_command("$DIR/snmpwalk $OPT $ip public connUnitSensor",
                       "mcdata.txt", $TO+5);

  if ($err0) {
     return ($err0, undef,undef);

  } elsif ("@$sensors" =~ /Timeout:/) {
     return ("@$sensors", undef,undef);
  }


  #Get system uptime
  ($OPT)   = "-r 0 -t $TO -m all -Os ";
  my($err8,$uptime) = Util->run_command("$DIR/snmpwalk $OPT $ip public sysuptime ", 
                       "sanbox_version.txt", $TO+5);



  if ($err8) {
    Debug->err(SNMP => "Cannot run snmp on $ip:$err8");
    return ("$err8","", undef) 
  }


  # Parse the sensor data
  # First create an array of sensors types and index number
  my ($max, $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);
       my $ix2 = $MAP[$sensorIndex];
       $R{"sensor.$ix2.name"} = $sensorValue;

    }
  }

  $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->addIdentification(\%R);

  $R{"id.wwn"} = Util->snmpWWN($ip);

  $R{"id.switch_type"} = "McDATA";

  return (undef, $R{"id.wwn"}, \%R);
}


sub FCCounters {
  my($class,$arg) = @_;

  return $class->switchFCCounters("mcdata", $arg);
}


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



  my $DIR  = System->get_home() . "/snmp";
  my($MIBS) = $DIR . "/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 0 -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) = "-r 0 -t $TO -m $MIBS/fcfe.mib -Os ";
  my($err4,$ports) = Util->run_command(
                 "$DIR/bin/snmpwalk $OPT $ip public fcFxPortErrorModuleIndex", 
                 "mcdata.txt", $TO+5);


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

  
  my($err5,$errors) = Util->run_command(
                 "$DIR/bin/snmpwalk $OPT $ip public fcFxPortErrorEntry", 
                 "sanbox_version.txt", $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
 
  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 public fcFxPort${class}${type}Frames", 
                 "mcdata.txt", $TO+5);


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

  if(exists($v->{"id.connect_errs"})){
     print "<b><font color=red>NOTE: Errors were encountered when this report was generated. The data being displayed could be from an old report.</font></b>";
  }

  my $port;

  my $header_line;

  if($v->{"id.productID"} =~ /3232/){
    $header_line = "<th>Port</th>";
  }else{
     $header_line = "<th>port#</th><th>Slot - Port</th>";
  }



  $out .= "
     <table border=0><tr><td></table>
     <table border=1 width=95% bgcolor=white cellspacing=0 cellpadding=0>
     <tr bgcolor=#CCCCFF><td><b>&nbsp;$header_line<th>Admin/Port State</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";
	}

	   
	if($v->{"id.productID"} =~ /3232/){
	   $out .= "<tr><td>&nbsp;$blade_port</td><td $bg>&nbsp;$port_stat</td><td>&nbsp;$attached_wwn</td>";

        }else{
           $out .= "<tr><td>&nbsp;$port</td><td>&nbsp;$blade - $blade_port</td><td $bg>&nbsp;$port_stat</td><td>&nbsp;$attached_wwn</td>";
        }
     }
  $out .= "</table>&nbsp;<p>";


  foreach my $el (sort keys %$v) {
     if($el =~ /id.device_telnet/){
        #skip displaying password
        next;
     }
     if($el =~ /port\./){
      next;
     }
     my($a, $b) = split(/\./, $el);
     if ($a ne $last) {
        $out .= "<tr bgcolor=#CCCCFF><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($MIBS) = $DIR . "/share/snmp/mibs/mcdata";
  my($err);
  my $renv = System->get_renv();
  my($TO) = $renv->{'timeout.snmp'} || 60;


   # Get my domain id
   my $mydomainid;
   my ($num_zones) = 0;
   my ($OPT) = "-r 0 -t $TO -m $MIBS/fcmgmt.mib -Ose ";

   my($err1,$id) = Util->run_command(
                 "$DIR/bin/snmpwalk $OPT $s_ip public fcConnUnitDomainId", 
                 "mcdata.txt", $TO+5);

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


   # Get active member table
   $OPT = "-r 0 -t $TO -m $MIBS/ef-6000.mib -Ose ";

   my($err2,$active_table) = Util->run_command(
                 "$DIR/bin/snmpwalk $OPT $s_ip public ef6000ActiveMemberTable", 
                 "mcdata.txt", $TO+5);

   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 ";

	 }
      }

   }


  $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($MIBS) = $DIR . "/share/snmp/mibs/mcdata";


  my($renv) = System->get_renv();
  my($TO) = $renv->{'timeout.snmp'} || 60;
    
  my $OPT = "-r 0 -t $TO -m $MIBS/fcmgmt.mib -Os ";


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


  if ($err) {
     Debug->print2("snmpwalk $ip fcConnUnitProduct: $err");
     return undef;
  }
  #/opt/SUNWstade/snmp/bin/snmpwalk -r 0 -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 =~ /^fcConnUnitProduct.+ = (.+)/){
           $R->{"id.productID"} =  $1;
     }
   }

}

1;
