#!/usr/bin/perl
#
## @summary Retrieve various commands outputs from filer
##
## @description
##   Gather information from various filer commands on a remote filer
##   and place it in a specified directory. From that directory, also
##   create a tarball, either compressed (Solaris) or gzipped (Windows,
##   HP-UX)
##
## @arg -d dir Optional: specify alternate output directory
##
## @arg -l login[:password] Optional: specify user/password for filer
##
## @arg -n name Required: name of filer
##
#
# Copyright (C) 2002-2003 Network Appliance, Inc.
#
use strict;
use Socket;
use vars qw($opt_d $opt_n $opt_l $opt_h $opt_u $opt_f $opt_v);
use Getopt::Std;
use Cwd;
use English;
use File::Basename;

my $dir;
my ($name, $path, $suffix) = fileparse($0);
push @INC, $path;
require SHsupport;

my ($filer,$partner, $user, $version, $release);

my $usage="filer_info [-d <directory>] [-l <login>[:<password>]] [-f] -n <filer> [-u <command>]\n" .
    "filer_info -[v]h\n";
#
# Map filer commands against output file names
#
my %cmd_map = (
	       "options" => "options",
	       "ifconfig_a" => "ifconfig -a",
	       "ifstat" => "ifstat -a",
	       "netstat_s" => "netstat -s",
	       "netstat_r" => "netstat -r",
	       "license" => "priv set -q advanced; license",
	       "sysconfig_av" => "sysconfig -av ",
	       "sysconfig_r" => "sysconfig -r ",
	       "df_r" => "df -r ",
	       "snap_list" => "snap list",
	       "snap_delta" => "snap delta",
	       "iscsi_security" => "iscsi security show",
	       "iscsi_status" => "iscsi status",
	       "iscsi_stats" => "iscsi stats",
	       "iscsi_nodename" => "iscsi nodename",
	       "fcp_show_cfmode" => "fcp show cfmode",
	       "fcp_show_adapter" => "fcp show adapter -v",
	       "fcp_show_initiator" => "fcp show initiator -v",
	       "fcp_status" => "fcp status",
	       "fcp_stats" => "fcp stats",
	       "fcp_config" => "fcp config",
	       "fcp_nodename" => "fcp nodename",
	       "igroup_show" => "igroup show",
	       "igroup_show_verbose" => "igroup show -v",
	       "options_lun" => "options lun",
	       "lun_show" => "lun show -v all",
	       "lun_config_check" => 
			"priv set -q advanced; lun config_check -v",
	       "vol_status" => "vol status -v",
	       "version" => "version",
	       "cf_status" => "cf status",
	       "cf_monitor" => "cf monitor",
	       "cf_partner" => "cf partner",
	       "messages_log" => "rdfile /etc/log/messages",
	       "audit_log" => "rdfile /etc/log/auditlog",
		   "vif_status" => "vif status",
		   "ipsec_policy" => "ipsec policy show",
		   "ipsec_sa" => "ipsec sa show",
		   "ipspace_list" => "ipspace list",
		   "netstat_in" => "netstat -in",
		   "vlan_stat" => "vlan stat",
		   "vfiler_status" => "vfiler status",
		   "snapmirror_status" => "snapmirror status",
	       );

if ($OSNAME eq "MSWin32") {
  $dir = substr(getcwd(),0,2) . "\\temp\\netapp";
} else {
  $dir = "/tmp/netapp";
}

my $usage1="\nCollects configuration information about filer and packages\n" .
    "it ready to be sent to Network Appliance	 Customer Support.\n" .
    "\t-n <filer> specify the filer to query\n\t-d <directory>\tdirectory to " .
    "place the files in (default is $dir)\n\t-l <login>[:<password>]\tgives " . 
    "the login/password for the filer\n\t-f overwrite existing files\n" .
    "\t-h print help and exit\n\t-u <command> execute specific filer command";
my $usage2="";

my $j=0;
for my $key ( sort keys %cmd_map ) {
    if ($j%4==0) {
      $usage2 = $usage2 . "\n\t   " . $key;
    } else {
      $usage2 = $usage2 . ", " . $key;
    }
    $j++;
}

#
# Parse the possible options: "-d", "-n", and "-l"
getopts('fhd:l:n:u:v');

if ($opt_h) {
    print $usage;
    print $usage1;
    if ($opt_v) {
      print $usage2;
    }
    print "\n";
    exit 0;
}

