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

##################################################################
#T3Connection.pm
#Package T3Connection
##################################################################
package T3Connection;

use strict;
use LWP::UserAgent;
use Data::Dumper;
use HTTP::Request;
use HTTP::Response;
use URI::Heuristic;
use Util;

##################################################################
#T3Connection Consturctor
##################################################################
sub new {
  my $this = {}; 
  # object properties
  shift;
  $this->{T3address} = shift;
  $this->{T3url} = URI::Heuristic::uf_urlstr($this->{T3address});
  $this->{sysModel} = "device";
  $this->{usr} = shift;
  $this->{pass} = shift;
  $this->{ua} = LWP::UserAgent->new();
  $this->{ua}->agent("Storade 2.0");
  $this->{ua}->timeout(60);     #this is the HTTP GET time out in secs.
  $this->{sysprop}=undef;	#these get initialized in the init f(x)
  $this->{elemprop}=undef;
  $this->{set_debug}=undef;
  $this->{set_verbose}=undef;
  $this->{error}=undef;
  $this->{ondgOperPending}=undef;
  $this->{ondgOperProgress}=undef;
  $this->{ondgError}=undef;
  $this->{num_error}=0;
  $this->{defaultunitIndex}=0;
  $this->{DiskScrubber}="off";
  bless($this, 'T3Connection'); 
  return $this;
}
##################################################################
#T3Connection::init
##################################################################
sub init {
  my $this = shift;
  if ($this->{set_debug}){ print "initilizing T3 $this->{T3address}\n"; }
  my $sysprop = $this->get_html("http://$this->{T3address}/sysprop.htm");
  my $elemprop = $this->get_html("http://$this->{T3address}/elemprop.htm");
  my $system    = $this->get_html("http://$this->{T3address}/system.htm");
  my $ofdgoper  = $this->get_html("http://$this->{T3address}/ofdgoper.htm");
  my $volprop   = $this->get_html("http://$this->{T3address}/volprop.htm");
  my $frudata   = $this->get_html("http://$this->{T3address}/frudata.htm");
  my $vol       = $this->get_html("http://$this->{T3address}/vol.htm");
  return $this->refresh();
}

##################################################################
#T3Connection::set_debug
##################################################################
sub set_debug {
  my $this = shift;
  $this->{set_debug}="On";
  return "On";
}

##################################################################
#T3Connection::set_verbose
##################################################################
sub set_verbose {
  my $this = shift;
  $this->{set_verbose}="On";
  return "On";
}

