#!/usr/bin/perl
#<copyright>
# ----------------------------------------------------------
# Sun Proprietary/Confidential Code
# Copyright 2001, Sun Microsystems, Inc. All rights reserved.
# ----------------------------------------------------------
#</copyright>

#Errors Returned by these methods
#"cannot_locate_dsp_in_report"
#"no_default_gateway_defined_for_this_port"
#"java_error"
#"dsp_comunication_error"
#"no_links_configured_for_this_port"
##################################################################
#DSPUtils.pm
##################################################################
package DSPUtils;

use strict;
use Util;
use LWP;
use PDM::ConfigFile;
use Report;
use Data::Dumper;

##################################################################
sub pingAllLinks{
  my ($Args)=@_;
  my $localDSP = $Args->{"local"} || "192.168.0.10";
  my $Card= $Args->{card} || "3";
  my $Port= $Args->{port} || "7";
  my $results;
  my $err;
  my $config = PDM::ConfigFile->read();
  my $dev = $config->deviceByIP($localDSP);
  if (!$dev) {
     $err .= "Cannot find ($localDSP) in Config. ";
     return("cannot_locate_dsp_in_report",undef);
  }
  (my $readerr, my $rep1) = Report->readReport("dsp:".$dev->{key});
  if (! $rep1) {
    $err .= $readerr;
    $err .= "Cannot find Report for $localDSP, Run rasagent.\n ";
    return("cannot_locate_dsp_in_report",undef);
  }
  my $v = $rep1->value();
  my $linkTotal = $v->{"etherPort.m".$Card."p$Port.PeerLinkISCSI.total"}||0;
  my $l;
  for($l = 1; $l<=$linkTotal; $l++){
    my $link = 
      $v->{"etherPort.m".$Card."p$Port.PeerLinkISCSI.$l.PeerLinkISCSIRemoteIP"};
    my $result = &ping({target=> $link, port=>"$Port\/$Card"});
    $result->{LinkState}=$v->{"etherPort.m".$Card."p$Port.PeerLinkISCSI.$l.PeerLinkISCSIState"};
    push(@$results, $result);
  }
  return("no_links_configured_for_this_port", undef)if($l==1);
  return(undef,$results);
}

sub pingDefaultGateway{
  my ($Args)=@_;
  my $localDSP = $Args->{"local"} || "192.168.0.10";
  my $Card= $Args->{card} || "3";
  my $Port= $Args->{port} || "7";
  my $results;
  my $err;
  my $config = PDM::ConfigFile->read();
  my $dev = $config->deviceByIP($localDSP);
  if (!$dev) {
     $err .= "Cannot find ($localDSP) in Config. ";
     return("cannot_locate_dsp_in_report",undef);
  }
  (my $readerr, my $rep1) = Report->readReport("dsp:".$dev->{key});
  if (! $rep1) {
    $err .= $readerr;
     $err .= "Cannot find Report for $localDSP, Run rasagent.\n ";
     return("cannot_locate_dsp_in_report",undef);
  }
  my $v = $rep1->value();
  my $gateway = $v->{"etherPort.m".$Card."p$Port.PeerPortDefaultGateway"};
  return ("no_default_gateway_defined_for_this_port",undef) if(!$gateway);
  return &ping({target=>$gateway, port=>"$Port\/$Card"});
}

sub ping {
  my ($Args)=@_;
  my $localDSP = $Args->{local} || "192.168.0.10";
  my $targetIP=  $Args->{"target"} || "172.20.35.201";
  my $targetPort= $Args->{port} || "3/7";
  my $ERROR;
  my $response;
  $response->{IPaddr}=$targetIP;
  my $res;
  use Data::Dumper;
  use System;
  use Java::JrexMsg;
  use Java::JrexClient;
  eval{
    my $client = new Java::JrexClient();
    my $session = $client->openSession();
    if (!$session){
      Debug->err(JAVA_ERR => $client->error);
      return("java_error",undef);
    }
    my $dspUtil = $client->createObject
       ("com.sun.netstorage.fm.storade.device.storage.dsp.DSPUtil",[$localDSP]);
    $res=$dspUtil->doPost("/tmp/ping.htm",["target","port"],[$targetIP,$targetPort]);
    $client->closeSession();
  };
  if($@){
   #print "Jrex Error: ".Dumper($@);
   $response->{Status} = "StorADE Failure";
   $response->{ErrorCode} = "StorADE";
   $response->{ErrorString}="StorADE is configured improperly, run ras_install";
   return (undef, $response);
  }
#example return data
#<response>
#    <Status>SUCCESS</Status>
#    <ErrorCode>0</ErrorCode>
#    <ErrorString>N/A</ErrorString>
#    <ResultData>&#032;</ResultData>
#</response>
  require XML::LibXML;
  my $parser = XML::LibXML->new();
  my $elem;
  my $dom;
  eval {
        $dom = $parser->parse_string($res);
      };
  if ($@) {
   #print("Error parsing XML from \n$@");
   #print $res;
   $response->{Status} = "DSP XML Failure";
   $response->{ErrorCode} = "StorADE";
   $response->{ErrorString}="DSP returned malformed XML";
   return (undef, $response);
  }else{
    $elem = $dom->getDocumentElement();
  }
  foreach my $el ($elem->getChildNodes()) {
    next if ($el->getType() != &XML::LibXML::ELEMENT_NODE() );
    my $name = $el->getName();
    my $elval = Util->rtrim($el->textContent());
    $response->{$name} = $elval;
  }
  return (undef, $response);
}