#
# Change output directory if desired. Do directory setup
#
&SHsupport::get_os_specific($opt_d);

#
# Check that we have root/admin privilege.
#
&SHsupport::check_root_status();

#
# The "-n" flag is mandatory, to figure out which filer to contact.
#
if (defined($opt_n)) {
    $filer = $opt_n;
} else {
    print $usage;
    exit 1;
}

#
# The "-l" flag has a default to root.
$user = defined($opt_l) ? $opt_l : "root";

#
# Ping the filer. If we don't reach it, the subroutine will complain
# and exit.
#
&SHsupport::ping_remote("filer", $filer);

#
# This check will immediately return if not VMware.  Otherwise, it will 
# check to ensure the VMware firewall ports have been opened.
#
&SHsupport::check_firewall_status("rshClient");

#
# Determine the ONTAP version of the filer and build the cmd_map accordingly.
# If we can't determine the version, execute all commands. Also log the success
# or failure of the commands to the "filer_info_log" file.
#
$release = &SHsupport::rshget($filer, $user, "version");
if ($release =~ /^NetApp Release (.*)/) {
	$release = $1;
	if ((substr($release,0,3) =~ "7.1") || (substr($release,0,3) =~ "7.2") ||
		(substr($release,1,8) =~ "tsingtao") || (substr($release,1,13) =~ "gordonbiersch")) {

		$version = "postTsingtao";

	} elsif ((substr($release,0,3) =~ "6.4") || (substr($release,0,3) =~ "6.5") || (substr($release,0,3) =~ "7.0") ||
		(substr($release,1,8) =~ "fullsail") || (substr($release,1,9) =~ "scrimshaw") || (substr($release,1,11) =~ "anchorsteam")) {

		$version = "preTsingtao";

	} else {

		$version = "unknown";
	}
# check for Data ONTAP Release for IBM rebranding.
} elsif ($release =~ /^Data ONTAP Release (.*)/) {
	$release = $1;
	if ((substr($release,0,3) =~ "7.1") || (substr($release,0,3) =~ "7.2") ||
		(substr($release,1,8) =~ "tsingtao") || (substr($release,1,13) =~ "gordonbiersch")) {

		$version = "postTsingtao";

	} elsif ((substr($release,0,3) =~ "6.4") || (substr($release,0,3) =~ "6.5") || (substr($release,0,3) =~ "7.0") ||
		(substr($release,1,8) =~ "fullsail") || (substr($release,1,9) =~ "scrimshaw") || (substr($release,1,11) =~ "anchorsteam")) {
# This check may not be needed. I am leaving this here as a 
# safeguard so that if IBM needs a rebranded pre TT version
# we are covered.

		$version = "preTsingtao";

	} else {

		$version = "unknown";
	}

}

#
# Map filer commands against output file names
#
if ( $version =~ "postTsingtao" ) {

	$cmd_map{"iscsi_alias"} = "iscsi alias";
	$cmd_map{"iscsi_connection"} = "iscsi connection show -v";
	$cmd_map{"iscsi_initiator"} = "iscsi initiator show";
	$cmd_map{"iscsi_interface"} = "iscsi interface show";
	$cmd_map{"iscsi_portal"} = "iscsi portal show";
	$cmd_map{"iscsi_session"} = "iscsi session show -v";
	$cmd_map{"iscsi_tpgroup"} = "iscsi tpgroup show";
	$cmd_map{"iscsi_isns"} = "iscsi isns show";
} elsif ( $version =~ "preTsingtao" ) {

	$cmd_map{"iswt_session_iswta"} = "iswt session show -v iswta";
	$cmd_map{"iswt_session_iswtb"} = "iswt session show -v iswtb";
	$cmd_map{"iswt_interface"} = "iswt interface show";
	$cmd_map{"iscsi_show_adapter"} = "iscsi show adapter";
	$cmd_map{"iscsi_show_initiator"} = "iscsi show initiator";
	$cmd_map{"iscsi_config"} = "iscsi config";
} else {

	$cmd_map{"iswt_session_iswta"} = "iswt session show -v iswta";
	$cmd_map{"iswt_session_iswtb"} = "iswt session show -v iswtb";
	$cmd_map{"iswt_interface"} = "iswt interface show";
	$cmd_map{"iscsi_show_adapter"} = "iscsi show adapter";
	$cmd_map{"iscsi_show_initiator"} = "iscsi show initiator";
	$cmd_map{"iscsi_config"} = "iscsi config";
	$cmd_map{"iscsi_alias"} = "iscsi alias";
	$cmd_map{"iscsi_connection"} = "iscsi connection show -v";
	$cmd_map{"iscsi_initiator"} = "iscsi initiator show";
	$cmd_map{"iscsi_interface"} = "iscsi interface show";
	$cmd_map{"iscsi_portal"} = "iscsi portal show";
	$cmd_map{"iscsi_session"} = "iscsi session show -v";
	$cmd_map{"iscsi_tpgroup"} = "iscsi tpgroup show";
	$cmd_map{"iscsi_isns"} = "iscsi isns show";
}

