#
# Copyright (c) 2001, 2007, Oracle. All rights reserved.  
#
#  $Id: Emc.pm 21-jun-2007.19:39:46 spanchum Exp $ 
#
#
#
# NAME
#   Emc.pm
#
# DESC 
#   emc symmetrix specific subroutines
#
#
# FUNCTIONS
#
# sub generateDiskId( $ );  generate a edisk key for emc disks
# sub parsesymoutput;    parse the results of sympd to build a hash list
# sub getDiskinfo( $ );   return emc disk information from the list    
#
# NOTES
#
#
# MODIFIED  (MM/DD/YY)
# spanchum 06/21/07 - Backport rajverma_bug-6113649 from main
# spanchum 04/03/07 - Backport spanchum_bug-5842718 from main
# spanchum 01/23/07 - use symcli if present
# ajdsouza 04/04/05 - use sq_emc_serial instead of sq_serial_no
# ajdsouza 08/18/04 - override symcli not available
# ajdsouza 08/09/04 - 
# ajdsouza 06/25/04 - storage reporting sources 
# ajdsouza 04/14/04  - 
# ajdsouza 04/08/04 -  storage reporting modules 
# ajdsouza  10/01/01 - Created
#

package storage::vendor::Emc;

require v5.6.1;

use strict;
use warnings;
use locale;
use XML::Parser;

#-------------------------------------------------
# subs defined 
#------------------------------------------------
sub generateDiskId( $ );
sub getDiskinfo( $ );
sub generateClariionDiskId($);
sub getClariionDiskinfo($);
           
#---------------------------------------------
# Variables with Global scope
#---------------------------------------------
my $ret_val = "" ;
my $pd_name = "" ;
my $dev_name = "";
my $symmetrix_id = "";

#------------------------------------------------------------------------------------
# FUNCTION : generateDiskId (Symmetrix)
#
#
# DESC
# Generate a ID for a disk device
#
#
# ARGUMENTS:
# Reference to a Hash for the disk with the name,,inode serial_no of the disk
#
#------------------------------------------------------------------------------------
sub generateDiskId( $ )
{
  my ( $diskref ) = @_;
  
  warn "Disk name passed is NULL to get EMC Disk Information \n" 
   and return 
    unless $diskref->{nameinstance};
  
  getDiskInfo( $diskref ) 
   unless $diskref->{storage_system_id};
    
  warn "Failed to generate a diskkey from vendor information for disk $diskref->{nameinstance}\n"
   and return 
    unless 
    (  
     $diskref->{storage_system_id}
     and $diskref->{storage_disk_device_id}
    );

  $diskref->{vendor}='EMC' 
   unless $diskref->{vendor};

  # Form a diskkey from the symid and deviceid parsed from the serial number
  if ( $diskref->{product} and $diskref->{product} =~ /SYM/i )
  {
   $diskref->{disk_key} = 
    "$diskref->{vendor}-SYMMETRIX-$diskref->{storage_system_id}-$diskref->{storage_disk_device_id}"
  }
  else
  {
   $diskref->{disk_key} = 
    "$diskref->{vendor}-$diskref->{storage_system_id}-$diskref->{storage_disk_device_id}"
  }
  
  return 1;

}

#------------------------------------------------------------------------------------
# FUNCTION : getDiskinfo (Symmetrix)
#
#
# DESC
# Add to the hash EMC symmetrix specific disk information  
#
#
# ARGUMENTS:
# Reference to a Hash for the disk with the logical name of the disk
#
#------------------------------------------------------------------------------------
sub getDiskinfo( $ )
{
  
  my $diskref = $_[0];
  
  warn "Disk name passed is NULL to get EMC Disk Information \n" 
   and return 
    unless $diskref->{nameinstance};
 
  warn "Disk sequence no is NULL for EMC disk $diskref->{nameinstance}\n" 
   and return 
    unless $diskref->{sq_emc_serial};


  # Check is the Symcli / Soulutions Enabler is installed 
  if (-e "/usr/symcli/bin/sympd" )
  {
     my $command = "/usr/symcli/bin/sympd show  -output xml " . $diskref->{name};
     my $xml_out = `$command`;
     if($xml_out ne "")	
     {
        my $parser = XML::Parser->new(Handlers =>{
                     Start=>\&handle_start,
                     });
        $parser->parse($xml_out); 
     }
  }
 
  #If symcli returns data, then get device_id:port_no
  if ($ret_val ne "")
  {
     my ($symm_id, $device_id,$dir_id,$port_no) = split(/:/,$ret_val);
     $diskref->{storage_system_id}      = $symm_id;
     $diskref->{storage_disk_device_id} = $device_id.":".$dir_id.":".$port_no;
     $ret_val = "";  #reset ret_val
  }
  # Else use the default from disk serial .
  else
  {
  # Parse the symid and deviceid from the scsi serial number
  my ($symid,$deviceid,$port)  = 
   ( $diskref->{sq_emc_serial} =~ /^\s*(......)(...)(...).*/i );

  warn "Failed to get the EMC system id for disk $diskref->{nameinstance}\n"
   and return 
    unless $symid;

  $deviceid = '000' unless $deviceid;
    
  # Copy values farmed from the sq_emc_serial for EMC Symmetrix
  $diskref->{storage_system_id}      = "      ".$symid;
  $diskref->{storage_disk_device_id} = " ".$deviceid.":"."NA".":"."NA";
  } 
  return 1;

}