sub portStatus{
  my ($Args)=@_;
  my $localDSP = $Args->{"local"} || "192.168.0.10";
  my $Card= $Args->{card} || "3";
  my $Port= $Args->{port} || "7";
  my $response;
  my $err;
  my $config = PDM::ConfigFile->read();
  my $dev = $config->deviceByIP($localDSP);
  if (!$dev) {
     $err .= "Cannot find ($localDSP) in Config. ";
     return("cannot_locate_dsp_in_report",undef);
  }
  (my $readerr, my $rep1) = Report->readReport("dsp:".$dev->{key});
  if (! $rep1) {
    $err .= $readerr;
    $err .= "Cannot find Report for $localDSP, Run rasagent.\n ";
     return("cannot_locate_dsp_in_report",undef);
  }
  my $v = $rep1->value();
  $response->{Description}= $v->{"etherPort.m".$Card."p$Port.Description"};
  $response->{HardwareState}= $v->{"etherPort.m".$Card."p$Port.HardwareState"};
  $response->{Name}= $v->{"etherPort.m".$Card."p$Port.Name"};
  $response->{Name}= $v->{"etherPort.m".$Card."p$Port.Name"};
  $response->{PeerPortEnabled}=$v->{"etherPort.m".$Card."p$Port.PeerPortEnabled"};
  $response->{PortState}=$v->{"etherPort.m".$Card."p$Port.PortState"};
  return (undef, $response);
}

sub networkConfig{
  my ($Args)=@_;
  my $localDSP = $Args->{"local"} || "192.168.0.10";
  my $Card= $Args->{card} || "3";
  my $Port= $Args->{port} || "7";
  my $response;
  my $err;
  my $config = PDM::ConfigFile->read();
  my $dev = $config->deviceByIP($localDSP);
  if (!$dev) {
     return("cannot_locate_dsp_in_report",undef);
  }
  (my $readerr, my $rep1) = Report->readReport("dsp:".$dev->{key});
  if (! $rep1) {
    $err .= $readerr;
    $err .= "Cannot find Report for $localDSP, Run rasagent.\n ";
    return("cannot_locate_dsp_in_report",undef);
  }
  my $v = $rep1->value();
  $response->{IPAddress}= $v->{"etherPort.m".$Card."p$Port.PeerPortIP"};
  $response->{Netmask}= $v->{"etherPort.m".$Card."p$Port.PeerPortMask"};
  $response->{PeerPortEnabled}=$v->{"etherPort.m".$Card."p$Port.PeerPortEnabled"};
  $response->{DefaultGateway}=$v->{"etherPort.m".$Card."p$Port.PeerPortDefaultGateway"};
  return (undef, $response);

}

sub replicationLinkStatus{
  my ($Args)=@_;
  my $localDSP = $Args->{"local"} || "192.168.0.10";
  my $Card= $Args->{card} || "3";
  my $Port= $Args->{port} || "7";
  my $results;
  my $err;
  my $config = PDM::ConfigFile->read();
  my $dev = $config->deviceByIP($localDSP);
  if (!$dev) {
     $err .= "Cannot find ($localDSP) in Config. ";
    return("cannot_locate_dsp_in_report",undef);
  }
  (my $readerr, my $rep1) = Report->readReport("dsp:".$dev->{key});
  if (! $rep1) {
    $err .= $readerr;
    $err .= "Cannot find Report for $localDSP, Run rasagent.\n ";
    return("cannot_locate_dsp_in_report",undef);
  }
  my $v = $rep1->value();
  my $linkTotal = $v->{"etherPort.m".$Card."p$Port.PeerLinkISCSI.total"}||0;
  for(my $l = 1; $l<=$linkTotal; $l++){
    my $result;
    $result->{IPAddress}= $v->{"etherPort.m".$Card."p$Port.PeerLinkISCSI.$l.PeerLinkISCSIRemoteIP"};
    $result->{LinkState}=
        $v->{"etherPort.m".$Card."p$Port.PeerLinkISCSI.$l.PeerLinkISCSIState"};
    push(@$results, $result);
  }
  return (undef, $results);
}