#
# Test for the output files already in the way, and complain if so.
#
&SHsupport::test_existing_files("_KIT_BRAND__filer_" . "$filer", 0, $opt_f);

if (defined($opt_u)) {
    print "opt_u $opt_u\n";
    my $cmd = $cmd_map{$opt_u};
    my $out;
    if ($cmd ne "") {
	$out = &SHsupport::rshget($filer, $user, $cmd);
	if ($? != 0) {
	    print "Unable to rsh to filer $filer.  Please ";
	    print "configure $filer for rsh\n";
	    print "access from this host (or provide login:password)";
	    print " and try again.\n";
	    exit 1;
	} else {
	    print $out;
	    exit;
	}
    } else {
	print "Unknown command $opt_u\n";
	exit;
    }
}

#
# Cycle through all the commands we run against the filer and
# squirrel away the outputs.
#
&SHsupport::update_user();
open LOGFILE, ">filer_info_log";
foreach my $el (sort keys %cmd_map) {
    
    &SHsupport::update_user();
    if (&SHsupport::rshgetother($filer, $user, $cmd_map{$el}, $el) == 0) {
		print "Unable to rsh to filer $filer.  Please ";
		print "configure $filer for rsh\n";
		print "access from this host (or provide login:password)";
		print " and try again.\n";
    	print LOGFILE "ERROR: Failed to execute $cmd_map{$el}\n";
		close LOGFILE;
		exit 1;
    } else {
    	print LOGFILE "SUCCESS: $cmd_map{$el}\n";
	}
}

# If this is a CFO config and the partner has been taken over, save the
# partner info too. partner info filers will be suffixed with ".<partnername>".
my $cfstatus = &SHsupport::rshget($filer, $user, "cf status");
if ($cfstatus =~ /^\w+ has taken over (\w+)/) {
    $partner = $1; 
    # We have taken over the partner. Run the 'partner cmd' variants
    foreach my $el (sort keys %cmd_map) {
		# This is a hack for priv set -q advanced
		my $cmd = $cmd_map{$el};
		$cmd =~ s/\;/\; partner/;
		&SHsupport::update_user();
		if (&SHsupport::rshgetother($filer, $user, "partner $cmd", $el.".".$partner) == 0) { 
			print LOGFILE "ERROR: Failed to execute $cmd_map{$el} on partner filer\n";
		} else {
    		print LOGFILE "SUCCESS: partner $cmd_map{$el}\n";
		}
    }
} elsif ($cfstatus =~ /Cluster enabled, (\w+) is up/) {
    # The partner is up. Go to it to get all the files.
    $partner = $1; 
    foreach my $el (sort keys %cmd_map) {
		&SHsupport::update_user();
		if (&SHsupport::rshgetother($partner, $user, $cmd_map{$el}, $el . "." . $partner) == 0) {
		    print "\nUnable to rsh to filer $partner for partner info.\n";
		    print " Please configure $partner for rsh access\n";
		    print "from this host (or provide login:password) and try again.\n";
		    print "If the passwords on $filer and $partner differ, please run\n";
		    print "this script with \"-n $partner\" to gather complete information.\n";
       		print LOGFILE "ERROR: Failed to execute $cmd_map{$el} on partner filer\n";
			close LOGFILE;
			exit 1;
		    last;
		} else {
    		print LOGFILE "SUCCESS: partner $cmd_map{$el}\n";
		}
    }
} else {
    # It's probably not a cluster, so don't do anything
}
close LOGFILE;

# Tar it up.
&SHsupport::make_tarball();

# Say bye-bye.
&SHsupport::print_summary("Filer $filer");

exit 0;