##################################################################
#T3Connection::refresh
##################################################################
sub refresh {
  my $this = shift;
  my $option =shift;

  if(!($option =~ /elemprop/i)){
  #get sysprop first
  if ($this->{set_debug}){
    print "refreshing http://$this->{T3address}/sysprop.htm\n";
  }
  $this->{error}= undef;
  my @stat;
  my $sysprop  = $this->get_html("http://$this->{T3address}/sysprop.htm");
     $sysprop .= $this->get_html("http://$this->{T3address}/system.htm");
     $sysprop .= $this->get_html("http://$this->{T3address}/ofdgoper.htm");
  if (!$sysprop || $this->{error}){return 0;}
    $this->{sysprop} = $sysprop;
    my @lines=split(/\n/,$sysprop);
    my $line=undef;
    my @words=undef;
    if ($this->{set_debug}){ print "parsing syprop\n" }
    foreach $line (@lines){

      if($line =~/sysModel/){
	@words=split(/;/,$line);
        @stat=split(/,/,$words[1]);
        $this->{sysModel}=Util->trim($stat[2]);
      }
      if($line =~/unitCount/){
	@words=split(/;/,$line);
        @stat=split(/,/,$words[1]);
        $this->{unitCount}=$stat[2];
      }

      if($line =~/ondgOperPending/){
	@words=split(/;/,$line);
        @stat=split(/,/,$words[1]);
        $this->{ondgOperPending}=$stat[2];
      }

      if($line =~/ondgOperProgress/){
	@words=split(/;/,$line);
        @stat=split(/,/,$words[1]);
        $this->{ondgOperProgress}=$stat[2];
      }

      if($line =~/ondgError/){
	@words=split(/;/,$line);
        @stat=split(/,/,$words[1]);
        $this->{ondgError}=$stat[2];
      }

      if($line =~/volCount/){
	@words=split(/;/,$line);
        @stat=split(/,/,$words[1]);
        $this->{volCount}=$stat[2];
      }

      if($line =~/sysHasVolumes/){
	@words=split(/;/,$line);
        @stat=split(/,/,$words[1]);
        $this->{sysHasVolumes}=$stat[2];
      }
      if($line =~/sysDiskScrubber/){
	@words=split(/;/,$line);
        @stat=split(/,/,$words[1]);
        $this->{DiskScrubber}=$stat[2];
      }
    } 
    if($this->{set_debug}){
      print "Refreshed $this->{T3address} :: sysprop.htm\n";
    }
  }

  if(!($option =~ /sysprop/i)){
  #now get elemprop
    my $hash;
    my $elemprop;
    for(my $i = 0; $i < $this->{unitCount}; $i++ ){
      $elemprop .= $this->get_html(
                     "http://$this->{T3address}/elemprop.htm?unitIndex=$i");
    }
    $elemprop .= $this->get_html(
                     "http://$this->{T3address}/volprop.htm");
    $elemprop .= $this->get_html(
                     "http://$this->{T3address}/frudata.htm");
    $elemprop .= $this->get_html(
                     "http://$this->{T3address}/vol.htm");
    if (!$elemprop){ 
      return 0;
    }
    my @elemlines=split(/\n/,$elemprop);
    my $line=undef;
    my @words=undef;
    my @stats=undef;
    my $token;
    my $value;
    foreach $line (@elemlines){
    $line = Util->trim($line);
      if($line =~ /^\;/){
        @words=split(/;/,$line);
        @stats=split(/,/,$words[1]);
        #$value=@stats[$#stats];
        #@stats[$#stats] = undef;
        $value=pop(@stats); #Fix for  
        $token=undef;
        foreach my $stat (@stats){ $token .= $stat;}
          $hash->{$token}=$value;
          #print "\$hs->{$token}= $hs->{$token}=$value\n";
        }
      }
	
      if($this->{set_debug}){
        print "Refreshed $this->{T3address} :: elemprop.htmi\n";
      }
    $this->{elemprop}=undef;
    $this->{elemprop}=\%$hash;
    }

  return 1;
}