sub showCurrentARPTable{
  use XML::LibXML;
  use Util::Http;
  my ($Args)=@_;
  my $localDSP = $Args->{"local"} || "192.168.0.10";
  my $Card= $Args->{card} || "3";
  my $Port= $Args->{port} || "7";
  my $results;
  my $err;
  my $parser = XML::LibXML->new();
  my $dom;
  my $elem;
  my $MAP;
  my $xml = Util::Http->get("http://$localDSP/sa_eprt.xml","20");

     $xml =~ s/<InitSize>(\d+).*GB<\/InitSize>/<InitSize>$1 GB<\/InitSize>/g;
     $xml =~ s/<RawSize>(\d+).*GB<\/RawSize>/<RawSize>$1 GB<\/RawSize>/g;

     if(length($xml) > 5){
      eval {
        $dom = $parser->parse_string($xml);
      };
      if ($@) {
          #print("Error parsing XML from \"$localDSP/sa_eprt.xml\". $@");
        return("dsp_comunication_error", undef);
      }else{
        eval{
          my $node = $dom->getDocumentElement();
          foreach my $el ($node->getChildNodes()) { #ports
              next if ($el->getType() != &XML::LibXML::ELEMENT_NODE() );
              my $name = $el->getName();
              my $pr;
              my @ch1 = $el->getChildNodes();
              foreach my $port ($el->getChildNodes()) {#1st attr
                my $attr = $port->getName();
                if (index(",ARPTable,", ",$attr,") >= 0) {
                  foreach my $ARPTag ($port->getChildNodes()) { #APR attr
                    my $IP;
                    my $MAC;
                    foreach my $entry ($ARPTag->getChildNodes()) { #APR attr
                      my $key = $entry->getName();
                      if ($key eq "arpTable_currentDestinationIpAddr")  {
                        $IP = Util->trim($entry->textContent());
                      }elsif ($key eq "arpTable_currentDestinationMacAddr"){
                        $MAC = Util->trim($entry->textContent());
                      }
                    }
                    if($IP){
                      $MAP->{$IP} = $MAC
                    }
                  }
                }
              }
          }
        };
        if ($@) {
          #print("Error parsing XML from \"$localDSP/sa_eprt.xml\". $@");
          return("dsp_comunication_error", undef);
        }
      }
    } else {
          #print("Error parsing XML from \"$localDSP/sa_eprt.xml\".");
          return("dsp_comunication_error", undef);
    }
  return (undef, $MAP);
}

sub deleteCurrentARPTable{
  my ($Args)=@_;
  my $localDSP = $Args->{"local"} || "192.168.0.10";
  my $Card= $Args->{card} || "3";
  my $Port= $Args->{port} || "7";
  my $targetPort= "$Card/$Port";
  my $results;
  my $res;
  my $response;

  use Data::Dumper;
  use System;
  use Java::JrexMsg;
  use Java::JrexClient;
  eval{
    my $client = new Java::JrexClient();
    my $session = $client->openSession();
    if (!$session){
      Debug->err(JAVA_ERR => $client->error);
      return("java_error", undef);
    }
    my $dspUtil = $client->createObject
       ("com.sun.netstorage.fm.storade.device.storage.dsp.DSPUtil",[$localDSP]);
    $res=$dspUtil->doPost("/arpDel.htm",["port","arpEntry"],[$targetPort,"0.0.0.0"]);
#print $res;
    $client->closeSession();
  };
  if($@){
   #print "Jrex Error: ".Dumper($@);
   $response->{Status} = "StorADE Failure";
   $response->{ErrorCode} = "StorADE";
   $response->{ErrorString}="StorADE is configured improperly, run ras_install";
#   return $response;
  }
  require XML::LibXML;
  my $parser = XML::LibXML->new();
  my $elem;
  my $dom;
  eval {
        $dom = $parser->parse_string($res);
      };
  if ($@) {
   #print("Error parsing XML from \n$@");
   #print $res;
   $response->{Status} = "StorADE XML Failure";
   $response->{ErrorCode} = "StorADE";
   $response->{ErrorString}="StorADE is configured improperly, run ras_install";
   return (undef, $response);
  }else{
    $elem = $dom->getDocumentElement();
  }
  foreach my $el ($elem->getChildNodes()) {
    next if ($el->getType() != &XML::LibXML::ELEMENT_NODE() );
    my $name = $el->getName();
    my $elval = Util->rtrim($el->textContent());
    $response->{$name} = $elval;
  }
  return (undef, $response);
}

1;
