#!/usr/bin/perl -w
# Copyright (c) 2006 Red Hat, Inc. All rights reserved. This copyrighted
# material is made available to anyone wishing to use, modify, copy, or
# redistribute it subject to the terms and conditions of the GNU General
# Public License v.2.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
# USA.
#
# Author: Xiaowei Li <xiaoli@redhat.com>

# only run this test on st05_lpfc

use strict;
use LibSAN;
use LibSAN::Host::FC qw/:all/;
use LibSAN::Host::SCSI qw/:all/;
use ST::Misc qw/:all/;
use ST::Cmd qw/:all/;
use ST::DT qw/:all/;
use ST::MP::All qw/:all/;
use Time::HiRes qw( time );
use Data::Dumper;


###################### global variables ##########
our $obj;
our @lun_names;
our $dt_pid;
our $t_wwpn;
our $base_mpath;

###################### cleanup ###################
sub _cleanup{
# kill dt
    run("kill -9 $dt_pid");

    foreach my $lun_name (@lun_names) {
        my $wwid  = $obj->wwid_of_lun($lun_name);
        my $mpath = mp_mpath_name_of($wwid);
        mp_remove_mpath($mpath);
        my $ref_scsi_disks = scsi_ids_of_wwid($wwid);
        $obj->lun_remove( $lun_name );
    }
    $obj->port_rscn_disable( $t_wwpn );
    $obj->link_down( $t_wwpn );
    $obj->link_up( $t_wwpn );
    #Release NFS lock as it is not needed any more
    run("stqe-tool release_nfs_lock --mpath $base_mpath --lock_type exclusive");
    #Release already wait 120s
    #sleep 60;
}

sub _texit {
    my $msg = shift;
    _cleanup();
    texit($msg);
}


# select the mpath
my @mpaths = get_mpath_devices();
unless (@mpaths) {
    tlog "FAIL: no mpath devices\n";
    exit 1;
}
$base_mpath = $mpaths[0];
$obj = create_libsan_for_mpath($base_mpath);
texit("failed to create the libSAN object") unless $obj;
my @t_wwpns = @{$obj->t_wwpns};
texit("should have at least two target ports") if $#t_wwpns < 1;
 $t_wwpn = $t_wwpns[0];
texit("not proper target port is attached to this host") unless $t_wwpn;

@lun_names;
for (my $index = 1; $index <= 4; $index ++) {
    my $lun_name = $obj->lun_create_and_map( size => '1GiB' );
    push @lun_names, $lun_name;
}
my @fc_host_ids = fc_host_id_of();
foreach my $hostid (@fc_host_ids) {
    rescan($hostid);
};

texit("failed to create lun on the storage array") unless $base_mpath;

#Wait until we are able to disable port on target
if (!run("stqe-tool wait_nfs_lock --mpath $base_mpath --lock_type exclusive")) {
    _texit("Could not request access to use Storage Array");
}

# run dt
$dt_pid = dt_stress_background(
    of       => "/dev/mapper/$base_mpath",
    verbose  => 0,
    log_file => "/tmp/$$",
    time     => '1h'
);

sleep 10;

#by default, it's off for RHEL 6.6
#we should test this
my @msgs;
# case 1: rscn is enabled, eh_deadline = 1
my $start = 0;
my $end   = 0;
my $pre_timeout = 0;
my @eh_deadlines = qw(30);
#my @eh_deadlines = qw(0 1 30 60 off);
foreach my $eh_deadline (@eh_deadlines) {
    tlog "eh_deadline = $eh_deadline\n";
    foreach my $hostid (@fc_host_ids) {
        run("echo $eh_deadline > /sys/class/scsi_host/host$hostid/eh_deadline");
    }

    $obj->port_rscn_enable( $t_wwpn ) or _texit("failed to enable the rscn on $t_wwpn");
    $obj->link_down( $t_wwpn ) or _texit("failed to bring the $t_wwpn down");
    sleep 5;
    $start = time();
# run multipath -ll to get the timeout
    run("time multipath -ll &> /dev/null ");
    $end   = time();
    my $timeout = int($end - $start);
    if ($pre_timeout > $timeout) {
        _texit("the eh_deadline cannot work, the timeout is $timeout for $eh_deadline but is greater than the $pre_timeout");
    }
    my $msg = "the timeout value for multipath hung is $timeout seconds: rscn is enabled, eh_deadline=$eh_deadline\n";
    push @msgs, $msg;
    print $msg;

    $obj->port_rscn_disable( $t_wwpn ) or _texit("failed to disable the rscn on $t_wwpn");
    $obj->link_up( $t_wwpn ) or _texit("failed to bring the $t_wwpn up");
    sleep 120;
    run("service multipathd restart &> /dev/null");
    run("multipath -r &>/dev/null");
    sleep 120;
    run("service multipathd restart &> /dev/null");
    run("multipath -r &>/dev/null");
    run("multipath -ll $base_mpath ");
}

_cleanup();

run("service multipathd restart &> /dev/null");
run("multipath -r &>/dev/null");

# print the time report
print "================= testing sumarry ====================\n";
foreach my $msg (@msgs) {
    print "$msg";
    print "$t_wwpn";
}
print "=================       end       ====================\n";

exit 0;