##################################################################
#T3Connection::get_html
##################################################################
sub get_html {
  my $this = shift;
  my $doc = shift;

  if($this->{set_debug}){
    print "get_html Attempting to http get $doc\n"; 
  }

  my $T3url;
  my $error_line;

  if(defined($this->{usr}) && defined($this->{pass}) ) {
    (my $pre, my $post)=split(/http:\/\//, $doc);
    if ($this->{set_debug}){ print "\$pre: $pre  \$post: $post";}
    $T3url= 
      URI::Heuristic::uf_urlstr("http://$this->{usr}:$this->{pass}\@".$post);
    $error_line = "http://$this->{usr}:<password>\@".$post;
  }else{ 
     my $T3url = URI::Heuristic::uf_urlstr($doc);
     $error_line = $doc;
  }

  my $request = HTTP::Request->new(GET => $T3url);
  $request->referer("http://sun.com");
  $request->content_type('application/x-www-form-urlencoded');

  if ($this->{set_debug}){ print "Attempting to http get $T3url\n"; }
  my $response = $this->{ua}->request(HTTP::Request->new(GET => $T3url));
  my $content = undef;
  if ($response->is_error()) {
      $this->{num_error}++;
      $this->{error}= "\nError getting $error_line\n".
      		 "Status line: ".$response->status_line."\n".
      		 "Array may not be responding or possible invalid IP address,".
		 " hostname, login, or password.\n";
      return 0;
  }else{
    $content = $response->content();
    if ($this->{set_debug}){ 
     print "get_html recieved $doc with out error\n"; 
    }
    return $content;
  }
}

##################################################################
#T3Connection::canOFDG
##################################################################

sub canOFDG{
  my ($this, $args) = @_;
  my ($ERR, $elemprop, $disks);
  if (defined($this->{elemprop})){
    $elemprop = $this->{elemprop};
    foreach my $token(keys %$elemprop){
      if(($elemprop->{$token} =~ /unassigned/)&&
         ($token=~/^u\dd\d+fruDiskRole/)&&
         ($token!~/^u1/)){    #this is to skip the 1st Unit
	 my @disk = split(/fruDiskRole/, $token);
	 if ($elemprop->{@disk[0]."fruStatus"} ne "dummy"){
	   $disks .="\t@disk[0]\n";
	 }
      }
    }
    if(defined($disks)){
      $ERR="OFDG cannot run when all disks in any unit besides unit 1 are".
           " not in a volume.\nRECOMENDED-ACTION:\nAssign the following drives".
           " to a volume and run OFDG again.\n$disks";
    }
  }else{
    $ERR="No out of band Data, Verify Device is booted, ethernet is connected,".
    " and web directory is installed."
  }
  return ($ERR);
}

##################################################################
#T3Connection::setFRULED
# call this method (coppied from Purple 2 3.0 API)
#1. fruSetLed
#Type: Enum {"ok", "busy", "disabled", "failed", "service",
#		"locate", "nolocate"}
#    Property of:    FRU
#    Access:         write-only
#    Index:	     unitIndex
#                    fruIndex
#Description: Set fru level leds
##################################################################

sub setFRULED {
  my $this = shift;
  my $unit = shift;
  my $fru = shift;
  my $LEDstat = shift;
  my $settings="update?unitIndex=$unit&fruIndex=$fru";
  my $command="fruSetLed=$LEDstat";
  $this->issueCommand($settings, $command);
}

##################################################################
#T3Connection::setUnitLED
# call this method (coppied from Purple 2 3.0 API)
#1. unitSetLeds
#Type: Enum {"ok", "busy", "disabled", "failed", "service",
#"locate", "nolocate"}
#Property of: Unit
#Access: write-only
#Index: unitIndex
#Description: Set unit level led.
##################################################################

sub setUnitLED {
  my $this = shift;
  my $unit = shift;
  my $LEDstat = shift;
  my $settings="update?unitIndex=$unit";
  my $command="unitSetLeds=$LEDstat";
  $this->issueCommand($settings, $command);
}

##################################################################
#T3Connection::blastWebFiles
#returns Hash
##################################################################

sub blastWebFiles {
  my $this = shift;
  use Net::FTP;
  use System;
  my $res;
  my $webFileDir = System->home_dir().  "/archive/3.0webfiles";
  my $ftp = Net::FTP->new($this->{T3address}, Debug => 0);
  $res = $ftp->login($this->{usr},$this->{pass});
  
  my $rootFiles = $ftp->dir("/");
  if("@$rootFiles" !~ /\/web /){
    print "There is no \"/web\" directory on the $this->{sysModel}\n";
    print "Creating \"/web\" directory on the $this->{sysModel}\n";
    $res = $ftp->mkdir("/web") or print "unable to mkdir /web\n";return(-1);
  }
  $res = $ftp->cwd("/web");
  my $actualWebFiles = $ftp->dir("/web");
  foreach my $file (<$webFileDir/*>){
    my @dirs = split(/\//,$file);
    if("@$actualWebFiles" !~ /@dirs[$#dirs]/ ){
      print "ftp->put(".@dirs[$#dirs].")\n";
      $ftp->put($file);
    }else{
      print "No Need to trasfer \"".@dirs[$#dirs]."\", the file already exsists\n";
    }
  }
  $ftp->quit;
}

##################################################################
#T3Connection::runFastTest
##################################################################

sub runFastTest {
  my $this = shift;
  my $unit = shift;
  my $loop = shift;
  my $settings="update?unitIndex=$unit&loopIndex=$loop";
  my $command="ondgFastTest=FastTest";
  $this->issueCommand($settings, $command);
}

##################################################################
#T3Connection::runHealthCheck
##################################################################

sub runHealthCheck {
  my $this = shift;
  my $settings="update?";
  my $command="ondgHealthCheck=HealthCheck";
  $this->issueCommand($settings, $command);
}

##################################################################
#T3Connection::runFastFind
##################################################################

sub runFastFind {
  my $this = shift;
  my $unit = shift;
  my $loop = shift;
  my $settings="update?unitIndex=$unit&loopIndex=$loop";
  my $command="ondgFastFind=FastFind";
  $this->issueCommand($settings, $command);
}

##################################################################
#T3Connection::runFind
##################################################################

sub runFind {
  my $this = shift;
  my $unit = shift;
  my $loop = shift;
  my $settings="update?unitIndex=$unit&loopIndex=$loop";
  my $command="ondgFind=Find";
  $this->issueCommand($settings, $command);
}

##################################################################
#T3Connection::KillTest
##################################################################

sub runKillTest {
  my $this = shift;
  my $unit = shift;
  my $loop = shift;
  my $settings="update?sysOndgMode=off";
  my $command="sysApplySettings=Apply";
  $this->issueCommand($settings, $command);
  my $settings="update?ondgAbort=Abort";
  my $command="sysApplySettings=Apply";
  $this->issueCommand($settings, $command);
}


##################################################################
#T3Connection::AbortVolumeOperation
##################################################################

sub AbortVolumeOperation {
  my $this = shift;
  my $unit = shift;
  my $vol = shift;
  my $settings="update?unitIndex=$unit".
	       "&volIndex=$vol";
  my $command="volAbort=Abort";
  $this->issueCommand($settings, $command);
}

##################################################################
#T3Connection::runVolumeVerify
##################################################################

sub runVolumeVerify{
  my $this = shift;
  my $unit = shift;
  my $vol = shift;
  my $rate = shift;
  my $fix = shift;
  my $setting = "update?unitIndex=$unit".
		"&volIndex=$vol".
		"&volVerifyRate=$rate".
		"&volSafety=$fix";
  my $command = "volVerify=Verify";
  $this->issueCommand($setting, $command);

}
##################################################################
#T3Connection::StartMonitoringMessages
##################################################################
sub StartMonitoringMessages {
  my $this = shift;
  my $filter = shift;
  my $doc = $this->{T3address}."/messages";
  my $T3url;

if( defined($this->{usr}) && defined($this->{pass}) ) {
  $T3url= URI::Heuristic::uf_urlstr(
    "http://$this->{usr}:$this->{pass}\@".$this->{T3address}."/messages");
}else{ my $T3url = URI::Heuristic::uf_urlstr($doc);} 
  my $request = HTTP::Request->new(GET => $T3url);
  $request->referer("http://sun.com");
  $request->content_type('application/x-www-form-urlencoded');
  if ($this->{set_debug}){ print "Attempting to http get $T3url\n"; }
  $this->{ua}->timeout(5*60);
  my $response;
  if(defined($filter)){
    $response = $this->{ua}->request(HTTP::Request->new(GET => $T3url),
  					  \&message_filter_output, 80 );
  }else{
    $response = $this->{ua}->request(HTTP::Request->new(GET => $T3url),
  					  \&message_output, 80 );
  }
  my $content = undef;
  if ($response->is_error()) {
  $this->{error}= "\nError getting $T3url\n".
    print "Status line: ".$response->status_line."\n";
    print "Error:\n$this->{error}\n";
    print $response->content();
    print "Status line: ".$response->status_line."\n";
    return 0;
  }else{
  $content = $response->content();
  if ($this->{set_debug}){
    print "get_html recieved $doc with out error\n";
  }
  return $content;
}
}

##################################################################
#T3Connection::issueCommand
##################################################################
sub issueCommand {
  my $this = shift;
  my $setting=shift;
  my $command = shift;
  my $path=URI::Heuristic::uf_urlstr("http://".$this->{T3address}."/$setting");
  my $req = HTTP::Request->new(POST => $path);
  $req->content_type('application/x-www-form-urlencoded');
  $req->content($command);
  if( defined($this->{usr}) && defined($this->{pass}) ) {
    if(defined($this->{set_debug})){
      print "\n **Authentication**\n";
      print "usr=",$this->{usr},"  pass=\n";
      print $req->url->host_port, "\n";
    }
    $req->authorization_basic($this->{usr}, $this->{pass});
  }else{print "Password or User Name not Found\n";}
  my $res = $this->{ua}->request($req);
  if ($res->is_error()) {
    print "Status line: ".$res->status_line."\n";
    print "Error:\n$this->{error}\n";
    print $res->content();
    print "Status line: ".$res->status_line."\n";
  }
  return $res;
}

##################################################################
#Message Call Backs
##################################################################
sub message_output {
  my $data =shift;
  my $response =shift;
  my $protocol =shift;

  print $data."\n";
  
}

sub message_filter_output {
  my $data =shift;
  my $response =shift;
  my $protocol =shift;
  if($data =~ /ONDG/){
    print $data."\n";
  }
}
  


1;

