#
# (c) Jan Gehring <jan.gehring@gmail.com>
# 
# vim: set ts=3 sw=3 tw=0:
# vim: set expandtab:

package Rex::Inventory::HP::ACU;
    
use strict;
use warnings;

use Rex::Commands::Run;
    
sub get {

   if(can_run("hpacucli")) {
      my @lines = run "/usr/sbin/hpacucli controller all show config detail";
      my $ret = parse_config(@lines);
      return $ret;
   }
   else {
      return 0;
   }

}

#
# The bellow code is from Parse::HP::ACU
#
# Copyright 2010 Jeremy Cole.
# 
# This program is free software; you can redistribute it and/or modify it
# under the terms of either: the GNU General Public License as published
# by the Free Software Foundation; or the Artistic License.
# 
# See http://dev.perl.org/licenses/ for more information.
#
sub parse_config
{
   my (@lines) = @_;

   my $controller = {};
   my $current_controller         = 0;
   my $current_array                = undef;
   my $current_logical_drive    = undef;
   my $current_mirror_group      = undef;
   my $current_physical_drive   = undef;

   LINE: for my $line (@lines)
   {
      chomp $line;

      next if($line =~ /^$/);

      if($line !~ /^[ ]+/)
      {
         $current_controller       = $current_controller + 1;
         $current_array               = undef;
         $current_logical_drive   = undef;
         $current_mirror_group    = undef;
         $current_physical_drive = undef;
         $controller->{$current_controller} = {};
         $controller->{$current_controller}
            ->{'description'} = $line;
         next;
      }

      next if(!defined($current_controller));

      $line =~ s/^\s+//g;
      $line =~ s/\s+$//g;
      $line =~ s/[ ]+/ /g;

      if($line =~ /unassigned/)
      {
         $current_array               = "unassigned";
         $current_logical_drive   = undef;
         $current_mirror_group    = undef;
         $current_physical_drive = undef;
         $controller->{$current_controller}
            ->{'unassigned'} = {};
         $controller->{$current_controller}
            ->{'unassigned'}->{'physical_drive'} = {};
         next;
      }

      if($line =~ /Array: ([A-Z]+)/)
      {
         $current_array               = $1;
         $current_logical_drive   = undef;
         $current_mirror_group    = undef;
         $current_physical_drive = undef;
         $controller->{$current_controller}
            ->{'array'}->{$current_array} = {};
         $controller->{$current_controller}
            ->{'array'}->{$current_array}
            ->{'logical_drive'} = {};
         $controller->{$current_controller}
            ->{'array'}->{$current_array}
            ->{'physical_drive'} = {};
         next;
      }

      if($line =~ /Logical Drive: ([0-9]+)/)
      {
         $current_logical_drive   = $1;
         $current_physical_drive = undef;
         $current_mirror_group    = undef;
         $controller->{$current_controller}
            ->{'array'}->{$current_array}
            ->{'logical_drive'}->{$current_logical_drive} = {};
         $controller->{$current_controller}
            ->{'array'}->{$current_array}
            ->{'logical_drive'}->{$current_logical_drive}
            ->{'mirror_group'} = {};
         next;
      }

      if($line =~ /physicaldrive ([0-9IC:]+)/ and $line !~ /port/)
      {
         $current_logical_drive   = undef;
         $current_physical_drive = $1;
         $current_mirror_group    = undef;
         if($current_array eq 'unassigned')
         {
            $controller->{$current_controller}
               ->{'unassigned'}
               ->{'physical_drive'}->{$current_physical_drive} = {};
         } else {
            $controller->{$current_controller}
               ->{'array'}->{$current_array}
               ->{'physical_drive'}->{$current_physical_drive} = {};
         }
         next;
      }

      if($line =~ /Mirror Group ([0-9]+):/)
      {
         $current_mirror_group = $1;
         $controller->{$current_controller}
            ->{'array'}->{$current_array}
            ->{'logical_drive'}->{$current_logical_drive}
            ->{'mirror_group'}->{$current_mirror_group} = [];
         next;
      }

      if(defined($current_array) 
         and defined($current_logical_drive)
         and defined($current_mirror_group))
      {
         if($line =~ /physicaldrive ([0-9IC:]+) \(/)
         {
            my $current_mirror_group_list = $controller->{$current_controller}
               ->{'array'}->{$current_array}
               ->{'logical_drive'}->{$current_logical_drive}
               ->{'mirror_group'}->{$current_mirror_group};

            foreach my $pd (@{$current_mirror_group_list})
            {
               next LINE if($pd eq $1);
            }
            push @{$current_mirror_group_list}, $1;
         }
         next;
      }

      if(defined($current_array)
         and defined($current_logical_drive))
      {
         if(my ($k, $v) = &K_V($line))
         {
            next unless defined($k);
            $controller->{$current_controller}
               ->{'array'}->{$current_array}
               ->{'logical_drive'}->{$current_logical_drive}->{$k} = $v;
         }
         next;
      }

      if(defined($current_array)
         and defined($current_physical_drive))
      {
         if(my ($k, $v) = &K_V($line))
         {
            next unless defined($k);
            if($current_array eq 'unassigned')
            {
               $controller->{$current_controller}
                  ->{'unassigned'}
                  ->{'physical_drive'}->{$current_physical_drive}->{$k} = $v;
            } else {
               $controller->{$current_controller}
                  ->{'array'}->{$current_array}
                  ->{'physical_drive'}->{$current_physical_drive}->{$k} = $v;
            }
         }
         next;
      }
   
      if(defined($current_array))
      {
         if(my ($k, $v) = &K_V($line))
         {
            next unless defined($k);
            $controller->{$current_controller}
               ->{'array'}->{$current_array}->{$k} = $v;
         }
         next;
      }

      if(my ($k, $v) = &K_V($line))
      {
         next unless defined($k);
         $controller->{$current_controller}->{$k} = $v;
      }
      next;
   }
   
   return $controller;
}

sub K
{
   my ($k) = @_;

   $k = lc $k;   
   $k =~ s/[ \/\-]/_/g;
   $k =~ s/[\(\)]//g;

   return $k;
}

sub V
{
   my ($k, $v) = @_;

   if($k eq 'accelerator_ratio')
   {
      if($v =~ /([0-9]+)% Read \/ ([0-9]+)% Write/)
      {
         return {'read' => $1, 'write' => $2};
      }
   }

   return $v;
}

sub K_V($)
{
   my ($line) = @_;

   if($line =~ /(.+):\s+(.+)/)
   {
      my $k = &K($1);
      my $v = &V($k, $2);
      return ($k, $v);
   }

   return (undef, undef);
}
    
1;