sub handle_start
{
   my($expat, $element,%attrs) = @_;
   my $dir        = "";
   my $port       = "";

   if($element eq "Device")
   {
      if(%attrs)
      {
         $pd_name    = $attrs{"pd_name"};		
         $dev_name   = $attrs{"dev_name"};
      }	
   }
   if($element eq "Product" )
   {
      if(%attrs)
      {
         $symmetrix_id = $attrs{"symmetrix"};
      }
   }
   if($element eq "Port")
   {
      if(%attrs)
      {
         my $temp_pdname = $attrs{"pd_name"};
         if($pd_name eq $temp_pdname)
         {	
            $dir  = $attrs{"director"};
            $port = $attrs{"port"};
            $ret_val = $symmetrix_id.":".$dev_name.":".$dir.":".$port ;
            #return  1 ;
         }
      }	
   }	
}



#------------------------------------------------------------------------------------
# FUNCTION : generateClariionDiskId
#
#
# DESC
# Generate a ID for a Clariion disk device
#
#
# ARGUMENTS:
# Reference to a Hash for the disk with the name,,inode serial_no of the disk
#
#------------------------------------------------------------------------------------

sub generateClariionDiskId( $ )
{
  my ( $diskref ) = @_;

  warn "Disk name passed is NULL to get EMC Disk Information \n"
   and return
    unless $diskref->{nameinstance};

  getClariionDiskInfo( $diskref )
   unless $diskref->{storage_system_id};

  warn "Failed to generate a diskkey from vendor information for disk $diskref->{nameinstance}\n"
   and return
    unless
    (
     $diskref->{storage_system_id}
     and $diskref->{storage_disk_device_id}
    );

  $diskref->{vendor}='DGC'
   unless $diskref->{vendor};

 # Form a diskkey from the clariionid and deviceid parsed from the serial number
  if ( $diskref->{product} and $diskref->{product} =~ /DGC/i )
  {
   $diskref->{disk_key} =
    "$diskref->{vendor}-CLARIION-$diskref->{storage_system_id}-$diskref->{storage_disk_device_id}"
  }
  else
  {
   $diskref->{disk_key} =
    "$diskref->{vendor}-$diskref->{storage_system_id}-$diskref->{storage_disk_device_id}"
  }

  return 1;

}

#------------------------------------------------------------------------------------
# FUNCTION : getClariionDiskinfo
#
#
# DESC
# Add to the hash EMC Clariion specific disk information
#
#
# ARGUMENTS:
# Reference to a Hash for the disk with the logical name of the disk
#
#------------------------------------------------------------------------------------
sub getClariionDiskinfo( $ )
{

  my $diskref = $_[0];
 
  warn "Disk name passed is NULL to get EMC Disk Information \n"
   and return
    unless $diskref->{nameinstance};

  #Get the Array ID from the serial ascii
  warn "Failed to get the Clariion system id for disk $diskref->{nameinstance}\n"
   and return 
    unless  $diskref->{sq_serial_no_ascii};
  $diskref->{storage_system_id} = uc($diskref->{sq_serial_no_ascii});

  #Get the LUN UID from the page83 data.
  warn "Failed to get the Clariion device id for disk $diskref->{nameinstance}\n"
   and return 
    unless  substr($diskref->{sq_vpd_pagecode_83},8,32);
  $diskref->{storage_disk_device_id} = uc(substr($diskref->{sq_vpd_pagecode_83},8,32));

  return 1;

}

1;
