#$Id: //depot/prod/test/Rsierranevada/storage/hdd/NADQ_SEA/FS/Common_Lib.pm#39 $ # # Library of utility functions for HDD qualification tests # # ## @summary Library of routines to help simply HDD qualfication test development ## @description Library of routines to help in simplify the verfication required for various test cases oh hdd test plan. ## ## @synopsis ## use Storage::Common_Lib; ## ## ## @author ## arunak@netapp.com ## vpankaj@netapp.com ## arjunl@netapp.com ## himangin@netapp.com ## aditis@netapp.com #################################################################### ## Subroutines used from 7_Mode Common_lib.pm ## ## ## ## ## ## ## ## ## #################################################################### ## ## Design guidelines to be followed ## ## Each subroutine must use validate options ## Each subroutine must contain author and usage of subroutines ## Every optional value must contain default value assigned ## ## ################################################################### package Storage::Common_Lib; use TCD; use CR::Setup::TCD qw(nlog); use strict; use Tharn; use NACL::C::StorageAggregate; use NACL::APISet; use Data::Dumper; use NACL::C::Disk; use NACL::C::Volume; use NACL::C::Aggregate; use NACL::C::Vserver; use NACL::C::VolumeMember; use NACL::CS::StorageAggregateMember; use NACL::MTask::EventLogDetector; use Utils; use HTML::Mail; use NACL::MTask::SCP; use NACL::C::Client; use NACL::STask::SecurityLogin; use NACL::STask::Node; use NACL::MTask::SystemLogDetector; use Net::SCP::Expect; use boot; use San; use List::Util qw( min max ); use Utils qw(make_conn); use Storage::SASUtils qw(filer_cmd); use Storage::Misc qw(filer_cmd); use install; use misc qw(cli_localhost); use Storage::Storage qw(storage_show_adapter); use POSIX; use NACL::Transit; use Storage::SASUtils qw(disable_dbg_msgs); use HTML::Mail; use NACL::C::Node; use Tharn qw(sleep); use Tharn qw(param); use Hostrec; use Server; use Options; use Expect; use SayRetry; use mount; use NACL::MTask::EventLogDetector; use NACL::STask::StorageFailover; use NACL::CS::Cluster; use Sys::Hostname; use lib "/usr/PNATE/pnate/lib"; use PNATE; use lib "/usr/PNATE/nate/lib"; use NATE; use List::Util qw(shuffle); my $params = NATE::ParamSet->new( global => 1 ); my $FILER = $params->get( 'FILER', default => undef ); my $Kernel = $params->get( 'KERNEL', default => 'SN' ); my $MAIL_TO = $params->get( 'MAIL_TO', default => 'Email to' ); my $MAIL_FROM = $params->get( 'MAIL_FROM', default => 'Email from' ); my $EMAIL = $params->get( 'EMAIL', default => 'y' ); my $RUNID = $params->get( 'RUNID', default => 'undef' ); my $STEST_FILE = $params->get( 'STEST_FILE', default => '' ); my $BOOT_MODE = $params->get( 'BOOT_MODE', default => undef ); my $Filer_mode = $params->get( 'Filer_mode', default => 'F' ); my $TEST_WAIT_TIME = $params->get( 'TEST_WAIT_TIME', default => '3' ); my $GROUP_NO = $params->get( 'GROUP_NO', default => undef ); my $DRIVE_TYPE = $params->get( 'DRIVE_TYPE', default => '' ); my $ERT_VOL = $params->get( "ERT_VOL", default => '1' ); my $CMPRSN = $params->get( 'CMPRSN', default => '0' ); my $PRE_DETAILS; my $POST_DETAILS; my @pre_disk_count; my @post_disk_count; my $pre_post_recon_copy; my %Non_Medium_Model; logcomment("Kernel $Kernel"); logcomment("Id $RUNID"); my @run_id = split( '/', $RUNID ); my $parse_id = $run_id[-1]; my @Filers; if ( $FILER =~ /\,/ ) { @Filers = split( /\,/, $FILER ); } else { push( @Filers, $FILER ); } #if ( $Kernel =~ /FS|LB|HP|Harpoon/i ) { require NACL::C::StorageDiskPartition; require NACL::CS::StorageDiskPartition; #} my $AGGR_CNT = {}; our $SAS_ADMIN_DEV_PRE; our $GET_PHY_STATE; our $PHYDUMP; our $SHELFLOG_DETECTOR = {}; our $EMS_DETECTOR = {}; our $STO_DISK_SHOW = {}; our $AGGR_CREATE_CNTR; our $pre_storage_show_drive = {}; our $post_storage_show_drive = {}; my $SCSI_DISK_ERRORS = {}; my $STSB_FOR_EACH_DISKS_PRE; # Import exceptions # use NACL::APISet::Exceptions::ResponseException qw(:try); use NACL::APISet::Exceptions::CommandFailedException qw (:try); use NACL::APISet::Exceptions::MissingRequiredParamException qw(:try); use NACL::APISet::Exceptions::InvalidParamValueException qw(:try); use NACL::APISet::Exceptions::MethodNotFoundException qw(:try); use NACL::Exceptions::NoElementsFound qw(:try); use NATE::BaseException qw(:try); use NACL::Transit::Exceptions::Timeout qw(:try); use NACL::Transit::Exceptions::RetriesExceeded qw(:try); use NACL::Transit::Exceptions::TransitException qw(:try); use NACL::APISet::Exceptions::TimeoutException qw(:try); use NACL::Exceptions::EventCheckFailure qw(:try); #use NATE::Result::Fatal qw(:try); # use Params::Validate qw(validate OBJECT SCALAR HASHREF ARRAYREF); use Tharn qw( host logcomment ); BEGIN { Params::Validate::validation_options( on_fail => sub { my @msgs = @_; chomp(@msgs); Carp::confess( Tharn::script_result(@msgs) ); } ); } require Exporter; use vars ( '@ISA', '@EXPORT' ); @ISA = ('Exporter'); @EXPORT = qw( disk_assign_partition difference disk_list_data run_disk_qual_t12 disk_show_drive_maint copy_files_to_client_from_filer spare_count_cmode sysconfig_v_data sysconfig_r_data storage_show_data fail_parity_drive fail_data_drive hammer_start hammer_status boot_filer_in_req_state remove_partition enable_ssh aggregate_volume_delete disk_qual_abort get_disk_information get_max_timeout remv_assign_ownership_maint remv_assign_ownership_cli storage_show_disk_a_data disk_remv_assign_ownership disk_show_n zero_spares check_mode_nodes disk_ddr_label_print boot_it_good_Maint compare_disk_qual_t12 delete_mini_disk create_mini_disk compact_flash list_of_disk vserver_delete check_non_root_volumes setup_cmode_filers wipe_config_filers disk_qual_stop_file_system create_join_cluster cm_disk_firmware update_disk_to_lower_firmware copy_files_to_filer_from_client compare_disk_lists compare_fcadmin_link_stats compare_fcadmin_fcal_stats compare_sasadmin_dev_stats check_ert_config compare_sasadmin_expander_map compare_storage_show trim node_new_obj twenty_four_bar_seven clean_config get_max_disk_size comp_disk_qual_t12 pnate_versions_display destroy_root_volume check_multiple_filer_names version_test display_version get_disks_list delete_aggregates_with_no_volumes intersection max_drives_count eye_catcher check_for_drive_ownership change_diag_more_than_6 filer_disk_create check_disk_owner array_diff diag_password_change_cmode commom_drives boot_in_twenty_four_seven_cmode time_taken_for_frm_dwnld convert_to_date convertTime HA_config create_flex_vol create_aggr_volume status_return send_message disk_show_v compare_scsi_disk copy_FW_files_to_filer_directory copy_files_to_filer unique compare_sysconfig compare_fcadmins scrub_stop scsi_disk_errors execute_pre_test execute_post_test sasadmin_expander_map_cmode sasadmin_dev_stats_cmode handle_run_local_error enable_firmware_console_message sasadmin_inject_sub display_node_details fcadmin_inject_sub fcadmin_link_stats fcadmin_device_map fcadmin_fcal_stats disable_debug_msg create_spares check_aggr_vol_offline unfail_disk_zero_spares disable_fg_bg_firmware_hammer get_config_status storage_shw_initiators WaitReconstruct WaitSickDiskcopy check_recons_sickdisk check_path_ha get_filer_check get_phy_state handle_prompts report_failed_drives print_test_variables scsi_inquiry_cmode giveback_takeover sasadmin_expander_cli_phydump sasadmin_expander_cli compare_sasadmin_expander_cli_phydump compare_phy_state read_shelflog read_ems_logs start_shelflog_detector end_shelflog_detector start_ems_detector end_ems_detector drive_names_minus_adapter compare_WWN set_filer_time get_valid_drives_for_firm compare_scsi_disk_errors fail_if_diff_drive_foramt get_system_logs del_system_logs nodename_interchange_checkup compare_stsb_get_status_disk_values STSB_Get_Status_Results scsi_logsense_pages storage_disk_show_usable_size get_required_spares_size_less_than_2TB storage_show_drive compare_storage_show_drive disk_type_maint readable_disk_size disk_qual_Status run_dq_perfm_1_8_Cmode run_dq_perfm_9_Cmode run_dq_perfm_10_12_Cmode run_dq_perfm_13_Cmode run_dq_perfm_14_Cmode run_dq_perfm_15_Cmode run_dq_perfm_16_Cmode run_dq_perfm_17_Cmode run_dq_perfm_18_Cmode run_dq_perfm_19_Cmode run_dq_perfm_20_Cmode run_dq_perfm_21_Cmode disk_qual_drive_assign_maint pre_condition_ssd_drive seq_pre_condition_ssd_drive rand_pre_condition_ssd_drive stsb_event_crash_log diskshow_filer check_filer_connection check_existing_disk_firmware setup_okm check_encry_okm_lock_state check_valid_platform create_aggr_vol _print_array run_default_dsk_ql_scpt shuffle_array push_data_lake shelf_id_trafford get_lif_from_config_file check_disk_firmware_revision_number get_sk_trace_logs client_io_basic_checks set_client_io_port_mtu_9k assign_p1_p2_p3_drvs ); ################################################################################## # Assign P1 P2 and P3 drives after re-initilization, # Tahiti and Apollo will have unassigned partition drives after wipr config, ################################################################################## sub assign_p1_p2_p3_drvs { my (%opts) = validate( @_, { Nodes => { type => ARRAYREF }, handle => { type => SCALAR, optional => 1, default => 'NVMe' }, } ); my @Nodes = @{ $opts{Nodes} }; my $handle = $opts{handle}; my $assign = 0; my ( $dsk_shw_n_out, $API_obj_cli ); my ( @P1_DRV, @P2_DRV, @P3_DRV ); logcomment("check for any un-assigned drives"); foreach my $Node (@Nodes) { $Node->refresh_command_interface(); my $FILER_C = $Node->name(); my $Transit_obj = NACL::Transit->new( name => $FILER_C ); logcomment("Get state of filer :$FILER_C"); my $FILER_O_STATE = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 ); logcomment("FILER- $FILER_C - Is in $FILER_O_STATE state"); if ( $FILER_O_STATE =~ /CLI|UP|DBLADECLI/ ) { $API_obj_cli = $Node->get_7m_or_nodescope_apiset( connid => 'console' ); my $prompts_answers = [ ".*Do you want to continue.*" => 'y' ]; $API_obj_cli->execute_raw_command( 'command' => "set test", 'connectrec-match_table' => $prompts_answers ); logcomment("$FILER_C : Check any un-owned drives"); $dsk_shw_n_out = $API_obj_cli->execute_raw_command( 'command' => "run local disk show -n" ); if ( $dsk_shw_n_out =~ /Not Owned |Unowned / ) { logcomment("$FILER_C: Un-owned drives exists, assign drives"); $assign = 1; } else { logcomment("$FILER_C : No unassigned drives present, Proceed with next steps"); } } else { logcomment("FILER : $FILER_C is not in CLI or File system"); } } if ( $assign == 1 ) { foreach my $line ( split /\n/, $dsk_shw_n_out ) { if ( $line =~ /(\S+\.\S+)|(\S+\.\S+\.\S+)/ ) { my $drv = $1; if ( $drv =~ /P1$/ ) { push( @P1_DRV, $drv ); } elsif ( $drv =~ /P2$/ ) { push( @P2_DRV, $drv ); } elsif ( $drv =~ /P3$/ ) { push( @P3_DRV, $drv ); } } } #end of foreach logcomment("Drives un-assigned"); logcomment("@P1_DRV") if (@P1_DRV); logcomment("@P2_DRV") if (@P2_DRV); logcomment("@P3_DRV") if (@P3_DRV); logcomment("Get system ID of both filers"); my ( $NODE_A_NAME, $NODE_B_NAME, $NODEA_OBJ, $NODEB_OBJ, $NODE_A_API, $NODE_B_API ); $NODEA_OBJ = $Nodes[0]; $NODE_A_API = $NODEA_OBJ->get_7m_or_nodescope_apiset( connid => 'console' ); $NODE_A_NAME = $NODEA_OBJ->name(); $NODEB_OBJ = $Nodes[1]; $NODE_B_API = $NODEB_OBJ->get_7m_or_nodescope_apiset( connid => 'console' ); $NODE_B_NAME = $NODEB_OBJ->name(); logcomment("NODE A : $NODE_A_NAME"); logcomment("NODE B : $NODE_B_NAME"); logcomment("Partition P1 Drives : @P1_DRV"); logcomment("Partition P2 Drives : @P2_DRV"); logcomment("Partition P3 Drives : @P3_DRV") if (@P3_DRV); logcomment("Get System ID from both nodes "); my $sys_out_A = $NODE_A_API->execute_raw_command( 'command' => "run local sysconfig -v" ); my ( $NODE_A_SYSID, $NODE_B_SYSID ); foreach my $line ( split /\n/, $sys_out_A ) { if ( $line =~ /System ID/ ) { ($NODE_A_SYSID) = $line =~ /System\s+ID:\s+(\S+)\s+\($NODE_A_NAME\).*/; } } my $sys_out_B = $NODE_B_API->execute_raw_command( 'command' => "run local sysconfig -v" ); foreach my $line ( split /\n/, $sys_out_B ) { if ( $line =~ /System ID/ ) { ($NODE_B_SYSID) = $line =~ /System\s+ID:\s+(\S+)\s+\($NODE_B_NAME\).*/; } } logcomment("NODE A : $NODE_A_NAME - SysID : $NODE_A_SYSID"); logcomment("NODE B : $NODE_B_NAME - SysID : $NODE_B_SYSID"); my $CMD_A = "run local disk assign @P1_DRV -s $NODE_A_SYSID -o $NODE_A_NAME -f "; my $CMD_B = "run local disk assign @P2_DRV -s $NODE_B_SYSID -o $NODE_B_NAME -f "; logcomment("Assigning drives "); $NODE_A_API->execute_raw_command( 'command' => "$CMD_A" ); $NODE_A_API->execute_raw_command( 'command' => "\013" ); $NODE_A_API->execute_raw_command( 'command' => "$CMD_B" ); logcomment("Assigned drive to both nodes, re-check any un-assigned drive"); sleep 60; } foreach my $Node (@Nodes) { my $FILER_C = $Node->name(); my $API_obj_cli = $Node->get_7m_or_nodescope_apiset( connid => 'console' ); my $out = $API_obj_cli->execute_raw_command( 'command' => "run local disk show -n" ); if ( $out =~ /No unassigned disks/ ) { logcomment("All drives are assigned"); } else { logcomment("Some drives are not assigned"); } } } ######################################################## ##Setting Client IO port to 9000 Burt# ######################################################## sub set_client_io_port_mtu_9k { my (%opts) = validate( @_, { handle => { type => SCALAR, optional => 1, default => 0 }, Node_Name => { type => SCALAR }, Node_API => { type => OBJECT }, Test => { type => OBJECT }, port1 => { type => SCALAR }, port2 => { type => SCALAR }, } ); my $handle = $opts{handle}; my $Test = $opts{Test}; my $flag = 0; my $port_1 = $opts{port1}; my $port_2 = $opts{port2}; my $Api_Set_Obj = $opts{Node_API}; my $FILER_C = $opts{Node_Name}; eye_catcher( Test => $Test, string => "Get Ports user selected for Client Traffic " ); logcomment("User selected port for client IO : $port_1 and $port_2"); logcomment("Check port on filer $FILER_C "); $Api_Set_Obj->set_timeout( "connectrec-timeout" => 1200000 ); my $prompts_answers = [ ".*Do you want to continue.*" => 'y' ]; $Api_Set_Obj->execute_raw_command( 'command' => "set test", 'connectrec-match_table' => $prompts_answers ); $Api_Set_Obj->execute_raw_command( 'command' => "set -rows 0" ); my $output = $Api_Set_Obj->execute_raw_command( 'command' => "net port show -node $FILER_C" ); logcomment("$FILER_C : Display all Available domains"); $Api_Set_Obj->execute_raw_command( 'command' => "network port broadcast-domain show" ); sleep 2; my $cdomain_name = "ClientData_" . $FILER_C; logcomment("$FILER_C : Create ClientData Domain : $cdomain_name "); $Api_Set_Obj->execute_raw_command( 'command' => "network port broadcast-domain create -broadcast-domain $cdomain_name -mtu 9000" ); logcomment("$FILER_C : $cdomain_name Domain Created"); $Api_Set_Obj->execute_raw_command( 'command' => "network port broadcast-domain show" ); sleep 2; my $temp_port1 = $FILER_C . ":" . $port_1; my $temp_port2 = $FILER_C . ":" . $port_2; logcomment("Check for ports $temp_port1 and $temp_port2"); logcomment("Remove ports from Default Domain"); $Api_Set_Obj->execute_raw_command( 'command' => "network port broadcast-domain remove-ports -broadcast-domain Default -ports $temp_port1 $temp_port2" ); logcomment("Removed ports $temp_port1 and $temp_port2 from Default Domain"); sleep 2; logcomment("Add Clients ports to ClientData Domain"); $Api_Set_Obj->execute_raw_command( 'command' => "network port broadcast-domain add-ports -broadcast-domain $cdomain_name -ports $temp_port1 $temp_port2" ); sleep 1; $Api_Set_Obj->execute_raw_command( 'command' => "network port broadcast-domain show" ); logcomment("$FILER_C : Added ports $port_1 and $port_2 to $cdomain_name Domain"); logcomment("$FILER_C : Check port "); $Api_Set_Obj->execute_raw_command( 'command' => "net port show" ); sleep 2; logcomment("Completed Client Port and Domain Modifications"); return $flag; } ######################################################## ## Supported only for CLIENTIO test #Burt 1174066 ####################################################### sub client_io_basic_checks { my (%opts) = validate( @_, { handle => { type => SCALAR, optional => 1, default => 0 }, Node => { type => OBJECT, optional => 1, default => undef }, Client_API => { type => OBJECT, optional => 1, default => undef }, Node_API => { type => OBJECT }, Client_Name => { type => SCALAR }, Test => { type => OBJECT }, port1 => { type => SCALAR, optional => 1, default => 0 }, port2 => { type => SCALAR, optional => 1, default => 0 }, } ); my $handle = $opts{handle}; my $Client_API = $opts{Client_API}; my $Node_API = $opts{Node_API}; my $Node = $opts{Node}; my $client_name = $opts{Client_Name}; my $Test = $opts{Test}; my $flag = 0; my $port_1 = $opts{port1}; my $port_2 = $opts{port2}; my @temp_nodes = NACL::C::Node->find(); my $Api_Set_Obj; eye_catcher( Test => $Test, string => "Checking basic client requirements, before starting client IO test" ); logcomment("Checking basic client requirements, before starting client IO test"); logcomment("Mandatory requirements will be checked"); ## Check main : check for port status foreach my $Node (@temp_nodes) { my $FILER_C = $Node->name(); logcomment("Check port on filer $FILER_C "); $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset( connid => "console" ); $Api_Set_Obj->set_timeout( "connectrec-timeout" => 1200000 ); my $prompts_answers = [ ".*Do you want to continue.*" => 'y' ]; $Api_Set_Obj->execute_raw_command( 'command' => "set test", 'connectrec-match_table' => $prompts_answers ); $Api_Set_Obj->execute_raw_command( 'command' => "set -rows 0" ); my $output = $Api_Set_Obj->execute_raw_command( 'command' => "net port show -node $FILER_C" ); foreach my $line ( split /\n/, $output ) { next if ( $line =~ /Domain|Link|MTU|^-/ ); if ( $line =~ /(\S+)\s+\S+\s+\S+\s+(\S+)\s+(\S+)\s+.*/ ) { my $port = $1; my $status = $2; my $mtu = $3; if ( $port =~ /$port_1|$port_2/ ) { logcomment("$FILER_C : Port $port MTU is $mtu and Status is $status"); if ( $status =~ /down/ ) { logcomment("Selected port for Client IO test on Filer $FILER_C is down, Check Link on port $port"); logcomment("**NORUN** : Selected port for Client IO test on Filer $FILER_C is down, Check Link on port $port"); $flag = 5; } } } } if ( $flag == 5 ) { return $flag; } else { } } eye_catcher( Test => $Test, string => "CHECK port $port_1 and $port_2 status" ); my $output = $Api_Set_Obj->execute_command( 'command' => "sysconfig -v" ); eye_catcher( Test => $Test, string => "CHECK CLIENT HOST FILE" ); logcomment("Client selected : $client_name"); ## Check 1 : Check for client host file my $Home = $ENV{HOME}; my $ho_path = $Home . "/NDATE/FILER_INFO/"; logcomment("Check client host file under : $ho_path"); opendir( DIR_LOG31, $ho_path ); my @files_DIR_LOG31 = readdir(DIR_LOG31); foreach my $file (@files_DIR_LOG31) { if ( $file =~ /$client_name/ ) { logcomment("Client host file FOUND - $file"); $flag = 0; last; } else { $flag = 1; } } if ( $flag == 1 ) { logcomment("**NORUN** : Client host file cannot be found, Create client host file and restart test"); return $flag; } ## Check 2 : Check for Client Accessiblity eye_catcher( Test => $Test, string => "Check client accessibility : Client $client_name" ); logcomment("Check client accessibility : Client is : $client_name"); my $Api_Set_Client; try { $Api_Set_Client = NACL::APISet->new( name => $client_name, category => 'Host', interface => 'CLI', set => 'Linux', ); logcomment("Client API created, Login successful"); my $out = $Api_Set_Client->execute_raw_command( command => "hostname" ); logcomment("Client host name : $out"); } catch NATE::BaseException with { $flag = 2; logcomment("Could NOT login to client $client_name , please check the connections"); return $flag; }; if ( $flag == 2 ) { logcomment("**NORUN** : Connection failed : Could NOT login to client $client_name , please check the connections"); return $flag; } logcomment("Check Client $client_name Config "); my $out = $Api_Set_Client->execute_raw_command( command => "ifconfig" ); ## Check 3 : Check for sio and iozone if NVMe eye_catcher( Test => $Test, string => "Check for sio and iozone tool on client" ) if ( $RUNID =~ /NVMe/ ); eye_catcher( Test => $Test, string => "Check for sio tool on client" ) if ( $RUNID !~ /NVMe/ ); logcomment("Check for sio tool on client $client_name"); my $out = $Api_Set_Client->execute_raw_command( command => "whereis sio" ); if ( $out =~ /sio\:\s(\S+)/ ) { my $s_path = $1; if ( $s_path ne '' ) { logcomment("SIO Tool present in : $s_path"); } else { logcomment("**NORUN** :SIO tool cannot be found on client, Please install SIO tool under /usr/bin/"); $flag = 3; return $flag; } } ## Check 4 - IOZONE tool. logcomment("Check for NVMe "); logcomment("DEBUG : Run ID is : $RUNID"); if ( $RUNID =~ /NVMe/ ) { logcomment("NVMe Script is selected, NVMe uses iozone for data set creation, check for iozone tool on client"); my $out = $Api_Set_Client->execute_raw_command( command => "./iozone" ); if ( $out =~ /No such file or directory/ ) { logcomment("**NORUN** : IOZONE tool CANNOT be found on client root home directory, Install iozone and re-start test"); $flag = 4; return $flag; } else { logcomment("IOZONE tool found"); logcomment("DEBUG : $out"); } } return $flag; } ####################################################### ## Author : arunak #Burt : 1164004 ####################################################### sub get_sk_trace_logs { my (%opts) = validate( @_, { Node => { type => OBJECT }, Destination => { type => SCALAR }, runtime => { type => SCALAR }, } ); my $Node = $opts{Node}; my $destination = $opts{Destination}; my $FILER_C = $Node->name(); my $runtime = $opts{runtime}; my $sk_trace_path = "/mroot/etc/log/mlog/"; my $sk_trace_dir = "$FILER_C" . "_" . "sk_trace_logs"; my $main_dir = "SK_TRACE_LOGS"; my $client = hostname(); my @clienta = split( /\./, $client ); my $CLIENT = $clienta[0]; my $Client = NACL::C::Client->new( client => $CLIENT ); logcomment("Client : $Client - $CLIENT "); my ($actual_log_dir) = $destination =~ /(\S+)\/HDD/; my $num; if ( $parse_id =~ /(\d+)\_\S+/ ) { $num = $1; } my $log_dir_2_copy = "$actual_log_dir\/SK_TRACE_LOGS\/" . $FILER_C . "_T_" . $num . "/"; system("sudo mkdir -p $log_dir_2_copy"); logcomment("$log_dir_2_copy Created"); system("sudo chmod 777 $log_dir_2_copy"); logcomment("############### $FILER_C : SK TRACE LOG CAPTURE START ###############"); logcomment("Copy sk_trace logs from filer :$FILER_C "); logcomment("$FILER_C : sk_trace runtime : $runtime seconds"); logcomment("$FILER_C : sk_trace log path : $sk_trace_path"); logcomment("$FILER_C : sk_trace log destination : $log_dir_2_copy"); #my $Client = NACL::C::Client->find(); my $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset( connid => "console" ); $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 ); my $prompts_answers = [ ".*Do you want to continue.*" => 'y' ]; logcomment("$FILER_C : Set privilage to diag"); $Api_Set_Obj->execute_raw_command( 'command' => "set -privilege diag", 'connectrec-match_table' => $prompts_answers ); logcomment("$FILER_C : Start sk_trace and wait for $runtime seconds"); $Api_Set_Obj->execute_raw_command( 'command' => "systemshell -node $FILER_C -command sudo sysctl sysvar.sktrace.DISK_enable=-1" ); logcomment("Wait for $runtime seconds"); sleep($runtime); $Api_Set_Obj->execute_raw_command( 'command' => "\013" ); logcomment("$FILER_C : $runtime seconds completed , Stop sk_trace and copy logs to $log_dir_2_copy"); $Api_Set_Obj->execute_raw_command( 'command' => "systemshell -node $FILER_C -command sudo sysctl sysvar.sktrace.DISK_enable=0" ); logcomment("$FILER_C : sk_trace stopped, copy logs"); my $scp; my $flag = 0; try { $scp = NACL::MTask::SCP->new( target_command_interface => $Node, source_command_interface => $Client, ); } catch NATE::BaseException with { $flag = 1; logcomment("Could NOT create SCP object, please check the connections"); }; if ($flag) { return 1; } logcomment("$FILER_C : SCP object created"); my $Filer_apiset = $Node->apiset( category => 'Node', interface => 'CLI', set => "Systemshell" ); my $File_on_filer = $Filer_apiset->execute_raw_command( command => "ls $sk_trace_path" ); chomp($File_on_filer); logcomment("File on filer >$File_on_filer<"); my $files = [$File_on_filer]; my @temp_array = @$files; @temp_array = split( "\t+|\n", $temp_array[0] ); foreach my $file (@temp_array) { chomp($file); if ( $file =~ /sktrace\.log/ ) { $file = "/mroot/etc/log/mlog/" . "$file"; $Filer_apiset->execute_raw_command( command => "chmod 777 $file" ); logcomment("Copy sk_trace $file logs to $log_dir_2_copy directory"); try { $scp->copy_from_target_to_source( 'files_to_copy' => [$file], set_directory_on_source => "$log_dir_2_copy", ); } catch NATE::BaseException with { logcomment("$FILER_C : Could NOT copy file :$file"); }; } } logcomment("$FILER_C : sk_trace logs copied"); logcomment("############### $FILER_C : SK TRACE LOG CAPTURE END ###############"); } ####################################################### ## Author : arjun.lavu@netapp.com ###################################################### sub version_test { my (%opts) = validate( @_, { node_present => { type => ARRAYREF }, tc_name => { type => SCALAR }, } ); my @Nodes = @{ $opts{node_present} }; my $TC_name = $opts{tc_name}; my $node_version; logcomment("Number of filers @Filers"); pnate_versions_display(); print_test_variables(); if ( $TC_name !~ /NVMe|NVME|SCM/ ) { if ( ( $GROUP_NO == 10 ) || ( $GROUP_NO == 3 ) || ( $GROUP_NO == 4 ) || ( $GROUP_NO == 5 ) || ( $GROUP_NO == 6 ) || ( $GROUP_NO =~ /NADQ02_ERT_Fsys/ ) || ( $GROUP_NO =~ /NADQ02_SSD_Durability/ ) || ( $GROUP_NO == 8 ) || ( $GROUP_NO == 9 ) || ( $GROUP_NO =~ /NADQ02_Long_Term_Data_Handling/ ) || ( $GROUP_NO =~ /STRESS_TESTING/ ) ) { logcomment("Group selected: $GROUP_NO , Changing state to CLI Mode"); my @subtests; foreach my $node (@Nodes) { my $filer_name = $node->name(); push( @subtests, subtest( \&boot_filer_in_req_state, -runid, "boot_filer_in_req_state_" . "$filer_name", -bg, "--", filer_name => $filer_name, change_state_to => 'CLI', ) ); } Subtest::wait_finish( subtest => [@subtests] ); } else { logcomment("Group selected: $GROUP_NO ,Changing state to MAINT Mode"); my @subtests; foreach my $node (@Nodes) { my $filer_name = $node->name(); push( @subtests, subtest( \&boot_filer_in_req_state, -runid, "boot_filer_in_req_state_" . "$filer_name", -bg, "--", filer_name => $filer_name, change_state_to => 'MAINT', ) ); } Subtest::wait_finish( subtest => [@subtests] ); } foreach my $Node (@Nodes) { my $Mode = $Node->mode(); my $FILER_C = $Node->name(); my $Host = host($FILER_C); display_node_details( Node => $Node ); my $Transit_obj = NACL::Transit->new( name => $FILER_C ); my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 ); logcomment("DEBUG:Node $FILER_C is in the Filer state $filer_state"); #BURT 862716 nmamatha --> logcomments replaced to DEBUG. if ( $filer_state =~ /PASS|USER/i ) { $Transit_obj->set( 'change_state_timeout' => 7200 ); $Transit_obj->change_state( to => "CLI" ); } if ( $filer_state =~ /UP|CLI/i ) { diag_password_change_cmode( Node_ref => [$Node] ); my $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset(); $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 ); try { set_filer_time( Node => $Node ); my $prompts_answers = [ ".*Do you want to continue.*" => 'y' ]; $Api_Set_Obj->execute_raw_command( 'command' => "set test", 'connectrec-match_table' => $prompts_answers ); $Api_Set_Obj->execute_raw_command( 'command' => "set -rows 0" ); $node_version = $Api_Set_Obj->execute_raw_command( 'command' => 'run local version' ); $Api_Set_Obj->execute_raw_command( 'command' => 'event config modify -suppression off -console on' ); $Api_Set_Obj->execute_raw_command( 'command' => 'event config modify -suppression off -consoleloglevel DEBUG' ); } catch NATE::BaseException with { logcomment("$FILER_C : Filer is in CMODE, SSH connection is NOT proper!!!"); }; } elsif ( $filer_state =~ /MAINT/i ) { my $API_Object = NACL::APISet->new( hostobj => $Host, category => "Node", interface => "CLI", set => "Maintenance" ); $API_Object->set_timeout( "connectrec-timeout" => 7200 ); $node_version = $API_Object->execute_raw_command( command => "version" ); } logcomment("Node Version : $node_version"); } filer_disk_create(); } else { logcomment("DEBUG : NVMe Setup Calls"); foreach my $Node (@Nodes) { my $Mode = $Node->mode(); my $FILER_C = $Node->name(); my $Host = host($FILER_C); display_node_details( Node => $Node ); my $Transit_obj = NACL::Transit->new( name => $FILER_C ); my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 ); logcomment("DEBUG:Node $FILER_C is in the Filer state $filer_state"); #BURT 862716 nmamatha --> logcomments replaced to DEBUG. if ( $filer_state =~ /PASS|USER/i ) { $Transit_obj->set( 'change_state_timeout' => 7200 ); $Transit_obj->change_state( to => "CLI" ); } if ( $filer_state =~ /UP|CLI/i ) { diag_password_change_cmode( Node_ref => [$Node] ); my $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset(); $Api_Set_Obj->set_timeout( "connectrec-timeout" => 1200 ); try { set_filer_time( Node => $Node ); my $prompts_answers = [ ".*Do you want to continue.*" => 'y' ]; $Api_Set_Obj->execute_raw_command( 'command' => "set test", 'connectrec-match_table' => $prompts_answers ); $Api_Set_Obj->execute_raw_command( 'command' => "set -rows 0" ); $node_version = $Api_Set_Obj->execute_raw_command( 'command' => 'system timeout modify 0' ); $Api_Set_Obj->execute_raw_command( 'command' => 'run local dbg to off' ); $Api_Set_Obj->execute_raw_command( 'command' => 'event config modify -suppression on -console on -console-log-level DEBUG' ); #disable debug message -Dev build } catch NATE::BaseException with { logcomment("$FILER_C : Filer is in CLI"); }; } else { logcomment("Filer :$FILER_C is NOT in CLI, to set rows and system timeout, Proceeding with next steps"); } } } } sub display_node_details { my (%opts) = validate( @_, { Node => { type => OBJECT }, } ); my $Node = $opts{Node}; my $FILER_C = $Node->name(); my $Host = host($FILER_C); logcomment("DEBUG:Printing the details of the filer $FILER_C"); my ( $N_M_P, $N_M_I, $N_M_M, $N_M_G, $C_P, $C_I, $C_M, $C_G, $C_M_P, $C_M_I, $C_M_G, $C_M_M, $Cluster_Name ) = ( $Host->{MGMT_PORT}, $Host->{MGMT_IP}, $Host->{MGMT_MASK}, $Host->{MGMT_GATEWAY}, $Host->{CLUSTER_PORT1}, $Host->{CLUSTER_IP1}, $Host->{CLUSTER_MASK1}, $Host->{CLUSTER_GATEWAY1}, $Host->{CLUSTER_MGMT_PORT}, $Host->{CLUSTER_MGMT_IP}, $Host->{CLUSTER_MGMT_GATEWAY}, $Host->{CLUSTER_MGMT_MASK}, $Host->{CLUSTER_NAME} ); logcomment( "Node Management Port = $N_M_P \nNode Management IP = $N_M_I \nNode Management mask = $N_M_M \nNode Management Gateway = $N_M_G \n\nCluster Port = $C_P \nCluster IP = $C_I \nCluster Mask = $C_M \nCluster Gateway = $C_G \n\nCluster Mangement Port = $C_M_P \nCluster Mangement IP = $C_M_I \nCluster Mangement Gateway = $C_M_G \nCluster Mangement Mask = $C_M_M \n Cluster Name = $Cluster_Name" ); } sub hammer_start { my (%opts) = validate( @_, { Node => { type => OBJECT }, file_name => { type => SCALAR }, file_size => { type => SCALAR }, root_vol => { type => SCALAR, optional => 1, default => 'no' }, Test => { type => OBJECT }, } ); my $Node = $opts{Node}; my $file_name = $opts{file_name}; my $file_size = $opts{file_size}; my $root_vol = $opts{root_vol}; my $Test = $opts{Test}; my $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset( connid => "console" ); $Api_Set_Obj->set_timeout( "connectrec-timeout" => 18000 ); try { my $response = $Api_Set_Obj->hammer( 'force' => "1", 'num-runs' => "-1", 'file-name' => $file_name, 'num-blocks' => $file_size ); my $ret = $Api_Set_Obj->hammer_status(); if ( !$ret->get_raw_output() ) { $Test->nlog("Hammer is not running checking again"); my $ret1 = $Api_Set_Obj->hammer_status(); if ( !$ret1->get_raw_output() ) { $Test->nlog("Hammer is not running"); return 1; } } else { $Test->nlog( "Status of HAMMER is " . $ret->get_raw_output() ); return 0; } } catch NACL::APISet::Exceptions::ResponseException with { my $exception_object = shift; my $resp = $exception_object->get_response_object(); $Test->nlog( "Caught a " . ref($exception_object) . "!" ); $Test->nlog( "Error is: " . $exception_object->text() ); $Test->nlog( "Raw output was:\n" . $resp->get_raw_output() ); $Test->nlog("Hammer with $file_size and file $file_name didnt start properly"); return 1; }; } ####################################################################################################### ##@name :: enable_ssh ## @auther - arunak@netapp.com ## @This subrotine enable ssh and rsh based on modes of the filers. ## @The following named arguments are accepted, ##(Required) : Filer Node Object to use. ##(Required) : Test Object. ##(Required) : Mode of the Filer/Node. ####################################################################################################### sub enable_ssh { my (%opts) = validate( @_, { Node => { type => OBJECT }, Test => { type => OBJECT }, Mode => { type => SCALAR }, } ); my $Node = $opts{Node}; my $Test = $opts{Test}; my $Mode = $opts{Mode}; my $flag = 0; my $Vserver; $Node->refresh_command_interface(); my $FILER_C = $Node->name(); my $Home = $ENV{HOME}; #Get ssh values logcomment("DEBUG:$FILER_C : Checking host key"); `sudo rm -rf $Home/.ssh/known_hosts`; $Test->nlog("$FILER_C : Getting ssh parameters from host file"); my $ssh_user = $Node->{hostrec}->{conn}->{ssh}->{username}; my $ssh_pass = $Node->{hostrec}->{conn}->{ssh}->{password}; my $ssh_conn = $Node->{hostrec}->{conn}->{ssh}->{connhost}; my $ssh_con_ty = $Node->{hostrec}->{conn}->{ssh}->{conntype}; $Test->nlog(" Captured ssh options for host file"); $Test->nlog("------------------ ssh params ---------------------"); $Test->nlog(" Connection-user : $ssh_user"); $Test->nlog(" Connection-type : $ssh_con_ty"); $Test->nlog(" Connection-host-IP : $ssh_conn"); $Test->nlog(" Connection-password : $ssh_pass"); $Test->nlog("---------------------------------------------------"); #Enable ssh if Mode is CMode if ( $Mode eq 'CMode' ) { logcomment("$FILER_C : Get vserver present on Node"); # Call vserver subroutine my $vserver_obj = NACL::STask::Vserver->find( command_interface => $Node, filter => { 'type' => "node" }, ); $Vserver = $vserver_obj->get_one_state_attribute('vserver'); logcomment("DEBUG:Vserever name - $Vserver"); logcomment("DEBUG:$FILER_C : Checking network interface of e0M for SSH connection"); my $Home = $ENV{HOME}; my $Address; my $interface; my $Netmask; $Home = trim($Home); my $host_file = "$Home/NDATE/FILER_INFO/$FILER_C"; my $filer_config = `cat $host_file`; foreach my $line ( split /\n/, $filer_config ) { if ( $line =~ /^\#/ ) { next; # skip overall result report starting with a '#'. } elsif ( $line =~ /^MGMT_IP\=(.*)/ ) { $Address = $1; } elsif ( $line =~ /^MGMT_MASK=(.*)/ ) { $Netmask = $1; } elsif ( $line =~ /^MGMT_PORT=(.*)/ ) { $interface = $1; } } my $Lif = "mgmt1"; # my $Address = $Node->{hostrec}->{net}->[2]->{address}; # my $interface = $Node->{hostrec}->{conn}->{MGMT_PORT}; $Test->nlog("Lif - $Lif"); $Test->nlog("Add - $Address"); $Test->nlog("Netmask - $Netmask"); $Test->nlog("Interface - $interface"); try { NACL::STask::NetworkInterface->create( command_interface => $Node, lif => $Lif, vserver => $Vserver, role => 'node-mgmt', 'home-node' => $FILER_C, 'home-port' => $interface, address => $Address, netmask => $Netmask, nacltask_if_exists => 'reuse', ); } catch NACL::APISet::Exceptions::NoMatchingEntriesException with { $Test->nlog("LIF is already configured"); } catch NACL::APISet::Exceptions::CommandFailedException with { $Test->nlog("LIF is already configured"); } catch NACL::APISet::Exceptions::MgwdCrashedException with { $Test->nlog("Management gateway restarted in between, Check for any coredump"); my $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset( connid => "console" ); my $prompts_answers = [ ".*continue.*" => 'y' ]; $Api_Set_Obj->execute_raw_command( 'command' => "set test", 'connectrec-match_table' => $prompts_answers ); #$Api_Set_Obj->execute_raw_command( 'command' => "run local priv set -q test", 'connectrec-match_table' => $prompts_answers ); my $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset( connid => "console" ); my $prompts_answers1 = [ ".*Do you want to continue.*" => 'y' ]; $Api_Set_Obj->execute_raw_command( command => "set test;set -rows 0;system node coredump show -node local -type application -corename mgwd.* -instance", 'connectrec-match_table' => $prompts_answers1 ); $Api_Set_Obj->execute_raw_command( command => "\013" ); $Test->nlog("Captured system node core dump for management gateway"); } catch NACL::APISet::Exceptions::TimeoutException with { logcomment("Management gateway restarted in between, Proceed with next steps"); }; logcomment("DEBUG:$FILER_C : Checking for SSH options"); logcomment("DEBUG:$FILER_C : Enabling security login, if exists re-using same "); try { my $obj = NACL::STask::SecurityLogin->create( command_interface => $Node, 'vserver' => $Vserver, 'username' => $ssh_user, 'authmethod' => "password", 'application' => "ssh", 'password' => $ssh_pass, 'role' => "admin", nacltask_if_exists => "reuse", ); } catch NACL::APISet::Exceptions::NoMatchingEntriesException with { logcomment("$FILER_C : Element NOT found, configure SSH manually"); } catch NACL::APISet::Exceptions::CommandFailedException with { logcomment("SSH configured "); } catch NACL::APISet::Exceptions::TimeoutException with { logcomment("Management gateway restarted in between, Proceed with next steps"); }; my $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset( connid => "console" ); $Api_Set_Obj->execute_raw_command( command => "\013" ); $Api_Set_Obj->execute_raw_command( command => "cd" ); $Api_Set_Obj->execute_raw_command( command => "\013" ); sleep 2; $Api_Set_Obj->execute_raw_command( command => "\013" ); } } ####################################################################################################### ##@name ::hammer_status ## @auther - arjun.lavu@netapp.com ## @my $hash = hammer_status(node=>$node,Test=>$Test); ## @This routine returns a either 1(Fail) or 0(Pass). ## @The following named arguments are accepted, ##(Required) : Filer Node Object to use. ##(Required) : Test Object. ####################################################################################################### sub hammer_status { my (%opts) = validate( @_, { Node => { type => OBJECT }, Test => { type => OBJECT, optional => 1, default => '' } } ); my $Node = $opts{Node}; my $Test = $opts{Test}; my $flag = 0; my $return = 0; my $API_obj = $Node->get_7m_or_nodescope_apiset( connid => 'console' ); $API_obj->set_timeout( "connectrec-timeout" => 43200 ); #added by sags Burt No:1168576 try { my $ret = $API_obj->hammer_status(); my @arr_hammer = @{ $ret->{'parsed_output'} }; if ( !@arr_hammer ) { logcomment("Hammer is NOT running"); $return = 1; } for my $ref (@arr_hammer) { for my $reff ( sort keys %$ref ) { my $file_name; if ( ( $reff == 'file_name' ) && ( $ref->{$reff} ) ) { $file_name = $ref->{$reff}; } if ( ( $reff == 'status' ) && ( $ref->{$reff} == 'Writing' ) ) { logcomment("Hammer is running for the file $file_name"); last; } } } } catch NACL::APISet::Exceptions::ResponseException with { my $exception_object = shift; my $resp = $exception_object->get_response_object(); logcomment( "Caught a " . ref($exception_object) . "!" ); logcomment( "Error is: " . $exception_object->text() ); logcomment( "Raw output was:\n" . $resp->get_raw_output() ); logcomment("Hammer status could NOT start properly"); $return = 1; }; return $return; } ##################################################################################################### ##@name :: boot_filer_in_req_state ##auther :: arunak@netapp.com ##Description : Boots the filer in required mode, used in pre_n_post_test_process in subtest ##Return : NULL ##Mandatory param : Filer name, Test object and State to change ##Supported Mode : CMODE ##################################################################################################### sub boot_filer_in_req_state { my (%opts) = validate( @_, { filer_name => { type => SCALAR }, Test => { type => OBJECT, optional => 1, default => '' }, change_state_to => { type => SCALAR }, } ); my $filer_name = $opts{filer_name}; my $Test = $opts{Test}; my $change_state_to = $opts{change_state_to}; logcomment("DEBUG:Checking State of $filer_name"); my $Transit_obj = NACL::Transit->new( name => $filer_name ); my $filer_state = $Transit_obj->get_state( 'timeout' => 360000, 'get_state_timeout' => 720000 ); if ( $filer_state ne $change_state_to ) { $Transit_obj->set( 'change_state_timeout' => 7200 ); $Transit_obj->change_state( to => "$change_state_to" ); logcomment("Filer state changed to $change_state_to : $filer_name"); } else { logcomment("Filer state is already in required state ($change_state_to) : $filer_name"); } } ##################################################################################################### ##@name ::copy_files_to_client_from_filer ##auther ::skaran ##DEscripton : Copies files from filer to client using scp ##Return : NULL ##Mandatory : Nodes Present, Filer Path , Start toend, log path ##Supported Mode : CMODE ##################################################################################################### sub copy_files_to_client_from_filer { my (%opts) = validate( @_, { node_present => { type => OBJECT }, filer_path => { type => SCALAR }, start_or_end => { type => SCALAR, optional => 1, default => undef }, #BURT961618 - abalaji log_path => { type => SCALAR }, } ); my $node = $opts{node_present}; my $filer_path = $opts{filer_path}; my $when = $opts{start_or_end}; my $LOGDIR = $opts{log_path}; my $Filer_apiset = $node->apiset( category => 'Node', interface => 'CLI', set => "Systemshell" ); my $Username; my $Password; my $Client = NACL::C::Client->find(); my $conn = $Client->hostrec()->conn(); my $Client_apiset = $Client->apiset(); while ( my ( $user, $pass ) = each(%$conn) ) { if ( defined( $pass->{username} ) && defined( $pass->{password} ) ) { $Username = $pass->{username}; $Password = $pass->{password}; last; } } ## end while my $scp; my $flag = 0; try { $scp = NACL::MTask::SCP->new( target_command_interface => $node, source_command_interface => $Client, ); } catch NATE::BaseException with { $flag = 1; logcomment("Could NOT create SCP object, please check the connections"); }; if ($flag) { return; } my $File_on_filer = $Filer_apiset->execute_raw_command( command => "ls $filer_path" ); chomp($File_on_filer); logcomment("File on filer >$File_on_filer<"); my $files = [$File_on_filer]; my @temp_array = @$files; @temp_array = split( "\t+|\n", $temp_array[0] ); foreach my $file (@temp_array) { chomp($file); logcomment("Copying $file to $LOGDIR"); try { $scp->copy_from_target_to_source( 'files_to_copy' => [$file], set_directory_on_source => "$LOGDIR", ); } catch NATE::BaseException with { logcomment("Could NOT copy file :$file"); }; } } #end of subroutine copy_files_to_client_from_filer ##################################################################################################### ##@name :: check_non_root_volumes ##auther ::Arjun Lavu ##DEscripton : Returns the non-root volumes of the node which is passed ##Return : array, which contains all the non-root volumes or null if no non-root volumes found ##Mandatory : Node ##Supported Mode : CMODE ##################################################################################################### sub check_non_root_volumes { my (%opts) = validate( @_, { Node => { type => OBJECT }, } ); my $Node = $opts{Node}; my $Mode = $Node->mode(); my @aggregates; my $FILER_C = $Node->name(); my @non_root; my $filter = 'vsroot'; try { ##Checking for Non Rooot Volumes my @tot_vol = NACL::C::Volume->find( command_interface => $Node, filter => { node => $FILER_C, $filter => 'false' } ); foreach my $vol (@tot_vol) { push( @aggregates, $vol->get_one_state_attribute('aggregate') ); push( @non_root, $vol->volume() ); } logcomment("$FILER_C : Non Root volumes available are - @non_root"); } catch NACL::Exceptions::NoElementsFound with { logcomment("$FILER_C : NON ROOT VOLUME are NOT found"); }; return @non_root; } ##Author Arjun Lavu # Description - # Support - Returns Spare drives ########################################################################################################## sub spare_count_cmode { my (%opts) = validate( @_, { Node => { type => OBJECT }, run_local => { type => SCALAR, optional => 1, default => 'NO' }, waiting => { type => SCALAR, optional => 1, default => undef }, required_spare => { type => SCALAR, optional => 1, default => undef } } ); my $Node = $opts{Node}; my $filer = $Node->name(); my $runlocal = $opts{run_local}; my $required_spare = $opts{required_spare}; my $params = NATE::ParamSet->new( global => 1 ); my $Kernel = $params->get( 'KERNEL', default => 'FS' ); my @spare_disk_list; my $view_msg = 1; if ( $parse_id =~ /(304|305|306|400|402|407|502|504|505|506)/ ) { $opts{waiting} = "yes"; } while (1) { my $API_obj = $Node->get_7m_or_nodescope_apiset(); my $out = $API_obj->execute_command( 'command' => "aggr status -s" ); # my $zero_cnt;\ my ( @zeroing, @clear_spares ); if ( $out =~ /zeroing|not zeroed/i ) { # $zero_cnt=$out=~/zeroing|not zeroed/ig; my $n = 0; my @lines = split( /\n/, $out ); while ( $n <= $#lines ) { last if ( $lines[$n] =~ /^-----/ ); $n++; } $n++; foreach my $var ( @lines[ $n .. $#lines ] ) { $var =~ s/^\s+|\s+$//gi; if ( $var =~ /spare\s*(\S+).*(not zeroed|zeroing)/ ) { push( @zeroing, $1 ); } if ( $var !~ /zeroing|not zeroed/ ) { if ( $var =~ /spare\s*(\S+)/ ) { push( @clear_spares, $1 ); } } } if ( $out =~ /not zeroed/i ) { $API_obj->execute_command( 'command' => "disk zero spares" ); sleep 300; } my $dsks = _print_array( \@zeroing ); logcomment( "$filer : Zeroing spare count is :: " . scalar @zeroing . " and the spares are:\n" . $dsks ); my $dsks = _print_array( \@clear_spares ); logcomment( "$filer : Total non zeroing spare count : " . scalar @clear_spares . " and the spare are:\n" . $dsks ) if (@clear_spares); logcomment("$filer : NO NON ZEROING SPARES found in the filer ") if ( !scalar @clear_spares ); my $clear_spares = scalar @clear_spares; if ( $opts{waiting} =~ /yes/i ) { logcomment("Filer : $filer : Spare drives are zeroing, Please wait .."); sleep 600; } elsif ( $opts{waiting} =~ /No/i ) { logcomment("**WARNING** : $filer : Spare drives are zeroing \(@zeroing\), Test execution will continue without waiting for disk zeroing completion"); my $mail_subject = "INFO : $parse_id : zeroing spares found "; my $mail_body = "################################################################################################# ## ## Spare disk(s) on FILER : $filer are zeroing, Test execution will continue without waiting for disk zeroing completion. ## ## Zeroing Drives : @zeroing ## #################################################################################################"; if ( $EMAIL !~ /d/i ) { my %mail_params = ( HTML => $mail_body, Text => $mail_body, From => $MAIL_FROM, To => $MAIL_TO, Subject => $mail_subject, ); $mail_params{HTML} = "
$mail_params{Text}<\\HTML>";
                    my $mail = HTML::Mail->new(%mail_params);
                    $mail->send() or logcomment("CONFIG : trouble sending mail");
                } else {
                    logcomment("Email NOT sent because email set to debug by user.");
                }
                last;

            } else {
                my @non_root_volumes = check_non_root_volumes( Node => $Node );
                if ( !( scalar @non_root_volumes ) ) {
                    logcomment("$filer : NON-ROOT VOLUMES are NOT found in the filer $filer");
                    logcomment( "$filer : Zeroing spare count is : " . scalar @zeroing );
                    ##check for partition
                    my $num_of_spares;
                    if ( defined $required_spare ) {
                        $num_of_spares = $required_spare;
                    } else {
                        my $API_Obj = $Node->get_7m_or_nodescope_apiset();
                        my $kernel = $API_Obj->execute_raw_command( command => "run local version" );
                        if ( $kernel !~ /<1d>/ ) {

                            #logcomment("Non debug kernel will require at least 5 disks for raid_dp");
                            #                $num_of_spares = 6 + 2;    # 1 root aggr and 1 as Spare
                            $num_of_spares = 5;    #change added by aditis
                        } else {

                            #                            $num_of_spares = 4 + 2;    # 1 root aggr and 1 as Spare
                            $num_of_spares = 3;    #change added by aditis
                        }
                    }
                    if ( scalar @clear_spares >= $num_of_spares ) {

                        # logcomment("Difference is : $diff_spares");
                        if ($view_msg) {
                            logcomment("INFO : $filer : Normal spare count\($clear_spares\) are sufficient to proceed with test execution");
                            my $mail_subject = "INFO : $parse_id : zeroing spares found ";
                            my $mail_body    = "#################################################################################################
##
## FILER : $filer :: drives are zeroing, Normal spare count \($clear_spares\) are sufficient to proceed with test execution.
##
##
## Zeroing Drives : @zeroing
##
##
#################################################################################################";
                            if ( $EMAIL !~ /d/i ) {
                                my %mail_params = (
                                    HTML    => $mail_body,
                                    Text    => $mail_body,
                                    From    => $MAIL_FROM,
                                    To      => $MAIL_TO,
                                    Subject => $mail_subject,
                                );

                                $mail_params{HTML} = "
$mail_params{Text}<\\HTML>";
                                my $mail = HTML::Mail->new(%mail_params);
                                $mail->send() or logcomment("CONFIG : trouble sending mail");
                                $view_msg = 0;
                            } else {
                                logcomment("Email NOT sent because email set to debug by user.");
                            }

                        }
                        last;
                    } elsif ( ( ( scalar @zeroing ) + ( scalar @clear_spares ) ) >= $num_of_spares ) {
                        logcomment("$filer : NOT ENOUGH SPARE to create aggregate, ndate will wait till disk zeroing completes");
                        if ($view_msg) {

                            # logcomment("INFO : $filer : Normal spare\($diff_spares\) are sufficient to proceed with test execution");
                            my $mail_subject = "INFO : $parse_id : zeroing spares found ";
                            my $mail_body    = "#################################################################################################
##
## FILER : $filer :: drives are zeroing, NDATE will wait till the completion.
##
## User can stop execution of test by killing  to stop execution.
##
## sudo kill -9 $$
##
##
#################################################################################################";
                            if ( $EMAIL !~ /d/i ) {
                                my %mail_params = (
                                    HTML    => $mail_body,
                                    Text    => $mail_body,
                                    From    => $MAIL_FROM,
                                    To      => $MAIL_TO,
                                    Subject => $mail_subject,
                                );

                                $mail_params{HTML} = "
$mail_params{Text}<\\HTML>";
                                my $mail = HTML::Mail->new(%mail_params);
                                $mail->send() or logcomment("CONFIG : trouble sending mail");
                                $view_msg = 0;
                            } else {
                                logcomment("Email NOT sent because email set to debug by user.");
                            }

                        }
                        sleep 600;
                    } else {
                        logcomment("Spare drives are zeroing");
                        last;
                    }
                } else {
                    logcomment("$filer : Non-root volumes are : @non_root_volumes, So continuing test");
                    if (@zeroing) {
                        if ($view_msg) {
                            logcomment("INFO : $filer : Non-root volumes are present : @non_root_volumes, Test execution will NOT wait for disk zeroing completion");
                            my $mail_subject = "INFO : $parse_id : zeroing spares found ";
                            my $mail_body    = "#################################################################################################
##
## FILER : $filer :: Non-root volumes are present : @non_root_volumes, Test execution will not wait for disk zeroing completion.
##
##
## Zeroing Drives : @zeroing
##
##
#################################################################################################";
                            if ( $EMAIL !~ /d/i ) {
                                my %mail_params = (
                                    HTML    => $mail_body,
                                    Text    => $mail_body,
                                    From    => $MAIL_FROM,
                                    To      => $MAIL_TO,
                                    Subject => $mail_subject,
                                );

                                $mail_params{HTML} = "
$mail_params{Text}<\\HTML>";
                                my $mail = HTML::Mail->new(%mail_params);
                                $mail->send() or logcomment("CONFIG : trouble sending mail");
                                $view_msg = 0;
                            } else {
                                logcomment("Email NOT sent because email set to debug by user");
                            }

                        }
                        last;
                    }
                }
            }
        } else {
            logcomment("NO ZEROING SPARE DRIVES found");
            last;
        }
    }
    if ( $runlocal =~ /YES/i ) {
        try {
            my $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
            my $output      = $Api_Set_Obj->execute_command( 'command' => "aggr status -s" );
            my $n           = 0;
            my @lines       = split( /\n/, $output );
            while ( $n <= $#lines ) {
                last if ( $lines[$n] =~ /^-----/ );
                $n++;
            }
            $n++;
            foreach my $line ( @lines[ $n .. $#lines ] ) {
                if ( $line =~ /spare\s+(\S+)/ ) {

                    # logcomment("spare present $1");
                    push( @spare_disk_list, $1 );
                }
            }
        }
        catch NACL::Exceptions::NoElementsFound with {
            logcomment("NO SPARE DISKS found for the filer $filer");
        };
        my $dsks = _print_array( \@spare_disk_list );
        logcomment( "$filer : The number of spare disks present are " . scalar @spare_disk_list . " and the disks are:\n" . $dsks ) if (@spare_disk_list);
        return @spare_disk_list;
    } else {
        node_new_obj( node_array => [$Node] );
        try {
            my %hash = ( filter => { "owner" => $filer, "state" => "spare" } );
            my @disk_obj = NACL::C::Disk->find(
                command_interface => $Node,
                %hash,
            );
            foreach my $state_obj (@disk_obj) {
                my $free_disk = $state_obj->disk();
                if ( $free_disk =~ /(\S+)\:(\S+)/ ) {
                    $free_disk = $2;
                }
                push( @spare_disk_list, $free_disk );
            }
        }
        catch NACL::Exceptions::NoElementsFound with {
            logcomment("NO CONTAINER SPARE DISKS found for the filer $filer,");

        };
        try {
            logcomment("Checking for partitioned spare drives if present");
            my @disk_obj = NACL::CS::StorageDiskPartition->fetch(
                command_interface => $Node,
                filter            => { "owner-node-name" => $filer, 'container-type' => "spare" },
                requested_fields  => [qw(partition)]
            );
            foreach my $state_obj (@disk_obj) {
                my $free_disk = $state_obj->partition();
                push( @spare_disk_list, $free_disk );
            }
        }
        catch NACL::Exceptions::NoElementsFound with {
            logcomment("NO PARTITIONED SPARE DRIVES found in the filer $filer");
        };
        my $dsks = _print_array( \@spare_disk_list );
        logcomment( "$filer : The number of spare disks present are " . scalar @spare_disk_list . " and the disks are:\n" . $dsks ) if (@spare_disk_list);
        return @spare_disk_list;
    }
}

##########################################################################################################
# Auther - skaran
# Description - This routine returns spare disk, failed disk and by passed disk , normal disk
# Usage -
# Support -
##########################################################################################################

sub sysconfig_v_data {
    my (%opts) = validate(
        @_,
        {
            node    => { type => OBJECT },
            API_Obj => { type => OBJECT, default => undef, optional => 1 },
        }
    );

    my $Node = $opts{node};
    my $API_Obj;
    $API_Obj = $opts{API_Obj} if ( defined $opts{API_Obj} );
    my $filer_name = $Node->name();
    my $sysconfig_out;
    logcomment("DEBUG:Get filer configuration for filer $filer_name");
    my $Transit_obj = NACL::Transit->new( name => $filer_name );
    my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    logcomment("DEBUG:Filer $filer_name is in state : $filer_state");

    if ( $filer_state =~ /CLI|UP/i ) {
        my $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
        $sysconfig_out = $Api_Set_Obj->execute_command( 'command' => 'sysconfig -v', 'timeout' => 600 );
    } elsif ( $filer_state =~ /MAINT/ ) {
        if ($API_Obj) {
            $API_Obj->set_timeout( "connectrec-timeout" => 7200 );
            $sysconfig_out = $API_Obj->execute_raw_command( 'command' => 'sysconfig -v' );
        } else {
            my $Host = host($filer_name);
            $API_Obj = NACL::APISet->new(
                hostobj   => $Host,
                category  => "Node",
                interface => "CLI",
                set       => "Maintenance",
            );
            $API_Obj->set_timeout( "connectrec-timeout" => 7200 );
            $sysconfig_out = $API_Obj->execute_raw_command( 'command' => 'sysconfig -v' );
        }
    }
    chomp( my @sysconf_lines = split( /\r?\n/, $sysconfig_out ) );
    my @normaldisks;
    my @faileddisks;
    my @upchannels;
    my @bypassdisks;
    my $path;
    my $system_id;
    my $model;
    my $disk_blocks   = {};
    my $config_struct = {};

    foreach my $line (@sysconf_lines) {
        if ( $line =~ // ) {
            $line =~ /\S+\s+\d+:.*Adapter\s+(.*)\s+\(\D.*\)/;
            push( @upchannels, $1 );
        }
        if ( $line =~ /System(\S+|\s+)Storage(\S+|\s+)Configuration:(\S+path|\s+.+path)/ig ) {
            $path = $3;
        }
        if ( $line =~ /System ID:\s+(\S+)/ig ) {
            $system_id = $1;
        }
        if ( $line =~ /Model Name:\s+(\S+)/ig ) {
            $model = $1 unless ( defined $model );
        }
        if ( $line =~ /(\S+)\s*:\s*\S+\s*\S+\s+\S+\s+\S+GB\s+\((\S+)\s+/ ) {
            $disk_blocks->{$1} = $2;
        }
        if ( $line =~ /^\s+(\S+)\s*:/ ) {
            my $disk = $1;
            next if ( $disk =~ /Connection|Revision|Processors|Controller|IPMI|PKT/ );
            if ( $line =~ /Failed/ ) {
                push( @faileddisks, $disk );
            } else {
                push( @normaldisks, $disk );
            }
        }
        if ( $line =~ /^\s+Disk\s+(.+)\s+in.+bypassed/ ) {
            push( @bypassdisks, $1 );
        }
    }
    if (@faileddisks) {
        @faileddisks = unique(@faileddisks);
    }
    my $dsks_upchannels  = _print_array( \@upchannels );
    my $dsks_faileddisks = _print_array( \@faileddisks );
    my $dsks_normaldisks = _print_array( \@normaldisks );
    my $dsks_bypassdisks = _print_array( \@bypassdisks );
    logcomment("\nUpchannels :\n$dsks_upchannels \nFaileddisks :\n$dsks_faileddisks  \nNormaldisks :\n$dsks_normaldisks \nBypassdisks :\n$dsks_bypassdisks");
    $config_struct = {
        upchannels  => [@upchannels],
        normaldisks => [@normaldisks],
        faileddisks => [@faileddisks],
        bypassdisks => [@bypassdisks],
        path        => $path,
        model       => $model,
        disk_blocks => $disk_blocks,
        system_id   => $system_id
    };
    return $config_struct;
}

##########################################################################################################
# Auther - skaran
# Description -
# Usage -
# Supported - Cmode (CLI)
##########################################################################################################

sub sysconfig_r_data {
    my (%opts) = validate(
        @_,
        {
            node => { type => OBJECT },

        }
    );

    my $Node       = $opts{node};
    my $filer_name = $Node->name();
    logcomment("DEBUG:Get filer configruation for filer $filer_name");
    my $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
    my $raw_output = $Api_Set_Obj->execute_command( 'command' => 'sysconfig -r', 'timeout' => 600 );
    chomp( my @sysconf_lines = split( /\r?\n/, $raw_output ) );
    my $spare_count   = 0;
    my $fail_count    = 0;
    my $offline_count = 0;
    foreach my $line (@sysconf_lines) {
        $spare_count++   if ( $line =~ /spare/ );
        $fail_count++    if ( $line =~ /failed|FAILED|not responding/ );
        $offline_count++ if ( $line =~ /\(offline\)/ );
    }

    my $sys_result = {
        spare_count   => $spare_count,
        fail_count    => $fail_count,
        offline_count => $offline_count
    };
    return $sys_result;
} ## end sub sysconfig__r

##Arjun.Lavu
sub disk_ddr_label_print {
    my (%opts) = validate( @_, { Node => { type => OBJECT }, } );
    my $Node   = $opts{Node};
    my $Mode   = $Node->mode();
    my $FILER_C = $Node->name();
    my $Host    = host($FILER_C);

    #**************************************************
    #Checking the filer state
    #**************************************************
    my $Transit_obj = NACL::Transit->new( name => $FILER_C );
    my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );

    my ( $API_obj, $output );
    ##############################################
    ##Based on mode(UP/MAINT) API object is created
    ##############################################
    if ( $filer_state =~ /(CLI|UP)/ ) {
        $API_obj = $Node->get_7m_or_nodescope_apiset();
        $API_obj->set_timeout( "connectrec-timeout" => 7200 );
        logcomment("DEBUG:$FILER_C - Executing disk ddr_label print -d all");
        $output = $API_obj->execute_command( 'command' => "disk ddr_label print -d all" );
    } elsif ( $filer_state =~ /MAINT/ ) {
        $API_obj = NACL::APISet->new(
            hostobj   => $Host,
            category  => "Node",
            interface => "CLI",
            set       => "Maintenance"
        );
        $API_obj->set_timeout( "connectrec-timeout" => 7200 );
        logcomment("DEBUG:$FILER_C : Executing disk ddr_label print -d all");
        $output = $API_obj->execute_raw_command( 'command' => "disk ddr_label print -d all" );
    }
    my $disk_data  = {};
    my $key_val    = {};
    my @data_total = split( /\n/, $output );
    foreach (@data_total) {
        my $disk;
        ###########################################################
        ##Total lines are splitted with the delimeter ":"
        ##and first part is taken as key and second part is taken as value
        ###########################################################
        foreach my $var (@data_total) {
            if ( $var =~ /Disk:\s(\S+)/ ) {
                $disk = $1;
            }
            my @data = split( /\n/, $var );
            foreach my $line (@data) {
                if ( $line =~ /(.+):\s+(.+)/ ) {
                    my ( $key, $value ) = $line =~ /(.+):\s+(.+)/;
                    $key_val->{$key} = $value;
                }
            }
            for my $dat ( keys %$key_val ) {
                $disk_data->{$disk}->{$dat} = $key_val->{$dat};
            }
            $key_val = {};
        }
    }
    return $disk_data;
}
#######################################################################################################
##storage_show_data
##auther - arjun.lavu@netapp.com
##my $hash = storage_show_data(node=>$node);
##This routine returns a pointer to hash table of storage show information in the filer
##It dies on failure.
##The following named arguments are accepted,
##(Required) : Filer Node to use.
########################################################################################################

sub storage_show_data {
    my (%opts) = validate(
        @_,
        {
            node    => { type => OBJECT },
            API_Obj => { type => OBJECT, default => undef, optional => 1 },
        }
    );

    my $Node           = $opts{node};
    my $API_Obj        = $opts{API_Obj} if ( defined $opts{API_Obj} );
    my $filer_name     = $Node->name();
    my $storage_struct = {};
    my @shelf_id;
    my ( @adapter_list, $cmd, $output, $line, @adap, $adapter_name, @shelflist, $shelflist, @shelfline, $shelfname, $channel, $shelfid, $shelfstate, $phy, $linenum, $disk, $shelf, $bay, $serial, $ven, $model, $rev, $crc, $Transit_obj, $filer_state );
    $Transit_obj = NACL::Transit->new( name => $filer_name );
    $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    logcomment("Filer $filer_name is in state : $filer_state");

    if ( $filer_state !~ /^(MAINT)/ ) {
        my $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
        $output = $Api_Set_Obj->execute_command( command => "storage show" );
    } else {
        if ($API_Obj) {
            $API_Obj->set_timeout( "connectrec-timeout" => 7200 );
            $output = $API_Obj->execute_raw_command( command => "storage show" );
        } else {
            my $console = Tharn::connect("$filer_name#console");

            # Set the properties for the Connectrec used for creating the APIset
            $console->{prompts}  = [qr/\*>/];
            $console->{max_idle} = 600;
            $console->{on_idle}  = sub { $console->execute(""); };
            $API_Obj             = NACL::APISet->new(
                connection => $console,
                category   => "Node",
                interface  => "CLI",
                set        => "Maintenance"
            );
            $API_Obj->set_timeout( "connectrec-timeout" => 7200 );
            $output = $API_Obj->execute_raw_command( command => "storage show" );
        }
    }

    @adapter_list = split( /\r*\n/, $output );
    @adapter_list = grep /\S+/, @adapter_list;
    foreach $line (@adapter_list) {
        @adap = split( /:\s+|\r\n/, $line );
        if ( !defined( $adap[1] ) ) {
            $adap[1] = "undef";
        }
        if ( $line =~ /^Slot:/ ) {
            $adapter_name = $adap[1];
            $adapter_name =~ s/\s+//g;
            goto LABEL;
        }
        if ( $adap[0] =~ /Description/ ) {
            $storage_struct->{$adapter_name}->{Description} = $adap[1];
        } elsif ( $adap[0] =~ /^State/ ) {
            $storage_struct->{$adapter_name}->{State} = $adap[1];
        }
      LABEL:;
    } ## end foreach $line (@adapter_list)
    @shelflist = split( /\r*\n/, $output );
    foreach $shelflist (@shelflist) {
        @shelfline = split( /\s+/, $shelflist );
        if ( $shelflist =~ /^Shelf name:/ ) {
            $shelfname = $shelfline[2];
        } elsif ( $shelflist =~ /^Channel:/ ) {
            $channel = $shelfline[1];
        } elsif ( $shelflist =~ /^Shelf id:/ ) {
            $shelfid = $shelfline[2];
        } elsif ( $shelflist =~ /^Shelf state:/ ) {
            $shelfstate                               = $shelfline[2];
            $storage_struct->{$channel}->{Shelfname}  = $shelfname;
            $storage_struct->{$channel}->{Shelfid}    = "$channel" . "." . "$shelfid";
            $storage_struct->{$channel}->{Shelfstate} = $shelfstate;
            push( @shelf_id, "$channel" . "." . "$shelfid" );

            # Consists of array of shelfids remove the duplicates later
            $storage_struct->{$channel}->{Shelfids} = \@shelf_id;
        } elsif ( $shelflist =~ /up\s+CRC\s+Word\s+Delta/ ) {
            $crc = 4;
        } elsif ( $shelflist =~ /Rate\s+DWord\s+Disparity/ ) {
            $crc = 8;
        } elsif ( $shelflist =~ /^\[(IN|OUT)/ ) {
            $phy = $shelfline[0];
            $phy =~ s/\[//g;
            if ( $phy =~ /\]/ ) {
                $phy =~ s/\]//g;
            }
            $phy =~ s/^\s+//;
            $phy =~ s/\s+$//;
            if ( ( $crc == 8 ) && ( $shelflist =~ /^\[(OUT)\S*\s*\]*\s+\S+\s+\S+\s+\S+\s+\d+\s+\d+\s+\d+\s+\d+\s+\d+\s*\d*/ ) ) {
                $storage_struct->{$channel}->{$shelfid}->{$phy}->{InvalidWordCount}      = $shelfline[4];
                $storage_struct->{$channel}->{$shelfid}->{$phy}->{RunningDisparityCount} = $shelfline[5];
                $storage_struct->{$channel}->{$shelfid}->{$phy}->{LossDwordCount}        = $shelfline[6];
                $storage_struct->{$channel}->{$shelfid}->{$phy}->{PhyResetProblem}       = $shelfline[7];
                $storage_struct->{$channel}->{$shelfid}->{$phy}->{CRCErrorCount}         = $shelfline[8];

                #Added for SAS disks
                $storage_struct->{$channel}->{$shelfid}->{$phy}->{PhyChangeCount} = $shelfline[9];
            } elsif ( ( $crc == 8 ) && ( $shelflist =~ /^\[(IN)\S*\s*\]*\s+\S+\s+\S+\s+\S+\s+\S+\s+\d+\s+\d+\s+\d+\s+\d+\s+\d+\s*\d*/ ) ) {
                $storage_struct->{$channel}->{$shelfid}->{$phy}->{InvalidWordCount}      = $shelfline[5];
                $storage_struct->{$channel}->{$shelfid}->{$phy}->{RunningDisparityCount} = $shelfline[6];
                $storage_struct->{$channel}->{$shelfid}->{$phy}->{LossDwordCount}        = $shelfline[7];
                $storage_struct->{$channel}->{$shelfid}->{$phy}->{PhyResetProblem}       = $shelfline[8];
                $storage_struct->{$channel}->{$shelfid}->{$phy}->{CRCErrorCount}         = $shelfline[9];

                #Added for SAS disks
                $storage_struct->{$channel}->{$shelfid}->{$phy}->{PhyChangeCount} = $shelfline[10];
            } elsif ( ( $crc == 4 ) && ( $shelflist =~ /^\[(IN|OUT)\S*\s*\]*\s+\S+\s+\S+\s+\d+\s+\d+\s+\d+\s+\d+\s+\d+\s+\d+/ ) ) {
                $storage_struct->{$channel}->{$shelfid}->{$phy}->{LoopupCount}      = $shelfline[3];
                $storage_struct->{$channel}->{$shelfid}->{$phy}->{CRCErrorCount}    = $shelfline[4];
                $storage_struct->{$channel}->{$shelfid}->{$phy}->{InvalidWordCount} = $shelfline[5];
                $storage_struct->{$channel}->{$shelfid}->{$phy}->{ClockDelta}       = $shelfline[6];
                $storage_struct->{$channel}->{$shelfid}->{$phy}->{InsertCount}      = $shelfline[7];
                $storage_struct->{$channel}->{$shelfid}->{$phy}->{LIPCount}         = $shelfline[8];
            }
        } elsif ( $shelflist =~ /^\[(AUX|SQR|CIR|SIL)/ ) {
            $phy = $shelfline[0];
            $phy =~ s/\[//g;
            if ( $phy =~ /\]/ ) {
                $phy =~ s/\]//g;
            }
            $phy =~ s/^\s+//;
            $phy =~ s/\s+$//;
            if ( ( $crc == 8 ) && ( $shelflist =~ /^\[(AUX|SQR|CIR|SIL)\S*\s*\]*\s+\S+\s+\S+\s+\S+\s+\d+\s+\d+\s+\d+\s+\d+\s+\d+\s*\d*/ ) ) {
                $storage_struct->{$channel}->{$shelfid}->{$phy}->{InvalidWordCount}      = $shelfline[4];
                $storage_struct->{$channel}->{$shelfid}->{$phy}->{RunningDisparityCount} = $shelfline[5];
                $storage_struct->{$channel}->{$shelfid}->{$phy}->{LossDwordCount}        = $shelfline[6];
                $storage_struct->{$channel}->{$shelfid}->{$phy}->{PhyResetProblem}       = $shelfline[7];
                $storage_struct->{$channel}->{$shelfid}->{$phy}->{CRCErrorCount}         = $shelfline[8];

                #Added for SAS
                $storage_struct->{$channel}->{$shelfid}->{$phy}->{PhyChangeCount} = $shelfline[9];
            } elsif ( ( $crc == 4 ) && ( $shelflist =~ /^\[(AUX|SQR|CIR|SIL)\S*\s*\]*\s+\S+\s+\d+\s+\d+\s+\d+\s+\d+\s+\d+\s+\S+\s+\d+/ ) ) {
                $storage_struct->{$channel}->{$shelfid}->{$phy}->{LoopupCount}      = $shelfline[2];
                $storage_struct->{$channel}->{$shelfid}->{$phy}->{CRCErrorCount}    = $shelfline[3];
                $storage_struct->{$channel}->{$shelfid}->{$phy}->{InvalidWordCount} = $shelfline[4];
                $storage_struct->{$channel}->{$shelfid}->{$phy}->{ClockDelta}       = $shelfline[5];
                $storage_struct->{$channel}->{$shelfid}->{$phy}->{InsertCount}      = $shelfline[6];
                $storage_struct->{$channel}->{$shelfid}->{$phy}->{LIPCount}         = $shelfline[8];
            }
        } elsif ( $shelflist =~ /^\[\s+\d+/ ) {
            $phy = $shelfline[1];
            if ( $phy =~ /\]/ ) {
                $phy =~ s/\]//g;
            }
            $phy =~ s/^\s+//;
            $phy =~ s/\s+$//;
            if ( ( $crc == 8 ) && ( $shelflist =~ /^\[\s+\d+\S*\s*\]*\s+\S+\s+\S+\s+\S+\s+\d+\s+\d+\s+\d+\s+\d+\s+\d+\s*\d*/ ) ) {
                $storage_struct->{$channel}->{$shelfid}->{$phy}->{InvalidWordCount}      = $shelfline[6];
                $storage_struct->{$channel}->{$shelfid}->{$phy}->{RunningDisparityCount} = $shelfline[7];
                $storage_struct->{$channel}->{$shelfid}->{$phy}->{LossDwordCount}        = $shelfline[8];
                $storage_struct->{$channel}->{$shelfid}->{$phy}->{PhyResetProblem}       = $shelfline[9];
                $storage_struct->{$channel}->{$shelfid}->{$phy}->{CRCErrorCount}         = $shelfline[10];

                #Added for SAS
                $storage_struct->{$channel}->{$shelfid}->{$phy}->{PhyChangeCount} = $shelfline[11];
            } elsif ( ( $crc == 4 ) && ( $shelflist =~ /^\[\s+\d+\S*\s*\]*\s+\S+\s+\d+\s+\d+\s+\d+\s+\d+\s+\d+/ ) ) {
                $storage_struct->{$channel}->{$shelfid}->{$phy}->{LoopupCount}      = $shelfline[4];
                $storage_struct->{$channel}->{$shelfid}->{$phy}->{CRCErrorCount}    = $shelfline[5];
                $storage_struct->{$channel}->{$shelfid}->{$phy}->{InvalidWordCount} = $shelfline[6];
                $storage_struct->{$channel}->{$shelfid}->{$phy}->{ClockDelta}       = $shelfline[7];
                $storage_struct->{$channel}->{$shelfid}->{$phy}->{InsertCount}      = $shelfline[8];
            }
        } ## end elsif ($shelflist =~ /^\[\s+\d+/)
    } ## end foreach $shelflist (@shelflist)
    $linenum = 0;
    foreach $line (@shelflist) {
        $linenum++;
        if ( $line =~ /^DISK\s+SHELF/ ) {
            $linenum = $linenum + 2;
            foreach my $line ( @shelflist[ $linenum .. $#shelflist ] ) {
                if ( $line =~ /(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)/ ) {
                    $disk   = $1;
                    $shelf  = $2;
                    $bay    = $3;
                    $serial = $4;
                    $ven    = $5;
                    $model  = $6;
                    $rev    = $7;
                } else {
                    next;
                }
                $storage_struct->{$disk} = {
                    'DISK'   => $disk,
                    'SHELF'  => $shelf,
                    'BAY'    => $bay,
                    'SERIAL' => $serial,
                    'VENDOR' => $ven,
                    'MODEL'  => $model,
                    'REV'    => $rev,
                };
            } ## end foreach my $line (@shelflist...
        } ## end if ($line =~ /^DISK\s+SHELF/)
    } ## end foreach $line (@shelflist)
    return $storage_struct;
}

###########################################
## Author : himangin@netapp.com
## Subroutine will fail one parity drive and record time taken for reconstruction
## Parity drive of 'vol' parameter passed will be failed
###########################################

sub fail_parity_drive {
    my (%opts) = validate(
        @_,
        {
            Node         => { type => OBJECT },
            vol          => { type => ARRAYREF, },
            disk_to_fail => { type => SCALAR, default => undef, optional => 1 },
            time_out     => { type => SCALAR, default => undef, optional => 1 },
        }
    );
    my $Node      = $opts{Node};
    my $Node_name = $Node->name();
    my @volumes   = @{ $opts{vol} };
    my $TIME_OUT;
    my $partition;
    if ( defined $opts{time_out} ) {
        $TIME_OUT = $opts{time_out};
    } else {
        $TIME_OUT = 600;
    }
    my @paritydrive       = ();
    my $paritycount       = 0;
    my $fail_parity_count = 0;
    my $fail_drives       = [];
    my $Api_Set_Obj       = $Node->get_7m_or_nodescope_apiset();
    my $api_timeout       = get_max_timeout( node_present => [$Node] );
    my $disk_tot          = disk_show_drive_maint( API_Obj => $Api_Set_Obj, Filer => $Node_name );
    my @drives            = @{ $disk_tot->{'driveA'} };
    my $total_tomeout     = int( ( $api_timeout * ( scalar @drives ) ) + 7200 );
    $Api_Set_Obj->set_timeout( "connectrec-timeout" => $total_tomeout );

    foreach my $vol (@volumes) {
        my $after = $Api_Set_Obj->execute_command( 'command' => "vol status $vol -r" );
        foreach my $line ( split( /\n/, $after ) ) {
            if ( $line =~ /^\s+parity\s+(\S+)/ ) {
                push @paritydrive, $1;
                $paritycount++;
            }
        }
    }

    # check for partition
    my @temp;
    foreach (@paritydrive) {
        if ( $_ =~ /P\d+$/ ) {
            ( my $dsk = $_ ) =~ s/P\d+$//;
            push( @temp, $dsk );
            $partition = 1;
        } else {
            push( @temp, $_ );
            last;
        }
    }
    if ( defined $opts{disk_to_fail} ) {
        @paritydrive = ();
        push( @paritydrive, $opts{disk_to_fail} );
        $paritycount = @paritydrive;
    } else {
        @temp        = unique(@temp);
        @paritydrive = ();
        push( @paritydrive, $temp[0] );
        $paritycount = @paritydrive;
    }
    my $dsks = _print_array( \@paritydrive );
    logcomment( "DEBUG:$paritycount parity drives to be FAILED --  and drives are:\n" . $dsks ) if (@paritydrive);
    if ( $partition == 1 ) {
        logcomment("Since this is a partitioin setup, FAILING the whole drive");

        #         @paritydrive = @temp;
    }

    for ( my $i = 0 ; $i < $paritycount ; $i++ ) {
        sleep 2;
        logcomment("Failparitydrive: SYSOP SYSOP! failing disk $paritydrive[$i]");
        $Api_Set_Obj->execute_command( 'command' => "disk fail -i $paritydrive[$i] -f" );
        sleep(120);
        $fail_drives->[$i] = $paritydrive[$i];
    }
    my $started_time = scalar( localtime() );
    $started_time = convertTime( time_val => $started_time );

    #logcomment("DEBUG:started_time = $started_time\n");
    my $states;
    while (1) {
        $states = $Api_Set_Obj->execute_command( 'command' => "aggr status -r" );
        if ( ( $states =~ /reconstruction\s*(\d+)/ ) || ( $states =~ /prefail/ ) ) {
            logcomment("Reconstruction is in process");
            logcomment("Completed $1%") if ($1);
            sleep $TIME_OUT;
        } else {
            logcomment("Reconstruction Completed");
            sleep 2;
            last;
        }
    }
    my $end_time = scalar( localtime() );
    $end_time = convertTime( time_val => $end_time );

    #logcomment("DEBUG:DEBUG:end_time = $end_time");
    #logcomment("Start Time = $started_time ,  Actual End Time  = $end_time");
    my $totaltime = ( $end_time - $started_time );
    my ( $sec, $min, $hour ) = gmtime($totaltime);
    logcomment("Total time to complete reconstruction is $hour Hours $min Minutes $sec Seconds ");
    $fail_parity_count = @$fail_drives;
    logcomment("fail_parity_count : $fail_parity_count fail parity drives : @$fail_drives ");
    return $fail_parity_count, $fail_drives;
}

###########################################
## Author : himangin@netapp.com
## Subroutine will fail one data drive and record time taken for reconstruction
## Data drive of 'vol' parameter passed will be failed
###########################################

sub fail_data_drive {
    my (%opts) = validate(
        @_,
        {
            Node         => { type => OBJECT },
            vol          => { type => ARRAYREF },
            disk_to_fail => { type => SCALAR, default => undef, optional => 1 },
            time_out     => { type => SCALAR, default => undef, optional => 1 },
        }
    );
    my $Node    = $opts{Node};
    my $FILER_C = $Node->name();
    my @volumes = @{ $opts{vol} };
    my $TIME_OUT;
    my $partition;
    if ( defined $opts{time_out} ) {
        $TIME_OUT = $opts{time_out};
    } else {
        $TIME_OUT = 600;
    }
    my @datadrive = ();
    my $datacount;
    my $fail_data_count = 0;
    my $fail_drives     = [];
    my $Api_Set_Obj     = $Node->get_7m_or_nodescope_apiset();
    my $disk_step4      = disk_show_v( Node => $Node );
    my $pass            = 0;
    my @temp            = ();
    my @tmp             = ();

    foreach my $vol (@volumes) {
        my $after = $Api_Set_Obj->execute_command( 'command' => "vol status $vol -r" );
        foreach my $line ( split( /\n/, $after ) ) {
            if ( ( $line =~ /\s+data\s*(\S+)/ ) && ( $line !~ /\s+FAIL\s*(\S+)/ ) ) {
                push @datadrive, $1;
            }
        }
    }
    my $flag0 = 0;
    foreach (@datadrive) {
        if ( $_ =~ /P\d+$/ ) {
            ( my $dsk = $_ ) =~ s/P\d+$//;
            foreach my $disk ( keys %$disk_step4 ) {
                my $owner = $disk_step4->{$disk}->{'OWNER'};
                if ( ( $dsk =~ /$disk$/ ) && ( $owner =~ /$FILER_C/i ) ) {
                    my $spare = $dsk;
                    push( @temp, $spare );
                    $flag0     = 1;
                    $pass      = 1;
                    $partition = 1;
                    last;
                }
            }
            if ( $flag0 == 1 ) {
                last;
            }
        } else {
            push( @tmp, $_ );
            $pass = 1;
            last;
        }
    }
    if ( !$pass ) {
        my $dsks = _print_array( \@datadrive );
        logcomment("**FATAL** : $FILER_C : Since the container drives for the partitioned spare drives :\n$dsks does NOT belong to filer $FILER_C, NOT able to FAIL the data disk");
        logresult( 'FATAL', "$FILER_C :  Since the container drives for THE PARTITIONED SPARE DRIVES :\n$dsks DOES NOT BELONG TO FILER $FILER_C, not able to fail the data disk" );
    }

    if ( $partition == 1 ) {
        $datacount = @temp;
        @datadrive = ();
        @datadrive = @temp;
    } else {
        @tmp       = unique(@tmp);
        @datadrive = ();
        push( @datadrive, $tmp[0] );
        $datacount = @datadrive;
    }
    if ( defined $opts{disk_to_fail} ) {
        @datadrive = ();
        push( @datadrive, $opts{disk_to_fail} );
        $datacount = @datadrive;
    }
    my $dsks = _print_array( \@datadrive );
    logcomment( "The number of data drives to be FAILED is $datacount and drives are:\n" . $dsks );
    if ( $partition == 1 ) {
        logcomment("Since this is a partition setup, FAILING the whole drive");

        #               @datadrive = @temp;
    }
    for ( my $i = 0 ; $i < $datacount ; $i++ ) {
        sleep 2;
        logcomment("Faildatadrive: SYSOP SYSOP! FAILING disk $datadrive[$i]");
        $Api_Set_Obj->execute_command( 'command' => "disk fail $datadrive[$i] -f" );
        sleep(120);
        $fail_drives->[$i] = $datadrive[$i];
    }
    my $started_time = scalar( localtime() );
    $started_time = convertTime( time_val => $started_time );

    #logcomment("DEBUG:started_time = $started_time\n");
    my $states;
    my $state;
    sleep(120);
    while (1) {
        $states = $Api_Set_Obj->execute_command( 'command' => "aggr status -r" );
        if ( ( $states =~ /-> copy\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+\(copy\s+(\S+%)\s+completed\)/ ) || ( $states =~ /copy\s*(\d+)/i ) || ( $states =~ /prefail/i ) ) {
            logcomment("Disk Copying is in process");
            logcomment("Completed $1%") if ($1);
            sleep $TIME_OUT;
        } else {
            logcomment("Waiting for 5 min for output.");
            sleep(300);
            $state = $Api_Set_Obj->execute_command( 'command' => "aggr status -r" );
            if ( ( $state =~ /-> copy\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+\(copy\s+(\S+%)\s+completed\)/ ) || ( $state =~ /copy\s*(\d+)/i ) || ( $state =~ /prefail/i ) ) {
                logcomment("Disk Copying is in process");
                logcomment("Completed $1%") if ($1);
                sleep $TIME_OUT;
            } else {
                logcomment("Sick Disk Copying Completed");
                last;
            }
        }
    }
    my $end_time = scalar( localtime() );
    $end_time = convertTime( time_val => $end_time );

    #logcomment("DEBUG:DEBUG:end_time = $end_time");
    #logcomment("Start Time = $started_time ,  Actual End Time  = $end_time");
    my $totaltime = ( $end_time - $started_time );
    my ( $sec, $min, $hour ) = gmtime($totaltime);
    logcomment("Total time to complete reconstruction is $hour Hours $min Minutes $sec Seconds ");
    $fail_data_count = @$fail_drives;
    logcomment("FAIL_DATA_COUNT : $fail_data_count FAIL data drives : @$fail_drives");
    return $fail_data_count, $fail_drives;
}

##########################################################################################################
# Auther -  arjunl
# Description - This subroutine will delete the Non root aggregates
#               If aggregates passed externally it will delete only those aggregates if present
#
# Usage - Mandatory paramanter - Node object , Test object, Mode of filer.
#		  Optional fields	   - array reference of the aggregates which has to get delete.
##########################################################################################################

sub aggregate_volume_delete {
    my (%opts) = validate( @_, { Node => { type => OBJECT }, Aggr_array => { type => ARRAYREF, optional => 1 } } );
    my $Node = $opts{Node};
    my @Aggr_array;

    #my $Transit_obj;
    my $FILER_C     = $Node->name();
    my $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
    $Api_Set_Obj->set_timeout( "connectrec-timeout" => 1200000 );

    #$Transit_obj = NACL::Transit->new( name => $FILER_C );
    my $filer_state;
    logcomment("$FILER_C : Deleting aggregates requires off-lining volume, Some of the error message might occur, these are expected messages.");
    if ( defined scalar @{ $opts{Aggr_array} } ) {
        @Aggr_array = sort { $b cmp $a } @{ $opts{Aggr_array} };
        logcomment("$FILER_C : aggregates to delete @Aggr_array");
        foreach my $aggregate (@Aggr_array) {
            try {
                NACL::STask::Aggregate->purge(
                    command_interface => $Node,
                    aggregate         => $aggregate,
                    'method-timeout'  => 108000,
                    nacltask_verify   => 1,
                );
            }
            catch NACL::Exceptions::NoElementsFound with {
                logcomment("$FILER_C : CANNOT DELETE AGGREGATE $aggregate ");
            }
            catch NACL::APISet::Exceptions::CommandFailedException with {
                try {
                    NACL::STask::Aggregate->purge(
                        command_interface => $Node,
                        aggregate         => $aggregate,
                        'method-timeout'  => 108000,
                        nacltask_verify   => 1
                    );
                }
                catch NACL::APISet::Exceptions::CommandFailedException with {
                    logcomment("$FILER_C : CANNOT DELETE AGGREGATE $aggregate, trying again");
                    try {
                        NACL::C::StorageAggregate->delete(
                            command_interface => $Node,
                            aggregate         => $aggregate,
                            force             => 'true',
                        );
                    }
                    catch NACL::APISet::Exceptions::CommandFailedException with {
                        logcomment("$FILER_C :: CANNOT DELETE AGGREGATE $aggregate");
                    };
                };
            }
            catch NACL::Exceptions::VserverHasVolumesOnAnotherAggregate with {
                logcomment("$FILER_C : CANNOT DELETE AGGREGATE $aggregate ");
            };
        }
    } else {
        my @non_root_aggr = ();
        logcomment("$FILER_C: Deletion of aggregates");
        try {
            my @aggrs = NACL::C::Aggregate->find(
                command_interface => $Node,
                filter            => { nodes => [$FILER_C], 'root' => 'false' }
            );
            foreach my $aggr (@aggrs) {
                my $aggregates = $aggr->get_one_state_attribute('aggregate');
                push( @non_root_aggr, $aggregates );
            }
            @non_root_aggr = sort { $b cmp $a } @non_root_aggr;
            logcomment("$FILER_C :Non root aggregates are @non_root_aggr");
        }
        catch NACL::Exceptions::NoElementsFound with {
            logcomment("$FILER_C : NON ROOT AGGREGATES are NOT found!!!");
        };
        foreach my $aggregate (@non_root_aggr) {
            try {
                NACL::STask::Aggregate->purge(
                    command_interface => $Node,
                    aggregate         => $aggregate,
                    'method-timeout'  => 108000,
                    nacltask_verify   => 1,
                );
            }
            catch NACL::Exceptions::NoElementsFound with {
                logcomment("DEBUG:Inside catch NACL::Exceptions::NoElementsFound with");
                logcomment("$FILER_C : CANNOT DELETE AGGREGATE $aggregate ");
            }
            catch NACL::APISet::Exceptions::CommandFailedException with {
                try {
                    NACL::STask::Aggregate->purge(
                        command_interface => $Node,
                        aggregate         => $aggregate,
                        'method-timeout'  => 108000,
                        nacltask_verify   => 1
                    );
                }
                catch NACL::APISet::Exceptions::CommandFailedException with {
                    try {
                        NACL::STask::Aggregate->purge(
                            command_interface => $Node,
                            aggregate         => $aggregate,
                            'method-timeout'  => 108000,
                            nacltask_verify   => 1
                        );
                    }
                    catch NACL::APISet::Exceptions::CommandFailedException with {
                        logcomment("$FILER_C : CANNOT DELETE AGGREGATE $aggregate, trying again");
                        try {
                            NACL::C::StorageAggregate->delete(
                                command_interface => $Node,
                                aggregate         => $aggregate,
                                force             => 'true',
                            );
                        }
                        catch NACL::APISet::Exceptions::CommandFailedException with {
                            logcomment("$FILER_C :: CANNOT DELETE AGGREGATE:: $aggregate");
                        };
                    };
                };

            }
            catch NACL::Exceptions::VserverHasVolumesOnAnotherAggregate with {
                logcomment("$FILER_C :CANNOT DELETE AGGREGATE $aggregate ");
            };
        }

        #my $API_Set_Obj = $Node->get_7m_or_nodescope_apiset( connid => "console" );
        my $API_Set_Obj = $Node->get_7m_or_nodescope_apiset();
        $API_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
        my @nonrootaggr = ();
        my $prompts_answers = [ ".*Do you want to continue.*" => 'y' ];
        $API_Set_Obj->execute_raw_command(
            'command'                => "set test",
            'connectrec-match_table' => $prompts_answers
        );
        logcomment("Checking if any stale aggregates are present");

        #$API_Set_Obj->execute_raw_command( 'command' => "run local" );
        #$API_Set_Obj->execute_raw_command( 'command' => "priv set -q test" );
        my $aggr_output = $API_Set_Obj->execute_raw_command( 'command' => "run local aggr status" );

        foreach my $var ( split( /\n/, $aggr_output ) ) {
            if ( $var =~ /\s*Aggr\s*State/ ) {
                next;
            }
            if ( $var =~ /\s*(\S+)\s*\S+\s*\S+/i ) {
                my $agr = $1;
                if ( $agr =~ /aggr/ ) {
                    push( @nonrootaggr, $agr ) if ( $agr !~ /aggr0/i );
                }
            }
        }

        #$API_Set_Obj->execute_raw_command( 'command' => "exit" );
        if (@nonrootaggr) {
            logcomment("Stale aggregates are present : @nonrootaggr");
            $API_Set_Obj->set_timeout( "connectrec-timeout" => 7200000000 );
            logcomment("Changing the filer state to Maintenance to destroy stale aggregates");

            #my $prompts_answers = [ ".*Do you want to continue.*" => 'y' ];
            #$API_Set_Obj->execute_raw_command( 'command' => "halt -node $FILER_C -inhibit-takeover true", 'connectrec-match_table' => $prompts_answers );
            #sleep(180);
            my $Transit_obj = NACL::Transit->new( name => $FILER_C );
            my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
            logcomment("Filer state: $filer_state");
            $Transit_obj->set( 'change_state_timeout' => 7200 );
            $Transit_obj->change_state( to => "FIRMWARE" );
            sleep 300;
            my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
            logcomment("Filer state after Halt :  $filer_state");

            if ( $filer_state =~ /LOADER|FIRMWARE/i ) {
                $Transit_obj->set( 'change_state_timeout' => 7200 );
                $Transit_obj->change_state( to => "MAINT" );
            }
            my $filer_state = $Transit_obj->get_state( 'timeout' => 360000, 'get_state_timeout' => 720000 );
            if ( $filer_state =~ /MAINT/i ) {
                my $Host    = host($FILER_C);
                my $API_OBJ = NACL::APISet->new(
                    hostobj   => $Host,
                    category  => "Node",
                    interface => "CLI",
                    set       => "Maintenance"
                );
                $API_OBJ->set_timeout( "connectrec-timeout" => 7200000 );
                $API_OBJ->execute_raw_command( 'command' => "aggr status" );
                my $prompts_answers1 = [ ".*you sure you want to destroy this aggregate.*" => 'yes' ];
                foreach my $aggr_destr (@nonrootaggr) {
                    $API_OBJ->execute_raw_command( 'command' => "aggr offline $aggr_destr" );
                    my $agr_dest = $API_OBJ->execute_raw_command( 'command' => "aggr destroy $aggr_destr -f", 'connectrec-match_table' => $prompts_answers1 );
                    sleep(5);
                    if ( $agr_dest =~ /Aggregate \'$aggr_destr\' destroyed/ ) {
                        logcomment("$FILER_C: Aggregate $aggr_destr is destroyed");
                    } else {
                        logcomment("**WARNING** : $FILER_C: Aggregate $aggr_destr is NOT destroyed properlly , please try manually");
                    }
                }
                logcomment("Changing the filer state to CLI");
                my $Transit_obj = NACL::Transit->new( name => $FILER_C );
                $Transit_obj->set( 'change_state_timeout' => 7200 );
                $Transit_obj->change_state( to => "CLI" );
                $Node->refresh_command_interface();
            }
        }
    }
    sleep 10;
}

##########################################################################################################
# Author -  arunak
# Description - This subroutine will return time-out based on disk attached.
# Usage - Mandatory parameter - Node object , Test object
# Return - max time-out value in seconds.
##########################################################################################################
sub get_max_timeout {
    my (%opts) = validate(
        @_,
        {
            node_present => { type => ARRAYREF },
            Test         => { type => OBJECT, optional => 1, default => '' },
        }
    );
    my @Nodes          = @{ $opts{node_present} };
    my $Test           = $opts{Test};
    my @time_out_array = ();
    my $max_disk_size  = 0;
    my $timeout;
    foreach my $Node (@Nodes) {
        my $Transit_obj;
        my $FILER_C = $Node->name();
        my $Mode    = $Node->mode();
        $Transit_obj = NACL::Transit->new( name => $FILER_C );
        my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
        logcomment("DEBUG:$FILER_C : Filer is in $filer_state ");
        if ( $filer_state =~ /CLI|UP/ ) {
            if ( $Mode =~ /CMode/i ) {
                my $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
                $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
                $Api_Set_Obj->execute_raw_command( 'command' => "rows 0" );
                my $output = $Api_Set_Obj->execute_raw_command( 'command' => "storage disk show -fields usable-size-mb" );
                foreach my $line ( split( /\n/, $output ) ) {
                    if ( ( $line =~ /(X;X)(\d+)(X;X)/ ) || ( $line =~ /(\s+)(\d+)(\s*)/ ) ) {
                        if ( $max_disk_size < $2 ) {
                            $max_disk_size = $2;
                        }
                    }
                }
                $max_disk_size = int( $max_disk_size / (1024) );

                #logcomment( "maximum disk size is $max_disk_size GB");
                my ($readable_disk_size) = readable_disk_size( GB => $max_disk_size );
                logcomment("Maximum disk size is $readable_disk_size");
                if ( $max_disk_size <= 10 ) {
                    $timeout = $timeout + 1200;
                } elsif ( $max_disk_size <= 1000 ) {
                    $timeout = $timeout + ( 1200 * 5 );
                } else {
                    $timeout = $timeout + int( $max_disk_size * 12 );
                }
                my ( $sec, $min, $hour ) = gmtime($timeout);
                logcomment("MAX timeout is $timeout seconds i.e $hour Hours $min Minutes $sec Seconds");
                return $timeout;
            }
            my ($dsk_size) = readable_disk_size( Blocks => $max_disk_size );
            logcomment("Max disk size : $max_disk_size Blocks i.e $dsk_size");
            if ( $max_disk_size <= 20971520 ) {
                $timeout = $timeout + 1200;
            } elsif ( $max_disk_size <= 2147483648 ) {
                $timeout = $timeout + ( 1200 * 5 );
            } else {
                $timeout = $timeout + int( ( $max_disk_size / 2147483648 ) * (12000) );
            }
            my ( $sec, $min, $hour ) = gmtime($timeout);
            logcomment("MAX timeout is $timeout seconds i.e $hour Hours $min Minutes $sec Seconds");
            return $timeout;
        }
        if ( $filer_state =~ /MAINT/ ) {
            my $disk_size;
            my $Host    = host($FILER_C);
            my $API_OBJ = NACL::APISet->new(
                hostobj   => $Host,
                category  => "Node",
                interface => "CLI",
                set       => "Maintenance"
            );
            $API_OBJ->set_timeout( "connectrec-timeout" => 7200 );
            my $disk_list_result = disk_list_data( API_Obj => $API_OBJ, );
            foreach my $dsk ( keys %$disk_list_result ) {
                $disk_size = $disk_list_result->{$dsk}->{'BLOCKS'};
                $max_disk_size = $disk_size if ( $disk_size > $max_disk_size );
            }
            my ($dsk_size) = readable_disk_size( Blocks => $max_disk_size );
            logcomment("Max disk size - $max_disk_size Blocks i.e $dsk_size");
            if ( $max_disk_size <= 20971520 ) {
                $timeout = $timeout + 1200;
            } elsif ( $max_disk_size <= 2147483648 ) {
                $timeout = $timeout + ( 1200 * 5 );
            } else {
                $timeout = $timeout + int( ( $max_disk_size / 2147483648 ) * (12000) );
            }
            my ( $sec, $min, $hour ) = gmtime($timeout);
            logcomment("MAX timeout is $timeout seconds i.e $hour Hours $min Minutes $sec Seconds");
            return $timeout;
        }
    }
}

###############################################################################
##	Auther 		- Arjun.Lavu@netapp.com
##
##	Description - This subroutine will return the hash which contains all the disk data which is
##				  obtained by after executing "storage show disk -a".
##				  EX: WWN,Vendor etc if present
##
##	Usage 		- Mandatory paramanter - Node.
##
##	Compatibility	- this subroutine will work both in FILESYSTEM and MAINTENENCE mode (C Mode /7 Mode)

sub storage_show_disk_a_data {
    my (%opts) = validate(
        @_,
        {
            Node      => { type => OBJECT },
            Armadillo => { type => SCALAR, optional => 2, default => 0 },
        }
    );

    my $Node      = $opts{Node};
    my $Mode      = $Node->mode();
    my $FILER_C   = $Node->name();
    my $Host      = host($FILER_C);
    my $Armadillo = $opts{Armadillo};

    #**************************************************
    #Checking the filer state
    #**************************************************
    my $Transit_obj = NACL::Transit->new( name => $FILER_C );
    my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );

    my ( $API_obj, $output );
    ##############################################
    ##Based on mode(UP/MAINT) API object is created
    ##############################################
    logcomment("Filer : $FILER_C : is in $filer_state state");
    if ( $filer_state =~ /(CLI|UP)/ ) {
        $API_obj = $Node->get_7m_or_nodescope_apiset();
        $API_obj->set_timeout( "connectrec-timeout" => 7200 );
        logcomment("DEBUG:$FILER_C : Executing storage show disk -a");
        $output = $API_obj->execute_command( 'command' => "storage show disk -a", 'timeout' => 1200 );
    } elsif ( $filer_state =~ /MAINT/ ) {
        $API_obj = NACL::APISet->new(
            hostobj   => $Host,
            category  => "Node",
            interface => "CLI",
            set       => "Maintenance"
        );
        $API_obj->set_timeout( "connectrec-timeout" => 7200 );
        logcomment("DEBUG:$FILER_C : Executing storage show disk -a");
        $output = $API_obj->execute_raw_command( 'command' => "storage show disk -a" );
    } else {
        logcomment("$FILER_C : Filer is NOT in proper state to execute command");
    }
    my $disk_data = {};
    my $key_val   = {};
    my @data_final;
    ################################################################################################################
    ##Total output is split into sections and starting section which contains text Unable to load any package
    ## is deleted and rest is taken into one more array which contains required data about disks
    ################################################################################################################
    my @data_total = split( /\n/, $output );    ##array @data_total will be having data of each disk as separate element
                                                #foreach(@data_total){
                                                #	if($_=~/Disk Qualification Package Details/){
                                                #		next;
                                                #	}else{
                                                #		push(@data_final,$_);
                                                #	}
                                                #}
    ##If required data present
    if (@data_total) {
        my $disk;
        ###########################################################
        ##Total lines are split with the delimiter ":"
        ##and first part is taken as key and second part is taken as value
        ###########################################################
        foreach my $var (@data_total) {
            if ( $var =~ /Disk:\s(\S+)/ ) {
                $disk = $1;
                ##checking for Boab Configuration.
                if ( ( $Armadillo == 1 ) && ( $disk =~ /(.+)\.(.+)\.(.+)L\d$/ ) ) {

                    #Splitting the drive name
                    $disk = substr( $disk, 0, -2 );
                }
            }

            if ( $var =~ /Package Date/ ) {
                my ($res) = $var =~ /Package Date:\s+(.*)/;
                $disk_data->{'PackageDate'} = $res;
            }
            if ( $var =~ /FileName/ ) {
                my ($res) = $var =~ /FileName\s*=\s*(\S+)/;
                $disk_data->{'FileName'} = $res;
            }
            if ( $var =~ /FileVersion/ ) {
                my ($res) = $var =~ /FileVersion\s*=\s*(\S+)/;
                $disk_data->{'FileVersion'} = $res;
            }
            if ( $var =~ /DriveRecordCount/ ) {
                my ($res) = $var =~ /DriveRecordCount\s*=\s*(\S+)/;
                $disk_data->{'DriveRecordCount'} = $res;
            }
            if ( $var =~ /AliasRecordCount/ ) {
                my ($res) = $var =~ /AliasRecordCount\s*=\s*(\S+)/;
                $disk_data->{'AliasRecordCount'} = $res;
            }

            my @data = split( /\n/, $var );
            foreach my $line (@data) {
                if ( $line =~ /(.+):\s+(.+)/ ) {
                    my ( $key, $value ) = $line =~ /(.+):\s+(.+)/;
                    $key   = trim($key);
                    $value = trim($value);
                    $key_val->{$key} = $value if ($key);
                }
            }
            for my $dat ( keys %$key_val ) {
                $disk_data->{$disk}->{$dat} = $key_val->{$dat};
            }
            $key_val = {};
        }
    }
    return $disk_data;
}

##################################################################################################
##	Auther 		- arunak@netapp.com
##	Description - This subroutine will wipe all configurations and sets the cluster using entries
##				  from tharnhost file.
##	Usage 		- Mandatory paramanter - Node(single node object)
##									   - Test object.
##				  Call to this subroutine should be made using subtest.
##	Compatibility	- This subroutine will work both in FILESYSTEM and MAINTENENCE mode (CMode)
##################################################################################################
sub wipe_config_filers {
    my (%opts) = validate(
        @_,
        {
            node       => { type => OBJECT },
            event_time => { type => SCALAR, optional => 1, default => 'NO' },
        }
    );
    my $Node       = $opts{node};
    my $event_time = $opts{event_time};
    my $Image      = $opts{image};
    my $Home       = $ENV{HOME};
    my $Node_name  = $Node->name();
    my $filer_info = `cat $Home/NDATE/FILER_INFO/$Node_name`;
    my $passwd;
    ($passwd) = $filer_info =~ /default_password\s*=\s*(\S+)\s*/ig;
    logcomment("DEBUG:password is $passwd");
    #############################################################################

    if ( $event_time !~ /NO/ ) {
        logcomment( scalar( localtime() ) . " Starting for $event_time time" );
    }
    my $time    = get_max_timeout( node_present => [$Node] );
    my $Host    = host($Node_name);
    my $API_OBJ = NACL::APISet->new(
        hostobj   => $Host,
        category  => "Node",
        interface => "CLI",
        set       => "Maintenance"
    );
    $API_OBJ->set_timeout( "connectrec-timeout" => 7200 );
    my $disk_tot      = disk_show_drive_maint( API_Obj => $API_OBJ, Filer => $Node_name );
    my @drives        = @{ $disk_tot->{'driveA'} };
    my $total_tomeout = ( $time * ( scalar @drives ) );

    #############################################################################
    my $prompt_fw;
    my $wipeclean_timeout = 660;
    my $ignore_strings = [ "MADIMM\\d+->", "DIMM\\d+->", "^T>" ];

    # Retreive valid prompts from NATE
    my $host         = Tharn::host($Node_name);
    my $prompt_array = $host->prompt_fw();
    my $prompts      = join( "|", @$prompt_array );
    $prompt_fw = "($prompts)";
    logcomment("DEBUG:This is the prompt regex: $prompt_fw");
    logcomment("Disable cluster/HA pair");
    my $Server = new Server( no_cli => 1 );
    $Server->set_execution_server( -Server => $Node_name );

    #    $Server->console(cmd => "storage failover modify -node * -enabled false -auto-giveback false" );
    #    logcomment("Enabled  storage failover");

    my $Transit_obj = NACL::Transit->new( name => $Node_name );
    my $conn = $Transit_obj->{'conn'};
    $Transit_obj->set( 'timeout' => 600, maxcycle => 20 );
    $Transit_obj->change_state( to => "FIRMWARE" );
    my $Server = new Server( no_cli => 1 );
    logcomment("Set AUTO BOOT to false ");
    my $timeout = "9000";
    $Server->set_execution_server( -Server => $Node_name );
    $Server->console(
        cmd                        => "setenv AUTOBOOT false",
        additional_prompts_timeout => $timeout,
        ignore                     => $ignore_strings,
        additional_prompts         => { "$prompt_fw" => "FINAL_PROMPT" }
    );
    logcomment("AUTOBOOT set to false");
    $Server->console(
        cmd                        => "printenv",
        additional_prompts_timeout => $timeout,
        ignore                     => $ignore_strings,
        additional_prompts         => { "$prompt_fw" => "FINAL_PROMPT" }
    );

    $Transit_obj->set( 'change_state_timeout' => 7200 );
    $Transit_obj->change_state( to => "BOOT_MENU" );
    logcomment("DEBUG:$Node_name : Filer is in boot_state");
    logcomment("DEBUG:$Node_name : Creating Server object");
    my $Server = new Server( no_cli => 1 );
    my @filer_working = $Server->servers();
    logcomment("DEBUG:Filers we are working on : @filer_working");

    my $timeout = "90000";    # Change timeout in final code.
    $timeout = $total_tomeout if ( $total_tomeout > $timeout );
    my ( $s, $m, $h ) = gmtime($timeout);
    logcomment("DEBUG:Setting timeout : $timeout seconds (i.e) $h Hours $m Minutes $s Seconds");
    logcomment("DEBUG:Set execution server");
    $Server->set_execution_server( -Server => $Node_name );    #set the execution server to the current node
    logcomment( "Boot_menu wipe clean util called " . scalar( localtime() ) );
    logcomment("Execution server set to $Node_name");
    logcomment("DEBUG:Disable password ");
    $Server->console( cmd => "options security.passwd.rules.everyone off", noprompt => 1 );
    eval {
        $Server->console(
            cmd                        => "4",
            additional_prompts_timeout => $timeout,
            ignore                     => $ignore_strings,
            additional_prompts         => {
                ".*Zero disks, reset config and install a new file system.*" => "yes",
                ".*reset config and install a new file.*"                    => "yes",
                ".*erase all the data on the disks.*"                        => "yes",
                ".*want to continue.*"                                       => "y",
                "Rebooting to finish"                                        => "FATAL_PROMPT",
                ".*Rebooting to finish.*"                                    => "FATAL_PROMPT",
                ".*Rebooting to finish wipeconfig.*"                         => "FATAL_PROMPT",
                "$prompt_fw"                                                 => "FATAL_PROMPT",
                "Selection "                                                 => "FATAL_PROMPT",
                "login"                                                      => "admin",
                ".*Type yes to confirm and continue.*"                       => 'exit',
                "::>"                                                        => "FATAL_PROMPT",
                ".*Password.*"                                               => "$passwd",

            }
        );
    };

    if ($@) {
        if ( $@ !~ /Err=TIMEOUT/ ) {
            if ( $@ =~ /Rebooting to finish/ ) {
                my $Transit_obj = NACL::Transit->new( name => $Node_name );
                logcomment("DEBUG:Changing state to firmware");
                $Server->set_execution_server( -Server => $Node_name );
                $Transit_obj->set( 'change_state_timeout' => 7200 );
                $Transit_obj->change_state( to => "FIRMWARE" );
                my $conn = $Server->get_connection( type => "console_connection" );
                $Server->console(
                    cmd                => "setenv AUTOBOOT false",
                    ignore             => $ignore_strings,
                    additional_prompts => {
                        "$prompt_fw"                           => "FINAL_PROMPT",
                        "::>"                                  => "FINAL_PROMPT",
                        ".*Type yes to confirm and continue.*" => 'exit',
                    }
                );
                sleep 10;
                $Server->console(
                    cmd                => "setenv bootarg.init.boot_clustered true",
                    ignore             => $ignore_strings,
                    additional_prompts => {
                        "$prompt_fw"                           => "FINAL_PROMPT",
                        "::>"                                  => "FINAL_PROMPT",
                        ".*Type yes to confirm and continue.*" => 'exit',
                    }
                );
                $Server->console(
                    cmd                        => "boot_ontap",
                    additional_prompts_timeout => $timeout,
                    ignore                     => $ignore_strings,
                    additional_prompts         => {
                        "$prompt_fw"                                                                       => "FINAL_PROMPT",
                        "::>"                                                                              => "FINAL_PROMPT",
                        "Do you want to create a new cluster or join an existing cluster? {create, join}:" => "exit",
                        "{create, join}:"                                                                  => "exit",
                        ".*create a new cluster or join an existing.*"                                     => "exit",
                        ".*Enter the node management interface IP address.*"                               => "exit",
                        "Enter the node management interface port .*"                                      => "exit",
                        ".*Type yes to confirm and continue.*"                                             => 'exit',
                        ".* Enter the .*"                                                                  => "exit",
                        "Password:"                                                                        => "$passwd",
                        ".*management interface port.*"                                                    => "exit",
                        ".*Welcome to node setup.*"                                                        => "exit",
                        ".*enter the following commands at any time.*"                                     => "exit",
                        ".*To accept a default or omit a question.*"                                       => "exit",
                        ".*interface IP address.*"                                                         => "exit",
                        ".*the node management.*"                                                          => "exit",
                        "login"                                                                            => "admin",
                        ".*Password.*"                                                                     => "$passwd",
                    }
                );
            } else {
                logcomment("Unknown error during wipeconfig :$@");
            }
        } else {
            logcomment("Timeout during wipeconfig:$@");
        }
    }
    logcomment("Renaming node ");
    try {
        $Server->console(
            cmd                        => "node rename -newname $Node_name",
            additional_prompts_timeout => $timeout,
            ignore                     => $ignore_strings,
            additional_prompts         => {
                "$prompt_fw"   => "FINAL_PROMPT",
                "::>"          => "FINAL_PROMPT",
                "login"        => "admin",
                ".*Password.*" => "$passwd",
            }
        );
        logcomment("Changing session timeout Value");
        $Server->console(
            cmd                        => "system timeout modify -timeout 3000",
            additional_prompts_timeout => $timeout,
            ignore                     => $ignore_strings,
            additional_prompts         => {
                "$prompt_fw"   => "FINAL_PROMPT",
                "::>"          => "FINAL_PROMPT",
                "login"        => "admin",
                ".*Password.*" => "$passwd",
            }
        );
    }
    catch NACL::Transit::Exceptions::TransitException with {
        my $exception_object = shift;
        logcomment( "Exception is of type: " . ref($exception_object) );
        logcomment( "Error text is: " . $exception_object->text() );
    };
    logcomment("Checking State of Filer");
    my $Transit_obj    = NACL::Transit->new( name => $Node_name );
    my $conn           = $Transit_obj->{'conn'};
    my $timeout        = "1900";
    my $ignore_strings = [ "MADIMM\\d+->", "DIMM\\d+->", "^T>" ];
    logcomment( "DEBUG:Checking state " . scalar( localtime() ) );
    my $current_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );

    if ( $current_state =~ /USERNAME|PASSWORD/ ) {
        $Transit_obj->set( 'change_state_timeout' => 7200 );
        $Transit_obj->change_state( to => "CLI" );
    }
    logcomment("DEBUG:Verifying Node name ");
    try {
        $Server->console(
            cmd                        => "node rename -newname $Node_name",
            additional_prompts_timeout => $timeout,
            ignore                     => $ignore_strings,
            additional_prompts         => {
                "$prompt_fw"   => "FINAL_PROMPT",
                "::>"          => "FINAL_PROMPT",
                "login"        => "admin",
                ".*Password.*" => "$passwd",
            }
        );
        logcomment("Changed node name");
    }
    catch NACL::Transit::Exceptions::TransitException with {
        my $exception_object = shift;
        logcomment( "Exception is of type: " . ref($exception_object) );
        logcomment( "Error text is: " . $exception_object->text() );
    };
    logcomment("Completed 4d Booting , Proceeding with cluster create");
    if ( $event_time !~ /NO/ ) {
        logcomment("Completed booting for $event_time time");
    }
}

##################################################################################################
##  Auther      - arunak@netapp.com
##  Description - This subroutine will setup cmode filer (wipe config and create,join cluster)
##  Usage       - Mandatory paramanter - node_present(All the node -Array reference)
##  Compatibility   - This subroutine will work both in FILESYSTEM mode CMode
##################################################################################################
sub setup_cmode_filers {
    my (%opts) = validate(
        @_,
        {
            node_present       => { type => ARRAYREF },
            Test               => { type => OBJECT },
            delete_mini_disk   => { type => SCALAR, optional => 1, default => 'YES' },
            remove_assign_disk => { type => SCALAR, optional => 1, default => 'YES' },
            event_time         => { type => SCALAR, optional => 1, default => 'NO' },
        }
    );
    my @Nodes = @{ $opts{node_present} };

    my $Test               = $opts{Test};
    my $delete_mini_disk   = $opts{delete_mini_disk};
    my $remove_assign_disk = $opts{remove_assign_disk};
    my $event_time         = $opts{event_time};
    logcomment("Node Present :");
    foreach my $Node (@Nodes) {
        my $FILER_C = $Node->name();
        logcomment(" $FILER_C");
    }
    logcomment("DEBUG:Setup Cmode filer");
    my $Home = $ENV{HOME};
    my @subtests;
    my $prompt_fw;
    my $Transit_obj;
    my $Server = new Server( no_cli => 1 );

    # Check state and boot in maintenancae
    my @change_2_maint = ();
    my $flag           = 0;
    foreach my $Node (@Nodes) {
        my $FILER_C = $Node->name();
        logcomment("DEBUG:Checking state of filer");
        my $Transit_obj = NACL::Transit->new( name => $FILER_C );
        my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
        logcomment("Filer : $FILER_C is in $filer_state state");
        if ( $filer_state !~ /MAINT/ ) {
            logcomment("Filer $FILER_C is NOT in Maintenance mode, changing state to Maintenance");
            push( @change_2_maint, $FILER_C );
            $flag = 1;
        }
    }
    if ( $flag == 1 ) {
        my @state_subtest;
        foreach my $filer (@change_2_maint) {
            logcomment("Changing state of filer - $filer to Maintenance");
            push(
                @state_subtest,
                subtest(
                    \&boot_filer_in_req_state,           -runid,
                    "change_state_to_maint_" . "$filer", -bg,
                    "--",
                    filer_name      => $filer,
                    Test            => $Test,
                    change_state_to => 'MAINT',
                )
            );
        }
        Subtest::wait_finish( subtest => [@state_subtest] );
    } else {
        logcomment("Filer is in Maintenance Mode");
    }

    # get_config_status(Nodes =>[@Nodes]);
## check for chassis and controller ha configurations
    foreach my $Node (@Nodes) {
        my $FILER_C     = $Node->name();
        my $host        = host($FILER_C);
        my $Api_Set_Obj = NACL::APISet->new(
            hostobj   => $host,
            category  => "Node",
            interface => "CLI",
            set       => "Maintenance"
        );
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
        HA_config( API_Obj => $Api_Set_Obj );
    }
    destroy_root_volume( Noderef => [@Nodes] );
    remove_partition( Noderef => [@Nodes] );
    check_disk_owner( Noderef => [@Nodes] );
    disk_remv_assign_ownership( Node_ref => \@Nodes ) if ( $remove_assign_disk =~ /YES/i );

    # mini disk delete
    if ( $delete_mini_disk =~ /YES/i ) {    #deleting mini_disks if parameter mini_disk_delete is YES else not
        $Test->nlog("Deleting the MINI_DISKS");
        my @mini_subtests;
        foreach my $Node (@Nodes) {
            my $FILER_C = $Node->name();
            push( @mini_subtests, subtest( \&delete_mini_disk, -runid, "delete_mini_disk_" . "$FILER_C", -bg, "--", node => $Node, ) );
        }
        Subtest::wait_finish( subtest => [@mini_subtests] );
        sleep 10;
    }
    logcomment("Basic check of filer and disk completed");
    logcomment("Proceeding with wipeconfig and cluster setup");

    foreach my $Node (@Nodes) {
        my $FILER_C    = $Node->name();
        my $filer_info = `cat $Home/NDATE/FILER_INFO/$FILER_C`;
        my $passwd;
        ($passwd) = $filer_info =~ /default_password\s*=\s*(\S+)\s*/ig;
        $Server->set_execution_server( -Server => $FILER_C );
        $Transit_obj = NACL::Transit->new( name => $FILER_C );
        my $filer_state    = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
        my $timeout        = "1900";
        my $ignore_strings = [ "MADIMM\\d+->", "DIMM\\d+->", "^T>" ];
        logcomment("Filer $FILER_C is in $filer_state state");

        if ( $filer_state =~ /CLI|UP/i ) {
            try {
                $Server->console(
                    cmd                        => "node rename -newname $FILER_C",
                    additional_prompts_timeout => $timeout,
                    ignore                     => $ignore_strings,
                    additional_prompts         => {
                        "$prompt_fw"   => "FINAL_PROMPT",
                        "::>"          => "FINAL_PROMPT",
                        "login"        => "admin",
                        ".*Password.*" => "$passwd",
                    }
                );
                logcomment("Changed node name");
            }
            catch NACL::Transit::Exceptions::TransitException with {
                my $exception_object = shift;
                logcomment( "Exception is of type: " . ref($exception_object) );
                logcomment( "Error text is: " . $exception_object->text() );
            };
        }
        if ( $filer_state !~ /CLI|UP|MAINT/i ) {
            $Transit_obj->set( 'change_state_timeout' => 7200 );
            $Transit_obj->change_state( to => "MAINT" );
        }
    }
    logcomment( "Wipe config for the filers will be initiated" . scalar( localtime() ) );
    if ( $event_time =~ /NO/ ) {
        foreach my $Node (@Nodes) {
            my $filer_name = $Node->name();
            push( @subtests, subtest( \&wipe_config_filers, -runid, "wipe_config_filers_" . "$filer_name", -bg, "--", node => $Node, ) );
        }
    } else {
        foreach my $Node (@Nodes) {
            my $filer_name = $Node->name();
            push(
                @subtests,
                subtest(
                    \&wipe_config_filers,                  -runid,
                    "wipe_config_filers_" . "$filer_name", -bg,
                    "--",
                    node       => $Node,
                    event_time => $event_time,
                )
            );
        }
    }
    Subtest::wait_finish( subtest => [@subtests] );
    logcomment( "Wipe config completed" . scalar( localtime() ) );
    my ( $fail_cnt, $fatal_cnt );
    my @results;
    foreach my $subtest (@subtests) {
        @results = $subtest->rslts();
        foreach my $result (@results) {
            if ( $result->type() =~ /INFO/ ) {
                logcomment("Subtest boot_filer_in_req_state completed successfully");
            } elsif ( $result->severity() >= 0 ) {
                logcomment("Subtest boot_filer_in_req_state NOT completed succesfully");
                if ( $result->type() =~ /FAIL/i ) {
                    $fail_cnt++;
                }
                if ( $result->type() =~ /FATAL|SCRIPT|CONFIG/ ) {
                    $fatal_cnt++;
                }
            } ## end elsif ($result->severity(...
        } ## end foreach my $result (@results)
    } ## end foreach my $subtest (@subtests)
    if ( $fail_cnt == 0 ) {
        logcomment("Filer Booted the filer successfully in required state");
    }
    my $Server = new Server( no_cli => 1 );
    logcomment("Server /Nodes working :");
    foreach my $Node (@Nodes) {
        my $FILER_C = $Node->name();
        logcomment(" $FILER_C");
    }

    my $filer_state;
    foreach my $Node (@Nodes) {
        my $FILER_C;
        try {
            $FILER_C = $Node->name();
            logcomment("DEBUG:Cheking the state of filer $FILER_C");
            my $Transit_obj = NACL::Transit->new( name => $FILER_C );
            $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
            logcomment("Filer : $FILER_C is in $filer_state state");
            if ( $filer_state !~ /CLI/i ) {
                $Transit_obj->set( 'change_state_timeout' => 7200 );
                $Transit_obj->change_state( to => "CLI" );
                $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
                logcomment("DEBUG:Filer : $FILER_C has changed state to $filer_state");
            }

        }
        catch NACL::Transit::Exceptions::TransitException with {
            logcomment("Caught TransitException exception");
            my $exception_object = shift;
            logcomment("**WARNING** : Filer - $FILER_C : is in $filer_state state");
        };
    }

    logcomment("Node Present :");
    foreach my $Node (@Nodes) {
        my $FILER_C = $Node->name();
        logcomment(" $FILER_C");
    }
    @Nodes = sort(@Nodes);
    logcomment("Node sorted :");
    foreach my $Node (@Nodes) {
        my $FILER_C = $Node->name();
        logcomment(" $FILER_C");
    }
    foreach my $a (@Nodes) {
        my $fil_name = $a->name();
        logcomment("DEBUG:Node name is - $fil_name");
    }
    logcomment("Creating cluster using nodes available");
    create_join_cluster( node_present => [@Nodes] );
    logcomment("Completed creating and joining cluster ");
    my @temp_nodes = NACL::C::Node->find();    # Find Nodes/Filers used in the test, Based on FILER param.
    my %nodes_filer;
    foreach my $Node (@temp_nodes) {
        my $FILER_C = $Node->name();
        $nodes_filer{$FILER_C} = [$Node];
    }
    my @Nodes_all = map { @{$_} } grep { (/\S/) } values(%nodes_filer);    # Contains Node object used for test execution.
    foreach my $Node (@Nodes_all) {
        my $FILER_C = $Node->name();
        my $Home    = $ENV{HOME};
        system("rm -rf $Home/.ssh/known_hosts");
        $Home = trim($Home);
        my $host_file    = "$Home/NDATE/FILER_INFO/$FILER_C";
        my $filer_config = `cat $host_file`;
        my $def_pass;
        foreach my $line ( split /\n/, $filer_config ) {

            if ( $line =~ /^default_password=(.*)/ ) {
                $def_pass = $1;
                logcomment("$FILER_C : Changing the diag mode password to $def_pass");
                last;
            }
        }
        try {
            my $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
            $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
            $Api_Set_Obj->execute_raw_command( 'command' => "security login unlock -username diag" );
            my $prompts_answers = [ 'Enter a new password:' => "$def_pass", 'Enter it again:' => "$def_pass" ];
            $Api_Set_Obj->execute_raw_command( 'command' => "security login password -username diag", 'connectrec-match_table' => $prompts_answers );
            $Api_Set_Obj->execute_raw_command( 'command' => "version" );
        }
        catch NATE::BaseException with {
            logcomment("$FILER_C : Caught BASE EXCEPTION, connection problem!!!");
        };
    }
}
##################################################################################################
##	Auther 		- arunak@netapp.com
##	Description - This subroutine will create cluster and join cluster. All inputs are captured from
##					tharn host file.
##	Usage 		- Mandatory paramanter - node_present(All the node -Array reference)
##	Compatibility	- This subroutine will work both in FILESYSTEM mode CMode
##################################################################################################
sub create_join_cluster {
    my (%opts) = validate( @_, { node_present => { type => ARRAYREF }, nvme_setup => { type => SCALAR, default => 'no', optional => 1 }, } );
    my @Nodes = @{ $opts{node_present} };
    my $nvme_setup = $opts{nvme_setup};
    logcomment("DEBUG : NVMe setup Selected ") if ( $nvme_setup =~ /yes/ );
    logcomment("Wait for cluster port to come up");
    sleep 120;
    logcomment("Node Present :");
    my @Node_obj = @Nodes;

    foreach my $Node (@Nodes) {
        my $FILER_C = $Node->name();
        logcomment(" $FILER_C");
    }
    logcomment("DEBUG:Creating Server object");
    my $Server = new Server( no_cli => 1 );

    #Params
    my %nodes_filer;
    my $base_license;
    my $base_license_sec = 'NULL';
    my $cluste_name;
    my $cluster_port_1;
    my $cluster_ip;
    my $cluster_mask;
    my $cluster_gateway;
    my $cluster_mtu;
    my $def_pass;
    my $cluster_mgmt_inter_port;
    my $cluster_mgmt_ip;
    my $cluster_mgmt_gateway;
    my $cluster_mgmt_mask;
    my $cluster_mgmt_mtu;
    my $node_mgmt_inter_port;
    my $node_mgmt_ip;
    my $node_mgmt_gateway;
    my $node_mgmt_mask;
    my $node_mgmt_mtu;
    my $create_again = 0;
    my $CLUSTER_IP_A;

    foreach my $Node (@Nodes) {

        #logcomment("Node - $Node");
        my $FILER_C = $Node->name();

        #logcomment("Name - $FILER_C");
        $nodes_filer{$FILER_C} = $Node;
    }
    my @filer_working = ();
  create_again:
    @Nodes         = keys(%nodes_filer);    # Contains Node names
    @filer_working = sort(@Nodes);

    logcomment("DEBUG:Filers we are working on : @filer_working");
    logcomment("Setting execution server to $filer_working[0]");
    my $Home = $ENV{HOME};
    $Home = trim($Home);
    my $host_file_C = "$Home/NDATE/FILER_INFO/$filer_working[0]" . "_C";
    my $host_file   = "$Home/NDATE/FILER_INFO/$filer_working[0]";
    system("sudo cp -rf $host_file_C $host_file");
    my $filer_config = `cat $host_file`;
    foreach my $line ( split /\n/, $filer_config ) {

        if ( $line =~ /^\#/ ) {
            next;    # skip overall result report starting with a '#'.
        } elsif ( $line =~ /^CLUSTER_NAME=(.*)/ ) {
            $cluste_name = $1;
        } elsif ( $line =~ /^BASE_LICENSE=(.*)/ ) {
            $base_license = $1;
        } elsif ( $line =~ /^SECONDARY_BASE_LICENSE=(.*)/i ) {
            my $temp = $1;
            $temp =~ s/^\s+|\s+$//g;
            if ( $temp =~ /^NULL$/i ) {
                $base_license_sec = $base_license;
            } else {
                $base_license_sec = $temp;
            }
        } elsif ( $line =~ /^CLUSTER_PORT1=(.*)/ ) {
            $cluster_port_1 = $1;
        } elsif ( $line =~ /^CLUSTER_IP1=(.*)/ ) {
            $cluster_ip   = $1;
            $CLUSTER_IP_A = $cluster_ip;
        } elsif ( $line =~ /^CLUSTER_MASK1=(.*)/ ) {
            $cluster_mask = $1;
        } elsif ( $line =~ /^CLUSTER_GATEWAY1=(.*)/ ) {
            $cluster_gateway = $1;
        } elsif ( $line =~ /^CLUSTER_MTU1=(.*)/ ) {
            $cluster_mtu = $1;
        } elsif ( $line =~ /^default_password=(.*)/ ) {
            $def_pass = $1;
        } elsif ( $line =~ /^CLUSTER_MGMT_PORT=(.*)/ ) {
            $cluster_mgmt_inter_port = $1;
        } elsif ( $line =~ /^CLUSTER_MGMT_IP=(.*)/ ) {
            $cluster_mgmt_ip = $1;
        } elsif ( $line =~ /^CLUSTER_MGMT_GATEWAY=(.*)/ ) {
            $cluster_mgmt_gateway = $1;
        } elsif ( $line =~ /^CLUSTER_MGMT_MASK=(.*)/ ) {
            $cluster_mgmt_mask = $1;
        } elsif ( $line =~ /^CLUSTER_MGMT_MTU=(.*)/ ) {
            $cluster_mgmt_mtu = $1;
        } elsif ( $line =~ /^MGMT_PORT=(.*)/ ) {
            $node_mgmt_inter_port = $1;
        } elsif ( $line =~ /^MGMT_IP=(.*)/ ) {
            $node_mgmt_ip = $1;
        } elsif ( $line =~ /^MGMT_GATEWAY=(.*)/ ) {
            $node_mgmt_gateway = $1;
        } elsif ( $line =~ /^MGMT_MASK=(.*)/ ) {
            $node_mgmt_mask = $1;
        } elsif ( $line =~ /^MGMT_MTU=(.*)/ ) {
            $node_mgmt_mtu = $1;
        }
    }
    $base_license_sec = $base_license if ( $base_license_sec =~ /^NULL$/i );    ##if param SECONDARY_BASE_LICENSE is not present in filer_conig
    $Server->set_execution_server( -Server => $filer_working[0] );              #set the execution server to the current node
    logcomment("Server is set to $filer_working[0]");
    my $timeout        = "1900";
    my $ignore_strings = [ "MADIMM\\d+->", "DIMM\\d+->", "^T>" ];
    my $host           = Tharn::host( $filer_working[0] );
    my $prompt_array   = $host->prompt_fw();
    my $prompts        = join( "|", @$prompt_array );
    my $prompt_fw      = "($prompts)";
    logcomment("DEBUG:This is the prompt regex: $prompt_fw");

    ####################################################################
    my $Transit_obj = NACL::Transit->new( name => $filer_working[0] );
    my $state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );

    if ( $state =~ /USERNAME|pass/ig ) {    ##if filer is in USERNAME mode that means filer is in CMODE, so for safety reading
        logcomment("DEBUG:password is - $def_pass");
        try {
            $Server->console(
                cmd                        => "\n",
                additional_prompts_timeout => 600,
                ignore                     => $ignore_strings,
                additional_prompts         => {
                    ".*login.*"           => "admin",
                    ".*Password.*"        => $def_pass,
                    ".*::>.*"             => "FINAL_PROMPT",
                    ".*Login incorrect.*" => 'FATAL_PROMPT',
                    "$prompt_fw"          => "FINAL_PROMPT",
                }
            );
        }
        catch NATE::BaseException with {
            logcomment("Filer  - $filer_working[0] : INCORRECT LOGIN, please check the configuration file ");
        };
    } else {
        logcomment("Filer $filer_working[0] state is - $state");

        if ( $state =~ /FIRMWARE|MAINT/i ) {
            logcomment("**FATAL** : Filer : $filer_working[0] : is in $state state, so CANNOT create the cluster");
            logresult( 'FATAL', "Filer : $filer_working[0] : IS IN $state STATE, SO CANNOT CREATE THE CLUSTER" );
        }
    }
    logcomment("FILERS : @filer_working");
    my $ic = 0;
    foreach my $Node (@filer_working) {
        my $Server_1 = new Server( no_cli => 1 );
        logcomment("Node is : $Node");
        my $FILER_C = $Node;
      re_port:
        logcomment("CHECK : FILER : $FILER_C");
        $Server_1->set_execution_server( -Server => $FILER_C );    #set the execution server to the current node
        logcomment("Server is set to $FILER_C");
        my $timeout        = "1900";
        my $ignore_strings = [ "MADIMM\\d+->", "DIMM\\d+->", "^T>" ];
        my $host           = Tharn::host($FILER_C);
        my $prompt_array   = $host->prompt_fw();
        my $prompts        = join( "|", @$prompt_array );
        my $prompt_fw      = "($prompts)";
        logcomment("DEBUG:This is the prompt regex: $prompt_fw");
        my $port_output = $Server_1->console(
            cmd                        => "net port show",
            additional_prompts_timeout => '180',
            ignore                     => $ignore_strings,
            additional_prompts         => {
                "$prompt_fw" => "FINAL_PROMPT",
                ".*::>.*"    => "FINAL_PROMPT",
                "::>"        => "FINAL_PROMPT",
            }
        );

=head
        if ( $port_output =~ /down/ ) {
            logcomment("Some cluster ports appear to be down");
            sleep 120;
            $ic++;
            if ( $ic > 2 ) {

                #   logcomment("**FATAL** : Port is down, Cluster Cannot be created");
                #   logresult( 'FATAL', "Port is down, Cluster Cannot be created" );
            } else {
                goto re_port;
            }
        }
=cut    

        my @ports;
        my @ports_down = ();
        foreach my $line ( split( /\n/, $port_output ) ) {
            if ( $line =~ /up/ ) {
                if ( $line =~ /(\S+)\s+\S+\s+\S+\s+up\s+\S+\.*/ ) {
                    push( @ports, $1 );
                }
            } elsif ( $line =~ /down/ ) {
                if ( $line =~ /(\S+)\s+\S+\s+\S+\s+(\S+)\s+\S+\.*/ ) {
                    push( @ports_down, $1 );
                }

            }
        }
        @ports_down = unique(@ports_down);
        if (@ports_down) {
            logcomment("Some ports appear to be down, and ports are : @ports_down");
            sleep 120;
            $ic++;
            if ( $ic <= 2 ) {
                goto re_port;
            }
        }
        foreach my $port (@ports_down) {
            if ( $port =~ /e0a|e1a/ ) {
                logcomment("**FATAL** : Cluster Port $port is DOWN, Cluster CANNOT be created");
                logresult( 'FATAL', "Cluster Port $port is DOWN, Cluster CANNOT be created" );

            }
        }
        @ports = unique(@ports);
        logcomment("Available ports are : @ports");
        logcomment("Set port \"e0a or e1a \" IPSpace to Cluster and MTU to 9000");
        foreach my $pt (@ports) {
            if ( $pt =~ /e0a|e1a/ ) {
                logcomment("Modify port $pt IPSpace and MTU ");
                my $pput = $Server_1->console(
                    cmd                        => "net port modify -node * -port $pt -IPSpace Cluster -mtu 9000",
                    additional_prompts_timeout => '180',
                    ignore                     => $ignore_strings,
                    additional_prompts         => {
                        "$prompt_fw" => "FINAL_PROMPT",
                        ".*::>.*"    => "FINAL_PROMPT",
                        "::>"        => "FINAL_PROMPT",
                    }
                );
                logcomment("$pt Changed IPSpace to cluster and MTU to 9000");
            }
        }
        logcomment("Port Config Completed on $FILER_C");
        sleep 5;
        last;
    }
    logcomment("Port Configured, Proceed with Cluster setup");
    ####################################################################
    try {
        logcomment("Executing cluster setup");
        $Server->console(
            cmd                        => "cluster setup",
            additional_prompts_timeout => $timeout,
            ignore                     => $ignore_strings,
            additional_prompts         => {
                "want to continue"                                                                       => "y",
                "Rebooting to finish"                                                                    => "FATAL_PROMPT",
                "$prompt_fw"                                                                             => "FINAL_PROMPT",
                "Selection "                                                                             => "FINAL_PROMPT",
                "Starting AUTOBOOT"                                                                      => "\cc",
                "Do you want to create a new cluster or join an existing cluster? {create, join}:"       => "create",
                ".*{join}.*"                                                                             => "FATAL_PROMPT",
                "Do you want to create a new cluster or join an existing cluster? {join}:"               => "FATAL_PROMPT",
                "{create, join}:"                                                                        => "create",
                "login"                                                                                  => "admin",
                ".*DNS.*"                                                                                => "\013",
                "Do you intend for this node to be used as a single node cluster?"                       => "no",
                "Do you want to use this configuration? {yes, no} [yes]:"                                => "yes",                      #no
                "Do you want to use this configuration?"                                                 => "yes",                      #no
                ".*to reboot now to set storage failover (SFO) to HA mode.*"                             => "no",
                ".*{yes, no} [yes]:.*"                                                                   => "no",
                ".*Do you want to reboot now to set storage failover (SFO) to HA mode.*"                 => "no",
                ".*reboot now to set storage failover (SFO).*"                                           => "no",
                ".*Enable IPv4 DHCP on the service processor interface.*"                                => "no",
                "Do you want to use these defaults?"                                                     => "yes",                      #no
                "List the private cluster network ports"                                                 => $cluster_port_1,
                ".*Enter the cluster ports' MTU size.*"                                                  => $cluster_mtu,
                "Enter the cluster network netmask"                                                      => $cluster_mask,
                "Enter the cluster interface IP address for port"                                        => $cluster_ip,
                ".*Enter the IP address of an interface on the.*"                                        => $cluster_ip,
                "Will the cluster network be configured to use network switches?"                        => "no",
                "Enter the cluster name:"                                                                => $cluste_name,
                "Enter the cluster base license key:"                                                    => $base_license,
                ".*The base license key for the cluster can be obtained from your sales or support.*"    => $base_license_sec,
                ".*the value \"$base_license_sec\" is invalid for.*"                                     => "FATAL_PROMPT",
                ".*Enter an additional license key.*"                                                    => "\013",
                ".*Enter the system config backup destination address.*"                                 => "\013",
                "::>"                                                                                    => "FINAL_PROMPT",
                ".*Press  to page down,  for next line, or 'q' to quit.*"                 => "\013",
                ".*Type yes to confirm and continue {yes}:.*"                                            => "yes",
                ".*Otherwise, press Enter to complete cluster setup using the command line interface:.*" => "\013",
                ".*command line interface:.*"                                                            => "\013",
                "^interface:"                                                                            => "\013",
                ".*Password.*"                                                                           => $def_pass,
                ".*Retype the password.*"                                                                => $def_pass,
                ".*cluster management interface port.*"                                                  => $cluster_mgmt_inter_port,
                ".*cluster management interface IP address.*"                                            => $cluster_mgmt_ip,
                ".*cluster management interface netmask.*"                                               => $cluster_mgmt_mask,
                ".*cluster management interface default gateway.*"                                       => $cluster_mgmt_gateway,
                ".*Enter the DNS domain names:.*"                                                        => "\013",
                ".*Where is the controller located.*"                                                    => "SVL",
                ".*cluster administrator's.*"                                                            => $def_pass,
                ".*Password.*"                                                                           => $def_pass,
                ".*node management interface port.*"                                                     => $node_mgmt_inter_port,
                ".*node management interface IP address.*"                                               => $node_mgmt_ip,
                ".*node management interface netmask.*"                                                  => $node_mgmt_mask,
                ".*node management interface default gateway.*"                                          => $node_mgmt_gateway,
                ".*Enter the service processor interface IP address.*"                                   => '1.1.1.1',
                ".*Enter the service processor interface netmask.*"                                      => $node_mgmt_mask,
                ".*Enter the service processor interface default gateway.*"                              => '1.1.1.1',
                ".*Error.*"                                                                              => "FATAL_PROMPT",
                ".*Exiting the cluster setup wizard.*"                                                   => "FINAL_PROMPT",
                "::*>"                                                                                   => "FINAL_PROMPT",
                ".*Cluster setup is now complete.*"                                                      => "FINAL_PROMPT",
                ".*::>.*"                                                                                => "FINAL_PROMPT",
                ".*reboot now to set storage failover.*"                                                 => "no",
            }
        );
    }
    catch NACL::Transit::Exceptions::TransitException with {
        my $exception_object = shift;
        logcomment( "Exception is of type: " . ref($exception_object) );
        logcomment( "Error text is: " . $exception_object->text() );
    }
    catch NATE::BaseException with {

        #Burt 981347
        my $string = $Server->console(
            cmd                        => "exit",
            additional_prompts_timeout => '120',
            ignore                     => $ignore_strings,
            additional_prompts         => {
                "$prompt_fw" => "FINAL_PROMPT",
                ".*::>.*"    => "FINAL_PROMPT",
            }
        );
        logcomment("Cluster setup was NOT successful, Re-Checking IP space and setting to defaults");
        set_ipspace_for_ports( Filer => \@filer_working );
        $create_again++;
        if ( $create_again == 1 ) {
            goto create_again;
        } else {
            logcomment("**FATAL** : Cluster creation FAILED, NDATE tried twice creating cluster,exiting from cluster setup");
            logresult( 'FATAL', "ERROR OCCURED DURING CLUSTER CREATION" );
        }
    };

    #burt 981347 End
    logcomment("Cluster created");

    #    sleep(600);
    logcomment("NDATE will wait for few minutes for cluster services to come up, and later cluster will be joined");
    sleep 60;
    logcomment("NDATE waitied for few minutes after creating cluster, Proceeding with cluster join");

    #	sleep 300;
    #Cehck identity and cluster creation health
    logcomment("Check for cluster identity and cluster health before joining cluster");
    my $string = $Server->console(
        cmd                        => "cluster show",
        additional_prompts_timeout => '180',
        ignore                     => $ignore_strings,
        additional_prompts         => {
            "$prompt_fw" => "FINAL_PROMPT",
            ".*::>.*"    => "FINAL_PROMPT",
            "::>"        => "FINAL_PROMPT",
        }
    );
    logcomment("Check for cluster identity, before joining another node");
    my $string = $Server->console(
        cmd                        => "cluster identity show",
        additional_prompts_timeout => '180',
        ignore                     => $ignore_strings,
        additional_prompts         => {
            "$prompt_fw" => "FINAL_PROMPT",
            ".*::>.*"    => "FINAL_PROMPT",
            "::>"        => "FINAL_PROMPT",
        }
    );
    logcomment("Cluster health and identity check completed, Proceeding with joining cluster");

    my $port_output = $Server->console(
        cmd                        => "net port show",
        additional_prompts_timeout => '180',
        ignore                     => $ignore_strings,
        additional_prompts         => {
            "$prompt_fw" => "FINAL_PROMPT",
            ".*::>.*"    => "FINAL_PROMPT",
            "::>"        => "FINAL_PROMPT",
        }
    );
    my @ports;

    foreach my $line ( split( /\n/, $port_output ) ) {
        if ( $line =~ /up/ ) {
            print "$line\n";
            if ( $line =~ /(\S+)\s+\S+\s+\S+\s+up\s+\S+\.*/ ) {
                push( @ports, $1 );
            }
        }
    }
    logcomment("Avialble ports are : @ports");

    logcomment("Check IP Auto generated IP configured");
    my $ip_out = $Server->console(
        cmd                        => "net int show",
        additional_prompts_timeout => '180',
        ignore                     => $ignore_strings,
        additional_prompts         => {
            "$prompt_fw" => "FINAL_PROMPT",
            ".*::>.*"    => "FINAL_PROMPT",
            "::>"        => "FINAL_PROMPT",
        }
    );
    my @clust_ip_auto;
    foreach my $line ( split( /\n/, $ip_out ) ) {
        if ( $line =~ /up/ ) {
            if ( $line !~ /e0M/ ) {
                if ( $line =~ /\S+\s+(\d+\.\d+\.\d+\.\d+)\/\d+\s+\S+\s+\S+\s+\S+/ ) {
                    push( @clust_ip_auto, $1 );
                }
            }
        }
    }
    logcomment("IPs auto configured - @clust_ip_auto");

    #End of cluster identity check .
    logcomment("DEBUG:Joining cluster ");
    logcomment("Node $filer_working[1] is being joined to $filer_working[0]");
    my $Home = $ENV{HOME};
    $Home = trim($Home);
    my $host_file_C = "$Home/NDATE/FILER_INFO/$filer_working[1]" . "_C";
    my $host_file   = "$Home/NDATE/FILER_INFO/$filer_working[1]";
    system("sudo cp -rf $host_file_C $host_file");
    my $host_file    = "$Home/NDATE/FILER_INFO/$filer_working[1]";
    my $filer_config = `cat $host_file`;
    my $cluster_port_1;
    my $cluster_mtu_2;
    my $cluster_mask;
    my $cluster_ip;
    my $node_mgt_inter_ip;
    my $node_mgt_inter_port;
    my $node_mgt_inter_mask;
    my $node_mgt_inter_gateway;
    my $MTU_error;
    my $def_pass;

    foreach my $line ( split /\n/, $filer_config ) {
        if ( $line =~ /^\#/ ) {
            next;    # skip overall result report starting with a '#'.
        } elsif ( $line =~ /^CLUSTER_NAME=(.*)/ ) {
            $cluste_name = $1;
        } elsif ( $line =~ /^CLUSTER_PORT1\=(.*)/ ) {
            $cluster_port_1 = $1;
        } elsif ( $line =~ /^CLUSTER_IP1=(.*)/ ) {
            $cluster_ip = $1;
        } elsif ( $line =~ /^CLUSTER_MTU1=(.*)/ ) {
            $cluster_mtu_2 = $1;
        } elsif ( $line =~ /^CLUSTER_MASK1=(.*)/ ) {
            $cluster_mask = $1;
        } elsif ( $line =~ /^MGMT_IP=(.*)/ ) {
            $node_mgt_inter_ip = $1;
        } elsif ( $line =~ /^MGMT_PORT=(.*)/ ) {
            $node_mgt_inter_port = $1;
        } elsif ( $line =~ /^MGMT_MASK=(.*)/ ) {
            $node_mgt_inter_mask = $1;
        } elsif ( $line =~ /^MGMT_GATEWAY=(.*)/ ) {
            $node_mgt_inter_gateway = $1;
        } elsif ( $line =~ /^default_password=(.*)/ ) {
            $def_pass = $1;
        }
    }
    if ( $cluster_mtu !~ /^$cluster_mtu_2$/ ) {
        logcomment("MTU value of the filer $filer_working[1] is NOT same as MTU value of the filer $filer_working[0], \nSo for cluster joining MTU values $cluster_mtu is considered");
        $cluster_mtu_2 = $cluster_mtu;
    }
    logcomment("Setting execution server to $filer_working[1]");
    $Server->set_execution_server( -Server => $filer_working[1] );

    ####################################################################
    my $Transit_obj2 = NACL::Transit->new( name => $filer_working[1] );
    my $state2 = $Transit_obj2->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    if ( $state2 =~ /USERNAME|pass/ig ) {    ##if filer is in USERNAME mode that means filer is in CMODE, so for safety reading
        logcomment("DEBUG:password is - $def_pass");
        try {
            $Server->console(
                cmd                        => "\n",
                additional_prompts_timeout => 600,
                ignore                     => $ignore_strings,
                additional_prompts         => {
                    ".*login.*"           => "admin",
                    ".*Password.*"        => $def_pass,
                    ".*::>.*"             => "FINAL_PROMPT",
                    ".*Login incorrect.*" => 'FATAL_PROMPT',
                    "$prompt_fw"          => "FINAL_PROMPT",
                }
            );
        }
        catch NATE::BaseException with {
            logcomment("Filer - $filer_working[1] : INCORRECT LOGIN, please check the configuration file ");
        };
    } else {
        logcomment("State of filer is : $state2");
        if ( $state2 =~ /FIRMWARE|MAINT/i ) {
            logcomment("**FATAL** : Filer : $filer_working[1] : is in $state2 state, so CANNOT join the cluster");
            logresult( 'FATAL', "Filer : $filer_working[1] : IS IN $state2 STATE, SO CANNOT JOIN THE CLUSTER" );
        }
    }
    sleep 5;
    my $join_cnt = 0;
    my $joining_output;
    ####################################################################
  join_again:
    if ( $MTU_error == 1 ) {
        my $Api_Set_Obj = $nodes_filer{ $filer_working[0] }->get_7m_or_nodescope_apiset( connid => "console" );
        my $prompts_answers = [ ".*continue?" => 'y' ];
        $Api_Set_Obj->execute_raw_command( 'command' => "set test", 'connectrec-match_table' => $prompts_answers );
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
        my $prompts_answers = [ ".*Do you want to continue.*" => 'y' ];
        $Api_Set_Obj->execute_raw_command( 'command' => "broadcast-domain show" );
        $Api_Set_Obj->execute_raw_command( 'command' => 'broadcast-domain modify -mtu 1500 *', 'connectrec-match_table' => $prompts_answers );
        $Api_Set_Obj->execute_raw_command( 'command' => "broadcast-domain show" );
        $Api_Set_Obj->execute_raw_command( 'command' => 'broadcast-domain modify -mtu 1500 *', 'connectrec-match_table' => $prompts_answers );
        $Api_Set_Obj->execute_raw_command( 'command' => "broadcast-domain show" );

        # my $Server = new Server(no_cli=>1);
        $Server->set_execution_server( -Server => $filer_working[1] );
        try {
            $Server->console(
                cmd                        => "net port modify -node $filer_working[1] -port \* -mtu 1500",
                additional_prompts_timeout => $timeout,
                ignore                     => $ignore_strings,
                additional_prompts         => {
                    ".*Do you want to continue.*" => "y",
                    "$prompt_fw"                  => "FINAL_PROMPT",
                    "::>"                         => "FINAL_PROMPT",
                }
            );
            $Server->console(
                cmd                        => "net port show",
                additional_prompts_timeout => $timeout,
                ignore                     => $ignore_strings,
                additional_prompts         => {
                    ".*Do you want to continue.*" => "y",
                    "$prompt_fw"                  => "FINAL_PROMPT",
                    "::>"                         => "FINAL_PROMPT",
                }
            );
        }
        catch NATE::BaseException with {
            logcomment("Caught exception in setting MTU values");
        };
        $cluster_mtu_2 = 1500;
    }
  re_join_ip_space:
    try {

        #sleep(200);
        logcomment("Joining cluster");
        $CLUSTER_IP_A = $clust_ip_auto[0];
        logcomment("DEBUG :: node A - cluster IP $CLUSTER_IP_A");
        $joining_output = $Server->console(
            cmd                        => "cluster setup",
            additional_prompts_timeout => $timeout,
            ignore                     => $ignore_strings,
            additional_prompts         => {
                "want to continue"                                                                         => "y",
                "$prompt_fw"                                                                               => "FINAL_PROMPT",
                "Starting AUTOBOOT"                                                                        => "\cc",
                "Do you want to create a new cluster or join an existing cluster? {create, join}:"         => "join",
                "Do you want to create a new cluster or join an existing cluster? {join}:"                 => "join",
                "{create, join}:"                                                                          => "join",
                ".*create a new cluster or join an existing.*"                                             => "join",
                ".*{join}.*"                                                                               => "join",
                "login"                                                                                    => "admin",
                ".*private cluster network ports.*"                                                        => $cluster_port_1,
                ".*cluster ports' MTU size.*"                                                              => $cluster_mtu_2,
                ".*cluster network netmask.*"                                                              => $cluster_mask,
                ".*Enter the cluster interface IP address for port.*"                                      => $cluster_ip,
                ".*Enter the name of the cluster you would like to join.*"                                 => $cluste_name,
                ".*Enter the IP address of an interface on the private cluster network from the cluster.*" => $CLUSTER_IP_A,
                ".*cluster network from the cluster you want to join.*"                                    => $CLUSTER_IP_A,
                ".*cluster you want to join.*"                                                             => $CLUSTER_IP_A,
                ".*the node management interface port.*"                                                   => $node_mgt_inter_port,
                ".*Restarting Cluster Setup.*"                                                             => "FATAL_PROMPT",
                ".*node management interface IP address.*"                                                 => $node_mgt_inter_ip,
                ".*node management interface netmask.*"                                                    => $node_mgt_inter_mask,
                ".*node management interface default gateway.*"                                            => $node_mgt_inter_gateway,
                ".*Press  to page down,  for next line, or 'q' to quit.*"                   => "\013",
                ".*Type yes to confirm and continue {yes}:.*"                                              => "yes",
                ".*Otherwise, press Enter to complete cluster setup using the command line interface:.*"   => "\013",
                ".*command line interface:.*"                                                              => "\013",
                "^interface:"                                                                              => "\013",
                ".*Enter the service processor interface IP address.*"                                     => '1.1.1.1',
                ".*Enter the service processor interface netmask.*"                                        => $node_mgt_inter_mask,
                ".*Enter the service processor interface default gateway.*"                                => '1.1.1.1',
                ".*Enter the system config backup destination address.*"                                   => "\013",
                "Do you intend for this node to be used as a single node cluster?"                         => "no",
                "Do you want to use this configuration? {yes, no} [yes]:"                                  => "yes",
                "Do you want to use this configuration?"                                                   => "yes",
                ".*Enter the system config backup destination address.*"                                   => "\013",
                ".*Enable IPv4 DHCP on the service processor interface.*"                                  => "no",
                ".*{yes, no} [yes]:.*"                                                                     => "yes",
                "Do you want to reboot now to set storage failover (SFO) to HA mode?"                      => "no",
                ".*Do you want to reboot now to set storage failover (SFO) to HA mode.*"                   => "no",
                ".*reboot now to set storage failover (SFO).*"                                             => "no",
                ".*an additional license key.*"                                                            => "\013",
                ".*reboot now to set storage failover.*"                                                   => "no",
                "Do you want to use these defaults?"                                                       => "no",
                ".*Password.*"                                                                             => $def_pass,
                ".*Exiting the cluster setup wizard.*"                                                     => "FINAL_PROMPT",
                ".*DNS.*"                                                                                  => "\013",
                "::>"                                                                                      => "FINAL_PROMPT",
                ".*address of an interface on the private cluster network from the cluster you.*"          => $CLUSTER_IP_A,
            }
        );
    }
    catch NACL::Transit::Exceptions::TransitException with {
        my $exception_object = shift;
        logcomment( "Exception is of type: " . ref($exception_object) );
        logcomment( "Error text is: " . $exception_object->text() );
    }
    catch NATE::BaseException with {
        my $exception_object = shift;
        logcomment( "Exception is of type: " . ref($exception_object) );
        my $exp_out = $exception_object->text();
        if ( $exp_out =~ /address of an interface on the private cluster network from the cluster you/ ) {
            logcomment("FAILED to determine the identity of the partner node's cluster");
            sleep 4;
            logcomment("Get prompt and check for cluster identity");
            $Server->console(
                cmd                        => "\013",
                additional_prompts_timeout => '120',
                ignore                     => $ignore_strings,
                additional_prompts         => {
                    "$prompt_fw"                         => "FINAL_PROMPT",
                    ".*::>.*"                            => "FINAL_PROMPT",
                    ".*cluster you would like to join.*" => $cluste_name,
                    "::>"                                => "FINAL_PROMPT",
                }
            );
            logcomment("cluster identity passed");
            logcomment("Press Enter once again to confirm");
            $Server->console(
                cmd                        => "\013",
                additional_prompts_timeout => '120',
                ignore                     => $ignore_strings,
                additional_prompts         => {
                    "$prompt_fw" => "FINAL_PROMPT",
                    ".*::>.*"    => "FINAL_PROMPT",
                }
            );
            logcomment("completed setup");
        }

        $join_cnt++;
        logcomment("CAUGHT BASE Exception in cluster Joining");
        $MTU_error = 1;
        sleep 2;
        my $string = $Server->console(
            cmd                        => "exit",
            additional_prompts_timeout => '120',
            ignore                     => $ignore_strings,
            additional_prompts         => {
                "$prompt_fw" => "FINAL_PROMPT",
                ".*::>.*"    => "FINAL_PROMPT",
            }
        );
        if ( $join_cnt > 2 ) {
            logcomment("**FATAL** : ERROR OCCURED during the cluster joining, script tried two times but cluster joining FAILED");
            logresult( 'FATAL', "ERROR OCCURED DURING THE CLUSTER JOINING" );
        }
        logcomment("ERROR OCCURED during cluster joining, setting ipspace and creating cluster join again");
        logcomment("Checking for IPspace and Setting to Default");
        if ( $join_cnt == 1 ) {
            my @temp_fil;
            push( @temp_fil, $filer_working[1] );
            logcomment("Set defaults IP space for filer - @temp_fil");
            set_ipspace_for_ports( Filer => \@temp_fil );
            logcomment("IP space was set to defaults, Proceeding with Join ");
            $MTU_error = 0;
            goto re_join_ip_space;
        }
        goto join_again;
    };
    logcomment("Cluster join completed");
    logcomment("Add license to the cluster");
    if ( $nvme_setup =~ /no/ ) {
        logcomment("Reboot nodes");
        my $Transit_obj;
        my @re_subtest = ();

        #Change in 4.3 - Do not re-boot after cluster create and join

=head
        foreach my $filer_name (@filer_working) {
            $Transit_obj = NACL::Transit->new( name => $filer_name );
            logcomment( "Calling change_state " . scalar( localtime() ) );
            push(
                @re_subtest,
                subtest(
                    \&boot_filer_in_req_state, -runid, "shutdown_node_" . "$filer_name", -bg, "--",
                    filer_name      => $filer_name,
                    change_state_to => 'FIRMWARE'
                )
            );
        }
        Subtest::wait_finish( subtest => [@re_subtest] );
        logcomment("DEBUG:Booting Filers in FIRMWARE");
        my @new_subtest = ();
        foreach my $filer_name (@filer_working) {
            logcomment("Rebooting.....");
            push(
                @new_subtest,
                subtest(
                    \&boot_filer_in_req_state, -runid, "reboot_filer_" . "$filer_name", -bg, "--",
                    filer_name      => $filer_name,
                    change_state_to => 'CLI'
                )
            );
        }
        Subtest::wait_finish( subtest => [@new_subtest] );
        logcomment("DEBUG:Rebooting Filers");
=cut

        #Change in 4.3 - Do not re-boot after cluster create and join - END
        logcomment("Cluster Create and Join completed");
    }    #end of if nvme
    logcomment("DEBUG:Enabling storage failover");
    my $Server         = new Server( no_cli => 1 );
    my $timeout        = "1900";
    my $ignore_strings = [ "MADIMM\\d+->", "DIMM\\d+->", "^T>" ];
    $Server->set_execution_server( -Server => $filer_working[0] );
    my $filer_info = `cat $Home/NDATE/FILER_INFO/$filer_working[0]`;
    my $passwd;
    ($passwd) = $filer_info =~ /default_password\s*=\s*(\S+)\s*/ig;
    $Server->console(
        cmd                        => "storage failover modify -node * -enabled false -auto-giveback false",
        additional_prompts_timeout => $timeout,
        ignore                     => $ignore_strings,
        additional_prompts         => {
            "$prompt_fw"                  => "FINAL_PROMPT",
            ".*::>.*"                     => "FINAL_PROMPT",
            "login"                       => "admin",
            ".*Password.*"                => "$passwd",
            ".*Do you want to continue.*" => "y",
        }
    );
    logcomment("Enabled storage failover");
    my $Home = $ENV{HOME};
    `sudo rm -rf $Home/.ssh/known_hosts`;

    foreach my $Node (@Node_obj) {
        my $FILER_C = $Node->name();
        logcomment("Set test and proceed with next steps");
        logcomment("Filer : $FILER_C");
        my $Transit_obj = NACL::Transit->new( name => $FILER_C );
        my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
        logcomment("Node $FILER_C is in the Filer state $filer_state");
        if ( $filer_state =~ /UP|CLI/i ) {
            my $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset( connid => "console" );
            $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
            try {
                my $prompts_answers = [ ".*Do you want to continue.*" => 'y' ];
                $Api_Set_Obj->execute_raw_command( 'command' => "set test", 'connectrec-match_table' => $prompts_answers );
                my $node_version = $Api_Set_Obj->execute_command( 'command' => 'version' );
                logcomment("Node Version : $node_version");
                my $prompts_answers_1 = [ "Do you want to continue" => 'y' ];
                my $return = $Api_Set_Obj->execute_raw_command( 'command' => 'cluster ha show' );
                $Api_Set_Obj->execute_raw_command( 'command' => 'cluster ha modify -configured false', 'connectrec-match_table' => $prompts_answers_1 );
            }
            catch NATE::BaseException with {
                logcomment("$FILER_C : Filer is in CMODE, SSH connection is NOT proper");
            };
        } else {
            logcomment("Filer is NOT in CLI mode to set privilage as test");
        }
    }
    logcomment("Check for any un-owned drives");
    logcomment("@Nodes");
    assign_p1_p2_p3_drvs( Nodes => \@Node_obj );
}

sub set_ipspace_for_ports {
    my (%opts) = validate( @_, { Filer => { type => ARRAYREF }, } );
    my @filer_list = @{ $opts{Filer} };
    foreach my $filer (@filer_list) {
        my $Server         = new Server( no_cli => 1 );
        my $timeout        = "1900";
        my $ignore_strings = [ "MADIMM\\d+->", "DIMM\\d+->", "^T>" ];
        my $prompt_fw;

        # Retreive valid prompts from NATE
        my $host         = Tharn::host($filer);
        my $prompt_array = $host->prompt_fw();
        my $prompts      = join( "|", @$prompt_array );
        $prompt_fw = "($prompts)";
        $Server->set_execution_server( -Server => $filer );
        my $output = $Server->console(
            cmd                        => "net port show",
            additional_prompts_timeout => '120',
            ignore                     => $ignore_strings,
            additional_prompts         => {
                "$prompt_fw" => "FINAL_PROMPT",
                ".*::>.*"    => "FINAL_PROMPT",
            }
        );
        my @port_array;

        foreach my $line ( split /\n/, $output ) {
            if ( $line =~ /^e/ ) {
                logcomment("**DEBUG** : Port variable found ");
                if ( $line =~ /(\S+)\s+(\S+)\s+/ ) {
                    if ( $1 !~ /e0M/ ) {
                        logcomment("Setting Default for port $1");
                        $Server->console(
                            cmd                        => "net port modify -node $filer -Ipspace Default -port $1",
                            additional_prompts_timeout => '120',
                            ignore                     => $ignore_strings,
                            additional_prompts         => {
                                "$prompt_fw" => "FINAL_PROMPT",
                                ".*::>.*"    => "FINAL_PROMPT",
                            }
                        );
                    }
                }
            }
        }
    }
}

##################################################################################################
##	Auther 		- arjun.lavu@netapp.com
##	Description - This subroutine will list all the disk attached to the filer.
##	Usage 		- Mandatory paramanter - Node(single node object.
##  Return 		- Array of disk.
##	Compatibility	- This subroutine will work both in FILESYSTEM and MAINTENENCE mode CMode and 7Mode
##################################################################################################
sub list_of_disk {
    my (%opts) = validate( @_, { Node => { type => OBJECT }, } );

    my $Node        = $opts{Node};
    my $Mode        = $Node->mode();
    my $FILER_C     = $Node->name();
    my $Host        = host($FILER_C);
    my $Transit_obj = NACL::Transit->new( name => $FILER_C );
    my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    logcomment("DEBUG:Filer state is : $filer_state");
    my @disk_list;
    my $API_Object;

    if ( $filer_state =~ /MAINT/ ) {
        $API_Object = NACL::APISet->new(
            hostobj   => $Host,
            category  => "Node",
            interface => "CLI",
            set       => "Maintenance"
        );
        $API_Object->set_timeout( "connectrec-timeout" => 7200 );
        my $return = disk_list_data( API_Obj => $API_Object );
        @disk_list = keys(%$return);
    }
    if ( $filer_state =~ /CLI|UP/ ) {
        my $return = disk_show_v( Node => $Node );
        @disk_list = keys(%$return);
    }
    my $dsks = _print_array( \@disk_list );
    logcomment( "Total disks attached:\n" . $dsks );

    return @disk_list;    #BurtNo859428
}

##########################################################################################################
# Auther - arjun.lavu@netapp.com
# Description - Execute disk_qual t 12 for particuler disk.
# Supports - Cmode (Maintenance) 7Mode (Maintenance)
# Usage - Mandatory param ; API ; disk_attached_to_filer -> disk_list_local
# All => pass the values as 'all' if you want to run on all the drives
##########################################################################################################
sub run_disk_qual_t12 {
    my (%opts) = validate(
        @_,
        {
            API_Obj         => { type => OBJECT },
            disk_list_local => { type => ARRAYREF },
            All             => { type => SCALAR, default => undef, optional => 1 },
            WITHOUT_ADPT    => { type => SCALAR, default => undef, optional => 1 },
        }
    );
    my $API_obj          = $opts{API_Obj};
    my $FILER_C          = $API_obj->get_name();
    my $ALL              = $opts{All} if ( defined $opts{All} );
    my $adapt            = $opts{WITHOUT_ADPT} if ( defined $opts{WITHOUT_ADPT} );
    my @disk_array_local = @{ $opts{disk_list_local} };
    my ( $value, $command );
    my $params = NATE::ParamSet->new( global => 1 );
    my $SATA_SETUP = $params->get( 'SATA_SETUP', default => 'N' );
    $value = '-n 1' if ( $SATA_SETUP =~ /Y/i );
    my $result      = {};
    my $Transit_obj = NACL::Transit->new( name => $FILER_C );
    my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    logcomment("DEBUG:$FILER_C : Filer is in $filer_state ");

    if ( $filer_state =~ /CLI/i ) {
        if ($ALL) {
            $command = "priv set -q test;disk_qual start -t 12 $value -d all";
        } else {
            $command = "priv set -q test;disk_qual start -t 12 $value -d @disk_array_local";
        }
    } else {
        if ($ALL) {
            $command = "disk_qual start -t 12 $value -d all";
        } else {
            $command = "disk_qual start -t 12 $value -d @disk_array_local";
        }
    }
    my $wait_time = ( ( scalar @disk_array_local ) * 60 ) + 200;
    my $timeout = $API_obj->get_timeout();
    my $TIME_OUT;
    if ( $timeout > $wait_time ) {
        $TIME_OUT = $timeout;
    } else {
        $TIME_OUT = $wait_time;
    }
    if ( !%Non_Medium_Model ) {
        $API_obj->set_timeout( "connectrec-timeout" => $TIME_OUT );
        my $output = $API_obj->execute_command( 'command' => 'sysconfig -v', 'timeout' => 600 );
        my $flag = 0;
        foreach my $line ( split( "\n", $output ) ) {
            if ( $line =~ /ID\s+Vendor\s+Model\s+FW\s+Size/ig ) { $flag = 1; }
            if ( ( $line =~ /(\d+\.\w+)\s*\:\s*\S+\s*(\S+)\s*(\S+)\s*(\S+)\s*/ ) && ( $flag == 1 ) ) {
                my $model = $2;
                my $drive = $1;
                $Non_Medium_Model{$drive} = $model;
            }
        }
    }
    my $after = $API_obj->execute_raw_command( 'command' => "$command" );
    sleep(20);
    my $result              = {};
    my $result_without_adpt = {};
    my @lines               = split( /\n/, $after );
    my $cur_disk            = "";
    my $disk1               = "";
    my @drives              = ();
    my $var;

    foreach my $line (@lines) {
        if ( $line =~ /\[(\w+\.\w+\.\w+)]:\s+Non-medium Error Count\:\s+\d+\s+\[\w+\.\w+\.\w+]:\s+Log Sense page\s+(\w+)\s+\S+/ ) {
            push( @drives, $1 );
            $var = $2;
        }
    }
    logcomment( "**WARNING** : Log Sense page $var is NOT supported and it appeared " . scalar @drives . " times for the drives: @drives " ) if (@drives);

    foreach my $line (@lines) {
        if ( $line =~ /\[(\S+)\]:\s+Write ECC/ ) {
            $cur_disk = $1;
            if ( $cur_disk =~ /\w+\.(\w+\.\w+)/ ) { $disk1 = $1; $result_without_adpt->{$disk1} = {}; }
            $result->{$cur_disk} = {};
        } elsif ( $line =~ /\S+:(.*):\s+(\S+)/ ) {
            next if ( !defined( $result->{$cur_disk} ) );
            my $paramname = $1;
            my $paramval  = $2;
            $paramval =~ s/^\s+|\s+$//g;
            $paramname =~ s/^\s+|\s+$//g;
            $result_without_adpt->{$disk1}->{$paramname} = $paramval;
            $result->{$cur_disk}->{$paramname}           = $paramval;
        }
    } ## end foreach my $line (@lines)

    foreach my $line (@lines) {    #added by aditis
        if ( $after =~ /Attribute/i ) {
            my $line_new = $line;
            chop($line_new);
            if ( $line_new =~ /\[(\S+)\]:\s*(\w+):\s*(.*)/ ) {
                my $cur_disk  = $1;
                my $paramname = $2;
                my $paramval  = $3;
                $paramval =~ s/^\s+|\s+$//g;
                $paramname =~ s/^\s+|\s+$//g;
                $result->{$cur_disk}->{$paramname} = $paramval;
            }
        }
    } ## end foreach my $line (@lines)

    #812199_START
    my $result_1   = {};
    my $cur_disk_1 = "";
    my @void_test;
    my $Test = new TCD( -testcases => [ \@void_test ] );
    foreach my $line (@lines) {
        if ( $line =~ /\[(\S+)\]:\s+Write ECC OTF/ ) {
            my $cur_disk_ = $1;
            ($cur_disk_1) = $cur_disk_ =~ /(\d+\.\w+)/;
            $cur_disk_1 = "$cur_disk_1" . "\t";
            $result_1->{$cur_disk_1} = {};
        }
        if ( $line =~ /\S+:(.*):\s+(\S+)/ ) {
            my $paramname = $1;
            my $paramval  = $2;
            $paramval =~ s/^\s+|\s+$//g;
            $paramname =~ s/^\s+|\s+$//g;
            next if ( $paramname =~ /Total bytes proces|User remarks/ );
            $paramname = "Non-medium Error"   if ( $paramname =~ /Non-medium Error Count/ );
            $paramname = "Power on time(min)" if ( $paramname =~ /Power on time \(minutes\)/ );
            $result_1->{$cur_disk_1}->{$paramname} = $paramval;
        }
    }
    my @values     = ();
    my @names      = sort keys %{$result_1};
    my @activities = sort keys %{ $result_1->{ $names[0] } };
    $Test->nlog("PRINT SUMMARY");
    $Test->nlog("---------------------------------------------------------------------------------------------------------------------\n");
    $Test->nlog("\t\t\t\t\t@names\n");
    $Test->nlog("---------------------------------------------------------------------------------------------------------------------\n");

    foreach my $act (@activities) {
        foreach my $name (@names) {
            my $len   = $result_1->{$name}->{$act};
            my $count = $len =~ s/(.)/$1/sg;

            #    if ( $act =~ /Power on time/ ) {
            #        if ( $count < 6 ) {
            #            push( @values, " " );
            #        } else {
            #            push( @values, "" );
            #        }
            #    }
            push( @values, $result_1->{$name}->{$act} );

            if ( $act =~ /Non-medium Error/ ) {
                push( @values, "\t" );
            } elsif ( $act !~ /Power on time/ ) {
                push( @values, "\t  " );
            }

            #if ( $act !~ /Power on time/ ) {
            #    push( @values, "\t  " );
            # }
        }
        if ( $act =~ /Non-medium Error/ ) {
            $Test->nlog("$act\t@values\n");
        } elsif ( $act =~ /Power on time/ ) {
            $Test->nlog("$act @values\n");
        } elsif ( $act =~ /Total/ ) {
            $Test->nlog("$act    @values\n");
        } elsif ( ( $act =~ /Total/ ) && ( $act =~ /Total Write/ ) ) {
            $Test->nlog("$act  @values\n");
        } elsif ( ( $act =~ /Read ECC|Write ECC/ ) && ( $act !~ /OTF/ ) ) {
            $Test->nlog("$act\t\t\t   @values\n");
        } else {
            $Test->nlog("$act\t\t   @values\n");
        }
        @values = ();
    }

    #812199_END
    if   ( defined $adapt ) { return $result_without_adpt; }
    else                    { return $result; }

} ## end sub disk_qual_t12_cmode

##########################################################################################################
# Auther - arjun.lavu@netapp.com
# Description - Gives the list of all the disks of particular filer
# Usage -		CMODE(MAINT/CLI) 7Mode(MAINT/CLI)
##########################################################################################################
sub disk_show_drive_maint {
    my (%opts) = validate(
        @_,
        {
            API_Obj => { type => OBJECT },
            Filer   => { type => SCALAR },
        }
    );
    my $Api_Set_Obj = $opts{API_Obj};
    my $filer       = $opts{Filer};
    my ( $Mode, $cmd );
    my @temp_nodes = NACL::C::Node->find();

    #logcomment("Nodes @temp_nodes");
    foreach my $node (@temp_nodes) {
        my $FILER_C = $node->name();
        if ( $filer eq $FILER_C ) {
            $Mode = $node->mode();
            last;
        }
    }

    my $Host        = host($filer);
    my $transit_obj = NACL::Transit->new( name => $Host );
    my $filer_state = $transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    if ( ( $filer_state =~ /(UP|CLI)/i ) ) {
        $cmd = "run local disk show -a";
    } else {
        $cmd = "disk show -a";
    }
    $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
    my $dsk_output = $Api_Set_Obj->execute_raw_command( 'command' => "$cmd" );
    my @lines  = split( /\n/, $dsk_output );
    my @driveA = ();
    my @driveB = ();
    my %disk_filer;
    my $disk_values;

    foreach my $line (@lines) {
        if ( $line !~ /DISK|OWNER|POOL|SERIAL NUMBER|HOME/ ) {
            if ( ( $line =~ /(\S+)\s+$filer\s*\(\d+\)\s+(\S+)\s+(\S+)\s+(\S+)\s*\(\d+\)/ ) || ( $line =~ /(\S+)\s+$filer\(\S+\)\s+(\S+)\s+(\S+)\s+(\S+)/ ) || ( $line =~ /(\S+)\s+$filer\s*\(\S+\)\s+(\S+)\s+(\S+)/ ) ) {
                push( @driveA, $1 );
                $disk_filer{$1} = $filer;
            } elsif ( ( $line =~ /(\S+)\s+(\S+)\s*\(\d+\)\s+(\S+)\s+(\S+)\s+(\S+)\s*\(\d+\)/ ) || ( $line =~ /(\S+)\s+(\S+)\s*\(\d+\)\s+(\S+)\s+(\S+)\s+(\S+)/ ) || ( $line =~ /(\S+)\s+(\S+)\s*\(\d+\)\s+(\S+)\s+(\S+)/ ) ) {
                push( @driveB, $1 );
                $disk_filer{$1} = $2;
            }
        }
    }
    $disk_values = {
        'driveA' => [@driveA],
        'driveB' => [@driveB],
        %disk_filer
    };

    return ($disk_values);
}

##########################################################################################################
# Auther - Arjun.Lavu@netapp.com
# Description - This subroutine will stop the disk_qual process.
# Usage - Mandatory paramanter - Node , API_Obj
# Optional parameters  - disk_list which is array refrence of disks present in the particular Filer
# Return Value - 1 if passed, 0 if failed.
###########################################################################################################

sub disk_qual_abort {
    my (%opts) = validate(
        @_,
        {
            Node      => { type => OBJECT },
            API_Obj   => { type => OBJECT },
            disk_list => { type => ARRAYREF, optional => 1, default => undef },
            timeout   => { type => SCALAR, default => 1200, optional => 1 },
        }
    );
    my $Node        = $opts{Node};
    my $API_Obj     = $opts{API_Obj};
    my $FILER_C     = $API_Obj->get_name();
    my $timeout     = $opts{timeout};
    my $transit_obj = NACL::Transit->new( name => $FILER_C );
    my $filer_state = $transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    my ( $match, @disks );
    my $FILER_C = $Node->name();
    $API_Obj->set_timeout( "connectrec-timeout" => 7200 );

    #Checking the status of disk_qual
    my $match = $API_Obj->execute_raw_command( 'command' => "disk_qual status" );
    if ( $match =~ /disk_qual test failed/i ) {
        return (0);
    }
    if ( $match =~ /idle/ ) {
        logcomment("$FILER_C : disk qual is idle");
        return 1;
    }
    logcomment("$FILER_C : DISK QUAL is NOT idle, waiting for the 'disk_qual stop' to complete");
    if ( defined scalar @{ $opts{disk_list} } ) {
        my @disks_temp = @{ $opts{disk_list} };
        grep {
            if ( $_ !~ /P\d+/i ) { push( @disks, $_ ) }
        } @disks_temp;
        logcomment("Re-using the output from disk_list @disks");
    } else {
        my @disks_temp = @{ disk_show_drive_maint( API_Obj => $API_Obj, Filer => $FILER_C )->{'driveA'} };
        grep {
            if ( $_ !~ /P\d+/i ) { push( @disks, $_ ) }
        } @disks_temp;

        logcomment("The disk_qual is about to abort for @disks disks");
    }
    my $command = "disk_qual stop -d @disks";

    # $timeout = ((scalar(@disks) * 60 )+ 300);
    $API_Obj->set_timeout( "connectrec-timeout" => 18000 );
    my $dis_qua_stop = $API_Obj->execute_raw_command( 'command' => $command );
    logcomment("Waiting 120 seconds to get first prompt from 'disk_qual stop'");
    if ( $dis_qua_stop =~ /disk_qual not found/ ) {
        logcomment("**WARNING** : Filer : $FILER_C : disk_qual is NOT supported in the kernel");
        return (0);
    }
    sleep(120);
    $API_Obj->execute_raw_command( 'command' => "\013" );

    #***********************************************
    #setting the time out value
    #***********************************************

    my $kill_time = time + $timeout;
    while ( $kill_time > time ) {
        $API_Obj->execute_raw_command( 'command' => "rm /etc/diskqual_output" ) if ( $filer_state =~ /CLI|UP/ig );    #Burt1031268
        my $output = $API_Obj->execute_raw_command( 'command' => "disk_qual status" );
        sleep 10;
        my $status = $API_Obj->execute_raw_command( 'command' => "rdfile /etc/diskqual_output" ) if ( $filer_state =~ /CLI|UP/ig );    #Burt1031268
        $status .= $output;
        if ( $status !~ /idle/ ) {
            sleep 120;                                                                                                                 #waiting for 1 min and again checking the while loop condition
        } elsif ( $status =~ /disk_qual not found/ ) {
            logcomment("**WARNING** : Filer : $FILER_C : disk_qual is NOT supported in the kernel");
            return (0);
        } elsif ( $status =~ /idle/g ) {
            logcomment("disk_qual is stopped ");
            return (1);
        } else {
            if ( $kill_time < time ) {
                sleep 120;                                                                                                             #waiting for 1 min and again checking the while loop condition if time-out has not occurred
            } else {
                last;
            }
        }
    }
    ###################################################################################
    ##Checking again the status of disk_qual, if it is not idle return 0; else return 1;
    ###################################################################################
    my $stat = $API_Obj->execute_raw_command( 'command' => "rdfile /etc/diskqual_output" ) if ( $filer_state =~ /CLI|UP/ig );    #Burt1031268
    my $output1 = $API_Obj->execute_raw_command( 'command' => "disk_qual status" );
    sleep 10;
    $stat .= $output1;
    if ( $stat !~ /idle/g ) {
        return (0);
    } else {
        return (1);
    }
}

##########################################################################################################
# Auther - Arjun.Lavu@netapp.com
# Description - This subroutine will give particular disk of filer.
# Usage - Mandatory paramanter - Node , API_Obj, Test
# Supports - 7Mode (/Maint) Cmode (maint)
# Return Value - array of disk.
###########################################################################################################

sub get_disk_information {
    my (%opts) = validate(
        @_,
        {
            API_Obj => { type => OBJECT },
            Filer   => { type => SCALAR },
            Test    => { type => OBJECT, optional => 1, default => undef },
        }
    );
    my $sysid;
    my $Api_Set_Obj = $opts{API_Obj};
    my $filer       = $opts{Filer};
    my $Transit_obj = NACL::Transit->new( name => $filer );
    my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    my $Test        = $opts{Test};
    my ( @disk_show_disks, @failed_disks, $curr_adpt, $diskL, $cmd );
    my $sysconf_out;
    $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );

    if ( $filer_state =~ /CLI|UP/ ) {
        $sysconf_out = $Api_Set_Obj->execute_command( 'command' => "sysconfig -v" );
    }
    if ( $filer_state =~ /MAINT/ ) {
        $sysconf_out = $Api_Set_Obj->execute_raw_command( 'command' => "sysconfig -v" );
    }
    chomp( my @sysconf_lines = split( /\r?\n/, "$sysconf_out" ) );

    foreach my $i ( 0 .. $#sysconf_lines ) {
        if ( $sysconf_lines[$i] =~ /^\s+\S+\s+ID:\s+(\d+)/ ) {
            $sysid = $1;
        }
        if ( $sysconf_lines[$i] =~ /Host Adapter/ ) {
            my @temp_arr = split( /\s+/, $sysconf_lines[$i] );
            $curr_adpt = $temp_arr[6];
        } elsif ( $sysconf_lines[$i] =~ /Failed\)/ ) {
            my @temp_arr = split( /\s+/, $sysconf_lines[$i] );
            my $last_char_t = substr( $temp_arr[1], -1 );
            if ( $last_char_t =~ /\:/ ) {
                chop( $temp_arr[1] );
            }
            push( @failed_disks, "$curr_adpt.$temp_arr[1]" );
        }
    } ## end foreach my $i (0 .. $#sysconf_lines)
    if ( ( $sysid =~ /^\s$/ ) || ( $sysid eq '' ) || ( $curr_adpt =~ /^\s$/ ) || ( $curr_adpt eq '' ) ) {
        my $sysconf_out = $Api_Set_Obj->execute_raw_command( 'command' => "sysconfig -v" );
        chomp( my @sysconf_lines = split( /\r?\n/, "$sysconf_out" ) );
        foreach my $i ( 0 .. $#sysconf_lines ) {
            if ( $sysconf_lines[$i] =~ /^\s+\S+\s+ID:\s+(\d+)/ ) {
                $sysid = $1;
            }
            if ( $sysconf_lines[$i] =~ /Host Adapter/ ) {
                my @temp_arr = split( /\s+/, $sysconf_lines[$i] );
                $curr_adpt = $temp_arr[6];
            } elsif ( $sysconf_lines[$i] =~ /Failed\)/ ) {
                my @temp_arr = split( /\s+/, $sysconf_lines[$i] );
                my $last_char_t = substr( $temp_arr[1], -1 );
                if ( $last_char_t =~ /\:/ ) {
                    chop( $temp_arr[1] );
                }
                push( @failed_disks, "$curr_adpt.$temp_arr[1]" );
            }
        } ## end foreach my $i (0 .. $#sysconf_lines)
    }
    if ( ( $sysid =~ /^\s$/ ) || ( $sysid eq '' ) ) {
        my $after = $Api_Set_Obj->execute_raw_command( 'command' => "sysconfig -v" );
        if ( ( $after =~ /\s*System ID:\s+(\d+)\s+(.*)/ ) ) {
            $sysid = $1;
        }
    }
    if ( ( $sysid =~ /^\s$/ ) || ( $sysid eq '' ) ) {
        logcomment("**FAIL** :  System ID of the filer could NOT be captured through sysconfig -v and storage show initiators command. This may lead to FAILURE in further commands. Exiting from the script");
        logresult( 'FAIL', "SYSTEM ID OF THE FILER COULD NOT BE CAPTURED THROUGH sysconfig -v AND storage show initiators COMMAND. THIS MAY LEAD TO FAILURE IN FURTHER COMMANDS. Exiting from the script" );

    }
    if (@failed_disks) {
        my $prompts_answers = [ 'Are you sure you want to continue with disk unfail (y/n)?' => 'y' ];
        if ( $filer_state =~ /CLI/i ) {
            foreach my $dsk (@failed_disks) {
                $Api_Set_Obj->execute_command( 'command' => "disk unfail -s $dsk", 'connectrec-match_table' => $prompts_answers );
            }
        } else {
            foreach my $dsk (@failed_disks) {
                $Api_Set_Obj->execute_raw_command( 'command' => "disk unfail $dsk" );
            }
        }
    } ## end if (@failed_disks)
    if ( $sysid == 0 ) {
        my $output = $Api_Set_Obj->execute_raw_command( command => "storage show initiators" );
        foreach my $line ( split( /\n/, $output ) ) {
            if ( $line =~ /$filer\s+(\S+)/ ) {
                $sysid = $1;
                logcomment("Filer : $filer and System ID : $sysid");
            }
        }
    }
    $cmd = "disk show -s $sysid ";
    my $output = $Api_Set_Obj->execute_raw_command( 'command' => "$cmd" );

    # --------------------------------------------
    #  The empty list is considered as not an error.
    # ---------------------------------------------
    #
    if ( $output =~ /disk show: No disks match option/ ) {
        logcomment("NO DISK ATTACHED to the filer, $output") if ( ( $parse_id !~ /_PVT/ ) || ( $parse_id !~ /(_IVS|_SprayCore_T)/ ) || ( $GROUP_NO != 6 ) || ( $GROUP_NO != 7 ) );
        return @disk_show_disks;
    }
    if ( $output =~ /disk show:/ || $output !~ /DISK/ || $output eq "" || $output =~ /disk:/ ) {
        logcomment("Re trying the disk show command, did NOT see proper output");
        $cmd = "disk show -s $sysid ";
        my $output1 = $Api_Set_Obj->execute_raw_command( 'command' => "$cmd" );
        if ( $output1 =~ /disk show: No disks match option/ ) {
            logcomment("NO DISK ATTACHED to the filer, $output1") if ( ( $parse_id !~ /_PVT/ ) || ( $parse_id !~ /(_IVS|_SprayCore_T)/ ) || ( $GROUP_NO != 6 ) || ( $GROUP_NO != 7 ) );
            return @disk_show_disks;
        }
        if ( $output1 =~ /disk show:/ || $output1 !~ /DISK/ || $output1 eq "" || $output1 =~ /disk:/ ) {
            logcomment("DISK SHOW command FAILED to: $output");
            $Api_Set_Obj->execute_raw_command( 'command' => "" );
        }
    }

    my @lines = split( /\r*\n/, $output );

    # --------------------------------------------------------
    # removes the header lines
    # --------------------------------------------------------
    shift(@lines);
    shift(@lines);
    foreach (@lines) {
        s/^\s*//;
        if (/^(\S+)\s+\S+\s*\(/) {
            push( @disk_show_disks, $1 );
        } elsif (/^(\S+)\s*\(\S+\)\s*\S+/) {
            push( @disk_show_disks, $1 );
        }
    } ## end foreach (@lines)
    my $dsks = _print_array( \@disk_show_disks );
    logcomment( "Total Number of drives attached to filer $filer are " . scalar @disk_show_disks . " and the drives are:\n" . $dsks ) if (@disk_show_disks);
    logcomment("NO DRIVES are assigned to the filer $filer") if ( !@disk_show_disks );
    return @disk_show_disks;
}

#######################################################################################
##	author - Arjun.Lavu@netapp.com
##	applicable to ERT tests MAINTNENCE mode
##
##	sub check_ert_config()
##	Node -> required param
##	disk_list -> optional param [ARRAY reference of disks belongs to filer]
## 	ert_config -> path of ERT disks/platform file
##
#######################################################################################
sub check_ert_config {
    my (%opts) = validate(
        @_,
        {
            Node       => { type => OBJECT },
            disk_list  => { type => ARRAYREF },
            ert_config => { type => SCALAR, optional => 1, default => undef },
        }
    );
    my $Node    = $opts{Node};
    my $FILER_C = $Node->name();
    my $Home    = $ENV{HOME};
    my $ert_config;
    my @disk_array;
    my ( $min_drives, $max_drives, $found );
    if ( defined( $opts{ert_config} ) ) {
        $ert_config = $opts{ert_config};
    } else {
        $ert_config = "$Home/NDATE/ERT_CONFIG";
    }
    my $Host    = host($FILER_C);
    my $API_obj = NACL::APISet->new(
        hostobj   => $Host,
        category  => "Node",
        interface => "CLI",
        set       => "Maintenance"
    );
    $API_obj->set_timeout( "connectrec-timeout" => 7200 );
    my $sysconfig = sysconfig_v_data( node => $Node );
    my $model = $sysconfig->{model};
    open FH, "$ert_config" or die "Unable to open the file $ert_config";
    while () {
        next if ( $_ =~ /\#/ );
        if ( $_ =~ /$model\s+(\d+)\s+(\d+)/ ) {
            $min_drives = $1;
            $max_drives = $2;
            $found      = 1;
            last;
        }
    }
    close FH;
    if ( $found == 0 ) {
        logcomment("**FATAL** : $FILER_C -Filer model $model NOT present in the list, please fill the details in the file $ert_config and start agaign the test");
        logresult( 'FATAL', "$FILER_C :FILER MODEL $model NOT PRESENT IN THE LIST $ert_config" );
    }
    if ( defined $opts{disk_list} ) {
        @disk_array = @{ $opts{disk_list} };
    } else {
        @disk_array = get_disk_information(
            API_Obj => $API_obj,
            Filer   => $FILER_C
        );
    }
    if ( !scalar @disk_array ) {
        logcomment( "**FATAL** : Filer - $FILER_C : disks present are " . scalar @disk_array . " and the disks are @disk_array" );
        logresult( 'FATAL', " NO DRIVES PRESENT TO FILER $FILER_C" );
    }

    if ( ( scalar @disk_array < $min_drives ) || ( scalar @disk_array > $max_drives ) ) {
        logcomment( "**FAIL** : Number of drives available in the filer are " . scalar @disk_array . " but drives expected are between $min_drives and $max_drives for ERT test to continue" );
        logresult( 'FAIL', "Number of drives available in the filer are " . scalar @disk_array . "BUT DRIVES EXPECTED ARE BETWEEN $min_drives AND $max_drives FOR ERT TEST TO CONTINUE" );
        return 0;
    }
    return 1;
}
##########################################################################################################
# Auther -  arjunl
# Description - This subroutine will boot the filer 24/7 mode
###########################################################################################################
sub boot_in_twenty_four_seven_cmode {
    my (%opts) = validate( @_, { node => { type => OBJECT }, } );
    my $Node = $opts{node};
    destroy_root_volume( Noderef => [$Node] );
    clean_config( Node => $Node );
}
##########################################################################################################
# Auther -  arjunl
# Description - This subroutine will boot the filer 24/7 mode
###########################################################################################################
sub twenty_four_bar_seven {
    my (%opts) = validate( @_, { nodes => { type => ARRAYREF }, } );
    my @Nodes = @{ $opts{nodes} };
    disk_remv_assign_ownership( Node_ref => [@Nodes] );
    my @subtests;
    foreach my $Node (@Nodes) {
        my $FILER_C = $Node->name();
        push( @subtests, subtest( \&boot_in_twenty_four_seven_cmode, -runid, "boot_in_twenty_four_seven_cmode_" . "$FILER_C", -bg, "--", node => $Node, ) );
    }
    Subtest::wait_finish( subtest => [@subtests] );
    foreach my $Node (@Nodes) {
        my $Node_name  = $Node->name();
        my $Home       = $ENV{HOME};
        my $filer_info = `cat $Home/NDATE/FILER_INFO/$Node_name`;
        my $passwd;
        ($passwd) = $filer_info =~ /default_password\s*=\s*(\S+)\s*/ig;
        my $prompt_fw;
        my $wipeclean_timeout = 660;
        my $ignore_strings    = [ "MADIMM\\d+->", "DIMM\\d+->", "^T>" ];
        my $host              = Tharn::host($Node_name);
        my $prompt_array      = $host->prompt_fw();
        my $prompts           = join( "|", @$prompt_array );
        $prompt_fw = "($prompts)";
        logcomment("DEBUG:This is the prompt regex: $prompt_fw");
        logcomment("Disable cluster/HA pair");
        my $Server = new Server( no_cli => 1 );
        $Server->set_execution_server( -Server => $Node_name );
        my $Transit_obj = NACL::Transit->new( name => $Node_name );
        my $conn = $Transit_obj->{'conn'};
        $Transit_obj->set( 'timeout' => 600, maxcycle => 20 );
        $Transit_obj->set( 'change_state_timeout' => 7200 );
        $Transit_obj->change_state( to => "BOOT_MENU" );
        logcomment("DEBUG:$Node_name : Filer is in boot_state");
        logcomment("DEBUG:$Node_name : Creating Server object");
        my $Server = new Server( no_cli => 1 );
        my @filer_working = $Server->servers();
        logcomment("DEBUG:Filers we are working on : @filer_working");
        my $timeout = "3600";    # Change timeout in final code.
        my ( $s, $m, $h ) = gmtime($timeout);
        logcomment("DEBUG:Setting timeout : $timeout (i.e) $h Hours $m Minutes $s Seconds");
        logcomment("DEBUG:Set execution server");
        $Server->set_execution_server( -Server => $Node_name );    #set the execution server to the current node
        logcomment( "DEBUG:Boot _menu wipe clean util called " . scalar( localtime() ) );
        logcomment("DEBUG:Execution server set to $Node_name");
        logcomment("DEBUG:Disable password ");
        $Server->console( cmd => "options security.passwd.rules.everyone off", noprompt => 1 );
        eval { $Server->console( cmd => "24/7", additional_prompts_timeout => $timeout, ignore => $ignore_strings, additional_prompts => { ".*Install new file system without zeroing disks.*" => "yes", ".*REALLY install file system without zeroing disks.*" => "yes", ".*How many disks should be designated as spares.*" => "\n", ".*How many volumes.*" => "\n", ".*Number of RAID groups per volume.*" => "\n", ".*Type yes to confirm and continue.*" => "yes", ".*Enter the node management interface port.*" => "exit", ".*Do you want to create a new cluster or join an existing cluster.*" => "exit", ".*login.*" => "admin", ".*Password.*" => "$passwd", "::>" => "FINAL_PROMPT", "$prompt_fw" => "FINAL_PROMPT", "Selection " => "FINAL_PROMPT" } ); };

        my $timeout = "1900";
        my $ignore_strings = [ "MADIMM\\d+->", "DIMM\\d+->", "^T>" ];
        logcomment("Changing Node Name");
        try {
            $Server->console(
                cmd                        => "node rename -newname $Node_name",
                additional_prompts_timeout => $timeout,
                ignore                     => $ignore_strings,
                additional_prompts         => {
                    "$prompt_fw"   => "FINAL_PROMPT",
                    "::>"          => "FINAL_PROMPT",
                    "login"        => "admin",
                    ".*Password.*" => "$passwd",
                }
            );
            logcomment("Changed node name");
        }
        catch NACL::Transit::Exceptions::TransitException with {
            my $exception_object = shift;
            logcomment( "Exception is of type: " . ref($exception_object) );
            logcomment( "Error text is: " . $exception_object->text() );
        };
    }
    create_join_cluster( node_present => [@Nodes] );
}

################################################################################################################
## Author arjun.lavu@netapp.com
## Description :: this subroutine will check for multiple filer names under disk show -a output
#################################################################################################################

sub check_multiple_filer_names {
    my (%opts) = validate( @_, { Node => { type => OBJECT }, } );

    my $Node    = $opts{Node};
    my $Mode    = $Node->mode();
    my $FILER_C = $Node->name();
    my $Host    = host($FILER_C);

    #**************************************************
    #Checking the filer state
    #**************************************************
    my $Transit_obj = NACL::Transit->new( name => $FILER_C );
    my $filer_state;
    try {
        $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    }
    catch NACL::Transit::Exceptions::Timeout with {
        logcomment("Expected: Caught a Timeout Exception");
        $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    }
    catch NACL::Transit::Exceptions::TransitException with {
        my $exception_object = shift;
        logcomment( "Exception is of type: " . ref($exception_object) );
        logcomment( "Error text is: " . $exception_object->text() );
    };

    my ( $API_obj, $output, @lines );
    ##############################################
    ##Based on mode(UP/MAINT) API object is created
    ##############################################
    logcomment(" DEBUG: $FILER_C : Filer state is $filer_state");
    if ( $filer_state =~ /(CLI|UP)/ ) {
        $API_obj = $Node->get_7m_or_nodescope_apiset();
        $API_obj->set_timeout( "connectrec-timeout" => 7200 );
        logcomment(" DEBUG: $FILER_C : Executing  disk show -a");
        $output = $API_obj->execute_raw_command( 'command' => "run local disk show -a" );
    } else {
        $API_obj = NACL::APISet->new(
            hostobj   => $Host,
            category  => "Node",
            interface => "CLI",
            set       => "Maintenance"
        );
        $API_obj->set_timeout( "connectrec-timeout" => 7200 );
        logcomment("DEBUG: $FILER_C : Executing  disk show -a");
        $output = $API_obj->execute_raw_command( 'command' => "disk show -a" );
    }
    my $n = 0;
    my %result;
    @lines = split( /\n/, $output );

    # skip to the start of table contents
    while ( $n <= $#lines ) {
        $lines[$n] =~ s/^\s*//;
        last if ( $lines[$n] =~ /^-----/ );
        $n++;
    }
    $n++;
    foreach my $line ( @lines[ $n .. $#lines ] ) {
        $line =~ s/^\s*//;
        if ( $line =~ /^(\S+)\s+(\S+)\s*\((\S+)\)\s+/ ) {
            my ( $disk, $owner, $system_id, $pool, $serial_number ) = ( $line =~ /^(\S+)\s+(\S+)\s*\((\S+)\)\s+/ );
            push( @{ $result{$owner}{'DISK'} }, $disk );
            $result{$owner}{'SYSTEM_ID'} = $system_id;
        }
    }
    return %result;
}
####################################################################################################
#Author - Arjun Lavu
# Description :: Disk remove assigning in maintenance mode
####################################################################################################
sub remv_assign_ownership_maint {
    my (%opts) = validate(
        @_,
        {
            Node_ref         => { type => ARRAYREF },
            Test             => { type => OBJECT, default => undef, optional => 1 },
            disk_ref         => { type => ARRAYREF, default => undef, optional => 1 },
            assign_disk_to   => { type => OBJECT, default => undef, optional => 1 },
            remove_disk_from => { type => OBJECT, default => undef, optional => 1 },
        }
    );
    my @Nodes        = @{ $opts{Node_ref} };
    my $FILER_C      = $Nodes[0]->name();
    my $Test         = $opts{Test};
    my %Node_unowned = ();
    my ( @API_ARRAY, @Filer, @disks, $assign_api, $assign_node );
    my $Mode = $Nodes[0]->mode();
    if ( defined( $opts{disk_ref} ) ) {
        @disks = @{ $opts{disk_ref} };
    }

    my $disk_max_sup = 50;
    my $delay_time   = 120;
    my %Node_Api;
    my $Transit_obj = NACL::Transit->new( name => $FILER_C );
    my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    logcomment("Filer state $filer_state ");
    my @total_disks;
    foreach my $node (@Nodes) {
        my $FILER = $node->name();
        push( @Filer, $FILER );
        my $Host    = host($FILER);
        my $console = Tharn::connect("$FILER#console");

        # Set the properties for the Connectrec used for creating the APIset
        $console->{prompts}  = [qr/\*>/];
        $console->{max_idle} = "600";
        $console->{on_idle}  = sub { $console->execute(""); };
        my $API_obj = NACL::APISet->new(
            connection => $console,
            category   => "Node",
            interface  => "CLI",
            set        => "Maintenance"
        );
        $API_obj->set_timeout( "connectrec-timeout" => "7200" );
        $Node_Api{$node} = $API_obj;
        push( @API_ARRAY, $API_obj );
    }
    my $remove;
    my $unowned_disks;
    logcomment("Inside Remove assign ownership");
    my $sys_id;
    my $disk_list_result = disk_list_data( API_Obj => $API_ARRAY[0], );
    @total_disks = keys(%$disk_list_result);
    if ( !@total_disks ) {
        logcomment("**FATAL** : DISK_LIST result shows NO DISKS PRESENT in the filers, So exiting from the rest of test");
        logresult( 'FATAL', " DISK_LIST RESULT SHOWS NO DISKS PRESENT IN THE FILERS So exiting from the rest of test" );
    } else {
        my $disks = @total_disks;
        logcomment("Total number of disks available in the filers are $disks");
        if ( $disks < 6 ) {
            logcomment("**WARNING** : disks present in the filers are less than 6,\nit may lead to system PANIC if the filers are booted in filesystem mode");
        }
    }
    my %filer_ret = check_multiple_filer_names( Node => $Nodes[0] );

    # logcomment("Dumping ".Dumper(\%filer_ret));
    my @ret_filers = keys(%filer_ret);
    logcomment("Number of filers present in the system are @ret_filers");
    foreach (@ret_filers) {
        logcomment "------------------------------------------------------------------";
        my @drives = @{ $filer_ret{$_}{'DISK'} };
        logcomment("Drives assigned to the filer $_ are @drives");
        logcomment( "DEBUG:System ID of the filer $_ captured from the command disk show -a is " . $filer_ret{$_}{'SYSTEM_ID'} );
    }
    if ( !@ret_filers ) {
        logcomment("NO OWNER found for any of the drives in the system which could be either all the drives are UNOWNED \n or NO OWNER name found for the drives so releasing the ownership of drives");
        $API_ARRAY[0]->execute_raw_command( 'command' => "disk remove_ownership all -f" );
        sleep 60;
        $API_ARRAY[0]->execute_raw_command( 'command' => "disk remove_ownership all -f" );
        $API_ARRAY[0]->execute_raw_command( 'command' => "storage release disks -f" );
    }
    if ( scalar @ret_filers > 2 ) {
        logcomment("Filers found in the system are more than two, which is NOT acceptable so releasing the ownership of drives");
        $API_ARRAY[0]->execute_raw_command( 'command' => "disk remove_ownership all -f" );
        sleep 60;
        $API_ARRAY[0]->execute_raw_command( 'command' => "disk remove_ownership all -f" );
        $API_ARRAY[0]->execute_raw_command( 'command' => "storage release disks -f" );
    }
    $remove = scalar @total_disks;
    if ( ( $remove > 50 ) && ( $remove <= 100 ) ) {
        $delay_time = 180;
    } elsif ( ( $remove > 100 ) && ( $remove <= 150 ) ) {
        $delay_time = 250;
    } elsif ( ( $remove > 150 ) && ( $remove <= 200 ) ) {
        $delay_time = 300;
    } elsif ( $remove > 200 ) {
        $delay_time = 400;
    }

    if ( scalar @Nodes == 1 ) {
        my $params = NATE::ParamSet->new( global => 1 );
        my $LOGDIR      = $params->get( 'LOGDIR',      default => undef );
        my $TEST_CONFIG = $params->get( 'TEST_CONFIG', default => undef );
        my $FILER_NAMES = $params->get( 'FILER',       default => undef );
        my $FILER_B;
        my $FILER = $Nodes[0]->name();
        my @FILERS = split( /,/, $FILER_NAMES );
        foreach (@FILERS) {

            if ( $_ !~ /^$FILER$/ ) {
                $FILER_B = $_;
                last;
            }
        }

        my $Host   = host($FILER);
        my $Host_b = host($FILER_B);
        disable_debug_msg( Node => $Nodes[0] );

        # disable_dbg_msgs( host => $Host, filermode => "maint" );
        # disable_dbg_msgs( host => $Host_b, filermode => "maint" );
        logcomment("Only one node is passed : $FILER");
        my $API_obj        = $Node_Api{ $Nodes[0] };
        my @temp_disk_info = get_disk_information(
            API_Obj => $API_obj,
            Filer   => $FILER
        );
        logcomment( "Total drives present in the filer $FILER are " . scalar @temp_disk_info . " and the drives are @temp_disk_info" ) if (@temp_disk_info);
        $API_obj->execute_raw_command( 'command' => "\013" );

        # my $unowned = disk_show_n(Node =>$Nodes[0]);
        my @unowned_disks = keys %{ disk_show_n( Node => $Nodes[0] ) };
        my $dsks = _print_array( \@unowned_disks );
        logcomment( "Total Number of drives which are currently unassigned are " . scalar @unowned_disks . " and the drives are:\n" . $dsks ) if (@unowned_disks);
        logcomment("NO UN-ASSIGNED DRIVES are present") if ( !@unowned_disks );
        if (@unowned_disks) {
            my ( $sysid, $API_obj_B );
            {
                my $console = Tharn::connect("$FILER_B#console");

                #Set the properties for the Connectrec used for creating the APIset
                $console->{prompts}  = [qr/\*>/];
                $console->{max_idle} = 600;
                $console->{on_idle}  = sub { $console->execute(""); };
                $API_obj_B           = NACL::APISet->new(
                    connection => $console,
                    category   => "Node",
                    interface  => "CLI",
                    set        => "Maintenance"
                );
            }
            $API_obj->set_timeout( "connectrec-timeout" => 7200 );
            $API_obj_B->set_timeout( "connectrec-timeout" => 7200 );
            logcomment("DEBUG:Executing sysconfig -v to capture system ID");
            my $after = $API_obj->execute_raw_command( 'command' => "sysconfig -v" );
            if ( ( $after =~ /\s*System ID:\s+(\d+)\s+/ ) ) {
                $sysid = $1;
            } else {
                logcomment("**FATAL** : Could NOT find the SYSID for the filer $FILER");
                logresult( 'FATAL', "COULDN'T FIND THE SYSID FOR THE FILER $FILER" );
            }
            my ( @partition_drives, @container_drives );
            my $retry_assign = 0;
            if (@disks) {
                logcomment( "$FILER : Number of drives passed by the user to assign to the filer $FILER are " . scalar @disks . " and the drives are @disks" );
                my @drives_need_to_assign = commom_drives( [@unowned_disks], [@disks] );
                if (@drives_need_to_assign) {
                    logcomment( "$FILER : Out of these drives, number of drives which got unassigned are " . scalar @drives_need_to_assign . " and the drives are @drives_need_to_assign" );
                } else {
                    logcomment("$FILER : NO DRIVES are matched to unassigned drives");
                    return 0;
                }

                grep {
                    if   ( $_ =~ /P\d+$/ ) { push( @partition_drives, $_ ) }
                    else                   { push( @container_drives, $_ ) }
                } @drives_need_to_assign;
                @partition_drives = unique(@partition_drives);
                @container_drives = unique(@container_drives);
                if (@container_drives) {
                    my $dsks = _print_array( \@container_drives );
                    logcomment( "Total number of container drives which needs to be assigned to filer : $FILER are " . scalar @container_drives . " and the drives are:\n" . $dsks );
                }
                if (@partition_drives) {
                    my $dsks = _print_array( \@partition_drives );
                    logcomment( "Total number of partitioned drives which needs to be assigned to filer : $FILER are " . scalar @partition_drives . " and the drives are:\n" . $dsks );
                }
                if (@container_drives) {
                    my $disk_max_sup               = 40;
                    my @copy_drives_need_to_assign = @container_drives;
                    while (@copy_drives_need_to_assign) {
                        my $loop_no     = 0;
                        my @disk_list_q = ();
                        while ( $loop_no < $disk_max_sup ) {
                            push @disk_list_q, pop @copy_drives_need_to_assign;
                            $loop_no++;
                            last if ( !(@copy_drives_need_to_assign) );
                        }
                        logcomment("Assigning the drives @disk_list_q to filer $FILER");
                        $API_obj->execute_raw_command( 'command' => "disk assign @disk_list_q -o $FILER -s $sysid -f" );
                        sleep( ( @disk_list_q * 5 ) + 60 );
                        $API_obj->execute_raw_command( 'command' => "\013" );
                    }
                }
                if (@partition_drives) {
                    my $status   = disk_show_drive_maint( API_Obj => $API_obj, Filer => $FILER );
                    my @drives_A = @{ $status->{'driveA'} };
                    my @drives_B = @{ $status->{'driveB'} };
                    logcomment("Drives A @drives_A and drvies B @drives_B");
                    my %disk_api;
                    $disk_api{$FILER}   = $API_obj;
                    $disk_api{$FILER_B} = $API_obj_B;
                    my $prompts_answers = [ "Do you want to continue" => 'y' ];

                    foreach my $dsk (@partition_drives) {
                        ( my $tmp = $dsk ) =~ s/P\d+$//;
                        $disk_api{ $status->{$tmp} }->execute_raw_command( 'command' => "disk assign $dsk -o $FILER -s $sysid -f", 'connectrec-match_table' => $prompts_answers ) if ( $disk_api{ $status->{$tmp} } );
                        sleep 1;
                    }
                }

                # return 0;
            } else {
              ASSIGN:
                my @actual_disks;
                my ($actual_log_dir) = $LOGDIR =~ /(\S+)\/HDD/;
                my $disks_file = "$actual_log_dir" . "/Pre_post_Drives_Details_" . "$FILER";
                if ( -f $disks_file ) {
                    open( H_LOGFILE, "<$disks_file " ) or die ">>>>> read: Failed opening $disks_file <<<<<";
                    foreach my $line () {
                        chomp($line);
                        next if ( $line !~ /\S/ );
                        $line =~ s/(^\s+)|(\s+$)//ig;
                        push @actual_disks, $line;
                    }
                    close H_LOGFILE;
                    logcomment( "Drives which found in the file $disks_file are " . scalar @actual_disks . " and the drives are @actual_disks" ) if (@actual_disks);
                    my @drives_need_to_assign = commom_drives( [@unowned_disks], [@actual_disks] );
                    logcomment( "Out of un-owned drives, drives which are common are " . scalar @drives_need_to_assign . " and the drives are @drives_need_to_assign" );
                    if (@drives_need_to_assign) {
                        logcomment( "$FILER :: Out of these drives, number of drives which got unassigned are " . scalar @drives_need_to_assign . " and the drives are @drives_need_to_assign" );
                    } else {
                        logcomment("$FILER :: NO DRIVES are matched to unassigned drives");
                        return 0;
                    }
                    grep {
                        if   ( $_ =~ /P\d+$/ ) { push( @partition_drives, $_ ) }
                        else                   { push( @container_drives, $_ ) }
                    } @drives_need_to_assign;
                    if (@container_drives) {
                        my $dsks = _print_array( \@container_drives );
                        logcomment( "Total number container drives which need to assign the filer : $FILER are " . scalar @container_drives . " and the drives are:\n" . $dsks );
                    }
                    if (@partition_drives) {
                        my $dsks = _print_array( \@partition_drives );
                        logcomment( "Total number partitioned drives which need to assign the filer : $FILER are " . scalar @partition_drives . " and the drives are:\n" . $dsks );
                    }
                    if (@container_drives) {
                        my $disk_max_sup               = 40;
                        my @copy_drives_need_to_assign = @container_drives;
                        while (@copy_drives_need_to_assign) {
                            my $loop_no     = 0;
                            my @disk_list_q = ();
                            while ( $loop_no < $disk_max_sup ) {
                                push @disk_list_q, pop @copy_drives_need_to_assign;
                                $loop_no++;
                                last if ( !(@copy_drives_need_to_assign) );
                            }
                            logcomment("Assigning the drives @disk_list_q to filer $FILER");
                            $API_obj->execute_raw_command( 'command' => "disk assign @disk_list_q -o $FILER -s $sysid -f" );
                            sleep( ( @disk_list_q * 5 ) + 60 );
                            $API_obj->execute_raw_command( 'command' => "\013" );
                        }
                    }
                    if (@partition_drives) {
                        my $status   = disk_show_drive_maint( API_Obj => $API_obj, Filer => $FILER );
                        my @drives_A = @{ $status->{'driveA'} };
                        my @drives_B = @{ $status->{'driveB'} };
                        logcomment("Drives A @drives_A and drvies B @drives_B");
                        my %disk_api;
                        $disk_api{$FILER}   = $API_obj;
                        $disk_api{$FILER_B} = $API_obj_B;
                        my $prompts_answers = [ "Do you want to continue" => 'y' ];

                        foreach my $dsk (@partition_drives) {
                            ( my $tmp = $dsk ) =~ s/P\d+$//;
                            $disk_api{ $status->{$tmp} }->execute_raw_command( 'command' => "disk assign $dsk -o $FILER -s $sysid -f", 'connectrec-match_table' => $prompts_answers ) if ( $disk_api{ $status->{$tmp} } );
                            sleep 1;
                        }
                    }
                }
            }
            sleep 120;
            sleep 300 if ( $retry_assign < 1 );
            my $unassigned = disk_show_n( Node => $Nodes[0] );
            my @unassigned_disks = keys %$unassigned;
            if (@unassigned_disks) {
                if ( $retry_assign < 1 ) {
                    @unowned_disks = @unassigned_disks;
                    logcomment("Some more un-assigned disks are found. Trying to reassign once again");
                    $retry_assign++;
                    goto ASSIGN;
                } else {
                    logcomment("**FATAL** : CANNOT assign disks to filer $FILER");
                    logresult( 'FATAL', "CAN NOT ASSIGN DISKS TO FILER $FILER" );
                }
            } else {
                return 0;
            }
        } else {
            logcomment("NO UN-ASSIGNED DISKS found on the filer $FILER");
            return 0;
        }
    }

    if ( defined( $opts{assign_disk_to} ) ) {
        $assign_node = $opts{assign_disk_to};
        my $filer_assign = $assign_node->name();
        my $Host         = host($filer_assign);
        my $console      = Tharn::connect("$filer_assign#console");

        # Set the properties for the Connectrec used for creating the APIset
        $console->{prompts}  = [qr/\*>/];
        $console->{max_idle} = 600;
        $console->{on_idle}  = sub { $console->execute(""); };
        $assign_api          = NACL::APISet->new(
            connection => $console,
            category   => "Node",
            interface  => "CLI",
            set        => "Maintenance"
        );
        $assign_api->set_timeout( "connectrec-timeout" => 7200 );
        $assign_api->execute_raw_command( 'command' => "storage release disks -f" );
    }
    if ( ( defined( $opts{remove_disk_from} ) ) && ( defined( $opts{assign_disk_to} ) ) ) {    ##If remove_disk_from and assign_disk_to are defined then only
        my $remove_disk_node = $opts{remove_disk_from};                                        ## remove disks from remove_disk_from node
        my $filer_remove     = $remove_disk_node->name();

        my $console = Tharn::connect("$filer_remove#console");

        # Set the properties for the Connectrec used for creating the APIset
        $console->{prompts}  = [qr/\*>/];
        $console->{max_idle} = 600;
        $console->{on_idle}  = sub { $console->execute(""); };
        my $remove_disk_from_api = NACL::APISet->new(
            connection => $console,
            category   => "Node",
            interface  => "CLI",
            set        => "Maintenance"
        );
        $remove_disk_from_api->set_timeout( "connectrec-timeout" => 7200 );
        my $filer_name     = $remove_disk_from_api->get_name();
        my @temp_disk_info = get_disk_information(
            API_Obj => $remove_disk_from_api,
            Filer   => $filer_name
        );

        if (@temp_disk_info) {
            my $dsks = _print_array( \@temp_disk_info );
            logcomment( "Total number of drives assigned to filer : $filer_name are " . scalar @temp_disk_info . " and the drives are:\n" . $dsks ) if ( scalar @temp_disk_info );
            logcomment("NO DRIVES are assigned to the filer : $filer_name") if ( !@temp_disk_info );
            $remove_disk_from_api->execute_raw_command( 'command' => "storage release disks -f" );
            logcomment("Removing all disks :: $filer_name");

            # $remove_disk_from_api->execute_raw_command('command' => "disk show -a");
            $remove_disk_from_api->execute_raw_command( 'command' => "disk remove_ownership all -f" );
            sleep 120;
            $remove_disk_from_api->execute_raw_command( 'command' => "\013" );
            sleep 10;
            $remove_disk_from_api->execute_raw_command( 'command' => "\013" );
            $remove_disk_from_api->execute_raw_command( 'command' => "storage release disks -f" );
            my $drives = disk_show_drive_maint( API_Obj => $remove_disk_from_api, Filer => $filer_remove );
            if ( ( @{ $drives->{'driveA'} } ) || ( @{ $drives->{'driveB'} } ) ) {
                logcomment("DEBUG:Still few more drives are left");
                $remove_disk_from_api->execute_raw_command( 'command' => "disk remove_ownership all -f" );
                sleep 120;
                $remove_disk_from_api->execute_raw_command( 'command' => "\013" );
                sleep 10;
                $remove_disk_from_api->execute_raw_command( 'command' => "\013" );
                $remove_disk_from_api->execute_raw_command( 'command' => "storage release disks -f" );
            }
        } else {
            logcomment("NO DRIVES are assigned to filer : $filer_remove");
        }

    }
    if ($assign_api) {
        my $FILER = $assign_api->get_name();
        my @unassigned_disks = keys %{ disk_show_n( Node => $opts{remove_disk_from} ) };
        if ( !scalar @unassigned_disks ) {
            logcomment("NO UNASSIGNED DISKS are available on the filers");
            return 0;
        } else {
            my $Host = host($FILER);
            my ($sys_id);
            my $dsks = _print_array( \@unassigned_disks );
            logcomment( "Total number of un-assigned drives are " . scalar @unassigned_disks . " and the drives are:\n" . $dsks ) if (@unassigned_disks);
            logcomment("UN-ASSIGNED dirves are NOT available") if ( !@unassigned_disks );
            my $after = $assign_api->execute_raw_command( 'command' => "sysconfig" );
            if ( ( $after =~ /\s*System ID:\s+(\d+)\s+/ ) ) {
                $sys_id = $1;
            }
            logcomment("Assigning all the drives to filer :: $FILER ");
            my $cnt = 2;
            while ( $cnt > 0 ) {
                my $result = $assign_api->execute_raw_command( 'command' => "disk assign all -o $FILER -s $sys_id -f" );
                sleep($delay_time);
                if ( $result =~ /Assign failed/ ) {
                    logcomment("**FATAL** : $FILER : Disk assign is FAILED on the filer.  Exiting from the test.");
                    logresult( 'FATAL', "$FILER :  DISK ASSIGN IS FAILED ON THE FILER.  Exiting from the test." );
                }
                sleep( scalar @disks + 1 ) * 5;
                $assign_api->execute_raw_command( 'command' => "\013" );
                $assign_api->execute_raw_command( 'command' => "\013" );
                sleep 2;
                $assign_api->execute_raw_command( 'command' => "\013" );
                disable_debug_msg( Node => $assign_node );

                # disable_dbg_msgs( host => $Host, filermode => "maint" );
                @unassigned_disks = keys %{ disk_show_n( Node => $opts{remove_disk_from} ) };
                if ( !scalar @unassigned_disks ) {
                    return 0;
                } else {
                    $cnt--;
                    logcomment("$FILER : Some drives are NOT assigned, again trying to assign the drives");
                }
            }
            sleep 60;
            $assign_api->execute_raw_command( 'command' => "\013" );
            disable_debug_msg( Node => $assign_node );

            # disable_dbg_msgs( host => $Host, filermode => "maint" );
            @unassigned_disks = keys %{ disk_show_n( Node => $opts{remove_disk_from} ) };
            if ( scalar @unassigned_disks ) {
                logcomment("Could NOT assign disks to filer $FILER");
                return 1;
            } else {
                return 0;
            }
        }
    }
    ##If no parameters are passed excep Nodes and Api object
    my $FilerA     = $Nodes[0]->name();
    my $FilerB     = $Nodes[1]->name();
    my $HostA      = host($FilerA);
    my $HostB      = host($FilerB);
    my $Api_filerA = $Node_Api{ $Nodes[0] };
    my $Api_filerB = $Node_Api{ $Nodes[1] };

    # SAMSUNG ISSUE PATCH V2.1
    # $Api_filerB->execute_raw_command( 'command' => "storage release disks -f" );
    # $Api_filerA->execute_raw_command( 'command' => "storage release disks -f" );
    my $hash = {};
    my ( $sysid, $sysid_p );
    {
        my $after = $Api_filerA->execute_raw_command( 'command' => "sysconfig -v" );
        if ( $after =~ /\s*System ID:\s+(\d+)\s+/ ) {
            $sysid = $1;
        }
        $after = $Api_filerB->execute_raw_command( 'command' => "sysconfig -v" );
        if ( $after =~ /\s*System ID:\s+(\d+)\s+/ ) {
            $sysid_p = $1;
        }
    }
    logcomment("System ID of Filer $FilerA is: $sysid");
    logcomment("Partner ID of Filer $FilerB is: $sysid_p");

    my $disksA        = 0;
    my $disksB        = 0;
    my $unowned_disks = 0;
    my $filer_name;
    my $filer_nameA;
    my $filer_nameB;
    my @Filer_disksA = get_disk_information(
        API_Obj => $Api_filerA,
        Filer   => $FilerA,
    );
    $disksA = @Filer_disksA;
    my @Filer_disksB = get_disk_information(
        API_Obj => $Api_filerB,
        Filer   => $FilerB,
    );
    $disksB = @Filer_disksB;
    my $unowned = disk_show_n( Node => $Nodes[0] );
    my @unowned_disks = keys %$unowned;
    $unowned_disks = @unowned_disks;
    my $dsks = _print_array( \@unowned_disks );
    logcomment( " Total number of un-assigned disks are $unowned_disks and the disks are:\n" . $dsks ) if (@unowned_disks);
    logcomment("NO UN-ASSIGNED DRIVES found in the filer setup") if ( !@unowned_disks );
    logcomment(" Drives present in filer $FilerA - $disksA");
    logcomment(" Drives present in filer $FilerB - $disksB");

    if ( @unowned_disks > 0 ) {
        logcomment("**WARNING** : NO OWNER found for some of the drives :: @unowned_disks ");
    }
    my $numberAB = 0;
    my $numberA  = 0;
    my $numberB  = 0;
    my $number   = 0;

    my $disk_diff = abs( $disksA - $disksB );
    if ( $unowned_disks > 0 ) {
        my ( $sys_id, $filer_name_b );
        if ( $disk_diff > $unowned_disks ) {
            logcomment("Total disk difference $disk_diff which is greater than un-assigned disks $unowned_disks");
            if ( ( $disk_diff / 2 ) <= $unowned_disks ) {
                logcomment("1/2 of drives difference i.e $disk_diff is lesser than un-assigned drives $unowned_disks ");
                if ( $disksA > $disksB ) {
                    $filer_name   = $FilerB;
                    $filer_name_b = $FilerA;
                    $sys_id       = $sysid_p;
                } elsif ( $disksB > $disksA ) {
                    $filer_name   = $FilerA;
                    $filer_name_b = $FilerB;
                    $sys_id       = $sysid;
                }
                @unowned_disks = sort {
                    if ( ( $a =~ /P\d+/ ) && ( $b !~ /P\d+/ ) ) {
                        return 1;
                    } elsif ( ( $a !~ /P\d+/ ) && ( $b =~ /P\d+/ ) ) {
                        return -1;
                    } elsif ( ( $a =~ /P\d+/ ) && ( $b =~ /P\d+/ ) ) {
                        my ($tst1) = $a =~ /P(\d+)/;
                        my ($tst2) = $b =~ /P(\d+)/;
                        return $tst1 <=> $tst2;
                    } else {
                        return $a <=> $b;
                    }
                } @unowned_disks;
                my ( @partition_drives, @container_drives );
                grep {
                    if   ( $_ =~ /P\d+$/ ) { push( @partition_drives, $_ ) }
                    else                   { push( @container_drives, $_ ) }
                } @unowned_disks;
                if (@container_drives) {
                    my $dsks = _print_array( \@container_drives );
                    logcomment( "Total number container drives which need to assign the filer : $filer_name are " . scalar @container_drives . " and the drives are:\n" . $dsks );
                }
                if (@partition_drives) {
                    my $dsks = _print_array( \@partition_drives );
                    logcomment( "Total number partitioned drives which need to assign the filer : $filer_name are " . scalar @partition_drives . " and the drives are:\n" . $dsks );
                }
                if (@container_drives) {
                    my $disk_max_sup               = 40;
                    my @copy_drives_need_to_assign = @container_drives;
                    while (@copy_drives_need_to_assign) {
                        my $loop_no     = 0;
                        my @disk_list_q = ();
                        while ( $loop_no < $disk_max_sup ) {
                            push @disk_list_q, pop @copy_drives_need_to_assign;
                            $loop_no++;
                            last if ( !(@copy_drives_need_to_assign) );
                        }
                        logcomment("Assigning the drives @disk_list_q to filer $filer_name");
                        $Api_filerA->execute_raw_command( 'command' => "disk assign @disk_list_q -o $filer_name -s $sysid -f" );
                        sleep( ( @disk_list_q * 5 ) + 60 );
                        $Api_filerA->execute_raw_command( 'command' => "\013" );
                    }
                }
                if (@partition_drives) {
                    my $status   = disk_show_drive_maint( API_Obj => $Api_filerA, Filer => $filer_name );
                    my @drives_A = @{ $status->{'driveA'} };
                    my @drives_B = @{ $status->{'driveB'} };
                    my ( %disk_api, %disk_sys );
                    $disk_api{$FilerA} = $Api_filerA;

                    # $disk_sys{$FilerA} = $sysid;
                    $disk_api{$FilerB} = $Api_filerB;

                    # $disk_sys{$FilerA} =$sysid_p;
                    my $prompts_answers = [ "Do you want to continue" => 'y' ];
                    foreach my $dsk (@partition_drives) {
                        ( my $tmp = $dsk ) =~ s/P\d+$//;
                        $disk_api{ $status->{$tmp} }->execute_raw_command( 'command' => "disk assign $dsk -o $filer_name -s $sysid -f", 'connectrec-match_table' => $prompts_answers ) if ( $disk_api{ $status->{$tmp} } );
                        sleep 1;
                    }
                }
                $Api_filerA->execute_raw_command( 'command' => "disk show -a" );
            } else {
                logcomment("1/2 of drives difference i.e $disk_diff is greater than un-assigned drives drives $unowned_disks  ");
                $Api_filerA->execute_raw_command( 'command' => "disk remove_ownership all -f" );
                sleep 10;
                $Api_filerA->execute_raw_command( 'command' => "disk remove_ownership all -f" );
                $Api_filerA->execute_raw_command( 'command' => "storage release disks -f" );
                $Api_filerB->execute_raw_command( 'command' => "storage release disks -f" );
                sleep($delay_time);
                my $output = $Api_filerA->execute_raw_command( 'command' => "disk show -n" );

                if ( $output =~ /No disks match option -n|No unassigned disks/ ) {
                    logcomment("**FATAL** : Disk assign, remove ownership has NOT done properly");
                    logresult( "FATAL", "DISK ASSIGN, REMOVE OWNERSHIP HAS NOT DONE PROPERLY" );
                }
                my @free_drives = keys %{ disk_show_n( Node => $Nodes[0] ) };
                my ( @partition_drives, @container_drives, @assign_arr, %filer_details );
                grep {
                    if   ( $_ =~ /P\d+$/ ) { push( @partition_drives, $_ ) }
                    else                   { push( @container_drives, $_ ) }
                } @free_drives;
                if (@container_drives) {
                    my $dsks = _print_array( \@container_drives );
                    logcomment( "Total number of container drives are " . scalar @container_drives . " and the drives are:\n" . $dsks );
                }
                if (@partition_drives) {
                    my $dsks = _print_array( \@partition_drives );
                    logcomment( "Total number of partition drives are " . scalar @partition_drives . " and the drives are:\n" . $dsks );
                }
                logcomment("Removing and assigning disks between the filers as one of the filer is having less than 3 drives");

                if (@container_drives) {
                    my $unowned = @container_drives;
                    if ( $unowned % 2 == 0 ) {
                        $numberA = $unowned / 2;
                    } else {
                        $numberB = $unowned + 1;
                        $numberA = $numberB / 2;
                    }
                    my @numberA = @container_drives[ 0 .. ( $numberA - 1 ) ];
                    my @numberB = @container_drives[ $numberA .. $#container_drives ];
                    my $returnA = $Api_filerA->execute_raw_command( 'command' => "disk assign @numberA -o $FilerA -s $sysid -f" ) if (@numberA);
                    sleep($delay_time);
                    if ( $returnA =~ /Assign failed/ ) {
                        logcomment("**FATAL** : Disk assign is FAILED on the filer. exiting from the test.");
                        logresult( 'FATAL', "DISK ASSIGN IS FAILED ON THE FILER. exiting from the test." );
                    }
                    my $returnB = $Api_filerA->execute_raw_command( 'command' => "disk assign @numberB -o $FilerB -s $sysid_p -f" ) if (@numberB);
                    sleep($delay_time);
                    if ( $returnB =~ /Assign failed/ ) {
                        logcomment("**FATAL** : Disk assign is FAILED on the filer. Exiting from the test.");
                        logresult( 'FATAL', "DISK ASSIGN IS FAILED ON THE FILER. exiting from the test." );
                    }
                }

                if (@partition_drives) {
                    my $status = disk_show_drive_maint( API_Obj => $Api_filerA, Filer => $FilerA );

                    # print"dumping ".Dumper($status);
                    my @drives_A = @{ $status->{'driveA'} };
                    my @drives_B = @{ $status->{'driveB'} };
                    logcomment("Drives A @drives_A and drvies B @drives_B");
                    my $unowned = @partition_drives;
                    if ( $unowned % 2 == 0 ) {
                        $numberA = $unowned / 2;
                    } else {
                        $numberB = $unowned + 1;
                        $numberA = $numberB / 2;
                    }
                    my @numberA   = @partition_drives[ 0 .. ( $numberA - 1 ) ];
                    my @numberB   = @partition_drives[ $numberA .. $#partition_drives ];
                    my $num_A_ref = \@numberA;
                    my $num_B_ref = \@numberB;
                    $filer_details{$num_A_ref} = "-o $FilerA -s $sysid";
                    $filer_details{$num_B_ref} = "-o $FilerB -s $sysid_p";
                    my %disk_api;
                    $disk_api{$FilerA} = $Api_filerA;
                    $disk_api{$FilerB} = $Api_filerB;
                    my $prompts_answers = [ "Do you want to continue" => 'y' ];
                    push( @assign_arr, $num_A_ref ) if (@numberA);
                    push( @assign_arr, $num_B_ref ) if (@numberB);

                    foreach my $disk_ref (@assign_arr) {
                        my @drives = @{$disk_ref};

                        # logcomment("DEBUG:drives ::: @drives");
                        foreach my $dsk (@drives) {
                            ( my $tmp = $dsk ) =~ s/P\d+$//;
                            $disk_api{ $status->{$tmp} }->execute_raw_command( 'command' => "disk assign $dsk $filer_details{$disk_ref} -f", 'connectrec-match_table' => $prompts_answers ) if ( $disk_api{ $status->{$tmp} } );
                            sleep 1;
                        }
                    }
                }
                $Api_filerA->execute_raw_command( 'command' => "disk show -a" );
            }
        } else {
            logcomment("Total disk difference $disk_diff which is lesser than un-owned disks $unowned_disks");
            if ( $disksA < $disksB ) {
                $numberA = $disk_diff;
            } elsif ( $disksB < $disksA ) {
                $numberB = $disk_diff;
            }
            $number        = sprintf( "%d", ( ( $unowned_disks - $disk_diff ) / 2 ) );
            $numberA       = $numberA + $number;
            $numberB       = $numberB + $number;
            @unowned_disks = sort {
                if ( ( $a =~ /P\d+/ ) && ( $b !~ /P\d+/ ) ) {
                    return 1;
                } elsif ( ( $a !~ /P\d+/ ) && ( $b =~ /P\d+/ ) ) {
                    return -1;
                } elsif ( ( $a =~ /P\d+/ ) && ( $b =~ /P\d+/ ) ) {
                    my ($tst1) = $a =~ /P(\d+)/;
                    my ($tst2) = $b =~ /P(\d+)/;
                    return $tst1 <=> $tst2;
                } else {
                    return $a <=> $b;
                }
            } @unowned_disks;

            my ( @partition_drives, @container_drives, @assign_arr, %filer_details );
            grep {
                if   ( $_ =~ /P\d+$/ ) { push( @partition_drives, $_ ) }
                else                   { push( @container_drives, $_ ) }
            } @unowned_disks;
            if (@container_drives) {
                my $dsks = _print_array( \@container_drives );
                logcomment( "Total number of container drives are " . scalar @container_drives . " and the drives are:\n" . $dsks );
            }
            if (@partition_drives) {
                my $dsks = _print_array( \@partition_drives );
                logcomment( "Total number of partition drives are " . scalar @partition_drives . " and the drives are:\n" . $dsks );
            }
            logcomment("Removing and assigning disks between the filers as one of the filer is having NO drives");
            if (@container_drives) {
                my @drives  = @container_drives;
                my $unowned = @drives;
                if ( $unowned % 2 == 0 ) {
                    $numberA = $unowned / 2;
                } else {
                    $numberB = $unowned + 1;
                    $numberA = $numberB / 2;
                }
                my @numberA = @container_drives[ 0 .. ( $numberA - 1 ) ];
                my @numberB = @container_drives[ $numberA .. $#container_drives ];
                my $returnA = $Api_filerA->execute_raw_command( 'command' => "disk assign @numberA -o $FilerA -s $sysid -f" ) if (@numberA);
                sleep($delay_time);
                if ( $returnA =~ /Assign failed/ ) {
                    logcomment("**FATAL** : Disk assign is FAILED on the filer. Exiting from the test.");
                    logresult( 'FATAL', "DISK ASSIGN IS FAILED ON THE FILER. exiting from the test." );
                }
                my $returnB = $Api_filerA->execute_raw_command( 'command' => "disk assign @numberB -o $FilerB -s $sysid_p -f" ) if (@numberB);
                sleep($delay_time);
                if ( $returnB =~ /Assign failed/ ) {
                    logcomment("**FATAL** : Disk assign is FAILED on the filer. Exiting from the test.");
                    logresult( 'FATAL', "DISK ASSIGN IS FAILED ON THE FILER. exiting from the test." );
                }
            }
            if (@partition_drives) {
                my $status = disk_show_drive_maint( API_Obj => $Api_filerA, Filer => $FilerA );

                # print"dumping ".Dumper($status);
                my @drives_A = @{ $status->{'driveA'} };
                my @drives_B = @{ $status->{'driveB'} };

                # logcomment("Drives a @drives_A and drviesb @drives_B");
                my $unowned = @partition_drives;
                if ( $unowned % 2 == 0 ) {
                    $numberA = $unowned / 2;
                } else {
                    $numberB = $unowned + 1;
                    $numberA = $numberB / 2;
                }
                my @numberA   = @partition_drives[ 0 .. ( $numberA - 1 ) ];
                my @numberB   = @partition_drives[ $numberA .. $#partition_drives ];
                my $num_A_ref = \@numberA;
                my $num_B_ref = \@numberB;
                $filer_details{$num_A_ref} = "-o $FilerA -s $sysid";
                $filer_details{$num_B_ref} = "-o $FilerB -s $sysid_p";
                my %disk_api;
                $disk_api{$FilerA} = $Api_filerA;
                $disk_api{$FilerB} = $Api_filerB;
                my $prompts_answers = [ "Do you want to continue" => 'y' ];
                push( @assign_arr, $num_A_ref ) if (@numberA);
                push( @assign_arr, $num_B_ref ) if (@numberB);

                foreach my $disk_ref (@assign_arr) {
                    my @drives = @{$disk_ref};

                    # logcomment("DEBUG:drives ::: @drives");
                    foreach my $dsk (@drives) {
                        ( my $tmp = $dsk ) =~ s/P\d+$//;
                        $disk_api{ $status->{$tmp} }->execute_raw_command( 'command' => "disk assign $dsk $filer_details{$disk_ref} -f", 'connectrec-match_table' => $prompts_answers ) if ( $disk_api{ $status->{$tmp} } );
                        sleep 1;
                    }
                }
            }
            $Api_filerA->execute_raw_command( 'command' => "disk show -a" );
        }
    } elsif ( ( $disksA == 0 ) || ( $disksB == 0 ) ) {
        logcomment("DEBUG: Either the filers disks are zero and NO un-assigned disks are present");
        $Api_filerA->execute_raw_command( 'command' => "storage release disks -f" );       #1198255 sags
        $Api_filerA->execute_raw_command( 'command' => "storage release disks -f" );
        $Api_filerA->execute_raw_command( 'command' => "disk remove_ownership all -f" );
        sleep 5;
        $Api_filerA->execute_raw_command( 'command' => "disk remove_ownership all -f" );
        $Api_filerA->execute_raw_command( 'command' => "storage release disks -f" );
        $Api_filerB->execute_raw_command( 'command' => "storage release disks -f" );
        sleep($delay_time);
        my @unown_disks = keys %{ disk_show_n( Node => $Nodes[0] ) };
        my $unowned = @unown_disks;

        if ( $unowned < 1 ) {
            logcomment("**FATAL** : Disk assign, remove ownership has NOT done properly");
            logresult( 'FATAL', " DISK ASSIGN , REMOVE OWNERSHIP HAS NOT DONE PROPERLY" );
        }
        my $dsks = _print_array( \@unown_disks );
        logcomment( "Total number of un-owned disks are $unowned and the disks:\n" . $dsks ) if (@unown_disks);
        logcomment("NO UN-OWNED DRIVES available") if ( !@unown_disks );
        my ( @partition_drives, @container_drives, @assign_arr, %filer_details );
        grep {
            if   ( $_ =~ /P\d+$/ ) { push( @partition_drives, $_ ) }
            else                   { push( @container_drives, $_ ) }
        } @unown_disks;
        if (@container_drives) {
            my $dsks = _print_array( \@container_drives );
            logcomment( "Total number of container drives are " . scalar @container_drives . " and the drives are:\n" . $dsks );
        }
        if (@partition_drives) {
            my $dsks = _print_array( \@partition_drives );
            logcomment( "Total number of partition drives are " . scalar @partition_drives . " and the drives are:\n" . $dsks );
        }
        logcomment("Removing and assigning disks between the filers as one of the filer is having NO drives");
        if (@container_drives) {
            my @drives  = @container_drives;
            my $unowned = @drives;
            if ( $unowned % 2 == 0 ) {
                $numberA = $unowned / 2;
            } else {
                $numberB = $unowned + 1;
                $numberA = $numberB / 2;
            }
            my @numberA = @drives[ 0 .. ( $numberA - 1 ) ];
            my @numberB = @drives[ $numberA .. $#drives ];
            my $returnA = $Api_filerA->execute_raw_command( 'command' => "disk assign @numberA -o $FilerA -s $sysid -f" ) if (@numberA);
            sleep($delay_time);
            if ( $returnA =~ /Assign failed/ ) {
                logcomment("**FATAL** : Disk assign is FAILED on the filer. Exiting from the test.");
                logresult( 'FATAL', "DISK ASSIGN IS FAILED ON THE FILER. Exiting from the test." );
            }
            my $returnB = $Api_filerA->execute_raw_command( 'command' => "disk assign @numberB -o $FilerB -s $sysid_p -f" ) if (@numberB);
            sleep($delay_time);
            if ( $returnB =~ /Assign failed/ ) {
                logcomment("**FATAL** : Disk assign is FAILED on the filer. Exiting from the test.");
                logresult( 'FATAL', "DISK ASSIGN IS FAILED ON THE FILER. Exiting from the test." );
            }
        }
        if (@partition_drives) {
            my $status = disk_show_drive_maint( API_Obj => $Api_filerA, Filer => $FilerA );

            # print"dumping ".Dumper($status);
            my @drives_A = @{ $status->{'driveA'} };
            my @drives_B = @{ $status->{'driveB'} };
            logcomment("Drives A @drives_A and drvies B @drives_B");
            my $unowned = @partition_drives;
            if ( $unowned % 2 == 0 ) {
                $numberA = $unowned / 2;
            } else {
                $numberB = $unowned + 1;
                $numberA = $numberB / 2;
            }
            my @numberA   = @partition_drives[ 0 .. ( $numberA - 1 ) ];
            my @numberB   = @partition_drives[ $numberA .. $#partition_drives ];
            my $num_A_ref = \@numberA;
            my $num_B_ref = \@numberB;
            $filer_details{$num_A_ref} = "-o $FilerA -s $sysid";
            $filer_details{$num_B_ref} = "-o $FilerB -s $sysid_p";
            my %disk_api;
            $disk_api{$FilerA} = $Api_filerA;
            $disk_api{$FilerB} = $Api_filerB;
            my $prompts_answers = [ "Do you want to continue" => 'y' ];
            push( @assign_arr, $num_A_ref ) if (@numberA);
            push( @assign_arr, $num_B_ref ) if (@numberB);

            foreach my $disk_ref (@assign_arr) {
                my @drives = @{$disk_ref};
                logcomment("DEBUG:drives ::: @drives");
                foreach my $dsk (@drives) {
                    ( my $tmp = $dsk ) =~ s/P\d+$//;
                    $disk_api{ $status->{$tmp} }->execute_raw_command( 'command' => "disk assign $dsk $filer_details{$disk_ref} -f", 'connectrec-match_table' => $prompts_answers ) if ( $disk_api{ $status->{$tmp} } );
                    sleep 1;
                }
            }
        }
        $Api_filerA->execute_raw_command( 'command' => "disk show -a" );

    } elsif ( ( ( $disksA < int( ( scalar @total_disks ) / 2 ) ) || ( $disksB < int( ( scalar @total_disks ) / 2 ) ) ) ) {
        if ( ( abs( $disksA - $disksB ) ) > 2 ) {
            logcomment("One of the Filers disks are less than half of the total drives");
            $Api_filerA->execute_raw_command( 'command' => "disk remove_ownership all -f" );
            sleep 5;
            $Api_filerB->execute_raw_command( 'command' => "disk remove_ownership all -f" );
            $Api_filerA->execute_raw_command( 'command' => "storage release disks -f" );
            $Api_filerB->execute_raw_command( 'command' => "storage release disks -f" );
            sleep($delay_time);
            my $output = $Api_filerA->execute_raw_command( 'command' => "disk show -n" );

            if ( $output =~ /No disks match option -n|No unassigned disks/ ) {
                logcomment("**FATAL** : Disk assign , remove ownership has NOT done properly, please assign the disk manually to the filer");
                logresult( "FATAL", "DISK ASSIGN , REMOVE OWNERSHIP HAS NOT DONE PROPERLY , please assign the disk manually to the filer" );
            }
            my @free_drives = keys %{ disk_show_n( Node => $Nodes[0] ) };

            my ( @partition_drives, @container_drives, @assign_arr, %filer_details );
            grep {
                if   ( $_ =~ /P\d+$/ ) { push( @partition_drives, $_ ) }
                else                   { push( @container_drives, $_ ) }
            } @free_drives;
            if (@container_drives) {
                my $dsks = _print_array( \@container_drives );
                logcomment( "Total number of container drives are " . scalar @container_drives . " and the drives are:\n" . $dsks );
            }
            if (@partition_drives) {
                my $dsks = _print_array( \@partition_drives );
                logcomment( "Total number of partition drives are " . scalar @partition_drives . " and the drives are:\n" . $dsks );
            }
            if (@container_drives) {
                my @drives  = @container_drives;
                my $unowned = @drives;
                if ( $unowned % 2 == 0 ) {
                    $numberA = $unowned / 2;
                } else {
                    $numberB = $unowned + 1;
                    $numberA = $numberB / 2;
                }
                my @numberA = @drives[ 0 .. ( $numberA - 1 ) ];
                my @numberB = @drives[ $numberA .. $#drives ];
                my $returnA = $Api_filerA->execute_raw_command( 'command' => "disk assign @numberA -o $FilerA -s $sysid -f" ) if (@numberA);
                sleep($delay_time);
                if ( $returnA =~ /Assign failed/ ) {
                    logcomment("**FATAL** : Disk assign is FAILED on the filer. Exiting from the test.");
                    logresult( 'FATAL', "DISK ASSIGN IS FAILED ON THE FILER. Exiting from the test." );
                }
                my $returnB = $Api_filerA->execute_raw_command( 'command' => "disk assign @numberB -o $FilerB -s $sysid_p -f" ) if (@numberB);
                sleep($delay_time);
                if ( $returnB =~ /Assign failed/ ) {
                    logcomment("**FATAL** : Disk assign is FAILED on the filer. Exiting from the test.");
                    logresult( 'FATAL', "DISK ASSIGN IS FAILED ON THE FILER. Exiting from the test." );
                }
            }

            if (@partition_drives) {
                my $status = disk_show_drive_maint( API_Obj => $Api_filerA, Filer => $FilerA );

                # print"dumping ".Dumper($status);
                my @drives_A = @{ $status->{'driveA'} };
                my @drives_B = @{ $status->{'driveB'} };
                logcomment("Drives A @drives_A and drvies B @drives_B");
                my $unowned = @partition_drives;
                if ( $unowned % 2 == 0 ) {
                    $numberA = $unowned / 2;
                } else {
                    $numberB = $unowned + 1;
                    $numberA = $numberB / 2;
                }
                my @numberA   = @partition_drives[ 0 .. ( $numberA - 1 ) ];
                my @numberB   = @partition_drives[ $numberA .. $#partition_drives ];
                my $num_A_ref = \@numberA;
                my $num_B_ref = \@numberB;
                $filer_details{$num_A_ref} = "-o $FilerA -s $sysid";
                $filer_details{$num_B_ref} = "-o $FilerB -s $sysid_p";
                my %disk_api;
                $disk_api{$FilerA} = $Api_filerA;
                $disk_api{$FilerB} = $Api_filerB;
                my $prompts_answers = [ "Do you want to continue" => 'y' ];
                push( @assign_arr, $num_A_ref ) if (@numberA);
                push( @assign_arr, $num_B_ref ) if (@numberB);

                foreach my $disk_ref (@assign_arr) {
                    my @drives = @{$disk_ref};

                    # logcomment("DEBUG:drives ::: @drives");
                    foreach my $dsk (@drives) {
                        ( my $tmp = $dsk ) =~ s/P\d+$//;
                        $disk_api{ $status->{$tmp} }->execute_raw_command( 'command' => "disk assign $dsk $filer_details{$disk_ref} -f", 'connectrec-match_table' => $prompts_answers ) if ( $disk_api{ $status->{$tmp} } );
                        sleep 1;
                    }
                }
            }
            $Api_filerA->execute_raw_command( 'command' => "disk show -a" );
        }
    } else {
        logcomment("Disk are already assigned properly");
        return 0;
    }
}

####################################################################################################
#Author - Arjun Lavu
# Description :: Disk remove assigning in file-system mode
####################################################################################################
sub remv_assign_ownership_cli {
    my (%opts) = validate(
        @_,
        {
            Node_ref         => { type => ARRAYREF },
            disk_ref         => { type => ARRAYREF, default => undef, optional => 1 },
            assign_disk_to   => { type => OBJECT, default => undef, optional => 1 },
            remove_disk_from => { type => OBJECT, default => undef, optional => 1 },
            delete_aggr      => { type => SCALAR, default => undef, optional => 1 },
        }
    );
    my @Nodes = @{ $opts{Node_ref} };
    my @disks;
    my $assign_node;
    my $remove_disk_from;
    my $assign_api;
    my $remove_disk_from_api;
    my %Node_unowned;
    my @disk_A;
    my @disk_B;
    my @unassigned_disk;
    my @unowned;
    my @broken_disk_A;
    my @broken_disk_B;
    my @Total_spare;
    my $sysid_A;
    my $sysid_B;
    my $assign_filer_name;
    my $remove_disk_from_filer;
    logcomment("DEBUG:Inside remove assign ownership");
    my $params = NATE::ParamSet->new( global => 1 );
    my $Kernel = $params->get( 'KERNEL', default => 'FS' );
    my $Mode = $Nodes[0]->mode();

    if ( defined( $opts{disk_ref} ) ) {
        @disks = @{ $opts{disk_ref} };
    }
    foreach my $Node (@Nodes) {
        my $Mode = $Node->mode();
        diag_password_change_cmode( Node_ref => [$Node] );
    }

    if ( scalar @Nodes == 1 ) {
        my $params = NATE::ParamSet->new( global => 1 );
        my $LOGDIR      = $params->get( 'LOGDIR',      default => undef );
        my $TEST_CONFIG = $params->get( 'TEST_CONFIG', default => undef );
        logcomment( "Only one filer " . $Nodes[0]->name() . " is present" );
        my $FILER_C = $Nodes[0]->name();

        #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        #Checking whether any broken disks in CMode or FAILED disks in 7Mode present, if present unfailing them to spare drives
        {
            my @broken;
            try {
                my %hash = ( filter => { 'container-type' => "broken", 'owner' => $FILER_C } );
                my @broken_obj = NACL::C::Disk->find(
                    command_interface => $Nodes[0],
                    %hash,
                );
                foreach my $state_obj (@broken_obj) {
                    my $free_disk = $state_obj->disk();
                    if ( $free_disk =~ /(\S+)\:(\S+)/ ) {
                        $free_disk = $2;
                    }
                    push( @broken, $free_disk );
                }
                if (@broken) {
                    my $dsks = _print_array( \@broken );
                    logcomment( "$FILER_C : Number of broken disks are " . scalar @broken . " and the disks are:\n" . $dsks );
                }
            }
            catch NACL::Exceptions::NoElementsFound with {
                logcomment("$FILER_C : NO BROKEN DISKS found for the filer");
            };
            foreach my $boken (@broken) {
                try {
                    NACL::C::StorageDisk->unfail(
                        command_interface => $Nodes[0],
                        disk              => $boken,
                        spare             => "true",
                        'method-timeout'  => 1200
                    );
                }
                catch NACL::APISet::Exceptions::CommandFailedException with {
                    my $Filer = $Nodes[0]->name();
                    logcomment("**WARNING** : $Filer : Could NOT unfail the disk $boken");
                }
                catch NATE::BaseException with {
                    logcomment("Unfailing the drive is interupted, may be because of timeout issue, So trying again to unafail after 5 minutes");
                    sleep 300;
                    try {
                        NACL::C::StorageDisk->unfail(
                            command_interface => $Nodes[0],
                            disk              => $boken,
                            spare             => "true",
                            'method-timeout'  => 1200
                        );
                    }
                    catch NATE::BaseException with {
                        logcomment("Unfailing the drive is NOT successfull");
                    };
                };
            }
        }

        #****************************************************************************************
        #Check for any un-assigned disks
        #****************************************************************************************
        my @disk_obj_unown = NACL::C::Disk->find(
            command_interface => $Nodes[0],
            filter            => { owner => "-" },
            allow_empty       => 1,
        );
        foreach my $state_obj (@disk_obj_unown) {
            my $free_disk = $state_obj->disk();
            if ( $free_disk =~ /(\S+)\:(\S+)/ ) {
                $free_disk = $2;
            }
            push( @unassigned_disk, $free_disk );
        }
        my $dsks = _print_array( \@unassigned_disk );
        logcomment( "Number of container un-assigned drives are " . scalar @unassigned_disk . " and the drives are:\n" . $dsks ) if (@unassigned_disk);
        logcomment("NO CONTAINER UN-ASSIGNED DRIVES found") if ( !@unassigned_disk );
        my @temp_part;
        if ( $Kernel =~ /FS/i ) {
            try {
                logcomment("DEBUG:Checking for partitioned unowned drives if present");
                my @disk_obj = NACL::CS::StorageDiskPartition->fetch(
                    command_interface => $Nodes[0],
                    filter            => { "owner-node-name" => "-" },
                    requested_fields  => [qw(partition)],
                    allow_empty       => 1,
                );
                foreach (@disk_obj) {
                    push( @temp_part, $_->partition() );
                }
                my $dsks = _print_array( \@temp_part );
                logcomment( "Number of un-assigned partition drives found are " . scalar @temp_part . " and the drives are:\n" . $dsks ) if (@temp_part);
                logcomment("NO UN-ASSIGNED PARTITION DRIVES found") if ( !@temp_part );
            }
            catch NACL::Exceptions::NoElementsFound with {
                logcomment("NO UN-ASSIGNED PARTITIONED DRIVES found in the filer $FILER_C");
            };
            push( @unassigned_disk, @temp_part ) if (@temp_part);
        }
        my $dsks = _print_array( \@unassigned_disk );
        logcomment( "Total number of unassiged disks are " . scalar @unassigned_disk . " and the disks are:\n" . $dsks ) if (@unassigned_disk);
        logcomment("NO UNASSIGNED DISKS available") if ( !@unassigned_disk );
        if (@unassigned_disk) {
            my $remove_disk_from_api = $Nodes[0]->get_7m_or_nodescope_apiset();
            $remove_disk_from_api->set_timeout( "connectrec-timeout" => 7200 );
            my $sysid;
            if ( $Mode =~ /CMode/ ) {
                my $return = $remove_disk_from_api->execute_raw_command( 'command' => "system node show -fields systemid -node $FILER_C" );
                if ( $return =~ /$FILER_C(\D*)(\d+)(\D*)/ ) {
                    $sysid = $2;
                }
            } else {
                my $return = $remove_disk_from_api->execute_raw_command( 'command' => "sysconfig -v" );
                if ( $return =~ /\s*System(\D*)ID:(\D*)(\d+)(\D*)/ ) {
                    $sysid = $3;
                }
            }
            if (@disks) {
                my $dsks = _print_array( \@disks );
                logcomment( "$FILER_C : Drives passed by the user to assign to the filer $FILER_C are " . scalar @disks . " and the drives are:\n" . $dsks );
                my @drives_need_to_assign = commom_drives( [@unassigned_disk], [@disks] );
                my $dsks = _print_array( \@drives_need_to_assign );
                logcomment( "$FILER_C : Out of these drives, drives which got unassigned are " . scalar @drives_need_to_assign . " and the drives are:\n" . $dsks );
                if (@drives_need_to_assign) {
                    logcomment("Assigning the drives @drives_need_to_assign to filer $FILER_C");
                    foreach my $disk (@drives_need_to_assign) {
                        if ( $disk !~ /P\d+$/ ) {
                            try {
                                NACL::C::StorageDisk->assign(
                                    command_interface => $Nodes[0],
                                    owner             => $FILER_C,
                                    disk              => $disk,
                                    sysid             => $sysid,
                                    force             => 'true',
                                    'method-timeout'  => 1200
                                );
                            }
                            catch NACL::APISet::Exceptions::CommandFailedException with {
                                logcomment("**WARNING** : $disk is NOT assigned to filer $FILER_C");
                            }
                            catch NATE::BaseException with {
                                sleep 120;
                                logcomment("DEBUG:May be the timeout exception");
                                my $API = $Nodes[0]->get_7m_or_nodescope_apiset();
                                $API->set_timeout( "connectrec-timeout" => 7200 );
                                $API->execute_command( 'command' => "disk show -a" );
                            };
                        } else {
                            try {
                                NACL::C::StorageDiskPartition->assign(
                                    command_interface => $Nodes[0],
                                    partition         => $disk,
                                    owner             => $FILER_C,
                                    sysid             => $sysid,
                                    force             => 'true',
                                    'method-timeout'  => 1200
                                );
                            }
                            catch NACL::APISet::Exceptions::CommandFailedException with {
                                logcomment("**WARNING** : Partitioned $disk is NOT assigned to filer $FILER_C");
                            };
                        }
                    }

                    # return 0;
                } else {
                    logcomment("$FILER_C : NO DRIVES are matched to unassigned drives");
                }
                return 0;
            } else {
                my @actual_disks;
                my ($actual_log_dir) = $LOGDIR =~ /(\S+)\/HDD/;
                my $disks_file = "$actual_log_dir" . "/Pre_post_Drives_Details_" . "$FILER_C";
                if ( -f $disks_file ) {
                    open( H_LOGFILE, "<$disks_file " ) or die ">>>>> read: Failed opening $disks_file <<<<<";
                    foreach my $line () {
                        chomp($line);
                        $line =~ s/(^\s+)|(\s+$)//ig;
                        next if ( $line !~ /\S/ );
                        push @actual_disks, $line;
                    }
                    close H_LOGFILE;
                    my $dsks = _print_array( \@actual_disks );
                    logcomment( "Drives which found in the file $disks_file are:\n" . $dsks );
                    my @drives_need_to_assign = commom_drives( [@unassigned_disk], [@actual_disks] );
                    if (@drives_need_to_assign) {
                        foreach my $disk (@drives_need_to_assign) {
                            my $dsks = _print_array( \@drives_need_to_assign );
                            logcomment( "Out of the un-owned drives, drives which are common are ::\n" . $dsks );
                            logcomment("Assigning the drives @drives_need_to_assign to the Filer ::: $FILER_C");
                            if ( $disk !~ /P\d+$/ ) {
                                try {
                                    NACL::C::StorageDisk->assign(
                                        command_interface => $Nodes[0],
                                        owner             => $FILER_C,
                                        disk              => $disk,
                                        sysid             => $sysid,
                                        force             => 'true',
                                        'method-timeout'  => 1200
                                    );
                                }
                                catch NACL::APISet::Exceptions::CommandFailedException with {
                                    logcomment("**WARNING** : $disk is NOT assigned to filer $FILER_C");
                                };
                            } else {
                                try {
                                    NACL::C::StorageDiskPartition->assign(
                                        command_interface => $Nodes[0],
                                        partition         => $disk,
                                        owner             => $FILER_C,
                                        sysid             => $sysid,
                                        force             => 'true',
                                        'method-timeout'  => 1200
                                    );
                                }
                                catch NACL::APISet::Exceptions::CommandFailedException with {
                                    logcomment("**WARNING** :: Partitioned disk $disk is NOT assigned to filer $FILER_C");
                                };
                            }
                        }
                    } else {
                        logcomment("$FILER_C : NO DRIVES are matched to unassigned drives when compared to file : $disks_file");
                    }
                    return 0;
                }
            }

            if (@disk_obj_unown) {
                try {
                    NACL::C::StorageDisk->assign(
                        command_interface => $Nodes[0],
                        all               => 'true',
                        node              => $Nodes[0],
                        force             => 'true',
                        'method-timeout'  => 1200
                    );
                }
                catch NACL::APISet::Exceptions::CommandFailedException with {
                    my $Filer = $Nodes[0]->name();
                    logcomment("**WARNING** : $Filer : Some of the disks are NOT assigned");
                };
            }

            if (@temp_part) {
                try {
                    NACL::C::StorageDiskPartition->assign(
                        command_interface => $Nodes[0],
                        all               => 'true',
                        node              => $Nodes[0],
                        force             => 'true',
                        'method-timeout'  => 1200
                    );
                }
                catch NACL::APISet::Exceptions::CommandFailedException with {
                    my $Filer = $Nodes[0]->name();
                    logcomment("**WARNING** :: $Filer : Some of the partitioned are NOT assigned");
                };
                return 0;
            }
        } else {
            logcomment("NO UN-ASSIGNED DISKS found in the filers");
            return 0;
        }

        #****************************************************************************************
    }

    if ( defined( $opts{assign_disk_to} ) ) {
        $assign_node       = $opts{assign_disk_to};
        $assign_filer_name = $assign_node->name();
        $assign_api        = $assign_node->get_7m_or_nodescope_apiset();
        $assign_api->set_timeout( "connectrec-timeout" => 7200 );
        if ( $Mode =~ /CMode/i ) {
            $assign_api->execute_raw_command( 'command' => "storage disk option modify -node $assign_filer_name -autoassign off" );
        } else {
            $assign_api->execute_raw_command( 'command' => "options disk.auto_assign off" );
        }
    }

    #------------------------------------------------------------------
    if ( defined( $opts{remove_disk_from} ) ) {
        $remove_disk_from     = $opts{remove_disk_from};
        $remove_disk_from_api = $remove_disk_from->get_7m_or_nodescope_apiset();
        $remove_disk_from_api->set_timeout( "connectrec-timeout" => 7200 );
        $remove_disk_from_filer = $remove_disk_from->name();
        if ( $Mode =~ /CMode/ ) {
            $remove_disk_from_api->execute_raw_command( 'command' => "storage disk option modify -node $remove_disk_from_filer -autoassign off" );
        } else {
            $remove_disk_from_api->execute_raw_command( 'command' => "options disk.auto_assign off" );
        }
    }
    if ( ($remove_disk_from_filer) && ($assign_filer_name) ) {    ##If remove_disk_from and assign_disk_to are defined then only
        my @disk_obj;                                             ## remove disks from remove_disk_from node
        my @unowned_remove;
        my @spare_remove;

        #deleting aggregates from the node where spare disks has to be removed
        #vserver_delete(Node => $remove_disk_from) if($Mode =~/CMode/i);
        aggregate_volume_delete( Node => $remove_disk_from );

        #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        #Checking whether any broken disks in CMode or FAILED disks in 7Mode present, if present unfailing them to spare drives
        {
            my $type = "broken" if ( $Mode =~ /CMode/i );
            try {
                my %hash = ( filter => { 'container-type' => "broken", 'owner' => $remove_disk_from_filer } );
                my @broken_obj = NACL::C::Disk->find(
                    command_interface => $remove_disk_from,
                    %hash,
                );
                foreach my $state_obj (@broken_obj) {
                    my $free_disk = $state_obj->disk();
                    if ( $free_disk =~ /(\S+)\:(\S+)/ ) {
                        $free_disk = $2;
                    }
                    push( @broken_disk_B, $free_disk );
                }
                if (@broken_disk_B) {
                    my $dsks = _print_array( \@broken_disk_B );
                    logcomment( "$remove_disk_from_filer : Number of broken disks are " . scalar @broken_disk_B . " and the disks are:\n" . $dsks );
                }
            }
            catch NACL::Exceptions::NoElementsFound with {
                logcomment("$remove_disk_from_filer : NO BROKEN DISKS found for the filer");
            };
            foreach my $boken (@broken_disk_B) {
                try {
                    NACL::C::StorageDisk->unfail(
                        command_interface => $remove_disk_from,
                        disk              => $boken,
                        spare             => "true",
                        'method-timeout'  => 1200
                    );
                }
                catch NACL::APISet::Exceptions::CommandFailedException with {
                    my $Filer = $remove_disk_from->name();
                    logcomment("**WARNING** : $Filer : Could NOT unfail the disk $boken");
                }
                catch NATE::BaseException with {
                    my $Filer = $remove_disk_from->name();
                    logcomment("**WARNING** : $Filer : Unfailing the drive is interupted, may be because of timeout issue, So trying again to unafail after 5 minutes");
                    sleep 300;
                    try {
                        NACL::C::StorageDisk->unfail(
                            command_interface => $remove_disk_from,
                            disk              => $boken,
                            spare             => "true",
                            'method-timeout'  => 1200
                        );
                    }
                    catch NATE::BaseException with {
                        logcomment("$Filer : Unfailing the drive is NOT successfull!!!");
                    };
                };
            }
        }

        {
            my $type = "broken" if ( $Mode =~ /CMode/i );
            try {
                my %hash = ( filter => { 'container-type' => "broken", 'owner' => $assign_filer_name } );
                my @broken_obj = NACL::C::Disk->find(
                    command_interface => $assign_node,
                    %hash,
                );
                foreach my $state_obj (@broken_obj) {
                    my $free_disk = $state_obj->disk();
                    if ( $free_disk =~ /(\S+)\:(\S+)/ ) {
                        $free_disk = $2;
                    }
                    push( @broken_disk_A, $free_disk );
                }
                if (@broken_disk_A) {
                    my $dsks = _print_array( \@broken_disk_A );
                    logcomment( "$assign_filer_name : Number of broken disks are " . scalar @broken_disk_A . " and the disks are:\n" . $dsks );
                }
            }
            catch NACL::Exceptions::NoElementsFound with {
                logcomment("$assign_filer_name : NO BROKEN DISKS found for the filer");
            };

            foreach my $boken (@broken_disk_A) {
                try {
                    NACL::C::StorageDisk->unfail(
                        command_interface => $assign_node,
                        disk              => $boken,
                        spare             => "true",
                        'method-timeout'  => 1200
                    );
                }
                catch NACL::APISet::Exceptions::CommandFailedException with {
                    my $Filer = $assign_node->name();
                    logcomment("**WARNING** : $Filer : Could NOT unfail the disk $boken");
                }
                catch NATE::BaseException with {
                    my $Filer = $assign_node->name();
                    logcomment("**WARNING** :$Filer : Unfailing the drive is interrupted, may be because of timeout issue, So trying again to unafail after 5 minutes");
                    sleep 300;
                    try {
                        NACL::C::StorageDisk->unfail(
                            command_interface => $assign_node,
                            disk              => $boken,
                            spare             => "true",
                            'method-timeout'  => 1200
                        );
                    }
                    catch NATE::BaseException with {

                        logcomment("**WARNING** : $Filer :: Unfailing the drive is NOT successfull");
                    };
                };
            }
        }

        #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

        ##$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
        #Check for any un-owned disks and assign back them to its parent node

        try {
            my %hash = ( filter => { 'container-type' => "unknown", 'home' => $remove_disk_from_filer } );
            my @unown;
            my @unowned_obj = NACL::C::Disk->find(
                command_interface => $remove_disk_from,
                %hash,
            );
            foreach my $state_obj (@unowned_obj) {
                my $free_disk = $state_obj->disk();
                if ( $free_disk =~ /(\S+)\:(\S+)/ ) {
                    $free_disk = $2;
                }
                push( @unown, $free_disk );
            }
            if (@unown) {
                push( @unowned_remove, @unown );    #Total unowned disks
                logcomment("$remove_disk_from_filer : Unowned disks are @unown");
            }
        }
        catch NACL::Exceptions::NoElementsFound with {
            logcomment("$remove_disk_from_filer : NO UNOWNED DISKS found");
        };

        if ( $Kernel =~ /FS/i ) {
            try {
                my %hash = ( filter => { "owner-node-name" => $remove_disk_from_filer, 'container-type' => "unknown" } );
                my @unown;
                my @unowned_obj = NACL::CS::StorageDiskPartition->fetch(
                    command_interface => $remove_disk_from,
                    %hash,
                    requested_fields => [qw(partition)]
                );

                foreach my $state_obj (@unowned_obj) {
                    my $free_disk = $state_obj->partition();
                    if ( $free_disk =~ /(\S+)\:(\S+)/ ) {
                        $free_disk = $2;
                    }
                    push( @unown, $free_disk );
                }
                if (@unown) {
                    push( @unowned_remove, @unown );    #Total unowned disks
                    my $dsks = _print_array( \@unown );
                    logcomment( "$remove_disk_from_filer : Unowned partitioned disks are:\n" . $dsks );
                }
            }
            catch NACL::Exceptions::NoElementsFound with {
                logcomment("$remove_disk_from_filer :: NO UNOWNED PARTITIONED DISKS found");
            };
        }
        ##Assigning back to its owner if present then these disks will become spare drives
        if (@unowned_remove) {
            my $sysid;
            my $return = $remove_disk_from_api->execute_raw_command( 'command' => "system node show -fields systemid -node $remove_disk_from_filer" );
            if ( $return =~ /$remove_disk_from_filer(\D*)(\d+)(\D*)/ ) {
                $sysid = $2;
            }

            foreach my $disk (@unowned_remove) {
                if ( $disk !~ /P\d+$/ ) {
                    try {
                        NACL::C::StorageDisk->assign(
                            command_interface => $remove_disk_from,
                            owner             => $remove_disk_from_filer,
                            disk              => $disk,
                            sysid             => $sysid,
                            force             => 'true',
                            'method-timeout'  => 1200
                        );
                    }
                    catch NACL::APISet::Exceptions::CommandFailedException with {
                        logcomment("**WARNING** : $disk is NOT assigned to filer $remove_disk_from_filer");
                    };
                } else {
                    try {
                        NACL::C::StorageDiskPartition->assign(
                            command_interface => $remove_disk_from,
                            owner             => $remove_disk_from_filer,
                            partition         => $disk,
                            sysid             => $sysid,
                            force             => 'true',
                            'method-timeout'  => 1200
                        );
                    }
                    catch NACL::APISet::Exceptions::CommandFailedException with {
                        logcomment("**WARNING** :: Partitioned disk $disk is NOT assigned to filer $remove_disk_from_filer");
                    };
                }
            }
        }
        ##$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$

        #****************************************************************************************
        #Check for any un-assigned disks
        my @disk_obj_unown = NACL::C::Disk->find(
            command_interface => $remove_disk_from,
            filter            => { owner => "-" },
            allow_empty       => 1,
        );
        foreach my $state_obj (@disk_obj_unown) {
            my $free_disk = $state_obj->disk();
            if ( $free_disk =~ /(\S+)\:(\S+)/ ) {
                $free_disk = $2;
            }
            push( @unassigned_disk, $free_disk );
        }

        my @temp_part;
        if ( $Kernel =~ /FS/i ) {
            try {
                logcomment("DEBUG:Checking for partitioned unowned drives if present");
                my @disk_obj = NACL::CS::StorageDiskPartition->fetch(
                    command_interface => $remove_disk_from,
                    filter            => { "owner-node-name" => "-" },
                    requested_fields  => [qw(partition)],
                    allow_empty       => 1,
                );
                foreach (@disk_obj) {
                    push( @temp_part, $_->partition() );
                }
                my $dsks = _print_array( \@temp_part );
                logcomment( "Number of un-assigned partition drives found are " . scalar @temp_part . " and the drives are:\n" . $dsks ) if (@temp_part);
                logcomment("NO UN-ASSIGNED PARTITION DRIVES found") if ( !@temp_part );
            }
            catch NACL::Exceptions::NoElementsFound with {
                logcomment("NO UN-ASSIGNED PARTITIONED DRIVES found in the filer $remove_disk_from_filer");
            };
            push( @unassigned_disk, @temp_part ) if (@temp_part);
        }
        my $dsks = _print_array( \@unassigned_disk );
        logcomment( "Total number of unassiged partitioned disks are " . scalar @unassigned_disk . " and the disks are:\n" . $dsks ) if (@unassigned_disk);
        logcomment("NO UN-ASSIGNED PARTITION DRIVES found") if ( !@unassigned_disk );

        if (@unassigned_disk) {
            my $dsks = _print_array( \@unassigned_disk );
            logcomment( "Number of unassiged disks are " . scalar @unassigned_disk . " and the disks are:\n" . $dsks );
            push( @disks, @unassigned_disk );    #pushing to @disks even these disks also will get assign.
            @unassigned_disk = ();               # resetting the array;
        } else {
            logcomment("NO UN-ASSIGNED DISKS found in the filers");
        }

        #****************************************************************************************

        ################################################################################################
        #getting spare drives of the filer

        my @spare_remove = spare_count_cmode( Node => $remove_disk_from, waiting => 'no' );

        logcomment("Removing the ownership of drives @spare_remove") if (@spare_remove);
        foreach my $disk (@spare_remove) {
            if ( $disk !~ /P\d+$/ ) {
                NACL::C::StorageDisk->removeowner(
                    command_interface => $remove_disk_from,
                    disk              => $disk,
                    force             => 'true',
                    'method-timeout'  => 600
                );
            } else {
                NACL::C::StorageDiskPartition->removeowner(
                    command_interface => $remove_disk_from,
                    'partition'       => $disk,
                    force             => 'true',
                    'method-timeout'  => 600
                );
            }
        }
        if (@spare_remove) {
            push( @disks, @spare_remove );
        }
        sleep 60;
        ################################################################################################
    }
    if ($assign_filer_name) {
        if (@disks) {
            my $dsks = _print_array( \@disks );
            logcomment( "DEBUG:Drives which are assigning to filer $assign_filer_name are ::\n" . $dsks );
            my $sysid;
            if ( $Mode =~ /CMode/ ) {
                my $return = $assign_api->execute_raw_command( 'command' => "system node show -fields systemid -node $assign_filer_name" );
                if ( $return =~ /$assign_filer_name(\D*)(\d+)(\D*)/ ) {
                    $sysid = $2;
                }
            } else {
                my $return = $assign_api->execute_raw_command( 'command' => "sysconfig -v" );
                if ( $return =~ /\s*System(\D*)ID:(\D*)(\d+)(\D*)/ ) {
                    $sysid = $3;
                }
            }
            sleep 60;
            foreach my $disk (@disks) {
                if ( $disk !~ /P\d+$/ ) {
                    try {
                        NACL::C::StorageDisk->assign(
                            command_interface => $assign_node,
                            owner             => $assign_filer_name,
                            disk              => $disk,
                            sysid             => $sysid,
                            force             => 'true',
                            'method-timeout'  => 1200
                        );
                    }
                    catch NACL::APISet::Exceptions::CommandFailedException with {
                        logcomment("**WARNING** : $assign_filer_name : Some of the disks are NOT assigned");
                    };
                } else {
                    try {
                        NACL::C::StorageDiskPartition->assign(
                            command_interface => $assign_node,
                            owner             => $assign_filer_name,
                            partition         => $disk,
                            force             => 'true',
                            'method-timeout'  => 1200
                        );
                    }
                    catch NACL::APISet::Exceptions::CommandFailedException with {
                        logcomment("**WARNING** : $assign_filer_name : Some of the disks are NOT assigned");
                    };

                }
            }
            return 0;
        } else {
            logcomment("NO SPARE DISKS are available on the filer $remove_disk_from_filer and NO UNKNOWN, UNASSIGNED disks are also NOT available");
            return 0;
        }
    }

    logcomment("If NO disks, remove node, assign node are passed then disk will be allocated between the filers appropriately");
    ###If disk_ref,remove_disk_from, assign_disk_to	parameters are not passed then disks are allocated according to below conditions

    ##listing all the disks attached to filers
    #try{
    {
        my @disk_list_common = get_disks_list( Node => $Nodes[0] );

        #my @disk_list_common_obj = NACL::C::StorageDisk->find( command_interface => $Nodes[0]);
        #foreach my $disk (@disk_list_common_obj) {
        #	push( @disk_list_common, $disk->get_one_state_attribute('disk') );
        #}
        if ( !scalar @disk_list_common ) {
            logcomment("**FATAL** : NO DISKS are attached to the filers");
            logresult( 'FATAL', "NO DISKS ARE ATTACHED TO THE FILERS" );
        }
        my $dsks = _print_array( \@disk_list_common );
        logcomment( "Total number of disks attached to filers are " . scalar @disk_list_common . " and the disks are:\n" . $dsks );

    }

    #}catch NACL::Exceptions::NoElementsFound with{

    #};
    ##If nothing is passed except nodes, delete all the aggregates except root, so that all the spare drives will be available to assign them
    ## equally on both the nodes.
    foreach my $node (@Nodes) {
        my $FILER_C = $node->name();
        $node->refresh_command_interface();
        my $API_obj = $node->get_7m_or_nodescope_apiset();
        $API_obj->set_timeout( "connectrec-timeout" => 7200 );
        ##Stopping all the SCRUB and hammer process , so that we can delete volumes
        try {
            $API_obj->hammer_abort();
            my @test_aggr = NACL::C::Aggregate->find(
                command_interface => $node,
                filter            => { nodes => [$FILER_C] }
            );
            foreach my $aggr_c (@test_aggr) {
                my $status = $aggr_c->scrub( action => "status" );
                if ( $status =~ /Percentage Completed/gi ) {
                    logcomment("Scrub status - $status");
                    logcomment("Stopping Scrub process");
                    $aggr_c->scrub( action => "stop" );
                } else {
                    logcomment("Scrub is NOT in progress, proceeding with next steps");
                }
            }
        }
        catch NACL::Exceptions::NoElementsFound with {
            logcomment("$FILER_C : NO AGGREGATE found, re_initialize filer to create root aggregate");
        };
        if ( defined $opts{delete_aggr} ) {
            vserver_delete( Node => $node );    #Vserver deletion
            aggregate_volume_delete( Node => $node );
        }
    }

    foreach my $node (@Nodes) {
        my $api = $node->get_7m_or_nodescope_apiset();
        $api->set_timeout( "connectrec-timeout" => 7200 );
        my $Filer = $node->name();
        $api->execute_raw_command( 'command' => "storage disk option modify -node $Filer -autoassign off" );
    }

    #AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    #Check for any un-owned disks on both the filers
    foreach my $node (@Nodes) {
        my $FILER_C = $node->name();
        $node->refresh_command_interface();
        try {
            my %hash = ( filter => { 'container-type' => "unknown", 'home' => $FILER_C } );
            my @unown;
            my @unowned_obj = NACL::C::Disk->find(
                command_interface => $node,
                %hash,
            );
            foreach my $state_obj (@unowned_obj) {
                my $free_disk = $state_obj->disk();
                if ( $free_disk =~ /(\S+)\:(\S+)/ ) {
                    $free_disk = $2;
                }
                push( @unown, $free_disk );
            }
            if (@unown) {
                $Node_unowned{$node} = [@unown];
                push( @unowned, @unown );    #Total unowned disks
                my $dsks = _print_array( \@unown );
                logcomment( "$FILER_C : Unowned disks are:\n" . $dsks );
            }
        }
        catch NACL::Exceptions::NoElementsFound with {
            logcomment("$FILER_C : NO UNOWNED DISKS found");
        };

        if ( $Kernel =~ /FS/ ) {
            try {
                my %hash = ( filter => { "owner-node-name" => $FILER_C, 'container-type' => "unknown" } );
                my @unown;
                my @unowned_obj = NACL::CS::StorageDiskPartition->fetch(
                    command_interface => $node,
                    %hash,
                    requested_fields => [qw(partition)]
                );

                foreach my $state_obj (@unowned_obj) {
                    push( @unown, $state_obj->partition() );
                }
                if (@unown) {
                    $Node_unowned{$node} = [@unown];
                    push( @unowned, @unown );    #Total unowned disks
                    my $dsks = _print_array( \@unown );
                    logcomment( "$FILER_C : Unowned partitioned disks are:\n" . $dsks );
                }
            }
            catch NACL::Exceptions::NoElementsFound with {
                logcomment("$FILER_C : NO UNOWNED PARTITIONED DISKS found");
            };
        }
    }
    ##Assigning back to its owner then these disks will become spare drives
    foreach my $node (@Nodes) {
        my $FILER = $node->name();
        my $api   = $node->get_7m_or_nodescope_apiset();
        $api->set_timeout( "connectrec-timeout" => 7200 );
        my $return = $api->execute_raw_command( 'command' => "system node show -fields systemid -node $FILER" );
        if ( $Node_unowned{$node} ) {
            my @assign = @{ $Node_unowned{$node} };
            my $sysid;
            my $return = $api->execute_raw_command( 'command' => "system node show -fields systemid -node $FILER" );
            if ( $return =~ /$remove_disk_from_filer(\D*)(\d+)(\D*)/ ) {
                $sysid = $2;
            }
            foreach my $disk (@assign) {
                if ( $disk !~ /P\d+$/ ) {
                    try {
                        NACL::C::StorageDisk->assign(
                            command_interface => $node,
                            owner             => $FILER,
                            disk              => $disk,
                            sysid             => $sysid,
                            force             => 'true',
                            'method-timeout'  => 1200
                        );
                    }
                    catch NACL::APISet::Exceptions::CommandFailedException with {
                        logcomment("**WARNING** : $disk is NOT assigned to filer $FILER");
                    };
                } else {
                    try {
                        NACL::C::StorageDiskPartition->assign(
                            command_interface => $node,
                            owner             => $FILER,
                            partition         => $disk,
                            force             => 'true',
                            'method-timeout'  => 1200
                        );
                    }
                    catch NACL::APISet::Exceptions::CommandFailedException with {
                        logcomment("**WARNING** :: Partitioned unknowned disk $disk is NOT assigned to filer $FILER");
                    };
                }
            }
        }
    }

    #AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    my $API_obj_A = $Nodes[0]->get_7m_or_nodescope_apiset();    #Creating Api objects
    $API_obj_A->set_timeout( "connectrec-timeout" => 7200 );
    my $filer_a   = $Nodes[0]->name();
    my $API_obj_B = $Nodes[1]->get_7m_or_nodescope_apiset();
    $API_obj_B->set_timeout( "connectrec-timeout" => 7200 );
    my $filer_b = $Nodes[1]->name();

    #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    #Checking whether any broken disks in CMode or FAILED disks in 7Mode present, if present unfailing them to spare drives
    ###Checking for filer A
    {
        try {
            my $FILER_C = $Nodes[0]->name();
            my %hash;
            %hash = ( filter => { 'container-type' => "broken", "owner" => $FILER_C } );
            my @broken_obj = NACL::C::Disk->find(
                command_interface => $Nodes[0],
                %hash,
            );
            foreach my $state_obj (@broken_obj) {
                my $free_disk = $state_obj->disk();
                if ( $free_disk =~ /(\S+)\:(\S+)/ ) {
                    $free_disk = $2;
                }
                push( @broken_disk_A, $free_disk );
            }
            if (@broken_disk_A) {
                my $dsks = _print_array( \@broken_disk_A );
                logcomment( "$filer_a : Number of broken disks are " . scalar @broken_disk_A . " and the disks are:\n" . $dsks );
            }
        }
        catch NACL::Exceptions::NoElementsFound with {
            logcomment("$filer_a : NO BROKEN DISKS found for the filer");
        };

        foreach my $boken (@broken_disk_A) {
            try {
                NACL::C::StorageDisk->unfail(
                    command_interface => $Nodes[0],
                    disk              => $boken,
                    spare             => "true",
                    'method-timeout'  => 1200
                );
            }
            catch NACL::APISet::Exceptions::CommandFailedException with {
                my $Filer = $Nodes[0]->name();
                logcomment("**WARNING** : $Filer : Could NOT unfail the disk $boken");
            }
            catch NATE::BaseException with {
                logcomment("Unfailing the drive is INTERRUPTED, may be because of timeout issue, so trying again to unfail after 5 minutes");
                sleep 300;
                try {
                    NACL::C::StorageDisk->unfail(
                        command_interface => $Nodes[0],
                        disk              => $boken,
                        spare             => "true",
                        'method-timeout'  => 1200
                    );
                }
                catch NATE::BaseException with {
                    logcomment("Unfailing the drive is NOT successfull!!!");
                };
            };
        }
    }

###Checking for filer B
    {
        try {
            my $FILER_C    = $Nodes[1]->name();
            my %hash       = ( filter => { 'container-type' => "broken", 'owner' => $FILER_C } );
            my @broken_obj = NACL::C::Disk->find(
                command_interface => $Nodes[1],
                %hash,
            );
            foreach my $state_obj (@broken_obj) {
                my $free_disk = $state_obj->disk();
                if ( $free_disk =~ /(\S+)\:(\S+)/ ) {
                    $free_disk = $2;
                }
                push( @broken_disk_B, $free_disk );
            }
            if (@broken_disk_B) {
                my $dsks = _print_array( \@broken_disk_B );
                logcomment( "$filer_b : Number of broken disks are " . scalar @broken_disk_B . " and the disks are:\n" . $dsks );
            }
        }
        catch NACL::Exceptions::NoElementsFound with {
            logcomment("$filer_b : NO BROKEN DISKS found for the filer");
        };

        foreach my $boken (@broken_disk_B) {
            try {
                NACL::C::StorageDisk->unfail(
                    command_interface => $Nodes[1],
                    disk              => $boken,
                    spare             => "true",
                    'method-timeout'  => 1200
                );
            }
            catch NACL::APISet::Exceptions::CommandFailedException with {
                my $Filer = $Nodes[1]->name();
                logcomment("**WARNING** : $Filer : Could NOT unfail the disk $boken");
            }
            catch NATE::BaseException with {
                logcomment("Unfailing the drive is INTERRUPTED, may be because of timeout issue, so trying to unfail after 5 minutes");
                sleep 300;
                try {
                    NACL::C::StorageDisk->unfail(
                        command_interface => $Nodes[1],
                        disk              => $boken,
                        spare             => "true",
                        'method-timeout'  => 1200
                    );
                }
                catch NATE::BaseException with {
                    logcomment("**WARNING** : Unfailing the drive is NOT successfull");
                };
            };
        }
    }

    ##Checking for disks which are failed in 7mode/broken in CMODE but have no owner
    {
        my @broken_disk_U;
        try {
            my $FILER_C    = $Nodes[1]->name();
            my %hash       = ( filter => { 'container-type' => "broken", 'owner' => "-" } );
            my @broken_obj = NACL::C::Disk->find(
                command_interface => $Nodes[1],
                %hash,
                allow_empty => 1,
            );
            foreach my $state_obj (@broken_obj) {
                my $free_disk = $state_obj->disk();
                if ( $free_disk =~ /(\S+)\:(\S+)/ ) {
                    $free_disk = $2;
                }
                push( @broken_disk_U, $free_disk );
            }
            if (@broken_disk_U) {
                my $dsks = _print_array( \@broken_disk_U );
                logcomment( "$FILER_C : Number of broken disks are " . scalar @broken_disk_U . " and the disks are:\n" . $dsks );
            }
        }
        catch NACL::Exceptions::NoElementsFound with {
            my $FILER_C = $Nodes[1]->name();
            logcomment("$FILER_C : NO BROKEN DISKS found for the filer");
        };

        foreach my $boken (@broken_disk_U) {
            try {
                NACL::C::StorageDisk->unfail(
                    command_interface => $Nodes[1],
                    disk              => $boken,
                    spare             => "true",
                    'method-timeout'  => 1200
                );
            }
            catch NACL::APISet::Exceptions::CommandFailedException with {
                try {
                    NACL::C::StorageDisk->unfail(
                        command_interface => $Nodes[1],
                        disk              => $boken,
                        'method-timeout'  => 1200
                    );
                    sleep 20;
                }
                catch NACL::APISet::Exceptions::CommandFailedException with {
                    my $FILER_C = $Nodes[1]->name();
                    logcomment("**WARNING** : $FILER_C : Could NOT unfail the disk : $boken");
                };

            }
            catch NATE::BaseException with {
                logcomment("Unfailing the drive is INTERRUPTED, may be because of timeout issue, so trying again to unfail after 5 minutes");
                sleep 300;
                try {
                    NACL::C::StorageDisk->unfail(
                        command_interface => $Nodes[1],
                        disk              => $boken,
                        spare             => "true",
                        'method-timeout'  => 1200
                    );
                }
                catch NATE::BaseException with {
                    logcomment("Unfailing the drive is NOT successfull!!!");
                };
            };
        }
    }

    #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    {
        my $ret_A = $API_obj_A->execute_raw_command( 'command' => "system node show -fields systemid -node $filer_a" );
        my @sys_id_A = split( /\n/, $ret_A );
        foreach (@sys_id_A) {
            if ( $_ =~ /$filer_a(\D*)(\d+)(\D*)/ ) {
                $sysid_A = $2;
                last;
            }
        }
        my $ret_B = $API_obj_B->execute_raw_command( 'command' => "system node show -fields systemid -node $filer_b" );
        my @sys_id_B = split( /\n/, $ret_B );
        foreach (@sys_id_B) {
            if ( $_ =~ /$filer_b(\D*)(\d+)(\D*)/ ) {
                $sysid_B = $2;
                last;
            }
        }
    }
    logcomment("System ID of Filer  $filer_a is: $sysid_A");
    logcomment("partner ID of Filer  $filer_b is: $sysid_B");

    ########## finding total spare count of filera ##################################################
    @disk_A = spare_count_cmode( Node => $Nodes[0], waiting => 'no' );
    if (@disk_A) {
        my $dsks = _print_array( \@disk_A );
        logcomment( "Total Spare drives in filer $filer_a are " . scalar @disk_A . " and the disks are:\n" . $dsks );
    } else {
        logcomment("$filer_a : NO SPARE DRIVES present in the filer");
    }

    ####################################################################################################

    ########## Finding total spare count of filerb ########################################
    @disk_B = spare_count_cmode( Node => $Nodes[1], waiting => 'no' );
    if (@disk_B) {
        my $dsks = _print_array( \@disk_B );
        logcomment( "Total Spare drives in filer $filer_b are " . scalar @disk_B . " and the disks are:\n" . $dsks );
    } else {
        logcomment("$filer_b : NO SPARE DRIVES present in the filer");
    }

    ###############################################################################################

    #***********Total Spare drives are***********************
    push( @Total_spare, @disk_A ) if (@disk_A);
    push( @Total_spare, @disk_B ) if (@disk_B);
    if (@Total_spare) {
        my $dsks = _print_array( \@Total_spare );
        logcomment( "Total Spare drives present in the system are " . scalar @Total_spare . " and the drives are:\n" . $dsks );
    }

    #UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU
    #Check for any un-assigned disks
    try {
        my @disk_obj_unown = NACL::C::Disk->find(
            command_interface => $Nodes[0],
            filter            => { owner => "-" },
            allow_empty       => 1,
        );
        foreach my $state_obj (@disk_obj_unown) {
            my $free_disk = $state_obj->disk();
            if ( $free_disk =~ /(\S+)\:(\S+)/ ) {
                $free_disk = $2;
            }
            push( @unassigned_disk, $free_disk );
        }
        if (@unassigned_disk) {
            my $dsks = _print_array( \@unassigned_disk );
            logcomment( "Total un-assigned container disks are " . scalar @unassigned_disk . " and the disks are:\n" . $dsks );
        }
    }
    catch NACL::Exceptions::NoElementsFound with {
        logcomment("NO UNASSIGNED DISKS found on the filers");
    };
    if ( $Kernel =~ /FS/i ) {
        try {
            my @temp_part;
            logcomment("DEBUG:Checking for partitioned unowned drives if present");
            my @disk_obj = NACL::CS::StorageDiskPartition->fetch(
                command_interface => $Nodes[0],
                filter            => { "owner-node-name" => "-" },
                requested_fields  => [qw(partition)],
                allow_empty       => 1,
            );
            foreach (@disk_obj) {
                push( @temp_part, $_->partition() );
            }
            push( @unassigned_disk, @temp_part ) if @temp_part;
            my $dsks = _print_array( \@temp_part );
            logcomment( "Number of un-assigned partition drives found are " . scalar @temp_part . " and the drives are:\n" . $dsks ) if (@temp_part);
            logcomment("NO UN-ASSIGNED PARTITION DRIVES found") if ( !@temp_part );
        }
        catch NACL::Exceptions::NoElementsFound with {
            logcomment( "NO UN-ASSIGNED PARTITIONED DRIVES found in the filer " . $Nodes[0]->name() );
        };
    }
    my $dsks = _print_array( \@unassigned_disk );
    logcomment( "Total number of unknowed drives are " . scalar @unassigned_disk . " and the drives are:\n" . $dsks ) if (@unassigned_disk);

    #UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU

    my $disksA = @disk_A;
    my $disksB = @disk_B;
    my ( $filer_nameA, $filer_nameB, $numberA, $numberB, $number, $filer_name );
    my $unowned_disks = @unassigned_disk;
    my $disk_diff     = abs( $disksA - $disksB );
    if ( $unowned_disks > 0 ) {
        if ( $disk_diff > $unowned_disks ) {
            logcomment("Spare disks difference $disk_diff is greater than unowned disks $unowned_disks ");
            if ( ( $disk_diff / 2 ) <= $unowned_disks ) {
                logcomment("1/2 of Spare disks difference i.e $disk_diff is greater than unowned drives unowned_disks $unowned_disks ");
                my ( $sys_id, $node );
                if ( $disksA > $disksB ) {
                    $filer_name = $filer_a;
                    $sys_id     = $sysid_B;
                    $node       = $Nodes[1];
                } elsif ( $disksB > $disksA ) {
                    $filer_name = $filer_b;
                    $sys_id     = $sysid_A;
                    $node       = $Nodes[0];
                }
                foreach my $disk (@unassigned_disk) {
                    if ( $disk !~ /P\d+$/ ) {
                        try {
                            NACL::C::StorageDisk->assign(
                                command_interface => $node,
                                owner             => $filer_name,
                                disk              => $disk,
                                sysid             => $sys_id,
                                force             => 'true',
                                'method-timeout'  => 1200
                            );
                        }
                        catch NACL::APISet::Exceptions::CommandFailedException with {
                            logcomment("**WARNING** : $filer_name : Container disk $disk NOT assigned");
                        };
                    } else {
                        try {
                            NACL::C::StorageDiskPartition->assign(
                                command_interface => $node,
                                partition         => $disk,
                                owner             => $filer_name,
                                force             => 'true',
                                'method-timeout'  => 1200
                            );
                        }
                        catch NACL::APISet::Exceptions::CommandFailedException with {
                            logcomment("**WARNING** : Partitioned $disk is NOT assigned to filer $filer_name");
                        };
                    }
                }
            } else {
                logcomment("1/2 of Spare disks difference i.e $disk_diff is lesser than unowned drives $unowned_disks  ");
                foreach my $disk (@disk_A) {
                    if ( $disk !~ /P\d+$/ ) {
                        NACL::C::StorageDisk->removeowner(
                            command_interface => $Nodes[0],
                            disk              => $disk,
                            force             => 'true',
                            'method-timeout'  => 600
                        );
                    } else {
                        NACL::C::StorageDiskPartition->removeowner(
                            command_interface => $Nodes[0],
                            'partition'       => $disk,
                            force             => 'true',
                            'method-timeout'  => 600
                        );
                    }
                }
                foreach my $disk (@disk_B) {
                    if ( $disk !~ /P\d+$/ ) {
                        NACL::C::StorageDisk->removeowner(
                            command_interface => $Nodes[1],
                            disk              => $disk,
                            force             => 'true',
                            'method-timeout'  => 600
                        );
                    } else {
                        NACL::C::StorageDiskPartition->removeowner(
                            command_interface => $Nodes[1],
                            'partition'       => $disk,
                            force             => 'true',
                            'method-timeout'  => 600
                        );
                    }
                }
                my ( @final_count, @final_count_a, @final_count_b );
                push( @final_count, @disk_B, @disk_A, @unassigned_disk );
                if ( @final_count % 2 == 0 ) {
                    $numberA = @final_count / 2;
                } else {
                    $numberB = @final_count + 1;
                    $numberA = $numberB / 2;
                }
                $numberB = ( scalar @final_count ) - $numberA;
                sleep 30;
                @final_count   = sort @final_count;
                @final_count_a = @final_count[ 0 .. ( $numberA - 1 ) ];
                @final_count_b = @final_count[ $numberA .. $#final_count ];
                @final_count_a = grep { /\S/ } @final_count_a;
                @final_count_b = grep { /\S/ } @final_count_b;
                my $dsks = _print_array( \@final_count_a );
                logcomment( "Total number of drives assigning to the filer $filer_a are " . scalar @final_count_a . " and the drives are:\n" . $dsks ) if (@final_count_a);
                logcomment("NO DRIVES are assigned to the filer : $filer_a") if ( !@final_count_a );

                foreach my $disk (@final_count_a) {
                    if ( $disk !~ /P\d+/ ) {
                        try {
                            NACL::C::StorageDisk->assign(
                                command_interface => $Nodes[0],
                                owner             => $filer_a,
                                disk              => $disk,
                                sysid             => $sysid_A,
                                force             => 'true',
                                'method-timeout'  => 1200
                            );
                        }
                        catch NACL::APISet::Exceptions::CommandFailedException with {
                            logcomment("**WARNING** : $filer_a : Container disk $disk NOT assigned");
                        };
                    } else {
                        try {
                            NACL::C::StorageDiskPartition->assign(
                                command_interface => $Nodes[0],
                                partition         => $disk,
                                owner             => $filer_a,
                                force             => 'true',
                                'method-timeout'  => 1200
                            );
                        }
                        catch NACL::APISet::Exceptions::CommandFailedException with {
                            logcomment("**WARNING** :: Partitioned disk $disk is NOT assigned to filer $filer_a");
                        };
                    }
                }
                my $dsks = _print_array( \@final_count_b );
                logcomment( "Total number of drives assigning to the filer $filer_b are " . scalar @final_count_b . " and the drives are:\n" . $dsks ) if (@final_count_b);
                logcomment("NO DRIVES are available to assign to the filer : $filer_b") if ( !@final_count_b );
                foreach my $disk (@final_count_b) {
                    if ( $disk !~ /P\d+/ ) {
                        try {
                            NACL::C::StorageDisk->assign(
                                command_interface => $Nodes[1],
                                owner             => $filer_b,
                                disk              => $disk,
                                sysid             => $sysid_B,
                                force             => 'true',
                                'method-timeout'  => 1200
                            );
                        }
                        catch NACL::APISet::Exceptions::CommandFailedException with {
                            logcomment("**WARNING** : $filer_b : Container disk $disk NOT assigned");
                        };
                    } else {
                        try {
                            NACL::C::StorageDiskPartition->assign(
                                command_interface => $Nodes[1],
                                partition         => $disk,
                                owner             => $filer_b,
                                force             => 'true',
                                'method-timeout'  => 1200
                            );
                        }
                        catch NACL::APISet::Exceptions::CommandFailedException with {
                            logcomment("**WARNING** :: Partitioned disk $disk is NOT assigned to filer $filer_b");
                        };
                    }
                }
            }
        } elsif ( $disk_diff < $unowned_disks ) {
            logcomment("Spare disk difference :: $disk_diff is lesser than unowned disks $unowned_disks ");
            if ( $disksA < $disksB ) {
                $numberA = $disk_diff;
            } elsif ( $disksB < $disksA ) {
                $numberB = $disk_diff;
            }
            $filer_nameA = $filer_a;
            $filer_nameB = $filer_b;
            $number      = sprintf( "%d", ( ( $unowned_disks - $disk_diff ) / 2 ) );
            $numberA     = $numberA + $number;
            $numberB     = $numberB + $number;

            if ($numberA) {

                my @numberA = @unassigned_disk[ 0 .. ( $numberA - 1 ) ];
                @numberA = grep { /\S/ } @numberA;
                my $dsks = _print_array( \@numberA );
                logcomment( "Total number of drives assigning to the filer $filer_nameA are " . scalar @numberA . " and the drives are:\n" . $dsks ) if (@numberA);
                logcomment("NO DRIVES are available to assign to the filer $filer_nameA") if ( !@numberA );
                foreach my $disk (@numberA) {
                    if ( $disk !~ /P\d+/ ) {
                        try {
                            NACL::C::StorageDisk->assign(
                                command_interface => $Nodes[0],
                                owner             => $filer_nameA,
                                disk              => $disk,
                                sysid             => $sysid_A,
                                force             => 'true',
                                'method-timeout'  => 1200
                            );
                        }
                        catch NACL::APISet::Exceptions::CommandFailedException with {
                            logcomment("**WARNING** : $filer_nameA : Container disk $disk NOT assigned");
                        };
                    } else {
                        try {
                            NACL::C::StorageDiskPartition->assign(
                                command_interface => $Nodes[0],
                                partition         => $disk,
                                owner             => $filer_nameA,
                                force             => 'true',
                                'method-timeout'  => 1200
                            );
                        }
                        catch NACL::APISet::Exceptions::CommandFailedException with {
                            logcomment("**WARNING** Partitioned disk $disk is NOT assigned to filer $filer_nameA");
                        };
                    }
                }
            }
            my @numberB = @unassigned_disk[ $numberA .. $#unassigned_disk ];
            @numberB = grep { /\S/ } @numberB;
            my $dsks = _print_array( \@numberB );
            logcomment( "Total number of drives assigning to the filer $filer_nameB are " . scalar @numberB . " and the drives are:\n" . $dsks ) if (@numberB);
            logcomment("NO DRIVES are available to assign to the filer $filer_nameB") if ( !@numberB );
            foreach my $disk (@numberB) {
                if ( $disk !~ /P\d+/ ) {
                    try {
                        NACL::C::StorageDisk->assign(
                            command_interface => $Nodes[1],
                            owner             => $filer_nameB,
                            disk              => $disk,
                            sysid             => $sysid_B,
                            force             => 'true',
                            'method-timeout'  => 1200
                        );
                    }
                    catch NACL::APISet::Exceptions::CommandFailedException with {
                        logcomment("**WARNING** : $filer_nameB : Container disk $disk NOT assigned");
                    };
                } else {
                    try {
                        NACL::C::StorageDiskPartition->assign(
                            command_interface => $Nodes[1],
                            partition         => $disk,
                            owner             => $filer_nameB,
                            force             => 'true',
                            'method-timeout'  => 1200
                        );
                    }
                    catch NACL::APISet::Exceptions::CommandFailedException with {
                        logcomment("**WARNING** - Partitioned disk $disk is NOT assigned to filer $filer_nameB");
                    };
                }
            }
        } else {
            logcomment("Spare disks difference of both the filers is $disk_diff which is equal to unassigned disks $unowned_disks ");
            my ( $sys_id, $node );
            if ( $disksA < $disksB ) {
                $sys_id = $sysid_A;
                $node   = $Nodes[0];
            } elsif ( $disksB < $disksA ) {
                $sys_id = $sysid_B;
                $node   = $Nodes[1];
            }
            my $Filer = $node->name();
            foreach my $disk (@unassigned_disk) {
                if ( $disk !~ /P\d+/ ) {
                    try {
                        NACL::C::StorageDisk->assign(
                            command_interface => $node,
                            owner             => $Filer,
                            disk              => $disk,
                            sysid             => $sys_id,
                            force             => 'true',
                            'method-timeout'  => 1200
                        );
                    }
                    catch NACL::APISet::Exceptions::CommandFailedException with {
                        logcomment("**WARNING** : $Filer : Container disk $disk assigned");
                    };
                } else {
                    try {
                        NACL::C::StorageDiskPartition->assign(
                            command_interface => $node,
                            partition         => $disk,
                            owner             => $Filer,
                            force             => 'true',
                            'method-timeout'  => 1200
                        );
                    }
                    catch NACL::APISet::Exceptions::CommandFailedException with {
                        logcomment("**WARNING** - Partitioned disk $disk Is NOT assigned to filer $Filer");
                    };
                }
            }
        }
    } elsif ( ( $disksA == 0 ) || ( $disksB == 0 ) ) {
        logcomment("DEBUG:Either or both the filers spare disks are 0");
        my $node;
        if ( $disksA == 0 ) {
            $node = $Nodes[1];
        } else {
            $node = $Nodes[0];
        }
        foreach my $disk (@Total_spare) {
            if ( $disk !~ /P\d+/ ) {
                NACL::C::StorageDisk->removeowner(
                    command_interface => $node,
                    disk              => $disk,
                    force             => 'true',
                    'method-timeout'  => 600
                );

            } else {
                NACL::C::StorageDiskPartition->removeowner(
                    command_interface => $node,
                    'partition'       => $disk,
                    force             => 'true',
                    'method-timeout'  => 600
                );

            }
        }
        sleep 60;
        my $disk_diff = abs( $disksA - $disksB );
        logcomment("Differance between disks of both filers is $disk_diff");
        if ( $disk_diff % 2 == 0 ) {
            $numberA = $disk_diff / 2;
        } else {
            $numberB = $disk_diff + 1;
            $numberA = $numberB / 2;
        }
        my @numberA = @Total_spare[ 0 .. ( $numberA - 1 ) ] if (@Total_spare);
        my @numberB = @Total_spare[ $numberA .. $#Total_spare ] if (@Total_spare);
        @numberA = grep { /\S/ } @numberA;
        @numberB = grep { /\S/ } @numberB;
        my $dsks = _print_array( \@numberA );
        logcomment( "Total number of drives assigning to the filer $filer_a are " . scalar @numberA . " and the drives are:\n" . $dsks );
        logcomment("NO DRIVES are available to assign to the filer : $filer_a") if ( !@numberA );

        foreach my $disk (@numberA) {

            if ( $disk !~ /P\d+/ ) {
                try {
                    NACL::C::StorageDisk->assign(
                        command_interface => $Nodes[0],
                        owner             => $filer_a,
                        disk              => $disk,
                        sysid             => $sysid_A,
                        force             => 'true',
                        'method-timeout'  => 1200
                    );
                }
                catch NACL::APISet::Exceptions::CommandFailedException with {
                    logcomment("**WARNING** : $filer_a : Container disk $disk NOT assigned");
                };
            } else {
                try {
                    NACL::C::StorageDiskPartition->assign(
                        command_interface => $Nodes[0],
                        'partition'       => $disk,
                        owner             => $filer_a,
                        force             => 'true',
                        'method-timeout'  => 600
                    );
                }
                catch NACL::APISet::Exceptions::CommandFailedException with {
                    logcomment("**WARNING** : $filer_a :: Partition disk $disk NOT assigned");
                };
            }
        }
        my $dsks = _print_array( \@numberB );
        logcomment( "Total number of drives assigning to the filer $filer_b are " . scalar @numberB . " and the drives are:\n" . $dsks ) if (@numberB);
        logcomment("NO DRIVES are available to assign to the filer : $filer_b") if ( !@numberB );
        foreach my $disk (@numberB) {
            if ( $disk !~ /P\d+/ ) {
                try {
                    NACL::C::StorageDisk->assign(
                        command_interface => $Nodes[1],
                        owner             => $filer_b,
                        disk              => $disk,
                        sysid             => $sysid_B,
                        force             => 'true',
                        'method-timeout'  => 1200
                    );
                }
                catch NACL::APISet::Exceptions::CommandFailedException with {
                    logcomment("**WARNING** : $filer_b : Container disk $disk NOT assigned");
                };
            } else {
                try {
                    NACL::C::StorageDiskPartition->assign(
                        command_interface => $Nodes[1],
                        'partition'       => $disk,
                        owner             => $filer_b,
                        force             => 'true',
                        'method-timeout'  => 600
                    );
                }
                catch NACL::APISet::Exceptions::CommandFailedException with {
                    logcomment("**WARNING** : $filer_b :: Partition disk $disk NOT assigned");
                };
            }
        }
    } elsif ( ( $disksA < int( ( scalar @Total_spare ) / 2 ) ) || ( $disksB < int( ( scalar @Total_spare ) / 2 ) ) ) {
        if ( ( abs( $disksA - $disksB ) ) > 3 ) {
            logcomment("One of the filer spare disks are less than total number of disks and the difference between filer's disks are greater than 3");
            logcomment("Removing and assigning disks between the filers");
            foreach my $disk (@disk_A) {
                if ( $disk !~ /P\d+$/ ) {
                    try {
                        NACL::C::StorageDisk->removeowner(
                            command_interface => $Nodes[0],
                            disk              => $disk,
                            force             => 'true',
                            'method-timeout'  => 600
                        );
                    }
                    catch NACL::APISet::Exceptions::CommandFailedException with {
                        logcomment("**WARNING** : $filer_a - Container disk $disk NOT assigned");
                    };
                } else {
                    try {
                        NACL::C::StorageDiskPartition->removeowner(
                            command_interface => $Nodes[0],
                            'partition'       => $disk,
                            force             => 'true',
                            'method-timeout'  => 600
                        );
                    }
                    catch NACL::APISet::Exceptions::CommandFailedException with {
                        logcomment("**WARNING** : $filer_a - Parition disk $disk NOT assigned");
                    };
                }
            }
            foreach my $disk (@disk_B) {
                if ( $disk !~ /P\d+$/ ) {
                    try {
                        NACL::C::StorageDisk->removeowner(
                            command_interface => $Nodes[1],
                            disk              => $disk,
                            force             => 'true',
                            'method-timeout'  => 600
                        );
                    }
                    catch NACL::APISet::Exceptions::CommandFailedException with {
                        logcomment("**WARNING** : $filer_b - Container disk $disk NOT assigned");
                    };
                } else {
                    try {
                        NACL::C::StorageDiskPartition->removeowner(
                            command_interface => $Nodes[1],
                            'partition'       => $disk,
                            force             => 'true',
                            'method-timeout'  => 600
                        );
                    }
                    catch NACL::APISet::Exceptions::CommandFailedException with {
                        logcomment("**WARNING** : $filer_b - Partition disk $disk NOT assigned");
                    };
                }
            }
            sleep 90;
            my $unowned = @Total_spare;

            if ( $unowned % 2 == 0 ) {
                $numberA = $unowned / 2;
            } else {
                $numberB = $unowned + 1;
                $numberA = $numberB / 2;
            }
            my @numberA = @Total_spare[ 0 .. ( $numberA - 1 ) ];
            my @numberB = @Total_spare[ $numberA .. $#Total_spare ];
            @numberA = grep { /\S/ } @numberA;
            @numberB = grep { /\S/ } @numberB;
            my $dsks = _print_array( \@numberA );
            logcomment( "Total number of drives assigning to the filer $filer_a are " . scalar @numberA . " and the drives are:\n" . $dsks ) if (@numberA);
            logcomment("NO DRIVES are available to assign to the filer $filer_a") if ( !@numberA );

            foreach my $disk (@numberA) {

                if ( $disk !~ /P\d+$/ ) {
                    try {
                        NACL::C::StorageDisk->assign(
                            command_interface => $Nodes[0],
                            owner             => $filer_a,
                            disk              => $disk,
                            sysid             => $sysid_A,
                            force             => 'true',
                            'method-timeout'  => 1200
                        );
                    }
                    catch NACL::APISet::Exceptions::CommandFailedException with {
                        logcomment("**WARNING** : $filer_a : Container disk $disk NOT assigned");
                    };
                } else {
                    try {
                        NACL::C::StorageDiskPartition->assign(
                            command_interface => $Nodes[1],
                            'partition'       => $disk,
                            force             => 'true',
                            owner             => $filer_a,
                            'method-timeout'  => 600
                        );
                    }
                    catch NACL::APISet::Exceptions::CommandFailedException with {
                        logcomment("**WARNING** : $filer_a : Partitioned disk $disk NOT assigned");
                    };

                }
            }
            my $dsks = _print_array( \@numberB );
            logcomment( "Total number of drives assigning to the filer $filer_b are " . scalar @numberB . " and the drives are:\n" . $dsks ) if (@numberB);
            logcomment("NO DRIVES are assigned to the filer :: $filer_b") if ( !@numberB );
            foreach my $disk (@numberB) {
                if ( $disk !~ /P\d+/ ) {
                    try {
                        NACL::C::StorageDisk->assign(
                            command_interface => $Nodes[1],
                            owner             => $filer_b,
                            disk              => $disk,
                            sysid             => $sysid_B,
                            force             => 'true',
                            'method-timeout'  => 1200
                        );
                    }
                    catch NACL::APISet::Exceptions::CommandFailedException with {
                        logcomment("**WARNING** : $filer_b : Container disk $disk NOT assigned");
                    };
                } else {
                    try {
                        NACL::C::StorageDiskPartition->assign(
                            command_interface => $Nodes[1],
                            'partition'       => $disk,
                            force             => 'true',
                            owner             => $filer_b,
                            'method-timeout'  => 600
                        );
                    }
                    catch NACL::APISet::Exceptions::CommandFailedException with {
                        logcomment("**WARNING** : $filer_b : Partitioned disk $disk NOT assigned");
                    };

                }
            }
        } else {
            logcomment("Drives are already assigned properly");
        }
    } else {
        logcomment("Disks are already assigned properly");
        return 0;
    }

}

################################################################################
## Author Arjun Lavu
## Description :: this subroutine will delete the vserver in the filer
################################################################################
sub vserver_delete {
    my (%opts) = validate(
        @_,
        {
            Node         => { type => OBJECT },
            vserver_name => { type => SCALAR, default => undef, optional => 1 },
        }
    );
    my $node    = $opts{Node};
    my $Filer   = $node->name();
    my $vserver = $opts{vserver_name};
    my @vservers;
    logcomment("Deleting the Vservers");
    if ($vserver) {
        try {
            my $name = NACL::STask::Vserver->find(
                command_interface => $node,
                filter            => { vserver => $vserver, },
            );
            if ( $name->get_one_state_attribute("vserver") =~ /^($vserver)$/ ) {
                NACL::STask::Vserver->purge(
                    command_interface => $node,
                    vserver           => $vserver,
                    'method-timeout'  => 10800000,
                );
            }
        }
        catch NACL::Exceptions::NoElementsFound with {
            logcomment("$Filer : NO VSERVER found with the name  $vserver");
        }
        catch NACL::APISet::Exceptions::TimeoutException with {
            logcomment("Canniot delete vserver");
        }
        catch NACL::APISet::Exceptions::CommandFailedException with {
            logcomment("**WARNING** : Could NOT delete vserver $vserver");
        };
    } else {
        try {
            @vservers = NACL::STask::Vserver->find(
                command_interface => $node,
                filter            => { 'admin-state' => "stopped|running|starting|stopping" },
            );
        }
        catch NACL::Exceptions::NoElementsFound with {
            logcomment("$Filer : NO VSERVERS found in the filers");
        };
        foreach my $vser_obj (@vservers) {
            try {
                $vser_obj->purge();
            }
            catch NACL::APISet::Exceptions::CommandFailedException with {
                logcomment("**WARNING** : Could NOT delete vservers");
            }
            catch NACL::APISet::Exceptions::TimeoutException with {
                logcomment("Canniot delete vserver");
            };
        }
    }
}
##################################################################################################################
## Author Arjun Lavu
## Inputs - This subroutine will call the remove_assign ownership based on the filer mode
## return value - null
#################################################################################################################
sub disk_remv_assign_ownership {
    my %opts = @_;
    if ( defined $opts{Node_ref} ) {
        my @Nodes       = @{ $opts{Node_ref} };
        my $FILER_C     = $Nodes[0]->name();
        my $Transit_obj = NACL::Transit->new( name => $FILER_C );
        my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
        if ( $filer_state =~ /MAINT/g ) {
            remv_assign_ownership_maint( \%opts );
        } elsif ( $filer_state =~ /CLI|UP/g ) {
            remv_assign_ownership_cli( \%opts );
        } else {
            logcomment("**FATAL** :Filer is NOT in neither Maintanence nor Filesystem mode");
            logresult( 'FATAL', "FILER IS NOT IN NEITHER MAINTANENCE NOR FILESYSTEM MODE" );
        }
    } else {
        logcomment("**FATAL** :  Mandatory parameter node_ref is NOT passed");
        logresult( 'FATAL', "MANDATORY PARAMETER NODE_REF IS NOT PASSED" );
    }
}

###################################################################################################################
#	Author Arjun Lavu
#   Description
###################################################################################################################

sub check_mode_nodes {
    my (%opts) = validate(
        @_,
        {
            Node_ref  => { type => ARRAYREF },
            BOOT_MODE => { type => SCALAR },
        }
    );
    my %compare_state;
    my $Node_ref  = $opts{Node_ref};
    my $BOOT_MODE = $opts{BOOT_MODE};
    my $actual_state;
    if ( $BOOT_MODE == 1 ) {
        $actual_state = "CLI";
    } elsif ( $BOOT_MODE == 5 ) {
        $actual_state = "MAINT";
    } else {
        $actual_state = $BOOT_MODE;
    }
    my @Nodes = @{$Node_ref};
    if ( scalar @Nodes > 1 ) {
        logcomment( "Filer present are " . $Nodes[0]->name() . " and " . $Nodes[1]->name() );
        foreach (@Nodes) {
            my $FILER_C     = $_->name();
            my $Transit_obj = NACL::Transit->new( name => $FILER_C );
            my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
            if ( $filer_state =~ /MAINT/ig ) {
                $compare_state{$FILER_C} = 'MAINT';
            } elsif ( $filer_state =~ /CLI/ig ) {
                $compare_state{$FILER_C} = 'CLI';
            } else {
                logcomment("**FATAL** : Filer $FILER_C : is NOT in neither Maintanence nor Filesystem mode");
                logresult( 'FATAL', "FILER $FILER_C  IS NOT IN NEITHER MAINTANENCE NOR FILESYSTEM MODE" );
            }
        }
        my @filers = keys %compare_state;
        if ( $compare_state{ $filers[0] } ne $compare_state{ $filers[1] } ) {
            logcomment("Filer : $filers[0] state is NOT same as filer $filers[1] state");
            logcomment("Sate of filer $filers[0] is $compare_state{$filers[0]}");
            logcomment("Sate of filer $filers[1] is $compare_state{$filers[1]}");
        }
        my $flag = 0;
        foreach (@filers) {
            if ( $compare_state{$_} !~ /$actual_state/ig ) {
                if ( $compare_state{$_} =~ /CLI/ig ) {
                    logcomment("Filer $_ : is in file-system Mode but script needs to run in MAINT mode, So changing state to MAINT");
                    $flag = "MAINT";
                } elsif ( $compare_state{$_} =~ /MAINT/i ) {
                    logcomment("Filer $_ : is in MAINT Mode but the script needs to run in CLI state, so changing state to CLI if Root volume exist,else changing state to MAINT");
                    my $Host        = host($_);
                    my $Api_Set_Obj = NACL::APISet->new(
                        hostobj   => $Host,
                        category  => "Node",
                        interface => "CLI",
                        set       => "Maintenance"
                    );
                    $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
                    my $aggr_output = $Api_Set_Obj->execute_raw_command( command => "aggr status -r" );
                    if ( ( $aggr_output =~ /aggr0/i ) && ( $aggr_output !~ /No root aggregate/i ) ) {
                        logcomment("Root aggregate exist on Filer $_, so changing state to CLI");
                        $flag = "CLI";
                    } else {
                        logcomment("Root aggregate NOT exist on filer $_");
                        $flag = "MAINT";
                        last;
                    }
                } else {
                    logcomment("Filer : $_:  Mode choosed by the user is $actual_state, so changing state to Maintenance as of now.");
                    my $Transit_obj = NACL::Transit->new( name => $_ );
                    my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
                    $Transit_obj->set( 'change_state_timeout' => 7200 );
                    $Transit_obj->change_state( to => "MAINT" );
                }
            }
        }
        foreach (@filers) {
            if ($flag) {
                my $Transit_obj = NACL::Transit->new( name => $_ );
                my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
                $Transit_obj->set( 'change_state_timeout' => 7200 );
                $Transit_obj->change_state( to => "$flag" );
            }
        }
    }

}

###########################################################################
## Author Arjun Lavu
## Description :: This subroutine will return the unknown disk names(dblade names)
##########################################################################
sub disk_show_n {
    my (%opts) = validate( @_, { Node => { type => OBJECT }, } );

    my $Node    = $opts{Node};
    my $Mode    = $Node->mode();
    my $FILER_C = $Node->name();
    my $Host    = host($FILER_C);

    #**************************************************
    #Checking the filer state
    #**************************************************
    my $Transit_obj = NACL::Transit->new( name => $FILER_C );
    my $filer_state;
    try {
        $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    }
    catch NACL::Transit::Exceptions::Timeout with {
        logcomment("Expected: Caught a Timeout exception");
        $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    }
    catch NACL::Transit::Exceptions::TransitException with {
        my $exception_object = shift;
        logcomment( "Exception is of type: " . ref($exception_object) );
        logcomment( "Error text is: " . $exception_object->text() );
    };

    my ( $API_obj, $output, @lines );
    ##############################################
    ##Based on mode(UP/MAINT) API object is created
    ##############################################
    logcomment("DEBUG: $FILER_C : Filer state is $filer_state");
    if ( $filer_state =~ /(CLI|UP)/ ) {
        $API_obj = $Node->get_7m_or_nodescope_apiset();
        $API_obj->set_timeout( "connectrec-timeout" => 7200 );
        logcomment("DEBUG:$FILER_C : Executing  disk show -n");

        #$API_obj->execute_raw_command( 'command' => "run local");
        #$API_obj->execute_raw_command( 'command' => "priv set -q test");
        $output = $API_obj->execute_raw_command( 'command' => "run local disk show -n" );
    } else {
        $API_obj = NACL::APISet->new(
            hostobj   => $Host,
            category  => "Node",
            interface => "CLI",
            set       => "Maintenance"
        );
        $API_obj->set_timeout( "connectrec-timeout" => 7200 );
        logcomment("DEBUG:$FILER_C : Executing  disk show -n");
        $API_obj->execute_raw_command( 'command' => "\013" );
        $API_obj->execute_raw_command( 'command' => "\013" );
        $output = $API_obj->execute_raw_command( 'command' => "disk show -n" );
    }
    my $n      = 0;
    my $result = {};
    if ( $output =~ /No disks match option -n|No unassigned disks/ ) {
        logcomment("$FILER_C : Currently NO unowned disks available in the filer ");
        return $result;
    } else {
        @lines = split( /\n/, $output );

        # skip to the start of table contents
        while ( $n <= $#lines ) {
            last if ( $lines[$n] =~ /^-----/ );
            $n++;
        }
        $n++;
    }
    foreach my $line ( @lines[ $n .. $#lines ] ) {

        #        my ($disk, $owner, $pool, $serial_number ) = ( $line =~/(\S+)\s+(\S+\s+\S+)\s+(\S+)\s+(\S+)/);
        if ( ( $line =~ /Not Owned/g ) ) {
            my ( $disk, $owner, $pool, $serial_number ) = ( $line =~ /(\S+)\s+(\S+\s+\S+)\s+(\S+)\s+(\S+)/ );
            $result->{$disk} = {
                'DISK'          => $disk,
                'OWNER'         => $owner,
                'POOL'          => $pool,
                'SERIAL_NUMBER' => $serial_number,
            };
        }
    }
    return $result;
}
#######################################################################################
## Author Arjun Lavu
## Description :: This subroutine will initiate the disk zeroing if drives are not zeroed
#######################################################################################
sub zero_spares {
    my (%opts) = validate( @_, { Node => { type => OBJECT }, } );

    #spare_disk_list =>  { type => ARRAYREF, default => undef, optional => 1 },
    my $Node    = $opts{Node};
    my $Mode    = $Node->mode();
    my $FILER_C = $Node->name();
    my $flag    = 0;
    my @spare_disk;

    #if(defined $opts{spare_disk_list}){
    #	@spare_disk = @{$opts{spare_disk_list}};
    #my $dsks = _print_array(\@spare_disk);
    #	logcomment("Filer : $FILER_C :  Number of Spares passed are ".scalar @spare_disk." and the spares are:\n".$dsks);
    #}else{
    #	@spare_disk = spare_count_cmode(Node   => $Node, run_local => 'Y');
    #my $dsks = _print_array(\@spare_disk);
    #	logcomment("Filer : $FILER_C :  Number of Spares drives belongs to the filer are ".scalar @spare_disk." and the spares are:\n".$dsks);
    #}

    @spare_disk = spare_count_cmode( Node => $Node, run_local => 'Y', waiting => 'yes' );
    if ( scalar @spare_disk ) {
        my $dsks = _print_array( \@spare_disk );
        logcomment( "Filer : $FILER_C :  Number of Spares drives belongs to the filer are " . scalar @spare_disk . " and the spares are:\n" . $dsks );
    } else {
        logcomment("Filer : $FILER_C : NO SPARE DRIVES available on the filer : hint :- drives might be FAILED/NO SPARES present");
        return 0;
    }
    my $max_time = get_max_timeout( node_present => [$Node] );
    my $max_timeout_sec = int( ( $max_time * 2 ) + 300 );
    my $max_time_hr = $max_timeout_sec / (3600);
    my ( $s, $m, $h ) = gmtime($max_timeout_sec);
    logcomment("Filer : $FILER_C : Script will wait maximum of $max_time_hr Hrs (i.e) $h HRS $m MINS $s SECS to zero the spares");
    my $Transit_obj = NACL::Transit->new( name => $FILER_C );
    my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );

    if ( $filer_state =~ /(CLI|UP)/ ) {
        my $API_obj = $Node->get_7m_or_nodescope_apiset();
        $API_obj->set_timeout( "connectrec-timeout" => 7200 );
        $API_obj->execute_command( 'command' => "disk zero spares" );
        sleep 180;
        my $kill_time = time + $max_timeout_sec;
        while ( $kill_time > time ) {
            my $out = $API_obj->execute_command( 'command' => "aggr status -s" );
            if ( $out !~ /not zeroed|zeroing/ig ) {
                logcomment("Filer : $FILER_C : Disk zero spares completed.");
                $flag = 1;
                last;
            } else {
                logcomment("Filer : $FILER_C : Disk zero spares is in progress, waiting for disk zero spares to complete");
                sleep 300;
            }
        }
        if ($flag) {
            return 1;
        } else {
            logcomment("Filer : $FILER_C : Disks did NOT get zeroed after waiting for a time of $max_time_hr");
            return 0;
        }
    } else {
        logcomment("Filer : $FILER_C : Filer is NOT in CLI/UP, disk zero spares command will NOT work, so returning to main script");
        return 0;
    }

}
######################################################################################

=head2 comp_disk_qual_t12
	Arjun.lavu@netapp.com
    my $ret = comp_disk_qual_t12(disk_qual_t12_before => $hash_add_before, disk_qual_t12_after => $hash_add_after);
    This routine returns 1 - values are identical
			 0 - values are not matching
			-1 - if disk_qual not executed on all drives

The following named arguments are accepted,

=over

=item disk_qual_t12_before

(Required) : hash address of  disk_qual structure before

=item disk_qual_t12_after

(Required) : hash address of disk_qual structure later

=item nm_error
(Optional) : Non-medium error neeeds to compare?

=back

=cut

#######################################################################################
sub compare_disk_qual_t12 {
    my (%opts) = validate(
        @_,
        {
            disk_qual_t12_before => { type => HASHREF },
            disk_qual_t12_after  => { type => HASHREF },
            nm_error             => { type => SCALAR, default => 'Y', optional => 1 },
            logdir               => { type => SCALAR, default => undef, optional => 1 },
            Phy_count            => { type => HASHREF, default => undef, optional => 1 },

        }
    );
    my $fail                 = 0;
    my $disk_qual_t12_before = $opts{disk_qual_t12_before};
    my $disk_qual_t12_after  = $opts{disk_qual_t12_after};
    my $nm_error             = $opts{nm_error};
    my $logdir               = $opts{logdir} if ( defined $opts{logdir} );
    my $phy_count            = $opts{Phy_count} if ( defined $opts{Phy_count} );

    my @before = keys %{$disk_qual_t12_before};
    my @after  = keys %{$disk_qual_t12_after};
    if ( scalar @before != scalar @after ) {
        logcomment("**WARNING** : Since disk_qual has NOT run properly for all the drives, NOT comparing the values");    #BURT 1025104 - abalaji
        my $dsks = _print_array( \@before );
        logcomment( "disk_qual has run before for " . scalar @before . " number of drives and the drives are:\n" . $dsks );
        my $dsks = _print_array( \@after );
        logcomment( "disk_qual has run after for " . scalar @after . " number of drives and the drives are:\n" . $dsks );
        return (-1);                                                                                                      #BURT1025104 - abalaji
    }
    my %non_med_err_delta;
    my %non_med_err_vales;
    my @Models;
    my $flag_file = 0;
    my %disk_qual;
    my ($actual_log_dir) = $logdir =~ /(\S+)\/HDD/;
    my $logdir1 = $actual_log_dir . "/disk_qual_cnt_$parse_id.log";
    logcomment("DEBUG: Logdir is Present $logdir1");

    if ( -e $logdir1 ) {
        $flag_file = 1;
        open( Fh, "<$logdir1" ) or die "failed to open the File";
        my @file1 = ;
        close Fh;
        foreach my $line (@file1) {
            my ( $dsk, $count ) = ( $line =~ /\w+\.(\w+\.\w+)\s*(\d+)/i );
            $disk_qual{$dsk} = $count;
        }
    } else {
        logcomment("LOG is NOT present $logdir1");
    }

    #print Dumper( \%disk_qual );
    my $non_med_key;
    foreach my $dsk ( keys %$disk_qual_t12_before ) {
        my $count = 0;
        $count = $disk_qual{$dsk} if ( exists $disk_qual{$dsk} );
        my ( @keys, @keys1 );
        @keys  = keys %{ $disk_qual_t12_before->{$dsk} } if ( defined $disk_qual_t12_before->{$dsk} );
        @keys1 = keys %{ $disk_qual_t12_after->{$dsk} }  if ( defined $disk_qual_t12_after->{$dsk} );
        if ( scalar @keys != scalar @keys1 ) {

            # logcomment("For the DISK : $dsk : there is a difference in list of data from both the disk_qual commands");
            # logcomment("WARNING :: For the DISK : $dsk : Number of Attributes before are :: ".scalar @keys." and AFTER are :: ".scalar @keys1);
            # $fail = 1;
        }
        if ( $nm_error ne 'Y' ) {
            foreach (@keys) {
                my $after = $disk_qual_t12_after->{$dsk}->{$_};
                $after =~ s/^\s*|\s*$//g;
                my $before = $disk_qual_t12_before->{$dsk}->{$_};
                $before =~ s/^\s*|\s*$//g;
                if ( $_ !~ /Attribute_/i ) {
                    if ( $_ =~ /Non-medium Error Count/ig ) {
                        $non_med_key = $_;
                        my $model = $Non_Medium_Model{$dsk};
                        push( @Models, $model ) unless grep { $_ eq $model } @Models;
                        if ( ( !defined $before ) || ( !defined $after ) ) {
                            logcomment("**WARNING**: For the disk :: $dsk \"$_\" values are NOT present ,---> before ( $before ) and after ( $after ) <--- ");
                            next;
                        } elsif ( $after == $before ) {
                            logcomment( "Disk - $dsk : $_ values are matching,\t ---> before ( $before ) and after ( $after ) <--- Delta " . ( $after - $before ) . "" );
                            $fail = 0;
                        } elsif ( $after > $before ) {
                            push( @{ $non_med_err_delta{$model}{$count}{ $after - $before } }, $dsk );
                            $non_med_err_vales{$dsk} = " Value of $_ has been increased ---> Before ( $before ) and After ( $after ) <--- Delta " . ( $after - $before ) . "";
                            $fail = 1;
                        } elsif ( $after < $before ) {
                            push( @{ $non_med_err_delta{$model}{$count}{ $before - $after } }, $dsk );
                            $non_med_err_vales{$dsk} = " Value of $_ has been Decreased ---> Before ( $before ) and After ( $after ) <--- Delta " . ( $before - $after ) . "";
                            $fail = 1;
                        }
                    }
                } else {
                    $fail = 0;
                    logcomment("Since the disk_qual output is in Attribute Format, NOT Comparing the values");
                    return $fail;
                }
            }
        } else {
            foreach (@keys) {
                if ( ( $_ =~ /Non-medium Error Count/i ) || ( $_ =~ /Total Write errors/ig ) || ( $_ =~ /Total Read errors/ig ) || ( $_ =~ /Read ECC OTF/ig ) ) {
                    my $after = $disk_qual_t12_after->{$dsk}->{$_};
                    $after =~ s/^\s*|\s*$//g;
                    my $before = $disk_qual_t12_before->{$dsk}->{$_};
                    $before =~ s/^\s*|\s*$//g;
                    if ( $before > $after ) {
                        logcomment("**WARNING** : For the disk $dsk the value of $_ is GREATER when compared with after value");
                        logcomment("The values of [$_] are ----> before ($before) and after ($after) <----");
                        $fail = 1;
                    } else {
                        logcomment("Disk - $dsk : values of $_ are matching");
                    }
                } elsif ( ( ( $_ =~ /Power on time/ig ) && ( $parse_id !~ /201_NADQ02_Disk_Qual_WRV/i ) ) || ( ( $_ =~ /Total bytes proces/ig ) && ( $parse_id !~ /201_NADQ02_Disk_Qual_WRV/i ) ) ) {
                    my $after = $disk_qual_t12_after->{$dsk}->{$_};
                    $after =~ s/^\s*|\s*$//g;
                    my $before = $disk_qual_t12_before->{$dsk}->{$_};
                    $before =~ s/^\s*|\s*$//g;
                    if ( $before > $after ) {
                        logcomment("**WARNING** : For the disk $dsk the value of [$_] is GREATER when compared with after value");
                        logcomment("The values of [$_] are ----->before ($before) and after ($after) <-----");
                        $fail = 1;
                    } else {
                        logcomment("Disk - $dsk : values of $_ are matching");
                    }
                } else {
                    if ( ( ( $_ =~ /Power on time/ig ) || ( $_ =~ /Total bytes proces/ig ) ) && ( $parse_id =~ /201_NADQ02_Disk_Qual_WRV/ ) ) {
                    } else {
                        my $after = $disk_qual_t12_after->{$dsk}->{$_};
                        $after =~ s/^\s*|\s*$//g;
                        my $before = $disk_qual_t12_before->{$dsk}->{$_};
                        $before =~ s/^\s*|\s*$//g;
                        if ( $before != $after ) {
                            logcomment("**WARNING** : For the disk $dsk the values of [$_] are NOT matching");
                            logcomment("The values of [$_] are --->before ($before) and after ($after) <---");
                            $fail = 1;
                        } else {
                            logcomment("Disk - $dsk : values of $_ are matching");
                        }
                    }
                }
            }
        }
    }    #non_med_err_valesi
    if (%non_med_err_delta) {
        foreach my $model (@Models) {
            logcomment("**DEBUG** : Model : $model");
            my @count_dsk = keys %{ $non_med_err_delta{$model} };
            foreach my $cnt (@count_dsk) {
                my @delta_val = keys %{ $non_med_err_delta{$model}{$cnt} };
                if ( ( scalar @delta_val > 1 ) && (%non_med_err_delta) ) {
                    logcomment("DEBUG: More than one Delta values are present : @delta_val for Count $cnt");

                    #more than 1 delta value for the count(number of times the drive is executing disk_qual start in test)
                    $fail = 1;
                    my %injection = ();
                    my @drive;
                    foreach my $delta_1 (@delta_val) {
                        @drive = @{ $non_med_err_delta{$model}{$cnt}{$delta_1} };
                        if ( defined $phy_count ) {
                            logcomment("**DEBUG** : calculating (N-Me / PWR_CYCL) should be same for the drives ");
                            foreach my $dsk (@drive) {
                                my $NME = $disk_qual_t12_after->{$dsk}->{$non_med_key};
                                my ( $self, $bay ) = ( $dsk =~ /(\w+)\.(\w+)/i );
                                my $PHC = $phy_count->{$self}->{$bay}->{'Power cycle count'};
                                my $inj_cnt = int( $NME / $PHC ) if ( $PHC > 0 );
                                push( @{ $injection{$inj_cnt} }, $dsk );
                                logcomment("**DEBUG** : Disk: $dsk\t\t Delta : $delta_1\t\tNME : $NME\t\tPwr-Cycl : $PHC\t\t Cnt/inj : $inj_cnt");
                            }
                        } else {
                            grep { logcomment("**WARNING**: Disk  - $_ : $non_med_err_vales{$_}") } @drive;
                        }
                    }
                    if ( defined $phy_count ) {
                        if ( scalar( keys %injection ) == 1 ) {
                            grep { logcomment(" Disk  - $_ : $non_med_err_vales{$_}") } @drive;
                        } else {
                            grep { logcomment("**WARNING**: Disk  - $_ : $non_med_err_vales{$_}") } @drive;
                        }
                    }
                } elsif ( ( scalar @delta_val == 1 ) && (%non_med_err_delta) ) {
                    foreach my $delta_1 (@delta_val) {
                        my @arr = @{ $non_med_err_delta{$model}{$cnt}{$delta_1} };
                        grep { logcomment(" Disk  - $_ : $non_med_err_vales{$_}") } @arr;
                    }
                }
            }
        }
    }

    #unlink $logdir1;
    if ( $fail == 1 ) {
        return (0);
    }
    return (1);
} ## end sub compare_disk_qual_t12

#######################################################################################
## Author Arjun Lavu
## Description :: This subroutine will delete the mini_disks if present in the filer
#######################################################################################
sub delete_mini_disk {
    my (%opts) = validate(
        @_,
        {
            node              => { type => OBJECT },
            verify            => { type => SCALAR, optional => 1, default => 'N' },
            zero_after_delete => { type => SCALAR, optional => 1, default => 'n' }
        }
    );
    my $node              = $opts{node};
    my $zero_after_delete = $opts{zero_after_delete};
    if ( $zero_after_delete =~ /y/i ) {
        $zero_after_delete = 'y';
    } else {
        $zero_after_delete = 'n';
    }
    my $verify      = $opts{verify};
    my $FILER       = $node->name();
    my $Host        = host($FILER);
    my $transit_obj = NACL::Transit->new( name => $Host );
    my $filer_state = $transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    my ( %disk_object, @disks );
    if ( $filer_state =~ /MAINT/i ) {
        my $console = Tharn::connect("$FILER#console");

        # Set the properties for the Connectrec used for creating the APIset
        $console->{prompts}  = [qr/\*>/];
        $console->{max_idle} = 600;
        $console->{on_idle}  = sub { $console->execute(""); };
        my $Api_Set_Obj = NACL::APISet->new(
            connection => $console,
            category   => "Node",
            interface  => "CLI",
            set        => "Maintenance"
        );
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
        my ( @dele_mini, @normal_disk, $flag );
        logcomment("DEBUG:$FILER :Checking if any minidisk present in the filer");
        my $check = $Api_Set_Obj->execute_raw_command( 'command' => "mini_disk list" );

        if ( $check =~ /this command is only available in development kernels/ ) {
            logcomment("**FATAL** : $FILER : Kernel does NOT support the mini_disk options");
            logresult( 'FATAL', "$FILER : KERNEL DOESN'T SUPPORT THE MINI_DISK OPTIONS" );
        }

        my $res       = $Api_Set_Obj->mini_disk_list();
        my @disks_obj = @{ $res->get_parsed_output() };
        foreach (@disks_obj) {
            push( @disks, $_->{disk} );
            $disk_object{ $_->{disk} } = $_;
        }
        if (@disks) {
            my $dsks = _print_array( \@disks );
            logcomment( "$FILER : mini_disk list output gives total " . scalar @disks . " number of disks and the disks are:\n" . $dsks );
        } else {
            logcomment( "$FILER : mini_disk list output gives total " . scalar @disks . " number of disks" );
        }
        my $filer_disks = disk_show_drive_maint( API_Obj => $Api_Set_Obj, Filer => $FILER );
        my @filer_disks = @{ $filer_disks->{'driveA'} };
        my $dsks        = _print_array( \@filer_disks );
        logcomment( "$FILER : Total disks of the filer are " . scalar @filer_disks . " and the disks are:\n" . $dsks );
        logcomment("DEBUG:$FILER : Checking, out of these disks all are mini disks are not");
        my @matched_mini_disks = _intersect( \@filer_disks, \@disks );
        if (@matched_mini_disks) {
            my $dsks = _print_array( \@matched_mini_disks );
            logcomment( "$FILER : matched number of disks of the filer are " . scalar @matched_mini_disks . " and the disks are:\n" . $dsks );
        } else {
            logcomment( "$FILER : matched number of disks of the filer are " . scalar @matched_mini_disks );
        }
        foreach my $drive (@matched_mini_disks) {
            my $disk = $disk_object{$drive};    ##returns the disk object;
            if ( $disk->{type} ne "NORMAL disk" ) {
                push( @dele_mini, $disk->{disk} );
            } elsif ( $disk->{type} eq "NORMAL disk" ) {
                push( @normal_disk, $disk->{disk} );
            }
        }
        if ( (@normal_disk) && (@dele_mini) ) {
            my $dsks = _print_array( \@dele_mini );
            logcomment( "$FILER : Number of minidisks already present are " . scalar @dele_mini . " and the disks are:\n" . $dsks );
            my $dsks = _print_array( \@normal_disk );
            logcomment( "$FILER : Number of normal disks present are " . scalar @normal_disk . " and the disks are:\n" . $dsks );
            $flag = 1;
        } elsif ( (@dele_mini) && ( $verify =~ /Y/i ) ) {
            my $dsks = _print_array( \@dele_mini );
            logcomment( "$FILER : Number of minidisks already present are " . scalar @dele_mini . " and the disks are:\n" . $dsks );
            $flag = 0;
        } elsif ( (@dele_mini) && ( $verify =~ /N/i ) ) {
            my $dsks = _print_array( \@dele_mini );
            logcomment( "$FILER : Number of minidisks present are " . scalar @dele_mini . " and the disks are:\n" . $dsks );
            $flag = 1;
        } else {
            $flag = 2;
        }
        if ( $flag == 1 ) {
            logcomment("$FILER : Deleting Mini disks");
            try {
                my $prompts_answers = [ 'Are you sure you want to continue?' => 'y', 'Would you like to zero newly deleted minidisks now?' => "$zero_after_delete" ];
                $Api_Set_Obj->execute_raw_command( 'command' => "mini_disk delete @dele_mini", 'connectrec-match_table' => $prompts_answers );
                sleep 60;

                #$Test->nlog( "Response get_parsed_output:\n". Dumper( $response->get_parsed_output() ) );
            }
            catch NACL::APISet::Exceptions::ResponseException with {
                my $exception_object = shift;
                my $resp             = $exception_object->get_response_object();
                logcomment( "Caught a " . ref($exception_object) . "!" );
                logcomment( "Error is: " . $exception_object->text() );
                logcomment( "Raw output was:\n" . $resp->get_raw_output() );
                logcomment("**FATAL** : $FILER : Could NOT delete mini-disks");
                logresult( 'FATAL', "$FILER : COULDN'T DELETE MINI-DISKS" );
            };
            return 1;
        } else {
            if ( $flag == 0 ) {
                my $dsks = _print_array( \@dele_mini );
                logcomment( "$FILER : User selected option verify 'y', so not deleting the the Minidisks:\n" . $dsks );
                return "ignore";
            } elsif ( $flag == 2 ) {
                logcomment("$FILER : NO MINIDISKS present in the filer");
                return undef;
            }
        }
    } else {
        logcomment("**FATAL** : $FILER is NOT in maintenance mode,so CANNOT delete the mini_disk");
        logresult( 'FATAL', "$FILER : IS NOT IN MAINTENANCE MODE,SO CANNOT DELETE THE mini_disk" );
    }

    #sub _intersect(\@\@);
    sub _intersect($$) {
        my %e = map { $_ => undef } @{ $_[0] };
        return grep { exists( $e{$_} ) } @{ $_[1] };
    }
}
##########################################################################################################
## Author Arjun Lavu
## Description :: This subroutine will create the new node object based on the nodes which are passed
########################################################################################################
sub node_new_obj {
    my (%opts) = validate( @_, { node_array => { type => ARRAYREF }, } );
    my $node_ref    = $opts{node_array};
    my @Nodes_array = @{$node_ref};
    my @NODES_FINAL;

    my $Mode = $Nodes_array[0]->mode();
    logcomment("DEBUG:Mode of the filer passed is $Mode");
    foreach (@Nodes_array) {
        my $Filer = $_->name();
        $_->refresh_command_interface();
        logcomment("DEBUG:Getting the new object for the $Filer");
    }
    my @temp_nodes = NACL::C::Node->find();    # Find Nodes/Filers used in the test, Based on FILER param.
    my %nodes_filer;
    foreach my $Node (@temp_nodes) {
        $Node->refresh_command_interface();
        my $FILER_C = $Node->name();
        $nodes_filer{$FILER_C} = [$Node];
    }
    my @Nodes_again = map { @{$_} } values(%nodes_filer);
    if ( $Mode =~ /CMode/i ) {
        foreach my $main (@Nodes_array) {
            foreach my $sub (@Nodes_again) {
                my $first = $main->name();
                my $sec   = $sub->name();
                if ( $first eq $sec ) {
                    push( @NODES_FINAL, $sub );
                }
            }
        }
    } else {
        logcomment("Filer is in 7Mode, subroutine will NOT work");
        return @Nodes_array;
    }
    return @NODES_FINAL;
}
##########################################################################################################
## Author Arjun Lavu
## Description :: This subroutine will create mini_disks
## parameters :: size - size of mini_disk, node- Node object
##########################################################################################################
sub create_mini_disk {
    my (%opts) = validate(
        @_,
        {
            node => { type => OBJECT },
            size => { type => SCALAR }
        }
    );
    my $node        = $opts{node};
    my $size        = $opts{size};
    my $FILER       = $node->name();
    my $Host        = host($FILER);
    my $transit_obj = NACL::Transit->new( name => $Host );
    my $filer_state = $transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    if ( $filer_state =~ /MAINT/i ) {
        my $console = Tharn::connect("$FILER#console");

        # Set the properties for the Connectrec used for creating the APIset
        $console->{prompts}  = [qr/\*>/];
        $console->{max_idle} = 600;
        $console->{on_idle}  = sub { $console->execute(""); };
        my $Api_Set_Obj = NACL::APISet->new(
            connection => $console,
            category   => "Node",
            interface  => "CLI",
            set        => "Maintenance"
        );
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
        my $result = $Api_Set_Obj->execute_raw_command( 'command' => "sysconfig -v" );
        my @group = $result =~ /:\s*\S+\s*\S+\s+\S+\s+(\S+)GB/g;
        my ( $least_size, $mini_size );
        @group = sort { $a <=> $b } @group;
        $least_size = $group[0];
        logcomment("Minimum disk size is $least_size GB");

        if ( $size =~ /1/ ) {
            $mini_size = sprintf( "%.0f", $least_size * .1 );
        } else {
            $mini_size = sprintf( "%.0f", $least_size * .5 );
        }
        if ( $mini_size < 10 ) {
            logcomment("Since the size calculated $mini_size GB is less than 10GB, the size of mini disks which will be created will be 10GB");
            $mini_size = 10000;
        } elsif ( $mini_size > 70 ) {
            logcomment("Since the size calculated $mini_size GB is more than 72000MB, the size of mini disks which will be created will be 72000MB");
            $mini_size = 72000;
        } else {
            $mini_size = $mini_size * 1000;
        }
        logcomment("Size of the mini disk is : $mini_size MB");
        $mini_size = $mini_size . "MB";
        my $disk = disk_show_drive_maint( API_Obj => $Api_Set_Obj, Filer => $FILER );
        my @disks = @{ $disk->{'driveA'} };
        if ( !scalar @disks ) {
            logcomment("**FATAL** : Filer - $FILER : NO DISKS available on the filer to create mini_disks");
            logresult( 'FATAL', "Filer - $FILER : NO DISKS AVAILABLE ON THE FILER TO CREATE MINI_DISKS" );

            #return 0;
        }
        logcomment("$FILER : All the drives on which mini_disks are going to create are @disks");
        my $TIME_OUT = ( scalar @disks * 100 ) + 300;
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => $TIME_OUT );
        try {
            my $prompts_answers = [ 'Are you sure you want to continue?' => 'y', 'Would you like to zero newly created minidisks now?' => 'n' ];
            $Api_Set_Obj->execute_raw_command( 'command' => "mini_disk create $mini_size @disks", 'connectrec-match_table' => $prompts_answers );
            sleep 60;
        }
        catch NACL::APISet::Exceptions::ResponseException with {
            my $exception_object = shift;
            my $resp             = $exception_object->get_response_object();
            logcomment( "Caught a " . ref($exception_object) . "!" );
            logcomment( "Error is: " . $exception_object->text() );
            logcomment( "Raw output was:\n" . $resp->get_raw_output() );
            logcomment("**FATAL** : $FILER :  MINI_DISK creation FAILED");
            logresult( 'FATAL', "$FILER : MINI_DISK CREATION FAILED" );
        };
        return 1;
    } else {
        logcomment("**FATAL** : $FILER : Is NOT in maintenance mode, so cannot create mini_disk");
        logresult( 'FATAL', "$FILER : IS NOT IN MAINTENANCE MODE, SO CANNOT CREATE mini_disk" );
    }
}

##########################################################################################################
## Author Arjun Lavu
## Description :: Displays the version of pNATE and NDATE
##########################################################################################################
sub pnate_versions_display {

    # my (%opts) = validate(
    # @_,
    # {
    # Test   => { type => OBJECT },
    # }
    # );
    # my $Test = $opts{Test};
    my $Home = $ENV{HOME};
    $Home = trim($Home);
    if ( ( -e "$Home/.pnate_ndate_debug" ) || ( -d "$Home/NDATE/pnate" ) ) {
        my $Home = $ENV{HOME};
        $Home = trim($Home);
        my $NDATE_path = "$Home/NDATE_ver";

        #push(@INC, "$Home/archives/install/lib"); # Req for old pnate installation
        if ( -d "$Home/NDATE/pnate/lib" ) {
            push( @INC, "$Home/NDATE/pnate/lib" );
            require PNATE;
        }

        if ( -d "$Home/NDATE/pnate/bin" ) {
            my $osversion = `$Home/NDATE/pnate/bin/sfwmnt`;
            $osversion = trim($osversion);
            logcomment("Running on the OS: $osversion");
        }

        # my ($staf_os) = @_;
        my ( $stf_ver, $inst, @staf );
        ##get the staf version
        #opendir(READDIR, "$Home/NDATE/pSTAF/$staf_os");# Req for old pnate installtion
        opendir( READDIR, "$Home/NDATE/pSTAF" );
        @staf = readdir(READDIR);
        closedir(READDIR);

        foreach my $dirs (@staf) {

            #if ($dirs =~ /staf\-/){ #Req for old pnate install
            if ( $dirs =~ /startSTAF/ ) {
                $dirs = trim($dirs);

                #$path = "$Home/NDATE/pSTAF/$staf_os/" . $dirs; # Req for old pnate install
                my $path = "$Home/NDATE/pSTAF";

                # logcomment("Presently I am in directry $path");
                open( INST, "$path/install.properties" );

                while ( $inst =  ) {
                    if ( $inst =~ /version=(\S+)/i ) {
                        $stf_ver = $1;

                        # logcomment("Installed STAF version $stf_ver");
                        last;
                    }
                }
                close(INST);
                last;
            }
        }

        # Get the pNATE build version
        open( READ, "$Home/README" ) || logcomment("FAILED to read the readme file");
        my $pbuild;
        while ( $inst =  ) {
            if ( $inst =~ /pnate\_(\w+)\.zip(?:.*)PNATE/ ) {
                $pbuild = $1;
                last;
            }
        }
        close(READ);

        # Reading NDATE_ver file to get the version number and build date
        my ( $major, $minor, $patch, $release, $date );
        my @ver_arr;
        open( NDATEVER, "$NDATE_path" ) || logcomment("CANNOT OPEN THE FILE $NDATE_path");
        my $var;
        while ( $var =  ) {
            $var =~ s/^\s+//;
            $var =~ s/\s+$//;
            @ver_arr = split( "=", $var );
            if ( $var =~ /NDTE_MAJOR_VERSION/ ) {
                $major = $ver_arr[1];
            } elsif ( $var =~ /NDTE_MINOR_VERSION/ ) {
                $minor = $ver_arr[1];
            } elsif ( $var =~ /NDTE_PATCH_VERSION/ ) {
                $patch = $ver_arr[1];
            } elsif ( $var =~ /NDTE_RELEASE_VERSION/ ) {
                $release = $ver_arr[1];
            } elsif ( $var =~ /DATE/ ) {
                $date = $ver_arr[1];
            }
        }
        close NDATEVER;
        my $VERSION;
        if ( $patch =~ /^\d+/ ) {
            $VERSION = "$major.$minor.$patch.$release";
        } else {
            $VERSION = "$major.$minor";
        }
        my $BUILD_DATE = "$date";

        #HARD CODED need to be modified
        $pbuild = '03-02-2016';
        my $pversion = PNATE::version_string();
        if ( $pversion =~ /3\.0\.6/ ) { $pversion = "3.0.7"; }
        my $pntver      = $pversion;
        my $pnNATEver   = NATE::version_string();
        my $STAFver     = 'STAF 3.4.10b_debug';
        my $version_str = "NDATE Build Version used    : $VERSION
NDATE Build Date             : $BUILD_DATE
PNATE Build Date             : $pbuild
PNATE Build Version          : $pntver
PNATE NATE Version           : $pnNATEver
PNATE STAF Version           : $STAFver";

=head
		my $version_str =
"NDATE Build Version used      : $VERSION
NDATE Build Date              : $BUILD_DATE
PNATE Build Date              : $pbuild
PNATE Build Version           : ".PNATE::version_string().
"\nPNATE NATE Version            : ".NATE::version_string().
"\nPNATE STAF Version            : ". "$stf_ver";
=cut

        #	logcomment("\n======================================================================================\n$version_str\n======================================================================================");
        logcomment(" NDATE and PNATE versions \n\n$version_str\n ");

        # $Test->nlog("======================================================================================");
        #$Test->nlog("--------------------------------------------------------------------------------------");
        #logcomment("pNATE is installed - Following are pNATE versions");
        # $Test->nlog("NDATE Build Version used     : $VERSION ");
        # $Test->nlog("NDATE Build Date             : $BUILD_DATE ");
        # $Test->nlog("PNATE Build Date             : ". $pbuild);
        # $Test->nlog("PNATE Build Version          : ". PNATE::version_string());
        # $Test->nlog("PNATE NATE  Version          : ". NATE::version_string());
        # $Test->nlog("PNATE STAF  Version          : ". $stf_ver);
        #$Test->nlog("--------------------------------------------------------------------------------------");
        # $Test->nlog("======================================================================================");

    }
}

################################################
###	Author Arjun.lavu@netapp.com
### description : update new kernel image on the filer
#################################################
sub compact_flash {
    my (%opts) = validate(
        @_,
        {
            Node     => { type => OBJECT },
            tar_file => { type => SCALAR },
        }
    );
    my $Node = $opts{Node};
    my $Home = $ENV{HOME};
    $Home = trim($Home);
    my $FILER    = $Node->name();
    my $tar_file = $opts{tar_file};
    my $flag     = 0;
    logcomment("Filer - $FILER : Installing Image");
    logcomment("Filer - $FILER : Image file given by the user is - $tar_file");
    my $host = host($FILER);
    my $Mode = $Node->mode();
    my ( $network_port,            $node_mgmt_ip,  $net_mask,     $gateway );
    my ( $cluster_mgmt_inter_port, $clust_mgmt_ip, $clu_net_mask, $clu_gateway );

    if ( -e "$Home/NDATE/FILER_INFO/$FILER" ) {
        logcomment("Configuration file found for the filer $FILER");
    } else {
        logcomment("**WARNING** : Could NOT find the configuration file for the filer $FILER");
    }
    if ( $Mode =~ /CMode/ig ) {
        my $host_file    = "$Home/NDATE/FILER_INFO/$FILER";
        my $filer_config = `cat $host_file`;
        if ( !$filer_config ) {
            logcomment("**WARNING** : NO DATA found in the configuration file $host_file");
        }
        foreach my $line ( split /\n/, $filer_config ) {
            $line = trim($line);
            if ( $line =~ /^MGMT_PORT\s*=\s*(\S+)/ ) {
                $network_port = $1;
                logcomment("Filer - $FILER : NODE_MANAGEMENT/Network port of the filer is $network_port");
            } elsif ( $line =~ /^MGMT_IP\s*=\s*(\S+)/ ) {
                $node_mgmt_ip = $1;
                logcomment("Filer - $FILER : NODE_MANAGEMENT_IP of the filer is $node_mgmt_ip");
            } elsif ( $line =~ /^MGMT_MASK\s*=\s*(\S+)/ ) {
                $net_mask = $1;
                logcomment("Filer - $FILER : NET_MASK of the filer is $net_mask");
            } elsif ( $line =~ /^MGMT_GATEWAY\s*=\s*(\S+)/ ) {
                $gateway = $1;
                logcomment("Filer - $FILER : Gateway of the filer is $gateway");
            } elsif ( $line =~ /^CLUSTER_MGMT_PORT\s*=\s*(\S+)/ ) {
                $cluster_mgmt_inter_port = $1;
                logcomment("Filer - $FILER : Cluster management port is $cluster_mgmt_inter_port");
            } elsif ( $line =~ /^CLUSTER_MGMT_IP\s*=\s*(\S+)/ ) {
                $clust_mgmt_ip = $1;
                logcomment("Filer - $FILER : Cluster management IP is $clust_mgmt_ip");
            } elsif ( $line =~ /^CLUSTER_MGMT_MASK\s*=\s*(\S+)/ ) {
                $clu_net_mask = $1;
                logcomment("Filer - $FILER : Cluster management mask is $clu_net_mask");
            } elsif ( $line =~ /^CLUSTER_MGMT_GATEWAY\s*=\s*(\S+)/ ) {
                $clu_gateway = $1;
                logcomment("Filer - $FILER : Cluster management gateway is $clu_gateway");
            }
        }
    } else {
        my $host_file    = "$Home/NDATE/FILER_INFO/$FILER";
        my $filer_config = `cat $host_file`;
        if ( !$filer_config ) {
            logcomment("**WARNING** : NO DATA found in the configuration file $host_file");
        }
        foreach my $line ( split /\n/, $filer_config ) {
            $line = trim($line);
            if ( $line =~ /^IFC\s*=\s*(\S+)/ ) {
                $network_port = $1;
                logcomment("Filer - $FILER : Network port of the filer is $network_port");
            } elsif ( $line =~ /^default_ip\s*=\s*(\S+)/ ) {
                $node_mgmt_ip = $1;
                logcomment("Filer - $FILER : IP is $node_mgmt_ip");
            } elsif ( $line =~ /^MASK\s*=\s*(\S+)/ ) {
                $net_mask = $1;
                logcomment("Filer - $FILER : NET_MASK of the filer is $net_mask");
            } elsif ( $line =~ /^GATEWAY\s*=\s*(\S+)/ ) {
                $gateway = $1;
                logcomment("Filer - $FILER : Gateway of the filer is $gateway");
            }
        }
    }

    #---------------------------------------------------------------------
    #Checking whether all required values are properly read or not
    #---------------------------------------------------------------------
    logcomment("IFC Port NOT found!!! ")       if ( !$network_port );
    logcomment("Filer IP NOT found!!! ")       if ( !$node_mgmt_ip );
    logcomment("Net_mask Value NOT found!!! ") if ( !$net_mask );
    logcomment("Gateway IP NOT found!!! ")     if ( !$gateway );

    if ( ( !$network_port ) || ( !$node_mgmt_ip ) || ( !$net_mask ) || ( !$gateway ) ) {
        logcomment("**FATAL** : One or more important credentials of the filer - $FILER are MISSING, please check the filer configuration file and re-run the test again");
        logresult( 'FATAL', "ONE OR MORE IMPORTANT CREDENTIALS OF THE FILER - $FILER ARE MISSING,Please check the Filer configuration file and re-run the test again" );
    }

    #---------------------------------------------------------------------
    #Checking the Filer state, at the end filer will be booted with the current state at the moment
    #---------------------------------------------------------------------
    my $Transit_obj = NACL::Transit->new( name => $FILER );
    $Transit_obj->set( 'timeout' => 600, maxcycle => 20 );
    my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    logcomment("Filer - $FILER state is $filer_state");
    if ( $filer_state =~ /CLI|UP/ ) {
        logcomment("filer :$FILER  is in CLI, Set privilage to test");
        my $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset( connid => "console" );
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
        my $prompts_answers = [ ".*Do you want to continue.*" => 'y' ];
        $Api_Set_Obj->execute_raw_command(
            'command'                => "set test",
            'connectrec-match_table' => $prompts_answers
        );
    }
    ################################################
    ##requirements to create server object
    ################################################
    my $prompt_fw;
    my $ignore_strings = [ "MADIMM\\d+->", "DIMM\\d+->", "^T>" ];
    my $prompt_array   = $host->prompt_fw();
    my $prompts        = join( "|", @$prompt_array );
    $prompt_fw = "($prompts)";
    logcomment("DEBUG:This is the prompt regex: $prompt_fw");
    my $Server = new Server( no_cli => 1 );
    $Server->set_execution_server( -Server => $FILER );    #set the execution server to the current node
    my @filer_working = $Server->servers();
    logcomment("Number of filers working are @filer_working");
    my $timeout = "7200";                                  # Change time-out in final code.

    #########################################################################################################
    #------ Changing state to LOADER setting AUTOBOOT to false then changing state to BOOT-MENU -------###
    #########################################################################################################
    try {
        logcomment(" Filer - $FILER : Changing state to Loader to set the option Autoboot to false");
        $Transit_obj->set( 'change_state_timeout' => 7200 );
        $Transit_obj->change_state( to => "FIRMWARE" );
        my $state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
        if ( $state =~ /FIRMWARE/ ) {
            logcomment("Filer is in Loader prompt, setting Autoboot to false");
            $Server->console(
                cmd                        => 'setenv AUTOBOOT false;unsetenv bootarg.bsdportname',
                additional_prompts_timeout => 60,
                ignore                     => $ignore_strings,
                additional_prompts         => { "$prompt_fw" => "FINAL_PROMPT", }
            );
        }
        logcomment(" Filer - $FILER : Changing state to boot-menu");
        $Transit_obj->set( 'change_state_timeout' => 7200 );
        $Transit_obj->change_state( to => "BOOT_MENU" );
    }
    catch NACL::Transit::Exceptions::RetriesExceeded with {
        logcomment("Expected: Caught a RetriesExceeded exception");
        logcomment("**WARNING** : Transit exceeded the max attempt");
    }
    catch NACL::Transit::Exceptions::TransitException with {
        my $exception_object = shift;
        logcomment( "Exception is of type: " . ref($exception_object) );
        logcomment( "Error text is: " . $exception_object->text() );
    }
    finally {
        logcomment("Reset fields 'timeout' and 'maxcycle'");
        $Transit_obj->set( 'timeout' => 700, maxcycle => 30 );
        $Transit_obj->set( 'change_state_timeout' => 600 );
        logcomment( "New object settings for timeout and maxcycle are: " . Dumper $Transit_obj->get( 'timeout', 'maxcycle' ) );
        $Transit_obj->set( 'change_state_timeout' => 7200 );
        $Transit_obj->change_state( to => "BOOT_MENU" );
    };

    ##########################################################
    ######  giving option 7 in the boot menu	###########
    ##########################################################
    try {
        logcomment("Filer - $FILER entering the option 7 to install image");
        $Server->console(
            cmd                        => "7",
            additional_prompts_timeout => $timeout,
            ignore                     => $ignore_strings,
            additional_prompts         => {
                ".*Do you want to continue.*"                                               => 'y',
                ".*Select the network port you want to use for the download.*"              => "$network_port",
                ".*The node needs to reboot for this setting to take effect.*"              => 'y',
                ".*The node must be rebooted to start using the newly installed software.*" => 'y',
                ".*Rebooting.*"                                                             => "FATAL_PROMPT",

                "$prompt_fw" => "FINAL_PROMPT",
            }
        );
    }
    catch NACL::Transit::Exceptions::Timeout with {    #Burt 1033916  nmamatha
        logcomment("Filer - $FILER : timeout exception");
        try {
            eval { $Server->console( cmd => " ", additional_prompts_timeout => $timeout, ignore => $ignore_strings, additional_prompts => { ".*Enter the IP address for port.*" => "$node_mgmt_ip", ".*Enter the netmask for port.*" => "$net_mask", ".*Enter IP address of default gateway.*" => "$gateway", ".*What is the URL for the package.*" => "$tar_file", ".*Verify that the network is properly configured, that the gateway is set.*" => "FATAL_PROMPT", ".*Verify that the URL is correct and points to a Data ONTAP.*" => "FATAL_PROMPT", ".*Verify that the gateway entered is correct.*" => "FATAL_PROMPT", ".*Verify that the server is configured correctly.*" => "FATAL_PROMPT", ".*contact Customer Support.*" => "FATAL_PROMPT", ".*not supported by this package.*" => "FATAL_PROMPT", ".*Verify file permissions on the server, and your user permissions.*" => "FATAL_PROMPT", ".*Retry.*" => 'FATAL_PROMPT', ".*This platform is not supported in this release.*" => "FATAL_PROMPT", ".*The system will now halt.*" => "FATAL_PROMPT", ".*Please choose one of the following.*" => '8', ".*Reboot now.*" => 'y', ".*What is the user name on.*" => "\n", ".*What is the password for.*" => "\013", ".*subsequent reboots?.*" => 'y', ".*Do you want to set the newly installed software as the default to be used for.*" => 'y', ".*The node must be rebooted to start using the newly installed software.*" => 'y', ".Rebooting.*" => "FINAL_PROMPT", "$prompt_fw" => "FINAL_PROMPT", } ); };
            if ($@) {
                if ( $@ =~ /This platform is not supported in this release/i ) {
                    logcomment("**FATAL**: The platform is NOT supported in the release ");
                    logresult( 'FATAL', "THE PLATFORM IS NOT SUPPORTED IN THE RELEASE" );
                }
            }
        }
        catch NATE::BaseException with {
            logcomment("Filer - $FILER : Verify that the network is properly configured, that the gateway is set or Verify that the URL is correct and points to a Data ONTAP OR Image is compatible or not");
            $Server->console(
                cmd                        => " ",
                additional_prompts_timeout => $timeout,
                ignore                     => $ignore_strings,
                additional_prompts         => {
                    ".*Retry.*"                              => 'n',
                    ".*Please choose one of the following.*" => '8',
                    ".*Reboot now.*"                         => 'y',
                    "$prompt_fw"                             => "FINAL_PROMPT",
                }
            );
            $flag = 1;
        };
        logcomment("Jumping to boot in require state");
        goto long;
    }
    catch NATE::BaseException with {
        sleep 120;
        my $state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
        if ( $state eq 'FIRMWARE' ) {
            logcomment("Filer - $FILER : Successfully rebooted");
        } elsif ( $state !~ /FIRMWARE|MAINT|CLI|UP/i ) {
            logcomment("Filer - $FILER : SOmething went WRONG with the rebooting, Changing filer state back to original state - $filer_state");
            $Transit_obj->set( 'change_state_timeout' => 7200 );
            $Transit_obj->change_state( to => "$filer_state" );
            $flag = 1;
            goto long;
        }
    };

    #####################################################################################
    ## giving the option boot_ontap in the boot-menu to give ip,mask,gateway etc ####
    #####################################################################################
    try {    #Burt 1033916  nmamatha
        eval { $Server->console( cmd => "boot_ontap", additional_prompts_timeout => $timeout, ignore => $ignore_strings, additional_prompts => { ".*Enter the IP address for port.*" => "$node_mgmt_ip", ".*Enter the netmask for port.*" => "$net_mask", ".*Enter IP address of default gateway.*" => "$gateway", ".*What is the URL for the package.*" => "$tar_file", ".*Verify that the network is properly configured, that the gateway is set.*" => "FATAL_PROMPT", ".*Verify that the URL is correct and points to a Data ONTAP.*" => "FATAL_PROMPT", ".*contact Customer Support.*" => "FATAL_PROMPT", ".*Verify that the server is configured correctly.*" => "FATAL_PROMPT", ".*Verify that the gateway entered is correct.*" => "FATAL_PROMPT", ".*not supported by this package.*" => "FATAL_PROMPT", ".*Verify file permissions on the server, and your user permissions.*" => "FATAL_PROMPT", ".*Retry.*" => 'FATAL_PROMPT', ".*This platform is not supported in this release.*" => "FATAL_PROMPT", ".*The system will now halt.*" => "FATAL_PROMPT", ".*Please choose one of the following.*" => '8', ".*Reboot now.*" => 'y', ".*What is the user name on.*" => "\n", ".*What is the password for.*" => "\013", ".*Do you want to set the newly installed software as the default to be used for.*" => 'y', ".*The node must be rebooted to start using the newly installed software.*" => 'y', ".Rebooting.*" => "FINAL_PROMPT", "$prompt_fw" => "FINAL_PROMPT", } ); };
        if ($@) {
            if ( $@ =~ /This platform is not supported in this release/i ) {
                logcomment("**FATAL**: The platform is NOT supported in the release ");
                logresult( 'FATAL', "THE PLATFORM IS NOT SUPPORTED IN THE RELEASE" );
            }
        }
    }
    catch NATE::BaseException with {
        logcomment("Filer - $FILER : Verify that the network is properly configured, that the gateway is set or Verify that the URL is correct and points to a Data ONTAP, NDATE will re-install using other available ports");
        $Server->console(
            cmd                        => " ",
            additional_prompts_timeout => $timeout,
            ignore                     => $ignore_strings,
            additional_prompts         => {
                ".*Retry.*"                              => 'n',
                ".*Please choose one of the following.*" => '8',
                ".*Reboot now.*"                         => 'y',
                "$prompt_fw"                             => "FINAL_PROMPT",
            }
        );
        $flag = 1;
    };
    $Server = undef;
    #####################################################################################
    ## Changing state to filer state which was $filer_state[which was there before] ####
    #####################################################################################
    sleep 60;
  long: my $state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    logcomment("DEBUG: Filer State is $state");
    if ( $flag == 1 ) {
        my $filer_state1 = "FIRMWARE";
        logcomment("Filer - $FILER changing state to $filer_state1");
        $Transit_obj->set( 'change_state_timeout' => 7200 );
        $Transit_obj->change_state( to => "$filer_state1" );
        if ( $state =~ /FIRMWARE/ig ) {
            $flag = 0;

            #		logcomment("Filer - $FILER checking state is  $filer_state");
            #		$Transit_obj->change_state( to => "$filer_state");
            logcomment("Filer - IP - $node_mgmt_ip of port $network_port FAILED, Re-Configuring with other available port");

            #my $rtn = re_image_recovery();
            my $Server = new Server( no_cli => 1 );
            $Server->set_execution_server( -Server => $FILER );    #set the execution server to the current node
            my @filer_working = $Server->servers();
            logcomment("Number of filers working are @filer_working");
            logcomment("Re-configuring port and installing image");
            logcomment("Port - $cluster_mgmt_inter_port will be used for installing image");

            #Check for State  - FIRMWARE
            my $state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
            if ( $state eq 'FIRMWARE' ) {
                logcomment("Filer - $FILER :is in LOADER, Proceeding with setting bsd port");
            }

            #Change bsdport to e0i/e0a/e0j - cluster management port
            $Server->console(
                cmd                        => "setenv bootarg.bsdportname $cluster_mgmt_inter_port;saveenv",
                additional_prompts_timeout => 60,
                ignore                     => $ignore_strings,
                additional_prompts         => { "$prompt_fw" => "FINAL_PROMPT", }
            );
            logcomment("Configured $cluster_mgmt_inter_port as network port to download image");

            #change to boot_menu
            logcomment("Reset fields 'timeout' and 'maxcycle'");
            $Transit_obj->set( 'timeout' => 700, maxcycle => 30 );
            $Transit_obj->set( 'change_state_timeout' => 7200 );
            logcomment( "New object settings for timeout and maxcycle are: " . Dumper $Transit_obj->get( 'timeout', 'maxcycle' ) );
            $Transit_obj->change_state( to => "BOOT_MENU" );

            #Select option 7 - Install image
            try {
                logcomment("Filer - $FILER Entering the option 7 to install image");
                $Server->console(
                    cmd                        => "7",
                    additional_prompts_timeout => $timeout,
                    ignore                     => $ignore_strings,
                    additional_prompts         => {
                        ".*Do you want to continue.*"                                                       => 'y',
                        ".*Select the network port you want to use for the download.*"                      => "$cluster_mgmt_inter_port",
                        ".*The node needs to reboot for this setting to take effect.*"                      => 'y',
                        ".*The node must be rebooted to start using the newly installed software.*"         => 'y',
                        ".*Enter the IP address for port.*"                                                 => "$clust_mgmt_ip",
                        ".*Enter the netmask for port.*"                                                    => "$clu_net_mask",
                        ".*Enter IP address of default gateway.*"                                           => "$clu_gateway",
                        ".*What is the URL for the package.*"                                               => "$tar_file",
                        ".*Verify that the network is properly configured, that the gateway is set.*"       => "FATAL_PROMPT",
                        ".*Verify that the URL is correct and points to a Data ONTAP.*"                     => "FATAL_PROMPT",
                        ".*contact Customer Support.*"                                                      => "FATAL_PROMPT",
                        ".*Verify that the server is configured correctly.*"                                => "FATAL_PROMPT",
                        ".*Interface $cluster_mgmt_inter_port does not exist.*"                             => "FATAL_PROMPT",
                        ".*Verify that the gateway entered is correct.*"                                    => "FATAL_PROMPT",
                        ".*not supported by this package.*"                                                 => "FATAL_PROMPT",
                        ".*Verify file permissions on the server, and your user permissions.*"              => "FATAL_PROMPT",
                        ".*Retry.*"                                                                         => 'FATAL_PROMPT',
                        ".*This platform is not supported in this release.*"                                => "FATAL_PROMPT",
                        ".*The system will now halt.*"                                                      => "FATAL_PROMPT",
                        ".*Please choose one of the following.*"                                            => '8',
                        ".*Reboot now.*"                                                                    => 'y',
                        ".*What is the user name on.*"                                                      => "\n",
                        ".*What is the password for.*"                                                      => "\013",
                        ".*Do you want to set the newly installed software as the default to be used for.*" => 'y',
                        ".*The node must be rebooted to start using the newly installed software.*"         => 'y',
                        ".Rebooting.*"                                                                      => "FINAL_PROMPT",
                        "$prompt_fw"                                                                        => "FINAL_PROMPT",
                        ".*Rebooting.*"                                                                     => "FINAL_PROMPT",
                        "$prompt_fw"                                                                        => "FINAL_PROMPT",
                    }
                );
            }
            catch NACL::Transit::Exceptions::Timeout with {
                logcomment("$FILER : Could NOT be reached, tried to access and failed with time out");
            }
            catch NATE::BaseException with {
                logcomment("Filer - $FILER : Verify network port conection and  URL is correct and points to existing kernel image ");
                $flag = 1;
            };
            logcomment("Wait for few min");
            sleep 30;
        }
    }
    if ( $flag == 1 ) {
        logcomment("**FAIL** : $FILER : Image installation has NOT done, check with network connection, port and access to image location");
        logresult( 'FAIL', "$FILER : IMAGE INSTALLATION HAS NOT DONE, CHECK WITH NETWORK CONNECTION, PORT AND ACCESS TO IMAGE LOCATION" );
        return 1;
    } else {
        logcomment("Filer - $FILER changing state to $filer_state");
        $Transit_obj->set( 'timeout' => 700, maxcycle => 30 );
        $Transit_obj->set( 'change_state_timeout' => 60000 );
        $Transit_obj->change_state( to => "$filer_state" );
    }
}
#################################################
### Author Arjun.lavu@netapp.com
### description : disk_qual stop in only file system
### Usage : Only or FullSteam kernel
#################################################
sub disk_qual_stop_file_system {
    my (%opts) = validate(
        @_,
        {
            Node      => { type => OBJECT },
            disk_list => { type => ARRAYREF, optional => 1, default => undef },
        }
    );
    my $Node    = $opts{Node};
    my $Mode    = $Node->mode();
    my $FILER_C = $Node->name();
    my $command = "run local \"priv set -q test;disk_qual stop -d all\"";
    my @disks;
    my $Transit_obj = NACL::Transit->new( name => $FILER_C );
    my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );    ##/etc/diskqual_output: No such file or directory
    logcomment("$FILER_C : Filer State is $filer_state");

    if ( ( $filer_state !~ /CLI|UP/ig ) || ( $Mode !~ /CMode/ig ) ) {
        logcomment("Filer : $FILER_C - filer is NOT either in cmode or in 7mode filesystem, so returning from the subroutine");
        return 0;
    }
    my $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
    $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
    $Api_Set_Obj->execute_raw_command( 'command' => "run local \"priv set -q test;rm /etc/diskqual_output\"" );
    $Api_Set_Obj->execute_raw_command( 'command' => "run local \"priv set -q test;disk_qual status\"" );
    my $dsk_out = $Api_Set_Obj->execute_raw_command( 'command' => "run local \"priv set -q test;rdfile /etc/diskqual_output\"" );
    if ( $dsk_out =~ /idle/ ) {
        logcomment("Filer : $FILER_C - Disk qual is idle");
        return 1;
    } elsif ( $dsk_out =~ /No such file or directory/ ) {
        logcomment("Filer : $FILER_C - DISK QUAL OUTPUT FILE IS NOT GENERATED");
        return 0;
    }
    logcomment("$FILER_C : DISK_QUAL is NOT idle, waiting for the 'disk_qual stop' to complete");
    if ( defined scalar @{ $opts{disk_list} } ) {
        @disks = @{ $opts{disk_list} };
        logcomment("Re-using the output from disk_list");
    } else {
        @disks = list_of_disk( Node => $Node );
    }
    $Api_Set_Obj->execute_raw_command( 'command' => "run local \"priv set -q test;rm /etc/diskqual_output\"" );    ##or else previous output will get mix
    my $dis_qua_stop = $Api_Set_Obj->execute_raw_command( 'command' => $command );
    my $timeout = ( ( scalar(@disks) * 60 ) + 600 );
    logcomment("DEBUG:Filer : $FILER_C - Waiting 120 seconds to get first prompt from 'disk_qual stop'");
    sleep(120);
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->set_timeout( "connectrec-timeout" => $timeout );
    my $kill_time = time + $timeout;

    while ( $kill_time > time ) {
        $Api_Set_Obj->execute_raw_command( 'command' => "run local \"priv set -q test;rm /etc/diskqual_output\"" );
        $Api_Set_Obj->execute_raw_command( 'command' => "run local \"priv set -q test;disk_qual status\"" );
        my $dsk_output = $Api_Set_Obj->execute_raw_command( 'command' => "run local \"priv set -q test;rdfile /etc/diskqual_output\"" );
        if ( $dsk_output !~ /idle/ ) {
            sleep 60;    #waiting for 1 min and again checking the while loop condition
        } elsif ( $dsk_output =~ /No such file or directory/i ) {
            logcomment("Filer : $FILER_C - Disk_qual Output file is NOT created, there must be some ERROR");
            return (0);
        } elsif ( $dsk_output =~ /idle/ ) {
            logcomment("Filer : $FILER_C - Disk_qual is stopped!!!");
            return (1);
        }
    }
    $Api_Set_Obj->execute_raw_command( 'command' => "run local \"priv set -q test;rm /etc/diskqual_output\"" );
    $Api_Set_Obj->execute_raw_command( 'command' => "run local \"priv set -q test;disk_qual status\"" );
    my $dsk_output = $Api_Set_Obj->execute_raw_command( 'command' => "run local \"priv set -q test;rdfile /etc/diskqual_output\"" );
    if ( $dsk_output !~ /idle/ ) {
        return (0);
    } else {
        logcomment("Filer : $FILER_C - Something wrong with the disk_qual stop");
        return (1);
    }
}

####################################
## Author : arjun.lavu@netapp.com
## executing wipeconfig command on the boot-menu
####################################
sub clean_config {
    my (%opts) = validate( @_, { Node => { type => OBJECT }, } );
    my $Node   = $opts{Node};
    my $FILER  = $Node->name();
    logcomment("Filer : $FILER - Cleaning the configuration");

    #$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$

    my $prompt_fw;
    my $ignore_strings = [ "MADIMM\\d+->", "DIMM\\d+->", "^T>" ];
    my $host           = host($FILER);
    my $prompt_array   = $host->prompt_fw();
    my $prompts        = join( "|", @$prompt_array );
    $prompt_fw = "($prompts)";
    logcomment("DEBUG:This is the prompt regex: $prompt_fw");
    my $Server = new Server( no_cli => 1 );

    #my $Server = new Server(nodes =>$FILER,no_cli=>1,filers_on_demand =>1);
    $Server->set_execution_server( -Server => $FILER );    #set the execution server to the current node
    my @filer_working = $Server->servers();
    logcomment("Number of filers working are @filer_working");
    my $timeout = 3600;

    #$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
    #logcomment("Filer - $FILER : Cleaning the configuration");
    my $Transit_obj = NACL::Transit->new( name => $FILER );
    $Transit_obj->set( 'timeout' => 600, maxcycle => 5 );
    ## Changing state to LOADER and setting AUTOBOOT false
    logcomment("Filer - $FILER : Changing state to Loader and setting Autoboot false");
    $Transit_obj->set( 'change_state_timeout' => 7200 );
    $Transit_obj->change_state( to => "FIRMWARE" );
    try {
        $Server->console(
            cmd                        => "setenv AUTOBOOT false",
            additional_prompts_timeout => $timeout,
            ignore                     => $ignore_strings,
            additional_prompts         => { "$prompt_fw" => "FINAL_PROMPT", }
        );
    }
    catch NATE::BaseException with {
        logcomment("Filer : $FILER Something went WRONG in setting autoboot");
    };
    logcomment("Filer : $FILER : Changing state to boot-menu");
    $Transit_obj->set( 'change_state_timeout' => 7200 );
    $Transit_obj->change_state( to => "BOOT_MENU" );
    logcomment("DEBUG:Filer : $FILER executing wipeconfig on the boot_menu");
    try {
        $Server->console(
            cmd                        => "wipeconfig",
            additional_prompts_timeout => $timeout,
            ignore                     => $ignore_strings,
            additional_prompts         => {
                ".*Are you sure you want to continue.*" => 'yes',
                "$prompt_fw"                            => "FINAL_PROMPT",
            }
        );
    }
    catch NATE::BaseException with {
        logcomment("Filer : $FILER  Inside first base exception");
    };
    try {
        $Server->console(
            cmd                        => "boot_ontap",
            additional_prompts_timeout => $timeout,
            ignore                     => $ignore_strings,
            additional_prompts         => { "$prompt_fw" => "FINAL_PROMPT", }
        );
    }
    catch NATE::BaseException with {
        logcomment("Filer : $FILER  Inside second base exception");
    };
    $Server = undef;
}

######################################################################
##Arjun.lavu@netapp.com
## Description :: Destroys root aggrgate in the filers
#################################################################
sub destroy_root_volume {
    my (%opts) = validate( @_, { Noderef => { type => ARRAYREF }, } );

    # my %FILER_API;
    my @Nodes = @{ $opts{Noderef} };
    foreach my $Node (@Nodes) {
        my $FILER_C     = $Node->name();
        my $Host        = host($FILER_C);
        my $Transit_obj = NACL::Transit->new( name => $FILER_C );
        my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
        logcomment("Filer : $FILER_C state is $filer_state");
        $Transit_obj->set( 'change_state_timeout' => 7200 );
        $Transit_obj->change_state( to => "MAINT" ) if ( $filer_state !~ /MAINT/i );
        logcomment("DEBUG: Creating API object for filer - $FILER_C");
        my $API_obj = NACL::APISet->new(
            hostobj   => $Host,
            category  => "Node",
            interface => "CLI",
            set       => "Maintenance"
        );
        $API_obj->set_timeout( "connectrec-timeout" => 7200 );
        disable_debug_msg( Node => $Node );

        # disable_dbg_msgs( host => $Host, filermode => "maint" );
        #my $output = $API_obj->execute_raw_command( 'command' =>"aggr status");
        my $prompts_answers = [ ".*Aggregate set.*" => '1' ];
        my $output = $API_obj->execute_raw_command( 'command' => "aggr status", 'connectrec-match_table' => $prompts_answers );
        sleep(5);
        $API_obj->execute_raw_command( 'command' => "" );
        my $output1 = $API_obj->execute_raw_command( 'command' => "" );
        $output = $output1 . $output;
        if ( $output =~ /No root aggregate|Please supply a number/ig ) {

            if ( $output =~ /failed|offline/ ) {
                foreach my $var ( split( /\n/, $output ) ) {
                    if ( $var =~ /failed/ ) {
                        $var =~ s/^\s+|\s+$//gi;
                        my ($aggr) = $var =~ /^(agg\S+)\s*/i;
                        if ( $aggr =~ /agg/i ) {
                            logcomment("Destroy the aggreagate");
                            my $prompts_answers1 = [ ".*you sure you want to destroy this aggregate.*" => 'yes', ".*Aggregate set.*" => '1' ];
                            my $res_destroy = $API_obj->execute_raw_command( 'command' => "aggr destroy $aggr -f", 'connectrec-match_table' => $prompts_answers1 );
                            sleep(30);
                            my $output1 = $API_obj->execute_raw_command( 'command' => "" );
                            $res_destroy = $res_destroy . $output1;
                            if ( $res_destroy =~ /Aggregate \'$aggr\' destroyed/ ) {
                                logcomment("$FILER_C: Root aggregate is destroyed");
                            } else {
                                logcomment("**WARNING** : $FILER_C: Root aggregate is NOT destroyed properlly , please try manually");
                            }
                        }
                    }
                }
            } else {
                logcomment("NO ROOT VOLUME exist on the filer $FILER_C");
                next;
            }
        } else {
            foreach my $var ( split( /\n/, $output ) ) {
                if ( $var =~ /root/i ) {
                    logcomment("Destroying the root aggregates on the filer $FILER_C ");
                    $var =~ s/^\s+|\s+$//gi;
                    my ($aggr) = $var =~ /^(\S+)\s*/i;
                    my $LOOP = 0;
                  LOOP1:
                    logcomment("Offline the aggregate before destroy");
                    my $prompts_answers = [ "Are you sure want to take the root aggregate.*" => 'yes' ];
                    my $output = $API_obj->execute_raw_command( 'command' => "aggr offline $aggr", 'connectrec-match_table' => $prompts_answers );

                    if ( $output =~ /Aggregate \'$aggr\' is (now|already) offline/ig ) {
                        logcomment("root aggr is offline ");
                    } else {
                        logcomment("**WARNING**:FAILED to offline the aggregate $aggr");
                    }
                    sleep(30);
                    logcomment("Destroy the aggreagate");
                    my $prompts_answers1 = [ ".*you sure you want to destroy this aggregate.*" => 'yes' ];
                    my $res_destroy = $API_obj->execute_raw_command( 'command' => "aggr destroy $aggr -f", 'connectrec-match_table' => $prompts_answers1 );
                    sleep(30);
                    if ( $res_destroy =~ /Aggregate \'$aggr\' destroyed/ ) {
                        logcomment("$FILER_C: Root aggregate is destroyed");
                    } else {
                        logcomment("$FILER_C: Root aggregate is NOT destroyed properlly , please try once again");
                        $LOOP++;
                        last if ( $LOOP > 2 );
                        goto LOOP1;
                    }
                }
            }
        }
    }
}
####################################################################################################
#Author - abalaji
#Description - update_disk_to_lower_fw
#            - update the disk firmware to lower version available in NDATE/FIRMWARE/DISKFW/LOW
#Supported Mode - Cmode
####################################################################################################
sub update_disk_to_lower_firmware {
    my (%opts) = validate( @_, { Node => { type => OBJECT }, } );
    logcomment("Checking for availability of firmare under /NDATE/FIRMWARE/DISKFW/LOW");
    my $Node          = $opts{Node};
    my $Home          = $ENV{HOME};
    my %firmware_hash = ();
    my @firmware_list = ();
    my $test_status   = 0;
    my $disk_dir      = "$Home/NDATE/FIRMWARE/DISKFW/LOW";
    my $firmware_list = cm_disk_firmware(
        Node             => $Node,
        disk_fw_location => $disk_dir,
    );
    %firmware_hash = %$firmware_list;
    my %hash;
    my ( $key, $value );

    while ( ( $key, $value ) = each %firmware_hash ) {
        push( @{ $hash{$value} }, $key );
    }
    my @drive_list = grep { (/\S/) } keys(%firmware_hash);
    logcomment("The list of drives on which lower firmware will download : @drive_list ");
    @firmware_list = unique( values(%firmware_hash) );
    logcomment("The list of lower firmware files present : @firmware_list ");
    if ( !@firmware_list ) {
        logcomment("**FAIL**:  NO LOWER FIRMWARE FILES are available for filer ");
        $test_status = 1;    # to mark as sub routine fail
        return $test_status;
    }
    logcomment("Copying the FW files to filer directory");
    my $FILER_C = $Node->name();
    logcomment( "Lower firmware files to be copied are " . scalar(@firmware_list) . " - @firmware_list " );
    my @firmwares;
    foreach (@firmware_list) {
        my $val = $disk_dir . "/" . $_;
        push( @firmwares, $val );
    }
    my @fw_files = copy_FW_files_to_filer_directory(
        Node  => $Node,
        Files => \@firmwares
    );
    if ( !@fw_files ) {
        logcomment("**FAIL**: $FILER_C - Disk firmware files are NOT found in /etc/disk_fw");
        $test_status = 1;    # to mark as sub routine fail
        return $test_status;
    }
    logcomment("Updating the disks with lower firmware before Starting FW Download Qualification test");
    my $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset( connid => "console" );
    $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
    my $prompts_answers = [ ".*Do you want to continue.*" => 'y' ];
    $Api_Set_Obj->execute_raw_command(
        'command'                => "set test",
        'connectrec-match_table' => $prompts_answers
    );
    $Api_Set_Obj->execute_raw_command( 'command' => "run local" );
    $Api_Set_Obj->execute_raw_command( 'command' => "priv set -q test" );
    $Api_Set_Obj->execute_raw_command( 'command' => "dbg level diskfw=0" );
    my $time_out = 1000;

    foreach my $value ( keys %hash ) {
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => $time_out );
        my @arr_t = split( /\./, $value );
        my $prod_id = $arr_t[0];
        logcomment("DEBUG: Executing disk_fw_update -F $value $prod_id");
        my @prompts = ( 'Are you sure you want to' => 'y', );
        my $output = $Api_Set_Obj->execute_raw_command(
            'command'                => "disk_fw_update -F $value -t $prod_id",
            "connectrec-match_table" => \@prompts
        );
    }
    logcomment("Waiting for 10 minutes");
    for ( my $i = 0 ; $i < 2 ; $i++ ) {
        $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
        sleep(300);
    }

    #Stop any disk_fw_update process running in the background
    my $response;
    $Api_Set_Obj->execute_raw_command( 'command' => "exit" );
    logcomment("Stop any disk_fw_update process running in the background.");
    try {
        my $prompts = [ 'Are you sure you want to' => 'y' ];
        $Api_Set_Obj->execute_command( 'command' => "disk_fw_update -S", 'connectrec-match_table' => $prompts );
        sleep(60);
        logcomment("Firmware qualification download stopped ");
    }
    catch NACL::APISet::Exceptions::ResponseException with {
        logcomment("Could NOT stop firmware foreground.");
    };

    #$Api_Set_Obj->execute_raw_command( 'command' => "run local" );
    #$Api_Set_Obj->execute_raw_command( 'command' => "priv set -q test" );
    #$Api_Set_Obj->execute_raw_command( 'command' => "dbg level diskfw=0" );
    #$Api_Set_Obj->execute_raw_command( 'command' => "exit");
    return $test_status;
}

#######################################################################################################
# Auther - arjunl
# Description - cm_disk_firmware
# Supported Mode - CMode
######################################################################################################

sub cm_disk_firmware {
    my (%opts) = validate(
        @_,
        {
            Node             => { type => OBJECT },
            disk_fw_location => { type => SCALAR },
            timeout          => { type => SCALAR, default => 1200, optional => 1 },
        }
    );

    my $Node          = $opts{Node};
    my $disk_fw_path  = $opts{disk_fw_location};
    my $sudo          = "/usr/bin/sudo";
    my $Api_Set_Obj   = $Node->get_7m_or_nodescope_apiset();
    my $Mode          = $Node->mode();
    my %new_disk_fw   = ();
    my $new_disk_fw_p = [];
    $new_disk_fw_p = \%new_disk_fw;
    my %model   = ();
    my %rev     = ();
    my @disk_fw = `cd $opts{disk_fw_location};ls *.LOD`;
    my @failed_array;
    logcomment("Following Firmwares found in the directory $opts{disk_fw_location}:");
    logcomment("@disk_fw");
    $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );

    # This function validates the same firmwares with same product id's
    if ( @disk_fw < 1 ) {
        logcomment("NO DISK FIRMWARE files are available");
        return ($new_disk_fw_p);
    }
    my $ver = $Api_Set_Obj->execute_raw_command( 'command' => "version" );
    my @disk_list;
    my @list_of_disk = list_of_disk( Node => $Node );
    foreach my $dsk (@list_of_disk) {
        if ( $dsk =~ /(P\d+)$/ ) {
            next;
        }
        push( @disk_list, $dsk );
    }
    logcomment("Disk Available : @disk_list");

    # $Api_Set_Obj->execute_raw_command('command' => "set -rows 2000");
    my %sto_show_dsk = ();
    $sto_show_dsk{$Node} = storage_show_disk_a_data( Node => $Node );
    foreach my $disk (@disk_list) {
        my $mdl = $sto_show_dsk{$Node}->{$disk}->{'Model'};
        my $rvs = $sto_show_dsk{$Node}->{$disk}->{'Rev'};
        $model{$disk} = $mdl;
        $rev{$disk}   = $rvs;
    }
    foreach my $dsk (@disk_list) {
        my $model_name = $model{$dsk};
        my $rev_num    = $rev{$dsk};
        my $flag       = 0;
        foreach my $fw (@disk_fw) {
            $fw =~ s/^\s+|\s+$//g;
            $model_name =~ s/^\s+|\s+$//g;
            if ( $fw =~ /^$model_name\.\S+\.LOD$/ ) {
                logcomment(" Disk : $dsk ::: Model : $model_name ::: Rve No : $rev_num");
                $flag = 1;
                if ( !( $new_disk_fw{$dsk} ) ) {
                    $new_disk_fw{$dsk} = $fw;
                }
            }    ## if ( $fw =~ /$model_name/ )
        } ## end foreach my $fw (@disk_fw)
        if ( $flag == 0 ) {
            push( @failed_array, "No firmware file found for the disk $dsk with model number : $model_name and version $rev_num" );
        }
    }    ## foreach my $dsk (@disk_list)
    grep { logcomment("$_") } @failed_array;
    return ($new_disk_fw_p);

}
#######################################################################################################
# Auther - skaran
# Description - copy_files_to_filer_from_client
# Supported Mode - CMode
######################################################################################################
sub copy_files_to_filer_from_client {
    my (%opts) = validate(
        @_,
        {
            node_present     => { type => OBJECT },
            filer_path       => { type => SCALAR },
            file_To_transfer => { type => ARRAYREF },
        }
    );

    my $node       = $opts{node_present};
    my $filer_path = $opts{filer_path};

    #my $client_path=$opts{client_path};
    my $file_transfer = $opts{file_To_transfer};
    my $Client        = NACL::C::Client->find();
    logcomment("Client is $Client");
    my %Ipv6_opts;
    my $Is_ipv6_addr = '';
    $Ipv6_opts{use_ipv6_address} = 1 if ($Is_ipv6_addr);
    my $Home       = $ENV{HOME};
    my $Node_name  = $node->name();
    my $filer_info = `cat $Home/NDATE/FILER_INFO/$Node_name`;
    my $passwd;
    ($passwd) = $filer_info =~ /default_password\s*=\s*(\S+)\s*/ig;
    my $scp = NACL::MTask::SCP->new(
        source_command_interface => $Client,
        target_command_interface => $node,
        target_username          => 'diag',
        target_password          => "$passwd",
    );
    my $files = [$file_transfer];
    $scp->copy_from_source_to_target(
        'files_to_copy'         => $file_transfer,
        set_directory_on_target => $filer_path,
        %Ipv6_opts
    );
}

=head
#######################################################################################################
## Author Arjun Lavu
## Description -  sasadmin_expander_map
## The following named arguments are accepted:
## item Node
## (Required) : Node object to execute a command.
## item adapter_name
## (Optional) : Specific channel for which the information is
## required. Default is all
## Supported Mode - CMode/CLI/MAINT]
#######################################################################################################
sub sasadmin_expander_map {
	my (%opts) = validate(@_,
		{
			node     => { type => OBJECT },
			adapter_name   => {type=>SCALAR, default=>undef, optional=>1},
		}
	);
	my $Node = $opts{node};
	my $Mode = $Node->mode();
	my $API_obj;
	my $FILER_C = $Node->name();
	my $adapter = undef ;
	my $output = "";
	
	my $Transit_obj = NACL::Transit->new( name => $FILER_C );
	my $filer_state = $Transit_obj->get_state('timeout' => 600);
	if(defined($opts{adapter_name})){
		$adapter = $opts{adapter_name};
	}
	my %structure =();
	my $cmd = "sasadmin expander_map $adapter";
	if($filer_state=~/MAINT/gi){
		my $Host = host($FILER_C);
		$API_obj = NACL::APISet->new(
			hostobj   => $Host,
			category  => "Node",
			interface => "CLI",
			set       => "Maintenance"
		);
		$API_obj->set_timeout( "connectrec-timeout" => 1200 );
		$output = $API_obj->execute_raw_command('command' => "$cmd");
	}elsif($filer_state=~/(CLI|UP)/gi){
		$API_obj = $Node->get_7m_or_nodescope_apiset();
		$API_obj->set_timeout( "connectrec-timeout" => 1200 );
		$output = $API_obj->execute_command('command' => "$cmd");
	}
	
	if($output !~ /Expanders on channel/){
		logcomment("$FILER_C : NO EXPECTED OUTPUT APPEARED");
		return ;
	}
	$output=~s/'|,|://g;  #removing all (' and : and ,)
	my(@tot_channels,$total);
	@tot_channels=$output=~/Expanders on channel\s(\S+)/g;
	$total=@tot_channels;
	my $hba;
	my @lines = split(/\r*\n/, $output);
	foreach (@lines) {
		if($_ =~ /Expanders on channel\s(\S+)/){
			$hba = $1;
		}
		if($_ =~ /^Level/) {
			my @fields = split(/\s+/, $_);
			$structure{$hba}{"$fields[3]"}{'Level'} = $fields[1];
			$structure{$hba}{"$fields[3]"}{'ID'} = $fields[5];
			$structure{$hba}{"$fields[3]"}{'SerialNumber'} = $fields[8];
			$structure{$hba}{"$fields[3]"}{'Product'} = $fields[10];
			$structure{$hba}{"$fields[3]"}{'Rev'} = $fields[12];
			$structure{$hba}{"$fields[3]"}{'Slot'} = $fields[14];
		}
	}
	my $up_chan = 0;
	my @up_channles=keys(%structure);
	$up_chan = @up_channles;
	#logcomment("$FILER_C : Total number of channels are $total and the channels are @tot_channels");
	logcomment("$FILER_C : Total number of UP channels are $up_chan and the channels are @up_channles");
	return \%structure;
}

#######################################################################################################
# Auther - priya3
# Description -  sasadmin_dev_stats
# Supported Mode - CMode
######################################################################################################
sub sasadmin_dev_stats {
 my (%opts) = validate(@_,{
     node     => { type => OBJECT },
     adapter_name   => {type=>SCALAR, default=>undef, optional=>1},
  }
 );
 my $Node = $opts{node};
 my $Mode = $Node->mode();
 my $API_obj;
 my $FILER_C = $Node->name();
 my $adapter = undef ;
 my $output = "";
 if(defined($opts{adapter_name})){
  $adapter = $opts{adapter_name};
 }
	my %structure =();
	my $cmd = "sasadmin dev_stats";
	my $Transit_obj = NACL::Transit->new( name => $FILER_C );
	my $filer_state = $Transit_obj->get_state('timeout' => 3600, 'get_state_timeout' => 7200);
	if($filer_state=~/MAINT/gi){
		my $Host = host($FILER_C);
			$API_obj = NACL::APISet->new(
				hostobj   => $Host,
				category  => "Node",
				interface => "CLI",
				set       => "Maintenance"
			);
		$output = $API_obj->execute_raw_command('command' => "$cmd");
	}elsif($filer_state=~/(CLI|UP)/gi){
		$API_obj = $Node->get_7m_or_nodescope_apiset();
		$output = $API_obj->execute_command('command' => "$cmd");
	}
	$API_obj->set_timeout( "connectrec-timeout" => 1200 );
	if($output !~ /Device stats on channel/){
	logcomment("$FILER_C : NO EXPECTED OUTPUT APPEARED");
	return ;
	}
	$output=~s/'|,|://g;  #removing all (' and : and ,)
	my(@tot_channels,$total);
	@tot_channels=$output=~/Expanders on channel\s(\S+)/g;
	$total=@tot_channels;
	my $hba;
	my @lines = split(/\r*\n/, $output);
	foreach (@lines) {
	if($_ =~ /Device stats on channel\s(\S+)/){
	
	$hba = $1;
	}
	if($_ =~ /(^$hba\.\S+)\s+/) {
	
	my @fields = split(/\s+/, $_);
	$structure{$hba}{"$fields[0]"}{'Device'} = $fields[0];
	$structure{$hba}{"$fields[0]"}{'CmdsCmpltGood'} = $fields[1];
	$structure{$hba}{"$fields[0]"}{'CmdsCmpltError'} = $fields[2];
	$structure{$hba}{"$fields[0]"}{'FramesIn'} = $fields[3];
	$structure{$hba}{"$fields[0]"}{'FramesOut'} = $fields[4];
	$structure{$hba}{"$fields[0]"}{'VctmAbrt'} = $fields[5];
	$structure{$hba}{"$fields[0]"}{'QsceCnt'} = $fields[6];
	$structure{$hba}{"$fields[0]"}{'UdrnCnt'} = $fields[7];
	$structure{$hba}{"$fields[0]"}{'OvrnCnt'} = $fields[8];
	$structure{$hba}{"$fields[0]"}{'TrnsErrCnt'} = $fields[9];
	$structure{$hba}{"$fields[0]"}{'SCSIPtclErrCnt'} = $fields[10];
	$structure{$hba}{"$fields[0]"}{'CRCErrCnt'} = $fields[11];
	$structure{$hba}{"$fields[0]"}{'OPENErrCnt'} = $fields[12];
	$structure{$hba}{"$fields[0]"}{'InvdCnt'} = $fields[13];
	$structure{$hba}{"$fields[0]"}{'DlayCnt'} = $fields[14];
	$structure{$hba}{"$fields[0]"}{'SATAInitFailCnt'} = $fields[15];
	$structure{$hba}{"$fields[0]"}{'TO1Ct'} = $fields[16];
	$structure{$hba}{"$fields[0]"}{'TO2Ct'} = $fields[17];
	$structure{$hba}{"$fields[0]"}{'TO3Ct'} = $fields[18];
	$structure{$hba}{"$fields[0]"}{'TO4Ct'} = $fields[19];
	}
	}
	my $up_chan=0;
	my @up_channles=keys(%structure);
	$up_chan=@up_channles;
	logcomment("$FILER_C : Total number of channels are $total and the channels are @tot_channels");
	logcomment("$FILER_C : Total number of UP channels are $up_chan and the channels are @up_channles");
	return \%structure;
}
=cut

sub compare_disk_lists {
    my (%opts) = validate(
        @_,
        {
            diskL_add_before => { type => ARRAYREF },
            diskL_add_after  => { type => ARRAYREF },
        }
    );
    my @diskL_add_before = @{ $opts{diskL_add_before} };
    my @diskL_add_after  = @{ $opts{diskL_add_after} };

    #remove the null elements if any
    @diskL_add_before = grep( !/^$/, @diskL_add_before );
    @diskL_add_after  = grep( !/^$/, @diskL_add_after );

    my $d_before = @diskL_add_before;
    my $d_after  = @diskL_add_after;

    logcomment("The number of disk before = $d_before");
    logcomment("The number of disk after = $d_after");
    if ( $d_before != $d_after ) {
        return 0,;
    } else {
        return 1;
    }
} ## end sub compare_disk_lists

=head2 compare_fcadmin_link_stats

    my $ret = compare_fcadmin_link_stats(fcadmin_lnkstats_add_before => $fcadmin_lnkstats_add_before, fcadmin_lnkstats_add_after => $fcadmin_lnkstats_add_after);

This routine returns 1 on sucess and 0 on failure:

The following named arguments are accepted,

=over

=item fcadmin_lnkstats_add_before

(Required) : hash address returned by fcadmin_link_stats method on first instance

=item fcadmin_lnkstats_add_after

(Required) : hash address returned by fcadmin_link_stats method on second instance

=back

=cut

sub compare_fcadmin_link_stats {
    my (%opts) = validate(
        @_,
        {
            fcadmin_lnkstats_add_before => { type => HASHREF },
            fcadmin_lnkstats_add_after  => { type => HASHREF },
        }
    );
    my $fcadmin_lnkstats_add_before = $opts{fcadmin_lnkstats_add_before};
    my $fcadmin_lnkstats_add_after  = $opts{fcadmin_lnkstats_add_after};
    for my $state ( keys %$fcadmin_lnkstats_add_before ) {
        if ( defined( $fcadmin_lnkstats_add_before->{$state}->{'TransportErrorCount'} ) ) {
            if ( $fcadmin_lnkstats_add_before->{$state}->{'TransportErrorCount'} ne $fcadmin_lnkstats_add_after->{$state}->{'TransportErrorCount'} ) {
                my $error_count = $fcadmin_lnkstats_add_after->{$state}->{'TransportErrorCount'} - $fcadmin_lnkstats_add_before->{$state}->{'TransportErrorCount'};
                logcomment(" The values of fcadmin_lnkstats_add [TransportErrorCount] are different. ---> before($fcadmin_lnkstats_add_after->{$state}->{'TransportErrorCount'}) and after ($fcadmin_lnkstats_add_before->{$state}->{'TransportErrorCount'}) <---  Delta $error_count");
                return (0);
            }
        }
    }
    return (1);
} ## end sub compare_fcadmin_link_stats

=head2 compare_fcadmin_fcal_stats

    my $ret = compare_fcadmin_fcal_stats(fcadmin_fclstats_add_before => $fcadmin_fclstats_add_before, fcadmin_fclstats_add_after => $fcadmin_fclstats_add_after);

This routine returns 1 on sucess and 0 on failure:

The following named arguments are accepted,

=over

=item fcadmin_fclstats_add_before

(Required) : hash address returned by fcadmin_fclstats_add_before method on first instance

=item fcadmin_fclstats_add_after

(Required) : hash address returned by fcadmin_fclstats_add_after method on second instance

=back

=cut

sub compare_fcadmin_fcal_stats {
    my (%opts) = validate(
        @_,
        {
            fcadmin_fclstats_add_before => { type => HASHREF },
            fcadmin_fclstats_add_after  => { type => HASHREF },
        }
    );

    my $fcadmin_fclstats_add_before = $opts{fcadmin_fclstats_add_before};
    my $fcadmin_fclstats_add_after  = $opts{fcadmin_fclstats_add_after};
    for my $state ( keys %$fcadmin_fclstats_add_before ) {
        if ( defined( $fcadmin_fclstats_add_before->{$state}->{'device_transport_error_cnt'} ) ) {
            if ( $fcadmin_fclstats_add_before->{$state}->{'device_transport_error_cnt'} ne $fcadmin_fclstats_add_after->{$state}->{'device_transport_error_cnt'} ) {
                my $error_count = $fcadmin_fclstats_add_after->{$state}->{'device_transport_error_cnt'} - $fcadmin_fclstats_add_before->{$state}->{'device_transport_error_cnt'};
                logcomment("Values of fcadmin_fclstats_add [ device_transport_error_cnt ] are different.--->before ($fcadmin_fclstats_add_before->{$state}->{'device_transport_error_cnt'}) and after ($fcadmin_fclstats_add_after->{$state}->{'device_transport_error_cnt'}) <---  Delta $error_count");
                return (0);
            }
        }
    }
    return (1);
} ## end sub compare_fcadmin_fcal_stats

=head2 compare_sasadmin_dev_stats

        compare_sasadmin_dev_stats(initial_stats=>$initial,final_stats=>$final);

This functions compares structures returned by sasadmin_dev_stats and reports any unexpected increase in error counters
Returns 1 for pass and 0 for failure

Following error counters stats are compared:

1. Trns Err Cnt
2. SCSI Ptcl Err Cnt
3. CRC Err Cnt
4. SATA Init Fail Cnt


Example to use compare_sasadmin_dev_stats and sasadmin_dev_stats function

Get sas device states before doing operations

$initial = sasadmin_dev_stats(host => $host,timeout => $timeout);

Do some operations

Get sas device stats after operations

$final = sasadmin_dev_stats(host => $host,timeout => $timeout);


Compare two values

compare_sasadmin_dev_stats(initial_stats=>$initial, final_stats=>$final);


The following arguments are accepted:

=over

=item initial_stats

(Required): Initial data structure return by sasadmin_dev_stats()

=item final_stats

(Required): Final data structure return by sasadmin_dev_stats()

=back

=cut

sub compare_sasadmin_dev_stats {

    my (%opts) = validate(
        @_,
        {
            initial_stats => { type => HASHREF },
            final_stats   => { type => HASHREF },

        }
    );

    my @initial_sas_adapters = keys %{ $opts{initial_stats} };
    my @final_sas_adapters   = keys %{ $opts{final_stats} };
    my $ret_val              = 1;
    foreach my $adapter (@initial_sas_adapters) {
        my @initial_disks = keys %{ $opts{initial_stats}->{$adapter} };
        my $dev_error     = 0;
        foreach my $disk (@initial_disks) {
            if ( $opts{initial_stats}->{$adapter}->{$disk}->{TrnsErrCnt} < $opts{final_stats}->{$adapter}->{$disk}->{TrnsErrCnt} ) {
                $dev_error = ( $opts{final_stats}->{$adapter}->{$disk}->{TrnsErrCnt} - $opts{initial_stats}->{$adapter}->{$disk}->{TrnsErrCnt} );
                logcomment(" Disk - $disk : Trans Error count increased by : $dev_error");
                $ret_val = 0;
            }
            if ( $opts{initial_stats}->{$adapter}->{$disk}->{SCSIPtclErrCnt} < $opts{final_stats}->{$adapter}->{$disk}->{SCSIPtclErrCnt} ) {
                $dev_error = ( $opts{final_stats}->{$adapter}->{$disk}->{SCSIPtclErrCnt} - $opts{initial_stats}->{$adapter}->{$disk}->{SCSIPtclErrCnt} );
                logcomment(" Disk - $disk : SCSI PTCL Err count increased by : $dev_error");
                $ret_val = 0;
            }
            if ( $opts{initial_stats}->{$adapter}->{$disk}->{SATAInitFailCnt} < $opts{final_stats}->{$adapter}->{$disk}->{SATAInitFailCnt} ) {
                $dev_error = ( $opts{final_stats}->{$adapter}->{$disk}->{SATAInitFailCnt} - $opts{initial_stats}->{$adapter}->{$disk}->{SATAInitFailCnt} );
                logcomment(" Disk - $disk : SATA init Fail count increased by : $dev_error");
                $ret_val = 0;
            }
            if ( $opts{initial_stats}->{$adapter}->{$disk}->{CRCErrCnt} < $opts{final_stats}->{$adapter}->{$disk}->{CRCErrCnt} ) {
                $dev_error = ( $opts{final_stats}->{$adapter}->{$disk}->{CRCErrCnt} - $opts{initial_stats}->{$adapter}->{$disk}->{CRCErrCnt} );
                logcomment(" Disk - $disk : CRC err count increased by : $dev_error");
                $ret_val = 0;
            }

        } ## end foreach my $disk (@initial_disks)

    } ## end foreach my $adapter (@initial_sas_adapters)
    my $initial_count = @initial_sas_adapters;
    my $final_count   = @final_sas_adapters;
    if ( $initial_count != $final_count ) {
        $ret_val = 0;
        logcomment("The number of drives captured before is NOT IDENTICAL to number of drives captured after");
    }
    return $ret_val;
} ## end sub compare_sasadmin_dev_stats

################################################################
# arjun.lavu@netapp.com
## Description :: Compare sas-admin sxpander_map output
################################################################
sub compare_sasadmin_expander_map {
    my (%opts) = validate(
        @_,
        {
            sasadmin_addr_before => { type => HASHREF },
            sasadmin_addr_after  => { type => HASHREF },
        }
    );

    my $sasadmin_addr_before = $opts{sasadmin_addr_before};
    my $sasadmin_addr_after  = $opts{sasadmin_addr_after};

    for my $channels ( keys %$sasadmin_addr_before ) {
        my $channel_addr = $sasadmin_addr_before->{$channels};
        for my $wwn ( keys %$channel_addr ) {

            my $map_addr = $sasadmin_addr_before->{$channels}->{$wwn};

            foreach my $val ( keys %$map_addr ) {

                if ( $sasadmin_addr_before->{$channels}->{$wwn}->{$val} ne $sasadmin_addr_after->{$channels}->{$wwn}->{$val} ) {
                    logcomment("The values of $wwn [ $val ] are different. ---> before ($sasadmin_addr_before->{$channels}->{$wwn}->{$val}) and after ($sasadmin_addr_after->{$channels}->{$wwn}->{$val}) <---");
                    return (0);
                }
            } ## end foreach my $val (keys %$map_addr)

        } ## end for my $wwn (keys %$channel_addr)
    } ## end for my $channels (keys ...

    return (1);
} ## end sub compare_sasadmin_expander_map

=head2 compare_storage_show

    my $ret = compare_storage_show(storage_addr_before => $storage_addr_before, storage_addr_after => $storage_addr_after);

This routine returns 1 on sucess and 0 on failure:

The following named arguments are accepted,

=over

=item storage_addr_before

(Required) : hash address returned by storage_show  method on first instance

=item storage_addr_after

(Required) : hash address returned by storage_show method on second instance

=cut

sub compare_storage_show {

    my (%opts) = validate(
        @_,
        {
            storage_addr_before => { type => HASHREF },
            storage_addr_after  => { type => HASHREF },
        }
    );
    my $storage_addr_before = $opts{storage_addr_before};
    my $storage_addr_after  = $opts{storage_addr_after};
    my $flag                = 0;
    my $flag1               = 0;
    for my $channels ( keys %$storage_addr_before ) {
        for my $channela ( keys %$storage_addr_before ) {
            if ( $channels eq $channela ) {
                $flag1 = 1;

                #logcomment("Channel in before : $channels Channel in after : $channela ");
            }
        }
        if ( $flag1 == 1 ) {
            if ( $storage_addr_before->{$channels}->{'State'} ne $storage_addr_after->{$channels}->{'State'} ) {
                if (   ( $storage_addr_after->{$channels}->{'State'} =~ /Disabled|Enabled/i )
                    && ( $storage_addr_before->{$channels}->{'State'} =~ /Disabled|Enabled/i ) )
                {
                    $flag = 1;
                    logcomment("The state of the  Channel $channels are changed. ---> After ($storage_addr_after->{$channels}->{'State'}) and  Before ($storage_addr_before->{$channels}->{'State'}) <---");
                }
            }
            my $channel_addr = $storage_addr_before->{$channels};
            for my $shelf ( keys %$channel_addr ) {
                next if ( $shelf !~ /\d+/ );
                for my $disk ( keys %{ $channel_addr->{$shelf} } ) {
                    if ( $disk =~ /\d+/ ) {
                        if ( $storage_addr_before->{$channels}->{$shelf}->{$disk}->{CRCErrorCount} ne $storage_addr_after->{$channels}->{$shelf}->{$disk}->{CRCErrorCount} ) {
                            logcomment("Disk - $disk :The Values of [CRCErrorCount] are different. ---> Before ($storage_addr_before->{$channels}->{$shelf}->{$disk}->{CRCErrorCount}) and After ($storage_addr_after->{$channels}->{$shelf}->{$disk}->{CRCErrorCount}) <---");
                            $flag = 1;
                        }

                    } ## end if ($disk =~ /\d+/)

                } ## end of for my $shelf (keys %$channel_addr)
            } ## end for my $disk (keys %$channel_addr)
        } ## end of if ($flag1 === 1)
    } ## end for my $channels (keys ...

    if ( $flag == 1 ) {
        return 0;

    } else {
        return 1;
    }
} ## end sub compare_storage_show

#*************************************************************************
## Author - himangin@netapp.com
## This subroutine will calculate the time between the command executed and the ems message appeared for a particular disk
## Parameters required - either Start_string or Start_time any one is compulsarily required, Logfile and End_string are mandatory
## Returns the time difference in seconds
#*************************************************************************
sub time_taken_for_frm_dwnld {
    my (%opts) = validate(
        @_,
        {
            Start_string  => { type => SCALAR, default => undef, optional => 1 },
            Start_time    => { type => SCALAR, default => undef, optional => 1 },
            Logfile       => { type => ARRAYREF },
            End_string    => { type => SCALAR },
            Filer         => { type => SCALAR, default => undef, optional => 1 },
            multiple_msgs => { type => SCALAR, default => undef, optional => 1 }    # only in case of qualification tests (disk_fw_update -Q), since there will be multiple messages even for a single disk
        }
    );
    my $start_string  = $opts{Start_string};
    my $end_string    = $opts{End_string};
    my $multiple_msgs = $opts{multiple_msgs};
    my $start_time    = $opts{Start_time};
    my $FILER         = $opts{Filer};
    my @logfile       = @{ $opts{Logfile} };
    my ( $date, $time ) = 0;
    my ( $stime, $etime );

    foreach my $line (@logfile) {
        if ( defined $start_string ) {
            if ( ( $line =~ /^(\d+)\s+(\d+)/ ) && ( $line =~ /$start_string/ig ) ) {
                ( $date, $time ) = $line =~ /^(\d+)\s+(\d+)/;
                my $value = convert_to_date( date_val => $date, time_val => $time );
                $stime = convertTime( time_val => $value );
                last;
            }
        } elsif ( defined $start_time ) {
            $stime = convertTime( time_val => $start_time );
            last;
        }
    }
    my $y;
    foreach my $line (@logfile) {
        if ( defined $multiple_msgs ) {
            if ( ( $line !~ /console/ ) && ( $line =~ /$end_string/i ) && ( $line =~ /\"(\d+\/\d+\/\d+\s+\d+\:\d+\:\d+)\"/ ) ) {
                $y = $1;
            }
        } else {
            if ( ( $line !~ /console/ ) && ( $line =~ /$end_string/i ) && ( $line =~ /\"(\d+\/\d+\/\d+\s+\d+\:\d+\:\d+)\"/ ) ) {
                logcomment( "The last firmware download message - \"" . $end_string . "\", obtained from ems logs for filer $FILER at time $1" ) if ( defined $FILER );
                $y = $1;
                last;
            }
        }
    }
    $y =~ s/\://g;
    my %convert = ( '0' => '00', '1' => '01', '2' => '02', '3' => '03', '4' => '04', '5' => '05', '6' => '06', '7' => '07', '8' => '08', '9' => '09', '10' => '10', '11' => '11', '12' => '12' );
    if ( $y =~ /(\d+)\/(\d\d)\/(\d+)(.*)/ ) {
        $date = "$3" . "$convert{$1}" . "$2", $time = $4;
    } elsif ( $y =~ /(\d+)\/(\d)\/(\d+)(.*)/ ) {
        my $x = "0" . "$2";
        $date = "$3" . "$convert{$1}" . "$x", $time = $4;
    }
    my $value = convert_to_date( date_val => $date, time_val => $time );
    $etime = convertTime( time_val => $value );
    my $diff = $etime - $stime;
    return $diff;
}

=head
sub time_taken_for_frm_dwnld {
    my (%opts) = validate(
        @_,
        {
            Start_string  => { type => SCALAR, default => undef, optional => 1 },
            Start_time    => { type => SCALAR, default => undef, optional => 1 },
            Logfile       => { type => ARRAYREF },
            End_string    => { type => SCALAR },
	    Filer         => { type => SCALAR, default => undef, optional => 1 },
        }
    );
    my $start_string  = $opts{Start_string};
    my $end_string = $opts{End_string};
    my $start_time = $opts{Start_time};
    my $FILER = $opts{Filer};
        my @logfile = @{$opts{Logfile}};
        my ($date, $time) = 0;
        my ($stime, $etime);
        foreach my $line (@logfile) {
                if (defined $start_string) {
			if (($line =~ /^(\d+)\s+(\d+)/)&&($line =~ /$start_string/g)) {
                                ($date,$time) = $line =~ /^(\d+)\s+(\d+)/;
                                my $value = convert_to_date(date_val => $date, time_val => $time);
                                $stime = convertTime(time_val => $value );
				last;
                        }
                } elsif (defined $start_time) {
                        $stime = convertTime(time_val => $start_time);
			last;
                }
	}
	foreach my $line (@logfile) {
		if (($line !~ /console/)&&($line =~ /$end_string/)&&($line =~ /\"(\d+\/\d+\/\d+\s+\d+\:\d+\:\d+)\"/)){
			logcomment("The last firmware download message - \"".$end_string."\", obtained from ems logs for filer $FILER at time $1") if (defined $FILER);
                                                my $y = $1;
                                                $y =~ s/\://g;
                                                my %convert = ('0'=>'00','1' =>'01','2'=>'02','3'=>'03','4'=>'04','5'=>'05','6'=>'06','7'=>'07','8'=>'08','9'=>'09','10'=>'10','11'=>'11','12'=>'12');
                                                if ($y =~ /(\d+)\/(\d\d)\/(\d+)(.*)/){
                                                        $date = "$3"."$convert{$1}"."$2", $time = $4;
                                                } elsif ($y =~ /(\d+)\/(\d)\/(\d+)(.*)/){
							my $x = "0"."$2";
                                                        $date = "$3"."$convert{$1}"."$x", $time = $4;
                                                }
                        my $value = convert_to_date(date_val => $date, time_val => $time);
                        $etime = convertTime(time_val => $value );
			last;
                }
        }
        my $diff = $etime - $stime;
        return $diff;
}
=cut

#*************************************************************************
##Sub-routine which will return the date time stamp in localtime format
##eg - 20150528 084216 will be returned as May 28 08:42:16 2015
#*************************************************************************
sub convert_to_date {
    my (%opts) = validate(
        @_,
        {
            date_val => { type => SCALAR },
            time_val => { type => SCALAR },
        }
    );

    my $date_val = $opts{date_val};
    my $time_val = $opts{time_val};
    my $date;
    $date_val =~ /(\d\d\d\d)(\d\d)(\d\d)/;
    my $year = $1;
    my $mont = $2;
    my $day  = $3;
    my %mon  = (
        '01' => 'JAN',
        '02' => 'FEB',
        '03' => 'MAR',
        '04' => 'APR',
        '05' => 'MAY',
        '06' => 'JUN',
        '07' => 'JUL',
        '08' => 'AUG',
        '09' => 'SEP',
        '10' => 'OCT',
        '11' => 'NOV',
        '12' => 'DEC',

    );
    my $MONTH = $mon{$mont};
    $time_val =~ /(\d\d)(\d\d)(\d\d)/;
    my $hr   = $1;
    my $min  = $2;
    my $sec  = $3;
    my $time = join( ':', $hr, $min, $sec );
    $date = join( ' ', $MONTH, $day, $time, $year );
    return $date;
}

#*************************************************************************
##Sub-routine which will return the localtime format time in seconds.
##eg - time formats - (May 28 08:42:16 2015) or (Fri May 29 02:53:30 2015) will be returned in seconds
#*************************************************************************
sub convertTime {
    my (%opts) = validate( @_, { time_val => { type => SCALAR }, } );

    my $time = $opts{time_val};
    $time =~ s/\:/ /g;
    my ( $month, $day, $hour, $minute, $sec, $year ) = $time =~ /(\w+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/;
    if ( $year eq '' ) {
        my $nyear = localtime;
        if ( $nyear =~ /\S+\s\S+\s\d+\s\d+:\d+:\d+\s(\d+)/ ) {
            $year = $1;
        }
    }

    my $oneday = 24 * 3600;                                    #for convenience
    my $utime = $sec + ( $minute * 60 ) + ( $hour * 3600 );    ## time in seconds on the day in question

    my %mon = (
        JAN => 0,
        FEB => 1,
        MAR => 2,
        APR => 3,
        MAY => 4,
        JUN => 5,
        JUL => 6,
        AUG => 7,
        SEP => 8,
        OCT => 9,
        NOV => 10,
        DEC => 11,
    );
    my $mont   = uc($month);
    my $month  = $mon{$mont};
    my @months = ( 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 );
    for ( my $i = 0 ; $i < ( $month - 1 ) ; $i++ ) {
        $utime += ( $months[$i] * $oneday );
    }
    $utime += ( ( ( $year - ( $year % 4 ) ) / 4 ) * $oneday );    ## take leap years into account
    if ( ( $year % 4 ) == 0 && $month < 3 ) { $utime -= $oneday; }
    $utime += ( ( $day - 1 ) * $oneday );
    $utime += ( $year * 365 * $oneday );
    return $utime;
} ## end sub convertTime

##########################################################################################################
# Author -  vpankaj
# Description - This subroutine will return max disk size based on disk attached.
# Usage - Mandatory parameter - Node object , Test object
# Mode - CMode (UP/CLI)
# Return - max disk size in GB.
##########################################################################################################
sub get_max_disk_size {
    my (%opts) = validate( @_, { node_present => { type => ARRAYREF }, } );
    my @Nodes = @{ $opts{node_present} };
    my $max_disk_size    = 0;
    my $max_disk_size_GB = 0;
    foreach my $Node (@Nodes) {
        my $Transit_obj;
        my $Mode    = $Node->mode();
        my $FILER_C = $Node->name();
        $Transit_obj = NACL::Transit->new( name => $FILER_C );
        my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
        logcomment("DEBUG:$FILER_C : Filer is in $filer_state ");
        if ( $filer_state =~ /CLI|UP/ ) {
            my $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
            $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
            $Api_Set_Obj->execute_raw_command( 'command' => "rows 1000" );
            my $output = $Api_Set_Obj->execute_raw_command( 'command' => "storage disk show -fields usable-size-mb" );
            foreach my $line ( split( /\n/, $output ) ) {
                if ( ( $line =~ /(X;X)(\d+)(X;X)/ ) || ( $line =~ /(\s+)(\d+)(\s*)/ ) ) {
                    if ( $max_disk_size < $2 ) {
                        $max_disk_size = $2;
                    }
                }
            }
            $max_disk_size = int( $max_disk_size / (1024) );
            my ($d_size) = readable_disk_size( GB => $max_disk_size );
            logcomment("Maximum disk size is $d_size");
            return $max_disk_size;    #return value is in GB
        }
    }
}

##########################################################################################################
# Author -  arjunl
#Description : Returns the common values from two arrays
##########################################################################################################
sub intersection($$) {
    my %e = map { $_ => undef } @{ $_[0] };
    return grep { exists( $e{$_} ) } @{ $_[1] };
}

##########################################################################################################
# Author -  arjunl
## Description : Returns the common drives
##########################################################################################################
sub commom_drives($$) {
    my ( $drive_a, $drives_b ) = @_;
    my ( %unique_drive_one, %unique_drive_two );
    foreach my $dsk ( @{$drive_a} ) {
        ( my $drive = $dsk ) =~ s/(\w+\.?)//;
        $unique_drive_one{$drive} = $dsk;
    }
    foreach my $dsk ( @{$drives_b} ) {
        ( my $drive = $dsk ) =~ s/(\w+\.?)//;
        $unique_drive_two{$drive} = $dsk;
    }
    my @common = grep { /\S/ } intersection( [ sort keys %unique_drive_two ], [ sort keys %unique_drive_one ] );

    # logcomment("Common drives are : @common");
    my @final_array;
    foreach (@common) {
        push( @final_array, $unique_drive_one{$_} ) if ( $_ =~ /\S/ );
    }
    return @final_array;
}

### Arjun.Lavu
sub max_drives_count {
    my (%opts) = validate( @_, { Node => { type => OBJECT }, } );
    my $Node   = $opts{Node};
    my $Mode   = $Node->mode();
    my $FILER_C = $Node->name();
    my $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset( connid => "console" );
    my $after;
    my @array       = ();
    my @array_count = ();
    my %freq        = ();
    $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );

    if ( $Mode eq 'CMode' ) {
        $after = $Api_Set_Obj->execute_raw_command( 'command' => "run local sysconfig -r" );
    } else {
        $after = $Api_Set_Obj->execute_raw_command( 'command' => "sysconfig -r" );
    }
    foreach my $line ( split( /\n/, $after ) ) {
        if ( $line =~ /spare\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+(\S+)\s+\S+\s+\S+\s+\S+/ ) {
            push( @array, $1 );
        }
    }
    foreach $_ (@array) {
        $freq{$_}++;
    }
    foreach $_ ( values %freq ) {
        push( @array_count, $_ );
    }
    my $max = ( sort { $b <=> $a } @array_count )[0];
    return $max;
}

##########################################################################################################
# Author -  arjun.lavu@netapp.com
## Description : Format of printing test steps
##########################################################################################################
sub eye_catcher {
    my (%opts) = validate(
        @_,
        {
            Test   => { type => OBJECT },
            string => { type => SCALAR, default => undef, optional => 1 },
        }
    );
    my $Test   = $opts{Test};
    my $string = $opts{string};
    $Test->nlog("=====================================================================================================");
    $Test->nlog("=== $string");
    $Test->nlog("=====================================================================================================");
}
##########################################################################################################
# Author -  arjun.lavu@netapp.com
## Description : Subroutine will check for the file Pre_post_Drives_Details, if not present remove_assign will be called
##########################################################################################################
sub check_for_drive_ownership {
    my (%opts) = validate( @_, { Node_ref => { type => ARRAYREF }, } );
    my @Nodes = @{ $opts{Node_ref} };
    my $params = NATE::ParamSet->new( global => 1 );
    my $LOGDIR      = $params->get( 'LOGDIR',      default => undef );
    my $TEST_CONFIG = $params->get( 'TEST_CONFIG', default => undef );
    if ( $TEST_CONFIG !~ /E|C/gi ) {
        my $FILER_C = $Nodes[0]->name();
        my @actual_disks;
        my ($actual_log_dir) = $LOGDIR =~ /(\S+)\/HDD/;
        my $disks_file = "$actual_log_dir" . "/Pre_post_Drives_Details_" . "$FILER_C";
        if ( -f $disks_file ) {
            open( H_LOGFILE, "<$disks_file " ) or die ">>>>> read: Failed opening $disks_file <<<<<";
            foreach my $line () {
                chomp($line);
                $line =~ s/(^\s+)|(\s+$)//ig;
                if ( defined $line ) {
                    push @actual_disks, $line;
                }
            }
            close H_LOGFILE;
            logcomment("Assigning the drives @actual_disks to the filer :: $FILER_C");
            disk_remv_assign_ownership( Node_ref => [ $Nodes[0] ], disk_ref => \@actual_disks, assign_disk_to => $Nodes[0] );
        } else {
            disk_remv_assign_ownership( Node_ref => \@Nodes );
        }
    } else {
        disk_remv_assign_ownership( Node_ref => \@Nodes );
    }
}

##########################################################################################################
# Author -  arjun.lavu@netapp.com
## Description : This subroutine sets the diag password 6 times with, that is useful in setting new password(7Mode)
##########################################################################################################
sub change_diag_more_than_6() {
    my ( $c, $filer ) = @_;

    # $c = shift;
    # $filer=shift;
    for ( 0 .. 6 ) {
        my $temp = "temp" . "$$" . "_" . "$_";
        say( $c, "priv set -q test",           -prompt, "$filer*>", -timeout, 30,  -ok );
        say( $c, "useradmin diaguser unlock ", -prompt, "$filer*>", -timeout, 120, -ok );
        logcomment("DEBUG:Temp Password is $temp");
        my ( undef, undef, $after_diag, $prompt_diag ) = say( $c, "useradmin diaguser password", -prompt, [ 'Enter a new password:', 'Enter it again:' ], -timeout, 120, -ok );
        if ( ( $prompt_diag =~ /Enter a new password/i ) || ( $after_diag =~ /Enter a new password/i ) ) {
            my ( undef, undef, $after_diag_1, $prompt_diag_1 ) = say( $c, "$temp", -prompt, ['Enter it again:'], "$filer*>", -timeout, 120, -ok );
            if ( ( $prompt_diag_1 =~ /Enter it again/i ) || ( $after_diag_1 =~ /Enter it again/i ) ) {
                my ( undef, undef, $after_diag_2, $prompt_diag_2 ) = say( $c, "$temp", -prompt, "$filer*>", -timeout, 120, -ok );
            }
        }
    }
}
##########################################################################################################
# Author -  arjun.lavu@netapp.com
## Description : Sets the diag password of CMODE
##########################################################################################################
sub diag_password_change_cmode {
    my (%opts) = validate( @_, { Node_ref => { type => ARRAYREF }, } );
    my @Nodes = @{ $opts{Node_ref} };
    foreach my $Node (@Nodes) {
        my $FILER_C = $Node->name();
        my $Home    = $ENV{HOME};
        system("rm -rf $Home/.ssh/known_hosts");
        $Home = trim($Home);
        my $host_file    = "$Home/NDATE/FILER_INFO/$FILER_C";
        my $filer_config = `cat $host_file`;
        my $def_pass;
        foreach my $line ( split /\n/, $filer_config ) {

            if ( $line =~ /^default_password\s*=\s*(\S+)/ ) {
                $def_pass = $1;
                logcomment("$FILER_C :: Changing the Diag mode password to $def_pass");
                last;
            }
        }
        try {
            my $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
            $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
            $Api_Set_Obj->execute_raw_command( 'command' => "security login unlock -username diag" );
            my $prompts_answers = [ 'Enter a new password:' => "$def_pass", 'Enter it again:' => "$def_pass" ];
            my $output = $Api_Set_Obj->execute_raw_command( 'command' => "security login password -username diag", 'connectrec-match_table' => $prompts_answers );
            if ( $output =~ /different than last 6 passwords/i ) {
                change_diag_more_than_6_cmode( Node => $Node );
                $Api_Set_Obj->execute_raw_command( 'command' => "security login unlock -username diag" );
                my $prompts_answers = [ 'Enter a new password:' => "$def_pass", 'Enter it again:' => "$def_pass" ];
                my $output = $Api_Set_Obj->execute_raw_command( 'command' => "security login password -username diag", 'connectrec-match_table' => $prompts_answers );
            }
            $Api_Set_Obj->execute_raw_command( 'command' => "version" );
        }
        catch NATE::BaseException with {
            logcomment("$FILER_C : Caught Base Exception, connection problem");
        };
    }
}
##########################################################################################################
# Author -  arjun.lavu@netapp.com
## Description : This subroutine sets the diag password 6 times with, that is useful in setting new password(CMODE)
##########################################################################################################
sub change_diag_more_than_6_cmode() {
    my (%opts) = validate( @_, { Node => { type => OBJECT }, } );
    my @Nodes = $opts{Node};
    foreach my $Node (@Nodes) {
        my $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
        for ( 0 .. 6 ) {
            my $temp        = "temp_" . "$$" . "_" . "$_";
            my $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
            $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
            $Api_Set_Obj->execute_raw_command( 'command' => "security login unlock -username diag" );
            my $prompts_answers = [ 'Enter a new password:' => "$temp", 'Enter it again:' => "$temp" ];
            $Api_Set_Obj->execute_raw_command( 'command' => "security login password -username diag", 'connectrec-match_table' => $prompts_answers );
            sleep 5;
        }
    }
}

#################################################################################################
### Author
###	Arjun Lavu
#################################################################################################
sub filer_disk_create() {
    my $params = NATE::ParamSet->new( global => 1 );
    my $LOGDIR      = $params->get( 'LOGDIR',      default => undef );
    my $TEST_CONFIG = $params->get( 'TEST_CONFIG', default => undef );
    my $filer_state;
    if ( $TEST_CONFIG =~ /E/gi ) {

        #handle_run_local_error();
        my ( %nodes_filer, $Nodes );
        my @Nodes_temp = NACL::C::Node->find();
        handle_run_local_error( Nodes => [@Nodes_temp] );
        foreach my $Node (@Nodes_temp) {
            my $FILER_C = $Node->name();
            $nodes_filer{$FILER_C} = $Node;
        }
        my @Nodes = values(%nodes_filer);
        foreach my $node (@Nodes) {
            my $FILER_C          = $node->name();
            my ($actual_log_dir) = $LOGDIR =~ /(\S+)\/HDD/;
            my $file_name        = "$actual_log_dir" . "/Pre_post_Drives_Details_" . "$FILER_C";
            if ( -e $file_name ) {
                logcomment("Already disk list file $file_name exist for the filer $FILER_C");
                return;
            }
        }
        my %filer_vol;
        foreach my $node (@Nodes) {
            my $FILER_C = $node->name();
            my $Transit_obj = NACL::Transit->new( name => $FILER_C );
            $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
            if ( $filer_state =~ /CLI/ ) {
                check_aggr_vol_offline( Node => $node );
                my @arr = check_non_root_volumes( Node => $node );
                if (@arr) {
                    $filer_vol{$FILER_C} = [@arr];
                } else {
                    $filer_vol{$FILER_C} = undef;
                }
            } else {
                check_disk_owner( Noderef => [@Nodes] );
            }
        }
        if ( $filer_state =~ /CLI/ ) {
            my @keys = keys %filer_vol;
            if ( ( defined $filer_vol{ $keys[0] } ) && ( defined $filer_vol{ $keys[1] } ) ) {
                disk_remv_assign_ownership( Node_ref => [@Nodes] );
            } else {
                logcomment("Either one of two nodes does NOT have volumes");
                logcomment("Deleting all the aggregates and assigning spares between the systems");
                disk_remv_assign_ownership( Node_ref => [@Nodes], delete_aggr => 'yes' );
            }
            foreach (@Nodes) {
                logcomment("Checking for aggregates which does NOT have any volume and deleting them");
                delete_aggregates_with_no_volumes( Node => $_ );
            }
            my @subtests;
            foreach my $Node (@Nodes) {
                my $FILER_C = $Node->name();
                push( @subtests, subtest( \&check_recons_sickdisk, -runid, "check_recons_sickdisk_$FILER_C", -bg, "--", Node => $Node ) );
            }
            Subtest::wait_finish( subtest => [@subtests] );
        } else {
            disk_remv_assign_ownership( Node_ref => [@Nodes] );
        }

        # check_disk_owner( Noderef  => [@Nodes]) if ($filer_state=~/MAINT/); ##call only for MAINT MODE as of now
        # disk_remv_assign_ownership(Node_ref =>[@Nodes]);
        logcomment("Current logdir is $LOGDIR");
        my $API_obj;
        my @drives;
        foreach my $node (@Nodes) {
            my $FILER_C     = $node->name();
            my $Transit_obj = NACL::Transit->new( name => $FILER_C );
            my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
            if ( $filer_state =~ /MAINT/g ) {
                my $FILER_C = $node->name();
                my $Host    = host($FILER_C);
                $API_obj = NACL::APISet->new(
                    hostobj   => $Host,
                    category  => "Node",
                    interface => "CLI",
                    set       => "Maintenance"
                );
                $API_obj->set_timeout( "connectrec-timeout" => 7200 );
                @drives = @{ disk_show_drive_maint( API_Obj => $API_obj, Filer => $FILER_C )->{'driveA'} };
            } else {
                $API_obj = $node->get_7m_or_nodescope_apiset( connid => "console" );
                $API_obj->set_timeout( "connectrec-timeout" => 7200 );
                @drives = get_disks_list( Node => $node, FILER => $FILER_C );
                @drives = sort {
                    if ( ( $a =~ /P\d+/ ) && ( $b !~ /P\d+/ ) ) {
                        return 1;
                    } elsif ( ( $a !~ /P\d+/ ) && ( $b =~ /P\d+/ ) ) {
                        return -1;
                    } elsif ( ( $a =~ /P\d+/ ) && ( $b =~ /P\d+/ ) ) {
                        my ($tst1) = $a =~ /P(\d+)/;
                        my ($tst2) = $b =~ /P(\d+)/;
                        return $tst1 <=> $tst2;
                    } else {
                        return $a <=> $b;
                    }
                } @drives;
            }
            my $dsks = _print_array( \@drives );
            logcomment( "$FILER_C : Number of drives assigned are::\n" . $dsks );
            my $file_name = "$LOGDIR/../../../" . "Pre_post_Drives_Details_" . "$FILER_C";
            open( FH, ">$file_name" ) || print "cannot create file $file_name";
            foreach my $line (@drives) {
                if ( $line =~ /(^\s+$)|(^\.+$)/g ) {
                    next;
                }
                print( FH "$line \n" );
            }
            close FH;
        }
    } else {
        logcomment("Test-config is NOT equal to E");
    }
}

######################
#Author -- Arjun Lavu
######################

sub check_disk_owner {
    my (%opts) = validate( @_, { Noderef => { type => ARRAYREF }, } );
    my @Nodes  = @{ $opts{Noderef} };
    my $Mode   = $Nodes[0]->mode();
    foreach my $Node (@Nodes) {
        my $FILER_C     = $Node->name();
        my $host        = host($FILER_C);
        my $Transit_obj = NACL::Transit->new( name => $FILER_C );
        my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
        my $API_Object;
        if ( $filer_state =~ /MAINT/ ) {
            $API_Object = NACL::APISet->new(
                hostobj   => $host,
                category  => "Node",
                interface => "CLI",
                set       => "Maintenance",
            );
            $API_Object->set_timeout( "connectrec-timeout" => 7200 );
        } elsif ( $filer_state =~ /CLI|UP/i ) {
            $API_Object = $Node->get_7m_or_nodescope_apiset();
            $API_Object->set_timeout( "connectrec-timeout" => 7200 );
        }
        my @arr_get_disks = get_disk_information( API_Obj => $API_Object, Filer => $FILER_C );
        @arr_get_disks = sort @arr_get_disks;
        my $dsks = _print_array( \@arr_get_disks );
        logcomment( "Number of drives from disk show -s command are " . scalar @arr_get_disks . " and the drives are:\n" . $dsks ) if (@arr_get_disks);
        my @drives_disk_show_a = @{ disk_show_drive_maint( API_Obj => $API_Object, Filer => $FILER_C )->{'driveA'} };
        @drives_disk_show_a = sort @drives_disk_show_a;
        my $dsks = _print_array( \@drives_disk_show_a );
        logcomment( "Number of drives from disk show -a command are " . scalar @drives_disk_show_a . " and the drives are:\n" . $dsks ) if (@drives_disk_show_a);

        if ( scalar @arr_get_disks != scalar @drives_disk_show_a ) {
            if ( scalar @arr_get_disks > scalar @drives_disk_show_a ) {
                my @diff = array_diff( \@arr_get_disks, \@drives_disk_show_a );
                logcomment("$FILER_C  : In disk show -a command owner name is missing for the drives @diff");

                # logcomment("$FILER_C : Removing the disk ownership and assigning in a proper way");
                $API_Object->set_timeout( "connectrec-timeout" => 600 );
                my $system_id = sysconfig_v_data( node => $Node, API_Obj => $API_Object )->{'system_id'};

                # $API_Object->execute_raw_command('command' => "storage release disks -f");
                $API_Object->execute_raw_command( 'command' => "disk remove_ownership all -f" );
                sleep 60;
                $API_Object->execute_raw_command( 'command' => "disk remove_ownership all -f" );
                disk_remv_assign_ownership( Node_ref => [@Nodes] );
            }
            last;
        }
    }
}

#################################################################################################
### Author
###	Arjun Lavu
## diference in two arrays
#################################################################################################
sub array_diff {
    my %e = map { $_ => undef } @{ $_[1] };
    return @{ [ ( grep { ( exists $e{$_} ) ? ( delete $e{$_} ) : (1) } @{ $_[0] } ), keys %e ] };
}

#################################################################################################
### Author
###	Arjun Lavu
### Description:: Remove the partition drives in maintenance mode and return 1 if partition is done
#################################################################################################
sub remove_partition {
    my (%opts) = validate( @_, { Noderef => { type => ARRAYREF }, handle => { type => SCALAR, default => undef, optional => 1 } } );
    my @Nodes  = @{ $opts{Noderef} };
    my $handle = $opts{handle};
    my $Mode   = $Nodes[0]->mode();
    my $FILER_C         = $Nodes[0]->name();
    my $FILER_D         = $Nodes[1]->name();
    my $Transit_obj     = NACL::Transit->new( name => $FILER_C );
    my $Transit_obj_two = NACL::Transit->new( name => $FILER_D );
    my $filer_state     = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    my $filer_state1    = $Transit_obj_two->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    my $NVMe            = 0;
    logcomment("DEBUG:$FILER_C : Filer is in $filer_state ");
    logcomment("DEBUG : CHECK : $handle");
    $NVMe = 1 if ( $handle =~ /NVMe/ );
    logcomment("Check for NVMe ");
    logcomment("DEBUG : Run ID is : $RUNID");
    $NVMe = 1 if ( $RUNID =~ /NVMe/ );
    logcomment("NVMe Script is in execution ") if ( $NVMe == 1 );

    if ( $filer_state !~ /MAINT/i ) {
        logcomment("$FILER_C : Filer is NOT in required mode, changing state to MAINT");
        $Transit_obj->set( 'change_state_timeout' => 7200 );
        $Transit_obj->change_state( to => "MAINT" );
    }
    if ( $filer_state1 !~ /MAINT/i ) {
        logcomment("$FILER_D : Filer is in required mode, Changing state to MAINT");
        $Transit_obj_two->set( 'change_state_timeout' => 7200 );
        $Transit_obj_two->change_state( to => "MAINT" );
    }
    $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    my ( $API_Object, $data, @disk_part );
    if ( $filer_state =~ /MAINT/ ) {
        my $host = host($FILER_C);
        $API_Object = NACL::APISet->new(
            hostobj   => $host,
            category  => "Node",
            interface => "CLI",
            set       => "Maintenance",
        );
        $API_Object->set_timeout( "connectrec-timeout" => 7200 );
        $data = $API_Object->execute_raw_command( 'command' => "disk show -v" );
    } elsif ( ( $filer_state =~ /CLI/ ) && ( $Mode =~ /CMode/i ) ) {
        $API_Object = $Nodes[0]->get_7m_or_nodescope_apiset( connid => "console" );
        $API_Object->set_timeout( "connectrec-timeout" => 7200 );
        $data = $API_Object->execute_raw_command( 'command' => "disk show -v" );
    }

    my @data = split( /\n/, $data );
    foreach my $line (@data) {

        #if ( $line =~ /(\S+)\s+\S+\s*\(\d+/ ) {
        if ( ( $line =~ /(\S+)\s+\S+\s*\(\d+/ ) || ( $line =~ /(\S+)\s+\S+\s*/ ) ) {
            my $disk = $1;
            if ( $disk =~ /P\d+$/ ) {
                push( @disk_part, $disk );
            }
        }
    }
    if (@disk_part) {
        foreach my $Node (@Nodes) {
            my $FILER_C = $Node->name();
            logcomment("$FILER_C : Checking the partitioned drives un-owned pool");
            my $return = disk_show_n( Node => $Node );
            if ( keys %{$return} ) {
                push( @disk_part, keys %{$return} );
            }
        }
    }
    if (@disk_part) {
        my ( %filter, %FILER_API );
        my $dsks = _print_array( \@disk_part );
        logcomment( "$FILER_C : Partitioned drives found on the system and the drives are " . scalar @disk_part . " and the drives are:\n" . $dsks );
        logcomment("$FILER_C : Changing state to Maintenance Mode");
        $Transit_obj->set( 'change_state_timeout' => 7200 );
        $Transit_obj->change_state( to => "MAINT" );
        logcomment( $Nodes[1]->name() . " : Changing state to Maintenance Mode" );
        $Transit_obj_two->set( 'change_state_timeout' => 7200 );
        $Transit_obj_two->change_state( to => "MAINT" );

        foreach my $Node (@Nodes) {
            my $FILER_C = $Node->name();
            logcomment("DEBUG: Creating API object for filer - $FILER_C");
            my $Host    = host($FILER_C);
            my $console = Tharn::connect("$FILER_C#console");

            # Set the properties for the Connectrec used for creating the APIset
            $console->{prompts}  = [qr/\*>/];
            $console->{max_idle} = 300;
            $console->{on_idle}  = sub { $console->execute(""); };
            my $API_obj = NACL::APISet->new(
                connection => $console,
                category   => "Node",
                interface  => "CLI",
                set        => "Maintenance"
            );
            $FILER_API{$FILER_C} = $API_obj;
        }

        # Delete all aggregate to avoid partition ownership issue
        foreach my $Node (@Nodes) {
            my $FILER_C     = $Node->name();
            my $Api_Set_Obj = $FILER_API{$FILER_C};
            $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
            my @dele_aggr;
            logcomment("Checking for aggregate");
            my $prompts_answers = [ ".*Aggregate set.*" => '1' ];
            my $output = $Api_Set_Obj->execute_raw_command( 'command' => "aggr status", 'connectrec-match_table' => $prompts_answers );
            if ( $output =~ /No root aggregate|Please supply a number/ig ) {
                logcomment("NO ROOT VOLUME exist on the filer $FILER_C");
                next;
            } else {
                foreach my $var ( split( /\n/, $output ) ) {
                    if ( $var =~ /aggr\s+/ ) {
                        if ( $var =~ /(\S+)\s+/ ) {
                            my $ag = $1;
                            if ( $ag =~ /aggr/ ) {
                                logcomment("Aggregate found - $ag");
                                push( @dele_aggr, $ag );
                            }
                        }
                    }
                }
            }
            foreach my $aggrd (@dele_aggr) {
                logcomment("Delete aggregate - $aggrd");
                my $prompts_answers = [ ".*you sure want to take the root aggregate.*" => 'yes' ];
                $Api_Set_Obj->execute_raw_command( 'command' => "aggr offline $aggrd", 'connectrec-match_table' => $prompts_answers );
                sleep 4;
                my $prompts_answers1 = [ ".*you sure you want to destroy this aggregate.*" => 'yes' ];
                $Api_Set_Obj->execute_raw_command( 'command' => "aggr destroy $aggrd -f", 'connectrec-match_table' => $prompts_answers1 );
                sleep 4;
                logcomment("Deleted Aggregate - $aggrd");
            }
        }
        logcomment( "Assigning all the drives from " . $Nodes[1]->name() . " to " . $Nodes[0]->name() );
        disk_remv_assign_ownership( Node_ref => [@Nodes], assign_disk_to => $Nodes[0], remove_disk_from => $Nodes[1] );
        my $return = disk_show_drive_maint( API_Obj => $API_Object, Filer => $FILER_C );
        my @drives = @{ $return->{'driveA'} };
        foreach my $var (@drives) {
            $var =~ s/^\s|\s+$//g;
            if ( $var =~ /P\d+$/ ) {
                $var =~ s/P\d+$//g;
                $filter{$var} = undef;
            }
        }
        if ( $NVMe == 0 ) {
            $Transit_obj->set( 'change_state_timeout' => 7200 );
            $Transit_obj_two->set( 'change_state_timeout' => 7200 );
            $Transit_obj->change_state( to => "FIRMWARE" );
            $Transit_obj_two->change_state( to => "FIRMWARE" );
            $Transit_obj->change_state( to => "MAINT" );
            $Transit_obj_two->change_state( to => "MAINT" );
            sleep 10;
        }
        sleep 5;
        logcomment("Check kernel version");
        my $full_steam = 0;
        foreach my $Node (@Nodes) {
            my $FILER_C     = $Node->name();
            my $Api_Set_Obj = $FILER_API{$FILER_C};
            $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
            $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
            sleep 5;
            $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
            logcomment("Check version of Kernel");
            my $ker_ver = $Api_Set_Obj->execute_raw_command( 'command' => "version" );
            logcomment("Kernel - $ker_ver");

            if ( $ker_ver =~ /Fullsteam/i ) {
                $full_steam = 1;
            }
        }
        if ( $full_steam == 1 ) {
            logcomment("DEBUG: Kernel is Fullsteam");
            my $prompts_answers = [ "Abort unpartition" => 'n' ];
            my @partitioned = keys %filter;
            logcomment("DEBUG:Unpartitioning the drives @partitioned");
            foreach ( keys %filter ) {
                logcomment("$FILER_C : unpartitioning the drive $_");
                $API_Object->execute_command( 'command' => "disk unpartition $_", 'connectrec-match_table' => $prompts_answers );
            }
        } else {
            logcomment("DEBUG: Kernel is NOT Fullsteam");
            my $prompts_answers = [ "Abort unpartition" => 'n' ];
            $API_Object->execute_command( 'command' => "disk unpartition all -F", 'connectrec-match_table' => $prompts_answers );
        }
        logcomment("Partition Drives remove");
        if ( $NVMe == 0 ) {
            disk_remv_assign_ownership( Node_ref => [@Nodes] );
        } else {
            logcomment("Unpartitoned all drives");
        }
        return 1;
    } else {
        logcomment("NO PARTITIONED DRIVES found on the system");
        return 0;
    }
}

sub boot_it_good_Maint {
    my (%opts) = validate(
        @_,
        {
            Test  => { type => OBJECT },
            Filer => { type => SCALAR },
        }
    );
    my $Test  = $opts{Test};
    my $filer = $opts{Filer};

    my $filer_state;
    my $Transit_obj;
    logcomment("DEBUG:Boot to Maintenance mode");
    $Transit_obj = NACL::Transit->new( name => $filer );
    $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    if ( ( $filer_state =~ /^(CLI|FIRMWARE|BOOT_MENU|HALTED|CFE_BANNER|LOADER_BANNERFIRMWARE)/ ) || ( $filer_state !~ /MAINT/ ) ) {
        $Transit_obj->set( 'change_state_timeout' => 7200 );
        $Transit_obj->change_state( to => "MAINT" );
    }
    $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    if ( $filer_state !~ /^(MAINT)/ ) {
        $Transit_obj->set( 'change_state_timeout' => 7200 );
        $Transit_obj->change_state( to => "MAINT" );
    }
}

##########################################################################################################
# Auther - arunak
# Description - returns hash consisting data of all disk attached, like block, disk name, type etc..
# Supported - CMode - Maint
# Usage - Mandatory - API,
##########################################################################################################
sub disk_list_data {
    my (%opts) = validate( @_, { API_Obj => { type => OBJECT }, } );
    my $Api_Set_Obj = $opts{API_Obj};
    my $Mode        = $opts{mode};
    $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
    my $dsk_output = $Api_Set_Obj->execute_raw_command( 'command' => "disk_list" );
    my $dsk_result = {};
    my @lines      = split( /\n/, $dsk_output );
    my $n          = 0;

    while ( $n <= $#lines ) {
        last if ( $lines[$n] =~ /^-----/ );
        $n++;
    }
    $n++;
    foreach my $line ( @lines[ $n .. $#lines ] ) {
        my ( $disk, $chan, $ven, $prodid, $rev, $serialno, $hw, $blocks, $bps, $dq ) = ( $line =~ /(\S+)\s+(.*)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)/ );
        if ( ( $line =~ /\d\w\.\d\d/ ) || ( $line =~ /\d\w\.\d\d\.\d\d/ ) || ( $line =~ /\d\w\.\S+/ ) || ( $line =~ /\d\w\.\d\d\.\S+/ ) ) {
            $dsk_result->{$disk} = {
                'DISK'       => $disk,
                'CHAN'       => $chan,
                'VENDOR'     => $ven,
                'PRODUCT_ID' => $prodid,
                'REV'        => $rev,
                'SERIAL'     => $serialno,
                'HW'         => $hw,
                'BLOCKS'     => $blocks,
                'BPS'        => $bps,
                'DQ'         => $dq
            };
        }
    }
    return $dsk_result;
}

#######################################################################################################
# Auther - arjun.lavu@netapp.com
# Description - disk list command for Cmode
# Usage - Mandatory paramanter - Node
# Supported Mode - CMode (CLI/UP and MAINT)
# Return - array of disks attached
#######################################################################################################
sub get_disks_list {
    my (%opts) = validate(
        @_,
        {
            Node  => { type => OBJECT },
            FILER => { type => SCALAR, default => undef, optional => 1 },
        }
    );

    my $Node = $opts{Node};
    my $FILER_C;

    #	my $filer_passed = $opts{FILER};
    if ( defined $opts{FILER} ) {
        $FILER_C = $opts{FILER};
    } else {
        $FILER_C = $Node->name();
    }
  rechk:
    my @disk_list = ();
    $Node->refresh_command_interface();
    my $Transit_obj = NACL::Transit->new( name => $FILER_C );
    my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );    #BURT1033631 - abalaji
    logcomment("DEBUG:Filer state $filer_state");
    my $reck_flag = 0;

    if ( $filer_state =~ /MAINT/ ) {
        @disk_list = list_of_disk( Node => $Node );
    } else {
        $Node->refresh_command_interface();
        my $API_Obj = $Node->get_7m_or_nodescope_apiset();
        $API_Obj->set_timeout( "connectrec-timeout" => 7200 );
        $API_Obj->execute_raw_command( command => "\013" );
        $API_Obj->execute_raw_command( command => "\013" );
        try {
            logcomment("DEBUG: Getting the drives which belongs to filer $FILER_C");
            my %hash;
            %hash = ( filter => { 'owner' => $FILER_C } );
            my @disk_obj = NACL::C::StorageDisk->find(
                command_interface => $Node,
                filter            => { 'owner' => $FILER_C },
            );
            foreach my $state_obj (@disk_obj) {
                my $free_disk = $state_obj->disk();
                push( @disk_list, $free_disk );
            }
            my $dsks = _print_array( \@disk_list );
            logcomment( "Total number of container drives are " . scalar @disk_list . " and the drives are:\n" . $dsks ) if (@disk_list);
            logcomment("NO CONTAINER DRIVES are available") if ( !@disk_list );
        }
        catch NACL::Exceptions::NoElementsFound with {
            logcomment("NO DISKS found from the filer $FILER_C");
        }
        catch NATE::BaseException with {
            logcomment("Management gateway server re-started, Could NOT able to get drive details, Re-excecuting command");
            sleep 20;
            $reck_flag++;
        };
        if ($reck_flag) {
            logcomment("DEBUG - $reck_flag");
            goto rechk if ( $reck_flag < 3 );
        }
        my @disk_partitioned;
        try {
            my %hash;
            %hash = ( filter => { "owner-node-name" => $FILER_C } );
            logcomment("Checking for partitioned drives if present");
            my @disk_obj = NACL::CS::StorageDiskPartition->fetch(
                command_interface => $Node,
                filter            => { "owner-node-name" => $FILER_C },
            );
            foreach my $state_obj (@disk_obj) {
                my $free_disk = $state_obj->partition();
                push( @disk_partitioned, $free_disk );
            }
        }
        catch NACL::Exceptions::NoElementsFound with {
            logcomment("NO PARTITIONED DRIVES found in the filer $FILER_C");
        };
        if (@disk_partitioned) {
            my $dsks = _print_array( \@disk_partitioned );
            logcomment( "Total number partitioned drives are " . scalar @disk_partitioned . " and the drives are:\n" . $dsks );
            push( @disk_list, @disk_partitioned );
        }
    }
    return @disk_list;
}

sub trim($) {
    my $string = shift;
    $string =~ s/^\s+|\s+$//gm;
    return $string;

}

#########################
##Author - Arjun Lavu
#########################

sub create_aggr_volume {
    my (%opts) = validate(
        @_,
        {
            Node      => { type => OBJECT },
            disk_list => { type => ARRAYREF },
            size      => { type => SCALAR, optional => 1, default => '90' },
            test      => { type => SCALAR, optional => 1, default => undef },
            partition => { type => SCALAR, optional => 1, default => 'no' },
            aggr_name => { type => SCALAR, optional => 1, default => undef }
        }
    );
    my %hash;
    my %size;
    my $stask_vol;
    my $aggr_size;
    my $vol_size;
    my $node      = $opts{Node};
    my $filer     = $node->name();
    my @spares    = @{ $opts{disk_list} };
    my $Mode      = $node->mode();
    my @spares_t  = @spares;
    my $test_name = $opts{test};
    my $aggr_flag = 0;
    my $num_spares;
    my $RAID_tec;
    my $API_Obj = $node->get_7m_or_nodescope_apiset();
    $API_Obj->set_timeout( "connectrec-timeout" => 7200 );
    my $kernel = $API_Obj->execute_raw_command( command => "run local version" );

    if ( $kernel !~ /<1d>/ ) {

        #logcomment("Non debug kernel will require at least 5 disks for raid_dp");
        $num_spares = 5 + $RAID_tec;
    } else {
        $num_spares = 3 + $RAID_tec;
    }
    while (@spares_t) {

        #        if ( $aggr_flag == 0 ) {
        if ( ( $aggr_flag == 0 ) && ( $parse_id !~ /_ERT_Fsys/i ) ) {    #by aditis
                                                                         # logcomment("spares :: $AGGR_CNT->{$filer}  @spares_t");
            if ( ( defined $AGGR_CNT->{$filer} ) && ( @spares_t >= $AGGR_CNT->{$filer} ) ) {
                logcomment( "$filer : Total number of aggregates already present in the filer are " . $AGGR_CNT->{$filer} . " so leaving the spares " . $AGGR_CNT->{$filer} . " before creating aggregates from the available spares " . scalar @spares_t );
                for ( ( 1 .. $AGGR_CNT->{$filer} ) ) {
                    shift(@spares_t);
                }
            }
            $aggr_flag = 1;
        } elsif ( $parse_id =~ /_ERT_Fsys/i ) {                          #by aditis
            logcomment( "$filer : Leaving one spare for non-root aggregate before creating aggregates from the available spares " . scalar @spares_t );
            shift(@spares_t);
        }
        my $BOAB_check      = 0;
        my $return          = disk_show_v( Node => $node );
        my @disk_boab_check = ();
        @disk_boab_check = keys(%$return);
        if ( $disk_boab_check[0] =~ /\w+\.\w+\.\w+L\d+$/ ) {
            $BOAB_check = 1;
        }
        my @non_root_volumes = check_non_root_volumes( Node => $node );    # Burt1024377
        last if ( ( scalar @non_root_volumes >= 1 ) && ( $RAID_tec == 1 ) );     #aditis
        last if ( ( scalar @non_root_volumes >= 1 ) && ( $BOAB_check == 1 ) );
        my $disk_max_sup = 13;
        my $temp_disk;
        my $loop_no     = 0;
        my @disk_list_q = ();

        while ( $loop_no < $disk_max_sup ) {
            $temp_disk = pop(@spares_t);
            push( @disk_list_q, $temp_disk );
            $loop_no++;
            last if ( !(@spares_t) );
        }

        my $spare_cnt = scalar @disk_list_q;
        if ( @disk_list_q > $num_spares ) {
            my $left = shift(@disk_list_q);
            logcomment("DEBUG:$filer : leaving drive : $left in the spare pool to avoid potential errors");
            if ( $opts{partition} =~ /yes/i ) {
                my $dsks = _print_array( \@disk_list_q );
                logcomment( "Spares using to create aggregate are : " . scalar @disk_list_q . " and the spares are:\n" . $dsks );
                %hash = ( partitionlist => [@disk_list_q] );
            } else {

                # %hash = (disklist =>[@disk_list_q]);
                my @drives_use_7 = ();
                if ( $BOAB_check == 1 ) {
                    my %sata;
                    my @boab_arr_disk = ();
                    foreach my $dsk (@disk_list_q) {
                        if ( $dsk =~ /((\d+\.\d+\.\d+)\.\d+)/ ) {
                            push( @{ $sata{$2} }, $1 );
                        }
                    }
                    foreach my $key ( keys %sata ) {
                        my @arr = @{ $sata{$key} };
                        if ( scalar @arr > 1 ) {
                            push( @boab_arr_disk, $arr[0] );
                        } else {
                            push( @boab_arr_disk, @arr );
                        }
                    }
                    @drives_use_7 = splice( @boab_arr_disk, 0, 7 );    # Burt1024377
                    my $dsks = _print_array( \@drives_use_7 );
                    logcomment( "Spares using to create aggregate are : " . scalar @drives_use_7 . " and the spares are:\n" . $dsks );
                    %hash = ( disklist => \@drives_use_7, node => $filer );
                } else {

                    # %hash = (disklist =>[@disk_list_q]);
                    if ( $test_name =~ /308|309/ ) {
                        @drives_use_7 = splice( @disk_list_q, 0, 7 );
                        my $dsks = _print_array( \@drives_use_7 );
                        logcomment( "Spares using to create aggregate are : " . scalar @drives_use_7 . " and the spares are:\n" . $dsks );
                        %hash = ( disklist => \@drives_use_7, node => $filer );
                    } else {
                        my $dsks = _print_array( \@disk_list_q );
                        logcomment( "Spares using to create aggregate are : " . scalar @disk_list_q . " and the spares are:\n" . $dsks );
                        %hash = ( disklist => \@disk_list_q, node => $filer );
                    }
                }
            }
        } else {
            logcomment("NOT ENOUGH SPARES available to create aggregate");
            return;
        }
        my $num = 0;
        my $vserver_name;
        my $append_name = $filer;
        if ( $filer =~ /\-/ ) {
            $append_name =~ s/\-/_/g;
        }
        my @temp;
        my $agg = "aggr_" . "$append_name" . "_1";
        my $job;
        my @aggrs = NACL::C::Aggregate->find( command_interface => $node, filter => { nodes => [$filer] } );
        my ( @aggr_names, $num_aggr, @n_aggr, %num_obj );

        foreach my $aggr (@aggrs) {
            my $ag = $aggr->get_one_state_attribute('aggregate');
            push( @aggr_names, $ag );
            if ( $ag =~ /(\d+)$/g ) {
                push( @n_aggr, $1 );
                $num_obj{$1} = $aggr;
            }
        }
        @n_aggr = sort { $a <=> $b } @n_aggr;
        my $aggr_obj;
        $num_aggr = $n_aggr[-1];    ##the value will have maximum digit value
        logcomment("Current max suffix value of aggregates : $num_aggr");
        $aggr_obj = $num_obj{$num_aggr};
        logcomment( "$filer : Total number of aggregates present in the system are " . scalar @aggr_names . " and the aggregates are @aggr_names" );
        $AGGR_CNT->{$filer} = scalar @aggr_names;
        my ( @vol_names, $num_vol );
        my @vol = NACL::C::Volume->find( command_interface => $node, filter => { node => $filer } );

        foreach my $vols (@vol) {
            my $vg = $vols->get_one_state_attribute('volume');
            push( @vol_names, $vg );
            if ( $vg =~ /(\d+)$/g ) {
                if ( $num_vol < $1 ) {
                    $num_vol = $1;
                }
            }
        }
        logcomment( "$filer : Total number of volumes present in the system are " . scalar @vol_names . " and the volumes are @vol_names" );
        my $vol_flag       = 0;
        my $other_vol_flag = 0;
        if ( defined $aggr_obj ) {
            my $agg_test = $aggr_obj->get_one_state_attribute('aggregate');
            logcomment("DEBUG:Finding the number of volumes present in the aggregate $agg_test");
            my @aggr_obj;
            try {
                @aggr_obj = $aggr_obj->get_volumes();
            }
            catch NATE::BaseException with {
                logcomment("NO VOLUMES found in the aggregate $agg_test");
                $vol_flag = 1;
            };
            foreach my $vol_obj (@aggr_obj) {
                my $vol_test = $vol_obj->get_one_state_attribute('volume');
                logcomment("Volume present on the aggregate $agg_test are : $vol_test");
                $vol_test =~ s/^\s+|\s+$//g;
                if ( $vol_test =~ /volvs/i ) {
                    logcomment("$filer : Vsever volume volvs found on the aggregate $agg_test");
                    $vol_flag = 1;
                } elsif ( $vol_test =~ /vol0/i ) {
                    logcomment("$filer : Root volume found on the aggregate $agg_test");
                    $other_vol_flag = 1;
                } else {
                    logcomment("$filer : Volume found with the name $vol_test on the aggregate $agg_test ");
                    $other_vol_flag = 1;
                }
            }
        }
        my $aggr_ret_flag = 0;

        # $num = $num_aggr;
        $num = $num_aggr + 1;

        # if(($vol_flag)&&(!$other_vol_flag)&&($num_vol!=$num_aggr)){
        # $num = $num_aggr ;
        # }else{
        # $num = $num_aggr+1;
        # }
        logcomment("DEBUG:the number will get appended is to the aggregate name is : $num ") if ( !defined $opts{aggr_name} );
        try {
            if ( defined $opts{aggr_name} ) {
                $agg = "aggr_" . "$append_name" . "_" . $opts{aggr_name};
            } else {
                $agg = "aggr_" . "$append_name" . "_" . "$num";
            }
            if ( $test_name =~ /555/ ) {
                logcomment("Creating 50GB aggregate");
                my $stask_aggr_obj = NACL::STask::Aggregate->create(
                    command_interface => $node,
                    aggregate         => $agg,
                    nacltask_min_size => '50G',
                    job_component     => \$job,
                );
            } elsif ( $test_name =~ /308|309/ ) {
                logcomment("Creating aggregate of name $agg");
                my $stask_aggr_obj = NACL::STask::Aggregate->create(
                    command_interface => $node,
                    aggregate         => $agg,

                    #diskcount         => '7',
                    nacltask_if_exists => 'reuse',
                    nacltask_wait      => '1',
                    job_component      => \$job,
                    polling_interval   => '600',
                    %hash,
                );
            } else {
                my $stask_aggr_obj = NACL::STask::Aggregate->create(
                    command_interface  => $node,
                    aggregate          => $agg,
                    nacltask_if_exists => 'reuse',
                    nacltask_wait      => '1',
                    job_component      => \$job,
                    polling_interval   => '600',
                    %hash,
                );

                #'allow-mixed-rpm'  =>'true',
            }
        }
        catch NACL::APISet::Exceptions::CommandFailedException with {
            if ( !$AGGR_CREATE_CNTR ) {
                $AGGR_CREATE_CNTR++;
                logcomment("**WARNING** :: $filer : $agg reached UNEXPECTED state, checking and creating again");
                create_flex_vol( Node => $node );
            } else {
                logcomment("**WARNING** :: $filer : Script tries to create aggregate $agg two times but FAILED");
                $aggr_ret_flag = 1;
            }

            # logcomment("WARNING : Couldn't create aggregate");
        }
        catch NACL::Exceptions::UnexpectedState with {
            if ( !$AGGR_CREATE_CNTR ) {
                $AGGR_CREATE_CNTR++;
                logcomment("**WARNING** : $filer : $agg Reached unexpected state, checking and creating again");
                create_flex_vol( Node => $node );
            } else {
                logcomment("**WARNING** : $filer : Script tries to create aggregate $agg two times but FAILED");
                $aggr_ret_flag = 1;
            }
        };
        if ( $aggr_ret_flag == 1 ) {
            logcomment("**WARNING** : $filer : Could NOT create aggregate $agg");
            return undef;
        }
        my $skip = 0;
        {
            my $root      = "volvs";
            my $aggr_v    = "$agg";
            my $ns        = "file";
            my $sec       = "mixed";
            my $vser_flag = 0;
            $vserver_name = "vser_$filer";
            try {
                my $name = NACL::STask::Vserver->find(
                    command_interface => $node,
                    filter            => { vserver => $vserver_name },
                );
                if ( $name->get_one_state_attribute("vserver") =~ /^($vserver_name)$/ ) {
                    my $vol = $name->get_one_state_attribute("rootvolume");
                    logcomment("Vserver root volume is $vol");
                    $vol =~ s/^\s+$//;
                    if ( ( $vol =~ /^\-$/g ) || ( !$vol ) ) {
                        logcomment("For vserver : $vserver_name : NO VOLUME is there");
                        logcomment("Deleting the vserver $vserver_name");
                        $name->purge();    #deleting the Vserver if no volume present for the Vserver
                        $vser_flag = 1;
                    }
                }
            }
            catch NACL::Exceptions::NoElementsFound with {
                logcomment("NO VSERVER found with the name $vserver_name");
                $vser_flag = 1;
            };
            if ( $vser_flag == 1 ) {

                try {
                    my $vserver_obj = NACL::STask::Vserver->create(
                        command_interface           => $node,
                        vserver                     => $vserver_name,
                        nacltask_if_exists          => 'reuse',
                        rootvolume                  => $root,
                        aggregate                   => $aggr_v,
                        "ns-switch"                 => $ns,
                        "rootvolume-security-style" => $sec
                    );
                }
                catch NACL::APISet::Exceptions::CommandFailedException with {
                    if ( !$AGGR_CREATE_CNTR ) {
                        $AGGR_CREATE_CNTR++;
                        logcomment("$filer : $vserver_name : Could NOT create vserver, checking and creating agaiN");
                        create_flex_vol( Node => $node );
                    } else {
                        logcomment("**WARNING** :: $filer : script tries to create vserver $vserver_name two times but FAILED");
                        logcomment("**WARNING** : Could NOT create vserver $vserver_name, returning from the subroutine");
                        $skip = 1;
                    }
                };

            }
        }
        return undef if ($skip);

        #___---___---___---____---___---____---____---______---____---_____---____---______

        ##Calculating the aggregate size and calculating the volume size to create on the aggregate based on the user input
        my @aggrs = NACL::C::Aggregate->find( command_interface => $node, );
        foreach my $aggr (@aggrs) {
            my $name = $aggr->aggregate();
            if ( $name eq $agg ) {
                $aggr_size = $aggr->get_one_state_attribute('availsize');

                #logcomment("Initial aggregate size $aggr_size bytes");
                $aggr_size = int( $aggr_size / ( 1024 * 1024 ) );
                my ($readable_size) = readable_disk_size( MB => $aggr_size );
                logcomment("Total size of aggregate $agg is $readable_size");
            }
        }
        if ( $aggr_size == 0 ) {
            logcomment("**WARNING** : Total size of aggregate : $agg : is zero, so CANNOT create volumes on this aggregate");
            return;
        }
        my $vol_size = 90;
        {
            if ( ($vol_size) > 100 ) {
                logcomment("Size of Volume cannot be created more than the Aggregate size so making the size of volume equal to 100% of Aggreagte");
                $vol_size = 100;
            }
            my $required_size = int( ( $vol_size / 100 ) * $aggr_size );
            if ( $required_size > 50000000 ) {
                logcomment("Volume size is coming more than 50TB, so restricting the volume size to 50TB");
                $required_size = '50000000';
            }
            my ($readable_vol_size) = readable_disk_size( MB => $required_size );
            logcomment("Size of volume which will get created on aggregate $agg is $readable_vol_size");
            $required_size = $required_size . "m";    ##treating in MB's
            %size = ( size => $required_size );
        }

        #___---___---___---____---___---____---____---______---____---_____---____---______

        my $vol_name;
        if ( defined $opts{aggr_name} ) {
            $vol_name = "vol_" . "$append_name" . "_" . $opts{aggr_name};
        } else {
            $vol_name = "vol_" . "$append_name" . "_" . "$num";
        }

        if ( $Mode eq 'CMode' ) {

            if ( $test_name =~ /555/ ) {
                $stask_vol = NACL::STask::Volume->create(
                    command_interface  => $node,
                    vserver            => $vserver_name,
                    volume             => $vol_name,
                    nacltask_if_exists => 'reuse',
                    nacltask_wait      => '1',
                    aggregate          => $agg,
                    if_exists          => "reuse",
                    size               => '40GB',

                    #%size,
                );

            } else {
                $stask_vol = NACL::STask::Volume->create(
                    command_interface  => $node,
                    vserver            => $vserver_name,
                    volume             => $vol_name,
                    nacltask_if_exists => 'reuse',
                    nacltask_wait      => '1',
                    aggregate          => $agg,
                    if_exists          => "reuse",
                    %size,
                );
            }
        }
        my $Api_Set_Obj = $node->get_7m_or_nodescope_apiset();
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
        logcomment("DEBUG:Checking volume status");
        $Api_Set_Obj->execute_command( 'command' => "vol status" );
        logcomment("DEBUG:Checking aggregate status");
        my $result = $Api_Set_Obj->execute_command( 'command' => "aggr status" );
        if ( $result =~ /raid_tec/g ) {
            logcomment("DEBUG : Found raid tec");
            $RAID_tec = 1;
        }
        last if ( $test_name =~ /555/ );
    }
}

#######################################################################################################
# Auther - vpankaj@netapp.com
# Description - version command for Cmode
# Usage - Mandatory paramanter - Node
# Supported Mode - CMode (CLI/UP)
# Return - Status
#######################################################################################################
sub display_version {
    my (%opts) = validate( @_, { Node => { type => OBJECT }, } );
    my $Node = $opts{Node};
    my $FILER_C     = $Node->name();
    my $Host        = host($FILER_C);
    my $Transit_obj = NACL::Transit->new( name => $FILER_C );
    my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    logcomment("DEBUG:Node $FILER_C is in the Filer state $filer_state");
    my $node_version;

    if ( $filer_state =~ /UP|CLI/i ) {
        my $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
        $node_version = $Api_Set_Obj->execute_raw_command( 'command' => 'run local version' );
        if ( $node_version =~ /<1d>/i ) {
            logcomment("Debug Kernel : $node_version");
        } else {
            logcomment("Non-debug kernel : $node_version");
        }
    } elsif ( $filer_state =~ /MAINT/i ) {
        my $API_Object = NACL::APISet->new(
            hostobj   => $Host,
            category  => "Node",
            interface => "CLI",
            set       => "Maintenance"
        );
        $API_Object->set_timeout( "connectrec-timeout" => 7200 );
        $node_version = $API_Object->execute_raw_command( command => "version" );
        if ( $node_version =~ /<1d>/i ) {
            logcomment("Debug kernel : $node_version");
        } else {
            logcomment("Non-debug kernel : $node_version");
        }
    }
    if ( $node_version ne '' ) {
        logcomment("Filer - $FILER_C  version : $node_version");
        return 0;
    } else {
        logcomment("Version command FAILED for filer $FILER_C");
        return 1;
    }
}

###########################################
##
## @Author - Arjun
## Description :  Delete the aggregates with no volumes
##
###########################################

sub delete_aggregates_with_no_volumes {
    my (%opts) = validate( @_, { Node => { type => OBJECT } } );
    my $Node = $opts{Node};
    my $FILER_C = $Node->name();
    my @aggrs = NACL::C::Aggregate->find( command_interface => $Node, filter => { nodes => [$FILER_C] } );
    my @aggr_names;
    foreach my $aggr (@aggrs) {
        my $ag = $aggr->get_one_state_attribute('aggregate');
        push( @aggr_names, $ag );
    }
    logcomment( "$FILER_C : Total number of aggregates present in the system are " . scalar @aggr_names . " and the aggregates are @aggr_names" );
    foreach my $aggr_obj (@aggrs) {
        my $vol_flag = 0;
        my $agg_test = $aggr_obj->get_one_state_attribute('aggregate');
        logcomment("Trying to find the volumes present in the aggregate $agg_test");
        my @vol_obj;
        try {
            my @volu;
            @vol_obj = $aggr_obj->get_volumes();
            foreach (@vol_obj) {
                push( @volu, $_->get_one_state_attribute('volume') );
                logcomment("$FILER_C : Volumes present in the aggragate $agg_test are : @volu");
            }
        }
        catch NATE::BaseException with {
            logcomment("$FILER_C : NO VOLUMES found in the aggregate $agg_test, so deleting the aggregatE");
            $vol_flag = 1;
        };
        if ($vol_flag) {
            try {
                NACL::STask::Aggregate->purge(
                    command_interface => $Node,
                    aggregate         => $agg_test,
                    nacltask_verify   => 1,
                );
            }
            catch NACL::Exceptions::NoElementsFound with {
                logcomment("DEBUG:Inside catch NACL::Exceptions::NoElementsFound with");
                logcomment("$FILER_C : CANNOT delete the aggregate $agg_test ");
            }
            catch NACL::APISet::Exceptions::CommandFailedException with {
                try {
                    NACL::STask::Aggregate->purge(
                        command_interface => $Node,
                        aggregate         => $agg_test,
                        nacltask_verify   => 1
                    );
                }
                catch NACL::APISet::Exceptions::CommandFailedException with {
                    logcomment("$FILER_C : CANNOT delete aggregate $agg_test");
                };
            }
            catch NACL::Exceptions::VserverHasVolumesOnAnotherAggregate with {
                logcomment("$FILER_C : CANNOT delete aggregate $agg_test ");
            };
        }
    }
}

#############################################
## himangin@netapp.com
## The subroutine will check for chassis and controller HA and Non-Ha configurations during initialization
## No return value, called in support scripts
#############################################

sub HA_config {
    my (%opts) = validate( @_, { API_Obj => { type => OBJECT } } );
    my $Api_Set_Obj = $opts{API_Obj};
    $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
    logcomment("DEBUG:Checking for chassis and controller configurations");
    my $FILER_C     = $Api_Set_Obj->get_name();
    my $Transit_obj = NACL::Transit->new( name => $FILER_C );
    my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    my $config;

    if ( $filer_state =~ /CLI/ ) {
        $config = $Api_Set_Obj->execute_command( command => "ha-config show" );
    } else {
        $config = $Api_Set_Obj->execute_raw_command( command => "ha-config show" );
    }
    my @array;
    foreach ( split( /\n/, $config ) ) {
        if ( $_ =~ /(Chassis|Controller)(.*)\:\s*(\S+)/ ) {
            push( @array, $3 );
        }
    }
    if ( $array[0] eq $array[1] ) {
        logcomment("$FILER_C : Chassis and controller are configured same");
    } else {
        logcomment("**WARNING** : $FILER_C : Chassis and controller are NOT configured same. Modifying chassis and controller to same configuration");
        my $prompts_answers = [ ".*Do you want to continue??.*" => 'y' ];
        if ( $filer_state =~ /CLI/ ) {
            $Api_Set_Obj->execute_command( command => "ha-config modify controller ha", 'connectrec-match_table' => $prompts_answers );
            $Api_Set_Obj->execute_command( command => "ha-config modify chassis ha",    'connectrec-match_table' => $prompts_answers );
        } else {
            $Api_Set_Obj->execute_raw_command( command => "ha-config modify controller ha", 'connectrec-match_table' => $prompts_answers );
            $Api_Set_Obj->execute_raw_command( command => "ha-config modify chassis ha",    'connectrec-match_table' => $prompts_answers );
        }
    }
}

##Arjun Lavu
sub create_flex_vol {
    my (%opts) = validate(
        @_,
        {
            Node      => { type => OBJECT },
            disk_list => { type => ARRAYREF, optional => 1, default => undef },
            size      => { type => SCALAR, optional => 1, default => '90' },
            aggr_name => { type => SCALAR, optional => 1, default => undef },
            test      => { type => SCALAR, optional => 1, default => undef },
            diskcount => { type => SCALAR, optional => 1, default => undef },

        }
    );
    my $Node  = $opts{Node};
    my $filer = $Node->name();
    my %hash;
    my %size;
    my $stask_vol;
    my $flag_disk_list = 0;
    my $aggr_size;
    my $vol_size;
    my $test_name = $opts{test};
    my $diskcount = $opts{diskcount} if ( defined $opts{diskcount} );
    my ( @spares, @normal_spares );
    check_aggr_vol_offline( Node => $Node );
    @spares = @{ $opts{disk_list} } if ( defined $opts{disk_list} );

    if (@spares) {
        my $dsks = _print_array( \@spares );
        logcomment( "$filer : Spare drives which passed from the script to create aggregate are " . scalar @spares . " and the drives are:\n" . $dsks );
        $flag_disk_list = 1;
    } else {
        aggregate_volume_delete( Node => $Node );
        @spares = spare_count_cmode( Node => $Node );
    }
    my $dsks = _print_array( \@spares );
    logcomment( "Total spare drives are : " . scalar @spares . " and the spare drives are:\n" . $dsks ) if (@spares);
    my (%part_spares);
    my $num_spares;
    my $API_Obj = $Node->get_7m_or_nodescope_apiset();
    $API_Obj->set_timeout( "connectrec-timeout" => 7200 );
    my $kernel = $API_Obj->execute_raw_command( command => "run local version" );

    if ( $kernel !~ /<1d>/ ) {

        #logcomment("Non debug kernel will require at least 5 disks for raid_dp");
        #        $num_spares = 6;
        $num_spares = 5;    #change added by aditis
    } else {

        #        $num_spares = 4;
        $num_spares = 3;    #change added by aditis
    }
    my @partiton_drives = ();
    foreach (@spares) {
        if ( $_ =~ /(P\d+)$/ ) {
            push( @{ $part_spares{$1} }, $_ );
            push( @partiton_drives,      $_ );
        } else {
            push( @normal_spares, $_ );
        }
    }
    my $flag_set   = 0;
    my @partitions = keys %part_spares;
    if ( (@partiton_drives) && (@normal_spares) ) {
        if ( @normal_spares < @partiton_drives ) {
            $flag_set = 1;
        }
    }
    if (@partitions) {
        logcomment("Number of partitions present are :: @partitions");
        foreach (@partitions) {
            logcomment( "Number of drives present under the partition $_ : are " . scalar @{ $part_spares{$_} } . " and the drives are @{$part_spares{$_}}" );
            if ( @{ $part_spares{$_} } < $num_spares ) {
                logcomment("$filer : CANNOT create aggregate for the partition drives $_, because number of spare are less than $num_spares");
                next;
            } else {
                if ( ( defined $opts{aggr_name} ) && ( defined $test_name ) ) {

                    #                    create_aggr_volume( Node => $Node, disk_list => $part_spares{$_}, size => $opts{size}, partition => 'yes', aggr_name => $opts{aggr_name}, test => $test_name );
                    create_aggr_vol( Node => $Node, disk_list => $part_spares{$_}, size => $opts{size}, partition => 'yes', aggr_name => $opts{aggr_name}, test => $test_name, flag_disk_list => $flag_disk_list );
                    last;
                } elsif ( defined $test_name ) {

                    #                    create_aggr_volume( Node => $Node, disk_list => $part_spares{$_}, size => $opts{size}, partition => 'yes', test => $test_name );
                    create_aggr_vol( Node => $Node, disk_list => $part_spares{$_}, size => $opts{size}, partition => 'yes', test => $test_name, flag_disk_list => $flag_disk_list );
                    last;
                } else {

                    #                    create_aggr_volume( Node => $Node, disk_list => $part_spares{$_}, size => $opts{size}, partition => 'yes' );
                    create_aggr_vol( Node => $Node, disk_list => $part_spares{$_}, size => $opts{size}, partition => 'yes', flag_disk_list => $flag_disk_list );
                    last;
                }
            }
        }
    }
    if ( $flag_set != 1 ) {
        if (@normal_spares) {
            if ( @normal_spares < $num_spares ) {
                logcomment("$filer : CANNOT create aggregate, because spare drives are less than $num_spares");
            } else {
                if ( ( defined $opts{aggr_name} ) && ( defined $test_name ) ) {

                    #                create_aggr_volume( Node => $Node, disk_list => [@normal_spares], size => $opts{size}, aggr_name => $opts{aggr_name}, test => $test_name );
                    create_aggr_vol( Node => $Node, disk_list => [@normal_spares], size => $opts{size}, aggr_name => $opts{aggr_name}, test => $test_name, flag_disk_list => $flag_disk_list );
                } elsif ( defined $test_name ) {

                    #                create_aggr_volume( Node => $Node, disk_list => [@normal_spares], size => $opts{size}, test => $test_name );
                    create_aggr_vol( Node => $Node, disk_list => [@normal_spares], size => $opts{size}, test => $test_name, flag_disk_list => $flag_disk_list );
                } elsif ( defined $diskcount ) {
                    create_aggr_vol( Node => $Node, disk_list => [@normal_spares], diskcount => $diskcount, size => $opts{size}, flag_disk_list => $flag_disk_list );
                } else {

                    # logcomment("Creating volumes with the drives ". scalar @normal_spares." and the drives are @normal_spares");
                    #                create_aggr_volume( Node => $Node, disk_list => [@normal_spares], size => $opts{size} );
                    create_aggr_vol( Node => $Node, disk_list => [@normal_spares], size => $opts{size}, flag_disk_list => $flag_disk_list );
                }
            }
        }
    }
}

sub fcadmin_fcal_stats {
    my (%opts) = validate(
        @_,
        {
            Node         => { type => OBJECT },
            channel_name => { type => SCALAR, default => undef, optional => 1 },
        }
    );
    my $Node = $opts{Node};
    my $API_obj;
    my $FILER_C = $Node->name();

    my $cmd    = "fcadmin fcal_stats $opts{channel_name}";
    my $output = "";

    my $Transit_obj = NACL::Transit->new( name => $FILER_C );
    my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    my $cmd = "fcadmin link_stats $opts{channel_name}";
    if ( $filer_state =~ /MAINT/gi ) {
        my $Host = host($FILER_C);
        $API_obj = NACL::APISet->new(
            hostobj   => $Host,
            category  => "Node",
            interface => "CLI",
            set       => "Maintenance"
        );
        $API_obj->set_timeout( "connectrec-timeout" => 7200 );
        $output = $API_obj->execute_raw_command( 'command' => "$cmd" );
    } elsif ( $filer_state =~ /(CLI|UP)/gi ) {
        $API_obj = $Node->get_7m_or_nodescope_apiset();
        $API_obj->set_timeout( "connectrec-timeout" => 7200 );
        $output = $API_obj->execute_command( 'command' => "$cmd" );
    }
    my %HoH = ();
    if ( $output =~ /fcadmin fcal_stats: No such channel/ ) {
        if ( $opts{channel_name} ) {
            logcomment("**FAIL** : NO CHANNEL found");
            logresult( 'FAIL', "NO CHANNEL FOUND" );
            return \%HoH;
        }
    }
    my @lines = split( /\r*\n/, $output );
    my ( $slot_name, @mailbox_fields, @device_fields );
    foreach (@lines) {

        #Get the slot
        if ( $_ =~ /driver statistics for slot (\w+)/ ) {
            $slot_name = $1;
        }

        #Get adapter-related information
        elsif ( $_ =~ /adap_/ ) {
            $_ =~ s/^\s+//;
            my @adap_fields = split( /:\s*/, $_ );
            $adap_fields[1] =~ s/\s+//;

            $HoH{$slot_name}{ $adap_fields[0] } = $adap_fields[1];
        }

        #Get mailbox-related information
        elsif ( $_ =~ /mailbox status: (.*)/ ) {
            @mailbox_fields = split( /\s+/, $1 );
        } elsif ( ( $_ =~ /(issued)(.*)/ ) || ( $_ =~ /(failed)(.*)/ ) || ( $_ =~ /(timed out)(.*)/ ) ) {
            my $mailbox_status        = "mailbox_" . $1;
            my $mailbox_status_fields = $2;
            $mailbox_status =~ s/\s+//;
            $mailbox_status_fields =~ s/\s+//;
            my @fields = split( /\s+/, $mailbox_status_fields );
            my $count;
            for ( $count = 0 ; $count < @mailbox_fields ; $count++ ) {
                my $mailbox_name = $slot_name . "\." . $mailbox_fields[$count];

                $HoH{$mailbox_name}{$mailbox_status} = $fields[$count];
            }
        }

        #Get device-related information
        elsif ( $_ =~ /device status:\s+(.*)/ ) {
            @device_fields = split( /\s+/, $1 );
        } elsif ( $_ =~ /device_/ ) {
            my ( $device_status, @fields );
            $_ =~ s/^\s+//;
            if ( $_ =~ /^\w+:/ ) {
                $_ =~ /(\w+:?\s*\d*)\s+(.*)/;
                $device_status = $1;
                @fields = split( /\s+/, $2 );
            } else {
                $_ =~ /(\w+)\s+(.*)/;
                $device_status = $1;
                @fields = split( /\s+/, $2 );
            }
            my $count = 0;
            for ( $count = 0 ; $count < @device_fields ; $count++ ) {
                my $device_name = $slot_name . "\." . $device_fields[$count];

                $HoH{$device_name}{$device_status} = $fields[$count];
            }
            my $total = $device_status . "_total";
            $HoH{$slot_name}{$total} = $fields[ $count + 1 ];
        }
    }
    return \%HoH;
}

##########################################################################################################
# Author -arjun.lavu@netapp,com
##########################################################################################################
sub disk_show_v {
    my (%opts) = validate( @_, { Node => { type => OBJECT }, } );

    my $Node        = $opts{Node};
    my $Mode        = $Node->mode();
    my $FILER_C     = $Node->name();
    my $Host        = host($FILER_C);
    my $Transit_obj = NACL::Transit->new( name => $FILER_C );
    my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    logcomment("DEBUG:Filer state :: $filer_state");
    my $API_Object;
    my $dsk_output;

    if ( $filer_state =~ /MAINT/ ) {
        $API_Object = NACL::APISet->new(
            hostobj   => $Host,
            category  => "Node",
            interface => "CLI",
            set       => "Maintenance"
        );
        $API_Object->set_timeout( "connectrec-timeout" => 7200 );
    }
    if ( $filer_state =~ /CLI|UP/ ) {
        $API_Object = $Node->get_7m_or_nodescope_apiset();
        $API_Object->set_timeout( "connectrec-timeout" => 7200 );
        my $prompts_answers = [ ".*Do you want to continue.*" => 'y' ];
        $API_Object->execute_raw_command( 'command' => "set test", 'connectrec-match_table' => $prompts_answers );
        $dsk_output = $API_Object->execute_command( 'command' => "disk show -v" );
    }

    if ( $filer_state =~ /MAINT/i ) {
        $dsk_output = $API_Object->execute_raw_command( 'command' => "disk show -v" );
    }

    my $dsk_result = {};
    my @lines      = split( /\n/, $dsk_output );
    my $n          = 0;
    my ( $disk, $owner, $pool, $serialno, $home, $chksum );
    while ( $n <= $#lines ) {
        last if ( $lines[$n] =~ /^-----/ );
        $n++;
    }
    $n++;
    my $home_flag = 0;
    foreach my $line ( @lines[ $n .. $#lines ] ) {
        $line =~ s/^\s+|\s+$//g;
        if ( $line =~ /FAILED/i ) {
            if ( $line =~ /^\S+\s*FAILED\s*\S+/ ) {
                $line =~ /(\S+)\s*(FAILED)\s*(\S+)/;
                ( $disk, $owner, $pool, $serialno, $home, $chksum ) = ( $1, undef, 'FAILED', $3, undef, undef );
            } else {
                ( $disk, $owner, $pool, $serialno, $home, $chksum ) = ( $line =~ /(\S+)\s+(\S+)\s*\(\d+\)\s+(\S+)\s+(\S+)\s+(\S+)\s*\(\d+\)\s+(\S+)/ );
            }
        } else {
            if ( $line =~ /(\S+)\s+(\S+)\s*\(\d+\)\s+(\S+)\s+(\S+)\s+(\S+)\s*\(\d+\)\s+(\S+)/ ) {
                ( $disk, $owner, $pool, $serialno, $home, $chksum ) = ( $line =~ /(\S+)\s+(\S+)\s*\(\d+\)\s+(\S+)\s+(\S+)\s+(\S+)\s*\(\d+\)\s+(\S+)/ );
            } elsif ( $line =~ /(\S+)\s+(\S+)\s*\(\d+\)\s+(\S+)\s+(\S+)\s+/ ) {
                ( $disk, $owner, $pool, $serialno ) = ( $line =~ /(\S+)\s+(\S+)\s*\(\d+\)\s+(\S+)\s+(\S+)\s+/ );
                $home_flag = 1;
            }
        }

        $disk =~ s/^\s+|\s+$//g;
        next if ( $disk !~ /\S/ );
        $dsk_result->{$disk} = {
            'DISK'   => $disk,
            'OWNER'  => $owner,
            'POOL'   => $pool,
            'SERIAL' => $serialno,
            'HOME'   => $home,
            'CHKSUM' => $chksum
        };
    }
    logcomment("DEBUG : disk show -v output is NOT listing the values under home section") if ( $home_flag == 1 );
    return $dsk_result;
}

##########################################################################################################
# Author - skaran@netapp.com
# Usage - Mandatory paramanter - scsi_disk_error_before, scsi_disk_error_after
#
##########################################################################################################
sub compare_scsi_disk {
    my (%opts) = validate(
        @_,
        {
            scsi_disk_error_before => { type => HASHREF },
            scsi_disk_error_after  => { type => HASHREF },
            nm_error               => { type => SCALAR, default => 'Y', optional => 1 },
        }
    );

    my $beforeref = $opts{scsi_disk_error_before};
    my $afterref  = $opts{scsi_disk_error_after};
    my $flag      = 0;
    foreach my $value ( keys %{$beforeref} ) {
        my $dsk;
        if ( $value =~ /\w+\.\w+\.\w+/ ) {
            ( $dsk = $value ) =~ s/(\w+\.)//;    # removing the adapters from the disk to matching only the actual name
        } else {
            $dsk = $value;
        }    # for armadillo setups
        foreach my $parm ( keys %{ $beforeref->{$dsk} } ) {

            #Comparing all paramaters present in hash.
            #if ( $beforeref->{$dsk}{$parm} != $afterref->{$dsk}{$parm} ) {
            #    print "\n\n$dsk---->$parm mismatched\n\n";
            #   }
            if ( $parm eq 'Number of glist entries' ) {
                if ( $beforeref->{$dsk}->{'Number of glist entries'} != $afterref->{$dsk}->{'Number of glist entries'} ) {
                    logcomment("Disk - $dsk : Number of glist entries are different. --->Before ($beforeref->{$dsk}->{'Number of glist entries'}) and After ($afterref->{$dsk}->{'Number of glist entries'}) <---");
                    $flag = 1;
                }
            }
            if ( $parm eq 'Soft errors on read since boot' ) {
                if ( $beforeref->{$dsk}->{'Soft errors on read since boot'} != $afterref->{$dsk}->{'Soft errors on read since boot'} ) {
                    logcomment("Disk - $dsk : The values of Soft errors on read since boot are different. --->Before ($beforeref->{$dsk}->{'Soft errors on read since boot'}) and After ($afterref->{$dsk}->{'Soft errors on read since boot'} ) <---");
                    $flag = 1;
                }
            }
            if ( $parm eq 'Soft errors on write since boot' ) {
                if ( $beforeref->{$dsk}->{'Soft errors on write since boot'} != $afterref->{$dsk}->{'Soft errors on write since boot'} ) {
                    logcomment("Disk - $dsk : The values of Soft errors on write since boot are different. --->Before ($beforeref->{$dsk}->{'Soft errors on write since boot'}) and After ($afterref->{$dsk}->{'Soft errors on write since boot'} ) <---");
                    $flag = 1;
                }
            }
            if ( $parm eq 'Hard errors on read since boot' ) {
                if ( $beforeref->{$dsk}->{'Hard errors on read since boot'} != $afterref->{$dsk}->{'Hard errors on read since boot'} ) {
                    logcomment("Disk - $dsk : Hard errors on read since boot is different. --->Before ($beforeref->{$dsk}->{'Hard errors on read since boot'}) and After ($afterref->{$dsk}->{'Hard errors on read since boot'}) <---");
                    $flag = 1;
                }
            }
            if ( $parm eq 'Hard errors on write since boot' ) {
                if ( $beforeref->{$dsk}->{'Hard errors on write since boot'} != $afterref->{$dsk}->{'Hard errors on write since boot'} ) {
                    logcomment("Disk - $dsk : Hard errors on write since boot is different. ---> Before ($beforeref->{$dsk}->{'Hard errors on write since boot'}) and After ( $afterref->{$dsk}->{'Hard errors on read since boot'}) <---");
                    $flag = 1;
                }
            }
        }    #end of foreach parm
    }    #end of foreach dsk
    if ( $flag == 1 ) {
        return (1);
    } else {
        return (0);
    }
}

#######################################################
### Author
###        Arjun Lavu
## description :: returns the status of two sub tests
#######################################################

sub status_return {
    my (%opts) = validate( @_, { subtest_ref => { type => ARRAYREF }, } );

    my @subtests = @{ $opts{subtest_ref} };
    my @results;
    my $state = 0;
    foreach my $subtest (@subtests) {
        @results = $subtest->rslts();
        foreach my $result (@results) {
            if ( $result->type() =~ /INFO/ ) {
                $state = $result->{messages}->[0];
                if ( $state =~ /^1$/ ) {

                    # logcomment("dumping $state");
                    return $state;
                }
            }
        }
    }
    return $state;
}

=head2     my $email_subject = "$TC_name - $FILER : Test Aborted";
    my  $email_body    = "Test aborted due to filer is not in proper state"."\nLog location :$LOGDIR\n";
    send_message(mail_subject => $email_subject,
                 mail_body => $email_body,
                 MAIL_FROM => $MAIL_FROM,
                 MAIL_TO   => $MAIL_TO,
                 EOE       => 3,
                 EMAIL     => 'Y'  );

returns 1 on success and 0 on failure

The following named arguments are accepted,

=over

=item mail_subject
(Required): Subject of email to be included

=item mail_body
(Required) : Email boby along with log location

=item MAIL_FROM
(Required) : email id of person running test.

=item MAIL_TO
(Required) : list of names as the recipients wants to receive email.

=item EOE
(Required) : option to set the test suite termmination TYPE

=item EMAIL
(Required) : Send email message is enabled/disabled on an the test of the test suite

=back

=cut

sub send_message {

    my (%opts) = validate(
        @_,
        {
            mail_body    => { type => SCALAR },
            mail_subject => { type => SCALAR, },
            MAIL_FROM    => { type => SCALAR },
            MAIL_TO      => { type => SCALAR },
            EOE          => { type => SCALAR },
            EMAIL        => { type => SCALAR },
        }
    );
    my $mail_subject = $opts{mail_subject};
    my $mail_body    = $opts{mail_body};
    my $MAIL_FROM    = $opts{MAIL_FROM};
    my $MAIL_TO      = $opts{MAIL_TO};
    my $EOE          = $opts{EOE};
    my $EMAIL        = $opts{EMAIL};

    my $string;
    my $fail_msg;

    my $san_obj = new San( \*ntest::NTEST_STDOUT );
    if ( $san_obj->error() ) {
        logcomment( "**FATAL** :FAILED to instantiate san object" . $san_obj->errmsg() );
        logresult( 'FATAL', "FAILED TO INSTANTIATE SAN OBJECT" . $san_obj->errmsg() );
    }
    my %mail_params = (
        HTML    => $mail_body,
        Text    => $mail_body,
        From    => $MAIL_FROM,
        To      => $MAIL_TO,
        Subject => $mail_subject,
    );
    if ( $mail_body =~ /([\w\s\,\:\;\-\.\/]+)\.\s*(Log Location)*/ ) {
        $fail_msg = $1;
    }
    $mail_params{HTML} = "
$mail_params{Text}<\><\\HTML>";
    my $mail = HTML::Mail->new(%mail_params);
    if ( $mail_subject =~ /\:\s(FAIL)$/ ) {
        $string = $1;
    } elsif ( $mail_subject =~ /\:\s(FATAL)$/ ) {
        $string = $1;
    } elsif ( $mail_subject =~ /\:\s(INSPECT)$/ ) {
        $string = $1;
    }
    my $flag = 1;
    if (   ( $string eq "FAIL" )
        && ( $EOE != 3 )
        && ( $EMAIL =~ /No/i || $EMAIL =~ /N/i ) )
    {
        $flag = 0;
        $san_obj->sanlog( -msg => " Email not sent for failure  because EOE is not set to 3 and EMAIL set to NO by user, Reason for FAIL - $fail_msg " . scalar( localtime() ) );
        return 0;
    } elsif ( ( $string eq "FAIL" )
        && ( $EOE != 3 )
        && ( $EMAIL =~ /Yes/i || $EMAIL =~ /Y/i ) )
    {
        $mail->send() or logresult( "CONFIG", "trouble sending mail" );
        $san_obj->sanlog( -msg => " Email  sent successfully Reason for FAIL - $fail_msg  " . scalar( localtime() ) );
        logcomment("Mail sent successfully and reason is  - $fail_msg");
        return 1;

        #croak("-T option set to either 1 or 2");

    } elsif ( $EMAIL =~ /d/i ) {
        logcomment("Email NOT sent because email set to debug by user.");
    } else {
        $mail->send() or logresult( "CONFIG", "trouble sending mail" );
        if ( $string eq "FAIL" ) {
            $san_obj->sanlog( -msg => " Email  sent successfully and reason for FAIL - $fail_msg  " . scalar( localtime() ) );
        }
        logcomment("Mail sent successfully and reason is  - $fail_msg");
        return 1;
    }
} ## end sub send_message($$$$$)

################################
### Copy firmware files to filer
################################
sub copy_FW_files_to_filer_directory {
    my (%opts) = validate(
        @_,
        {
            Node       => { type => OBJECT },
            Files_path => { type => SCALAR, default => undef, optional => 1 },
            Files      => { type => ARRAYREF, default => undef, optional => 1 }
        }
    );

    my $Node        = $opts{Node};
    my $files       = $opts{Files};
    my $files_path  = $opts{Files_path};
    my $FILER_C     = $Node->name();
    my $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
    $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
    my $Mode = $Node->mode();
    my $Host = host($FILER_C);
    my ( @files_to_remove_dup, @files_to_remove, @files_to_transfer, @fw_files );
    logcomment("Deleting all the previous files present in /mroot/etc/disk_fw directory.");
    my $Api_Set_Obj_SS = NACL::APISet->new(
        hostobj   => $Host,
        category  => "Node",
        interface => "CLI",
        set       => "Systemshell",
    );
    $Api_Set_Obj_SS->set_timeout( "connectrec-timeout" => 7200 );
    my $fw_path      = "/mroot/etc/disk_fw";
    my $Filer_apiset = $Node->apiset(
        category  => 'Node',
        interface => 'CLI',
        set       => "Systemshell",
    );
    $Api_Set_Obj_SS->execute_raw_command( command => "sudo chmod 777 /mroot/etc/disk_fw" );
    my $File_on_filer = $Filer_apiset->execute_raw_command( command => "ls /mroot/etc/disk_fw" );
    chomp($File_on_filer);
    my @files_to_remove = grep { /LOD$/ } sort split( /\s+/, $File_on_filer );

    my @actual_disks_t_dup = @files_to_remove;
    my $disk_max_sup       = 3;
    my $str;
    while (@actual_disks_t_dup) {
        my $loop_no = 0;
        my @disk_list_q;
        while ( $loop_no < $disk_max_sup ) {
            push @disk_list_q, pop @actual_disks_t_dup;
            $loop_no++;
            last if ( !(@actual_disks_t_dup) );
        }
        my $local_str = join( " ", @disk_list_q );
        $str = "$str" . "$local_str" . "\n";
    }
    logcomment("Firmware files present under $fw_path  are :\n $str");

    #	foreach my $curr_file (@files_to_remove) {
    #    trim($curr_file);
    #    if ( $curr_file =~ /LOD$/ ) {
    $Api_Set_Obj_SS->execute_raw_command( command => "rm -f /mroot/etc/disk_fw/*" );

    #        logcomment(" File :: $curr_file deleted from /mroot/etc/disk_fw.");
    #    }
    #}
    if ( ( defined $files ) && ( !defined $files_path ) ) {
        foreach my $file ( @{$files} ) {
            chomp($file);
            if ( $file =~ /LOD$/ ) {
                copy_files_to_filer( Node => $Node, dest_path => $fw_path, files_to_transfer => [$file] ) if ($file);
            }
        }
    } elsif ( defined $files ) {
        foreach my $file ( @{$files} ) {
            chomp($file);
            if ( $file =~ /LOD$/ ) {
                my $tmp = $files_path . "/" . $file;
                copy_files_to_filer( Node => $Node, dest_path => $fw_path, files_to_transfer => [$tmp] ) if ($tmp);
            }
        }
    } elsif ( defined $files_path ) {
        my @files;
        opendir( FH, "$files_path" ) || die("Cannot open directory");
        my @thefiles = readdir(FH);
        closedir(FH);
        grep { push( @files, $_ ) if ( $_ =~ /LOD$/ ) } @thefiles;
        logcomment( "The number of files to copy : " . scalar @files . " and the files are @files" );
        foreach my $file (@files) {
            chomp($file);
            my $temp = $files_path . "/" . $file;
            copy_files_to_filer( Node => $Node, dest_path => $fw_path, files_to_transfer => [$temp] ) if ($temp);
        }
    }
    logcomment("$FILER_C : Verifying whether the firmware files are successfully copied to filer directory");
    my $firmware_files = $Filer_apiset->execute_raw_command( command => "ls /mroot/etc/disk_fw" );
    chomp($firmware_files);
    my @total_files = split( /\s+/, $firmware_files );
    grep { push( @fw_files, $_ ) if ( $_ =~ /LOD$/ ) } @total_files;
    my @actual_disks_t_dup = @fw_files;
    my $disk_max_sup       = 3;
    my $str;

    while (@actual_disks_t_dup) {
        my $loop_no = 0;
        my @disk_list_q;
        while ( $loop_no < $disk_max_sup ) {
            push @disk_list_q, pop @actual_disks_t_dup;
            $loop_no++;
            last if ( !(@actual_disks_t_dup) );
        }
        my $local_str = join( " ", @disk_list_q );
        $str = "$str" . "$local_str" . "\n";
    }
    logcomment( "$FILER_C : Total number of firmware files present in filer directory are " . scalar(@fw_files) . " and the files are \n $str" );
    return @fw_files;
}

sub copy_files_to_filer {
    my (%opts) = validate(
        @_,
        {
            Node              => { type => OBJECT },
            dest_path         => { type => SCALAR },
            files_to_transfer => { type => ARRAYREF },
        }
    );

    my $Node              = $opts{Node};
    my $dest_path         = $opts{dest_path};
    my $files_to_transfer = $opts{files_to_transfer};
    my $Client            = NACL::C::Client->find();
    logcomment( "Source client is : " . $Client->name() );
    my $FILER_C = $Node->name();
    my $Host    = host($FILER_C);
    my $passwd  = $Host->{default_password};
    my $scp     = NACL::MTask::SCP->new(
        source_command_interface => $Client,
        target_command_interface => $Node,
        target_username          => 'diag',
        target_password          => "$passwd",
    );
    logcomment("$FILER_C : Files to transfer :: @$files_to_transfer");
    try {
        $scp->copy_from_source_to_target(
            'files_to_copy'         => $files_to_transfer,
            set_directory_on_target => $dest_path,
        );
    }
    catch NATE::BaseException with {
        logcomment("Could NOT copy the file");    # from ".@{$files_to_transfer});
    }
}
##########################################################################################################
# Author -arjun.lavu@netapp,com
##########################################################################################################
sub unique {
    return keys %{ { map { $_ => undef } @_ } };
}
##########################################################################################################
# Author -arjun.lavu@netapp,com
##########################################################################################################
sub scsi_disk_errors {
    my (%opts) = validate( @_, { Node => { type => OBJECT }, Flag_Pre => { type => SCALAR, default => undef, optional => 1 }, } );
    my $flag        = $opts{Flag_Pre} if ( defined $opts{Flag_Pre} );
    my $Node        = $opts{Node};
    my $FILER_C     = $Node->name();
    my $Host        = host($FILER_C);
    my $Transit_obj = NACL::Transit->new( name => $FILER_C );
    my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    logcomment("DEBUG:Filer state is :$filer_state");
    my $API_Object;
    my $disk_qual_s12_pre = {};

    if ( $filer_state =~ /MAINT/ ) {
        $API_Object = NACL::APISet->new(
            hostobj   => $Host,
            category  => "Node",
            interface => "CLI",
            set       => "Maintenance"
        );

    } elsif ( $filer_state =~ /CLI|UP/ ) {
        $API_Object = $Node->get_7m_or_nodescope_apiset( connid => "console" );
    }
    $API_Object->set_timeout( "connectrec-timeout" => 7200 );
    my $raw_output;
    if ( $filer_state =~ /MAINT/i ) {

        logcomment("Filer is in Maintenance mode. Disk_qual will execute instead of scsi disk_errors");
        my $disk_list_result = disk_list_data( API_Obj => $API_Object, );
        my @dsk = keys %$disk_list_result;
        $disk_qual_s12_pre = run_disk_qual_t12(
            API_Obj         => $API_Object,
            disk_list_local => \@dsk,
            All             => "all",
            WITHOUT_ADPT    => "yes",
        );
        sleep(120);
        $API_Object->execute_raw_command( command => "\013" );
        $API_Object->execute_raw_command( command => "\013" );
        return $disk_qual_s12_pre;

        #        	$raw_output =  $API_Object->execute_raw_command( 'command' => "disk_qual start -t 12 -d all" );
        #	}
    } elsif ( $filer_state =~ /CLI|UP/i ) {
        my $kernel = $API_Object->execute_raw_command( 'command' => "run local version" );
        if ( $kernel !~ /<1d>/ ) {
            logcomment("The kernel present is non debug. command scsi disk_errors will NOT execute");
            return 1;
        } else {
            $raw_output = $API_Object->execute_command( 'command' => "scsi disk_errors" );
        }
    }
    my $cur_disk;
    my $result = {};
    my ( $paramname, $paramval );
    my @disk_list = ();
    foreach my $line ( split( /\n/, $raw_output ) ) {
        my ( $var, $paramname, $paramval );
        $line =~ s/^\s+|\s+$//g;
        if ( $line =~ /\[(\S+)\]:\s+Serial number/ ) {
            $cur_disk = $1;
        }
        if ( $line =~ /\S+:\s+(.*):\s+(.*)/ ) {
            $paramname = $1;
            $paramval  = $2;
            ($var) = ( $paramval =~ /(\d+)/i );    #Burt nmamatha 1042611
            if ( ( $paramname =~ /glist entries/ig ) && ( $flag == 1 ) ) {
                logcomment("**WARNING** : Existing G-LIST count for the drive $cur_disk is  $var ") if ( ( int($var) > 0 ) && ( int($var) < 10 ) );
                logcomment("**WARNING** : Existing G-LIST count for the drive $cur_disk is  $var is more than 10 please investigate this ") if ( ( int($var) >= 10 ) );
            }
            $paramname =~ s/^\s+|\s+$//g;
            $paramval =~ s/^\s+|\s+$//g;
            $result->{$cur_disk}->{$paramname} = $paramval;
        }
    }
    return $result;
}

sub compare_sysconfig {

    my (%opts) = validate(
        @_,
        {
            sys_addr_before => { type => HASHREF },
            sys_addr_after  => { type => HASHREF },
        }
    );

    my $sys_addr_before = $opts{sys_addr_before};
    my $sys_addr_after  = $opts{sys_addr_after};
    my $flag            = 0;
    my $i;
    my @upchannels_before;
    my @normaldisks_before;
    my @faileddisks_before;
    my @bypassdisks_before;
    my @upchannels_after;
    my @normaldisks_after;
    my @faileddisks_after;
    my @bypassdisks_after;

    #Upchannels compare
    @upchannels_before = @{ $sys_addr_before->{'upchannels'} };
    @upchannels_after  = @{ $sys_addr_after->{'upchannels'} };
    foreach my $val (@upchannels_before) {
        if ( grep /$val/, @upchannels_after ) {
            next;
        } else {
            $flag = 1;
            logcomment("Upchannel - $val is different from captured sysconfig -v command\n");
        }
    }

    #Normal disk comapre
    @normaldisks_before = @{ $sys_addr_before->{'normaldisks'} };
    @normaldisks_after  = @{ $sys_addr_after->{'normaldisks'} };
    foreach my $val (@normaldisks_before) {
        if ( grep /$val/, @normaldisks_after ) {
            next;
        } else {
            $flag = 1;
            logcomment("Normal disk $val is different from captured sysconfig -v command\n");
        }
    }

    #Failed drives
    @faileddisks_before = @{ $sys_addr_before->{'faileddisks'} };
    @faileddisks_after  = @{ $sys_addr_after->{'faileddisks'} };
    foreach my $val (@faileddisks_before) {
        if ( grep /$val/, @faileddisks_after ) {
            next;
        } else {
            $flag = 1;
            logcomment("FAILED Disk - $val is different from captured sysconfig -v command\n");
        }
    }

    #Bypass drives
    @bypassdisks_before = @{ $sys_addr_before->{'bypassdisks'} };
    @bypassdisks_after  = @{ $sys_addr_after->{'bypassdisks'} };
    foreach my $val (@faileddisks_before) {
        if ( grep /$val/, @faileddisks_after ) {
            next;
        } else {
            $flag = 1;
            logcomment("Bypassed drive - $val is different from captured sysconfig -v command\n");
        }
    }
######
    #    @upchannels = @{ $sys_addr_before->{'upchannels'} };
    #
    #    for ( $i = 0 ; $i <= $#upchannels ; $i++ ) {
    #
    #        if ( $sys_addr_before->{'upchannels'}->[$i] ne
    #            $sys_addr_after->{'upchannels'}->[$i] )
    #        {
    #
    #            logcomment(
    #"Before upchannels @{$sys_addr_before->{'upchannels'}},after upchannels @{$sys_addr_after->{'upchannels'}}\n"
    #            );
    #           $flag = 1;
    #        }
    #    } ## end for ($i = 0 ; $i < $#upchannels...
    #    @normaldisks = @{ $sys_addr_before->{'normaldisks'} };
    #
    #    for ( $i = 0 ; $i <= $#normaldisks ; $i++ ) {
    #
    #        if ( $sys_addr_before->{'normaldisks'}->[$i] ne
    #            $sys_addr_after->{'normaldisks'}->[$i] )
    #        {
    #
    #            logcomment(
    #"Before normaldisks @{$sys_addr_before->{'normaldisks'}},after normaldisks @{$sys_addr_after->{'normaldisks'}}\n"
    #            );
    #
    #           $flag = 1;
    #        }
    #    } ## end for ($i = 0 ; $i < $#normaldisks...
    #
    #    @faileddisks = @{ $sys_addr_before->{'faileddisks'} };
    #
    #    for ( $i = 0 ; $i <= $#faileddisks ; $i++ ) {
    #        if ( $sys_addr_before->{'faileddisks'}->[$i] ne
    #            $sys_addr_after->{'faileddisks'}->[$i] )
    #        {
    #
    #            logcomment(
    #"Before faileddisks @{$sys_addr_before->{'faileddisks'}},after faileddisks @{$sys_addr_after->{'faileddisks'}}\n"
    #            );
    #            $flag = 1;
    #        }
    #    }
    #
    #    @bypassdisks = @{ $sys_addr_before->{'bypassdisks'} };
    #
    #    for ( $i = 0 ; $i <= $#bypassdisks ; $i++ ) {
    #        if ( $sys_addr_before->{'bypassdisks'}->[$i] ne
    #            $sys_addr_after->{'bypassdisks'}->[$i] )
    #        {
    #
    #            logcomment(
    #"Before bypassdisks @{$sys_addr_before->{'bypassdisks'}},after bypassdisks @{$sys_addr_after->{'bypassdisks'}}\n"
    #            );
    #            $flag = 1;
    #        }
    #
    #    } ## end for ($i = 0 ; $i < $#bypassdisks...
######

    if ( $flag == 0 ) {
        return 1;
    } else {
        return 0;
    }

} ## end sub compare_sysconfig

=head2 compare_fcadmins

    my $ret = compare_fcadmins(fcadmin_add_before => $fcadmin_add_before, fcadmin_add_after => $fcadmin_add_after);

This routine returns 1 on sucess and 0 on failure:

The following named arguments are accepted,

=over

=item fcadmin_add_before

(Required) : hash address returned by fcadmin_device_map method on first instance

=item fcadmin_add_after

(Required) : hash address returned by fcadmin_device_map method on second instance

=back

=cut

sub compare_fcadmins {
    my (%opts) = validate(
        @_,
        {
            fcadmin_add_before => { type => HASHREF },
            fcadmin_add_after  => { type => HASHREF },
        }
    );

    my $disk_index;
    my $start              = 0;
    my $end                = 13;
    my $fcadmin_add_before = $opts{fcadmin_add_before};
    my $fcadmin_add_after  = $opts{fcadmin_add_after};
    for my $channels ( keys %$fcadmin_add_before ) {
        my $channel_add = $fcadmin_add_before->{$channels};
        for my $status ( keys %$channel_add ) {
            if ( $status =~ /(\d+)/ ) {
                for ( $disk_index = $start ; $disk_index <= $end ; $disk_index++ ) {
                    if ( $fcadmin_add_before->{$channels}->{$status}->{'ShelfMapping'}[$disk_index] != $fcadmin_add_after->{$channels}->{$status}->{'ShelfMapping'}[$disk_index] ) {
                        logcomment("The Values of fcadmin_add ShelfMapping disk are different . ---> Before ( $fcadmin_add_before->{$channels}->{$status}->{'ShelfMapping'}[$disk_index] ) and After ( $fcadmin_add_after->{$channels}->{$status}->{'ShelfMapping'}[$disk_index] ) <--- ");
                        return (0);
                    }
                }
            } elsif ( $status eq "Unknown" ) {
                print("Configuration issue in loop\n");
            }
        } ## end for my $status (keys %$channel_add)
    } ## end for my $channels (keys ...
    return (1);
} ## end sub compare_fcadmins

sub scrub_stop {
    my (%opts) = validate( @_, { Node => { type => OBJECT }, } );
    my $Node = $opts{Node};
    logcomment("DEBUG:Checking for Scub");
    my $Mode    = $Node->mode();
    my $FILER_C = $Node->name();
    my $Host    = host($FILER_C);
    my $API_Object_maint;
    logcomment("DEBUG:Mode of the filer $FILER_C is $Mode");
    my $Transit_obj = NACL::Transit->new( name => $FILER_C );
    my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    logcomment("DEBUG:Filer state $filer_state");

    if ( $filer_state =~ /MAINT/ ) {
        $API_Object_maint = NACL::APISet->new(
            hostobj   => $Host,
            category  => "Node",
            interface => "CLI",
            set       => "Maintenance"
        );
        $API_Object_maint->set_timeout( "connectrec-timeout" => 7200 );
        $API_Object_maint->execute_raw_command( 'command' => "aggr scrub stop" );
        sleep 30;
    }
    if ( $filer_state =~ /(CLI|UP)/gi ) {
        my $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset( connid => "console" );
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
        $Api_Set_Obj->execute_command( 'command' => "aggr scrub stop" );
        sleep 10;
        $Api_Set_Obj->execute_command( 'command' => "disk scrub stop" );
        sleep 10;
        logcomment("Scrub has been stopped");
    }
}

#######################################################################################################
#Subroutine Defn Begins
###
###
# Auther         - vpankaj@netapp.com
# Description    - This subroutine is used in all the test for pre test process.
# Pre Functions  -  check state and change to required state
#                   version
#                   disk_list
#                   sysconfig -v
#                   sysconfig -r
#                   sasadmin dev_stats
#                   storage show
#                   sasadmin expander_map
#                   vol status -s
#                   df command to display size
#                   disk_qual start -t 12 -d all
#                   start media scrub
#                   check for failed and zeroing drives.
#                   set log sense interval to 4 hrs
#                   Set disk_mfg_test 0
#                   Check for mini-disks. Send out Notification mail
#                   Check for fan speed and set to default.
#                   Stop error injection
#                   sasadmin dev_stats
# Supported Mode -  Cmode
###
#######################################################################################################

sub execute_pre_test {
    my (%opts) = validate(
        @_,
        {
            filer_mode      => { type => SCALAR },
            node_present    => { type => ARRAYREF },
            Test            => { type => OBJECT },
            change_state_to => { type => SCALAR, optional => 1, default => 'CLI' },
            LOGDIR          => { type => SCALAR, optional => 1, default => '' },
            test_setup      => { type => SCALAR, optional => 1, default => 'SAS' },
            BOOT_TYPE       => { type => SCALAR, optional => 1, default => 'A' },
        }
    );

    my @Nodes;

    #handle_run_local_error();
    if ( defined( @{ $opts{node_present} } ) ) {
        @Nodes = @{ $opts{node_present} };
    } else {
        @Nodes = NACL::C::Node->find();
    }

    handle_run_local_error( Nodes => [@Nodes] );
    my $Filer_mode  = $opts{filer_mode};
    my $Test        = $opts{Test};
    my $change_to   = $opts{change_state_to};
    my $TEST_CONFIG = $opts{test_config};
    my $test_setup  = $opts{test_setup};
    my $exit_test   = 0;
    my @Filer_array = ();
    my $execution_state;
    my @disk_list;
    my $node_ref;
    my @disk_array;
    my %FILER_API = ();
    my @disk_array;
    my $timeout;
    my $Api_Set_Obj;
    my $disk_capacity_total = 0;
    my $LOGDIR              = $opts{LOGDIR};
    my $params              = NATE::ParamSet->new( global => 1 );
    my $EOE                 = $params->get( 'EOE', default => 'default' );
    my $EMAIL               = $params->get( 'EMAIL', default => 'y' );
    my $MAIL_TO             = $params->get( 'MAIL_TO', default => 'Email to' );
    my $MAIL_FROM           = $params->get( 'MAIL_FROM', default => 'Email from' );

    if ( $opts{LOGDIR} ) {
        $LOGDIR = $opts{LOGDIR};
    } else {
        $LOGDIR = $ENV{HOME};
    }
    my $TEST_NAME;
    opendir( DIR_LOG31, $LOGDIR );
    my @files_DIR_LOG31 = readdir(DIR_LOG31);
    foreach my $file (@files_DIR_LOG31) {
        if ( ( $file =~ /(.*_NADQ02.*)\.log/ ) && ( $file !~ /results|END_FILER_CONFIG/ ) ) {
            $TEST_NAME = $1;
        }
    }
    $node_ref = \@Nodes;
    foreach my $temp_node (@Nodes) {
        my $Filer = $temp_node->name();
        push( @Filer_array, $Filer );
    }

    # Check state of filer and Execute based on state
    logcomment("Nodes present - @Filer_array");
    logcomment("DEBUG:Log loction - $LOGDIR");
    my @chk_state = ();

    # Check for state and call respective subroutines:
    foreach my $Node (@Nodes) {
        my $Transit_obj;
        my $FILER_C = $Node->name();
        $Transit_obj = NACL::Transit->new( name => $FILER_C );
        my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
        $Test->nlog("$FILER_C : Filer is in $filer_state ");
        push( @chk_state, $filer_state );
    }
    my $len = @chk_state;
    if ( $len > 1 ) {
        if ( $chk_state[0] eq $chk_state[1] ) {
            $execution_state = $chk_state[0];
            $Test->nlog("Execution state - $execution_state\n");
        } else {
            $Test->nlog("States of filer is different, Boot filer in same mode");
        }
    } else {
        $execution_state = $chk_state[0];
        $Test->nlog("Execution state - $execution_state\n");
    }

    # Check filer State and change to required state
    $Test->nlog("##################################################################################");
    $Test->nlog("##");
    $Test->nlog("## Begining of PRE_TEST logs for Filer : @Filer_array");
    $Test->nlog("##");
    $Test->nlog("##################################################################################");
    $Test->nlog("Checking boot state of filer, and booting in required mode");
    my $filer_state;
    my $Transit_obj;
    my @change_states;
    my $Check_flag = 0;

    foreach my $Node (@Nodes) {
        my $FILER_C     = $Node->name();
        my $Transit_obj = NACL::Transit->new( name => $FILER_C );
        my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
        logcomment("Filer $FILER_C is in $filer_state ");
        if ( $opts{change_state_to} ) {
            if ( $filer_state ne $change_to ) {
                $Test->nlog("Filer - $FILER_C is in $filer_state state");
                logcomment("Filer - $FILER_C is NOT in required state - $change_to, changing to $change_to");
                push( @change_states, $FILER_C );
            }
            if ( $filer_state eq $change_to ) {
                $Test->nlog("Filer - $FILER_C is in $filer_state state");
                $Test->nlog("Filer - $FILER_C is in required state - $change_to");
            }
        }
    }
    my @subtests;
    if (@change_states) {
        foreach my $filer_name (@change_states) {
            push(
                @subtests,
                subtest(
                    \&boot_filer_in_req_state,                  -runid,
                    "boot_filer_in_req_state_" . "$filer_name", -bg,
                    "--",
                    Test            => $Test,
                    filer_name      => $filer_name,
                    change_state_to => $change_to,
                )
            );
        }
        Subtest::wait_finish( subtest => [@subtests] );
        my ( $fail_cnt, $fatal_cnt );
        my @results;
        foreach my $subtest (@subtests) {
            @results = $subtest->rslts();
            foreach my $result (@results) {
                if ( $result->type() =~ /INFO/ ) {
                    $Test->nlog("Subtest boot_filer_in_req_state completed successfully");
                } elsif ( $result->severity() >= 0 ) {
                    $Test->nlog("Subtest boot_filer_in_req_state not completed successfully");
                    if ( $result->type() =~ /FAIL/i ) {
                        $fail_cnt++;
                    }
                    if ( $result->type() =~ /FATAL|SCRIPT|CONFIG/ ) {
                        $fatal_cnt++;
                    }
                } ## end elsif ($result->severity(...
            } ## end foreach my $result (@results)
        } ## end foreach my $subtest (@subtests)
        if ( $fail_cnt == 0 ) {
            $Test->nlog("FILER Booted the filer successfully in required state");
            $Check_flag = 1;
        }
    }

    # Check state of filer after booting
    if ( $Check_flag == 1 ) {
        foreach my $Node (@Nodes) {
            my $Transit_obj;
            my $FILER_C = $Node->name();
            $Transit_obj = NACL::Transit->new( name => $FILER_C );
            my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
            $Test->nlog("$FILER_C : Filer is in $filer_state ");
            if ( "$filer_state" eq "$change_to" ) {
                $Test->nlog("$FILER_C : Is in required test, proceeding with test");
                $execution_state = $filer_state;
                $Test->nlog("$FILER_C : Execution state changed to : $change_to");
            }
            if ( "$filer_state" ne "$change_to" ) {
                logcomment("**FATAL** : $FILER_C is not in required state, CANNOT boot in required state");
                logresult( "FATAL", "$FILER_C IS NOT IN REQUIRED STATE, CANNOT BOOT IN REQUIRED STATE" );
            }
        }
    }

    # If maintenanace mode :
    if ( $execution_state eq 'MAINT' ) {
        foreach my $Node (@Nodes) {
            my $Filer      = $Node->name();
            my $host       = host($Filer);
            my $API_Object = NACL::APISet->new(
                hostobj   => $host,
                category  => "Node",
                interface => "CLI",
                set       => "Maintenance"
            );
            $FILER_API{$Filer} = $API_Object;
        }
    }

    # Check security login, ssh option
    $Test->nlog("===================================================================================");
    $Test->nlog("==== PRE_TEST STEP 1 : Check SSH parameters and Enable SSH");
    $Test->nlog("===================================================================================");
    foreach my $Node (@Nodes) {
        my $FILER_C = $Node->name();
        logcomment("DEBUG:$FILER_C - Checking SSH and enabling SSH");
        if ( $execution_state eq 'CLI' ) {
            $Test->nlog("$FILER_C : Check security login, enable ssh option ");
            $Test->nlog("$FILER_C : Filer mode is : $Filer_mode");
            enable_ssh(
                Node => $Node,
                Test => $Test,
                Mode => $Filer_mode
            );
            logcomment("$FILER_C - End of Checking SSH and enabling SSH");

            # del_system_logs(Node  =>$Node);
            logcomment("$FILER_C : Disable all storage debug messages");
            my $host = host($FILER_C);
            disable_debug_msg( Node => $Node );

            #start_shelflog_detector(Node=>$Node);
            start_ems_detector( Node => $Node );
        } else {
            logcomment("$FILER_C - SSH will NOT be validated in Maintenance mode tests");
        }
    }

    # Check kernel version
    $Test->nlog("===================================================================================");
    $Test->nlog("==== PRE_TEST STEP 2 : Check Kernel Version");
    $Test->nlog("===================================================================================");
    foreach my $Node (@Nodes) {
        my $FILER_C = $Node->name();
        logcomment("$FILER_C - Check Version on filer");
        if ( $execution_state eq 'CLI' ) {
            $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
        } else {
            $Api_Set_Obj = $FILER_API{$FILER_C};
        }
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
        my $ver_output = $Api_Set_Obj->execute_command( 'command' => 'version' );
        logcomment("Version on $FILER_C - $ver_output");
        logcomment("$FILER_C - End of Checking Version on filer");
    }

    # Check for disk availibility (pre test)
    $Test->nlog("===================================================================================");
    $Test->nlog("==== PRE_TEST STEP 3 : Checking for disk availability");
    $Test->nlog("===================================================================================");
    {
        my ( $max_disk_size, $disk_size );
        my @disk_list_common;
        logcomment("Checking disk availability of Filer");
        if ( $execution_state eq 'CLI' ) {
            @disk_list_common = NACL::C::StorageDisk->find( command_interface => $Nodes[0] );
            @disk_list;
            foreach my $disk (@disk_list_common) {
                push( @disk_list, $disk->get_one_state_attribute('disk') );
            }
            my $disk_length = @disk_list;
            @pre_disk_count = @disk_list;
            if ( $disk_length > 0 ) {
                my $dsks = _print_array( \@disk_list );
                $Test->nlog( "@Filer_array - Disk attached - \n" . $dsks );
            } else {
                $Test->nlog("@Filer_array -No disk available for testing, exiting from rest of the test cases");
                $exit_test = 1;
                logcomment("**FATAL** : @Filer_array - NO DISK available for testing, exiting from rest of the test cases");
                logresult( "FATAL", "@Filer_array - NO DISK AVAILABLE FOR TESTING,exiting from rest of the test cases" );
            }
        } else {
            my $FILER_C     = $Nodes[0]->name();
            my $Api_Set_Obj = $FILER_API{$FILER_C};
            $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
            logcomment("DEBUG:Filer : $FILER_C : Executing disk_list on the filer");
            my $dsk_output       = $Api_Set_Obj->execute_raw_command( 'command' => "disk_list" );
            my $disk_list_result = {};
            my @lines            = split( /\n/, $dsk_output );
            my $n                = 0;

            while ( $n <= $#lines ) {
                last if ( $lines[$n] =~ /^-----/ );
                $n++;
            }
            $n++;
            foreach my $line ( @lines[ $n .. $#lines ] ) {
                my ( $disk, $chan, $ven, $prodid, $rev, $serialno, $hw, $blocks, $bps, $dq, ) = ( $line =~ /(\d\w.\d+\.\d+L?P?\d?)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)/ );
                if ( ( $line =~ /\d\w\.\d\d/ ) || ( $line =~ /\d\w\.\d\d\.\d\dL?P?\d?/ ) || ( $line =~ /\d\w\.\d\d\.\d\dL?P?\d+?/ ) ) {
                    $disk_list_result->{$disk} = {
                        'DISK'       => $disk,
                        'CHAN'       => $chan,
                        'VENDOR'     => $ven,
                        'PRODUCT_ID' => $prodid,
                        'REV'        => $rev,
                        'SERIAL'     => $serialno,
                        'HW'         => $hw,
                        'BLOCKS'     => $blocks,
                        'BPS'        => $bps,
                        'DQ'         => $dq
                    };
                }
            }
            @disk_array = keys( %{$disk_list_result} );
            my $disk_length = @disk_array;
            @pre_disk_count = @disk_array;
            if ( $disk_length > 0 ) {
                $Test->nlog(" Disk attached - @disk_array");
            } else {
                logcomment("**FATAL** : NO DISK AVAILABLE for testing, exiting from rest of the test cases");
                logresult( "FATAL", "- NO DISK AVAILABLE FOR TESTING,exiting from rest of the test cases" );
            }
            for my $dsk (@disk_array) {
                $disk_size           = $disk_list_result->{$dsk}->{'BLOCKS'};
                $max_disk_size       = $disk_size if ( $disk_size > $max_disk_size );
                $disk_capacity_total = $disk_capacity_total + $disk_size;
            }
            my ($string) = readable_disk_size( Blocks => $disk_capacity_total );
            logcomment("System capacity is $string");
            my ($string) = readable_disk_size( Blocks => $max_disk_size );
            logcomment("Maximum disk size is $string");
            if ( $max_disk_size <= 20971520 ) {
                $timeout = $timeout + 1200;
            } elsif ( $max_disk_size <= 2147483648 ) {
                $timeout = $timeout + ( 1200 * 5 );
            } else {
                $timeout = $timeout + ( 1200 * 10 );
            }
        }
        logcomment("End of Checking disk availability of Filer");
        foreach my $Node (@Nodes) {
            my $FILER_C        = $Node->name();
            my @temp_disk_info = list_of_disk( Node => $Node );
            my $dsks           = _print_array( \@temp_disk_info ) if (@temp_disk_info);
            logcomment( "Total drives present in the filer $FILER_C" . "are " . scalar @temp_disk_info . " and the drives are @temp_disk_info" );
            logcomment("$FILER_C : Checking if Rebuild Assist is disabled on drives");
            foreach my $drvs (@temp_disk_info) {
                next if ( $drvs =~ /P1|P2|P3/ );
                if ( $execution_state eq 'CLI' ) {
                    $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
                } else {
                    $Api_Set_Obj = $FILER_API{$FILER_C};
                }
                $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
                if ( $execution_state eq 'CLI' ) {
                    my $output = $Api_Set_Obj->execute_command( 'command' => "scsi rebuild_assist -c $drvs" );
                    if ( $output =~ /Rebuild Assist is enabled/i ) {
                        logcomment("Rebuild Assist is enabled on drive $drvs, disabling it");
                        $Api_Set_Obj->execute_command( 'command' => "scsi rebuild_assist -d $drvs" );
                    }
                } else {
                    my $output = $Api_Set_Obj->execute_raw_command( 'command' => "scsi rebuild_assist -c $drvs" );
                    if ( $output =~ /Rebuild Assist is enabled/i ) {
                        logcomment("Rebuild Assist is enabled on drive $drvs, disabling it");
                        $Api_Set_Obj->execute_raw_command( 'command' => "scsi rebuild_assist -d $drvs" );
                    }
                }
            }
        }
    }
    $Test->nlog("===================================================================================");
    $Test->nlog("==== PRE_TEST STEP 4 : Set log sense interval");
    $Test->nlog("===================================================================================");
    foreach my $Node (@Nodes) {
        my $FILER_C = $Node->name();
        logcomment("DEBUG: $FILER_C - Set log sense interval");
        if ( $execution_state eq 'CLI' ) {
            $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
            $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
            logcomment("DEBUG:$FILER_C -Set options disk.log_sense.interval for 40 minutes");
            NACL::C::Options->option(
                command_interface => $Node,
                'option-name'     => 'disk.log_sense.interval',
                'option-value'    => '4'
            );
            logcomment("DEBUG:Filer - Waiting for 6 minute");
            sleep(360);
            NACL::C::Options->option(
                command_interface => $Node,
                'option-name'     => 'disk.log_sense.interval',
                'option-value'    => '40'
            );
            logcomment("DEBUG:Filer - Waiting for a minute");
            sleep(60);
        } else {
            $Api_Set_Obj = $FILER_API{$FILER_C};
            logcomment("$FILER_C : NO NEED to set log sense interval to 4 hrs for Maintenance mode");
        }
        logcomment("$FILER_C - End of setting log sense interval");
    }

    # Get filer config
    $Test->nlog("===================================================================================");
    $Test->nlog("==== PRE_TEST STEP 5 : Get Filer configurations");
    $Test->nlog("===================================================================================");
    foreach my $Node (@Nodes) {
        my %config_1;
        my $flag     = 0;
        my $cnt_fw   = 1;
        my $cnt_size = 1;
        my @arr1     = ();
        my %comments;
        my $output;
        my @models;
        my $FILER_C = $Node->name();
        $Test->nlog("- Get filer configruation for filer $FILER_C");

        if ( $execution_state eq 'CLI' ) {
            $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
            $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
            $output = $Api_Set_Obj->execute_command( 'command' => 'sysconfig -v', 'timeout' => 600 );
        } else {
            $Api_Set_Obj = $FILER_API{$FILER_C};
            $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
            $output = $Api_Set_Obj->execute_command( 'command' => 'sysconfig -v', 'timeout' => 600 );
        }
        @arr1 = split( /\n/, $output );
        foreach my $line (@arr1) {
            if ( $line =~ /ID\s+Vendor\s+Model\s+FW\s+Size/ig ) { $flag = 1; }
            if ( ( $line =~ /(\d+\.\w+)\s*\:\s*\S+\s*(\S+)\s*(\S+)\s*(\S+)\s*/ ) && ( $flag == 1 ) ) {
                my $drive = $1;
                my $model = $2;
                my $fw    = $3;
                my $size  = $4;
                $Non_Medium_Model{$drive} = $model;
                push( @models,                            $model ) unless grep { $_ eq $model } @models;
                push( @{ $config_1{$model}{$fw}{$size} }, $drive ) unless grep { $_ == $drive } @{ $config_1{$model}{$fw}{$size} };
                my @key_Size = keys( %{ $config_1{$model}{$fw} } );
                my @key_fw   = keys( %{ $config_1{$model} } );

                if ( scalar @key_fw > $cnt_fw ) {
                    $comments{$model}{'fw'} = "**WARNING** : Model $model is having drives with different Firmware version : @key_fw\n";
                    $cnt_fw++;
                } elsif ( scalar @key_Size > $cnt_size ) {
                    $comments{$model}{'sz'} = "**WARNING** : Model $model is having drives with different Capacity : @key_Size\n";
                    $cnt_size++;
                }
            }
        }
        foreach my $mod (@models) {
            logcomment("$comments{$mod}{'fw'}") if ( defined $comments{$mod}{'fw'} );
            logcomment("$comments{$mod}{'sz'}") if ( defined $comments{$mod}{'sz'} );
        }

        $Test->nlog("- End of Get filer configruation for filer $FILER_C");
    }

    # Execution sysconfig -r
    $Test->nlog("===================================================================================");
    $Test->nlog("==== PRE_TEST STEP 6 : Record sysconfig -r information of the filer");
    $Test->nlog("===================================================================================");
    if ( $execution_state eq 'CLI' ) {
        my @subtests;
        $pre_post_recon_copy = "pre";
        foreach my $Node (@Nodes) {
            my $FILER_C = $Node->name();
            push( @subtests, subtest( \&check_recons_sickdisk, -runid, "check_recons_sickdisk_$FILER_C", -bg, "--", Node => $Node ) );
        }
        Subtest::wait_finish( subtest => [@subtests] );
        status_return( subtest_ref => [@subtests] );
    } else {
        logcomment("Filer is in Maintenance mode, command \"sysconfig -r\" is NOT supported");
    }

    # Record link statistics for all adapters and drives
    $Test->nlog("===================================================================================");
    $Test->nlog("==== PRE_TEST STEP 7 : Record link statistics for all adapters and drives");
    $Test->nlog("===================================================================================");
    foreach my $Node (@Nodes) {
        my $FILER_C = $Node->name();
        my $Host    = host($FILER_C);
        logcomment("$FILER_C - Record link statistics");
        if ( $test_setup ne 'FC' ) {
            $SAS_ADMIN_DEV_PRE->{$FILER_C} = sasadmin_dev_stats_cmode( node => $Node );
        } else {
            $SAS_ADMIN_DEV_PRE->{$FILER_C} = fcadmin_fcal_stats( Node => $Node );
        }
        logcomment("$FILER_C - End of Record link statistics");
    }

    # Storage show information of the filer
    $Test->nlog("===================================================================================");
    $Test->nlog("==== PRE_TEST STEP 8 : Record storage show information of the filer");
    $Test->nlog("===================================================================================");
    foreach my $Node (@Nodes) {
        my $FILER_C = $Node->name();
        logcomment("DEBUG:$FILER_C - Executing storage show");
        if ( $execution_state eq 'CLI' ) {
            $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
            $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
            $Api_Set_Obj->execute_command( 'command' => 'storage show', 'timeout' => 600 );
        } else {
            $Api_Set_Obj = $FILER_API{$FILER_C};
            $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
            $Api_Set_Obj->execute_command( 'command' => 'storage show', 'timeout' => 600 );
        }
        logcomment("$FILER_C - End of Executing storage show");
    }

    # Record expander map of the adapter
    $Test->nlog("===================================================================================");
    $Test->nlog("==== PRE_TEST STEP 9 : Record expander map of the adapter");
    $Test->nlog("===================================================================================");
    foreach my $Node (@Nodes) {
        my $FILER_C = $Node->name();
        logcomment("$FILER_C - Record expander map of the adapter");
        my $Host = host($FILER_C);
        if ( $test_setup ne 'FC' ) {
            sasadmin_expander_map_cmode( node => $Node );
        } else {
            fcadmin_device_map( Node => $Node );
        }
        logcomment("$FILER_C - End of Record expander map of the adapter");
    }

    # Record Spare drives
    $Test->nlog("===================================================================================");
    $Test->nlog("==== PRE_TEST STEP 10 : Record Spare drives attached");
    $Test->nlog("===================================================================================");
    foreach my $Node (@Nodes) {
        my $FILER_C = $Node->name();
        logcomment("$FILER_C - Recording Spare drives ");
        if ( $execution_state eq 'CLI' ) {
            $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
            $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
            $Api_Set_Obj->execute_command( 'command' => 'vol status -s' );
        } else {
            logcomment("Spare drive check is NOT required since the filer is in Maintenance mode");
        }
        logcomment("$FILER_C - End of recording Spare drives ");
    }

    # Record df command to display size
    $Test->nlog("===================================================================================");
    $Test->nlog("==== PRE_TEST STEP 11 : Record df command to display size");
    $Test->nlog("===================================================================================");
    foreach my $Node (@Nodes) {
        my $FILER_C = $Node->name();
        logcomment("$FILER_C - Record df command to display volume size or disk size");
        if ( $execution_state eq 'CLI' ) {
            $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
            $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
            $Api_Set_Obj->execute_command( 'command' => 'df' );
        } else {
            logcomment("Filer $FILER_C is in Maintenance, Hence printing disk capacity size");
            my ($string) = readable_disk_size( Blocks => $disk_capacity_total );
            logcomment("System capacity is $string");
        }
        logcomment("$FILER_C - End of recording df command to display volume size or disk size");
    }

    # Execute disk_qual t 12 for all disk
    $Test->nlog("===================================================================================");
    $Test->nlog("==== PRE_TEST STEP 12 : Printing logsense data for all the disks");
    $Test->nlog("===================================================================================");
    foreach my $Node (@Nodes) {
        my $FILER_C = $Node->name();
        logcomment("$FILER_C - Print logsense data for all drives");
        $SCSI_DISK_ERRORS->{$FILER_C} = scsi_disk_errors( Node => $Node, Flag_Pre => 1 );
        logcomment("$FILER_C - End if printing logsense data for all drives");
    }

    # start media scrub
    $Test->nlog("===================================================================================");
    $Test->nlog("==== PRE_TEST STEP 13 : Enable  media scrub ");
    $Test->nlog("===================================================================================");
    foreach my $Node (@Nodes) {
        my $FILER_C = $Node->name();
        logcomment("$FILER_C - Enable media Scrub ");
        if ( $execution_state eq 'CLI' ) {
            $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
            $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
            $Api_Set_Obj->execute_raw_command( 'command' => 'storage raid-options modify * -name raid.media_scrub.enable on' );

            #BURT1048953 - abalaji
            logcomment("$FILER_C : Disable shelf fw auto update");
            $Api_Set_Obj->execute_command( 'command' => "options shelf.fw.auto.update OFF" );
            $Api_Set_Obj->execute_command( 'command' => "options shelf.fw.auto.update" );

            #----End of change for BURT1048953----#
        } else {
            logcomment("$FILER_C : NO NEED to enable media scrub on Maintenance mode");
        }
        logcomment("$FILER_C - End of enabling media Scrub ");
    }

    #check for failed and zeroing drives
    $Test->nlog("===================================================================================");
    $Test->nlog("==== PRE_TEST STEP 14 : Check for non-zeroed disk or failed disk");
    $Test->nlog("===================================================================================");
    if ( $execution_state =~ /CLI|UP|MAINT/ ) {    #BURT1041406 - abalaji
        {
            my @subtests;
            foreach my $Node (@Nodes) {
                my $FILER_C = $Node->name();
                push( @subtests, subtest( \&report_failed_drives, -runid, "report_failed_drives_" . "$FILER_C", -bg, "--", Node => $Node ) );
            }
            Subtest::wait_finish( subtest => [@subtests] );
        }
        if ( $execution_state =~ /CLI|UP/ ) {      #BURT1041406 - abalaji
            disable_fg_bg_firmware_hammer( Nodes => [@Nodes] );
            unfail_disk_zero_spares( Nodes => [@Nodes] );
        }
        logcomment("End of checking for non-zeroed disk or failed disk, unfail disk");
    } else {
        logcomment("As the filer is in $execution_state state, check for non-zeroed disk or FAILED disk could NOT be performed");    #BURT1041406 - abalaji
    }

=cut
                $Test->nlog("===================================================================================");
                $Test->nlog("==== PRE_TEST STEP 14 : Set log sense interval");
                $Test->nlog("===================================================================================");
                foreach my $Node (@Nodes){
                	my $FILER_C = $Node->name();
			logcomment("$FILER_C - Set log sense interval");
                    	if ($execution_state eq 'CLI'){
    	                	$Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
	            		logcomment("$FILER_C -Set options disk.log_sense.interval for 30 minutes");
			        NACL::C::Options->option(
			                command_interface => $Node,
			                'option-name'     => 'disk.log_sense.interval',
			                'option-value'    => '30'
			        );
				logcomment("DEBUG:FILER - Waiting for a minute");
				sleep(60);
                    	} else {
				$Api_Set_Obj = $FILER_API{$FILER_C};
				logcomment("$FILER_C : No need to Set log sense interval to 4 hrs for Maintenance mode");
                    	}
			logcomment("$FILER_C - End of setting log sense interval");
                }
=cut

    # Set disk mfg flag
    $Test->nlog("===================================================================================");
    $Test->nlog("==== PRE_TEST STEP 15 : Set flag disk mfg");
    $Test->nlog("===================================================================================");
    foreach my $Node (@Nodes) {
        my $FILER_C = $Node->name();
        logcomment("$FILER_C - Setting disk_mfg_test 0");
        if ( $execution_state eq 'CLI' ) {
            $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
            $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
            $Api_Set_Obj->execute_command( 'command' => 'setflag disk_mfg_test 0' );
            $Test->nlog("$FILER_C - Flag set");
            $Api_Set_Obj->execute_command( 'command' => 'printflag disk_mfg_test' );
            sleep 5;
        } else {
            logcomment("Filer is in Maintenance mode. mfg flag is NOT accessible!!!");
        }
        logcomment("$FILER_C - End of setting disk mfg flag");
    }

    # Check for mini-disks. Send out Notification mail
    $Test->nlog("===================================================================================");
    $Test->nlog("==== PRE_TEST STEP 16 : Check for mini-disks");
    $Test->nlog("===================================================================================");
    my $FILER_MINI = {};
    foreach my $Node (@Nodes) {
        my $FILER_C = $Node->name();
        logcomment("$FILER_C - Check for mini-disks");
        my $Mode        = $Node->mode();
        my $Host        = host($FILER_C);
        my $transit_obj = NACL::Transit->new( name => $Host );
        my $filer_state = $transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
        my ( @mini_disks, $Api_Set_Obj );
        my $kernel;

        if ( $filer_state =~ /UP|CLI/i ) {
            $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
            $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
            $kernel = $Api_Set_Obj->execute_raw_command( command => "run local version" );
        } elsif ( $filer_state =~ /MAINT/i ) {
            my $console = Tharn::connect("$FILER_C#console");

            # Set the properties for the Connectrec used for creating the APIset
            $console->{prompts}  = [qr/\*>/];
            $console->{max_idle} = 600;
            $console->{on_idle}  = sub { $console->execute(""); };
            $Api_Set_Obj         = NACL::APISet->new(
                connection => $console,
                category   => "Node",
                interface  => "CLI",
                set        => "Maintenance"
            );
            $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
            $kernel = $Api_Set_Obj->execute_raw_command( command => "version" );
        }
        my $res;
        if ( $kernel !~ /<1d>/ ) {
            logcomment("The kernel present is non debug. Mini disk command will NOT execute");
        } else {
            try {
                $res = $Api_Set_Obj->mini_disk_list();
            }
            catch NACL::APISet::Exceptions::FailedAndNotFoundException with {
                logcomment("FILER : $FILER_C : mini_disk list command is NOT working on this particular kernel");
            };
        }
        if ( !$res ) {
            next;
        }
        my @disks_obj = @{ $res->get_parsed_output() };
        foreach (@disks_obj) {
            if ( $_->{type} ne "NORMAL disk" ) {
                push( @mini_disks, $_->{disk} );
                $FILER_MINI->{$FILER_C} = [@mini_disks] if ( scalar @mini_disks );
            }
        }
        logcomment("$FILER_C - End of checking for mini-disks");
    }
    foreach ( keys %{$FILER_MINI} ) {
        logcomment( "Number of Mini_disks present on the filer $_ are " . scalar @{ $FILER_MINI->{$_} } . " and the drives are @{$FILER_MINI->{$_}}" );
    }

    # Check for fan speed (pre)
    $Test->nlog("===================================================================================");
    $Test->nlog("==== PRE_TEST STEP 17 : Check for fan speed and set to defaults");
    $Test->nlog("===================================================================================");
    if ( $test_setup eq "SAS" ) {
        foreach my $Node (@Nodes) {
            my $FILER_C = $Node->name();
            my $sysconfig_out;
            logcomment("$FILER_C - Checking for fan speed");
            if ( $execution_state eq 'CLI' ) {
                $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
            } else {
                $Api_Set_Obj = $FILER_API{$FILER_C};
            }
            $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
            if ( $execution_state =~ /CLI|UP/i ) {
                logcomment("Executing sysconfig -v for checking platform");
                $sysconfig_out = $Api_Set_Obj->execute_command( 'command' => 'sysconfig -v', 'timeout' => 600 );
            } elsif ( $execution_state =~ /MAINT/ ) {
                logcomment("Executing sysconfig -v for checking platform");
                $sysconfig_out = $Api_Set_Obj->execute_raw_command( 'command' => 'sysconfig -v' );
            }
            chomp( my @sysconf_lines = split( /\r?\n/, $sysconfig_out ) );
            my $shelf_id;
            foreach my $line (@sysconf_lines) {
                if ( $line =~ /Shelf\s*\d*:\s*(\S+)\s+Firmware rev/ ) {
                    $shelf_id = $1;
                }
            }
            if ( ( $shelf_id =~ /DS46012/i ) && ( $execution_state =~ /CLI|UP/i ) ) {
                logcomment("PLATFORM: Trafford(Shelf ID:$shelf_id)");
                my $adapters    = {};
                my @expanders_r = ();

                $adapters = shelf_id_trafford( Node => $Node );
                @expanders_r = keys %$adapters;
                foreach my $var (@expanders_r) {
                    my $aft = $Api_Set_Obj->execute_command( 'command' => "sasadmin expander_cli $var 'fan_set normal'" );
                    if ( $aft =~ /Setting all fans to normal/ ) {
                        sleep(60);
                        logcomment("Fan-speed has set to default value");
                        logcomment("Checking the Fans speed again");
                        $Api_Set_Obj->execute_command( 'command' => "sasadmin expander_cli $var 'fan_set speed'" );
                        sleep 5;
                    }
                }
            } else {
                my $adapterslot;
                my ( $shelfid, $adapter_val );
                my %adapter_hash;
                my $flag1      = 0;
                my $output     = $Api_Set_Obj->execute_command( 'command' => 'sasadmin expander_map' );
                my @slot_array = split( /\n\n/, $output );
                foreach (@slot_array) {
                    my @shelfid;
                    if ( $_ =~ /Expanders on channel\s+(\w+)/ ) {
                        $adapterslot = $1;
                    }
                    if ( $_ =~ /.*\s+ID\s+(\d+)/ ) {
                        @shelfid = $_ =~ /.*\s+ID\s+(\d+)/g;
                    }
                    if ( ( $adapterslot ne "" ) && (@shelfid) ) {
                        $adapter_hash{$adapterslot} = [@shelfid];
                    }
                }

                #Setting the fan Speeds to default values
                my $flag1 = 0;
                foreach my $key ( keys %adapter_hash ) {
                    last if ( $flag1 == 1 );
                    my @var = @{ $adapter_hash{$key} } if ( defined $adapter_hash{$key} );
                    foreach (@var) {
                        $adapter_val = "$key.$_";
                        my $aft = $Api_Set_Obj->execute_command( 'command' => "sasadmin expander_cli $adapter_val 'fan_set normal'" );
                        if ( $aft =~ /Setting all fans to normal/ ) {
                            sleep(60);
                            logcomment("Fan-speed has set to default value");
                            logcomment("Checking the Fans speed again");
                            $Api_Set_Obj->execute_command( 'command' => "sasadmin expander_cli $adapter_val 'fan_set speed'" );
                            sleep 5;
                            $flag1 = 1;
                            last;
                        }
                    }
                }
            }
            logcomment("$FILER_C - End of checking for fan speed");
        }    #End of foreach nodes.
    } else {
        logcomment("Test setup is NOT SAS, hence not checking fan speed");
    }

    # Stop any error injection if running (pre-cli)
    $Test->nlog("===================================================================================");
    $Test->nlog("==== PRE_TEST STEP 18 : Stop any error injection if running ");
    $Test->nlog("===================================================================================");
    foreach my $Node (@Nodes) {
        my $FILER_C = $Node->name();
        logcomment("$FILER_C - Stop any error injection");
        if ( $execution_state eq 'CLI' ) {
            $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
            $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
            my $kernel;
            $kernel = $Api_Set_Obj->execute_raw_command( command => "run local version" );
            if ( $kernel !~ /<1d>/ ) {
                logcomment("The kernel present is non debug. error injections CANNOT be disabled");
            } else {
                if ( $test_setup ne 'FC' ) {
                    $Api_Set_Obj->execute_command( 'command' => 'sasadmin inject disable' );
                } else {
                    $Api_Set_Obj->execute_command( 'command' => 'fcadmin inject disable' );
                }
            }
        } else {
            $Api_Set_Obj = $FILER_API{$FILER_C};
            $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
            my $kernel;
            $kernel = $Api_Set_Obj->execute_raw_command( command => "version" );
            if ( $kernel !~ /<1d>/ ) {
                logcomment("The kernel present is non debug. error injections CANNOT be disabled");
            } else {
                if ( $test_setup ne 'FC' ) {
                    $Api_Set_Obj->execute_command( 'command' => 'sasadmin inject disable' );
                } else {
                    $Api_Set_Obj->execute_command( 'command' => 'fcadmin inject disable' );
                }
            }
        }
        logcomment("End of error injection");
    }

    $Test->nlog("===================================================================================");
    $Test->nlog("==== PRE_TEST STEP 19 : Execute get_phy_state");
    $Test->nlog("===================================================================================");
    foreach my $Node (@Nodes) {
        my $FILER_C = $Node->name();
        if ( $test_setup ne 'FC' ) {
            logcomment("$FILER_C - Execute sasadmin expander_phy_state");
            $GET_PHY_STATE->{$FILER_C} = get_phy_state( Node => $Node );
            logcomment("$FILER_C - End of sasadmin expander_phy_state");
        } else {
            logcomment("NO CHECKING for FC");
        }
    }
    $Test->nlog("===================================================================================");
    $Test->nlog("==== PRE_TEST STEP 20 : Executing command to get details of each disk");
    $Test->nlog("===================================================================================");
    foreach my $Node (@Nodes) {
        my $FILER_C = $Node->name();
        logcomment("DEBUG : $FILER_C - Execute storage show disk -a ");
        if ( $execution_state eq 'CLI' ) {
            $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
        } else {
            $Api_Set_Obj = $FILER_API{$FILER_C};
        }
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
        $pre_storage_show_drive->{$FILER_C} = storage_show_drive( API_OBJ => $Api_Set_Obj, Node => $Node );

        #my $result = scsi_inquiry_cmode(API_OBJ=> $Api_Set_Obj,Node=> $Node);
        #if ($result == 0) {
        #       logcomment("storage show completed for all disks");
        #}
    }
    $Test->nlog("===================================================================================");
    $Test->nlog("==== PRE_TEST STEP 21 : Execute storage show disk -a");
    $Test->nlog("===================================================================================");
    foreach my $Node (@Nodes) {
        my $FILER_C = $Node->name();
        logcomment("DEBUG:$FILER_C - Execute storage show disk -a");
        logcomment("PRE_TEST : $FILER_C - Checking for Dynamic Qualification of the drives");
        $STO_DISK_SHOW->{$FILER_C} = storage_show_disk_a_data( Node => $Node );
        my @sto_disk_show_fields = keys ${$STO_DISK_SHOW}{$FILER_C};
        my %dq_drives;
        foreach my $field (@sto_disk_show_fields) {
            if ( $field =~ /\w+\.\S+/ ) {
                if ( ${$STO_DISK_SHOW}{$FILER_C}{$field}{'Dynamically qualified'} =~ /[Yy][Ee][Ss]/ ) {
                    $dq_drives{$field} = ${$STO_DISK_SHOW}{$FILER_C}{$field}{'Dynamically qualified'};
                }
            }
        }
        if (%dq_drives) {
            logcomment("**WARNING** : PRE_TEST : $FILER_C - One or more drives have been determined to be dynamically qualified");

            # logcomment("Drives need to be dynamically qualified are");
            # while ((my $drive, my $dq) = each %dq_drives){
            #         logcomment ("Drive is $drive and the DQ value is $dq");
            # }
        } else {
            logcomment("PRE_TEST : $FILER_C : There are NO drives to be dynamically qualified");
        }
        logcomment("$FILER_C - End of Execute storage show disk -a");
    }

    # Execute stsb get_status and scsi logsense for all disks
    if ( $parse_id !~ /_ERT_Maint/ ) {
        $Test->nlog("===================================================================================");
        $Test->nlog("==== PRE_TEST STEP 22 : Printing stsb get_status and scsi logsense data for all the disks");
        $Test->nlog("===================================================================================");
        logcomment("PRE_TEST - Getting stsb get_status info for all disks");
        $STSB_FOR_EACH_DISKS_PRE = STSB_Get_Status_Results( Node => $Nodes[0] );
        logcomment("PRE-TEST - End of stsb get_status info for all disks");
    }
    logcomment("PRE_TEST - Printing scsi logsense data of few pages for all the disks");
    scsi_logsense_pages( Node => $Nodes[0] );
    logcomment("PRE-TEST - End of scsi logsense data for all the disks");

    #Execute scsi modesense for 702,800 and 900 series
    if ( $parse_id =~ /(702|801|802|803|804|805|806|901|902|903|904)/ ) {
        logcomment("PRE_TEST - Getting scsi modesense info for all disks");
        scsi_modesense_pages( Node => $Nodes[0] );
        logcomment("PRE-TEST - End of scsi modesense data for all the disks");
    }

    # Dump All log pages
    my $stp;
    $stp = "23" if ( $parse_id !~ /_ERT_Maint/ );
    $stp = "22" if ( $parse_id =~ /_ERT_Maint/ );
    $Test->nlog("===================================================================================");
    $Test->nlog("==== PRE_TEST STEP $stp : Get log Pages for Data Analysis ");
    $Test->nlog("===================================================================================");
    my $Api_Set_Obj;
    my $dsk_typ;

    foreach my $Node (@Nodes) {
        my $FILER_C = $Node->name();
        logcomment("FILER: $FILER_C : Get log pages for Data Analysis");
        if ( $execution_state eq 'CLI' ) {
            $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
            $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
            my $disk_type = NACL::CS::StorageDisk->fetch( command_interface => $Node, requested_fields => ['type'] );
            $dsk_typ = $disk_type->type();
            logcomment("DEBUG:disk type is $dsk_typ");
        } else {
            $Api_Set_Obj = $FILER_API{$FILER_C};
            $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
            my $disk_type = disk_type_maint( Node => $Node );
            foreach my $dsk ( keys %$disk_type ) {
                $dsk_typ = $disk_type->{$dsk}->{'Type'};
                if ($dsk_typ) {
                    logcomment("DEBUG:disk type is $dsk_typ");
                    last;
                }
            }
        }
        logcomment("Drive type obtained : $dsk_typ and filer state is $execution_state ");

        #logcomment( "Get Drive attached to" . $Nodes[0]->name() . " and " . $Nodes[1]->name() );
        logcomment("Get Drive attached to $FILER_C");
        my @temp_disk_info = list_of_disk( Node => $Node );

        # my @temp_disk_info = get_disk_information( API_Obj => $Api_Set_Obj, Filer => $FILER_C );
        my $dsks = _print_array( \@temp_disk_info ) if (@temp_disk_info);

        #logcomment( "Total drives present in the filer" . $Nodes[0]->name() . " and " . $Nodes[1]->name() . " are " . scalar @temp_disk_info . " and the drives are @temp_disk_info" );
        logcomment( "Total drives present in the filer $FILER_C" . " are " . scalar @temp_disk_info . " and the drives are @temp_disk_info" );
        logcomment("$dsks");
        foreach my $drvs (@temp_disk_info) {
            next if ( $drvs =~ /P1|P2|P3/ );
            logcomment("Get log pages for Drive : $drvs");
            $Api_Set_Obj->execute_command( 'command' => "scsi logsense -p 0x02 $drvs" );
            $Api_Set_Obj->execute_command( 'command' => "scsi logsense -p 0x03 $drvs" );
            $Api_Set_Obj->execute_command( 'command' => "scsi logsense -p 0x05 $drvs" );
            $Api_Set_Obj->execute_command( 'command' => "scsi logsense -p 0x06 $drvs" );

            # $Api_Set_Obj->execute_command( 'command' => "scsi logsense -p 0x07 $drvs" ); #1079640
            $Api_Set_Obj->execute_command( 'command' => "scsi logsense -p 0x15 $drvs" );
            $Api_Set_Obj->execute_command( 'command' => "scsi logsense -p 0x18 $drvs" );
            $Api_Set_Obj->execute_command( 'command' => "scsi logsense -p 0x19 -r 0x0002 $drvs" ) if ( $drvs !~ /L1|L2/ );
            $Api_Set_Obj->execute_command( 'command' => "scsi logsense -p 0x2f $drvs" );
            $Api_Set_Obj->execute_command( 'command' => "scsi logsense -p 0x0d -s 0x01 $drvs" );
            if ( $dsk_typ =~ /SSD/ ) {
                $Api_Set_Obj->execute_command( 'command' => "scsi logsense -p 0x11 $drvs" );
                $Api_Set_Obj->execute_command( 'command' => "scsi logsense -p 0x30 $drvs" );
                $Api_Set_Obj->execute_command( 'command' => "scsi logsense -p 0x33 -s 0x09 $drvs" );
                $Api_Set_Obj->execute_command( 'command' => "scsi logsense -p 0x33 -s 0x10 $drvs" );
            }

        }
        last;    #as all drive are captured , exectuing only on one node.
    }    #End of Foreach node
    $Test->nlog("##################################################################################");
    $Test->nlog("##");
    $Test->nlog("## End of PRE_TEST logs for Filer : @Filer_array");
    $Test->nlog("##");
    $Test->nlog("##################################################################################");

    #End of pre test
}

#######################################################################################################
#Subroutine Defn Begins
###
###
# Auther         - vpankaj@netapp.com
# Description    - This subroutine is used in all the test for post test process.
# Post Functions -  check state and change to required state
#                   version
#                   disk_list
#                   sysconfig -v
#                   sysconfig -r
#                   sasadmin dev_stats
#                   storage show
#                   sasadmin expander_map
#                   vol status -s
#                   df command to display size
#                   disk_qual start -t 12 -d all
#                   check for failed and zeroing drives.
#                   Check for fan speed and set to default.
#                   Stop error injection
#                   sasadmin dev_stats
# Supported Mode -  Cmode
###
#######################################################################################################

sub execute_post_test {
    my (%opts) = validate(
        @_,
        {
            filer_mode      => { type => SCALAR },
            node_present    => { type => ARRAYREF },
            Test            => { type => OBJECT },
            change_state_to => { type => SCALAR, optional => 1, default => 'CLI' },
            LOGDIR          => { type => SCALAR, optional => 1, default => '' },
            test_setup      => { type => SCALAR, optional => 1, default => 'SAS' },
            BOOT_TYPE       => { type => SCALAR, optional => 1, default => 'A' },
        }
    );
    my @Nodes;
    if ( defined( @{ $opts{node_present} } ) ) {
        @Nodes = @{ $opts{node_present} };
    } else {
        @Nodes = NACL::C::Node->find();
    }
    handle_run_local_error( Nodes => [@Nodes] );
    my $Filer_mode  = $opts{filer_mode};
    my $Test        = $opts{Test};
    my $change_to   = $opts{change_state_to};
    my $TEST_CONFIG = $opts{test_config};
    my $test_setup  = $opts{test_setup};
    my $exit_test   = 0;
    my @Filer_array = ();
    my $execution_state;
    my @disk_list;
    my $node_ref;
    my @disk_array;
    my $result_flag = 0;
    my %FILER_API   = ();
    my @disk_array;
    my $timeout;
    my $Api_Set_Obj;
    my $disk_capacity_total = 0;
    my $LOGDIR              = $opts{LOGDIR};
    my $params              = NATE::ParamSet->new( global => 1 );
    my $EOE                 = $params->get( 'EOE', default => 'default' );
    my $EMAIL               = $params->get( 'EMAIL', default => 'y' );
    my $MAIL_TO             = $params->get( 'MAIL_TO', default => 'Email to' );
    my $MAIL_FROM           = $params->get( 'MAIL_FROM', default => 'Email from' );

    if ( $opts{LOGDIR} ) {
        $LOGDIR = $opts{LOGDIR};
    } else {
        $LOGDIR = $ENV{HOME};
    }
    my $TEST_NAME;
    opendir( DIR_LOG31, $LOGDIR );
    my @files_DIR_LOG31 = readdir(DIR_LOG31);
    foreach my $file (@files_DIR_LOG31) {
        if ( ( $file =~ /(.*_NADQ02.*)\.log/ ) && ( $file !~ /results|END_FILER_CONFIG/ ) ) {
            $TEST_NAME = $1;
        }
    }
    $node_ref = \@Nodes;
    foreach my $temp_node (@Nodes) {
        my $Filer = $temp_node->name();
        push( @Filer_array, $Filer );
    }

    # Check state of filer and Execute based on state
    logcomment("DEBUG:Nodes present - @Filer_array");
    logcomment("DEBUG:Log loction - $LOGDIR");
    my @chk_state = ();

    # Check for state and call respective subroutines:
    foreach my $Node (@Nodes) {
        my $Transit_obj;
        my $FILER_C = $Node->name();
        $Transit_obj = NACL::Transit->new( name => $FILER_C );
        my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
        $Test->nlog("$FILER_C : Filer is in $filer_state ");
        push( @chk_state, $filer_state );
    }
    my $len = @chk_state;
    if ( $len > 1 ) {
        if ( $chk_state[0] eq $chk_state[1] ) {
            $execution_state = $chk_state[0];
            $Test->nlog("Execution state - $execution_state\n");
        } else {
            $Test->nlog("States of filer is different, Boot filer in same mode");
        }
    } else {
        $execution_state = $chk_state[0];
        $Test->nlog("Execution state - $execution_state\n");
    }

    # Check filer State and change to required state
    $Test->nlog("##################################################################################");
    $Test->nlog("##");
    $Test->nlog("## Begining of POST_TEST logs for Filer : @Filer_array");
    $Test->nlog("##");
    $Test->nlog("##################################################################################");
    $Test->nlog("Checking boot state of filer, and booting in required mode");
    my $filer_state;
    my $Transit_obj;
    my @change_states;
    my $Check_flag = 0;

    foreach my $Node (@Nodes) {
        my $FILER_C     = $Node->name();
        my $Transit_obj = NACL::Transit->new( name => $FILER_C );
        my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
        logcomment("Filer $FILER_C is in $filer_state ");
        if ( $opts{change_state_to} ) {
            if ( $filer_state ne $change_to ) {
                $Test->nlog("Filer - $FILER_C is in $filer_state state");
                logcomment("Filer - $FILER_C is NOT in required state - $change_to, Changing to $change_to");
                push( @change_states, $FILER_C );
            }
            if ( $filer_state eq $change_to ) {
                $Test->nlog("Filer - $FILER_C is in $filer_state state");
                $Test->nlog("Filer - $FILER_C is in required state - $change_to");
            }
        }
    }
    my @subtests;
    if (@change_states) {
        foreach my $filer_name (@change_states) {
            push( @subtests, subtest( \&boot_filer_in_req_state, -runid, "boot_filer_in_req_state_" . "$filer_name", -bg, "--", Test => $Test, filer_name => $filer_name, change_state_to => $change_to ) );
        }
        Subtest::wait_finish( subtest => [@subtests] );
        my ( $fail_cnt, $fatal_cnt );
        my @results;
        foreach my $subtest (@subtests) {
            @results = $subtest->rslts();
            foreach my $result (@results) {
                if ( $result->type() =~ /INFO/ ) {
                    $Test->nlog("Subtest boot_filer_in_req_state completed successfully");
                } elsif ( $result->severity() >= 0 ) {
                    $Test->nlog("Subtest boot_filer_in_req_state not completed successfully");
                    if ( $result->type() =~ /FAIL/i ) {
                        $fail_cnt++;
                    }
                    if ( $result->type() =~ /FATAL|SCRIPT|CONFIG/ ) {
                        $fatal_cnt++;
                    }
                } ## end elsif ($result->severity(...
            } ## end foreach my $result (@results)
        } ## end foreach my $subtest (@subtests)
        if ( $fail_cnt == 0 ) {
            $Test->nlog("FILER Booted the filer successfully in required state");
            $Check_flag = 1;
        }
    }

    # Check state of filer after booting
    if ( $Check_flag == 1 ) {
        foreach my $Node (@Nodes) {
            my $Transit_obj;
            my $FILER_C = $Node->name();
            $Transit_obj = NACL::Transit->new( name => $FILER_C );
            my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
            $Test->nlog("$FILER_C : Filer is in $filer_state ");
            if ( "$filer_state" eq "$change_to" ) {
                $Test->nlog("$FILER_C : Is in required test, proceeding with test");
                $execution_state = $filer_state;
                $Test->nlog("$FILER_C : Execution state changed to : $change_to");
            }
            if ( "$filer_state" ne "$change_to" ) {
                logcomment("**FATAL** : $FILER_C is NOT in required state, CANNOT boot in required state");
                logresult( "FATAL", "$FILER_C IS NOT IN REQUIRED STATE, CANNOT BOOT IN REQUIRED STATE" );
            }
        }
    }

    # If maintenanace mode :
    if ( $execution_state eq 'MAINT' ) {
        foreach my $Node (@Nodes) {
            my $Filer      = $Node->name();
            my $host       = host($Filer);
            my $API_Object = NACL::APISet->new(
                hostobj   => $host,
                category  => "Node",
                interface => "CLI",
                set       => "Maintenance"
            );
            $FILER_API{$Filer} = $API_Object;
        }
    }

    # Check security login, ssh option
    $Test->nlog("===================================================================================");
    $Test->nlog("==== POST_TEST STEP 1 : Check SSH connection in post test");
    $Test->nlog("===================================================================================");
    foreach my $Node (@Nodes) {
        my $FILER_C = $Node->name();
        logcomment("$FILER_C - Checking SSH parameters");
        if ( $execution_state eq 'CLI' ) {
            $Test->nlog("$FILER_C : Check security login, enable ssh option ");
            $Test->nlog("$FILER_C : Filer mode is : $Filer_mode");
            enable_ssh( Node => $Node, Test => $Test, Mode => $Filer_mode );
            $Test->nlog("$FILER_C : Disable all storage debug messages");
            my $host = host($FILER_C);
            disable_debug_msg( Node => $Node );
        } else {
            logcomment("Filer $FILER_C is in Maintenance mode, ssh is NOT used in Maintenance mode");
        }
        logcomment("$FILER_C - End of Checking SSH");
    }

    # Checking Kernel version
    $Test->nlog("===================================================================================");
    $Test->nlog("==== POST_TEST STEP 2 : Record version of Kernel used in Post test");
    $Test->nlog("===================================================================================");
    foreach my $Node (@Nodes) {
        my $FILER_C = $Node->name();
        logcomment("$FILER_C - Checking Kernel version on filers");
        if ( $execution_state eq 'CLI' ) {
            $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
        } else {
            $Api_Set_Obj = $FILER_API{$FILER_C};
        }
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
        my $ver_output = $Api_Set_Obj->execute_command( 'command' => 'version' );
        logcomment("Version on $FILER_C - $ver_output");
        logcomment("End of Checking kernel version");
    }
    $Test->nlog("===================================================================================");
    $Test->nlog("==== POST_TEST STEP 3 : Copying the system logs to the filer");
    $Test->nlog("===================================================================================");
    foreach my $Node (@Nodes) {
        my $num;
        my $FILER_C     = $Node->name();
        my $Transit_obj = NACL::Transit->new( name => $FILER_C );
        my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
        if ( $filer_state =~ /MAINT/gi ) {
            logcomment("Filer is in $filer_state state. System logs will NOT be generated");
            last;
        } elsif ( $filer_state =~ /CLI/gi ) {
            my $params = NATE::ParamSet->new( global => 1 );
            my $LOGDIR = $params->get( 'LOGDIR', default => undef );
            my ($actual_log_dir) = $LOGDIR =~ /(\S+)\/HDD/;
            if ( $parse_id =~ /(\d+)\_\S+/ ) {    #aditis: 861147
                $num = $1;
            }
            my $log_dir = "$actual_log_dir\/SYSTEM_LOGS\/" . $FILER_C;    #blessy: 861147
            if ( !( -d "$log_dir" ) ) {
                system("sudo mkdir -p $log_dir");
            }

            #            my $log_dir = "$actual_log_dir\/SYSTEM_LOGS\/" . $parse_id . "_" . $FILER_C;
            get_system_logs( Node => $Node, logdir => $log_dir );
            logcomment("$FILER_C : System logs copied to the directory : $log_dir");
        }
    }

    #check for disk availibility (pre test)
    $Test->nlog("===================================================================================");
    $Test->nlog("==== POST_TEST STEP 4 : Checking for disk availability");
    $Test->nlog("===================================================================================");
    {
        my ( $max_disk_size, $disk_size );
        my @disk_list_common;
        logcomment("Checking Disk Availability");
        if ( $execution_state eq 'CLI' ) {
            @disk_list_common = NACL::C::StorageDisk->find( command_interface => $Nodes[0] );
            @disk_list;
            foreach my $disk (@disk_list_common) {
                push( @disk_list, $disk->get_one_state_attribute('disk') );
            }
            my $disk_length = @disk_list;
            @post_disk_count = @disk_list;
            if ( $disk_length > 0 ) {
                $Test->nlog("@Filer_array - Disk attached - @disk_list");
            } else {
                $Test->nlog("@Filer_array -No disk available for testing, exiting from rest of the test cases");
                $exit_test = 1;
                logcomment("**FATAL** : @Filer_array - NO DISK AVAILABLE For testing,  exiting from rest of the test cases");
                logresult( "FATAL", "@Filer_array - NO DISK AVAILABLE FOR TESTING,  exiting from rest of the test cases" );
            }
        } else {
            my $FILER_C     = $Nodes[0]->name();
            my $Api_Set_Obj = $FILER_API{$FILER_C};
            $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
            logcomment("DEBUG:Filer : $FILER_C : Executing disk_list on the filer");
            my $dsk_output       = $Api_Set_Obj->execute_raw_command( 'command' => "disk_list" );
            my $disk_list_result = {};
            my @lines            = split( /\n/, $dsk_output );
            my $n                = 0;

            while ( $n <= $#lines ) {
                last if ( $lines[$n] =~ /^-----/ );
                $n++;
            }
            $n++;
            foreach my $line ( @lines[ $n .. $#lines ] ) {
                my ( $disk, $chan, $ven, $prodid, $rev, $serialno, $hw, $blocks, $bps, $dq ) = ( $line =~ /(\d\w.\d+\.\d+L?P?\d?)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)/ );
                if ( ( $line =~ /\d\w\.\d\d/ ) || ( $line =~ /\d\w\.\d\d\.\d\dL?P?\d?/ ) || ( $line =~ /\d\w\.\d\d\.\d\dL?P?\d+?/ ) ) {
                    $disk_list_result->{$disk} = {
                        'DISK'       => $disk,
                        'CHAN'       => $chan,
                        'VENDOR'     => $ven,
                        'PRODUCT_ID' => $prodid,
                        'REV'        => $rev,
                        'SERIAL'     => $serialno,
                        'HW'         => $hw,
                        'BLOCKS'     => $blocks,
                        'BPS'        => $bps,
                        'DQ'         => $dq
                    };
                }
            }
            @disk_array = keys( %{$disk_list_result} );
            my $disk_length = @disk_array;
            @post_disk_count = @disk_array;
            if ( $disk_length > 0 ) {
                $Test->nlog(" Disk attached - @disk_array");
            } else {
                logcomment("**FATAL** : NO DISK AVAILABLE for testing, exiting from rest of the test cases");
                logresult( "FATAL", "NO DISK AVAILABLE FOR TESTING,  exiting from rest of the test cases" );
            }
            for my $dsk (@disk_array) {
                $disk_size           = $disk_list_result->{$dsk}->{'BLOCKS'};
                $max_disk_size       = $disk_size if ( $disk_size > $max_disk_size );
                $disk_capacity_total = $disk_capacity_total + $disk_size;
            }
            my ($string) = readable_disk_size( Blocks => $disk_capacity_total );
            logcomment("System capacity is $string");
            my ($string) = readable_disk_size( Blocks => $max_disk_size );
            logcomment("Maximum disk size is $string");
            if ( $max_disk_size <= 20971520 ) {
                $timeout = $timeout + 1200;
            } elsif ( $max_disk_size <= 2147483648 ) {
                $timeout = $timeout + ( 1200 * 5 );
            } else {
                $timeout = $timeout + ( 1200 * 10 );
            }
        }
        if ( scalar @pre_disk_count != scalar @post_disk_count ) {
            my @Pre_drv  = ();
            my @Post_drv = ();
            grep {
                if ( $_ =~ /\w+\.(\w+\.\w+)/ ) { push( @Pre_drv, $1 ) }
            } @pre_disk_count;
            grep {
                if ( $_ =~ /\w+\.(\w+\.\w+)/ ) { push( @Post_drv, $1 ) }
            } @post_disk_count;
            my @diff = difference( [ sort @Pre_drv ], [ sort @Post_drv ] );
            push( @diff, difference( [ sort @Post_drv ], [ sort @Pre_drv ] ) );
            logcomment( "**FAIL** :Disk device @diff was NOT found during  post test( PRE = " . scalar @pre_disk_count . " disks and POST = " . scalar @post_disk_count . " disks )" );
            logresult( 'FATAL', "DISK DEVICE @diff WAS NOT FOUND DURING  POST TEST( PRE = " . scalar @pre_disk_count . " disks and POST = " . scalar @post_disk_count . " disks )" );
        }
        logcomment("End of checking Disk Availability");
        foreach my $Node (@Nodes) {
            my $FILER_C        = $Node->name();
            my @temp_disk_info = list_of_disk( Node => $Node );
            my $dsks           = _print_array( \@temp_disk_info ) if (@temp_disk_info);
            logcomment( "Total drives present in the filer $FILER_C" . "are " . scalar @temp_disk_info . " and the drives are @temp_disk_info" );
            logcomment("$FILER_C : Checking if Rebuild Assist is disabled on drives");
            foreach my $drvs (@temp_disk_info) {
                next if ( $drvs =~ /P1|P2|P3/ );
                if ( $execution_state eq 'CLI' ) {
                    $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
                } else {
                    $Api_Set_Obj = $FILER_API{$FILER_C};
                }
                $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
                if ( $execution_state eq 'CLI' ) {
                    my $output = $Api_Set_Obj->execute_command( 'command' => "scsi rebuild_assist -c $drvs" );
                    if ( $output =~ /Rebuild Assist is enabled/i ) {
                        logcomment("Rebuild Assist is enabled on drive $drvs, disabling it");
                        $Api_Set_Obj->execute_command( 'command' => "scsi rebuild_assist -d $drvs" );
                    }
                } else {
                    my $output = $Api_Set_Obj->execute_raw_command( 'command' => "scsi rebuild_assist -c $drvs" );
                    if ( $output =~ /Rebuild Assist is enabled/i ) {
                        logcomment("Rebuild Assist is enabled on drive $drvs, disabling it");
                        $Api_Set_Obj->execute_raw_command( 'command' => "scsi rebuild_assist -d $drvs" );
                    }
                }
            }
        }
    }

    # Get filer config
    $Test->nlog("===================================================================================");
    $Test->nlog("==== POST_TEST STEP 5 : Get Filer configurations");
    $Test->nlog("===================================================================================");
    foreach my $Node (@Nodes) {
        my %comments;
        my %config_1;
        my $flag     = 0;
        my $cnt_fw   = 1;
        my $cnt_size = 1;
        my @models;
        my @arr1 = ();
        my $output;
        my $FILER_C = $Node->name();
        logcomment("Get filer configruation for filer $FILER_C");

        if ( $execution_state eq 'CLI' ) {
            $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
            $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
            $output = $Api_Set_Obj->execute_command( 'command' => 'sysconfig -v', 'timeout' => 600 );
        } else {
            $Api_Set_Obj = $FILER_API{$FILER_C};
            $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
            $output = $Api_Set_Obj->execute_command( 'command' => 'sysconfig -v', 'timeout' => 600 );
        }
        @arr1 = split( /\n/, $output );
        foreach my $line (@arr1) {
            if ( $line =~ /ID\s+Vendor\s+Model\s+FW\s+Size/ig ) { $flag = 1; }
            if ( ( $line =~ /(\d+\.\w+)\s*\:\s*\S+\s*(\S+)\s*(\S+)\s*(\S+)\s*/ ) && ( $flag == 1 ) ) {
                my $drive = $1;
                my $model = $2;
                my $fw    = $3;
                my $size  = $4;
                $Non_Medium_Model{$drive} = $model;
                push( @models,                            $model ) unless grep { $_ eq $model } @models;
                push( @{ $config_1{$model}{$fw}{$size} }, $drive ) unless grep { $_ == $drive } @{ $config_1{$model}{$fw}{$size} };
                my @key_Size = keys( %{ $config_1{$model}{$fw} } );
                my @key_fw   = keys( %{ $config_1{$model} } );

                if ( scalar @key_fw > $cnt_fw ) {
                    $comments{$model}{'fw'} = "**WARNING** : Model $model is having drives with different Firmware version : @key_fw\n";
                    $cnt_fw++;
                } elsif ( scalar @key_Size > $cnt_size ) {
                    $comments{$model}{'sz'} = "**WARNING** : Model $model is having drives with different Capacity : @key_Size\n";
                    $cnt_size++;
                }
            }
        }
        foreach my $mod (@models) {
            logcomment("$comments{$mod}{'fw'}") if ( defined $comments{$mod}{'fw'} );
            logcomment("$comments{$mod}{'sz'}") if ( defined $comments{$mod}{'sz'} );

        }
        logcomment("End of Get filer configruation for filer $FILER_C");
    }

    # Execution sysconfig -r
    $Test->nlog("===================================================================================");
    $Test->nlog("==== POST_TEST STEP 6 :Record sysconfig -r information of the filer");
    $Test->nlog("===================================================================================");
    if ( $execution_state eq 'CLI' ) {
        my @subtests;
        $pre_post_recon_copy = "post";
        foreach my $Node (@Nodes) {
            my $FILER_C = $Node->name();
            push( @subtests, subtest( \&check_recons_sickdisk, -runid, "check_recons_sickdisk_$FILER_C", -bg, "--", Node => $Node ) );
        }
        Subtest::wait_finish( subtest => [@subtests] );
        status_return( subtest_ref => [@subtests] );
    } else {
        logcomment("Filer is in Maintenance mode, command \"sysconfig -r\" is NOT supported");
    }

    # Record link statistics for all adapters and drives
    $Test->nlog("===================================================================================");
    $Test->nlog("==== POST_TEST STEP 7 : Record link statistics for all adapters and drives");
    $Test->nlog("===================================================================================");
    foreach my $Node (@Nodes) {
        my $FILER_C = $Node->name();
        my $Host    = host($FILER_C);
        logcomment("$FILER_C - Record link statistics");
        if ( !( defined $SAS_ADMIN_DEV_PRE->{$FILER_C} ) ) {
            logcomment("**WARNING** : $FILER_C : Link statistics are not recorded properly in PRE-TEST process");
            next;
        }
        if ( $test_setup ne 'FC' ) {
            my $after = sasadmin_dev_stats_cmode( node => $Node );
            if ( compare_sasadmin_dev_stats( initial_stats => $SAS_ADMIN_DEV_PRE->{$FILER_C}, final_stats => $after ) == 1 ) {
                logcomment("$FILER_C : link statistics values are same when compared from PRE to POST test process");
            } else {
                logcomment("$FILER_C : Link statistics values are DIFFERENT when compared from pre to post test process");
            }
        } else {
            my $after = fcadmin_fcal_stats( Node => $Node );
            if ( compare_fcadmin_fcal_stats( fcadmin_fclstats_add_before => $SAS_ADMIN_DEV_PRE->{$FILER_C}, fcadmin_fclstats_add_after => $after ) == 1 ) {
                logcomment("$FILER_C : link statistics values are same when compared from PRE to POST test process");
            } else {
                logcomment("$FILER_C : link statistics values are NOT same when compared from PRE to POST test process");
            }
        }
        logcomment("$FILER_C - End of recording link stats");
    }

    # Storage show information of the filer
    $Test->nlog("===================================================================================");
    $Test->nlog("==== POST_TEST STEP 8 : Record storage show information of the filer");
    $Test->nlog("===================================================================================");
    foreach my $Node (@Nodes) {
        my $FILER_C = $Node->name();
        logcomment("DEBUG:$FILER_C - Executing storage show");
        if ( $execution_state eq 'CLI' ) {
            $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
            $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
            $Api_Set_Obj->execute_command( 'command' => 'storage show', 'timeout' => 600 );
        } else {
            $Api_Set_Obj = $FILER_API{$FILER_C};
            $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
            $Api_Set_Obj->execute_command( 'command' => 'storage show', 'timeout' => 600 );
        }
        logcomment("End of $FILER_C - Executing storage show");
    }

    # Record expander map of the adapter
    $Test->nlog("===================================================================================");
    $Test->nlog("==== POST_TEST STEP 9  : Record expander map of the adapter");
    $Test->nlog("===================================================================================");
    foreach my $Node (@Nodes) {
        my $FILER_C = $Node->name();
        my $Host    = host($FILER_C);
        logcomment("$FILER_C - Record expander map of the adapter");
        if ( $test_setup ne 'FC' ) {
            sasadmin_expander_map_cmode( node => $Node );
        } else {
            fcadmin_device_map( Node => $Node );
        }
        logcomment("$FILER_C - End of recording expander map");
    }

    # Record Spare drives
    $Test->nlog("===================================================================================");
    $Test->nlog("==== POST_TEST STEP 10  : Record Spare drives attached");
    $Test->nlog("===================================================================================");
    foreach my $Node (@Nodes) {
        my $FILER_C = $Node->name();
        logcomment("Record Spare drives attached");
        if ( $execution_state eq 'CLI' ) {
            $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
            $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
            $Api_Set_Obj->execute_command( 'command' => 'vol status -s' );
        } else {
            logcomment("Spare drive check is NOT required since the filer is in Maintenance mode");
        }
        logcomment("End of recording spare drives");
    }

    # Record df command to display size
    $Test->nlog("===================================================================================");
    $Test->nlog("==== POST_TEST STEP 11 : Record df command to display size");
    $Test->nlog("===================================================================================");
    foreach my $Node (@Nodes) {
        my $FILER_C = $Node->name();
        logcomment("$FILER_C - Record df command to display size");
        if ( $execution_state eq 'CLI' ) {
            $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
            $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
            $Api_Set_Obj->execute_command( 'command' => 'df' );
        } else {
            logcomment("Filer $FILER_C is in Maintenance, Hence printing disk capacity size");
            my ($string) = readable_disk_size( Blocks => $disk_capacity_total );
            logcomment("DEBUG : System capacity is $string");
        }
        logcomment("End of recording df command to display size");
    }
    $Test->nlog("===================================================================================");
    $Test->nlog("==== POST_TEST STEP 12 : Set log sense interval");
    $Test->nlog("===================================================================================");
    foreach my $Node (@Nodes) {
        my $FILER_C = $Node->name();
        logcomment("DEBUG: $FILER_C - Set log sense interval");
        if ( $execution_state eq 'CLI' ) {
            $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
            $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
            logcomment("DEBUG:$FILER_C -Set options disk.log_sense.interval for 40 minutes");
            NACL::C::Options->option(
                command_interface => $Node,
                'option-name'     => 'disk.log_sense.interval',
                'option-value'    => '4'
            );
            logcomment("DEBUG:Filer - Waiting for 6 minute");
            sleep(360);
            NACL::C::Options->option(
                command_interface => $Node,
                'option-name'     => 'disk.log_sense.interval',
                'option-value'    => '40'
            );
            logcomment("DEBUG:Filer - Waiting for a minute");
            sleep(60);
        } else {
            $Api_Set_Obj = $FILER_API{$FILER_C};
            $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
            logcomment("$FILER_C : NO need to set log sense interval to 4 hrs for Maintenance mode");
        }
        logcomment("$FILER_C - End of setting log sense interval");
    }

    # Execute disk_qual t 12 for all disk
    $Test->nlog("===================================================================================");
    $Test->nlog("==== POST_TEST STEP 13 : Printing logsense data for all the disks");
    $Test->nlog("===================================================================================");
    foreach my $Node (@Nodes) {
        my $FILER_C = $Node->name();
        logcomment("$FILER_C - Print logsense data for all the disks");
        my $after = scsi_disk_errors( Node => $Node, Flag_Pre => 0 );
        my $Transit_obj = NACL::Transit->new( name => $FILER_C );
        my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
        logcomment("DEBUG:Filer state is :$filer_state");
        if ( ( defined $SCSI_DISK_ERRORS->{$FILER_C} ) && ( defined $after ) ) {
            if ( ( $SCSI_DISK_ERRORS->{$FILER_C} == 1 ) || ( $after == 1 ) ) {
                logcomment("The kernel present is non-debug. command scsi disk_errors will NOT execute");
            } else {
                if ( $filer_state =~ /MAINT/ ) {
                    my $return = get_phy_state( Node => $Node );

                    #---------------------BURT1025104---------------------#
                    my $res = compare_disk_qual_t12( disk_qual_t12_before => $SCSI_DISK_ERRORS->{$FILER_C}, disk_qual_t12_after => $after, nm_error => 'n', logdir => $LOGDIR, Phy_count => $return );
                    if ( $res == 0 ) {
                        logcomment(" $FILER_C - Log Sense information are different from PRE to POST test process");
                    } elsif ( $res == 1 ) {
                        logcomment(" $FILER_C Log Sense information are identical from PRE to POST test process");
                    }

                    #-----------------------------------------------------#
                } else {
                    if ( compare_scsi_disk_errors( before => $SCSI_DISK_ERRORS->{$FILER_C}, after => $after, Node => $Node ) == 1 ) {
                        logcomment("Ssci disk error values are DIFFERENT from PRE to POST test process");
                    } else {
                        logcomment("Ssci disk error values are matching from PRE to POST test process");
                    }
                }
            }
        } else {
            logcomment("**WARNING** : $FILER_C : logsense data for all the disks was NOT executed properly either in PRE-TEST|POST-TEST process");
            next;
        }

=head
                if(!(defined  $SCSI_DISK_ERRORS->{$FILER_C})){
                    logcomment("**WARNING** : $FILER_C : LOGSENSE DATA FOR ALL THE DISKS WAS NOT EXECUTED PROPERLY IN PRE-TEST process");
                    next;
                }
                if($filer_state =~ /MAINT/){
                    if(compare_disk_qual_t12(disk_qual_t12_before => $SCSI_DISK_ERRORS->{$FILER_C}, disk_qual_t12_after  => $after, nm_error  => 'n')==0){
                        logcomment(" $FILER_C - LOG SENSE INFORMATION ARE DIFFERENT FROM PRE TO POST TEST PROCESS" );
                    } else {
                        logcomment("For $FILER_C Log Sense information are identical from PRE to POST test process " );
                    }
               }else{
                    if(compare_scsi_disk_errors(before =>$SCSI_DISK_ERRORS->{$FILER_C},after =>$after)==1){
                        logcomment("SCSI DISK ERROR VALUES ARE DIFFERENT from PRE to POST test process");
                    }else{
                        logcomment("Scsi disk error values are matching from PRE to POST test process");
                    }
                }
=cut

    }
    logcomment("End of Printing logsense data for all the disks");

    #check for failed and zeroing drives
    $Test->nlog("===================================================================================");
    $Test->nlog("==== POST_TEST STEP 14 : Check for non-zeroed disk or failed disk, unfail disk");
    $Test->nlog("===================================================================================");
    if ( $execution_state =~ /CLI|UP|MAINT/ ) {    #BURT1041406 - abalaji
        disable_fg_bg_firmware_hammer( Nodes => [@Nodes] ) if ( $execution_state =~ /CLI|UP/ );    #BURT1041406 - abalaji
        {
            my @subtests;
            foreach my $Node (@Nodes) {
                my $FILER_C = $Node->name();
                push( @subtests, subtest( \&report_failed_drives, -runid, "report_failed_drives_" . "$FILER_C", -bg, "--", Node => $Node ) );
            }
            Subtest::wait_finish( subtest => [@subtests] );
        }
        unfail_disk_zero_spares( Nodes => [@Nodes] ) if ( $execution_state =~ /CLI|UP/ );          #BURT1041406 - abalaji
        logcomment("End of checking for non-zeroed disk or failed disk, unfail disk");
    } else {
        logcomment("as the filer is in $execution_state state, check for non-zeroed disk or failed disk could NOT be performed");    #BURT1041406 - abalaji
    }

    # Check for fan speed (pre)
    $Test->nlog("===================================================================================");
    $Test->nlog("==== POST_TEST STEP 15 : Making changes for fan speed if test setup is SAS");
    $Test->nlog("===================================================================================");
    foreach my $Node (@Nodes) {
        my $FILER_C = $Node->name();
        if ( $test_setup eq "SAS" ) {
            my $sysconfig_out;
            logcomment("$FILER_C - Checking for fan speed");
            if ( $execution_state eq 'CLI' ) {
                $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
            } else {
                $Api_Set_Obj = $FILER_API{$FILER_C};
            }
            $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
            if ( $execution_state =~ /CLI|UP/i ) {
                logcomment("Executing sysconfig -v for checking platform");
                $sysconfig_out = $Api_Set_Obj->execute_command( 'command' => 'sysconfig -v', 'timeout' => 600 );
            } elsif ( $execution_state =~ /MAINT/ ) {
                logcomment("Executing sysconfig -v for checking platform");
                $sysconfig_out = $Api_Set_Obj->execute_raw_command( 'command' => 'sysconfig -v' );
            }

            chomp( my @sysconf_lines = split( /\r?\n/, $sysconfig_out ) );
            my $shelf_id;
            foreach my $line (@sysconf_lines) {
                if ( $line =~ /Shelf\s*\d*:\s*(\S+)\s+Firmware rev/ ) {
                    $shelf_id = $1;
                }
            }
            if ( ( $shelf_id =~ /DS46012/i ) && ( $execution_state =~ /CLI|UP/i ) ) {
                logcomment("Platform: Trafford(Shelf ID:$shelf_id)");
                my $adapters    = {};
                my @expanders_r = ();
                $adapters = shelf_id_trafford( Node => $Node );
                @expanders_r = keys %$adapters;
                foreach my $var (@expanders_r) {
                    my $aft = $Api_Set_Obj->execute_command( 'command' => "sasadmin expander_cli $var 'fan_set normal'" );
                    if ( $aft =~ /Setting all fans to normal/ ) {
                        sleep(60);
                        logcomment("Fan-speed has set to default value");
                        logcomment("Checking the Fans speed again");
                        $Api_Set_Obj->execute_command( 'command' => "sasadmin expander_cli $var 'fan_set speed'" );
                        sleep 5;
                    }
                }
            } else {
                my $adapterslot;
                my ( $shelfid, $adapter_val );
                my %adapter_hash;
                my $flag1      = 0;
                my $output     = $Api_Set_Obj->execute_command( 'command' => 'sasadmin expander_map' );
                my @slot_array = split( /\n\n/, $output );
                foreach (@slot_array) {
                    my @shelfid;
                    if ( $_ =~ /Expanders on channel\s+(\w+)/ ) {
                        $adapterslot = $1;
                    }
                    if ( $_ =~ /.*\s+ID\s+(\d+)/ ) {
                        @shelfid = $_ =~ /.*\s+ID\s+(\d+)/g;
                    }
                    if ( ( $adapterslot ne "" ) && (@shelfid) ) {
                        $adapter_hash{$adapterslot} = [@shelfid];
                    }
                }

                #Setting the fan Speeds to default values
                my $flag1 = 0;
                foreach my $key ( keys %adapter_hash ) {
                    last if ( $flag1 == 1 );
                    my @var = @{ $adapter_hash{$key} } if ( defined $adapter_hash{$key} );
                    foreach (@var) {
                        $adapter_val = "$key.$_";
                        my $aft = $Api_Set_Obj->execute_command( 'command' => "sasadmin expander_cli $adapter_val 'fan_set normal'" );
                        if ( $aft =~ /Setting all fans to normal/ ) {
                            sleep(60);
                            logcomment("Fan-speed has set to default value");
                            logcomment("Checking the Fans speed again");
                            $Api_Set_Obj->execute_command( 'command' => "sasadmin expander_cli $adapter_val 'fan_set speed'" );
                            sleep 5;
                            $flag1 = 1;
                            last;
                        }
                    }
                }
            }
            logcomment("End of Checking for fan speed");
        } else {
            logcomment("$FILER_C - Filer is NOT of SAS type , hence NOT checking for fan speed");
        }
    }    #End of foreach nodeselse

    # Stop any error injection if running (pre-cli)
    $Test->nlog("===================================================================================");
    $Test->nlog("==== POST_TEST STEP 16 : Stop any error injection if running ");
    $Test->nlog("===================================================================================");
    foreach my $Node (@Nodes) {
        my $FILER_C = $Node->name();
        logcomment("$FILER_C - Stop any error injection");
        if ( $execution_state eq 'CLI' ) {
            $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
            $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
            my $kernel;
            $kernel = $Api_Set_Obj->execute_raw_command( command => "run local version" );
            if ( $kernel !~ /<1d>/ ) {
                logcomment("The kernel present is non debug. Error injections CANNOT be disabled");
            } else {
                if ( $test_setup ne 'FC' ) {
                    $Api_Set_Obj->execute_command( 'command' => 'sasadmin inject disable' );
                } else {
                    $Api_Set_Obj->execute_command( 'command' => 'fcadmin inject disable' );
                }
            }
        } else {
            $Api_Set_Obj = $FILER_API{$FILER_C};
            $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
            my $kernel;
            $kernel = $Api_Set_Obj->execute_raw_command( command => "version" );
            if ( $kernel !~ /<1d>/ ) {
                logcomment("The kernel present is non debug. Error injections CANNOT be disabled");
            } else {
                if ( $test_setup ne 'FC' ) {
                    $Api_Set_Obj->execute_command( 'command' => 'sasadmin inject disable' );
                } else {
                    $Api_Set_Obj->execute_command( 'command' => 'fcadmin inject disable' );
                }
            }
        }
        logcomment("End of Stopping any error injection");
    }

    # Execute sasadmin dev_stats
    $Test->nlog("===================================================================================");
    $Test->nlog("==== POST_TEST STEP 17 : Execute sasadmin get_phy_state");
    $Test->nlog("===================================================================================");
    foreach my $Node (@Nodes) {
        my $FILER_C = $Node->name();
        if ( $test_setup ne 'FC' ) {
            logcomment("$FILER_C - Execute sasadmin expander_phy_state");
            my $return = get_phy_state( Node => $Node );
            logcomment("$FILER_C - End of Execute sasadmin get_phy_state");
            if ( !( defined $GET_PHY_STATE->{$FILER_C} ) ) {
                logcomment("**WARNING** : $FILER_C : sasadmin get_phy_state command was NOT executed properly in PRE-TEST process");
                next;
            }
            if ( compare_phy_state( before => $GET_PHY_STATE->{$FILER_C}, after => $return, Node => $Node ) =~ /true|1/ ) {    #disk_ref=>[@drives_disk_show_a])
                logcomment("$FILER_C : sasadmin get_phy_state values are matching from PRE to POST test process");
            } else {
                logcomment("$FILER_C : sasadmin get_phy_state values  are NOT MATCHING from PRE to POST test process");
            }
        } else {
            logcomment("NOT checking for FC");
        }
    }
    $Test->nlog("===================================================================================");
    $Test->nlog("==== POST_TEST STEP 18 : Executing command to get details of each disk");
    $Test->nlog("===================================================================================");
    foreach my $Node (@Nodes) {
        my $FILER_C = $Node->name();
        logcomment("DEBUG:$FILER_C - Execute storage show disk -a ");
        if ( $execution_state eq 'CLI' ) {
            $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
        } else {
            $Api_Set_Obj = $FILER_API{$FILER_C};
        }
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
        $post_storage_show_drive->{$FILER_C} = storage_show_drive( API_OBJ => $Api_Set_Obj, Node => $Node );
        $result_flag = compare_storage_show_drive(
            pre_storage_show_drive  => $pre_storage_show_drive->{$FILER_C},
            post_storage_show_drive => $post_storage_show_drive->{$FILER_C},

            #                            disk_list                => [@disk_list],
            Test => $Test,
            Node => $Node
        );

        #my $result = scsi_inquiry_cmode(API_OBJ=> $Api_Set_Obj,Node=> $Node);
        #if ($result == 0) {
        #	logcomment("storage show completed for all disks");
        #}
    }
    $Test->nlog("===================================================================================");
    $Test->nlog("==== POST_TEST STEP 19 : Execute storage show disk -a");
    $Test->nlog("===================================================================================");
    foreach my $Node (@Nodes) {
        my $FILER_C = $Node->name();
        logcomment("DEBUG:$FILER_C - Execute storage show disk -a");
        logcomment("POST_TEST : $FILER_C - Checking for Dynamic Qualification of the drives");
        my $return = storage_show_disk_a_data( Node => $Node );
        if ( !( defined $STO_DISK_SHOW->{$FILER_C} ) ) {
            logcomment("**WARNING** : $FILER_C : storage show disk -a command was NOT executed properly in PRE-TEST process");
            next;
        }
        if ( compare_WWN( before => $STO_DISK_SHOW->{$FILER_C}, after => $return ) ) {
            logcomment("$FILER_C : WWN values are matching from PRE to POST test process");
        } else {
            logcomment("$FILER_C : WWN values are DIFFERENT from PRE to POST TEST process");
        }
        my @sto_disk_show_fields = keys $return;
        my %dq_drives;
        foreach my $field (@sto_disk_show_fields) {
            if ( $field =~ /\w+\.\S+/ ) {
                if ( ${$return}{$field}{'Dynamically qualified'} =~ /[Yy][Ee][Ss]/ ) {
                    $dq_drives{$field} = ${$return}{$field}{'Dynamically qualified'};
                }
            }
        }
        if (%dq_drives) {
            logcomment("**WARNING** : POST_TEST : $FILER_C - One or more drives have been determined to be dynamically qualified ");

            #while ((my $drive, my $dq) = each %dq_drives){
            #        logcomment ("Drive is $drive and the DQ value is $dq");
            #}
        } else {
            logcomment("POST_TEST : $FILER_C : There are NO drives to be dynamically qualified");
        }
        logcomment("$FILER_C - End of Execute storage show disk -a");
        last;
    }
    my @subtests;
    @Nodes = node_new_obj( node_array => [@Nodes] );
    foreach my $Node (@Nodes) {
        my $FILER_C = $Node->name();
        if ( $parse_id !~ /CF_To_Gb/ ) {
            push( @subtests, subtest( \&read_ems_logs, -runid, "read_ems_logs_$FILER_C", -bg, "--", Node => $Node ) );

            #push(@subtests,    subtest(\&read_shelflog, -runid, "read_shelflog_$FILER_C", -bg,"--", Node =>$Node));
        } else {
            logcomment("Event log Dectector stopped when filer rebooted, EMS logs will be copied with system logs");
        }
    }
    Subtest::wait_finish( subtest => [@subtests] );

    # Subtest::wait_finish(subtest => [@subtests]);
    # Execute stsb get_status and scsi logsense for all disks
    if ( $parse_id !~ /_ERT_Maint/ ) {
        $Test->nlog("===================================================================================");
        $Test->nlog("==== POST_TEST STEP 20: Printing and comparing stsb get_status data and printing scsi logsense for all the disks");
        $Test->nlog("===================================================================================");
        logcomment("POST_TEST - Printing stsb get_status data for all the disks");
        my $after = STSB_Get_Status_Results( Node => $Nodes[0] );
        if ( ( defined $STSB_FOR_EACH_DISKS_PRE ) ) {
            if ( $STSB_FOR_EACH_DISKS_PRE == 1 ) {
                logcomment("stsb get_status data will NOT be compared as this is applicable only for SATA drives");
            } else {
                if ( compare_stsb_get_status_disk_values( Node => $Nodes[0], before => $STSB_FOR_EACH_DISKS_PRE, after => $after ) == 1 ) {

                    #logcomment("**WARNING** : some of the stsb get_status values are DIFFERENT from PRE to POST test process");
                } else {
                    logcomment("stsb get_status values are matching from PRE to POST test process");
                }
            }
        } else {
            logcomment("**WARNING** : STSB : stsb get_status data for all the disks was NOT executed properly in PRE-TEST process");
        }
        logcomment("End of stsb get_status data for all the disks");
    }
    logcomment("POST_TEST - Printing scsi logsense data of few pages for all the disks");
    scsi_logsense_pages( Node => $Nodes[0] );

    #Execute scsi modesense for 702,800 and 900 series
    if ( $parse_id =~ /(702|801|802|803|804|805|806|901|902|903|904)/ ) {
        logcomment("POST_TEST - Getting scsi modesense info for all disks");
        scsi_modesense_pages( Node => $Nodes[0] );
        logcomment("POST-TEST - End of scsi modesense data for all the disks");
    }
    foreach my $Node (@Nodes) {
        my $FILER_C = $Node->name();
        logcomment("POST_TEST - Writing Crash dump and event log of BSAS or MSATA drives if present");
        my $Transit_obj = NACL::Transit->new( name => $FILER_C );
        my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
        if ( $filer_state =~ /MAINT/gi ) {
            logcomment("Filer is in $filer_state State. Skipping get_event_log and get_crash_dump as filer is NOT in file system mode");
            last;
        } elsif ( $filer_state =~ /CLI/gi ) {
            stsb_event_crash_log( Node => $Node );
        }
    }
    logcomment("POST-TEST - End of Writing Crash dump and event log of BSAS or MSATA drives");

    # Get log pages for all drives
    logcomment("Get log pages for all drives");
    $Test->nlog("===================================================================================");
    $Test->nlog("==== POST_TEST STEP 21 : Get log Pages for Data Analysis ");
    $Test->nlog("===================================================================================");
    my $Api_Set_Obj;
    my $dsk_typ;
    foreach my $Node (@Nodes) {
        my $FILER_C = $Node->name();
        logcomment("FILER: $FILER_C : Get log pages for Data Analysis");
        if ( $execution_state eq 'CLI' ) {
            $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
            $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
            my $disk_type = NACL::CS::StorageDisk->fetch( command_interface => $Node, requested_fields => ['type'] );
            $dsk_typ = $disk_type->type();
            logcomment("DEBUG:disk type is $dsk_typ");
        } else {
            $Api_Set_Obj = $FILER_API{$FILER_C};
            my $disk_type = disk_type_maint( Node => $Node );
            foreach my $dsk ( keys %$disk_type ) {
                $dsk_typ = $disk_type->{$dsk}->{'Type'};
                if ($dsk_typ) {
                    logcomment("DEBUG:disk type is $dsk_typ");
                    last;
                }
            }
        }
        logcomment("Drive type obtained : $dsk_typ and filer state is $execution_state ");

        #logcomment( "Get Drive attached to " . $Nodes[0]->name() . " and " . $Nodes[1]->name() );
        logcomment("Get Drive attached to $FILER_C");
        my @temp_disk_info = list_of_disk( Node => $Node );

        #        my @temp_disk_info = get_disk_information( API_Obj => $Api_Set_Obj, Filer => $FILER_C );
        my $dsks = _print_array( \@temp_disk_info ) if (@temp_disk_info);

        #logcomment( "Total drives present in the filer" . $Nodes[0]->name() . " and " . $Nodes[1]->name() . " are " . scalar @temp_disk_info . " and the drives are @temp_disk_info" );
        logcomment( "Total drives present in the filer $FILER_C" . "are " . scalar @temp_disk_info . " and the drives are @temp_disk_info" );
        logcomment("$dsks");
        logcomment("Get log pages for all available drives");
        foreach my $drvs (@temp_disk_info) {
            next if ( $drvs =~ /P1|P2|P3/ );
            logcomment("Get log pages for Drive : $drvs");
            $Api_Set_Obj->execute_command( 'command' => "scsi logsense -p 0x02 $drvs" );
            $Api_Set_Obj->execute_command( 'command' => "scsi logsense -p 0x03 $drvs" );
            $Api_Set_Obj->execute_command( 'command' => "scsi logsense -p 0x05 $drvs" );
            $Api_Set_Obj->execute_command( 'command' => "scsi logsense -p 0x06 $drvs" );

            # $Api_Set_Obj->execute_command( 'command' => "scsi logsense -p 0x07 $drvs" );
            $Api_Set_Obj->execute_command( 'command' => "scsi logsense -p 0x15 $drvs" );
            $Api_Set_Obj->execute_command( 'command' => "scsi logsense -p 0x18 $drvs" );
            $Api_Set_Obj->execute_command( 'command' => "scsi logsense -p 0x19 -r 0x0002 $drvs" ) if ( $drvs !~ /L1|L2/ );
            $Api_Set_Obj->execute_command( 'command' => "scsi logsense -p 0x2f $drvs" );
            $Api_Set_Obj->execute_command( 'command' => "scsi logsense -p 0x0d -s 0x01 $drvs" );
            if ( $dsk_typ =~ /SSD/ ) {
                $Api_Set_Obj->execute_command( 'command' => "scsi logsense -p 0x11 $drvs" );
                $Api_Set_Obj->execute_command( 'command' => "scsi logsense -p 0x30 $drvs" );
                $Api_Set_Obj->execute_command( 'command' => "scsi logsense -p 0x33 -s 0x09 $drvs" );
                $Api_Set_Obj->execute_command( 'command' => "scsi logsense -p 0x33 -s 0x10 $drvs" );
            }
        }
        last;    #as all drive are captured , exectuing only on one node.
    }    #End of Foreach node
    logcomment("POST-TEST - End of scsi logsense data for all the disks");

=head #Burt 1138944 - Moved to send_result
    foreach my $Node (@Nodes) {
        my $FILER_C     = $Node->name();
        my $Transit_obj = NACL::Transit->new( name => $FILER_C );
        my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
        my $Host        = host($FILER_C);
        my $prompt_fw;
        my $ignore_strings = [ "MADIMM\\d+->", "DIMM\\d+->", "^T>" ];
        my $prompt_array   = $Host->prompt_fw();
        my $prompts        = join( "|", @$prompt_array );
        $prompt_fw = "($prompts)";
        logcomment("This is the prompt regex: $prompt_fw");
        my $Server = new Server( no_cli => 1 );
        $Server->set_execution_server( -Server => $FILER_C );    #set the execution server to the current node
        logcomment("Filer state is : $filer_state");

        if ( $CMPRSN == 1 ) {
            logcomment("POST_TEST : $FILER_C : As user selected option -c=1, Unsetting the environment variable wafl-disable-packing?");
            if ( $filer_state !~ /LOADER|FIRMWARE/ ) {
                logcomment("Changing the state to FIRMWARE");
                $Transit_obj->change_state( to => "FIRMWARE" );
            }
            my $filer_state1 = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
            if ( $filer_state1 =~ /LOADER|FIRMWARE/ ) {
                $Server->console(
                    cmd                        => "unsetenv wafl-disable-packing?",
                    additional_prompts_timeout => 60,
                    ignore                     => $ignore_strings,
                    additional_prompts         => { "$prompt_fw" => "FINAL_PROMPT", }
                );
                $Server->console(
                    cmd                        => "saveenv",
                    additional_prompts_timeout => 60,
                    ignore                     => $ignore_strings,
                    additional_prompts         => { "$prompt_fw" => "FINAL_PROMPT", }
                );
                $Server->console(
                    cmd                        => "printenv wafl-disable-packing?",
                    additional_prompts_timeout => 60,
                    ignore                     => $ignore_strings,
                    additional_prompts         => { "$prompt_fw" => "FINAL_PROMPT", }
                );
            }
        }
        logcomment("As filer $FILER_C was in $filer_state before setting the environment variable, changing back to $filer_state state");
        $Transit_obj->change_state( to => "$filer_state" );
        my $filr_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
        logcomment("Filer state is : $filr_state");
    }
=cut #Burt 1138944 

    $Test->nlog("##################################################################################");
    $Test->nlog("##");
    $Test->nlog("## End of POST_TEST logs for Filer : @Filer_array");
    $Test->nlog("##");
    $Test->nlog("##################################################################################");

    #End of post test
    return $result_flag;

}

#######################################################################################################
# Auther - priya3
# Description -  sasadmin_dev_stats_cmode
# Supported Mode - CMode/7Mode
######################################################################################################
sub sasadmin_dev_stats_cmode {
    my (%opts) = validate(
        @_,
        {
            node         => { type => OBJECT },
            adapter_name => { type => SCALAR, default => undef, optional => 1 },
        }
    );
    my $Node = $opts{node};
    my $Mode = $Node->mode();
    my $API_obj;
    my $FILER_C = $Node->name();
    my $adapter = undef;
    my $output  = "";
    if ( defined( $opts{adapter_name} ) ) {
        $adapter = $opts{adapter_name};
    }
    my %structure   = ();
    my $cmd         = "sasadmin dev_stats";
    my $Transit_obj = NACL::Transit->new( name => $FILER_C );
    my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    if ( $filer_state =~ /MAINT/gi ) {
        my $Host = host($FILER_C);
        $API_obj = NACL::APISet->new(
            hostobj   => $Host,
            category  => "Node",
            interface => "CLI",
            set       => "Maintenance"
        );
        $API_obj->set_timeout( "connectrec-timeout" => 7200 );
        $output = $API_obj->execute_raw_command( 'command' => "$cmd" );
    } elsif ( $filer_state =~ /(CLI|UP)/gi ) {
        $API_obj = $Node->get_7m_or_nodescope_apiset();
        $API_obj->set_timeout( "connectrec-timeout" => 7200 );
        $output = $API_obj->execute_command( 'command' => "$cmd" );
    }
    if ( $output !~ /Device stats on channel/ ) {
        logcomment("$FILER_C : NO EXPECTED OUTPUT appeared");
        return;
    }
    $output =~ s/'|,|://g;    #removing all (' and : and ,)
    my ( @tot_channels, $total );
    @tot_channels = $output =~ /Device stats on channel\s(\S+)/g;
    $total        = @tot_channels;
    my $hba;
    my @lines = split( /\r*\n/, $output );
    foreach (@lines) {

        if ( $_ =~ /Device stats on channel\s(\S+)/ ) {

            $hba = $1;
        }
        if ( $_ =~ /(^$hba\.\S+)\s+/ ) {

            my @fields = split( /\s+/, $_ );
            $structure{$hba}{"$fields[0]"}{'Device'}          = $fields[0];
            $structure{$hba}{"$fields[0]"}{'CmdsCmpltGood'}   = $fields[1];
            $structure{$hba}{"$fields[0]"}{'CmdsCmpltError'}  = $fields[2];
            $structure{$hba}{"$fields[0]"}{'FramesIn'}        = $fields[3];
            $structure{$hba}{"$fields[0]"}{'FramesOut'}       = $fields[4];
            $structure{$hba}{"$fields[0]"}{'VctmAbrt'}        = $fields[5];
            $structure{$hba}{"$fields[0]"}{'QsceCnt'}         = $fields[6];
            $structure{$hba}{"$fields[0]"}{'UdrnCnt'}         = $fields[7];
            $structure{$hba}{"$fields[0]"}{'OvrnCnt'}         = $fields[8];
            $structure{$hba}{"$fields[0]"}{'TrnsErrCnt'}      = $fields[9];
            $structure{$hba}{"$fields[0]"}{'SCSIPtclErrCnt'}  = $fields[10];
            $structure{$hba}{"$fields[0]"}{'CRCErrCnt'}       = $fields[11];
            $structure{$hba}{"$fields[0]"}{'OPENErrCnt'}      = $fields[12];
            $structure{$hba}{"$fields[0]"}{'InvdCnt'}         = $fields[13];
            $structure{$hba}{"$fields[0]"}{'DlayCnt'}         = $fields[14];
            $structure{$hba}{"$fields[0]"}{'SATAInitFailCnt'} = $fields[15];
            $structure{$hba}{"$fields[0]"}{'TO1Ct'}           = $fields[16];
            $structure{$hba}{"$fields[0]"}{'TO2Ct'}           = $fields[17];
            $structure{$hba}{"$fields[0]"}{'TO3Ct'}           = $fields[18];
            $structure{$hba}{"$fields[0]"}{'TO4Ct'}           = $fields[19];
        }
    }
    my $up_chan     = 0;
    my @up_channles = keys(%structure);
    $up_chan = @up_channles;
    logcomment("$FILER_C : Total number of channels are $total and the channels are @tot_channels");
    logcomment("$FILER_C : Total number of UP channels are $up_chan and the channels are @up_channles");
    return \%structure;
}

#######################################################################################################
## Author Arjun Lavu
## Description -  sasadmin_expander_map_cmode
## The following named arguments are accepted:
## item Node
## (Required) : Node object to execute a command.
## item adapter_name
## (Optional) : Specific channel for which the information is
## required. Default is all
## Supported Mode - CMode/7Mode[CLI/MAINT]
#######################################################################################################
sub sasadmin_expander_map_cmode {
    my (%opts) = validate(
        @_,
        {
            node         => { type => OBJECT },
            adapter_name => { type => SCALAR, default => undef, optional => 1 },
        }
    );
    my $Node = $opts{node};
    my $Mode = $Node->mode();
    my $API_obj;
    my $FILER_C = $Node->name();
    my $adapter = undef;
    my $output  = "";

    my $Transit_obj = NACL::Transit->new( name => $FILER_C );
    my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    if ( defined( $opts{adapter_name} ) ) {
        $adapter = $opts{adapter_name};
    }
    my %structure = ();
    my $cmd       = "sasadmin expander_map $adapter";
    if ( $filer_state =~ /MAINT/gi ) {
        my $Host = host($FILER_C);
        $API_obj = NACL::APISet->new(
            hostobj   => $Host,
            category  => "Node",
            interface => "CLI",
            set       => "Maintenance"
        );
        $API_obj->set_timeout( "connectrec-timeout" => 7200 );
        $output = $API_obj->execute_raw_command( 'command' => "$cmd" );
    } elsif ( $filer_state =~ /(CLI|UP)/gi ) {
        $API_obj = $Node->get_7m_or_nodescope_apiset();
        $API_obj->set_timeout( "connectrec-timeout" => 7200 );
        $output = $API_obj->execute_command( 'command' => "$cmd" );
    }

    if ( $output !~ /Expanders on channel/ ) {
        logcomment("$FILER_C : NO EXPECTED OUTPUT appeared");
        return;
    }
    $output =~ s/'|,|://g;    #removing all (' and : and ,)
    my ( @tot_channels, $total );
    @tot_channels = $output =~ /Expanders on channel\s(\S+)/g;
    $total        = @tot_channels;
    my $hba;
    my @lines = split( /\r*\n/, $output );
    foreach (@lines) {

        if ( $_ =~ /Expanders on channel\s(\S+)/ ) {
            $hba = $1;
        }
        if ( $_ =~ /^Level/ ) {
            my @fields = split( /\s+/, $_ );
            $structure{$hba}{"$fields[3]"}{'Level'}        = $fields[1];
            $structure{$hba}{"$fields[3]"}{'ID'}           = $fields[5];
            $structure{$hba}{"$fields[3]"}{'SerialNumber'} = $fields[8];
            $structure{$hba}{"$fields[3]"}{'Product'}      = $fields[10];
            $structure{$hba}{"$fields[3]"}{'Rev'}          = $fields[12];
            $structure{$hba}{"$fields[3]"}{'Slot'}         = $fields[14];
        }
    }
    my $up_chan     = 0;
    my @up_channles = keys(%structure);
    $up_chan = @up_channles;
    logcomment("$FILER_C : Total number of channels are $total and the channels are @tot_channels");
    logcomment("$FILER_C : Total number of UP channels are $up_chan and the channels are @up_channles");
    return \%structure;
}

sub handle_run_local_error {
    my (%opts) = validate( @_, { Nodes => { type => ARRAYREF }, } );
    my @temp_nodes = @{ $opts{Nodes} };

    #my @temp_nodes = NACL::C::Node->find();    # Find Nodes/Filers used in the test, Based on FILER param.
    my %nodes_filer;
    foreach my $Node (@temp_nodes) {
        my $FILER_C = $Node->name();
        $nodes_filer{$FILER_C} = [$Node];
    }
    my @Nodes = map { @{$_} } grep { (/\S/) } values(%nodes_filer);
    foreach my $Node (@Nodes) {
        my $FILER_C = $Node->name();
        my $Transit_obj = NACL::Transit->new( name => $FILER_C );
        my $filer_state;
        try {
            $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
        }
        catch NACL::Transit::Exceptions::Timeout with {
            logcomment("Expected: Caught a Timeout Exception");
            $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
        }
        catch NACL::Transit::Exceptions::TransitException with {
            my $exception_object = shift;

            # logcomment("Exception is of type: " . ref ($exception_object));
            # logcomment("Error text is: " . $exception_object->text());
        };
        if ( $filer_state =~ /USER|PASS/i ) {
            $Transit_obj->set( 'change_state_timeout' => 7200 );
            $Transit_obj->change_state( to => "CLI" );
        }
        if ( $filer_state =~ /CLI/i ) {
            #############################################################################
            my $prompt_fw;
            my $ignore_strings = [ "MADIMM\\d+->", "DIMM\\d+->", "^T>" ];
            my $host           = Tharn::host($FILER_C);
            my $prompt_array   = $host->prompt_fw();
            my $prompts        = join( "|", @$prompt_array );
            $prompt_fw = "($prompts)";
            logcomment("DEBUG:This is the prompt regex: $prompt_fw");
            my $Server = new Server( no_cli => 1 );
            $Server->set_execution_server( -Server => $FILER_C );

            #
            try {
                $Server->console(
                    cmd                        => "run local",
                    additional_prompts_timeout => 600,
                    ignore                     => $ignore_strings,
                    additional_prompts         => {
                        "$FILER_C\>"                   => "FINAL_PROMPT",
                        "run not found"                => "FINAL_PROMPT",
                        "::*>"                         => "FATAL_PROMPT",
                        "::>"                          => "FATAL_PROMPT",
                        ".*Too many users logged in.*" => "FATAL_PROMPT",
                        "$prompt_fw"                   => "FINAL_PROMPT",
                        "takeover"                     => "FINAL_PROMPT",
                    }
                );
                $Transit_obj->set( 'change_state_timeout' => 7200 );
                $Transit_obj->change_state( to => "CLI" );
            }
            catch NATE::BaseException with {
                logcomment("Filer  - $FILER_C : Error while logging in DBLADE, rebooting the node to rectify it");
                $Transit_obj->set( 'change_state_timeout' => 7200 );
                $Transit_obj->change_state( to => "FIRMWARE" );
                sleep 60;
                $Transit_obj->change_state( to => "CLI" );

                # try{
                # $Server->console(cmd => "run local",
                # additional_prompts_timeout => 600,
                # ignore => $ignore_strings,
                # additional_prompts => {
                # "$FILER_C\>" => "exit",
                # "::*>" => "FINAL_PROMPT",
                # "::>" => "FINAL_PROMPT",
                # ".*Too many users logged in.*"=>"FATAL_PROMPT",
                # "$prompt_fw" => "FINAL_PROMPT",
                # }
                # );
                # }catch NATE::BaseException with{
                # logcomment("FILER  - $FILER_C : Some other error occured on the filer");

                # };
            };
        }
    }
}

sub enable_firmware_console_message {
    my (%opts) = validate( @_, { Node => { type => OBJECT }, } );
    my $Node = $opts{Node};
    my $FILER_C     = $Node->name();
    my $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
    $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
    logcomment("DEBUG:Enabling required firmware console debug messages");

    $Api_Set_Obj->execute_raw_command( 'command' => "run local" );
    $Api_Set_Obj->execute_raw_command( 'command' => "priv set -q test" );
    $Api_Set_Obj->execute_raw_command( 'command' => "dbg level diskfw=0" );
    $Api_Set_Obj->execute_raw_command( 'command' => "exit" );
    my $prompts_answers = [ ".*continue?" => 'y' ];
    $Api_Set_Obj->execute_raw_command( 'command' => "set test", 'connectrec-match_table' => $prompts_answers );
    $Api_Set_Obj->execute_raw_command( 'command' => "set -rows 0" );
    $Api_Set_Obj->execute_raw_command( 'command' => "event show-suppression -node $FILER_C -is-on false" );

    #	$Api_Set_Obj->execute_raw_command('command' => "event show-suppression -node $FILER_C -level NO");
    $Api_Set_Obj->execute_raw_command( 'command' => "event config modify -suppression off -console on" );
    $Api_Set_Obj->execute_raw_command( 'command' => "event config modify -suppression off -consoleloglevel DEBUG" );

    # $Api_Set_Obj->execute_raw_command('command' => "event config modify -consoleloglevel DEBUG");
    # $Api_Set_Obj->execute_raw_command('command' => "set advance");
    # $Api_Set_Obj->execute_raw_command('command' => "event config mod -console on");

    logcomment("All Necessary firmware console message are enabled");
}

sub sasadmin_inject_sub {
    my (%opts) = validate(
        @_,
        {
            host         => { type => OBJECT, isa     => 'Hostrec' },
            adapter_name => { type => SCALAR, default => undef, optional => 1 },
            device_name  => { type => SCALAR, default => undef, optional => 1 },
            period       => { type => SCALAR, default => 300, optional => 1 },
            command   => { type => SCALAR },
            timeout   => { type => SCALAR, default => 1200, optional => 1 },
            filermode => { type => SCALAR, default => "normal", optional => 1 },
        }
    );
    my $output;
    my $adapter_name;
    my $a = "";
    my $b = "";
    my $mark;
    my $cmd_option;
    my $cmd1;
    my $cmd;
    my $Node;
    my $Api_Set_Obj;
    my $Host    = $opts{host};
    my $FILER_C = $Host->{hostname};
    $FILER_C =~ s/\"//gi;
    my @Nodes = NACL::C::Node->find();

    foreach (@Nodes) {
        if ( $_->name() =~ /^$FILER_C$/ ) {
            $Node = $_;
            last;
        }
    }
    if ( !($Node) ) {
        logcomment("**FATAL** : Could NOT found node object ");
        logresult( 'FATAL', "COULD NOT FOUND NODE OBJECT " );
    }
    if ( $opts{filermode} =~ /normal/ ) {
        $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
    } else {
        $Api_Set_Obj = NACL::APISet->new(
            hostobj   => $Host,
            category  => "Node",
            interface => "CLI",
            set       => "Maintenance"
        );
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
    }

    $cmd1 = "sasadmin inject";
    if ( $opts{command} =~ /^dev_reset$/ ) {
        if ( defined( $opts{adapter_name} ) ) {
            $cmd = "$cmd1 dev_reset enable -t $opts{period} -r -c $opts{adapter_name}";
        } elsif ( defined( $opts{device_name} ) ) {
            $cmd = "$cmd1 dev_reset enable -t $opts{period} -d $opts{device_name}";
        } else {
            logresult( 'script', "adapter_name or device_name are the required parameters" );
        }
        if ( $opts{filermode} =~ /normal/ ) {
            $output = $Api_Set_Obj->execute_command( command => "$cmd" );
        } else {
            $output = $Api_Set_Obj->execute_raw_command( command => "$cmd" );
        }
        if ( $output =~ /Not a SAS adapter|failed|No such adapter|Usage/ ) {
            logcomment("$output");
        }
        return 1;
    } elsif ( $opts{command} =~ /^abort$/ ) {
        if ( defined( $opts{adapter_name} ) ) {
            $cmd = "$cmd1 abort enable -t $opts{period} -r -c $opts{adapter_name}";
        } elsif ( defined( $opts{device_name} ) ) {
            $cmd = "$cmd1 abort enable -t $opts{period} -d $opts{device_name}";
        } else {
            logresult( 'script', "adapter_name or device_name are the required parameters" );
        }

        if ( $opts{filermode} =~ /normal/ ) {
            $output = $Api_Set_Obj->execute_command( command => "$cmd" );
        } else {
            $output = $Api_Set_Obj->execute_raw_command( command => "$cmd" );
        }

        if ( $output =~ /Not a SAS adapter|failed|No such adapter|Usage/ ) {
            logcomment("$output");
        }
        return 1;
    } elsif ( $opts{command} =~ /^timeout$/ ) {
        if ( defined( $opts{adapter_name} ) ) {
            $cmd = "$cmd1 timeout enable -t $opts{period} -r -c $opts{adapter_name}";
        } elsif ( defined( $opts{device_name} ) ) {
            $cmd = "$cmd1 timeout enable -t $opts{period} -d $opts{device_name}";
        } else {
            logresult( 'script', "adapter_name or device_name are the required parameters" );
        }

        if ( $opts{filermode} =~ /normal/ ) {
            $output = $Api_Set_Obj->execute_command( command => "$cmd" );
        } else {
            $output = $Api_Set_Obj->execute_raw_command( command => "$cmd" );
        }

        if ( $output =~ /Not a SAS adapter|failed|No such adapter|Usage/ ) {
            logcomment("$output");
        }
        return 1;
    } elsif ( $opts{command} =~ /^adapter_reset$/ ) {
        if ( defined( $opts{adapter_name} ) ) {
            $cmd = "$cmd1 adapter_reset enable -t $opts{period} -r -c $opts{adapter_name}";
        } else {
            logresult( 'script', "adapter_name is the required parameter" );
        }

        if ( $opts{filermode} =~ /normal/ ) {
            $output = $Api_Set_Obj->execute_command( command => "$cmd" );
        } else {
            $output = $Api_Set_Obj->execute_raw_command( command => "$cmd" );
        }
        if ( $output =~ /Not a SAS adapter|failed|No such adapter|Usage/ ) {
            logcomment("$output");
        }
        return 1;
    } elsif ( $opts{command} =~ /^disable$/ ) {
        $cmd = "$cmd1 disable";
        if ( $opts{filermode} =~ /normal/ ) {
            $output = $Api_Set_Obj->execute_command( command => "$cmd" );
        } else {
            $output = $Api_Set_Obj->execute_raw_command( command => "$cmd" );
        }

        if ( $output !~ /Disabling all error injection/ ) {
            logcomment("$output");
        }
        return 1;
    } elsif ( $opts{command} =~ /^show$/ ) {
        $cmd = "$cmd1 show";

        if ( $opts{filermode} =~ /normal/ ) {
            $output = $Api_Set_Obj->execute_command( command => "$cmd" );
        } else {
            $output = $Api_Set_Obj->execute_raw_command( command => "$cmd" );
        }

        if ( $output =~ /Not a SAS adapter|failed|No such adapter|Usage/ ) {
            logcomment("$output");
        }
        return $output;
    } else {
        logresult( 'script', "Invalid command:  %opts{command}" );
    }
}

##########################################################################################################
#Author- arjunl.lavu@netapp.com
##########################################################################################################
sub fcadmin_inject_sub {
    my (%opts) = validate(
        @_,
        {
            host         => { type => OBJECT },
            adapter_name => { type => SCALAR, default => undef, optional => 1 },
            device_name  => { type => SCALAR, default => undef, optional => 1 },
            period       => { type => SCALAR, default => 300, optional => 1 },
            command      => { type => SCALAR },
            timeout      => { type => SCALAR, default => 1200, optional => 1 },
            filermode    => { type => SCALAR, default => "normal", optional => 1 },
        }
    );
    my $output;
    my $adapter_name;
    my $a = "";
    my $b = "";
    my $mark;
    my $cmd_option;
    my $cmd1;
    my $cmd;
    my $Node;
    my $Api_Set_Obj;
    my $Host    = $opts{host};
    my $FILER_C = $Host->{hostname};
    $FILER_C =~ s/\"//gi;
    my @Nodes = NACL::C::Node->find();

    foreach (@Nodes) {
        if ( $_->name() =~ /^$FILER_C$/ ) {
            $Node = $_;
            last;
        }
    }
    if ( !($Node) ) {
        logcomment("**FATAL** : Could NOT found node object ");
        logresult( 'FATAL', "COULD NOT FOUND NODE OBJECT " );
    }
    if ( $opts{filermode} =~ /normal/ ) {
        $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
    } else {
        $Api_Set_Obj = NACL::APISet->new(
            hostobj   => $Host,
            category  => "Node",
            interface => "CLI",
            set       => "Maintenance"
        );
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
    }
    $cmd1 = "fcadmin inject";
    if ( $opts{command} =~ /^dev_reset$/ ) {
        if ( defined( $opts{adapter_name} ) ) {
            $cmd = "$cmd1 dev_reset enable -t $opts{period} -r -c $opts{adapter_name}";
        } elsif ( defined( $opts{device_name} ) ) {
            $cmd = "$cmd1 dev_reset enable -t $opts{period} -d $opts{device_name}";
        } else {
            logresult( 'script', "adapter_name or device_name are the required parameters" );
        }
        if ( $opts{filermode} =~ /normal/ ) {
            $output = $Api_Set_Obj->execute_command( command => "$cmd" );
        } else {
            $output = $Api_Set_Obj->execute_raw_command( command => "$cmd" );
        }
        if ( $output =~ /adapter|failed|No such adapter|Usage/ ) {
            logcomment("$output");
        }
        return 1;
    } elsif ( $opts{command} =~ /^abort$/ ) {
        if ( defined( $opts{adapter_name} ) ) {
            $cmd = "$cmd1 abort enable -t $opts{period} -r -c $opts{adapter_name}";
        } elsif ( defined( $opts{device_name} ) ) {
            $cmd = "$cmd1 abort enable -t $opts{period} -d $opts{device_name}";
        } else {
            logresult( 'script', "adapter_name or device_name are the required parameters" );
        }
        if ( $opts{filermode} =~ /normal/ ) {
            $output = $Api_Set_Obj->execute_command( command => "$cmd" );
        } else {
            $output = $Api_Set_Obj->execute_raw_command( command => "$cmd" );
        }

        if ( $output =~ /failed|No such adapter|Usage/ ) {
            logcomment("$output");
        }
        return 1;
    } elsif ( $opts{command} =~ /^timeout$/ ) {
        if ( defined( $opts{adapter_name} ) ) {
            $cmd = "$cmd1 timeout enable -t $opts{period} -r -c $opts{adapter_name}";
        } elsif ( defined( $opts{device_name} ) ) {
            $cmd = "$cmd1 timeout enable -t $opts{period} -d $opts{device_name}";
        } else {
            logresult( 'script', "adapter_name or device_name are the required parameters" );
        }
        if ( $opts{filermode} =~ /normal/ ) {
            $output = $Api_Set_Obj->execute_command( command => "$cmd" );
        } else {
            $output = $Api_Set_Obj->execute_raw_command( command => "$cmd" );
        }
        if ( $output =~ /failed|No such adapter|Usage/ ) {
            logcomment("$output");
        }
        return 1;

    } elsif ( $opts{command} =~ /^adapter_reset$/ ) {
        if ( defined( $opts{adapter_name} ) ) {
            $cmd = "$cmd1 adapter_reset enable -t $opts{period}  -c $opts{adapter_name}";
        } else {
            logresult( 'script', "adapter_name is the required parameter" );
        }
        if ( $opts{filermode} =~ /normal/ ) {
            $output = $Api_Set_Obj->execute_command( command => "$cmd" );
        } else {
            $output = $Api_Set_Obj->execute_raw_command( command => "$cmd" );
        }
        if ( $output =~ /failed|No such adapter|Usage/ ) {
            logcomment("$output");
        }
        return 1;
    } elsif ( $opts{command} =~ /^lip$/ ) {
        if ( defined( $opts{adapter_name} ) ) {
            $cmd = "$cmd1 lip enable -t $opts{period}  -c $opts{adapter_name}";
        } else {
            logresult( 'script', "adapter_name is the required parameter" );
        }
        if ( $opts{filermode} =~ /normal/ ) {
            $output = $Api_Set_Obj->execute_command( command => "$cmd" );
        } else {
            $output = $Api_Set_Obj->execute_raw_command( command => "$cmd" );
        }

        if ( $output =~ /failed|No such adapter|Usage/ ) {
            logcomment("$output");
        }
        return 1;
    } elsif ( $opts{command} =~ /^disable$/ ) {
        $cmd = "$cmd1 disable";
        if ( $opts{filermode} =~ /normal/ ) {
            $output = $Api_Set_Obj->execute_command( command => "$cmd" );
        } else {
            $output = $Api_Set_Obj->execute_raw_command( command => "$cmd" );
        }
        if ( $output =~ /failed/ ) {
            logcomment("$output");
        }
        return 1;
    } elsif ( $opts{command} =~ /^show$/ ) {
        $cmd = "$cmd1 show";
        if ( $opts{filermode} =~ /normal/ ) {
            $output = $Api_Set_Obj->execute_command( command => "$cmd" );
        } else {
            $output = $Api_Set_Obj->execute_raw_command( command => "$cmd" );
        }
        if ( $output =~ /failed|No such adapter|Usage/ ) {
            logcomment("$output");
        }
        return $output;
    } else {
        logresult( 'script', "Invalid command:  %opts{command}" );
    }

}

#####################################################
##Disable debug messages
## Author :: Arjun Lavu
#####################################################

sub disable_debug_msg {
    my (%opts) = validate( @_, { Node => { type => OBJECT }, } );
    my $Node = $opts{Node};
    my $FILER_C = $Node->name();
    my $Api_Set_Obj;
    my $Transit_obj = NACL::Transit->new( name => $FILER_C );
    my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    if ( $filer_state =~ /CLI/ ) {
        $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
        $Api_Set_Obj->execute_command( 'command' => 'dbg to off' );
    } else {
        my $Host = host($FILER_C);
        $Api_Set_Obj = NACL::APISet->new(
            hostobj   => $Host,
            category  => "Node",
            interface => "CLI",
            set       => "Maintenance",
        );
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
        $Api_Set_Obj->execute_raw_command( 'command' => 'dbg to off' );
    }
}

####################################
### Arjun Lavu
####################################

sub fcadmin_device_map {
    my (%opts) = validate(
        @_,
        {
            Node         => { type => OBJECT },
            channel_name => { type => SCALAR, optional => 1 },
        }
    );
    my $Node    = $opts{Node};
    my $FILER_C = $Node->name();
    my $Host    = host($FILER_C);
    my ( $output, $Api_Set_Obj );
    my $Transit_obj = NACL::Transit->new( name => $FILER_C );
    my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    my $cmd = "fcadmin device_map $opts{channel_name}";

    if ( $filer_state =~ /CLI|UP/i ) {
        $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
        $output = $Api_Set_Obj->execute_command( command => "$cmd" );
    } else {
        $Api_Set_Obj = NACL::APISet->new(
            hostobj   => $Host,
            category  => "Node",
            interface => "CLI",
            set       => "Maintenance"
        );
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
        $output = $Api_Set_Obj->execute_raw_command( command => "$cmd" );
    }
    if ( $output =~ /fcadmin device_map: No such channel/ ) {
        logcomment("$output");
    }

    my %HoH = ();

    my @lines = split( /\r*\n/, $output );
    my ( $channel, $shelf, $translated_map_flag, @translated_map, $shelf_map_flag, @shelf_map, $target_ses_flag, @target_ses_map );
    $translated_map_flag = $shelf_map_flag = $target_ses_flag = 0;
    $shelf = '';
    foreach (@lines) {
        $_ =~ s/^\s+//;
        $_ =~ s/\s+$//;
        if ( $_ =~ /Cannot complete operation on channel (\w+); link is DOWN/ ) {
            $HoH{$1}{'State'} = "DOWN";
        } elsif ( $_ =~ /Loop Map for channel (\S+):$/ ) {
            my @channel = split( /\s+/, $_ );
            $channel = $channel[4];
            chop($channel);

            #$channel = $1;
            $HoH{$channel}{'State'} = "UP";
        } elsif ( $_ =~ /Translated Map: Port Count (\d+)/ ) {
            $HoH{$channel}{'PortCount'} = $1;
            $translated_map_flag = 1;
        } elsif ( ($translated_map_flag) && ( $_ !~ /Shelf mapping:/ ) ) {
            my @fields1 = split( /\s+/, $_ );
            push( @translated_map, @fields1 );
        } elsif ( $_ =~ /Shelf mapping:/ ) {
            $shelf_map_flag = 1;
            $HoH{$channel}{'TranslatedMap'} = [@translated_map];

            # clear map
            @translated_map      = ();
            $translated_map_flag = 0;
        } elsif ( $_ =~ /Target SES devices on this loop:/ ) {
            $target_ses_flag = 1;
            $shelf_map_flag  = 0;
        } elsif ( $_ =~ /^Shelf (\d+):\s+(.*)/ ) {
            $shelf = $1;

            # Die if the shelf configuration is not valid
            if ( $shelf eq "Unknown" ) {
                die "Configuration issue in loop: Loop $channel not properly configured";
            }

            my @fields = split( /\s+/, $2 );
            if ($shelf_map_flag) {
                push( @shelf_map, @fields );
                print "\nShelf Map : @shelf_map";
                $HoH{$channel}{$shelf}{'ShelfMapping'} = [@shelf_map];
                @shelf_map = ();
            } elsif ($target_ses_flag) {
                push( @target_ses_map, @fields );
                $HoH{$channel}{$shelf}{'TargetSES'} = [@target_ses_map];
                @target_ses_map = ();
            }
        }
    }
    return \%HoH;
}

##########################################################################################################
#Author- arjunl.lavu@netapp.com
##########################################################################################################
sub fcadmin_link_stats {
    my (%opts) = validate(
        @_,
        {
            Node         => { type => OBJECT },
            channel_name => { type => SCALAR, optional => 1 },
        }
    );
    my $Node    = $opts{Node};
    my $FILER_C = $Node->name();
    my $Host    = host($FILER_C);
    my ( $output, $Api_Set_Obj );
    my $Transit_obj = NACL::Transit->new( name => $FILER_C );
    my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    my $cmd = "fcadmin link_stats $opts{channel_name}";

    if ( $filer_state =~ /CLI|UP/i ) {
        $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
        $output = $Api_Set_Obj->execute_command( command => "$cmd" );
    } else {
        $Api_Set_Obj = NACL::APISet->new(
            hostobj   => $Host,
            category  => "Node",
            interface => "CLI",
            set       => "Maintenance"
        );
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
        $output = $Api_Set_Obj->execute_raw_command( command => "$cmd" );
    }

    if ( $output =~ /fcadmin link_stats: No such channel/ ) {
        logcomment("$output");
    }
    my %HoH = ();
    my @lines = split( /\r*\n/, $output );
    foreach (@lines) {
        if ( $_ =~ /Cannot complete operation on channel (\w+); link is DOWN/ ) {
            $HoH{$1}{'State'} = "DOWN";
        } elsif ( $_ =~ /(\w+)\./ ) {
            my @fields = split( /\s+/, $_ );
            my $device_name = $fields[0];
            if ( $device_name =~ /(\w+)\.ha/ ) {
                if ( ( !exists $HoH{$1}{'State'} ) && ( !defined $HoH{$1}{'State'} ) ) {
                    $device_name = $1;
                    $HoH{$device_name}{'State'} = "UP";
                }
            }
            $HoH{$device_name}{'LinkFailureCount'}    = $fields[1];
            $HoH{$device_name}{'TransportErrorCount'} = $fields[2];
            $HoH{$device_name}{'LossOfSyncCount'}     = $fields[3];
            $HoH{$device_name}{'InvalidCRCCount'}     = $fields[4];
            $HoH{$device_name}{'FrameInCount'}        = $fields[5];
            $HoH{$device_name}{'FrameOutCount'}       = $fields[6];
        }
    }
    return \%HoH;
}

########################################################################################################################################
### Arjun Lavu
## Description :: This subroutine will create required number of spares by deleting the aggregates if needed
########################################################################################################################################

sub create_spares {
    my (%opts) = validate(
        @_,
        {
            Node           => { type => OBJECT },
            required_spare => { type => SCALAR },
        }
    );
    my $Node            = $opts{Node};
    my $required_spares = $opts{required_spare};
    my $FILER_C         = $Node->name();
    my ( $err_flag, $flag_fill, %aggr_disks, $vser_aggr );
    my @spares = spare_count_cmode( Node => $Node );
    my ( @aggregates, @non_root, @delete_aggr );
    if ( $required_spares <= scalar @spares ) {
        logcomment("Already enough spare are available in the filer $FILER_C.");
        return;
    }
    my $spares_needed = $required_spares - ( scalar @spares );
    logcomment("$FILER_C : Spares required more are :: $spares_needed");
    try {
        my @tot_aggr = NACL::CS::StorageAggregate->fetch(
            command_interface => $Node,
            filter            => { node => $FILER_C, 'root' => 'false' }
        );
        foreach my $aggr (@tot_aggr) {
            push( @aggregates, $aggr->aggregate );
        }
        logcomment("$FILER_C :: Non Root aggregates are - @aggregates");
    }
    catch NACL::Exceptions::NoElementsFound with {
        logcomment("$FILER_C : Non root aggregates are NOT found in the filer");
        $err_flag = 1;
    };
    if ($err_flag) {
        logcomment("NO ADDITIONAL AGGREGATES present in the filer : $FILER_C");
        return;
    }
    foreach my $aggr (@aggregates) {
        my $disk_obj = NACL::CS::StorageAggregate->fetch(
            command_interface => $Node,
            filter            => { 'aggregate' => "$aggr", },
            requested_fields  => ['disklist']
        );
        my @disks = $disk_obj->disklist();
        logcomment("In the aggregare : $aggr total number of drives present are :: @disks");
        $aggr_disks{$aggr} = [@disks];
    }
    my $sum = 0;
    foreach my $key ( keys %aggr_disks ) {
        $sum = $sum + scalar @{ $aggr_disks{$key} };
    }
    if ( ( $sum + ( scalar @spares ) ) < $required_spares ) {
        logcomment("Sum of total number of drives in the aggregates are : $sum , which are less than required spares :: $required_spares, So NOT deleting any aggregates");
        return;
    }
    if ( scalar @aggregates == 1 ) {
        logcomment("Only one aggregate is present in the filer");
        vserver_delete( Node => $Node );
        aggregate_volume_delete( Node => $Node );
        return;
    } else {
        my $vserver_name = "vser_$FILER_C";
        try {
            my $name = NACL::STask::Vserver->find(
                command_interface => $Node,
                filter            => { vserver => $vserver_name },
            );
            $vser_aggr = $name->get_one_state_attribute("aggregate");
            logcomment("Vserver aggregate name is : $vser_aggr");
        }
        catch NACL::Exceptions::NoElementsFound with {
            logcomment("NO VSERVER found with the name $vserver_name");
        };
    }
    $sum = 0;
    my %bkp_hash = %aggr_disks;
    delete $bkp_hash{$vser_aggr};
    foreach my $aggr ( sort keys %bkp_hash ) {
        $sum = $sum + scalar @{ $bkp_hash{$aggr} };
        push( @delete_aggr, $aggr );
        if ( $sum >= $spares_needed ) {
            $flag_fill = 1;
            last;
        }
    }
    if ( $flag_fill == 1 ) {
        logcomment("Deleting the aggregates :: @delete_aggr");
        foreach my $aggr (@delete_aggr) {
            try {
                NACL::STask::Aggregate->purge(
                    command_interface => $Node,
                    aggregate         => $aggr,
                    nacltask_verify   => 1,
                );
            }
            catch NACL::Exceptions::NoElementsFound with {
                logcomment("DEBUG:Inside catch NACL::Exceptions::NoElementsFound with");
                logcomment("$FILER_C : CANNOT delete the aggregate $aggr ");
            }
            catch NACL::APISet::Exceptions::CommandFailedException with {
                try {
                    NACL::STask::Aggregate->purge(
                        command_interface => $Node,
                        aggregate         => $aggr,
                        nacltask_verify   => 1
                    );
                }
                catch NACL::APISet::Exceptions::CommandFailedException with {
                    logcomment("$FILER_C : CANNOT delete aggregate $aggr ");
                };
            }
            catch NACL::Exceptions::VserverHasVolumesOnAnotherAggregate with {
                logcomment("$FILER_C : CANNOT delete aggregate $aggr ");
            };
        }

    } else {
        vserver_delete( Node => $Node );
        aggregate_volume_delete( Node => $Node );
    }
}

######################################################
## Author :  Arjun Lavu
## Description : checks for the volumes and aggregates state
##				if they are off-line, it will try to make it on-line else it will delete them
##	Return value : no return value
#####################################################
sub check_aggr_vol_offline {
    my (%opts) = validate( @_, { Node => { type => OBJECT }, } );
    my $Node = $opts{Node};
    my $FILER_C       = $Node->name();
    my $Transit_obj_C = NACL::Transit->new( name => $FILER_C );
    my $filer_state_C = $Transit_obj_C->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );

    if ( $filer_state_C !~ /CLI/i ) {
        return;
    }
    logcomment("DEBUG:Checking the aggregate and volume states");
    try {
        my @aggrs = NACL::C::Aggregate->find(
            command_interface => $Node,
            filter            => { nodes => [$FILER_C], 'root' => 'false,-' }
        );
        foreach my $aggr (@aggrs) {
            my $aggregate = $aggr->get_one_state_attribute('aggregate');
            if ( $aggr->get_one_state_attribute('raidstatus') =~ /degraded/i ) {
                logcomment("$FILER_C : Aggregate : $aggregate is degraded, so deleting the aggregate");
                aggregate_volume_delete( Node => $Node, Aggr_array => [$aggregate] );
            } elsif ( $aggr->get_one_state_attribute('state') =~ /offline/ ) {
                logcomment("Aggregate is offline, onlinig the aggregate $aggregate ");
                try {
                    $aggr->online( 'method-timeout' => '1200' );
                    try {
                        my @vol_obj = $aggr->get_volumes();
                        foreach my $vol (@vol_obj) {
                            my $vol_name = $vol->get_one_state_attribute('volume');
                            logcomment("Volume name $vol_name");
                            my $vserver = $vol->get_one_state_attribute('vserver');
                            logcomment("Vserver name $vserver");
                            if ( $vol->get_one_state_attribute('state') =~ /offline/ ) {
                                logcomment("State of volume : $vol_name is offline, trying to make it online ");
                                try {
                                    $vol->online( 'method-timeout' => '1200' );
                                }
                                catch NACL::APISet::Exceptions::CommandFailedException with {
                                    logcomment("Could NOT online the volume $vol_name, so deleting the volume $vol_name");
                                    NACL::STask::Volume->purge(
                                        command_interface => $Node,
                                        volume            => $vol_name,
                                        vserver           => $vserver,
                                    );
                                };
                            }
                        }
                    }
                    catch NACL::APISet::Exceptions::CommandFailedException with {
                        logcomment("NO VOLUME found in the aggregate - $aggregate");
                        aggregate_volume_delete( Node => $Node, Aggr_array => [$aggregate] );
                    };
                }
                catch NACL::APISet::Exceptions::CommandFailedException with {
                    logcomment("Could NOT online the aggregate, so deleting the aggregate :: $aggregate");
                    aggregate_volume_delete( Node => $Node, Aggr_array => [$aggregate] );
                };
            } elsif ( $aggr->get_one_state_attribute('state') =~ /online/ ) {
                try {
                    my @vol_obj = $aggr->get_volumes();
                    foreach my $vol (@vol_obj) {
                        my $vol_name = $vol->get_one_state_attribute('volume');
                        logcomment("Volume name $vol_name");
                        my $vserver = $vol->get_one_state_attribute('vserver');
                        logcomment("Vserver name $vserver");
                        if ( $vol->get_one_state_attribute('state') =~ /offline/ ) {
                            logcomment("State of volume : $vol_name is offline, trying to make it online ");
                            try {
                                $vol->online( 'method-timeout' => '1200' );
                            }
                            catch NACL::APISet::Exceptions::CommandFailedException with {
                                logcomment("Could NOT online the volume $vol_name, so deleting the volume $vol_name");
                                NACL::STask::Volume->purge(
                                    command_interface => $Node,
                                    volume            => $vol_name,
                                    vserver           => $vserver,
                                );
                            };
                        }
                    }
                }
                catch NATE::BaseException with {
                    logcomment("NO VOLUME found in the aggregate :: $aggregate");
                    aggregate_volume_delete( Node => $Node, Aggr_array => [$aggregate] );
                };
            } elsif ( $aggr->get_one_state_attribute('state') !~ /online/ ) {
                logcomment("Aggregate is neither offline nor online, So deleting the aggregate $aggregate");
                aggregate_volume_delete( Node => $Node, Aggr_array => [$aggregate] );
            }
        }

    }
    catch NACL::Exceptions::NoElementsFound with {
        logcomment("$FILER_C : Non root aggregates are NOT found");

        # $AGGR_CNT->{$FILER_C} = 0;
    };
    sleep 30;
    try {
        my @agg_names;
        my @aggrs = NACL::C::Aggregate->find(
            command_interface => $Node,
            filter            => { nodes => [$FILER_C] }
        );
        foreach my $aggr (@aggrs) {
            push( @agg_names, $aggr->get_one_state_attribute('aggregate') );
        }
        if (@agg_names) {
            logcomment( "Total number of aggregates present in the filer : $FILER_C : are " . scalar @agg_names . " and the aggregates are @agg_names" );
            $AGGR_CNT->{$FILER_C} = scalar @agg_names;
        }
    }
    catch NACL::Exceptions::NoElementsFound with {
        $AGGR_CNT->{$FILER_C} = 0;
        logcomment("$FILER_C :: NO NON ROOT AGGREGATES found");
    };
}

###########################################################################
## Check for failed drives and unfail, after that zero spares
###########################################################################
sub unfail_disk_zero_spares {
    my (%opts) = validate( @_, { Nodes => { type => ARRAYREF }, } );
    my @Nodes = @{ $opts{Nodes} };
    my $filer_c       = $Nodes[0]->name();
    my $Transit_obj_C = NACL::Transit->new( name => $filer_c );
    my $filer_state_C = $Transit_obj_C->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    if ( $filer_state_C !~ /CLI/i ) {
        return;
    }
    my @subtest;
    foreach my $node (@Nodes) {
        my $FILER_C = $node->name();
        push( @subtest, subtest( \&spare_count_cmode, -runid, "spare_count_cmode_" . "$FILER_C", -bg, "--", Node => $node, ) );
    }
    Subtest::wait_finish( subtest => [@subtest] );
}

###########################################################################
### Disable firmware foreground background hammer
###########################################################################

sub disable_fg_bg_firmware_hammer {
    my (%opts) = validate( @_, { Nodes => { type => ARRAYREF }, } );
    my @Nodes = @{ $opts{Nodes} };
    foreach my $Node (@Nodes) {
        my $FILER_C = $Node->name();
        my $kernel;
        my $Api_Set_Obj;
        my $Transit_obj = NACL::Transit->new( name => $FILER_C );
        my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
        if ( $filer_state !~ /CLI/ ) {
            logcomment("Filer is NOT in file-system");
            next;
        } else {
            $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
            $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
            if ( $filer_state =~ /DBLADECLI/i ) {
                $kernel = $Api_Set_Obj->execute_raw_command( command => "version" );
            } elsif ( $filer_state =~ /CLI/i ) {
                $kernel = $Api_Set_Obj->execute_raw_command( command => "run local version" );
            }
        }
        ##disabling background firmwares
        NACL::C::Options->option(
            command_interface => $Node,
            'option-name'     => 'raid.background_disk_fw_update.enable',
            'option-value'    => 'off'
        );
        ##disabling foreground firmwares
        if ( $kernel !~ /<1d>/ ) {
            logcomment("The kernel present is non debug");
        } else {
            try {
                my $prompts = [ 'Are you sure you want to' => 'y' ];
                $Api_Set_Obj->execute_command( 'command' => "disk_fw_update -S", 'connectrec-match_table' => $prompts );
                sleep(60);
                logcomment("Firmware qualification download stopped ");
            }
            catch NACL::APISet::Exceptions::ResponseException with {
                logcomment("Could NOT stop firmware foreground.");
            };
        }
        ##hammer stopping
        $Api_Set_Obj->hammer_abort();
        sleep 20;
        $Api_Set_Obj->hammer_abort();
    }
}

sub get_config_status {
    my (%opts) = validate( @_, { Nodes => { type => ARRAYREF }, } );
    my @Nodes = @{ $opts{Nodes} };
    my ( %filer_details, $Api_Set_Obj, $output );
    foreach my $Node (@Nodes) {
        my $FILER_C     = $Node->name();
        my $Host        = host($FILER_C);
        my $Transit_obj = NACL::Transit->new( name => $FILER_C );
        my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
        logcomment("Filer : $FILER_C is in $filer_state state");
        if ( $filer_state =~ /PASS/i ) {
            $Transit_obj->set( 'change_state_timeout' => 7200 );
            $Transit_obj->change_state( to => "CLI" );
        }
        if ( $filer_state =~ /UP|CLI/i ) {
            $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
            $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
            $output = $Api_Set_Obj->execute_command( 'command' => 'sysconfig -v' );
        } elsif ( $filer_state =~ /MAINT/i ) {
            $Api_Set_Obj = NACL::APISet->new(
                hostobj   => $Host,
                category  => "Node",
                interface => "CLI",
                set       => "Maintenance"
            );
            $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
            $output = $Api_Set_Obj->execute_raw_command( 'command' => 'sysconfig -v' );
        }
        if ( $output =~ /System\s*ID\s*:\s*\S+\s*\((\S+)\)/ ) {
            $filer_details{$FILER_C}{system_name} = $1;
            logcomment("Filer Name : $1");
        }
        if ( $output =~ /System\s*ID\s*:\s*(\S+)/ ) {
            $filer_details{$FILER_C}{system_id} = $1;
            logcomment("Model-id :$1");
        }

        if ( $output =~ /partner\s*ID\s*:\s*(\S+)/ ) {
            $filer_details{$FILER_C}{partne_id} = $1;
            logcomment("Partner-id :  $1");
        }
        if ( $output =~ /partner\s*ID\s*:\s*\S+\s*\((\S+)\)/ ) {
            $filer_details{$FILER_C}{partner_name} = $1;
            logcomment("Partner filer name :  $1");
        }
        if ( $output =~ /System\s*Serial\s*Number\s*:\s*(\S+)/ ) {
            $filer_details{$FILER_C}{System_Serial_Number} = $1;
            logcomment("System Serial number : $1");
        }
        if ( $output =~ /System\s*Serial\s*Number\s*:\s*\S+\s*\((\S+)\)/ ) {
            $filer_details{$FILER_C}{System_Serial_Number_ID} = $1;
        }
        if ( $filer_details{$FILER_C}{system_name} ne $filer_details{$FILER_C}{System_Serial_Number_ID} ) {
            logcomment( "**WARNING** : Could NOT find filer name " . $filer_details{$FILER_C}{system_name} . " in System serial number" );
        }
        my $filer_name = $Host->{'hostname'};
        logcomment("filer name from tharnhost $filer_name");
        $filer_name =~ s/\"//gi;
        if ( $filer_details{$FILER_C}{'system_name'} !~ /^$filer_name$/ ) {
            storage_shw_initiators( Node => $Node );

            #logcomment("**FATAL** : Filer name in the configuration file is $filer_name , But the filer name found in sysconfig -v is :".$filer_details{$FILER_C}{system_name}. " which are different");
            #logcomment("Please check/correct the filer IP's and re-run the test again");
            #logresult('FATAL','Filer name in the configuration file is $filer_name , But the filer name found in sysconfig -v : '. $filer_details{$FILER_C}{system_name}.' are different');
        }
    }
    my ( $fail_1, $fail_2 );
    if ( $filer_details{ $Nodes[0]->name }{system_id} ne $filer_details{ $Nodes[1]->name }{partne_id} ) {
        logcomment( "**WARNING** : Filer name " . $Nodes[0]->name . " is NOT same as filer's " . $Nodes[1]->name . " partner ID" );
        $fail_1 = 1;
    }
    if ( $filer_details{ $Nodes[1]->name }{system_id} ne $filer_details{ $Nodes[0]->name }{partne_id} ) {
        logcomment( "**WARNING** : Filer name " . $Nodes[1]->name . " is NOT same as filer's " . $Nodes[0]->name . " partner id" );
        $fail_2 = 1;
    }
    if ( ($fail_1) && ($fail_2) ) {
        logcomment("**FATAL** : Filers are NOT connected to each other, Please re-run the test with the correct configuration");
        logresult( 'FATAL', 'FILERS ARE NOT CONNECTED TO EACH OTHER, Please re-run the test with the correct configuration' );
    }
    HA_config( API_Obj => $Api_Set_Obj );
}

###################################################################################################
## Author : aditis@netapp.com
## Subroutine will match the system name with filer name present in configuration file
###################################################################################################
sub storage_shw_initiators {
    my (%opts) = validate(
        @_,
        {
            Node => { type => OBJECT },

            #                        Nodes => { type=>ARRAYREF},
        }
    );
    my $Node    = $opts{Node};
    my $FILER_C = $Node->name();
    my $Host    = host($FILER_C);
    my ( $system_name, $Api_Set_Obj, $output );

    #     foreach my $Node(@Nodes){
    #            my $FILER_C = $Node->name();
    #           my $Host = host($FILER_C);
    my $Transit_obj = NACL::Transit->new( name => $FILER_C );
    my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    logcomment("Filer : $FILER_C is in $filer_state state");
    if ( $filer_state =~ /PASS/i ) {
        $Transit_obj->set( 'change_state_timeout' => 7200 );
        $Transit_obj->change_state( to => "CLI" );
    }
    if ( $filer_state =~ /UP|CLI/i ) {
        $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
        $output = $Api_Set_Obj->execute_command( 'command' => 'storage show initiators' );
    } elsif ( $filer_state =~ /MAINT/i ) {
        $Api_Set_Obj = NACL::APISet->new(
            hostobj   => $Host,
            category  => "Node",
            interface => "CLI",
            set       => "Maintenance"
        );
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
        $output = $Api_Set_Obj->execute_raw_command( 'command' => 'storage show initiators' );
    }
    foreach my $line ( split( /\n/, $output ) ) {
        if ( $line =~ /\(self\)/ ) {
            ( $line =~ /^(\S+)/ );
            $system_name = $1;
            logcomment("System name : $system_name");
        }
    }
    my $filer_name = $Host->{'hostname'};
    logcomment("Filer name from tharnhost : $filer_name");
    $filer_name =~ s/\"//gi;
    if ( $system_name !~ /^$filer_name$/ ) {
        logcomment("**FATAL** : Filer name in the configuration file is $filer_name ,but the filer name found in sysconfig -v is : $system_name  which are DIFFERENT");
        logcomment("Please check/correct the filer IP's and re-run the test again");
        logresult( 'FATAL', "Filer name in the configuration file is $filer_name ,BUT THE FILER NAME FOUND IN sysconfig -v IS : $system_name  WHICH ARE DIFFERENT" );
    }

    #       }
}

sub WaitSickDiskcopy {
    my (%opts) = validate(
        @_,
        {
            Node        => { type => OBJECT },
            failed_data => { type => SCALAR, default => undef, optional => 1 },
        }
    );
    my $Node        = $opts{Node};
    my $failed_data = $opts{failed_data} if ( defined $opts{failed_data} );
    my $timeout     = 288000;
    my $drcompleted = 0;
    my $curtime     = time;
    my $endtime     = $curtime + $timeout;
    my $FILER_C     = $Node->name();
    my $API_obj     = $Node->get_7m_or_nodescope_apiset();
    $API_obj->set_timeout( "connectrec-timeout" => 7200 );
    my @copying_disks;

    if ( !$failed_data ) {
        my $count;
        my $after = $API_obj->execute_command( "command" => "sysconfig -r" );
        foreach my $line ( split( /\n/, $after ) ) {
            if ( ( $line =~ /-> copy\s+(\S+)\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+\(copy\s+(\S+%)\s+completed\)/ ) || ( $line =~ /copy in progress/ ) ) {
                push( @copying_disks, $2 ) if ( defined $2 );
                $count++;
            }
        }
        if ($count) {
            my $mail_subject = "INFO : $parse_id : disks are copying ";
            $mail_subject = "INFO : $parse_id : disks are copying in check_filer_setup, killing the test" if ( $parse_id =~ /check_filer/i );

            my $mail_body = "#################################################################################################
## 
## Disk copy is under progress on FILER : $FILER_C.
## 
## User can stop execution of test by killing  to stop execution.
## sudo kill -9 $$
## 
#################################################################################################";
            if ( $EMAIL !~ /d/i ) {
                my %mail_params = (
                    HTML    => $mail_body,
                    Text    => $mail_body,
                    From    => $MAIL_FROM,
                    To      => $MAIL_TO,
                    Subject => $mail_subject,
                );

                $mail_params{HTML} = "
$mail_params{Text}<\\HTML>";
                my $mail = HTML::Mail->new(%mail_params);
                $mail->send() or logcomment("Config : Trouble sending mail");
            } else {
                logcomment("Email NOT sent because email set to debug by user.");
            }

            if ( $parse_id =~ /check_filer/i ) {
                logcomment("**FATAL** : $FILER_C : Disk copying found in CHECK_FILER_SETUP,so killing the test process");
                logresult( 'FATAL', "$FILER_C : DISK COPYING FOUND IN CHECK_FILER_SETUP,so killing the test process" );
            }
            if ( ( $pre_post_recon_copy =~ /pre/i ) || ( $pre_post_recon_copy =~ /post/i ) ) {
                logcomment("**WARNING** : $FILER_C : Disk copying found in $pre_post_recon_copy test ");
            }
        }
        $failed_data = $count;
    }

    logcomment("$FILER_C : Number of drives found re-constructing are : $failed_data") if ($failed_data);
    sleep 60;
    while ( ( $curtime < $endtime ) && ( $drcompleted < $failed_data ) ) {
        my $dsk_cpy_flag = 0;
        my $after = $API_obj->execute_command( "command" => "sysconfig -r" );
        foreach my $line ( split( /\n/, $after ) ) {
            if ( ( $line =~ /-> copy\s+(\S+)\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+\(copy\s+(\S+%)\s+completed\)/ ) || ( $line =~ /copy in progress/ ) ) {
                if ( defined($2) ) {
                    logcomment("$2 percent of Disk copying has completd on disk $1 ");
                }
                $dsk_cpy_flag = 1;
            }
        }

        if ( $dsk_cpy_flag == 0 ) {
            logcomment("Filer : $FILER_C : Sick Disk copy completed as per the output of sysconfig -r command");
            return 1;
        } else {
            sleep(600);
        }
        $curtime = time;
    } ## end while (($drcompleted < $numfaildr...

}

## himangin@netapp.com
## return 1 - PASS(all recontruction complete)
sub WaitReconstruct {
    my (%opts) = validate(
        @_,
        {
            Node          => { type => OBJECT },
            failed_parity => { type => SCALAR, default => undef, optional => 1 },
            MIXED_CONFIG  => { type => SCALAR, default => "0", optional => 1 },
        }
    );
    my $Node          = $opts{Node};
    my $failed_parity = $opts{failed_parity} if ( defined $opts{failed_parity} );
    my $MIXED_CONFIG  = $opts{MIXED_CONFIG};
    my $timeout       = 288000;
    my $drcompleted   = 0;
    my $curtime       = time;
    my $endtime       = $curtime + $timeout;
    my $FILER_C       = $Node->name();
    my $Api_Set_Obj   = $Node->get_7m_or_nodescope_apiset();
    my @copying_disks;
    $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );

    if ( !$failed_parity ) {
        my $count;
        my $after = $Api_Set_Obj->execute_command( 'command' => "sysconfig -r" );
        foreach my $line ( split( /\n/, $after ) ) {
            if ( ( $line =~ /reconstruction\s(.*)/ ) || ( $line =~ /\s*RAID group\s+(\S+)\s*\(reconstruction\s+(\S+%)\s(.*)/ ) || ( $line =~ /.*\(prefail\,\scopy\sin\sprogress/ ) ) {
                $count++;
            }
        }
        if ($count) {
            my $mail_subject = "INFO : $parse_id : disk re-construction is going on ";
            $mail_subject = "INFO : $parse_id : disk re-construction is going on in check_filer_setup ,so killing the test" if ( $parse_id =~ /check_filer/i );

            my $mail_body = "#################################################################################################
## 
## Disk copy is under progress on FILER : $FILER_C, NDATE will wait for completion.
## 
## 
## User can stop execution of test by killing  to stop execution.
## sudo kill -9 $$
## 
#################################################################################################";
            if ( $EMAIL !~ /d/i ) {
                my %mail_params = (
                    HTML    => $mail_body,
                    Text    => $mail_body,
                    From    => $MAIL_FROM,
                    To      => $MAIL_TO,
                    Subject => $mail_subject,
                );

                $mail_params{HTML} = "
$mail_params{Text}<\\HTML>";
                my $mail = HTML::Mail->new(%mail_params);
                $mail->send() or logcomment("Config : Trouble sending mail");
            } else {
                logcomment("Email NOT sent because email set to debug by user.");
            }
            if ( $parse_id =~ /check_filer/i ) {
                logcomment("**FATAL** : $FILER_C :Disk re-construction found in CHECK_FILER_SETUP, So killing the test process");
                logresult( 'FATAL', "$FILER_C : DISK RE-CONSTRUCTION FOUND IN CHECK_FILER_SETUP, So killing the test process" );
            }
            if ( ( $pre_post_recon_copy =~ /pre/i ) || ( $pre_post_recon_copy =~ /post/i ) ) {
                logcomment("**WARNING** : $FILER_C : Disk re-construction found in $pre_post_recon_copy test ");
            }
        }
        $failed_parity = $count;
    }
    logcomment("$FILER_C : Number of drives found re-constructing are : $failed_parity") if ($failed_parity);
    sleep 60;
    while ( ( $curtime < $endtime ) && ( $drcompleted < $failed_parity ) ) {

        #Only for SAS/BSAS configuration, while reconstruction is underway, issue statit -b, wait for 5 minutes and issue statit -e for each reconstruction.
        if ( $MIXED_CONFIG == 1 ) {
            logcomment("Issue statit -b ,wait for 5 minutes and issue statit -e for each reconstruction.");
            my $statit_b_output = $Api_Set_Obj->execute_raw_command( 'command' => "statit -b" );
            sleep(300);
            my $statit_e_output = $Api_Set_Obj->execute_raw_command( 'command' => "statit -e" );
            sleep(300);

        }
        my $recons_flag = 1;
        my $after = $Api_Set_Obj->execute_command( 'command' => "sysconfig -r" );
        foreach my $line ( split( /\n/, $after ) ) {
            if ( ( $line =~ /\s*RAID group\s+(\S+)\s*\(reconstruction\s+(\S+%)\s(.*)/ ) || ( $line =~ /.*\(prefail\,\scopy\sin\sprogress/ ) || ( $line =~ /reconstruction\s(.*)/ ) ) {
                if ( defined($2) ) {
                    logcomment("Filer - $FILER_C : $2 percent of reconstruction is completed on RAID group $1 ");
                }
                $recons_flag = 0;
            }
        }
        logcomment("The number of drives found reconstructing are $failed_parity");

        #Executing sysconfig -r command to check if reconstruction is still in progress
        if ( $recons_flag == 1 ) {
            logcomment("DEBUG : Filer : $FILER_C : Reconstruction completed as per the output of sysconfig -r command");
            return 1;
        } else {
            sleep 600;
        }
        $curtime = time;
    }    ##
} ## end sub WaitReconstruct

sub check_recons_sickdisk {
    my (%opts) = validate( @_, { Node => { type => OBJECT }, } );
    my $Node = $opts{Node};
    my $return = WaitSickDiskcopy( Node => $Node );
    my $result = WaitReconstruct( Node => $Node );
    if ( ( $return = 1 ) && ( $result = 1 ) ) {

        # logcomment("Reconstruction or disk copying completed successfully. Please carry on with the scrub process");
        return 1;
    } else {
        logcomment("Reconstruction or sick disk copying is NOT complete");
        return 0;
    }
}

sub check_path_ha {
    my (%opts) = validate( @_, { Node => { type => OBJECT }, } );
    my $Node = $opts{Node};
    my $FILER_C     = $Node->name();
    my $Transit_obj = NACL::Transit->new( name => $FILER_C );
    my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    my $return      = sysconfig_v_data( node => $Node );
    logcomment( "DEBUG:$FILER_C : Model No    : " . $return->{model} );
    logcomment( "$FILER_C : System Path : " . $return->{path} );

    if ( $return->{model} =~ /FAS2520|FAS2650/ ) {
        logcomment("Entry level Model with internal dirves found,  Skipping the check for \"System Storage Configuration\"");
    } elsif ( ( ( $return->{model} =~ /FAS2/ ) && ( $return->{path} =~ /single/i ) ) || ( ( $return->{model} =~ /^(FAS3)|(FAS6)|(FAS8)|(AFF)|(FAS9)/ ) && ( $return->{path} =~ /multi|Quad/i ) ) ) {
        logcomment("$FILER_C $return->{model} is a $return->{path} system");
    } else {
        logcomment("Filer state is : $filer_state ");
        if ( $filer_state =~ /CLI/ ) {
            my $Api_set_object = $Node->get_7m_or_nodescope_apiset;
            $Api_set_object->set_timeout( "connectrec-timeout" => 7200 );
            $Api_set_object->execute_raw_command( 'command' => "run local storage show disk -p" );
        }
        if ( $filer_state =~ /MAINT/ ) {
            my $Host        = host($FILER_C);
            my $Api_Set_Obj = NACL::APISet->new(
                hostobj   => $Host,
                category  => "Node",
                interface => "CLI",
                set       => "Maintenance"
            );
            $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
            $Api_Set_Obj->execute_raw_command( 'command' => "storage show disk -p" );
        }

        logcomment("**FATAL** : $FILER_C $return->{model} is a $return->{path} system. Non-entry level system must have multipath system and entry level system must have singlepath system, also external shelf for entry level is NOT supported. Exiting from the test");
        logresult( 'FATAL', "$FILER_C : NON-ENTRY LEVEL SYSTEM MUST HAVE MULTIPATH SYSTEM AND ENTRY LEVEL SYSTEM MUST HAVE SINGLEPATH SYSTEM, also EXTERNAL SHELF for ENTRY LEVEL is not SUPPORTED. Exiting from the test" );
    }

    if ( $filer_state =~ /CLI/ ) {
        my $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
        my $prompts_answers = [ "Do you want to continue" => 'y' ];
        my $return = $Api_Set_Obj->execute_raw_command( 'command' => 'cluster ha show' );
        if ( $return =~ /false/i ) {
            logcomment("**WARNING** : HA is NOT configured, setting the HA to true");
            $Api_Set_Obj->execute_raw_command( 'command' => 'cluster ha modify -configured true', 'connectrec-match_table' => $prompts_answers );
        }
    }
}

##############################
## himangin@netapp.com
## check for stsb or acron dongles
sub get_filer_check {
    my (%opts) = validate( @_, { Node => { type => OBJECT }, } );
    my $Node = $opts{Node};
    my $FILER_C        = $Node->name();
    my $Api_set_object = $Node->get_7m_or_nodescope_apiset;
    $Api_set_object->set_timeout( "connectrec-timeout" => 7200 );
    my $output = $Api_set_object->execute_command( 'command' => "help" );
    my $var = "";
    foreach my $line ( split( /\n/, $output ) ) {

        if ( $line =~ /stsb/i ) {
            logcomment("stsb command found");
            $var = 'stsb';
            return $var;
        } elsif ( $line =~ /acron/i ) {
            logcomment("Acron command found");
            $var = 'acron';
            return $var;
        }
    }
}

#######################################################################################################
# Author - priya3@netapp.com
# Description - power cycle count and phy change count for Cmode/7mode
# Usage - Mandatory paramanter - Node
# Supported Mode - CMode/7mode (CLI/UP)
# Return - hash ref
#######################################################################################################
sub get_phy_state {
    my (%opts) = validate( @_, { Node => { type => OBJECT }, } );
    my $Node = $opts{Node};
    my $FILER_C = $Node->name();
    my $Api_Set_Obj;

    ## Refreshing the node
    $Node->refresh_command_interface();
    my $Transit_obj = NACL::Transit->new( name => $FILER_C );

    #my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    my $filer_state = $Transit_obj->get_state(
        'timeout'           => 86400,
        'get_state_timeout' => 86400,
        'maxidle'           => 86400
    );
    if ( $filer_state =~ /MAINT/gi ) {
        my $Host = host($FILER_C);
        $Api_Set_Obj = NACL::APISet->new(
            hostobj   => $Host,
            category  => "Node",
            interface => "CLI",
            set       => "Maintenance"
        );
    } elsif ( $filer_state =~ /(CLI|UP)/gi ) {
        $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
    }
    $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    my $output       = $Api_Set_Obj->execute_command( 'command' => "sasadmin expander_phy_state", 'timeout' => 600 );
    my $power_struct = {};
    my $shlfid       = "";
    my %convert      = ( '0' => '00', '1' => '01', '2' => '02', '3' => '03', '4' => '04', '5' => '05', '6' => '06', '7' => '07', '8' => '08', '9' => '09' );
    my @DISABLED;
    my $shfid = "";

    foreach my $outp ( split( /\r*\n/, $output ) ) {
        $outp =~ s/^\s+|\s+$//g;
        my $bay;
        my $phy;
        if ( $outp =~ /Expander phy state on\s+(\S+)\s+/ ) {
            $shlfid = $1;
            if ( $shlfid =~ /(\S+)\.(\S+)/ ) {
                my $first  = $1;
                my $second = $2;
                if ( $2 =~ /^\d$/ ) {
                    $shlfid = $first . "." . $convert{$second};
                    $shfid  = $convert{$second};
                } else {
                    $shlfid = $first . "." . $second;
                    $shfid  = $second;
                }
                $power_struct->{$shlfid}->{Shelfid} = $shlfid;
            }
        } elsif ( $outp =~ /^(\d+)\/(\d+)\s+(Disabled\/PHCHG|Disabled\/PCD)\s+\S+/i ) {
            push( @DISABLED, "$shlfid.$2" );
        } elsif ( $outp =~ /^(\d+)\/(\d+)\s+\S+\s+\S+\s+\S+\s+(\d+)\s+\d+\s+\d+\s+\d+\s+\d+\s+\d+\s+\d+\s+\d+\s+(\d+)/ ) {
            $phy                                                    = $1;
            $bay                                                    = $2;
            $power_struct->{$shlfid}->{$bay}->{'Power cycle count'} = $3;
            $power_struct->{$shfid}->{$bay}->{'Power cycle count'}  = $3;
            $power_struct->{$shlfid}->{$bay}->{'Phy change count'}  = $4;
        } else {
            next;
        }
    }

    # logcomment("DISABLED drives :: @DISABLED and pi $parse_id") if(@DISABLED);
    if ( (@DISABLED) && ( $parse_id =~ /check_filer/i ) ) {
        my @drives_disk_show_a;
        foreach my $drv ( @{ disk_show_drive_maint( API_Obj => $Api_Set_Obj, Filer => $FILER_C )->{'driveA'} } ) {
            if ( $drv =~ /(L|P)\d+$/ ) {
                $drv =~ s/(L|P)\d+$//gi;
                push( @drives_disk_show_a, $drv );
            }
        }

        # logcomment("disk show -a @drives_disk_show_a");
        my @Common_drives = grep { /\S/ } intersection( [ sort @DISABLED ], [ sort @drives_disk_show_a ] );
        if (@Common_drives) {
            my $dsks = _print_array( \@Common_drives );
            logcomment( "**WARNING** : Disabled drives which belongs to filer : $FILER_C : are " . scalar @Common_drives . " and the drives are:\n" . $dsks );
        }
    }
    return ($power_struct);
}
##############################################################
## Author: Arjun Lavu, Balaji A
## Description: This subroutine checks for the failed drives present in the node.
##              If failed drives are found, terminates the execution of test.
##              Supports both CLI & Maintenance mode
##              Command: CLI - NACL method NACL::C::Disk->find
##                       MAINT - disk show -v
##@change - BURT1041406 - abalaji
##############################################################
sub report_failed_drives {
    my (%opts) = validate( @_, { Node => { type => OBJECT }, } );
    my $Node = $opts{Node};
    my $FILER_C = $Node->name();
    my ( $failed, $failed_u, $sysconfig_flg ) = ( 0, 0, 0 );
    my @broken;
    my @broken_disk_o;
    my @broken_disk_U;
    my $Transit_obj = NACL::Transit->new( name => $FILER_C );
    my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );

    if ( $filer_state =~ /CLI|UP/ ) {    #BURT1041406 - abalaji
        try {
            my %hash = ( filter => { 'container-type' => "broken", 'owner' => $FILER_C } );
            my @broken_obj = NACL::C::Disk->find(
                command_interface => $Node,
                %hash,
            );
            foreach my $state_obj (@broken_obj) {
                my $free_disk = $state_obj->disk();
                if ( $free_disk =~ /(\S+)\:(\S+)/ ) {
                    $free_disk = $2;
                }
                push( @broken_disk_o, $free_disk );
            }

        }
        catch NACL::Exceptions::NoElementsFound with {

            # logcomment("$FILER_C : NO FAILED DISKS FOUND FOR THE FILER");
            $failed = 1;
        };

        {
            try {
                my %hash = ( filter => { 'container-type' => "broken", 'owner' => "-" } );
                my @broken_obj = NACL::C::Disk->find(
                    command_interface => $Node,
                    %hash,
                    allow_empty => 1,
                );
                foreach my $state_obj (@broken_obj) {
                    my $free_disk = $state_obj->disk();
                    if ( $free_disk =~ /(\S+)\:(\S+)/ ) {
                        $free_disk = $2;
                    }
                    push( @broken_disk_U, $free_disk );
                }
            }
            catch NACL::Exceptions::NoElementsFound with {

                # logcomment("$FILER_C : NO UNKNOWN BROKEN DISKS FOUND FOR THE FILER");
                $failed_u = 1;
            };
            $failed_u = 1 if ( !( scalar @broken_disk_U ) );

            #push( @broken, @broken_disk_U ) if ( scalar @broken_disk_U );
        }

        my @broken_disks_sysconfig = ();
        my $Api_Set_Obj            = $Node->get_7m_or_nodescope_apiset();
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
        my $response_obj = $Api_Set_Obj->sysconfig( "verbose" => 1 );
        my $sysconfig_out = $response_obj->get_raw_output();
        chomp( my @sysconf_lines = split( /\r?\n/, $sysconfig_out ) );
        my ( $drv, $model, $fw, $size, $bytes_sec, $state, $adapter );
        foreach my $line (@sysconf_lines) {
            if ( $line =~ /\s*\S+\s*:\s*SAS Host Adapter\s*(\S+)\s*\(.*\s*\\)/i ) {
                $adapter = $1;
            } else {
                ( $drv, $model, $fw, $size, $bytes_sec, $state ) = $line =~ /\s*(\d+\.\w+)\s*\:\s*\S+\s*(\S+)\s*(\S+)\s*(\S+)\s*\((.*)\)\s*\((.*)\)\s*/i;
                logcomment("drv : $drv Model : $model FW : $fw Size : $size Bytes_sec : $bytes_sec State : $state") if ( $state =~ /Failed/i );
            }
            my $drive = "$adapter.$drv" if ( $drv && $adapter );
            push( @broken_disks_sysconfig, $drive ) if ($drive);
        }
        $sysconfig_flg = 1 if ( !( scalar @broken_disks_sysconfig ) );

        ## Assigning the broken disks to array @broken
        if ( scalar(@broken_disk_o) ) {
            @broken = @broken_disk_o;
        } elsif ( scalar(@broken_disk_U) ) {
            @broken = @broken_disk_U;
        } elsif ( scalar(@broken_disks_sysconfig) ) {
            @broken = @broken_disks_sysconfig;
        }

        ## return nothing if there are no failed drives
        if ( ($failed) && ($failed_u) && ($sysconfig_flg) ) {
            logcomment("$FILER_C : NO UNKNOWN BROKEN DISKS found for the filer");
            return;
        }
    }

    #---------------BURT1041406 - abalaji-----------------#
    elsif ( $filer_state =~ /MAINT/ ) {
        logcomment("Checking for failed disk - Maintenance mode");
        my $result = disk_show_v( Node => $Node );
        my @res_disks = keys $result;
        foreach (@res_disks) {
            if ( $result->{$_}->{POOL} =~ /FAILED/ ) {
                push( @broken, $_ );
            }
        }
    }

    #-----------------------------------------------------#

=head
	foreach my $boken (@broken){
		
		try{
			NACL::C::StorageDisk->unfail( command_interface => $Node,
													disk => $boken,
													spare => "true",
													'method-timeout'  => 1200);
			sleep 30;
		}catch NACL::APISet::Exceptions::CommandFailedException with {
			try{
				NACL::C::StorageDisk->unfail( command_interface => $Node,
                                                disk => $boken,
												'method-timeout'  => 1200);
				sleep 20;							
			}catch NACL::APISet::Exceptions::CommandFailedException with {
				# logcomment("**WARNING** : $FILER_C : Couldn't unfail the disk $boken");
			};
		}catch NATE::BaseException with {
			logcomment("Unfailing the drive is interupted, may be because of timeout issue, So trying again to unafail after 5 minutes");
			sleep 300;
			try{
				NACL::C::StorageDisk->unfail( command_interface => $Node,
													disk => $boken,
													spare => "true",
													'method-timeout'  => 1200);
			}catch NATE::BaseException with {
				logcomment("**WARNING** : Unfailing the drive $boken is not successfull");
			};
		};												
	}
	sleep 120;
	
	@broken=();
	logcomment("$FILER_C : Checking again for the failed drvies");
	try{
		my %hash = (filter => {'container-type' => "broken",'owner' => $FILER_C});
		my @broken_obj = NACL::C::Disk->find(
						command_interface => $Node,
						%hash,
					);
		foreach my $state_obj (@broken_obj){
			my $free_disk = $state_obj->disk();
			if ($free_disk =~ /(\S+)\:(\S+)/){
				$free_disk = $2;
			}
			push( @broken,$free_disk);
		}
		
		
	}catch NACL::Exceptions::NoElementsFound with{
		# logcomment("$FILER_C :: No failed disks found in the filer");
	};
	{
		my @broken_disk_U;
		try{
			my %hash = (filter => {'container-type' => "broken",'owner' => "-"});
			my @broken_obj = NACL::C::Disk->find(
								command_interface => $Node,
								%hash,
								allow_empty => 1,
							);
			foreach my $state_obj (@broken_obj){
				my $free_disk = $state_obj->disk();
				if ($free_disk =~ /(\S+)\:(\S+)/){
					$free_disk = $2;
				}
				push( @broken_disk_U,$free_disk);
			}
		}catch NACL::Exceptions::NoElementsFound with{
			# logcomment("$FILER_C : No unknowun broken disks found for the filer");
			$failed_u = 1;
		};
		push(@broken,@broken_disk_U) if(scalar @broken_disk_U);
	}
=cut	

    if (@broken) {

        #my $dsks = _print_array( \@broken );
        #logcomment( "**FATAL** : $FILER_C : Number of FAILED disks are " . scalar @broken . " and the disks are: " . $dsks );
        if ( $filer_state =~ /CLI|UP/ ) {    #BURT1041406 - abalaji
            my $output;
            my @broken_dsk;
            my $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
            $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
            $output = $Api_Set_Obj->execute_raw_command( 'command' => "run local disk show -v", 'timeout' => 600 );
            foreach my $disk ( split( "\n", $output ) ) {
                if ( $disk =~ /^(\d.\.\d.+\.\w*\S)\s.*.*(FAILED|BROKEN)/ig ) {
                    push( @broken_dsk, $1 );
                }
            }
            my @disk_list = @broken_dsk;
            @broken_dsk = ();
            foreach my $dsk (@disk_list) {
                if ( $dsk =~ /(P\d+)$/ ) {
                    next;
                }
                push( @broken_dsk, $dsk );
            }
            @broken = ();
            @broken = @broken_dsk;
            my $dsks = _print_array( \@broken );

            #BURT-1150240 - kiranp1
            if ( scalar @broken ) {
                logcomment( "**FATAL** : $FILER_C : Number of FAILED disks are " . scalar @broken . " and the disks are:" . $dsks );
            }
            foreach my $disk (@broken) {
                $output = $Api_Set_Obj->execute_raw_command( 'command' => "system node run -node $FILER_C -command \" priv set -q test; scsi dumpfailures -s $disk\"", 'timeout' => 600 );
                logcomment("Failure information bytes read from disk $disk: $output");
            }
        }

        #---------------BURT1041406 - abalaji-----------------#
        elsif ( $filer_state =~ /MAINT/ ) {
            my $Host        = host($FILER_C);
            my $Api_Set_Obj = NACL::APISet->new(
                hostobj   => $Host,
                category  => "Node",
                interface => "CLI",
                set       => "Maintenance"
            );
            $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
            foreach my $disk (@broken) {
                my $output = $Api_Set_Obj->execute_raw_command( 'command' => "scsi dumpfailures $disk", 'timeout' => 600 );
                logcomment("Failure information bytes read from disk $disk: $output");
            }
        }

        #-----------------------------------------------------#
        my $mail_subject = "INFO : FAILED drives are present in the filer $FILER_C";
        my $mail_body    = "#################################################################################################
## 
## FAILED drives are present in the filer $FILER_C
## 
## Number of failed drives are " . scalar @broken . " and the drives are @broken" . "
##
## Stopping the test suite execution : $STEST_FILE
##
#################################################################################################";
        if ( $EMAIL !~ /d/i ) {
            my %mail_params = (
                HTML    => $mail_body,
                Text    => $mail_body,
                From    => $MAIL_FROM,
                To      => $MAIL_TO,
                Subject => $mail_subject,
            );
            $mail_params{HTML} = "
$mail_params{Text}<\\HTML>";
            my $mail = HTML::Mail->new(%mail_params);
            $mail->send() or logcomment("CONFIG : Trouble sending mail");
        } else {
            logcomment("Email NOT sent because email set to debug by user.");
        }
        logcomment("**FATAL** :FAILED DRIVES are present in the filer $FILER_C, so killing the test suite : $STEST_FILE");
        logresult( 'FATAL', "FAILED DRIVES ARE PRESENT IN THE FILER $FILER_C, so killing the test suite : $STEST_FILE" );
    }
}

######################################################
## Author :  Arjun Lavu
## Description : Prints the test dependent values
######################################################
sub print_test_variables {
    my $Home = $ENV{HOME};
    my $mini_disk_present;
    $/ = undef;
    open( FH, "$Home/NDATE/TEST_LISTS/$STEST_FILE" );
    my $test_suite_file = ;
    $/ = "\n";
    close(FH);
    my $params = NATE::ParamSet->new( global => 1 );
    my $LOGDIR = $params->get( 'LOGDIR', default => undef );
    my $actual_log_dir;

    if ( $LOGDIR =~ /\/HDD/ ) {
        ($actual_log_dir) = $LOGDIR =~ /(\S+)\/HDD/;
    } else {
        $actual_log_dir = $LOGDIR;
    }
    opendir( READDIR, "$actual_log_dir" );
    my @thefiles = readdir(READDIR);

    # logcomment("Total number of files present are : @thefiles");
    foreach my $file (@thefiles) {
        if ( $file =~ /check_filer_setup(.*?)\.log/ ) {
            $/ = undef;
            open( FH1, "$actual_log_dir\/$file" ) || logcomment("CANNOT open file $actual_log_dir\/$file");
            my $data = ;
            $/ = "\n";
            if ( $data =~ /is\s+configured\s+as\s+a\s+\S+\s+minidisk/igs ) {
                $mini_disk_present = 1;
            }
            last;
        }
    }
    close(FH1);
    if ( $parse_id =~ /_Hmr_Scrub/ ) {
        my ($priority) = $test_suite_file =~ /SCRUB_PRIORITY_LEVEL\s*\=\s*(\S+)/;
        logcomment("Scrub priority level is : $priority");
    } elsif ( $parse_id =~ /Disk_FW_DL_Dev_Rst/ ) {
        my ($RESETVALUE) = $test_suite_file =~ /RESETVALUE\s*\=\s*(\S+)/;
        logcomment("Device reset value is : $RESETVALUE");
    } elsif ( $parse_id =~ /Hmr_Adp_Rst/ ) {
        my ($RESETVALUE) = $test_suite_file =~ /RESETVALUE\s*\=\s*(\S+)/;
        logcomment("Device reset value is : $RESETVALUE");
    }
    if ( $parse_id =~ /check_filer/ ) {
        my %modes = ( 1 => 'FILE_SYSTEM', 2 => 'MAINTENANCE', 'F' => 'FILE_SYSTEM', 'M' => 'MAINTENANCE' );
        if ( $test_suite_file =~ /Filer_mode\s*\=\s*(\S+)/i ) {
            my $filer_mode = $1;
            logcomment( "Required filer mode is : " . $modes{ uc($filer_mode) } );
        }
        if ( $BOOT_MODE !~ /1|5/ ) {
            logcomment("User selected boot_mode is : $BOOT_MODE");
        }
    } else {
        my $str;
        my %wait_time = ( '1' => '10%', '2' => '50%', '3' => '100%', '4' => '95%' );
        if ( $wait_time{$TEST_WAIT_TIME} ) {
            $str = "TEST WAIT-TIME IS : " . $wait_time{$TEST_WAIT_TIME};
        } else {
            $str = "TEST WAIT-TIME IS : 100%\n";
        }
        if ($mini_disk_present) {
            $str = $str . "\n" . "MINI DISKS ARE PRESENT IN THE FILER-SETUP";
        } else {
            $str = $str . "\n" . "MINI DISKS ARE NOT PRESENT IN THE FILER-SETUP";
        }
        logcomment("$str");
    }
}

##############################################################################################################################
### Arjun Lavu
## description: subroutine will handle unknown prompts during logging-in the filer for the first time
##############################################################################################################################
sub handle_prompts {
    my (%opts) = validate( @_, { Node => { type => OBJECT }, } );
    my $Node = $opts{Node};
    my $FILER_C     = $Node->name();
    my $filer_con   = connect("$FILER_C#console");
    my $Transit_obj = NACL::Transit->new( name => $FILER_C );
    my $filer_state;
    try {
        $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    }
    catch NACL::Transit::Exceptions::Timeout with {
        logcomment("Could NOT get the filer prompt with in the timeout, so attempting ctrl_c on the console of the filer $FILER_C");
        say( $filer_con, "\cC", "::>|::\*>|\*>", -noprompt, -timeout, 300, -ok );
    };
    if ( $filer_state =~ /TAKEN_OVER_WAITING/ ) {
        my $current;
        my $partner;
        my %nodes_filer;
        my @temp_nodes = NACL::C::Node->find();    # Find Nodes/Filers used in the test, Based on FILER param.
        foreach my $Node (@temp_nodes) {
            my $FILER_C = $Node->name();
            $nodes_filer{$FILER_C} = $Node;
        }
        @temp_nodes = values(%nodes_filer);
        foreach my $Node (@temp_nodes) {
            my $FILER = $Node->name();
            if ( $FILER =~ /^$FILER_C$/ ) {
                $current = $Node;
            } else {
                $partner = $Node;
            }
        }
        giveback_takeover( Node => $current, Partner => $partner );
    }
    try {
        $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
        if ( $filer_state !~ /CLI|MAINT|FIRMWARE|HALTED|BOOT_MENU|CFE_BANNER|LOADER_BANNERFIRMWARE/ ) {
            NACL::Transit::Exceptions::Timeout->throw("throwing exception ");
        }
    }
    catch NACL::Transit::Exceptions::Timeout with {
        logcomment("Filer - $FILER_C state is ::: $filer_state");
        try {
            logcomment("Again trying to get the prompts");
            my $Server        = new Server( no_cli => 1 );
            my $host          = Tharn::host($FILER_C);
            my $passwd        = $host->{'default_password'};
            my $prompt_array  = $host->prompt_fw();
            my $prompts       = join( "|", @$prompt_array );
            my $prompt_fw     = "($prompts)";
            my @filer_working = $Server->servers();
            $Server->set_execution_server( -Server => $FILER_C );
            my $ignore_strings = [ "MADIMM\\d+->", "DIMM\\d+->", "^T>" ];
            $Server->console(
                cmd                        => "\cC",
                additional_prompts_timeout => 600,
                ignore                     => $ignore_strings,
                additional_prompts         => {
                    "$prompt_fw"               => "FINAL_PROMPT",
                    "::>"                      => "FINAL_PROMPT",
                    ".*>.*"                    => "FINAL_PROMPT",
                    ".*Enter it again.*"       => "$passwd",
                    ".*Password.*"             => "$passwd",
                    ".*Enter a new password.*" => "$passwd",
                    ".*New password.*"         => "$passwd",
                    ".*Continue with boot.*"   => "yes",
                    ".*login.*"                => "admin",
                    ".*Selection (1-8)?.*"     => '5',
                }
            );
        }
        catch NATE::BaseException with {
            logcomment("$FILER_C : Could NOT get the filer prompt");
        };
    };
}

######################################################
## Author :  aditis@netapp.com
## Description : checks for scsi inquiry on each disk
##
###################################################

sub scsi_inquiry_cmode {
    my (%opts) = validate(
        @_,
        {
            API_OBJ => { type => OBJECT },
            Node    => { type => OBJECT }
        }
    );
    my $Node      = $opts{Node};
    my $API_OBJ   = $opts{API_OBJ};
    my $FILER_C   = $Node->name();
    my @disk_list = list_of_disk( Node => $Node );
    my @dsk_arr;
    my $d_type;

    my $disk_type = NACL::CS::StorageDisk->fetch(
        command_interface => $Node,
        requested_fields  => ['type']
    );
    $d_type = $disk_type->type();
    foreach my $disk (@disk_list) {
        $disk =~ s/(^\s+)|(\s+$)//ig;
        next if ( $disk !~ /\S/ );
        push( @dsk_arr, $disk );
    }
    my @disk_array = grep { ( ( $_ !~ /P\d+$/ ) && ( $_ =~ /\S/ ) ) } @dsk_arr;

    my $disk_length = @disk_array;
    my $test_result = 0;
    my $dsks        = _print_array( \@disk_array );
    $API_OBJ->set_timeout( "connectrec-timeout" => 7200 );
    logcomment( "DEBUG:Disks used for executing storage show command are $disk_length and disks are:\n" . $dsks );
    foreach my $dsk (@disk_array) {
        if ( $disk_length > 0 ) {
            my $output = $API_OBJ->execute_command( 'command' => "storage show disk -a $dsk" );
            my $after  = $API_OBJ->execute_command( 'command' => "" );
            my $output = $after . $output;
            my $flag   = 0;
            my $flag1  = 0;
            my $prod_id;
            foreach my $line ( split( /\n/, $output ) ) {

                if ( $line =~ /Vendor:\s*(\S+)\s*/ ) {
                    if ( $1 =~ /NETAPP/ ) {
                        logcomment("Vendor of disk $dsk is Netapp");
                        $test_result = 0;
                    } else {
                        logcomment("**WARNING** : $FILER_C : Vendor of disk $dsk is $1");
                    }
                }
                if ( $line =~ /Model:\s*(\S+)\s*/ ) {
                    $prod_id = $1;
                    logcomment("Model of disk $dsk is $prod_id");
                    $flag1 = 1;
                }
                if ( $line =~ /Rev:\s*(\S+)/ ) {
                    if ( ( my $revision = $1 ) =~ /NA|NQ|NT|NE|NX\d\d$/ ) {
                        logcomment("Revision of disk $dsk is $revision");
                        $test_result = 0;
                    } else {
                        logcomment("**WARNING** : $FILER_C : Revision $revision for disk $dsk is NOT starting with any of the NA|NQ|NT|NE|NX");
                    }
                }

                #                if (($line =~ /vendor\s*unique\s*\"(\w+)\s*/) || ($line =~ /vendor\s*unique\s*\"\s*(\w+)\s*/))
                #		if ($line =~ /vendor\s*unique\s*\"\s*(.*)\"/gs)
                if ( $line =~ /RPM:\s*(\d+)/ ) {
                    logcomment("RPM value of disk $dsk is $1");
                    $flag        = 1;
                    $test_result = 0;
                }
            }
            if ( $flag1 != 1 ) {
                logcomment("**WARNING** : $FILER_C : Model is NOT present for disk $dsk");
            }
            if ( !( $d_type =~ /SSD/ ) ) {
                if ( $flag != 1 ) {
                    logcomment("**WARNING** : $FILER_C : RPM value is NOT present for disk $dsk");
                }
            }
        } else {
            $test_result = 1;
            logcomment("**FATAL**:$FILER_C: NO DISK available for testing, exiting from rest of the test case");

        }
    }
    return $test_result;
}

##############################################################
## Author : himangin@netapp.com
## Subroutine handles CMODE giveback and takeover states of the nodes making them up
## String "pass" is returned if both the nodes are found up else "fail"
##############################################################
sub giveback_takeover {
    my (%opts) = validate(
        @_,
        {
            Node    => { type => OBJECT },
            Partner => { type => OBJECT }
        }
    );
    my $Node    = $opts{Node};
    my $Partner = $opts{Partner};
    my ( $flag1, $flag2 );
    my $pass = "pass";
    my $fail = "fail";
    logcomment("DEBUG:Checking if the nodes are in giveback and takeover");
    my @Nodes;
    push( @Nodes, $Node, $Partner );
    my ( $takeoverA, $givebackA, $takeoverB, $givebackB );
    my $Server = new Server( no_cli => 1 );
    ##### Checking if the filer is in  loader or maint state
    foreach my $Node (@Nodes) {
        my $FILER_C        = $Node->name();
        my $Host           = host($FILER_C);
        my $Home           = $ENV{HOME};
        my $ignore_strings = [ "MADIMM\\d+->", "DIMM\\d+->", "^T>" ];
        my $prompt_array   = $Host->prompt_fw();
        my $prompts        = join( "|", @$prompt_array );
        my $prompt_fw      = "($prompts)";
        my $filer_info     = `cat $Home/NDATE/FILER_INFO/$FILER_C`;
        my $passwd;
        ($passwd) = $filer_info =~ /default_password\s*=\s*(\S+)\s*/ig;

        # logcomment("password is $passwd");
        my $transit_obj = NACL::Transit->new( name => $Host );
        my $filer_state = $transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
        if ( $filer_state =~ /MAINT/i ) {
            logcomment("Node is found in $filer_state state, changing it to cli state");
            $transit_obj->set( 'change_state_timeout' => 7200 );
            $transit_obj->change_state( to => "FIRMWARE" );
        }
        $filer_state = $transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
        if ( $filer_state =~ /FIRMWARE/i ) {
            logcomment("Node is found in $filer_state state, trying to change the state to CLI");
            try {
                $transit_obj->set( 'change_state_timeout' => 7200 );
                $filer_state = $transit_obj->change_state( to => "CLI" );
            }
            catch NACL::Transit::Exceptions::Timeout with {
                logcomment("Expected: Caught a Timeout Exception");
                $filer_state = $transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
            }
            catch NACL::Transit::Exceptions::TransitException with {
                my $exception_object = shift;

                #logcomment("Exception is of type: " . ref ($exception_object));
                #logcomment("Error text is: " . $exception_object->text());
                logcomment("Filer state could NOT be changed to cli");
            };
            sleep 10;
            my $filer_state = $transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
            if ( $filer_state =~ /USERNAME|PASSWORD|FIRMWARE/i ) {
                logcomment("Filer state could NOT be changed");
                return $fail;
            }
            if ( $filer_state =~ /CLI/i ) {
                logcomment("Node $FILER_C is Up and running");
            } elsif ( $filer_state =~ /TAKEN_OVER_WAITING/ ) {
                logcomment("Node $FILER_C is in $filer_state state");
            }
        }
    }
    my $FILER_A       = $Node->name();
    my $FILER_B       = $Partner->name();
    my $HostA         = host($FILER_A);
    my $transit_obj   = NACL::Transit->new( name => $HostA );
    my $filer_state_A = $transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    if ( $filer_state_A =~ /(UP|CLI)/i ) {
        logcomment("Node $FILER_A is up and running");
        $takeoverA = 1;
    } elsif ( $filer_state_A =~ /TAKEN_OVER_WAITING/ ) {
        logcomment("Node $FILER_A is in $filer_state_A state");
        $givebackA = 1;
    } else {
        logcomment("Node $FILER_A is in $filer_state_A state");
    }
    my $ignore_strings = [ "MADIMM\\d+->", "DIMM\\d+->", "^T>" ];
    my $HostB          = host($FILER_B);
    my $transit_obj    = NACL::Transit->new( name => $HostB );
    my $filer_state_B  = $transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    if ( $filer_state_B =~ /(UP|CLI)/i ) {
        logcomment("Partner node $FILER_B is up and running");
        $takeoverB = 1;
    } elsif ( $filer_state_B =~ /TAKEN_OVER_WAITING/ ) {
        logcomment("Partner node $FILER_B is in $filer_state_B state");
        $givebackB = 1;
    } else {
        logcomment("Patner node $FILER_B is in $filer_state_B state");
    }
    if ( ($takeoverA) && ($givebackB) ) {
        logcomment("DEBUG:Execute storage failover on node $FILER_A");
        $Server->set_execution_server( -Server => $FILER_A );
        eval {
            $Server->console(
                cmd                        => "set test",
                additional_prompts_timeout => 3600,
                additional_prompts         => {
                    ".*Do you want to continue.*" => "y",
                    ".*::*>.*"                    => "FINAL_PROMPT",
                    ignore                        => $ignore_strings,

                    #              "\:\:\.*\>" => "FATAL_PROMPT",
                    #                                "\:\:\>" => "FATAL_PROMPT",
                    #                               ".*Error:.*" => "FATAL_PROMPT",
                    #                              ".*is not a recognized command.*" => "FATAL_PROMPT",
                    #                             "$prompt_fw" => "FINAL_PROMPT"
                }
            );
        };
        if ($@) {
            logcomment("Inside Eval");
        }
        $Server->console( cmd => "storage failover giveback -ofnode $FILER_B" );
        sleep 600;
    } elsif ( ($givebackA) && ($takeoverB) ) {
        logcomment("DEBUG:Execute storage failover on partner $FILER_B");
        $Server->set_execution_server( -Server => $FILER_B );
        eval { $Server->console( cmd => "set test", additional_prompts_timeout => 3600, additional_prompts => { ".*Do you want to continue.*" => "y", ignore => $ignore_strings, ".*::*>.*" => "FINAL_PROMPT", } ); };
        if ($@) {
            logcomment("Inside Eval");
        }
        $Server->console( cmd => "storage failover giveback -ofnode $FILER_A" );
        sleep 600;
    }
    my $transit_obj = NACL::Transit->new( name => $HostA );
    my $filer_state_A = $transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    if ( $filer_state_A =~ /CLI|USERNAME|PASSWORD/i ) {
        $transit_obj->set( 'change_state_timeout' => 7200 );
        $transit_obj->change_state( to => "CLI" );
        my $filer_state_A = $transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
        if ( $filer_state_A =~ /(UP|CLI)/i ) {
            logcomment("Node $FILER_A is up and running");
            $flag1 = 1;
        } else {
            logcomment("Node $FILER_A is in $filer_state_A state");
        }
    } else {
        logcomment("Node $FILER_A is in $filer_state_A state");
    }
    my $transit_obj = NACL::Transit->new( name => $HostB );
    my $filer_state_B = $transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    if ( $filer_state_B =~ /CLI|USERNAME|PASSWORD/i ) {
        $transit_obj->set( 'change_state_timeout' => 7200 );
        $transit_obj->change_state( to => "CLI" );
        my $filer_state_B = $transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
        if ( $filer_state_B =~ /(UP|CLI)/i ) {
            logcomment("Partner node $FILER_B is up and running");
            $flag2 = 1;
        } else {
            logcomment("Partner node $FILER_B is in $filer_state_B state");
        }
    } else {
        logcomment("Partner node $FILER_B is in $filer_state_B state");
    }
    if ( ($flag1) && ($flag2) ) {
        return $pass;
    } else {
        return $fail;
    }
}
##############################################################
## Author : arjun.lavu@netapp.comapre
##############################################################
sub sasadmin_expander_cli_phydump {
    my (%opts) = validate( @_, { Node => { type => OBJECT, default => undef, optional => 1 }, } );
    my $Node = $opts{Node};
    my $output;
    my $FINAL    = {};
    my $FILER_C  = $Node->name();
    my $return   = sasadmin_expander_map_cmode( node => $Node );
    my @channels = keys %{$return};

    #LINE:
    foreach my $key (@channels) {
        my @WWN = keys %{ $return->{$key} };
        foreach my $WWN (@WWN) {
            my $ID = $return->{$key}->{$WWN}->{'ID'};
            if ($ID) {
                $output = sasadmin_expander_cli( Node => $Node, command => 'phydump', shelf_id => $ID, adapter_name => $key );
                if ( $output != 1 ) {
                    $output =~ s/(.*)(-----+)(.*)/$3/s;
                    foreach my $line ( split( "\n", $output ) ) {
                        if ( $line =~ /(\S+)\s*\|(.*)\|(.*)$/ ) {
                            $FINAL->{ $key . $ID }->{$1} = $3;
                        }
                    }
                }
            }
        }
    }

    #logcomment("Dumping ".Dumper($FINAL));
    return $FINAL;
}

##############################################################
## Author : arjun.lavu@netapp.comapre
##############################################################
sub sasadmin_expander_cli {
    my (%opts) = validate(
        @_,
        {
            Node         => { type => OBJECT, default => undef, optional => 1 },
            timeout      => { type => SCALAR, default => "300", optional => 1 },
            command      => { type => SCALAR },
            shelf_id     => { type => SCALAR },
            adapter_name => { type => SCALAR },
            retry        => { type => SCALAR, default => 5,     optional => 1 },
        }
    );
    my $output;
    my $adapter_name = $opts{adapter_name};
    my $command      = $opts{command};
    my $shelfid      = $opts{shelf_id};
    my $retry;
    my $Node        = $opts{Node};
    my $FILER_C     = $Node->name();
    my $Host        = host($FILER_C);
    my $cmd         = "sasadmin expander_cli $adapter_name\.$shelfid \'$command\' ";
    my $transit_obj = NACL::Transit->new( name => $FILER_C );
    my $filer_state = $transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    my $api_set_obj;

    if ( $filer_state =~ /CLI/ ) {
        $api_set_obj = $Node->get_7m_or_nodescope_apiset();
        $api_set_obj->set_timeout( 'connectrec-timeout' => 7200 );
    } elsif ( $filer_state =~ /MAINT/ ) {
        $api_set_obj = NACL::APISet->new(
            hostobj   => $Host,
            category  => "Node",
            interface => "CLI",
            set       => "Maintenance"
        );
        $api_set_obj->set_timeout( 'connectrec-timeout' => 7200 );
    } else {
        logcomment("**FATAL** : Filer : $FILER_C : is NOT in required state i,e $filer_state");
        logresult( 'FATAL', "Filer : $FILER_C : is NOT in required state i,e $filer_state" );
    }
  CLI_LABEL:;
    $output = $api_set_obj->execute_command( 'command' => $cmd );

    # print "response dump is" . Dumper $output;
    if ( $output =~ /Enclosure Services Unavailable/ ) {
        if ( $retry <= $opts{retry} ) {
            logcomment("INBAND CLI command FAILED because enclosure services are unavailable. Retry: $retry Retry after 20 secs");
            sleep 20;
            $retry++;
            goto CLI_LABEL;
        } else {
            logcomment("**WARNING** : INBAND CLI command FAILED with enclosure services unavaiable even after $opts{retry} retries with 20 secs interval");
            return 1;
        }
    }
    if ( $output =~ /DSA DB lock/ ) {
        if ( $retry <= $opts{retry} ) {
            logcomment("INBAND CLI command FAILED because DSA DB LOCK: unlocked; locks held. Retry: $retry Retry after 20 secs");
            sleep 20;
            $retry++;
            goto CLI_LABEL;
        } else {
            logcomment("**WARNING** :INBAND CLI command FAILED with DSA DB lock even after $opts{retry} retries with 20 secs interval");
            return 1;
        }
    }
    if ( ( $output =~ /expander_cli: failed/ ) && ( $command !~ /watchdog_tp|reboot/ ) ) {
        logcomment("**WARNING** : Command FAILED :: $output");
        return 1;
    }
    if ( $output =~ /resource busy/ && ( $retry == 15 ) ) {
        logcomment("**WARNING** : Command FAILED even after trying for 15 times :: $output");
        return 1;
    }
    return $output;
}
##############################################################
## Author : arjun.lavu@netapp.comapre
##############################################################
sub compare_phy_state {
    my (%opts) = validate(
        @_,
        {
            before   => { type => HASHREF },
            after    => { type => HASHREF },
            disk_ref => { type => ARRAYREF, default => undef, optional => 1 },
            Node     => { type => OBJECT, default => undef, optional => 1 },
            compare  => { type => SCALAR, default => 'n', optional => 1 },
            boab     => { type => SCALAR, default => 'n', optional => 1 }
        }
    );
    my $before = $opts{before};
    my $after  = $opts{after};
    my @disks;
    my $filer_state;
    my %disk_has;
    my $FILER_C;
    my $flag = 'true';
    my $times;
    my $boab = $opts{boab};

    if ( $boab == 1 ) {
        $times = 4;    # for boab setups the change in phy count is 4 times the change power cycle
    } else {
        $times = 2;
    }

    # if(($parse_id=~/PwrCyc/i)&&($opts{compare}=~/^n$/i)){
    # logcomment("Power Cycle test is selected, hence Phy change count/Power cycle count values will not be compared in POST steps");
    # return 'true';
    # }
    if ( defined $opts{disk_ref} ) {
        grep { $disk_has{$_} = 1 } @{ $opts{disk_ref} };
    } elsif ( defined $opts{Node} ) {
        $FILER_C = $opts{Node}->name();
        if ( ( $parse_id =~ /506/i ) || ( $parse_id =~ /504/i ) || ( $parse_id =~ /505/i ) ) {
            my @aggregates;
            my @hammer_run_disks;
            try {
                ##Checking for Non Rooot Volumes
                my @tot_vol = NACL::C::Volume->find(
                    command_interface => $opts{Node},
                    filter            => { node => $FILER_C, 'vsroot' => 'false' }
                );
                foreach my $vol (@tot_vol) {
                    push( @aggregates, $vol->get_one_state_attribute('aggregate') );
                }
                logcomment("$FILER_C : Non Root aggregates available are - @aggregates");
            }
            catch NACL::Exceptions::NoElementsFound with {
                logcomment("$FILER_C : Non root aggregate are NOT available");
            };
            foreach my $raid_disks (@aggregates) {
                my $API_obj = $opts{Node}->get_7m_or_nodescope_apiset();
                $API_obj->set_timeout( 'connectrec-timeout' => 7200 );
                my $after = $API_obj->execute_command( 'command' => "aggr status -r $raid_disks" );
                foreach ( split( /\n/, $after ) ) {

                    #Do not match the uninitialised
                    next if ( $_ =~ /parity uninit/ );
                    if ( $_ =~ /(data|dparity|parity)\s*(\S+)/ ) {
                        my $disk = $2;
                        $disk =~ s/(P|L)\d+$//g;
                        push( @hammer_run_disks, $disk );
                        $disk_has{$disk} = 1;
                    }
                }

            }
            if (@hammer_run_disks) {
                my $dsks = _print_array( \@hammer_run_disks );
                logcomment( "$FILER_C : Total drives on which Power Cycle and Phy Change Count will be validated are " . scalar @hammer_run_disks . " and the drives are:\n" . $dsks );
            }
        } else {
            my $API_Object;
            $FILER_C = $opts{Node}->name();
            my $Transit_obj = NACL::Transit->new( name => $FILER_C );
            $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
            if ( $filer_state =~ /CLI|UP/i ) {
                $API_Object = $opts{Node}->get_7m_or_nodescope_apiset();
            } else {
                my $Host    = host($FILER_C);
                my $API_obj = NACL::APISet->new(
                    hostobj   => $Host,
                    category  => "Node",
                    interface => "CLI",
                    set       => "Maintenance"
                );
                $API_Object = $API_obj;

            }
            $API_Object->set_timeout( 'connectrec-timeout' => 7200 );
            foreach my $disk ( @{ disk_show_drive_maint( API_Obj => $API_Object, Filer => $FILER_C )->{'driveA'} } ) {
                $disk =~ s/(P|L)\d+$//g;
                $disk_has{$disk} = 1;
            }

            # grep{$disk_has{$_}=1}@{disk_show_drive_maint(API_Obj => $API_Object,Filer => $FILER_C)->{'driveA'}};
        }
    }
    if ( !( keys %disk_has ) ) {
        logcomment("**WARNING** : $FILER_C : NO AGGREGATES are available to validate Power Cycle and Phy Change Count") if ( ( $parse_id !~ /_PVT/ ) || ( $parse_id !~ /_IVS/ ) );
        return 'fail';
    }
    my @keys_after = keys %{ $opts{after} };
    my @fail_drive;
    my @fail;
    foreach my $key (@keys_after) {
        my @keys_inside = keys %{ $after->{$key} };
        foreach my $key1 (@keys_inside) {
            my $disk_inside = $key . '.' . $key1;
            if ( defined $disk_has{$disk_inside} ) {

                # logcomment("disk to test $disk_inside");
                if ( $opts{compare} =~ /^Y$/i ) {
                    logcomment("Disk - $disk_inside : \n");
                    if ( $after->{$key}->{$key1}->{'STATE'} ne $before->{$key}->{$key1}->{'STATE'} ) {
                        push( @fail, "**WARNING** : The STATE values Before :: $before->{$key}->{$key1}->{'STATE'} AND AFTER :: $after->{$key}->{$key1}->{'STATE'}" );
                        push( @fail, "**FAIL** : The I/F VALUES ARE DIFFERENT for $disk_inside" );
                    }
                    my $phy_diff = ( $after->{$key}->{$key1}->{'Phy change count'} ) -  ( $before->{$key}->{$key1}->{'Phy change count'} );
                    my $pwr_diff = ( $after->{$key}->{$key1}->{'Power cycle count'} ) - ( $before->{$key}->{$key1}->{'Power cycle count'} );
                    my $value = int( $phy_diff / $times ) + ( $before->{$key}->{$key1}->{'Power cycle count'} );
                    if ( ( $value == ( $after->{$key}->{$key1}->{'Power cycle count'} ) ) || ( $value == ( ( $after->{$key}->{$key1}->{'Power cycle count'} ) + 255 ) ) ) {
                        logcomment( "The values of [ Phy change ] are , --->  Before ( " . $before->{$key}->{$key1}->{'Phy change count'} . " ) and After ( " . $after->{$key}->{$key1}->{'Phy change count'} . " ) <---  Delta $phy_diff" );
                    } else {
                        push( @fail_drive, $disk_inside );
                        logcomment( "The values of [ Phy change ] are , --->  Before ( " . $before->{$key}->{$key1}->{'Phy change count'} . " ) and AFTER ( " . $after->{$key}->{$key1}->{'Phy change count'} . " ) <---  DELTA $phy_diff" );
                        logcomment( "**WARNING**:Disk -  $disk_inside : Comparison of Phy change value FAILED, ---> Before ( " . $before->{$key}->{$key1}->{'Phy change count'} . " ) and AFTER ( " . $after->{$key}->{$key1}->{'Phy change count'} . " ) <--- DELTA $phy_diff" ) if ( $filer_state =~ /CLI|UP/i );
                        my $delta = ( $after->{$key}->{$key1}->{'Power cycle count'} ) - ( $before->{$key}->{$key1}->{'Power cycle count'} );
                        if ( $delta < 0 ) {
                            $delta = 255 + $delta;
                        }
                        logcomment( "The values of [Power cycle] are , --->  Before ( " . $before->{$key}->{$key1}->{'Power cycle count'} . " ) and AFTER ( " . $after->{$key}->{$key1}->{'Power cycle count'} . " ) <---  DELTA $delta (expected value is " . int( $phy_diff / $times ) . ")" );
                        logcomment( "**WARNING**: Disk -  $disk_inside : Comparison of Power cycle count FAILED ,---> Before :: " . $before->{$key}->{$key1}->{'Power cycle count'} . " ) and  AFTER ( " . $after->{$key}->{$key1}->{'Power cycle count'} . " ) <--- DELTA $delta (expected value is " . int( $phy_diff / $times ) . ")" ) if ( $filer_state =~ /CLI|UP/i );
                    }
                } else {
                    if ( $after->{$key}->{$key1}->{'STATE'} ne $before->{$key}->{$key1}->{'STATE'} ) {
                        push( @fail, "**WARNING** : The STATE values are , ---> Before ( $before->{$key}->{$key1}->{'STATE'}) and AFTER ( $after->{$key}->{$key1}->{'STATE'}) <---" );
                        push( @fail, "**FAIL** : Disk - $disk_inside : The I/F VALUES ARE DIFFERENT " );
                    }
                    if ( ( $parse_id =~ /506/i ) || ( $parse_id =~ /504/i ) || ( $parse_id =~ /505/i ) ) {
                        if ( $after->{$key}->{$key1}->{'Power cycle count'} == $before->{$key}->{$key1}->{'Power cycle count'} ) {
                            logcomment( "**WARNING** : $FILER_C : Power cycle count values of the drive $disk_inside are matching in the test $parse_id, ---> Before ( " . $before->{$key}->{$key1}->{'Power cycle count'} . " ) and after ( " . $after->{$key}->{$key1}->{'Power cycle count'} . ")" );
                            $flag = "fail";
                        } else {
                        }
                        if ( $after->{$key}->{$key1}->{'Phy change count'} == $before->{$key}->{$key1}->{'Phy change count'} ) {
                            logcomment( "**WARNING** : $FILER_C :  Phy change count values of the drive $disk_inside are matching in the test $parse_id, Value of Phy change count Before :: " . $before->{$key}->{$key1}->{'Phy change count'} . " and after :: " . $after->{$key}->{$key1}->{'Phy change count'} );
                            $flag = "fail";
                        } else {
                        }
                    } elsif ( ( $parse_id =~ /501/i ) || ( $parse_id =~ /502/i ) ) {

                        #elsif ( ( $parse_id =~ /501/i ) || ( $parse_id =~ /502/i ) || ( $parse_id =~ /510/i ) ) { #BURT1025976 - khosur
                        if ( $after->{$key}->{$key1}->{'Phy change count'} == $before->{$key}->{$key1}->{'Phy change count'} ) {
                            logcomment( "**WARNING** : $FILER_C :  Phy change count values of the drive $disk_inside are matching in the test $parse_id, Value of Phy change count Before :: " . $before->{$key}->{$key1}->{'Phy change count'} . " and after :: " . $after->{$key}->{$key1}->{'Phy change count'} );
                            $flag = "fail";
                        } else {
                        }
                    } else {
                        if ( $after->{$key}->{$key1}->{'Power cycle count'} != $before->{$key}->{$key1}->{'Power cycle count'} ) {
                            if ( $parse_id =~ /507/i ) {
                                logcomment("DEBUG : Comparing the Power cycle count for Test Id : 507");
                                my $diff = $after->{$key}->{$key1}->{'Power cycle count'} - $before->{$key}->{$key1}->{'Power cycle count'};
                                if ( ( $diff le 0 ) || ( $diff gt 1 ) ) {
                                    logcomment( "**WARNING** : $FILER_C :Disk - $disk_inside : Power cycle count values are different,  ---> Before ( " . $before->{$key}->{$key1}->{'Power cycle count'} . " ) and After ( " . $after->{$key}->{$key1}->{'Power cycle count'} . " )" ) if ( $filer_state =~ /CLI|UP/i );
                                    $flag = "fail";
                                }
                            } else {
                                logcomment( "**WARNING** : $FILER_C :Disk - $disk_inside : Power cycle count values are different,  ---> Before ( " . $before->{$key}->{$key1}->{'Power cycle count'} . " ) and After ( " . $after->{$key}->{$key1}->{'Power cycle count'} . " )" ) if ( $filer_state =~ /CLI|UP/i );
                                $flag = "fail";
                            }
                        } else {
                        }
                        if ( !$parse_id =~ /510/i ) {    #BURT1025976 - khosur
                            if ( $after->{$key}->{$key1}->{'Phy change count'} != $before->{$key}->{$key1}->{'Phy change count'} ) {
                                logcomment( "**WARNING** : $FILER_C :Disk - $disk_inside : Phy change count values are different, ---> Before ( " . $before->{$key}->{$key1}->{'Phy change count'} . " ) and After ( " . $after->{$key}->{$key1}->{'Phy change count'} . " )" ) if ( $filer_state =~ /CLI|UP/i );
                                $flag = "fail";
                            } else {

                                #logcomment("$FILER_C :  Phy change count values of the drive $disk_inside are MATCHING, Value of Phy change count BEFORE is ".$before->{$key}->{$key1}->{'Power cycle count'}." and Value of Power cycle count AFTER is ".$after->{$key}->{$key1}->{'Power cycle count'});
                            }
                        }
                    }
                }
            }
        }
    }
    if (@fail) {
        logcomment(@fail);
    } else {
        logcomment("The I/F values are matching ");
    }

    if (@fail_drive) {
        @fail_drive = unique(@fail_drive);

        #        logcomment("**WARNING**: Comparison failed on the following drive : @fail_drive");
        $flag = [@fail_drive];
    }

    return $flag;
}
##############################################################
## Author : arjun.lavu@netapp.comapre
##############################################################
sub compare_sasadmin_expander_cli_phydump {
    my (%opts) = validate(
        @_,
        {
            before => { type => HASHREF },
            after  => { type => HASHREF },
        }
    );
    my $before = $opts{before};
    my $after  = $opts{after};

    #	logcomment("Dum3".Dumper($before));
    #	logcomment("Dum4".Dumper($after));
    my $flag = 0;
    foreach my $key ( keys %{$after} ) {
        my @adapter = split( "", $key );
        logcomment( "Comparing the values of " . $adapter[0] . $adapter[1] . "." . $adapter[2] . " from PRE to POST test process" );
        foreach my $key1 ( keys %{ $after->{$key} } ) {
            if ( $after->{$key}->{$key1} != $before->{$key}->{$key1} ) {
                logcomment( "**WARNING** : Values are DIFFERENT for the phy : $key : in PRE " . $before->{$key}->{$key1} . " in POST " . $after->{$key}->{$key1} );
                $flag = 1;
            }

            # logcomment("$after->{$key}->{$key1}  hhdhd $before->{$key}->{$key1}");
        }
    }
    return $flag;
}

##############################################################
## Author : arjun.lavu@netapp.comapre
##############################################################
sub read_shelflog {
    my (%opts) = validate( @_, { Node => { type => HASHREF }, } );
    my $Node = $opts{Node};
    my $FILER_C          = $Node->name();
    my $params           = NATE::ParamSet->new( global => 1 );
    my $LOGDIR           = $params->get( 'LOGDIR', default => undef );
    my ($actual_log_dir) = $LOGDIR =~ /(\S+)\/HDD/;
    end_shelflog_detector( Node => $Node );
    $/ = undef;
    my $logfile = "$LOGDIR/" . "read_shelflog_$FILER_C" . "\.log";
    open( FH, "$logfile" ) || return logcomment("**WARNING** : $FILER_C : CANNOT open the file $logfile");
    my $DATA = ;
    my @copy;

    foreach ( split( "\n", $DATA ) ) {
        if ( $_ =~ /STAF_handle|END OF TEST/g ) {
            push( @copy, $_ );
        }
    }

    # if($DATA=~/(.*)(Ending shelflog_iom_master.*)(\d+\s+\d+\s+END OF TEST.*)/s){
    # $data = $1.$3;
    # }
    $/ = "\n";
    close FH;
    if ( !( -d "$actual_log_dir\/SYSTEM_LOGS" ) ) {
        system("sudo mkdir -p $actual_log_dir\/SYSTEM_LOGS");
    }
    my $file_create = "$actual_log_dir\/SYSTEM_LOGS\/" . $parse_id . "_" . $FILER_C . "_IOM\.log";
    system("sudo touch $file_create");
    system("sudo chmod 666 $file_create");

    # system("sudo cp -rf $logfile $file_create");
    $DATA =~ s/X\;X/ /gs;
    open( FH1, ">>$file_create" ) || return logcomment("**WARNING** : $FILER_C : CANNOT create the file $file_create");
    print FH1 $DATA;
    close FH1;
    push( @copy, "\n=========================================================================================\n" );
    push( @copy, "\n\t\t\tshelflog_iom_master log data is copied to file $file_create\n" );
    push( @copy, "=========================================================================================\n" );
    system("sudo chmod 666 $logfile");
    open( FH, ">$logfile" ) || return logcomment("**WARNING** : $FILER_C : CANNOT create the file $logfile");
    print FH "@copy";
    close FH;
}

##############################################################
## Author : arjun.lavu@netapp.comapre
##############################################################

sub read_ems_logs {
    my (%opts) = validate( @_, { Node => { type => OBJECT }, } );
    my $Node = $opts{Node};
    my $FILER_C          = $Node->name();
    my $params           = NATE::ParamSet->new( global => 1 );
    my $LOGDIR           = $params->get( 'LOGDIR', default => undef );
    my ($actual_log_dir) = $LOGDIR =~ /(\S+)\/HDD/;
    end_ems_detector( Node => $Node );
    $/ = undef;
    my $logfile = "$LOGDIR/" . "read_ems_logs_$FILER_C" . "\.log";
    open( FH, "$logfile" ) || return logcomment("$FILER_C : CANNOT open the file $logfile");
    my $DATA = ;
    my @copy;

    foreach ( split( "\n", $DATA ) ) {
        if ( $_ =~ /STAF_handle|END OF TEST/g ) {
            push( @copy, $_ );
        }
    }
    $/ = "\n";
    close FH;
    my $num;    #aditis: 861147
    if ( $parse_id =~ /(\d+)\_\S+/ ) {
        $num = $1;
    }
    my $dir = "$actual_log_dir\/SYSTEM_LOGS\/" . $FILER_C;
    if ( !( -d "$dir" ) ) {
        system("sudo mkdir -p $dir");
    }

    #blessy: 861147
    opendir DIR, $dir;
    my @list = readdir DIR;
    closedir(DIR);
    my $fileCount = 0;
    foreach my $file (@list) {
        if ( $file =~ m/^$parse_id.*\.log$/i ) {
            if ( $file =~ /.+_EMS_(\d+)\.log/i ) {
                if ( $fileCount < $1 ) {
                    $fileCount = $1;
                }

            }
        }

    }
    $fileCount++;
    my $file_create = "$dir\/" . $parse_id . "_EMS_$fileCount\.log";
    system("sudo touch $file_create");
    system("sudo chmod 666 $file_create");

    # system("sudo cp -rf $logfile $file_create");
    open( FH1, ">>$file_create" ) || return logcomment("$FILER_C :: CANNOT create the file $file_create");
    $DATA =~ s/X\;X/ /gs;
    print FH1 $DATA;
    close FH1;
    push( @copy, "\n=========================================================================================\n" );
    push( @copy, "\n\t\t\tEMS log data is copied to file $file_create\n" );
    push( @copy, "=========================================================================================\n" );
    system("chmod 666 $logfile");
    open( FH, ">$logfile" ) || return logcomment("$FILER_C ::: CANNOT create the filE $logfile");
    print FH "@copy";
    close FH;
}

##############################################################
## Author : arjun.lavu@netapp.comapre
##############################################################
sub start_shelflog_detector {
    my (%opts) = validate( @_, { Node => { type => OBJECT }, } );
    my $Node = $opts{Node};
    my $FILER_C = $Node->name();

    my $Log_file = '/mroot/etc/log/shelflog/shelflog_iom_master';
    $SHELFLOG_DETECTOR->{$FILER_C} = NACL::MTask::SystemLogDetector->new(
        command_interface => $Node,
        set_log_file      => [$Log_file],
        nacltask_timeout  => 432000,
    );
    $SHELFLOG_DETECTOR->{$FILER_C}->start();
    logcomment("$FILER_C : Reading shelflog_iom_master log started");
}

##############################################################
## Author : arjun.lavu@netapp.comapre
##############################################################
sub end_shelflog_detector {
    my (%opts) = validate( @_, { Node => { type => OBJECT }, } );
    my $Node = $opts{Node};
    my $FILER_C = $Node->name();
    logcomment("$FILER_C : Ending shelflog_iom_master log reading");
    my ($var) = $SHELFLOG_DETECTOR->{$FILER_C}->get_logs();
}

##############################################################
## Author : arjun.lavu@netapp.comapre
##############################################################
sub start_ems_detector {
    my (%opts) = validate( @_, { Node => { type => OBJECT }, } );
    my $Node = $opts{Node};
    my $FILER_C = $Node->name();
    $EMS_DETECTOR->{$FILER_C} = NACL::MTask::EventLogDetector->new(
        command_interface      => $Node,
        check_for_any_presence => [ 'dfu.firmwareDownloading', 'dfu.fwDownloaded' ],
    );
    $EMS_DETECTOR->{$FILER_C}->start();
    my $event_start_time = $EMS_DETECTOR->{$FILER_C}->event_begin_time();
    logcomment("$FILER_C : Reading EMS log started, Start time is :: $event_start_time");
}

##############################################################
## Author : arjun.lavu@netapp.comapre
##############################################################
sub end_ems_detector {
    my (%opts) = validate( @_, { Node => { type => OBJECT }, } );
    my $Node = $opts{Node};
    my $FILER_C = $Node->name();
    if ( defined $EMS_DETECTOR->{$FILER_C} ) {
        try {
            my $event_end_time = $EMS_DETECTOR->{$FILER_C}->event_end_time();

            # logcomment("$FILER_C : Ending EMS log reading, end time is : $event_end_time");
            $EMS_DETECTOR->{$FILER_C}->stop( 'check' => 1 );
        }
        catch NACL::Exceptions::EventCheckFailure with {
            logcomment("EMS logs read");
        }
        catch NATE::BaseException with {
            logcomment("**WARNING** : NATE Base exception captured, EMS log detector CANNOT be stopped");
        };
    } else {
        logcomment("**WARNING** : $FILER_C : Event detector object has NOT created in PRE_TEST process");
    }
}

##############################################################
## Author : arjun.lavu@netapp.comapre
##############################################################
sub drive_names_minus_adapter {
    my (%opts) = validate(
        @_,
        {
            primary   => { type => ARRAYREF },
            secondary => { type => ARRAYREF },
        }
    );
    my @primary   = @{ $opts{primary} };
    my @secondary = @{ $opts{secondary} };
    my @return;
    my %filter;
    foreach my $disk (@primary) {
        $disk =~ s/^\s*|\s*$//gi;
        ( my $bkp = $disk ) =~ s/^(\S+?)\.//;
        $filter{$bkp} = $disk;
    }
    foreach my $key ( keys %filter ) {
        $key =~ s/^\s+|\s+$//i;
        foreach my $dsk (@secondary) {
            $dsk =~ s/^\s+|\s+$//i;
            if ( $dsk =~ /$key$/ ) {
                push( @return, $filter{$key} ) if ( $filter{$key} =~ /\S/ );
            }
        }
    }

    # logcomment("Common drives @return");
    return @return;
}

##############################################################
## Author : arjun.lavu@netapp.comapre
##############################################################
sub compare_WWN {
    my (%opts) = validate(
        @_,
        {
            before => { type => HASHREF },
            after  => { type => HASHREF },
        }
    );
    my $before     = $opts{before};
    my $after      = $opts{after};
    my $before_dup = {};
    my $after_dup  = {};
    foreach my $dsk ( keys %{$after} ) {
        ( my $dsk_dup = $dsk ) =~ s/^(\S+?)\.//;
        $after_dup->{$dsk_dup} = $after->{$dsk};
    }
    foreach my $dsk ( keys %{$before} ) {
        ( my $dsk_dup = $dsk ) =~ s/^(\S+?)\.//;
        $before_dup->{$dsk_dup} = $before->{$dsk};
    }
    my $flag = 1;

    # my @drives = keys(%{$after});
    foreach my $disk ( keys %{$after} ) {
        my $ref = ref( $after->{$disk} );
        next if ( $ref !~ /HAS/i );
        ( my $dsk_dup = $disk ) =~ s/^(\S+?)\.//;
        if ( defined( $after_dup->{$dsk_dup}->{'WWN'} && $before_dup->{$dsk_dup}->{'WWN'} ) ) {
            if ( $after_dup->{$dsk_dup}->{'WWN'} ne $before_dup->{$dsk_dup}->{'WWN'} ) {
                logcomment("**WARNING** :  disk - $disk : WWN values are DIFFERENT. ---> Before ( $before->{$disk}->{'WWN'} ) and After ( $after->{$disk}->{'WWN'} ) <--- ");
                $flag = 0;
            }
        }
    }
    return $flag;
}

##############################################################
## Author : arjun.lavu@netapp.comapre
## Description :: Set the filer time as server time
##############################################################
sub set_filer_time {
    my (%opts) = validate( @_, { Node => { type => OBJECT }, } );
    logcomment("DEBUG:Setting the filer time");
    my $Node        = $opts{Node};
    my $FILER_C     = $Node->name();
    my $Transit_obj = NACL::Transit->new( name => $FILER_C );
    my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    if ( $filer_state =~ /CLI|UP/i ) {
        my $mon  = `date +%m`;
        my $day  = `date +%d`;
        my $year = `date +%Y`;
        my $date = `date`;
        my $time;
        chomp( $mon, $day, $year );
        $date =~ s/^\s+//g;
        if ( $date =~ /^\S+\s+\S+\s+\S+\s+(\S+)/ ) {
            $time = $1;
        }
        NACL::C::ClusterDate->modify(
            command_interface => $Node,
            date              => "$mon/$day/$year $time"
        );
    }
}

##############################################################
## Author : arjun.lavu@netapp
##############################################################
sub get_valid_drives_for_firm {
    my (%opts) = validate(
        @_,
        {
            Node   => { type => OBJECT },
            drives => { type => ARRAYREF }
        }
    );
    my $Node       = $opts{Node};
    my @drive_list = @{ $opts{drives} };
    my $FILER_C    = $Node->name();
    my $API_OBJ    = $Node->get_7m_or_nodescope_apiset();
    $API_OBJ->set_timeout( 'connectrec-timeout' => 7200 );
    my $disk_tot = disk_show_drive_maint( API_Obj => $API_OBJ, Filer => $FILER_C );
    my @drives = @{ $disk_tot->{'driveA'} };
    my ( @actual_drives, %actual_filter, %drives_filter, @disk_list, @return );

    foreach my $dsk (@drive_list) {
        ( my $fil_dsk = $dsk ) =~ s/(\w+\.)//;
        $drives_filter{$fil_dsk} = $dsk;
    }
    foreach my $dsk (@drives) {
        ( my $fil_dsk = $dsk ) =~ s/(\w+\.)//;
        $actual_filter{$fil_dsk} = $dsk;
    }
    my @actual_drives_tmp = grep { /\S/ } intersection( [ sort keys %drives_filter ], [ sort keys %actual_filter ] );
    foreach (@actual_drives_tmp) {
        push( @actual_drives, $actual_filter{$_} ) if ( ( $_ =~ /\S/ ) && ( $_ !~ /P\d+$/ ) );
    }
    try {
        my @aggrs = NACL::C::Aggregate->find(
            command_interface => $Node,
            filter            => { nodes => [$FILER_C], 'root' => 'false' }
        );
        foreach my $aggr (@aggrs) {
            my $aggregate = $aggr->get_one_state_attribute('aggregate');
            logcomment("$FILER_C : Aggr name :: $aggregate");
            if ( $aggr->get_one_state_attribute('raidstatus') =~ /degraded|reconstruct|offline/i ) {
                my $disk_obj = NACL::CS::StorageAggregate->fetch(
                    command_interface => $Node,
                    filter            => { 'aggregate' => "$aggregate", },
                    requested_fields  => ['disklist']
                );
                my @disks = $disk_obj->disklist();
                logcomment("Degraded aggregate : $aggregate : disks : @disks");
                my $disk_hashref = NACL::C::StorageDisk->get_nodescope_diskname(
                    command_interface => $Node,
                    disks             => \@disks,
                );

                # logcomment("dumoing ".Dumper($disk_hashref));
                @disk_list = values %{$disk_hashref};
                my $dsks = _print_array( \@disk_list );
                logcomment( "**WARNING** : $FILER_C : Degraded aggregate : $aggregate : drives(dblade) :: \n" . $dsks . " , So ignoring from firmware validation" );
            }
        }
    }
    catch NACL::Exceptions::NoElementsFound with {
        logcomment("$FILER_C : Non root aggregates are NOT found in the filer");
    };
    my $API_obj = $Node->get_7m_or_nodescope_apiset();
    $API_obj->set_timeout( 'connectrec-timeout' => 7200 );
    my $out = $API_obj->execute_command( 'command' => "aggr status -s" );
    my (@zeroing);
    if ( $out =~ /zeroing|not zeroed/i ) {
        my $n = 0;
        my @lines = split( /\n/, $out );
        while ( $n <= $#lines ) {
            last if ( $lines[$n] =~ /^-----/ );
            $n++;
        }
        $n++;
        foreach my $var ( @lines[ $n .. $#lines ] ) {
            $var =~ s/^\s+|\s+$//gi;
            if ( $var =~ /spare\s*(\S+).*(not zeroed|zeroing)/ ) {
                push( @zeroing, $1 );
            }
        }
    }
    if (@zeroing) {
        my $dsks = _print_array( \@zeroing );
        logcomment( "**WARNING** : Total number of zeroing/not zeroed drives are " . scalar @zeroing . " and the drives are :\n" . $dsks . " , So ignoring these drives from firmware download validation" );
    }
    push( @disk_list, @zeroing ) if (@zeroing);
    my @common;
    @common = intersection( [ sort @actual_drives ], [ sort @disk_list ] );
    my @return = array_diff( [ sort @actual_drives ], [ sort @common ] );
    @return = grep { /\S/ } @return;
    if (@return) {
        my $dsks = _print_array( \@return );
        logcomment( "$FILER_C : Drives on which firmware download needs to be validated are : " . scalar @return . " and the drives are:\n" . $dsks );
    } else {
        logcomment("$FILER_C : NO RELEVANT DRIVES are available to validate firmware update");
    }
    return @return;
}

##############################################################
## Author : arjun.lavu@netapp
##############################################################
sub compare_scsi_disk_errors {
    my (%opts) = validate(
        @_,
        {
            before => { type => HASHREF },
            after  => { type => HASHREF },
            Node   => { type => OBJECT, default => undef, optional => 1 },
        }
    );
    my $before     = $opts{before};
    my $after      = $opts{after};
    my $Node       = $opts{Node} if ( defined $opts{Node} );
    my $params     = NATE::ParamSet->new( global => 1 );
    my $LOGDIR     = $params->get( 'LOGDIR', default => undef );
    my $before_dup = {};
    my $after_dup  = {};
    my $fail       = 0;
    my %filter     = (
        'Number of glist entries'             => 1,
        'Soft errors on read bit error rate'  => 1,
        'Soft errors on write bit error rate' => 1,
        'Soft error instantaneous rate'       => 1,
        'Hard errors on read bit error rate'  => 1,
        'Hard errors on write bit error rate' => 1,
        'Hard error instantaneous rate'       => 1,
        'Soft errors on read since boot'      => 1,
        'Soft errors on write since boot'     => 1,
        'Hard errors on read since boot'      => 1,
        'Hard errors on write since boot'     => 1
    );

    foreach my $disk ( keys( %{$before} ) ) {
        ( my $disk_bkp = $disk ) =~ s/^(\S+?)\.//;
        $before_dup->{$disk_bkp} = $before->{$disk};
    }
    foreach my $disk ( keys( %{$after} ) ) {
        ( my $disk_bkp = $disk ) =~ s/^(\S+?)\.//;
        $after_dup->{$disk_bkp} = $after->{$disk};
    }
    my @disk_list_glist    = ();
    my $flag_glist_entries = 0;
    foreach my $dsk ( keys( %{$after} ) ) {    ## can be replaced  with disk show -a output
        ( my $disk_bkp = $dsk ) =~ s/^(\S+?)\.//;
        my @keys = keys( %{ $after->{$dsk} } );
        foreach my $val (@keys) {
            next if ( !( exists $filter{$val} ) );
            if ( $val =~ /Number of glist entries/ ) {    #Burt 1042611 nmamatha
                my $diff = $before_dup->{$disk_bkp}->{$val} - $after_dup->{$disk_bkp}->{$val};
                if ( $diff >= 3 ) {
                    $flag_glist_entries = 1;
                    push( @disk_list_glist, $dsk ) if ( ( $dsk !~ /P\d+$/ ) );

                    logcomment("**FAIL** : Disk - $dsk : G-LIST count grew by $diff , --->before : ($before_dup->{$disk_bkp}->{$val}) and after : ($after_dup->{$disk_bkp}->{$val})");

                    #            logresult('FAIL',"G-LIST COUNT GREW BY $diff , --->BEFORE : ($before_dup->{$disk_bkp}->{$val}) and AFTER : ($after_dup->{$disk_bkp}->{$val})");
                } elsif ( ( $diff < 3 ) && ( $diff > 0 ) ) {
                    logcomment("**WARNING** : Disk - $dsk : G-LIST count grew by $diff,  --->Before ($before_dup->{$disk_bkp}->{$val}) and After ($after_dup->{$disk_bkp}->{$val}) <---");
                    $fail = 1;
                } else {
                    logcomment("Disk - $dsk : The values of \[$val\] are Same. ---> >Before ($before_dup->{$disk_bkp}->{$val}) and After ($after_dup->{$disk_bkp}->{$val}) <---");
                }
            }
            if ( $val =~ /Hard errors on read in last 128 hours|Hard errors on write in last 128 hours/ig ) {
                if ( $after_dup->{$disk_bkp}->{$val} > $before_dup->{$disk_bkp}->{$val} ) {
                    logcomment("**WARNING** : Disk - $dsk : The values of \[$val\] are DIFFERENT. --->Before ($before_dup->{$disk_bkp}->{$val}) and After ($after_dup->{$disk_bkp}->{$val}) <---");
                    $fail = 1;
                }
                next;
            }
            if ( $parse_id =~ /PwrCyc/i ) {
                if ( $val =~ /Soft errors on read since boot|Soft errors on write since boot|Hard errors on read since boot|Hard errors on write since boot/ig ) {
                    if ( $after_dup->{$disk_bkp}->{$val} > $before_dup->{$disk_bkp}->{$val} ) {
                        logcomment("**WARNING** : Disk - $dsk : The values of \[$val\] are DIFFERENT. --->Before ($before_dup->{$disk_bkp}->{$val}) and After ($after_dup->{$disk_bkp}->{$val}) <---");
                        $fail = 1;
                    }
                } else {
                    if ( $after_dup->{$disk_bkp}->{$val} != $before_dup->{$disk_bkp}->{$val} ) {
                        logcomment("**WARNING** : Disk - $dsk : The values of \[$val\] are DIFFERENT. --->Before ($before_dup->{$disk_bkp}->{$val}) and After ($after_dup->{$disk_bkp}->{$val}) <---");
                        $fail = 1;
                    }
                }
            } else {
                if ( $after_dup->{$disk_bkp}->{$val} != $before_dup->{$disk_bkp}->{$val} ) {
                    logcomment("**WARNING** : Disk - $dsk : The values of \[$val\] are DIFFERENT. --->Before ($before_dup->{$disk_bkp}->{$val}) and After ($after_dup->{$disk_bkp}->{$val}) <---");
                    $fail = 1;
                }
            }
        }
    }

    #Burt 1042611 nmamatha
    if ( $flag_glist_entries == 1 ) {
        my $FILER_C = $Node->name();
        my $API_Object = $Node->get_7m_or_nodescope_apiset( connid => "console" );
        $API_Object->set_timeout( "connectrec-timeout" => 7200 );

        my $disk_res   = disk_show_v( Node => $Node );
        my $filer_path = '/mroot/etc/log/nht_info/';
        my ($logdir)   = $LOGDIR =~ /(\S+)\/HDD/;
        my @drives     = ();
        my $dsks       = _print_array( \@disk_list_glist );
        logcomment( "$FILER_C : Drives on which 'scsi drive_log ' will be executing are - " . scalar @disk_list_glist . " and the drives are:\n" . $dsks );
        $logdir = "$logdir" . "/DRIVE_LOGS/$FILER_C";
        foreach (@disk_list_glist) {
            my $cmd = "scsi drive_log $_";
            my $output = $API_Object->execute_command( 'command' => "$cmd" );
        }
        my @drvs_no_logs = ();
        sleep(280);
        my $res = $API_Object->execute_command( 'command' => "ls /etc/log/nht_info/" );
        sleep(20);
        $res .= $API_Object->execute_command( 'command' => " " );
        foreach (@disk_list_glist) {
            if ( $res !~ /$disk_res->{$_}->{SERIAL}/ ) {
                push( @drvs_no_logs, $_ );
            }
        }
        logcomment("**WARNING**: $FILER_C - Drive log for drive @drvs_no_logs is NOT available at /etc/log/nht_info");

        #Copy the log from /etc/log/nht_info to Drive_Log directory
        if ( scalar @drvs_no_logs < scalar @disk_list_glist ) {
            logcomment("Copying drive log from filer directory");
            system("mkdir -p $logdir");
            system("sudo chmod 777 $logdir");
            copy_files_to_client_from_filer(
                node_present => $Node,
                filer_path   => $filer_path,
                log_path     => $logdir,
            );
        }
        logresult( 'FAIL', "$FILER_C :NUMBER OF GLIST ENTRIES FOR THE DRIVES : @disk_list_glist DELTA VALUES ARE GREATER THAN 3" );
    }
    return $fail;
}

###############################################################################
## Author : arjun.lavu@netapp
## Description :: fail the test if the filer drive format is not in FS compatible
###############################################################################
sub fail_if_diff_drive_foramt {
    my (%opts) = validate( @_, { Node => { type => OBJECT }, } );
    my $Node = $opts{Node};
    my $FILER_C = $Node->name();
    my @drive_not_supported;
    my $Transit_obj = NACL::Transit->new( name => $FILER_C );
    my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    logcomment("DEBUG:$FILER_C :: filer state is : $filer_state");
    return undef if ( $filer_state !~ /CLI/i );
    my @disk_obj = NACL::C::Disk->find( command_interface => $Node, );

    foreach my $state_obj (@disk_obj) {
        my $free_disk = $state_obj->disk();
        if ( $free_disk =~ /(\S+)\:(\S+)/ ) {
            push( @drive_not_supported, $2 );
        }
    }
    if ( scalar @drive_not_supported ) {
        my $dsks = _print_array( \@drive_not_supported );
        logcomment( "**FATAL** : $FILER_C : Total number of drives which are NOT in FS format are " . scalar @drive_not_supported . " and the drives are:\n" . $dsks . " , \nPlease remove the unsupported drives from the system and try again" );
        return 'fail';
    }
}

###############################################################################
## Author : arjun.lavu@netapp
## Description :: Copy the system logs of the filer to server specified path
###############################################################################
sub get_system_logs {
    my (%opts) = validate(
        @_,
        {
            Node   => { type => OBJECT },
            logdir => { type => SCALAR },

        }
    );
    my $Node    = $opts{Node};
    my $FILER_C = $Node->name();
    my $log_dir = $opts{logdir};
    my $API_obj = $Node->get_7m_or_nodescope_apiset();
    my $API_Object;
    my $flag        = 0;
    my $Transit_obj = NACL::Transit->new( name => $FILER_C );
    my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    if ( $filer_state !~ /CLI/i ) {
        logcomment("**WARNING** : $FILER_C : Filer is NOT in file-system mode, so CANNOT copy system files");
    }
    logcomment("Getting the system logs of the filer :: $FILER_C");

    # my $sudo = "/usr/bin/sudo";
    my $client  = hostname();
    my @clienta = split( /\./, $client );
    my $CLIENT  = $clienta[0];
    my $Client  = NACL::C::Client->new( client => $CLIENT );
    logcomment("Client : $Client - $CLIENT ");

    #  my $Client = NACL::C::Client->find();
    my $scp;
    try {
        $scp = NACL::MTask::SCP->new(
            target_command_interface => $Node,
            source_command_interface => $Client,
        );
    }
    catch NATE::BaseException with {
        $flag = 1;
        logcomment("$FILER_C : Could NOT create SCP object, please check the connections");
    };
    if ($flag) {
        return;
    }
    logcomment("system log dir - $log_dir");
    my ($main_dir) = $log_dir =~ /(\S+)SYSTEM_LOGS.*/;
    my $num = 0;
    if ( $parse_id =~ /(\d+)\_\S+/ ) {
        $num = $1;
    } else {
        $num = time;
    }
    my $sys_log_dir = "SYSTEM_LOGS/" . $FILER_C . "_T_" . $num . "/";
    my $syscopy_dir = $main_dir . $sys_log_dir;
    $log_dir = $syscopy_dir;

    if ( -d "$log_dir" ) {
        logcomment(" Directory System_Log is created successfully");
    } else {
        system("sudo mkdir -p $log_dir");
        if ( !( -d "$log_dir" ) ) {
            logcomment("CANNOT Create directory :: $log_dir");
            return;
        }
    }
    logcomment("Copying system logs under : $log_dir");
    system("sudo chmod 777 $log_dir");
    logcomment("List all files in etc");
    my $local_api = $Node->get_7m_or_nodescope_apiset();
    $local_api->set_timeout( 'connectrec-timeout' => 7200 );
    try {
        my $response = $local_api->ls( paths => "/etc/log/" );
    }
    catch NATE::BaseException with {
        logcomment("CANNOT list files under /etc/log");
    };
    try {
        my $Filer_apiset = $Node->apiset(
            category  => 'Node',
            interface => 'CLI',
            set       => "Systemshell"
        );
        my @filer_logfile_names = ( '/mroot/etc/log/adapter_dump*', '/mroot/etc/log/ems*', '/mroot/etc/log/messages*', '/mroot/etc/log/shelflog/shelflog*', '/mroot/etc/shm_med_err*', '/mroot/etc/crash' );
        foreach my $log_path (@filer_logfile_names) {
            my $File_on_filer;
            try {
                $File_on_filer = $Filer_apiset->execute_raw_command( command => "ls $log_path" );
                if ( $File_on_filer =~ /No match|No such/i ) {
                    logcomment("$FILER_C : NO $log_path files found on the filer");
                    next;
                }
            }
            catch NATE::BaseException with {
                logcomment("$FILER_C : $log_path CANNOT be accessed");
            };
            my @files = $File_on_filer =~ /(\S+)/sg;

            # logcomment("files to transfer : @files");
            foreach my $file (@files) {
                next if ( $file =~ /core/ );    #Burt - NVMe - Ssytem logs huge #1167332
                if ( $log_path =~ /crash/i ) {
                    $file = $log_path . "/" . $file;
                }
                chomp($file);
                try {
                    $scp->copy_from_target_to_source(
                        'files_to_copy'         => [$file],
                        set_directory_on_source => "$log_dir",
                    );
                }
                catch NATE::BaseException with {
                    logcomment("$FILER_C : Could NOT copy file :$file");
                };
            }
        }
    }
    catch NACL::APISet::Exceptions::ConnectionFailedException with {
        logcomment("$FILER_C : CANNOT connect to filer using system shell");
    };
}

###############################################################################
## Author : arjun.lavu@netapp
## Description :: Delete the system logs from the filer
###############################################################################
sub del_system_logs {
    my (%opts) = validate( @_, { Node => { type => OBJECT }, } );
    my $Node = $opts{Node};
    my $FILER_C     = $Node->name();
    my $flag        = 0;
    my $Transit_obj = NACL::Transit->new( name => $FILER_C );
    my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    if ( $filer_state !~ /CLI/i ) {
        logcomment("**WARNING** : $FILER_C : Filer is NOT in file-system mode, so CANNOT copy system files");
    }
    my $Client = NACL::C::Client->find();
    logcomment("List all files in etc");
    my $local_api = $Node->get_7m_or_nodescope_apiset();
    $local_api->set_timeout( 'connectrec-timeout' => 7200 );
    try {
        my $response = $local_api->ls( paths => "/etc/log/" );
    }
    catch NATE::BaseException with {
        logcomment("CANNOT list files under /etc/log");
    };
    try {
        my $Filer_apiset = $Node->apiset(
            category  => 'Node',
            interface => 'CLI',
            set       => "Systemshell"
        );
        my @filer_logfile_names = ( '/mroot/etc/log/adapter_dump*', '/mroot/etc/log/ems*', '/mroot/etc/log/messages*', '/mroot/etc/log/shelflog/shelflog*', '/mroot/etc/shm_med_err*' );
        foreach my $log_path (@filer_logfile_names) {
            logcomment("$FILER_C : Deleting the log file $log_path");
            my $File_on_filer = $Filer_apiset->execute_raw_command( command => "ls $log_path" );
            if ( $File_on_filer =~ /No match|No such/i ) {
                logcomment("$FILER_C : NO $log_path files found on the filer");
                next;
            } else {
                $Filer_apiset->execute_raw_command( command => "rm -rf $log_path" );
            }
        }
    }
    catch NACL::APISet::Exceptions::ConnectionFailedException with {
        logcomment("$FILER_C :: CANNOT connect to filer using system shell");
    };

}

sub check_partition {
    my $Node    = shift;
    my $FILER_C = $Node->name();
    my @drives;
    pnate_versions_display();
    print_test_variables();
    display_node_details( Node => $Node );
    my $Transit_obj = NACL::Transit->new( name => $FILER_C );
    my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    logcomment("Node $FILER_C is in the Filer state $filer_state");

    if ( $filer_state =~ /PASS|USER|MAINT/i ) {
        $Transit_obj->set( 'change_state_timeout' => 7200 );
        $Transit_obj->change_state( to => "CLI" );
    }
    if ( $filer_state =~ /UP|CLI/i ) {
        my $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
        try {
            my $prompts_answers = [ ".*Do you want to continue.*" => 'y' ];
            $Api_Set_Obj->execute_raw_command( 'command' => "set test", 'connectrec-match_table' => $prompts_answers );
            my $node_version = $Api_Set_Obj->execute_command( 'command' => 'version' );
            logcomment("Node Version : $node_version");

        }
        catch NATE::BaseException with {
            logcomment("$FILER_C : Filer is in CMODE, SSH connection is NOT proper");
        };
    }
    try {
        my %hash = ( filter => { 'container-type' => [ "aggregate", "spare" ], 'owner' => $FILER_C } );
        my @container_obj = NACL::C::Disk->find(
            command_interface => $Node,
            %hash,
        );
        foreach my $state_obj (@container_obj) {
            my $free_disk = $state_obj->disk();
            if ( $free_disk =~ /(\S+)\:(\S+)/ ) {
                $free_disk = $2;
            }
            push( @drives, $free_disk );
        }
        if (@drives) {
            my $dsks = _print_array( \@drives );
            logcomment( "$FILER_C : Number of disks are " . scalar @drives . " and the disks are:\n" . $dsks );
        }
    }
    catch NACL::Exceptions::NoElementsFound with {
        logcomment("$FILER_C : NO NORMAL DISKS found for the filer other than the partition drives");
    };
    return @drives;
}

##################################################
## Author : Pavan Lk
## Description : Checks node names of filers are interchanged or not.
## If they are interchanged then replaces the node names to their original names corresponds to their filers.
## Inputs : Null
## Output : Null
##################################################
sub nodename_interchange_checkup {
    my %nodes_filer;
    my @temp_nodes = NACL::C::Node->find();    # Find Nodes/Filers used in the test, Based on FILER param.
    foreach my $Node (@temp_nodes) {
        my $FILER_C = $Node->name();
        $nodes_filer{$FILER_C} = [$Node];
    }
    my @Nodes = map { @{$_} } grep { (/\S/) } values(%nodes_filer);

    foreach my $Node (@Nodes) {
        my $FILER_C      = $Node->name();
        my $Transit_objt = NACL::Transit->new( name => $FILER_C );
        my $filr_stat    = $Transit_objt->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
        if ( $filr_stat =~ /UP|CLI/i ) {
            my $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
            $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
            my $prompts_answers = [ ".*Do you want to continue.*" => 'y' ];
            $Api_Set_Obj->execute_raw_command( 'command' => "set test", 'connectrec-match_table' => $prompts_answers );
        }
    }
    {
        my $FILER_C      = $Nodes[0]->name();
        my $FILER_SECOND = $Nodes[1]->name();
        my $Transit_obj  = NACL::Transit->new( name => $FILER_C );
        my $filer_state;
        try {
            $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
            logcomment("Filer $FILER_C is in $filer_state state");
        }
        catch NACL::Transit::Exceptions::Timeout with {
            logcomment("Expected: Caught a Timeout Exception");

            #$Transit_obj->change_state( to => "CLI");
            my $prompt_fw;
            my $ignore_strings = [ "MADIMM\\d+->", "DIMM\\d+->", "^T>" ];
            my $host           = Tharn::host($FILER_C);
            my $prompt_array   = $host->prompt_fw();
            my $prompts        = join( "|", @$prompt_array );
            $prompt_fw = "($prompts)";
            logcomment("**DEBUG** : This is the prompt regex: $prompt_fw");
            my $Server = new Server( no_cli => 1 );
            $Server->set_execution_server( -Server => $FILER_C );
            $Server->console(
                cmd                        => "exit",
                additional_prompts_timeout => 600,
                ignore                     => $ignore_strings,
                additional_prompts         => {
                    "$FILER_C\>"      => "FINAL_PROMPT",
                    "run not found"   => "FINAL_PROMPT",
                    "$FILER_SECOND\>" => "FATAL_PROMPT",
                    "$prompt_fw"      => "FINAL_PROMPT",
                    "takeover"        => "FINAL_PROMPT",
                    "\.*\>"           => "FINAL_PROMPT",
                    "\>"              => "FINAL_PROMPT"
                }
            );

            $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
            logcomment("State of the filer $FILER_C is $filer_state");
        }
        catch NACL::Transit::Exceptions::TransitException with {
            my $exception_object = shift;
        };
        if ( $filer_state =~ /USER|PASS|DBLADECLI/i ) {
            $Transit_obj->set( 'change_state_timeout' => 7200 );
            $Transit_obj->change_state( to => "CLI" );
        }
        if ( $filer_state =~ /CLI/i ) {
            my $prompt_fw;
            my $ignore_strings = [ "MADIMM\\d+->", "DIMM\\d+->", "^T>" ];
            my $host           = Tharn::host($FILER_C);
            my $prompt_array   = $host->prompt_fw();
            my $prompts        = join( "|", @$prompt_array );
            $prompt_fw = "($prompts)";
            logcomment("DEBUG:This is the prompt regex: $prompt_fw");
            my $Server = new Server( no_cli => 1 );
            $Server->set_execution_server( -Server => $FILER_C );
            try {
                $Server->console(
                    cmd                        => "run local",
                    additional_prompts_timeout => 600,
                    ignore                     => $ignore_strings,
                    additional_prompts         => {
                        "$FILER_C\>"      => "FINAL_PROMPT",
                        "run not found"   => "FINAL_PROMPT",
                        "$FILER_SECOND\>" => "FATAL_PROMPT",
                        "$prompt_fw"      => "FINAL_PROMPT",
                        "takeover"        => "FINAL_PROMPT",
                        "\.*\>"           => "FINAL_PROMPT",
                        "\>"              => "FINAL_PROMPT"
                    }
                );
                $Transit_obj->set( 'change_state_timeout' => 7200 );
                $Transit_obj->change_state( to => "CLI" );
                logcomment("Changed to CLI");
            }
            catch NATE::BaseException with {
                logcomment("Filer  - $FILER_C : Duplicate node name found ,Renaming the node to rectify it");
                $Server->console(
                    cmd                        => "exit",
                    additional_prompts_timeout => 600,
                    ignore                     => $ignore_strings,
                    additional_prompts         => {
                        "$FILER_C\>"      => "FINAL_PROMPT",
                        "run not found"   => "FINAL_PROMPT",
                        "$FILER_SECOND\>" => "FATAL_PROMPT",
                        "$prompt_fw"      => "FINAL_PROMPT",
                        "takeover"        => "FINAL_PROMPT",
                        "\.*\>"           => "FINAL_PROMPT",
                        "\>"              => "FINAL_PROMPT"
                    }
                );
                logcomment("**DEBUG** : Change to CLI");
                $Transit_obj->set( 'change_state_timeout' => 7200 );
                $Transit_obj->change_state( to => "CLI" );
                try {
                    $Transit_obj = NACL::Transit->new( name => $FILER_C );
                    my $Original_State_temp = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
                    logcomment("Filer $FILER_C is in  $Original_State_temp");
                    if ( $Original_State_temp =~ /USER|PASS|DBLADECLI/ ) {
                        $Transit_obj->set( 'change_state_timeout' => 7200 );
                        $Transit_obj->change_state( to => "CLI" );
                        logcomment("$FILER_C Change to CLI");
                    }
                    my $Server = new Server( no_cli => 1 );
                    $Server->set_execution_server( -Server => $FILER_C );
                    eval { $Server->console( cmd => "system node rename -node local -newname new_$$" ); };
                    if ($@) {
                        if ( $@ =~ /Error/i ) {
                            logcomment("Valid node name exist");
                        } else {
                            logcomment("Valid node name does NOT exists, changed node name to new_$$");
                        }
                    }
                }
                catch NACL::Transit::Exceptions::Timeout with {
                    my $timeout = "1900";
                    my $prompt_fw;
                    my $Server = new Server( no_cli => 1 );
                    $Server->set_execution_server( -Server => $FILER_C );
                    my $ignore_strings = [ "MADIMM\\d+->", "DIMM\\d+->", "^T>" ];

                    # Retrieve valid prompts from NATE
                    my $host         = Tharn::host($FILER_C);
                    my $prompt_array = $host->prompt_fw();
                    my $prompts      = join( "|", @$prompt_array );
                    $prompt_fw = "($prompts)";
                    $Server->console(
                        cmd                        => "system node rename -node local -newname new_$$",
                        additional_prompts_timeout => $timeout,
                        ignore                     => $ignore_strings,
                        additional_prompts         => {
                            "$prompt_fw"   => "FINAL_PROMPT",
                            "::>"          => "FINAL_PROMPT",
                            "\:\:\.*\>"    => "FINAL_PROMPT",
                            "login"        => "admin",
                            ".*Password.*" => "netapp1!",
                        }
                    );
                    logcomment("Changed node name");
                };

            };
        }

        if ( $filer_state =~ /CLI/i ) {
            my @Nodes_rev = reverse(@Nodes);
            foreach my $Node (@Nodes_rev) {
                my $FILER_C = $Node->name();
                try {
                    my $Transit_obj = NACL::Transit->new( name => $FILER_C );
                    my $Original_State_temp = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
                    logcomment("Filer $FILER_C is in  $Original_State_temp");
                    if ( $Original_State_temp =~ /USER|PASS|DBLADECLI/ ) {
                        $Transit_obj->set( 'change_state_timeout' => 7200 );
                        $Transit_obj->change_state( to => "CLI" );
                        logcomment("$FILER_C Change to CLI");
                    }
                    my $Server = new Server( no_cli => 1 );
                    $Server->set_execution_server( -Server => $FILER_C );
                    eval { $Server->console( cmd => "system node rename -node local -newname $FILER_C" ); };
                    if ($@) {
                        if ( $@ =~ /Error/i ) {
                            logcomment("Valid node name exist");
                        } else {
                            logcomment("Valid node name does NOT exists, changed node name to $FILER_C");
                        }
                    }
                }
                catch NACL::Transit::Exceptions::Timeout with {
                    logcomment("Filer  - $FILER_C : Error while renaming due to timeout, so renaming the node again to rectify it");
                    my $timeout = "1900";
                    my $prompt_fw;
                    my $Server = new Server( no_cli => 1 );
                    $Server->set_execution_server( -Server => $FILER_C );
                    my $ignore_strings = [ "MADIMM\\d+->", "DIMM\\d+->", "^T>" ];

                    # Retrieve valid prompts from NATE
                    my $host         = Tharn::host($FILER_C);
                    my $prompt_array = $host->prompt_fw();
                    my $prompts      = join( "|", @$prompt_array );
                    $prompt_fw = "($prompts)";
                    $Server->console(
                        cmd                        => "exit",
                        additional_prompts_timeout => 600,
                        ignore                     => $ignore_strings,
                        additional_prompts         => {
                            "$FILER_C\>"      => "FINAL_PROMPT",
                            "run not found"   => "FINAL_PROMPT",
                            "$FILER_SECOND\>" => "FATAL_PROMPT",
                            "$prompt_fw"      => "FINAL_PROMPT",
                            "takeover"        => "FINAL_PROMPT",
                            "\.*\>"           => "FINAL_PROMPT",
                            "\>"              => "FINAL_PROMPT"
                        }
                    );
                    $Server->console(
                        cmd                        => "system node rename -node local -newname $FILER_C",
                        additional_prompts_timeout => $timeout,
                        ignore                     => $ignore_strings,
                        additional_prompts         => {
                            "$prompt_fw"   => "FINAL_PROMPT",
                            "::>"          => "FINAL_PROMPT",
                            "\:\:\.*\>"    => "FINAL_PROMPT",
                            "login"        => "admin",
                            ".*Password.*" => "netapp1!",
                        }
                    );
                    logcomment("Changed node name");
                };
            }
        }
    }
}

##############################################################
## Author : pavan.kumar2@netapp
## Description :: To print and get stsb get_status data for all the disks into HASHREF
## Return : HASHREF, which contains stsb get_status values of all disks
## Mandatory : N/A
## Supported Mode : CMODE
##############################################################
sub STSB_Get_Status_Results {
    my (%opts) = validate(
        @_,
        {
            Node      => { type => OBJECT,   optional => 1, default => undef },
            disk_list => { type => ARRAYREF, optional => 1, default => undef },
        }
    );
    my @disk_list;
    my $Node;
    $Node      = $opts{Node}           if ( defined $opts{Node} );
    @disk_list = @{ $opts{disk_list} } if ( defined $opts{disk_list} );

    my %STSB_FOR_EACH_DISKS = ();
    my ( %nodes_filer, @Nodes );
    if ( !$Node ) {
        my @Nodes_temp = NACL::C::Node->find();
        foreach my $node (@Nodes_temp) {
            my $FILER_C = $node->name();
            $nodes_filer{$FILER_C} = $node;
        }
        @Nodes = values(%nodes_filer);
        $Node  = $Nodes[0];
    }
    if (@disk_list) {
        my $dsks = _print_array( \@disk_list );
        logcomment( "Drives which passed from the script to run stsb get_status:\n" . $dsks );
    } else {
        @disk_list = list_of_disk( Node => $Node );
        my @temp;
        foreach (@disk_list) {
            if ( $_ =~ /P\d+$/ ) {
                ( my $dsk = $_ ) =~ s/P\d+$//;
                push( @temp, $dsk );
            } else {
                push( @temp, $_ );
            }
        }
        @disk_list = @temp;
        @disk_list = unique(@disk_list);
    }
    my $Mode        = $Node->mode();
    my $FILER_C     = $Node->name();
    my $Transit_obj = NACL::Transit->new( name => $FILER_C );
    my $filer_state;
    try {
        $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    }
    catch NACL::Transit::Exceptions::Timeout with {
        logcomment("Expected: Caught a Timeout Exception");
        $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    }
    catch NACL::Transit::Exceptions::TransitException with {
        my $exception_object = shift;
    };

    if ( $filer_state =~ /USER|PASS|DBLADECLI/i ) {
        $Transit_obj->set( 'change_state_timeout' => 7200 );
        $Transit_obj->change_state( to => "CLI" );
    }

    my $API_obj;
    if ( $filer_state =~ /MAINT/gi ) {
        my $Host = host($FILER_C);
        $API_obj = NACL::APISet->new(
            hostobj   => $Host,
            category  => "Node",
            interface => "CLI",
            set       => "Maintenance"
        );
    }
    if ( ( $filer_state =~ /CLI/ ) && ( $Mode =~ /CMode/i ) ) {
        $API_obj = $Node->get_7m_or_nodescope_apiset( connid => "console" );
    }
    $API_obj->set_timeout( "connectrec-timeout" => 7200 );
    my $dsk_type;
    if ( $parse_id !~ /_ERT_Maint/ ) {
        my $type_output = $API_obj->execute_command( 'command' => "storage show disk -T -x" );
        foreach my $line ( split( /\n/, $type_output ) ) {
            if ( $line =~ /\S+\s+\d+\s+\d+\s+\S+\s+\S+\s+\S+\s+\S+\s+(\S+)\s*/ ) {
                $dsk_type = $1;
                last;
            }
        }
    }
    if ( ( $dsk_type =~ /MSATA|BSAS|SAS/i ) || ( $parse_id =~ /_ERT_Maint/ ) ) {

        my $Prim_key;
        my @val_arr = ( "SAS LINK INFO", "SATA LINK ERROR INFO", "SATA LINK INFO" );
        foreach my $disk (@disk_list) {
            my $data = $API_obj->execute_command( 'command' => "stsb get_status $disk" );
            foreach my $val (@val_arr) {
                if ( $data =~ /$val/ ) {
                    my @temp_data = split( /\n/, $data );
                    foreach my $line (@temp_data) {
                        if ( $line =~ /$val/ ) {
                            $Prim_key = $val;
                            next;
                        } else {
                            next if ( $line =~ /^=====/ );
                            next if ( $line =~ /stsb mode sense/ );    #burt:1031595
                            next if ( $line =~ /stsb log page/ );      #
                                                                       #                                next if ( $line =~ /SAS address/);				#
                                                                       #                               next if ( $line =~ /Attached SAS address/);			#
                                                                       #                              next if ( $line =~ /Attached PHY ID/);				#burt:1031595
                            last if ( ( $line =~ /^\s*$/ ) && ( $Prim_key ne "" ) );
                            next if ( $line =~ /^\s*$/ );

                            if ( $Prim_key ne "" ) {
                                my @data1 = split( /:/,   $line );
                                my @data2 = split( /\s+/, $data1[1] );
                                shift @data2;
                                $STSB_FOR_EACH_DISKS{$disk}{$Prim_key}{ $data1[0] } = [@data2];
                            }
                        }
                    }
                }
                $Prim_key = "";
            }
        }
        return \%STSB_FOR_EACH_DISKS;
    } else {
        logcomment("Skipping 'stsb get_status ' as this is applicable only for SATA and SAS drives");
        return 1;
    }
}    #end of STSB_Get_Status_Results sub

##############################################################
## Author : pavan.kumar2@netapp
## Description :: Compares stsb get_status data of all the disks for PRE and POST test
## Return : scalar, which contains 0 if two HASHREF are matching else contains 1
## Mandatory : Two HASHREF variables
## Supported Mode : CMODE
##############################################################
sub compare_stsb_get_status_disk_values {
    my (%opts) = validate(
        @_,
        {
            Node   => { type => OBJECT },
            before => { type => HASHREF },
            after  => { type => HASHREF },
        }
    );
    my $Node = $opts{Node};

    my $before = $opts{before};
    my $after  = $opts{after};
    my $flag   = 0;
    my $disk;
    my $disk_type;
    my $d_type;
    my $FILER_C     = $Node->name();
    my $Transit_obj = NACL::Transit->new( name => $FILER_C );
    my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    if ( $filer_state =~ /CLI/gi ) {
        try {
            $disk_type = NACL::CS::StorageDisk->fetch( command_interface => $Node, requested_fields => ['type'] );
            $d_type = $disk_type->type();
        }
        catch NATE::BaseException with {
            logcomment("Re-Executing Command again");
            $Node->refresh_command_interface();
            $disk_type = NACL::CS::StorageDisk->fetch( command_interface => $Node, requested_fields => ['type'] );
            $d_type = $disk_type->type();
        };
    } elsif ( $filer_state =~ /MAINT/gi ) {
        $disk_type = disk_type_maint( Node => $Node );
    }
    my @fail_values;
    foreach my $dsk ( keys %{$after} ) {
        if ( $filer_state =~ /MAINT/gi ) { $d_type = $disk_type->{$dsk}->{'Type'}; }
        foreach my $prim_key ( keys %{ $after->{$dsk} } ) {
            if ( $prim_key =~ /(\S+)\s+\S+.*/i ) { $disk = $1; }
            if ( ( $d_type =~ /$disk/i ) || ( $disk =~ /VERSION/i ) ) {
                foreach my $sec_key ( keys %{ $after->{$dsk}->{$prim_key} } ) {
                    if ( ( $parse_id =~ /(510|407|401|506|504|501|202|406|100)/ ) && ( $sec_key =~ /DWORD|LOS|Disparity/i ) ) {
                        next;
                    } else {
                        if ( $sec_key =~ /PHY/ ) { next; }
                        if ( exists $before->{$dsk}->{$prim_key}->{$sec_key} ) {
                            foreach my $i ( 0 .. $#{ $before->{$dsk}->{$prim_key}->{$sec_key} } ) {
                                if ( $after->{$dsk}->{$prim_key}->{$sec_key}[$i] ne $before->{$dsk}->{$prim_key}->{$sec_key}[$i] ) {
                                    my $val = "**WARNING** : Disk - $dsk : THE VALUE  \'$sec_key\' under \'$prim_key\' ARE DIFFERENT. --->Before ($before->{$dsk}->{$prim_key}->{$sec_key}[$i] ) and After ($after->{$dsk}->{$prim_key}->{$sec_key}[$i] ) <---";
                                    push( @fail_values, $val );
                                    $flag = 1;
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    if ( $flag == 1 ) {
        logcomment("All $d_type values have been compared and are matching except\n");
        foreach (@fail_values) {
            logcomment("$_\n");
        }
    } else {
        logcomment("All $d_type values have been compared and are matching ");
    }
    return $flag;
}    #end of compare_stsb_get_status_disk_values sub

##################################################
## Author : Pavan LK
## Description : Printing scsi logsense data for all disks
## Inputs : Null
## Output : Null
## Pass/Fail criteria: These additional steps are only for BSAS,SATA and MSATA drives
##################################################
sub scsi_logsense_pages {
    my (%opts) = validate( @_, { Node => { type => OBJECT }, } );

    my @SM_Pages_Arr      = ( 2,  3,  5,  6,  0x18, 0x30, 0x32, 0x37 );
    my @SA_Pages_Arr      = ( 2,  3,  5,  6,  0x31, 0x32, 0x35, 0x37 );
    my @SDB_Pages_Lun_Arr = ( 01, 02, 03, 05, 06,   0x0d, 0x18, 0x30 );
    my @SDB_Pages_Arr = ( 0x32, 0x34, 0x35, 0x36, 0x37, 0x38 );
    my @disk_list;
    my $sto_show_data = {};
    my $Node          = $opts{Node};
    my $filer_name    = $Node->name();
    my $Api_Set_Obj;
    my $after;
    my $Transit_obj = NACL::Transit->new( name => $filer_name );
    my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );

    if ( $filer_state =~ /MAINT/gi ) {
        my $Host = host($filer_name);
        $Api_Set_Obj = NACL::APISet->new(
            hostobj   => $Host,
            category  => "Node",
            interface => "CLI",
            set       => "Maintenance"
        );
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
        $after = $Api_Set_Obj->execute_raw_command( 'command' => "storage show disk -T -x" );
    } elsif ( $filer_state =~ /(CLI|UP)/gi ) {
        $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
        $after = $Api_Set_Obj->execute_command( 'command' => "storage show disk -T -x" );
    }
    logcomment("DEBUG:Get filer configruation for filer $filer_name");
    foreach my $line ( split( /\n/, $after ) ) {
        if ( $line =~ /(\S+)\s+(\d+)\s+(\d+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s*/ ) {
            my ( $Device, $SHELF, $BAY, $Serial, $Vendor, $Model, $Rev, $Type ) = ( $line =~ /(\S+)\s+(\d+)\s+(\d+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s*/ );
            if ( $Type =~ /BSAS|MSATA|SATA/ ) {
                push( @disk_list, $Device );
            }
        }
    }

    if ( scalar(@disk_list) != 0 ) {

        #		my $API_obj = $Node->get_7m_or_nodescope_apiset();
        my $FILER_C = $Node->name();
        my $Mode    = $Node->mode();
        $sto_show_data = storage_show_disk_a_data( Node => $Node );

        #Collect the SM/SA/SDB disks
        my ( $ssm, $ssa, $sdb, $dir );
        ( $ssm, $ssa, $sdb ) = ( 0, 0, 0 );
        my %dr_id = ();
        logcomment("DEBUG:Checking Model number of the disks @disk_list");
        foreach my $disk (@disk_list) {
            my $mdl = $sto_show_data->{$disk}->{'Model'};
            logcomment("Filer : $FILER_C : Model of disk $disk is $mdl");
            if ( $mdl =~ /(SA)$/ ) {
                $ssa = 1;
                $dr_id{$disk} = $1;
                logcomment("SA: $disk - $1");
                logcomment("Filbert(SSA): Writing crash dump to file of the $disk - type $dr_id{$disk}");
                foreach my $page (@SA_Pages_Arr) {
                    $Api_Set_Obj->execute_command( 'command' => "scsi logsense -p $page $disk" );
                }
            } elsif ( $mdl =~ /(SM)$/ ) {
                $ssm = 1;
                $dr_id{$disk} = $1;
                logcomment("SM: $disk - $1");
                logcomment("Acorn(SSM):  Scsi modesense of the disk $disk - type $dr_id{$disk}");
                foreach my $page (@SM_Pages_Arr) {
                    $Api_Set_Obj->execute_command( 'command' => "scsi logsense -p $page $disk" );
                }
            } elsif ( $mdl =~ /(SDB)$/ ) {
                $sdb = 1;
                $dr_id{$disk} = $1;
                print "SSD: $disk - $1\n";
                logcomment("Marvell(SDB): Acorn get status of the disk $disk - type $dr_id{$disk}");
                foreach my $page (@SDB_Pages_Lun_Arr) {
                    $Api_Set_Obj->execute_command( 'command' => "scsi logsense -p $page $disk" );
                }
                my $dsk_withot_lun = $disk;
                $dsk_withot_lun =~ s/L\d+$//;
                foreach my $page (@SDB_Pages_Arr) {
                    if ( $page == 0x34 ) {
                        $Api_Set_Obj->execute_command( 'command' => "scsi logsense -p $page -s 0 $dsk_withot_lun" );
                        $Api_Set_Obj->execute_command( 'command' => "scsi logsense -p $page -s 1 $dsk_withot_lun" );
                    } else {
                        $Api_Set_Obj->execute_command( 'command' => "scsi logsense -p $page $dsk_withot_lun" );
                    }
                }
            }
        }
        if ( ( $ssm == 0 ) && ( $ssa == 0 ) && ( $sdb == 0 ) ) {
            logcomment("NO SM/SA/SDB DRIVES found");
        }
    } else {
        logcomment("Skipping 'scsi logsense -p  ' as this is applicable only for SATA drives");
    }
}    #end of scsi_logsense_pages sub

##########################################################################################################
# Author -  Pavan L K
# Description - This subroutine will print and return total number count of disks having disk size more than 2TB.
# Usage - Mandatory parameter - Node object ,
# Mode - CMode (UP/CLI)
# Return - Total number of disks having disk size more than 2TB.
##########################################################################################################
sub storage_disk_show_usable_size {
    my (%opts) = validate( @_, { node_present => { type => ARRAYREF }, } );
    my @Nodes = @{ $opts{node_present} };
    my $disk_count_with_more_than_2TB_size = 0;
    my $hash_with_disks_above_2TB          = {};
    foreach my $Node (@Nodes) {
        my $Transit_obj;
        my $Mode    = $Node->mode();
        my $FILER_C = $Node->name();
        $Transit_obj = NACL::Transit->new( name => $FILER_C );
        my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
        logcomment("DEBUG:$FILER_C : Filer is in $filer_state ");
        if ( $filer_state =~ /CLI|UP/ ) {
            my $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
            $Api_Set_Obj->set_timeout( 'connectrec-timeout' => 7200 );
            $Api_Set_Obj->execute_raw_command( 'command' => "set -showallfields false" );
            $Api_Set_Obj->execute_raw_command( 'command' => "rows 1000" );
            my $output = $Api_Set_Obj->execute_raw_command( 'command' => "storage disk show -fields usable-size" );
            logcomment("Checking disks having size more than 2TB");
            foreach my $line ( split( /\n/, $output ) ) {
                if ( $line =~ /(\S+)\s+(.*)TB\s*/ ) {
                    if ( $2 > 2.0 ) {
                        logcomment("Disk $1 having size $2TB");
                        $hash_with_disks_above_2TB->{$1} = $2;
                    }
                }
            }
            $disk_count_with_more_than_2TB_size = keys {%$hash_with_disks_above_2TB};
            logcomment("Total number of disks having disk size more than 2TB are $disk_count_with_more_than_2TB_size") if ($disk_count_with_more_than_2TB_size);
            return $disk_count_with_more_than_2TB_size;
        }
    }
}

##########################################################################################################
# Author -  Pavan L K
# Description - This subroutine to get required number of spare disks having disk size less than 2TB for normal,BOAB or partition type filers.
# Usage mandatory inputs - Node object and Required spare count
# Mode - CMode (UP/CLI)
# Return - Returns 1 if spare disks present are less than required number
#	   else Array reference of required number of spare disks having disk size less than 2TB.
##########################################################################################################
sub get_required_spares_size_less_than_2TB {
    my (%opts) = validate(
        @_,
        {
            node_present   => { type => OBJECT },
            required_spare => { type => SCALAR },
        }
    );
    my $Total = 0;
    my @Root_Disks;
    my @normal_spares;
    my $Req_Spares = $opts{required_spare};
    my @Disk_Arr_With_Less_2TB;
    my @Disk_Arr_With_More_2TB;
    my $Node = $opts{node_present};
    my $disk_count_with_more_than_2TB_size;
    my $disk_count_with_less_than_2TB_size;
    my $hash_with_disks_above_2TB = {};
    my ( @zeroing, @clear_spares );
    my $Transit_obj;
    my $Mode    = $Node->mode();
    my $FILER_C = $Node->name();
    $Transit_obj = NACL::Transit->new( name => $FILER_C );
    my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    logcomment("DEBUG:$FILER_C : Filer is in $filer_state ");

    if ( $filer_state =~ /CLI|UP/ ) {
        ####################Checking  for type of filer(normal or partition)###################
        my @spares = spare_count_cmode( Node => $Node );
        if ( !@spares ) {
            return 1;
        }
        my (%part_spares);
        foreach (@spares) {
            if ( $_ =~ /(P\d+)$/ ) {
                push( @{ $part_spares{$1} }, $_ );
            } else {
                push( @normal_spares, $_ );
            }
        }
        my @partitions = keys %part_spares;
        #######################################################################################
        if (@partitions) {
            my $part_type;
            logcomment("Number of partitions present are :: @partitions");
            foreach (@partitions) {
                my $dsks = _print_array( \@{ $part_spares{$_} } );
                logcomment( "Number of drives present under the partition $_ : are " . scalar @{ $part_spares{$_} } . " and the drives are:\n" . $dsks );

                if ( @{ $part_spares{$_} } < $Req_Spares ) {
                    logcomment("$FILER_C : CANNOT CREATE AGGREGATE for the partition drives $_, because number of spare are less than $Req_Spares");
                    next;
                } else {
                    $part_type = $_;
                    my $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
                    $Api_Set_Obj->set_timeout( 'connectrec-timeout' => 7200 );
                    $Api_Set_Obj->execute_raw_command( 'command' => "set -showallfields false" );
                    $Api_Set_Obj->execute_raw_command( 'command' => "rows 1000" );
                    my $prompts_answers = [ ".*Do you want to continue.*" => 'y' ];
                    $Api_Set_Obj->execute_raw_command( 'command' => "set test", 'connectrec-match_table' => $prompts_answers );

                    foreach my $disk_check ( @{ $part_spares{$_} } ) {
                        ( my $tmp = $disk_check ) =~ s/\.P\d+$//;

                        #						my $output1 = $Api_Set_Obj->execute_raw_command('command' =>"storage disk show -disk $tmp -physical" );
                        my $output1 = $Api_Set_Obj->execute_raw_command( 'command' => "storage disk show -disk $tmp -fields physical-size" );

                        logcomment("Checking for disk names having disk size less than 2TB");
                        foreach my $line ( split( /\n/, $output1 ) ) {

=head
	                       	if ($line=~/(\S+)\s+\S+\s+\S+\s+.+\_.+(\d{2}).+\s+\S+\s+\S+\s+\d+/){
                                        if ($line=~/(\S+)\s+\S+\s+\S+\s+.+\_.+(\d{2})T.+\s+\S+\s+\S+\s+\d+/){        
                                                if($2 > 2){
                                                	logcomment("Disk $1 having size $2TB");
                                                    $hash_with_disks_above_2TB->{$disk_check} = $2;
                                                }else{
                                                        push(@Disk_Arr_With_Less_2TB,$disk_check);
                                                }

										}else{
                                        	push(@Disk_Arr_With_Less_2TB,$disk_check);
                                        }

                            }
=cut

                            if ( $line =~ /\S+\s+\d+\.*\d*(TB|MB|GB)/ ) {
                                if ( $line =~ /(\S+)\s+(\d+\.*\d*)TB/ ) {
                                    if ( $2 >= 2 ) {
                                        logcomment("Disk $1 having size $2TB");
                                        $hash_with_disks_above_2TB->{$disk_check} = $1;
                                    } else {
                                        push( @Disk_Arr_With_Less_2TB, $disk_check );
                                    }

                                } else {
                                    push( @Disk_Arr_With_Less_2TB, $disk_check );
                                }

                            }

                        }

                    }
                    logcomment("Disk names having disk size less than 2TB are @Disk_Arr_With_Less_2TB");
                    if ( scalar @Disk_Arr_With_Less_2TB < $Req_Spares ) {
                        logcomment("$FILER_C : CANNOT CREATE AGGREGATE for the partition drives $_, because number of spare with less than 2TB are less than $Req_Spares");
                        next;
                    } else {
                        my $API_obj = $Node->get_7m_or_nodescope_apiset();
                        $API_obj->set_timeout( 'connectrec-timeout' => 7200 );
                        my $out = $API_obj->execute_raw_command( 'command' => "aggr status -s -node $FILER_C" );
                        if ( $out !~ /zeroing|not zeroed/i ) {
                            my @return_array;
                            for ( my $i = 0 ; $i < $Req_Spares ; $i++ ) {
                                $return_array[$i] = $Disk_Arr_With_Less_2TB[$i];
                            }
                            logcomment("Disk names can be used for this test are @return_array");
                            return ( \@return_array );
                        } else {

                            while (1) {
                                @zeroing      = ();
                                @clear_spares = ();
                                my $API_obj = $Node->get_7m_or_nodescope_apiset();
                                $API_obj->set_timeout( 'connectrec-timeout' => 7200 );
                                my $out1 = $API_obj->execute_raw_command( 'command' => "aggr status -s -node $FILER_C" );
                                my $out  = $API_obj->execute_raw_command( 'command' => "disk partition show -container-type spare -owner-node-name $FILER_C -fields is-zeroed" );
                                if ( $out =~ /false/ ) {
                                    my $n = 0;
                                    my @lines = split( /\n/, $out );
                                    while ( $n <= $#lines ) {
                                        last if ( $lines[$n] =~ /^-----/ );
                                        $n++;
                                    }
                                    $n++;
                                    foreach my $var ( @lines[ $n .. $#lines ] ) {
                                        $var =~ s/^\s+|\s+$//gi;
                                        if ( $var =~ /\s*(\S+)\s+(true)/ ) {
                                            my $disk = $1;
                                            foreach my $drive (@Disk_Arr_With_Less_2TB) {
                                                if ( $disk eq $drive ) {
                                                    push( @clear_spares, $disk );
                                                }
                                            }

                                        }

                                    }

                                    logcomment( "$FILER_C : Total non zeroing spare count : " . scalar @clear_spares . " and the spare are @clear_spares" ) if (@clear_spares);
                                    logcomment("$FILER_C : NO NON ZEROING SPARES found in the filer ") if ( !scalar @clear_spares );
                                    my $clear_spares = scalar @clear_spares;
                                    if ( $out =~ /not zeroed/i ) {
                                        $API_obj->execute_command( 'command' => "disk zero spares" );
                                        sleep 300;
                                    }
                                    if ( ( scalar @clear_spares ) >= $Req_Spares ) {

                                        logcomment("INFO : $FILER_C : Normal spare count\($clear_spares\) are sufficient to proceed with test execution");
                                        last;
                                    } else {
                                        logcomment("$FILER_C : NOT ENOUGH SPARE are present to create aggregate, NDATE will wait till disk zeroing completes");
                                        sleep(600);
                                    }
                                } else {

                                    my $n = 0;
                                    my @lines = split( /\n/, $out );
                                    while ( $n <= $#lines ) {
                                        last if ( $lines[$n] =~ /^-----/ );
                                        $n++;
                                    }
                                    $n++;
                                    foreach my $var ( @lines[ $n .. $#lines ] ) {
                                        $var =~ s/^\s+|\s+$//gi;
                                        if ( $var =~ /\s*(\S+)\s+(true)/ ) {
                                            my $disk = $1;
                                            foreach my $drive (@Disk_Arr_With_Less_2TB) {
                                                if ( $disk eq $drive ) {
                                                    push( @clear_spares, $disk );
                                                }
                                            }

                                        }

                                    }

                                    logcomment("NO more ZEROING SPARE DRIVES found");
                                    last;
                                }

                            }
                            my @return_array;
                            for ( my $i = 0 ; $i < $Req_Spares ; $i++ ) {
                                $return_array[$i] = $clear_spares[$i];
                            }
                            logcomment("Disk names can be used for this test are @return_array");
                            return ( \@return_array );

                        }

                    }

                }
            }
            return 1;

        }

        if (@normal_spares) {
            my $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
            $Api_Set_Obj->set_timeout( 'connectrec-timeout' => 7200 );
            $Api_Set_Obj->execute_raw_command( 'command' => "set -showallfields false" );
            $Api_Set_Obj->execute_raw_command( 'command' => "rows 1000" );
            my $output1 = $Api_Set_Obj->execute_raw_command( 'command' => "aggr show -r -node $FILER_C" );
            my $n       = 0;
            my @lines   = split( /\n/, $output1 );
            while ( $n <= $#lines ) {
                last if ( $lines[$n] =~ /-----/ );
                $n++;
            }
            $n++;
            foreach my $line ( @lines[ $n .. $#lines ] ) {
                last if ( $line =~ /^\s*$/ );
                if ( $line =~ /\S+\s+(\S+)\s+\d+\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+/ ) {
                    push( @Root_Disks, $1 );
                }
            }
            logcomment("The root disk are : @Root_Disks");
            my %hash_check_root_disk = map { $_ => 1 } @Root_Disks;
            my $output = $Api_Set_Obj->execute_raw_command( 'command' => "disk show -physical -home $FILER_C" );
            logcomment("Checking for disk names having disk size more than 2TB");
            foreach my $line ( split( /\n/, $output ) ) {
                if ( $line =~ /(\S+)\s+\S+\s+\S+\s+.+\_.+(\d{2}).+\s+\S+\s+\S+\s+\d+/ ) {
                    $Total++;
                    if ( $line =~ /(\S+)\s+\S+\s+\S+\s+.+\_.+(\d{2})T.+\s+\S+\s+\S+\s+\d+/ ) {
                        next if ( exists $hash_check_root_disk{$1} );
                        if ( $2 > 2 ) {
                            logcomment("Disk $1 having size $2TB");
                            $hash_with_disks_above_2TB->{$1} = $2;
                        } else {
                            push( @Disk_Arr_With_Less_2TB, $1 );
                        }

                    } else {
                        next if ( exists $hash_check_root_disk{$1} );
                        push( @Disk_Arr_With_Less_2TB, $1 );
                    }

                }
            }

            $disk_count_with_more_than_2TB_size = keys {%$hash_with_disks_above_2TB};
            @Disk_Arr_With_More_2TB             = keys {%$hash_with_disks_above_2TB};
            $disk_count_with_less_than_2TB_size = scalar @Disk_Arr_With_Less_2TB;
            logcomment("Total number of disks having disk size more than 2TB are:$disk_count_with_more_than_2TB_size ");
            logcomment("Total number of disks having disk size less than 2TB are:$disk_count_with_less_than_2TB_size ");
            logcomment("The available spare disks having disk size less than 2TB which can be used for this test are @Disk_Arr_With_Less_2TB") if ( scalar @Disk_Arr_With_Less_2TB );
            if ( ( $Total - scalar(@Root_Disks) - $disk_count_with_more_than_2TB_size ) < $Req_Spares ) {

                return 1;
            } else {

                my $API_obj = $Node->get_7m_or_nodescope_apiset();
                $API_obj->set_timeout( 'connectrec-timeout' => 7200 );
                my $out = $API_obj->execute_command( 'command' => "aggr status -s" );
                if ( $out !~ /zeroing|not zeroed/i ) {
                    my @return_array;
                    for ( my $i = 0 ; $i < $Req_Spares ; $i++ ) {
                        $return_array[$i] = $Disk_Arr_With_Less_2TB[$i];
                    }
                    return ( \@return_array );
                } else {
                    my @zeroed_greater_than_2TB;
                    my @clear_spares_final = ();
                    my @final_result_spare = ();
                    while (1) {
                        @zeroing      = ();
                        @clear_spares = ();
                        my $API_obj = $Node->get_7m_or_nodescope_apiset();
                        $API_obj->set_timeout( 'connectrec-timeout' => 7200 );
                        my $out = $API_obj->execute_command( 'command' => "aggr status -s" );
                        if ( $out =~ /zeroing|not zeroed/i ) {
                            my $n = 0;
                            my @lines = split( /\n/, $out );
                            while ( $n <= $#lines ) {
                                last if ( $lines[$n] =~ /^-----/ );
                                $n++;
                            }
                            $n++;
                            foreach my $var ( @lines[ $n .. $#lines ] ) {
                                $var =~ s/^\s+|\s+$//gi;
                                if ( $var =~ /spare\s*(\S+).*(not zeroed|zeroing)/ ) {
                                    push( @zeroing, $1 );
                                }
                                if ( $var !~ /zeroing|not zeroed/ ) {
                                    if ( $var =~ /spare\s*(\S+)/ ) {
                                        push( @clear_spares, $1 );

                                    }
                                }
                            }

                            my $i = 0;
                            foreach my $drive (@Disk_Arr_With_More_2TB) {
                                foreach my $disk_use (@clear_spares) {
                                    if ( $disk_use eq $drive ) {
                                        push( @zeroed_greater_than_2TB, $drive );
                                    }
                                }
                            }
                            logcomment( "$FILER_C : Zeroing spare count is :: " . scalar @zeroing . " and the spares are @zeroing" );
                            logcomment( "$FILER_C : Total non zeroing spare count : " . scalar @clear_spares . " and the spare are @clear_spares" ) if (@clear_spares);
                            logcomment("$FILER_C : NO NON ZEROING SPARES found in the filer ") if ( !scalar @clear_spares );
                            my $clear_spares = scalar @clear_spares;
                            if ( $out =~ /not zeroed/i ) {
                                $API_obj->execute_command( 'command' => "disk zero spares" );
                                sleep 300;
                            }
                            if ( ( ( scalar @clear_spares ) - ( scalar @zeroed_greater_than_2TB ) ) >= $Req_Spares ) {

                                logcomment("Info : $FILER_C : Normal spare count\($clear_spares\) are sufficient to proceed with test execution");
                                last;
                            } elsif ( ( ( scalar @zeroing ) + ( scalar @clear_spares ) ) >= $Req_Spares ) {
                                logcomment("$FILER_C : NOT ENOUGH SPARE present to create aggregate, NDATE will wait till disk zeroing completes");
                                sleep(600);
                            }
                        } else {
                            my $n = 0;
                            my @lines = split( /\n/, $out );
                            while ( $n <= $#lines ) {
                                last if ( $lines[$n] =~ /^-----/ );
                                $n++;
                            }
                            $n++;
                            foreach my $var ( @lines[ $n .. $#lines ] ) {
                                $var =~ s/^\s+|\s+$//gi;
                                if ( $var =~ /spare\s*(\S+).*(not zeroed|zeroing)/ ) {
                                    push( @zeroing, $1 );
                                }
                                if ( $var !~ /zeroing|not zeroed/ ) {
                                    if ( $var =~ /spare\s*(\S+)/ ) {
                                        push( @clear_spares, $1 );

                                    }
                                }
                            }

                            my $i = 0;
                            foreach my $drive (@Disk_Arr_With_More_2TB) {
                                foreach my $disk_use (@clear_spares) {
                                    if ( $disk_use eq $drive ) {
                                        push( @zeroed_greater_than_2TB, $drive );
                                    }
                                }
                            }
                            logcomment("NO more ZEROING SPARRE DRIVES found");
                            last;

                        }
                    }

                    foreach my $clr_cpr (@clear_spares) {
                        my $Disk = NACL::C::Disk->get_ngsh_diskname(
                            'command_interface' => $Node,
                            disk                => $clr_cpr,
                        );
                        push( @clear_spares_final, $Disk );
                    }
                    foreach my $dsk (@Disk_Arr_With_Less_2TB) {
                        foreach my $clear_spr (@clear_spares_final) {
                            if ( $dsk eq $clear_spr ) {
                                push( @final_result_spare, $dsk );

                            }
                        }
                    }

=head
                        foreach my $dsk (@Disk_Arr_With_Less_2TB){
                                foreach my $clr_cpr (@clear_spares){
                                        ( my $new_disk = $dsk ) =~ s/(\w+\.)//;
                                        if ($clr_cpr =~ /$new_disk$/){
                                                push (@clear_spares_final,$dsk);
                                        }
                                }
                        }
=cut

                    @clear_spares = ();
                    @clear_spares = @final_result_spare;

                    my @result_array;
                    my $flag1;
                    foreach my $drive (@clear_spares) {
                        $flag1 = 0;
                        foreach my $disk_use (@zeroed_greater_than_2TB) {
                            if ( $disk_use eq $drive ) {
                                $flag1 = 1;
                            }
                        }
                        if ( $flag1 == 0 ) {
                            push( @result_array, $drive );
                        }
                    }
                    my @return_array;
                    for ( my $i = 0 ; $i <= $Req_Spares ; $i++ ) {
                        $return_array[$i] = $result_array[$i];
                    }
                    return ( \@return_array );
                }

            }

        }
    }

}
#######################################################################################
## Author :  aditis@netapp.com
## Description : storage show data will be captured of every disk
##
#######################################################################################
sub storage_show_drive {
    my (%opts) = validate(
        @_,
        {
            API_OBJ => { type => OBJECT },
            Node    => { type => OBJECT }
        }
    );
    my $Node    = $opts{Node};
    my $API_OBJ = $opts{API_OBJ};
    my $FILER_C = $Node->name();
    my @disk_list;

    #    my @disk_list = list_of_disk( Node => $Node );
    @disk_list = @{ disk_show_drive_maint( API_Obj => $API_OBJ, Filer => $FILER_C )->{'driveA'} };
    my @dsk_arr;
    my $serial;
    my $model;
    my $rpm;
    my $revision;
    my $poh;
    my $glist;
    my $ratedlife;
    my $spareblocks;
    my $storage_struct = {};
    my $vendor;

    foreach my $disk (@disk_list) {
        $disk =~ s/(^\s+)|(\s+$)//ig;
        next if ( $disk !~ /\S/ );
        push( @dsk_arr, $disk );
    }
    my @disk_array = grep { ( ( $_ !~ /P\d+$/ ) && ( $_ =~ /\S/ ) ) } @dsk_arr;

    my $disk_length = @disk_array;
    my $test_result = 0;
    my $dsks        = _print_array( \@disk_array );
    $API_OBJ->set_timeout( 'connectrec-timeout' => 7200 );
    logcomment( "DEBUG:Disks used for executing storage show command are $disk_length and disks are:\n" . $dsks );
    foreach my $disk (@disk_array) {
        my $dsk;
        if ( $disk =~ /\w+\.(\w+\.\w+)/g ) { $dsk = $1; }
        if ( $disk_length > 0 ) {
            my $output = $API_OBJ->execute_command( 'command' => "storage show disk -a $disk" );

            #my $after = $API_OBJ->execute_command('command' => "");
            #my $output = $after.$output;
            foreach my $line ( split( /\n/, $output ) ) {
                if ( $line =~ /Vendor:\s*(\S+)\s*/ ) {
                    $vendor = $1;
                } elsif ( $line =~ /Serial:\s*(\S+)\s*/ ) {
                    $serial = $1;
                } elsif ( $line =~ /Model:\s*(\S+)\s*/ ) {
                    $model = $1;
                } elsif ( $line =~ /Rev:\s*(\S+)/ ) {
                    $revision = $1;
                } elsif ( $line =~ /RPM:\s*(\d+)/ ) {
                    $rpm = $1;
                } elsif ( $line =~ /Power-on Hours:\s*(\S+)/ ) {
                    $poh = $1;
                } elsif ( $line =~ /Glist count:\s*(\S+)/ ) {
                    $glist = $1;
                } elsif ( $line =~ /Rated life used:\s*(\S+)/ ) {
                    $ratedlife = $1;
                } elsif ( $line =~ /Spare blocks consumed:\s*(\S+)/ ) {
                    $spareblocks = $1;
                }
            }
        }
        $storage_struct->{$dsk} = {
            Vendor                => $vendor,
            Serial                => $serial,
            Model                 => $model,
            Rev                   => $revision,
            RPM                   => $rpm,
            Power_on_Hours        => $poh,
            Glist_count           => $glist,
            Rated_life_used       => $ratedlife,
            Spare_blocks_consumed => $spareblocks
        };
    }
    return $storage_struct;
}
########################################################################################
##Author :  aditis@netapp.com,nmamatha@netapp.com
## Description: comparison of storage show disk data will be done
########################################################################################
sub compare_storage_show_drive {
    my (%opts) = validate(
        @_,
        {
            Test                    => { type => OBJECT },
            Node                    => { type => OBJECT },
            pre_storage_show_drive  => { type => HASHREF },
            post_storage_show_drive => { type => HASHREF }

              #        disk_list                => { type => ARRAYREF }
        }
    );
    my $Node = $opts{Node};
    my $dsk;
    my $Test = $opts{Test};
    my ( $disk_type, $d_type );
    my $pre_storage_show_drive  = $opts{pre_storage_show_drive};
    my $post_storage_show_drive = $opts{post_storage_show_drive};
    my $FILER_C                 = $Node->name();
    my $Transit_obj             = NACL::Transit->new( name => $FILER_C );
    my $filer_state             = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    my $test_flag               = 0;
    if ( $filer_state =~ /CLI/gi ) {
        $disk_type = NACL::CS::StorageDisk->fetch( command_interface => $Node, requested_fields => ['type'] );
        $d_type = $disk_type->type();
        logcomment("DEBUG:disk type is $d_type");
    } elsif ( $filer_state =~ /MAINT/gi ) {
        $disk_type = disk_type_maint( Node => $Node );
        foreach $dsk ( keys %$disk_type ) {
            $d_type = $disk_type->{$dsk}->{'Type'};
            if ($d_type) {
                logcomment("DEBUG:disk type is $d_type");
                last;
            }
        }
    }
    my @aggr_drives = ();                                                                          #Burt 1024388 nmamatha
    my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    if ( $filer_state =~ /CLI/gi ) {                                                               #@change - abalaji
        try {
            my @non_root_aggr;
            my @aggrs = NACL::C::Aggregate->find(
                command_interface => $Node,
                filter            => { nodes => [$FILER_C], 'root' => 'false' }
            );
            foreach my $aggr (@aggrs) {
                my $aggregates = $aggr->get_one_state_attribute('aggregate');
                push( @non_root_aggr, $aggregates );
            }
            @non_root_aggr = sort { $b cmp $a } @non_root_aggr;
            logcomment("$FILER_C :Non root aggregates are @non_root_aggr");
            logcomment("DEBUG : Executing the aggr status -r command for fetching the drives");
            foreach my $aggr (@non_root_aggr) {
                my $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
                $Api_Set_Obj->set_timeout( "connectrec-timeout" => '7200' );
                my $raw_output = $Api_Set_Obj->execute_command( 'command' => "aggr status -r $aggr" );
                my @sysconf_lines = split( /\r?\n/, $raw_output );
                foreach my $line (@sysconf_lines) {
                    if ( $line =~ /(dparity|parity|data)\s*(\S+)\s*.*/ ) {
                        my $dsk = $2;
                        if ( $dsk =~ /\w+\.(\d+\.\w+)/ig ) {
                            push( @aggr_drives, $1 );
                        }
                    }
                }
            }
        }
        catch NACL::Exceptions::NoElementsFound with {
            logcomment("$FILER_C : Non root aggregates are NOT found in the filer");
        };
        logcomment("DEBUG : Drives present in the aggr @aggr_drives") if (@aggr_drives);    #Burt 1024388 nmamatha
    }
    foreach $dsk ( keys %$pre_storage_show_drive ) {

        #printing Serial and Model for disk
        my @fail_arr = ();
        my $disk_parameter;
        my @warning;
        my $var;
        my $pre_storage_show_drive = $opts{pre_storage_show_drive};
        $disk_parameter = "DISK : $dsk";
        my $serial_num;
        my $model_num;
        my $vendor_id;
        $vendor_id  = $pre_storage_show_drive->{$dsk}->{'Vendor'};
        $serial_num = $pre_storage_show_drive->{$dsk}->{'Serial'};
        $model_num  = $pre_storage_show_drive->{$dsk}->{'Model'};
        $serial_num =~ s/ //g;
        $model_num =~ s/ //g;
        my $len_serial = length($serial_num);
        $Test->nlog("...............................................................");
        my $len_model = length($model_num);

        if ( $len_serial <= 20 ) {
            $var = "Serial         \t: $pre_storage_show_drive->{$dsk}->{'Serial'}";
            $Test->nlog(". Comment: $disk_parameter\t- $var");

        } else {
            push( @warning, "**WARNING** : For Disk $dsk Serial is $pre_storage_show_drive->{$dsk}->{'Serial'} IS NOT IN NADQ Spec FORMAT " );
        }
        if ( $vendor_id =~ /NETAPP/ ) {
            $var = "Vendor         \t: $pre_storage_show_drive->{$dsk}->{'Vendor'}";
            $Test->nlog(". Comment: $disk_parameter\t- $var");
        } else {
            push( @warning, "**WARNING** : For Disk $dsk Vendor is $pre_storage_show_drive->{$dsk}->{'Vendor'} , SHOULD BE NETAPP" );
        }
        if ( ( $len_model >= 16 ) || ( $len_model >= 20 ) ) {
            $var = "Model          \t: $pre_storage_show_drive->{$dsk}->{'Model'}";
            $Test->nlog(". Comment: $disk_parameter\t- $var");
        } else {
            push( @warning, "**WARNING** : For Disk $dsk Model is $pre_storage_show_drive->{$dsk}->{'Model'} IS NOT IN NADQ Spec FORMAT " );
        }

        #checking RPM is N/a or 7200 | 10K

        if ( $d_type !~ /SSD/ ) {
            if ( $pre_storage_show_drive->{$dsk}->{'RPM'} =~ /7200|10000/i ) {
                $var = "RPM            \t: $pre_storage_show_drive->{$dsk}->{'RPM'}";
                $Test->nlog(". Comment: $disk_parameter\t- $var");
            } else {
                push( @warning, "**WARNING** : For Disk  $dsk RPM is $pre_storage_show_drive->{$dsk}->{'RPM'} " );
            }
        }
        if ( $pre_storage_show_drive->{$dsk}->{'Rev'} =~ /NA|NQ|NT/i ) {
            $var = "Revision       \t: $pre_storage_show_drive->{$dsk}->{'Rev'}";
            $Test->nlog(". Comment: $disk_parameter\t- $var");
        } else {
            $var = "Revision       \t: $pre_storage_show_drive->{$dsk}->{'Rev'}";
            $Test->nlog(". Comment: $disk_parameter\t- $var");
            push( @warning, "**WARNING** : For Disk  $dsk  Revision is $pre_storage_show_drive->{$dsk}->{'Rev'}, SHOULD BE IN THE FORMAT NAxx|NQxx|NTxx " );
        }

        #checking Power on Hours, Glist count #Burt 1024388 nmamatha
        if ( ( $pre_storage_show_drive->{$dsk}->{'Power_on_Hours'} =~ /N\/A/i ) || ( $post_storage_show_drive->{$dsk}->{'Power_on_Hours'} =~ /N\/A/i ) ) {
            if ( ( $pre_storage_show_drive->{$dsk}->{'Power_on_Hours'} !~ /N\/A/i ) && ( $post_storage_show_drive->{$dsk}->{'Power_on_Hours'} =~ /N\/A/i ) ) {
                my $flag = 0;
                foreach my $disk1 (@aggr_drives) {
                    if ( $disk1 =~ /$dsk/i ) {
                        logcomment("Expected Behavior - Non Root Aggregate Drive : Power on Hours for $dsk , Pretest value of POH -> $pre_storage_show_drive->{$dsk}->{'Power_on_Hours'} and Posttest value of POH -> $post_storage_show_drive->{$dsk}->{'Power_on_Hours'}");
                        $flag = 1;
                        last;
                    }
                }
                if ( $flag == 0 ) {
                    push( @warning, "**WARNING** : Power on Hours for $dsk , Pretest value of POH -> $pre_storage_show_drive->{$dsk}->{'Power_on_Hours'} and Posttest value of POH -> $post_storage_show_drive->{$dsk}->{'Power_on_Hours'}\n" );
                }
            } else {
                logcomment("Power on Hours for $dsk , Pretest value of POH -> $pre_storage_show_drive->{$dsk}->{'Power_on_Hours'} and Posttest value of POH -> $post_storage_show_drive->{$dsk}->{'Power_on_Hours'}");
            }
        } elsif ( ( $pre_storage_show_drive->{$dsk}->{'Power_on_Hours'} =~ /\S+/ ) && ( $post_storage_show_drive->{$dsk}->{'Power_on_Hours'} =~ /\S+/ ) ) {
            if ( int( $pre_storage_show_drive->{$dsk}->{'Power_on_Hours'} ) > int( $post_storage_show_drive->{$dsk}->{'Power_on_Hours'} ) ) {
                $var = "Power on Hours \t: $post_storage_show_drive->{$dsk}->{'Power_on_Hours'}";
                $Test->nlog(". Comment: $disk_parameter\t- $var");
                push( @fail_arr, "**FAIL** : Power on Hours for $dsk are decremented, PRE_TEST value of POH -> $pre_storage_show_drive->{$dsk}->{'Power_on_Hours'} and POST_TEST value of POH -> $post_storage_show_drive->{$dsk}->{'Power_on_Hours'}" );
                if (@fail_arr) {
                    logcomment("**FAIL** : Power on Hours for $dsk are decremented, PRE_TEST value of POH -> $pre_storage_show_drive->{$dsk}->{'Power_on_Hours'} and POST_TEST value of POH -> $post_storage_show_drive->{$dsk}->{'Power_on_Hours'}");
                    logresult( 'FAIL', "Power on Hours for $dsk are decremented, PRE_TEST value of POH -> $pre_storage_show_drive->{$dsk}->{'Power_on_Hours'} and POST_TEST value of POH -> $post_storage_show_drive->{$dsk}->{'Power_on_Hours'}" );
                    $test_flag = 1;
                }
            } else {
                $var = "Power on Hours \t: $pre_storage_show_drive->{$dsk}->{'Power_on_Hours'}";
                $Test->nlog(". Comment: $disk_parameter\t- $var");
            }
        } else {
            push( @warning, "**WARNING** : Power on Hours for $dsk is missing, Pretest value of POH -> $pre_storage_show_drive->{$dsk}->{'Power_on_Hours'} and Posttest value of POH -> $post_storage_show_drive->{$dsk}->{'Power_on_Hours'}" );
        }
        if ( ( $pre_storage_show_drive->{$dsk}->{'Glist_count'} =~ /N\/A/ig ) || ( $post_storage_show_drive->{$dsk}->{'Glist_count'} =~ /N\/A/ig ) ) {
            if ( ( int( $pre_storage_show_drive->{$dsk}->{'Glist_count'} ) != 0 ) && ( $post_storage_show_drive->{$dsk}->{'Glist_count'} =~ /N\/A/ig ) ) {
                push( @warning, "**WARNING** : Glist count for $dsk , Pretest value of Glist count -> $pre_storage_show_drive->{$dsk}->{'Glist_count'} and Posttest value of Glist count -> $post_storage_show_drive->{$dsk}->{'Glist_count'} \n" );
            } else {
                logcomment(" Glist count for $dsk , Pretest value of Glist count -> $pre_storage_show_drive->{$dsk}->{'Glist_count'} and Posttest value of Glist count -> $post_storage_show_drive->{$dsk}->{'Glist_count'} ");
            }
        } elsif ( ( $pre_storage_show_drive->{$dsk}->{'Glist_count'} =~ /\S+/ ) && ( $post_storage_show_drive->{$dsk}->{'Glist_count'} =~ /\S+/ ) ) {
            if ( int( $pre_storage_show_drive->{$dsk}->{'Glist_count'} ) > int( $post_storage_show_drive->{$dsk}->{'Glist_count'} ) ) {
                $var = "Glist count    \t: $post_storage_show_drive->{$dsk}->{'Glist_count'}";
                $Test->nlog(". Comment: $disk_parameter\t- $var");
                push( @warning, "**WARNING** : Glist count for $dsk are decremented, Pretest value of Glist count -> $pre_storage_show_drive->{$dsk}->{'Glist_count'} and Posttest value of Glist count -> $post_storage_show_drive->{$dsk}->{'Glist_count'} " );
            } else {
                $var = "Glist count    \t: $post_storage_show_drive->{$dsk}->{'Glist_count'}";
                $Test->nlog(". Comment: $disk_parameter\t- $var");
            }
        } else {
            push( @warning, "**WARNING** : Glist count for $dsk is missing, Pretest value of Glist count -> $pre_storage_show_drive->{$dsk}->{'Glist_count'} and Posttest value of Glist count -> $post_storage_show_drive->{$dsk}->{'Glist_count'} " );
        }

        if ( $d_type =~ /SSD/ ) {
            if ( int( $pre_storage_show_drive->{$dsk}->{'Rated_life_used'} ) > int( $post_storage_show_drive->{$dsk}->{'Rated_life_used'} ) ) {
                $var = "Rated life used\t: $post_storage_show_drive->{$dsk}->{'Rated_life_used'}";
                $Test->nlog(". Comment: $disk_parameter\t- $var");
                push( @warning, "**WARNING** : Rated life used for $dsk are decremented, Pretest value of  Rated life used -> $pre_storage_show_drive->{$dsk}->{'Rated_life_used'} and Posttest value of Rated life used -> $post_storage_show_drive->{$dsk}->{'Rated_life_used'}" );
            } else {
                $var = "Rated life used\t: $post_storage_show_drive->{$dsk}->{'Rated_life_used'}";
                $Test->nlog(". Comment: $disk_parameter\t- $var");

            }
            if ( int( $pre_storage_show_drive->{$dsk}->{'Spare_blocks_consumed'} ) > int( $post_storage_show_drive->{$dsk}->{'Spare_blocks_consumed'} ) ) {
                $var = "Spare blocks   \t: $post_storage_show_drive->{$dsk}->{'Spare_blocks_consumed'}";
                $Test->nlog(". Comment: $disk_parameter\t- $var");
                push( @warning, "**WARNING** : Spare blocks consumed for $dsk are decremented, Pretest value of  Spare blocks consumed -> $pre_storage_show_drive->{$dsk}->{'Spare_blocks_consumed'} and Posttest value of Spare blocks consumed -> $post_storage_show_drive->{$dsk}->{'Spare_blocks_consumed'} " );
            } else {
                $var = "Spare blocks   \t: $post_storage_show_drive->{$dsk}->{'Spare_blocks_consumed'}";
                $Test->nlog(". Comment: $disk_parameter\t- $var");
            }

        }

        grep { logcomment("$_") } @warning;
        $Test->nlog("...............................................................");
    }
    return $test_flag;
}

########################################################################################
##Author :  aditis@netapp.com
## Description: return the type of disk in maintenance mode
########################################################################################
sub disk_type_maint {
    my (%opts) = validate( @_, { Node => { type => OBJECT }, } );
    my $Node = $opts{Node};
    my $FILER_C = $Node->name();
    my $after;
    my $result      = {};
    my $Host        = host($FILER_C);
    my $Api_Set_Obj = NACL::APISet->new(
        hostobj   => $Host,
        category  => "Node",
        interface => "CLI",
        set       => "Maintenance"
    );
    $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );

    #    $after=$Api_Set_Obj->execute_raw_command('command' => "aggr status -r");
    #    if ($after =~ /No root aggregate found/ig){
    sleep(10);
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $after = $Api_Set_Obj->execute_raw_command( 'command' => "storage show disk -T -x" );
    foreach my $line ( split( /\n/, $after ) ) {
        if ( $line =~ /(\S+)\s*(\d+)\s*(\d+)\s*(\S+)\s*(\S+)\s*(\S+)\s*(\S+)\s*(\S+)\s*/ ) {
            my ( $Device, $SHELF, $BAY, $Serial, $Vendor, $Model, $Rev, $Type ) = ( $line =~ /(\S+)\s*(\d+)\s*(\d+)\s*(\S+)\s*(\S+)\s*(\S+)\s*(\S+)\s*(\S+)\s*/ );
            my $key = $1;
            $result->{$key} = {
                'Device' => $Device,
                'SHELF'  => $SHELF,
                'BAY'    => $BAY,
                'SERIAL' => $Serial,
                'VENDOR' => $Vendor,
                'MODEL'  => $Model,
                'REV'    => $Rev,
                'Type'   => $Type
            };
        }
    }

=head
#    }else {
    	foreach my $line (split(/\n/,$after)){
    		if ( $line =~ /(\S+)\s+(\S+)\s+(\S+)\s+(\d+)\s+(\d+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)/) {
    		my ($RAID, $Device, $HA, $SHELF, $BAY, $CHAN, $Pool, $Type, $RPM, $Used, $Phys) = ($line =~ /(\S+)\s+(\S+)\s+(\S+)\s+(\d+)\s+(\d+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)/);
		my $key = $2;
		$result->{$key} = {
	                'RAID Disk' => $RAID,
	                'Device'    => $Device,
        	        'HA'        => $HA,
                	'SHELF'     => $SHELF,
	                'BAY'       => $BAY,
        	        'CHAN'      => $CHAN,
                	'Pool'      => $Pool,
	                'Type'      => $Type,
        	        'RPM'       => $RPM,
                	'Used'      => $Used,
	                'Phys'      => $Phys
        		};
        	}
		if ( $line =~ /(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\d+)\s+(\d+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)/) {
		my ($RAID, $Disk, $Device, $HA, $SHELF, $BAY, $CHAN, $Pool, $Type, $RPM, $Used, $Phys) = ($line =~ /(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\d+)\s+(\d+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)/);
		my $key = $3;
		$result->{$key} = {
	                'RAID'   => $RAID,
	                'Disk'   => $Disk,
        	        'Device' => $Device,
                	'HA'     => $HA,
	                'SHELF'  => $SHELF,
        	        'BAY'    => $BAY,
                	'CHAN'   => $CHAN,
	                'Pool'   => $Pool,
        	        'Type'   => $Type,
                	'RPM'    => $RPM,
	                'Used'   => $Used,
        	        'Phys'   => $Phys
            	};
		}
    	} 	
    }
=cut

    return $result;
}

###################################################################################################
## Author : himangin@netapp.com
## Subroutine converts any format (KB/GB/Blocks) of disk size to the nearest higher unit possible
## Two return values - 1) String is which will contain the disk size with its unit 2) the size value
## All the parameters are optional, one and only one parameter should be passed at a time
###################################################################################################
sub readable_disk_size {
    my (%opts) = validate(
        @_,
        {
            Blocks => { type => SCALAR, default => undef, optional => 1 },
            Bytes  => { type => SCALAR, default => undef, optional => 1 },
            KB     => { type => SCALAR, default => undef, optional => 1 },
            MB     => { type => SCALAR, default => undef, optional => 1 },
            GB     => { type => SCALAR, default => undef, optional => 1 },
            TB     => { type => SCALAR, default => undef, optional => 1 }
        }
    );
    my $readable_value;
    my $string;
    my ( $bytes_flag, $kb_flag, $mb_flag );
    if ( defined $opts{Blocks} ) {
        my $disk_capacity_total = $opts{Blocks};
        $readable_value = int( ( $disk_capacity_total / 2147483648 ) * 1000 );
        if ( $readable_value > 1024 ) {
            $readable_value = int( $readable_value / 1024 );
            $string         = "$readable_value TB";
            return ( $string, $readable_value );
        } else {
            $string = "$readable_value GB";
            return ( $string, $readable_value );
        }
    } elsif ( defined $opts{Bytes} ) {
        $bytes_flag = 1;
    } elsif ( defined $opts{KB} ) {
        $kb_flag = 1;
    } elsif ( defined $opts{MB} ) {
        $mb_flag = 1;
    } elsif ( defined $opts{GB} ) {
        $readable_value = $opts{GB};
        if ( $readable_value > 1024 ) {
            $readable_value = int( $readable_value / 1024 );
            $string         = "$readable_value TB";
            return ( $string, $readable_value );
        } else {
            $string = "$readable_value GB";
            return ( $string, $readable_value );
        }
    } elsif ( defined $opts{TB} ) {
        $readable_value = $opts{TB};
        $string         = "$readable_value TB";
        return ( $string, $readable_value );
    }
    if ($mb_flag) {
        $readable_value = $opts{MB};
        if ( $readable_value > 1024 ) {
            $readable_value = int( $readable_value / 1024 );
            if ( $readable_value > 1024 ) {
                $readable_value = int( $readable_value / 1024 );
                $string         = "$readable_value TB";
                return ( $string, $readable_value );
            } else {
                $string = "$readable_value GB";
                return ( $string, $readable_value );
            }
        } else {
            $string = "$readable_value MB";
            return ( $string, $readable_value );
        }
    }
    if ( ($bytes_flag) || ($kb_flag) ) {
        if ($bytes_flag) {
            $readable_value = int( $opts{Bytes} / (1048567) );    # 1MB = 1048567 Bytes
            $mb_flag = 1;
        } elsif ($kb_flag) {
            $readable_value = $opts{KB};
            if ( $readable_value > 1024 ) {
                $readable_value = int( $readable_value / 1024 );
                if ( $readable_value > 1024 ) {
                    $mb_flag = 1;
                } else {
                    $string = "$readable_value MB";
                    return ( $string, $readable_value );
                }
            } else {
                $string = "$readable_value KB";
                return ( $string, $readable_value );
            }
        }
        if ($mb_flag) {
            if ( $readable_value > 1024 ) {
                $readable_value = int( $readable_value / 1024 );
                if ( $readable_value > 1024 ) {
                    $readable_value = int( $readable_value / 1024 );
                    $string         = "$readable_value TB";
                    return ( $string, $readable_value );
                } else {
                    $string = "$readable_value GB";
                    return ( $string, $readable_value );
                }
            } else {
                $string = "$readable_value MB";
                return ( $string, $readable_value );
            }
        }
    }
}

#######################################################################################################
# Author - vpankaj@netapp.com
# Description - Check the status of disk qual
# Supported Mode - CMode/7mode
#######################################################################################################
sub disk_qual_Status {
    my (%opts) = validate( @_, { API => { type => OBJECT }, } );
    my $Api_Set_Obj = $opts{API};
    my $timeout     = $Api_Set_Obj->get_timeout();
    my $TIME;
    if ( $timeout < 600 ) {
        $TIME = 700;
    } else {
        $TIME = $timeout;
    }
    my $output;
    while (1) {
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => $TIME );
        $output = $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual status" );
        if ( $output =~ /idle/ ) {
            logcomment("Disk Qual is Completed and Status is idle.");
            last;
        } else {
            logcomment("Disk Qual is running.");
            sleep(600);
        }
    }
    return $output;
}

#######################################################################################################
# Author - himangin@netapp.com
# Description - Performance Test: T1 to T8, Sequential Read, OD/MD/ID diameter ranges, Que of 1 to 8, 4-256K Transfer Length
# Supported Mode - CMode/7mode Maintenance
#######################################################################################################
sub run_dq_perfm_1_8_Cmode {
    my (%opts) = validate(
        @_,
        {
            Node      => { type => OBJECT },
            API       => { type => OBJECT },
            MODE      => { type => SCALAR, default => "MAINT" },
            fw        => { type => SCALAR, optional => 1 },
            drid      => { type => SCALAR },
            que_path  => { type => SCALAR },
            disk_list => { type => ARRAYREF },
        }
    );
    my $node        = $opts{Node};
    my $Api_Set_Obj = $opts{API};
    my $MODE        = $opts{MODE};
    my $fw          = $opts{fw};
    my $drid        = $opts{drid};
    my $que_path    = $opts{que_path};
    my @disk_list   = @{ $opts{disk_list} };
    my $Filer       = $node->name();

    my $time = get_max_timeout( node_present => [$node] );
    $Api_Set_Obj->set_timeout( 'connectrec-timeout' => 7200 );

    #pre_commands_perf($Node, $API, $MODE, $drid);
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual remarks -d @disk_list -o 'T$que_path; SEQUENTIAL READ PERF; OD/MD/ID; QUEUE $que_path; 4K-256K Transfers; $drid drive; $fw FW'" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual setparam SyncScripting 5" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual setparam ForceUnitAccess 0" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual setparam ContinueOnError 1" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual setparam Relocate03Error 1" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "setflag disk_qual_time_limit 90000" );

    # OD SEQUENTIAL READ ##
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script0 -t 1 -q  $que_path -L 10000 -p 1 -f od -n 8 -d @disk_list -o noverify" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script1 -t 1 -q  $que_path -L 10000 -p 1 -f od -n 16 -d @disk_list -o noverify" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script2 -t 1 -q  $que_path -L 10000 -p 1 -f od -n 32 -d @disk_list -o noverify" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script3 -t 1 -q  $que_path -L 10000 -p 1 -f od -n 64 -d @disk_list -o noverify" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script4 -t 1 -q  $que_path -L 10000 -p 1 -f od -n 128 -d @disk_list -o noverify" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script5 -t 1 -q  $que_path -L 10000 -p 1 -f od -n 256 -d @disk_list -o noverify" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script6 -t 1 -q  $que_path -L 10000 -p 1 -f od -n 512 -d @disk_list -o noverify" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );

    # MD SEQUENTIAL READ ##
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script7 -t 1 -q  $que_path -L 10000 -p 1 -f md -n 8 -d @disk_list -o noverify" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script8 -t 1 -q  $que_path -L 10000 -p 1 -f md -n 16 -d @disk_list -o noverify" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script9 -t 1 -q  $que_path -L 10000 -p 1 -f md -n 32 -d @disk_list -o noverify" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script10 -t 1 -q  $que_path -L 10000 -p 1 -f md -n 64 -d @disk_list -o noverify" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script11 -t 1 -q  $que_path -L 10000 -p 1 -f md -n 128 -d @disk_list -o noverify" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script12 -t 1 -q  $que_path -L 10000 -p 1 -f md -n 256 -d @disk_list -o noverify" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script13 -t 1 -q  $que_path -L 10000 -p 1 -f md -n 512 -d @disk_list -o noverify" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );

    # ID SEQUENTIAL READ ##
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script14 -t 1 -q  $que_path -L 10000 -p 1 -f id -n 8 -d @disk_list -o noverify" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script15 -t 1 -q  $que_path -L 10000 -p 1 -f id -n 16 -d @disk_list -o noverify" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script16 -t 1 -q  $que_path -L 10000 -p 1 -f id -n 32 -d @disk_list -o noverify" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script17 -t 1 -q  $que_path -L 10000 -p 1 -f id -n 64 -d @disk_list -o noverify" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script18 -t 1 -q  $que_path -L 10000 -p 1 -f id -n 128 -d @disk_list -o noverify" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script19 -t 1 -q  $que_path -L 10000 -p 1 -f id -n 256 -d @disk_list -o noverify" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script20 -t 1 -q  $que_path -L 10000 -p 1 -f id -n 512 -d @disk_list -o noverify" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script21 -t -1 -d @disk_list" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );

    if ( $drid eq "all" ) {
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => "$time" );
        $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual runscript -d @disk_list" );
        sleep(60);
        foreach (@disk_list) {
            my $out = $Api_Set_Obj->execute_raw_command( 'command' => "" );
            if ( $out =~ /PANIC/ ) {
                die "Filer PANIC during disk_qual test";
            }
        }
        while (1) {
            my $output = disk_qual_Status( API => $Api_Set_Obj );
            if ( ( $output =~ /Ending script execution/ ) || ( $output =~ /idle/ ) ) {
                logcomment("**DEBUG** : Ending script execution");
                last;
            }
        }
        foreach my $disk (@disk_list) {
            $Api_Set_Obj->set_timeout( "connectrec-timeout" => "$time" );
            $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual summary -d $disk" );
            sleep(120);
            disk_qual_Status( API => $Api_Set_Obj );
            $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
            $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
        }
    } else {
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => "$time" );
        $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual runscript -d $drid" );
        sleep(60);
        my $out = $Api_Set_Obj->execute_raw_command( 'command' => "" );
        if ( $out =~ /PANIC/ ) {
            die "Filer PANIC during disk_qual test";
        }
        $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
        while (1) {
            my $output = disk_qual_Status( API => $Api_Set_Obj );
            if ( ( $output =~ /Ending script execution/ ) || ( $output =~ /idle/ ) ) {
                logcomment("**DEBUG** : Ending script execution");
                last;
            }
        }
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => "$time" );
        $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual summary -d $drid" );
        sleep(120);
        disk_qual_Status( API => $Api_Set_Obj );
        $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
        $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    }
} ## end sub run_dq_perfm_1_8_Cmode

#######################################################################################################
# Author - himangin@netapp.com
# Description - Performance Test: T9; SEQUENTIAL WRITE PERF; OD/MD/ID diameter ranges; QUEUE 1 2 3 4; 128K&256K Transfer Lengths
# Supported Mode - CMode/7mode Maintenance
#######################################################################################################
sub run_dq_perfm_9_Cmode {
    my (%opts) = validate(
        @_,
        {
            Node      => { type => OBJECT },
            API       => { type => OBJECT },
            MODE      => { type => SCALAR, default => "MAINT" },
            fw        => { type => SCALAR },
            drid      => { type => SCALAR },
            disk_list => { type => ARRAYREF },
        }
    );

    my $node        = $opts{Node};
    my $Api_Set_Obj = $opts{API};
    my $MODE        = $opts{MODE};
    my $fw          = $opts{fw};
    my $drid        = $opts{drid};
    my @disk_list   = @{ $opts{disk_list} };
    my $Filer       = $node->name();

    my $time = get_max_timeout( node_present => [$node] );
    $Api_Set_Obj->set_timeout( 'connectrec-timeout' => 7200 );

    # pre_commands_perf( $Node, $API, $MODE, $drid);
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual remarks -d @disk_list -o 'T9; SEQUENTIAL WRITE PERF; OD/MD/ID; QUEUE 1 2 3 4; 128K&256K Transfers; $drid drive; $fw FW'" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual setparam ForceUnitAccess 0" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual setparam ContinueOnError 1" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual setparam Relocate03Error 1" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "setflag disk_qual_time_limit 90000" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );

    ## OD SEQUENTIAL WRITE 128K ##
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script0 -t 5 -q 1 -L 10000 -p 1 -f od -n 256 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script1 -t 5 -q 2 -L 10000 -p 1 -f od -n 256 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script2 -t 5 -q 3 -L 10000 -p 1 -f od -n 256 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script3 -t 5 -q 4 -L 10000 -p 1 -f od -n 256 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );

    ## OD SEQUENTIAL WRITE 256K ##
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script4 -t 5 -q 1 -L 10000 -p 1 -f od -n 512 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script5 -t 5 -q 2 -L 10000 -p 1 -f od -n 512 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script6 -t 5 -q 3 -L 10000 -p 1 -f od -n 512 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script7 -t 5 -q 4 -L 10000 -p 1 -f od -n 512 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );

    ## MD SEQUENTIAL WRITE 128K ##
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script8 -t 5 -q 1 -L 10000 -p 1 -f md -n 256 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script9 -t 5 -q 2 -L 10000 -p 1 -f md -n 256 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script10 -t 5 -q 3 -L 10000 -p 1 -f md -n 256 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script11 -t 5 -q 4 -L 10000 -p 1 -f md -n 256 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );

    ## MD SEQUENTIAL WRITE 256K ##
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script12 -t 5 -q 1 -L 10000 -p 1 -f md -n 512 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script13 -t 5 -q 2 -L 10000 -p 1 -f md -n 512 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script14 -t 5 -q 3 -L 10000 -p 1 -f md -n 512 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script15 -t 5 -q 4 -L 10000 -p 1 -f md -n 512 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script16 -t 5 -q 1 -L 10000 -p 1 -f id -n 256 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script17 -t 5 -q 2 -L 10000 -p 1 -f id -n 256 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script18 -t 5 -q 3 -L 10000 -p 1 -f id -n 256 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script19 -t 5 -q 4 -L 10000 -p 1 -f id -n 256 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );

    ## ID SEQUENTIAL WRITE 256K ##
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script20 -t 5 -q 1 -L 10000 -p 1 -f id -n 512 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script21 -t 5 -q 2 -L 10000 -p 1 -f id -n 512 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script22 -t 5 -q 3 -L 10000 -p 1 -f id -n 512 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script23 -t 5 -q 4 -L 10000 -p 1 -f id -n 512 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script24 -t -1 -d @disk_list" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );

    if ( $drid eq "all" ) {
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => "$time" );
        $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual runscript -d @disk_list" );
        sleep(60);
        foreach (@disk_list) {
            my $out = $Api_Set_Obj->execute_raw_command( 'command' => "" );
            if ( $out =~ /PANIC/ ) {
                die "Filer PANIC during disk_qual test";
            }
        }
        while (1) {
            my $output = disk_qual_Status( API => $Api_Set_Obj );
            if ( ( $output =~ /Ending script execution/ ) || ( $output =~ /idle/ ) ) {
                logcomment("**DEBUG** : Ending script execution");
                last;
            }
        }
        foreach my $disk (@disk_list) {
            $Api_Set_Obj->set_timeout( "connectrec-timeout" => "$time" );
            $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual summary -d $disk" );
            sleep(120);
            disk_qual_Status( API => $Api_Set_Obj );
            $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
            $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
        }
    } else {
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => "$time" );
        $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual runscript -d $drid" );
        sleep(60);
        my $out = $Api_Set_Obj->execute_raw_command( 'command' => "" );
        if ( $out =~ /PANIC/ ) {
            die "Filer PANIC during disk_qual test";
        }
        while (1) {
            my $output = disk_qual_Status( API => $Api_Set_Obj );
            if ( ( $output =~ /Ending script execution/ ) || ( $output =~ /idle/ ) ) {
                logcomment("**DEBUG** : Ending script execution");
                last;
            }
        }
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => "$time" );
        $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual summary -d $drid " );
        sleep(120);
        disk_qual_Status( API => $Api_Set_Obj );
        $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
        $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    }
} ## end sub run_dq_perfm_9_Cmode

#######################################################################################################
# Author - himangin@netapp.com
# Description - Performance Test: T10 to T12; NEAR SEQUENTIAL WRITE PERF; OD 16MB Range; QUEUE 1 2 3 4; Transfers 12K&40K Skip 4K 12K 24K
# Supported Mode - CMode/7mode Maintenance
#######################################################################################################
sub run_dq_perfm_10_12_Cmode {
    my (%opts) = validate(
        @_,
        {
            Node      => { type => OBJECT },
            API       => { type => OBJECT },
            MODE      => { type => SCALAR, default => "MAINT" },
            fw        => { type => SCALAR },
            drid      => { type => SCALAR },
            zone      => { type => SCALAR },
            TS_no     => { type => SCALAR },
            disk_list => { type => ARRAYREF },
        }
    );
    my $node        = $opts{Node};
    my $Api_Set_Obj = $opts{API};
    my $fw          = $opts{fw};
    my $drid        = $opts{drid};
    my $zone        = $opts{zone};
    my $TS_no       = $opts{TS_no};
    my @disk_list   = @{ $opts{disk_list} };
    my $Filer       = $node->name();

    my $time = get_max_timeout( node_present => [$node] );
    $Api_Set_Obj->set_timeout( 'connectrec-timeout' => 7200 );

    #pre_commands_perf($Node, $API, $MODE, $drid);
    if ( $TS_no eq 'T10' ) {
        $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual remarks -d @disk_list -o '$TS_no; NEAR SEQUENTIAL WRITE PERF; OD 16MB Range; QUEUE 1 2 3 4; Transfers 12K&40K Skip 4K 12K 24K; $drid drive; $fw FW'" );
    } elsif ( $TS_no eq 'T11' ) {
        $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual remarks -d @disk_list -o '$TS_no; NEAR SEQUENTIAL WRITE PERF; MD 16MB Range; QUEUE 1 2 3 4; Transfers 12K&40K Skip 4K 12K 24K; $drid drive; $fw FW'" );
    } else {
        $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual remarks -d @disk_list -o '$TS_no; NEAR SEQUENTIAL WRITE PERF; ID 16MB Range; QUEUE 1 2 3 4; Transfers 12K&40K Skip 4K 12K 24K; $drid drive; $fw FW'" );
    }
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual setparam SyncScripting 5" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual setparam ForceUnitAccess 0" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual setparam ContinueOnError 1" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual setparam Relocate03Error 1" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "setflag disk_qual_time_limit 90000" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );

    ## 12K transfer, skip distance 4K
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script0 -t 23 -q 1 -L 10000 -p 1 -f $zone -l 32000 -n 24 -d @disk_list -o 32" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script1 -t 23 -q 2 -L 10000 -p 1 -f $zone -l 32000 -n 24 -d @disk_list -o 32" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script2 -t 23 -q 3 -L 10000 -p 1 -f $zone -l 32000 -n 24 -d @disk_list -o 32" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script3 -t 23 -q 4 -L 10000 -p 1 -f $zone -l 32000 -n 24 -d @disk_list -o 32" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );

    ## 12K transfer, skip distance 12K
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script4 -t 23 -q 1 -L 10000 -p 1 -f $zone -l 32000 -n 24 -d @disk_list -o 48" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script5 -t 23 -q 2 -L 10000 -p 1 -f $zone -l 32000 -n 24 -d @disk_list -o 48" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script6 -t 23 -q 3 -L 10000 -p 1 -f $zone -l 32000 -n 24 -d @disk_list -o 48" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script7 -t 23 -q 4 -L 10000 -p 1 -f $zone -l 32000 -n 24 -d @disk_list -o 48" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );

    ## 12K transfer, skip distance 24K
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script8 -t 23 -q 1 -L 10000 -p 1 -f $zone -l 32000 -n 24 -d @disk_list -o 72" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script9 -t 23 -q 2 -L 10000 -p 1 -f $zone -l 32000 -n 24 -d @disk_list -o 72" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script10 -t 23 -q 3 -L 10000 -p 1 -f $zone -l 32000 -n 24 -d @disk_list -o 72" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script11 -t 23 -q 4 -L 10000 -p 1 -f $zone -l 32000 -n 24 -d @disk_list -o 72" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );

    ## 40K transfer, skip distance 4K
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script12 -t 23 -q 1 -L 10000 -p 1 -f $zone -l 32000 -n 80 -d @disk_list -o 88" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script13 -t 23 -q 2 -L 10000 -p 1 -f $zone -l 32000 -n 80 -d @disk_list -o 88" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script14 -t 23 -q 3 -L 10000 -p 1 -f $zone -l 32000 -n 80 -d @disk_list -o 88" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script15 -t 23 -q 4 -L 10000 -p 1 -f $zone -l 32000 -n 80 -d @disk_list -o 88" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );

    ## 40K transfer, skip distance 12K
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script16 -t 23 -q 1 -L 10000 -p 1 -f $zone -l 32000 -n 80 -d @disk_list -o 104" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script17 -t 23 -q 2 -L 10000 -p 1 -f $zone -l 32000 -n 80 -d @disk_list -o 104" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script18 -t 23 -q 3 -L 10000 -p 1 -f $zone -l 32000 -n 80 -d @disk_list -o 104" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script19 -t 23 -q 4 -L 10000 -p 1 -f $zone -l 32000 -n 80 -d @disk_list -o 104" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );

    ## 40K transfer, skip distance 24K
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script20 -t 23 -q 1 -L 10000 -p 1 -f $zone -l 32000 -n 80 -d @disk_list -o 128" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script21 -t 23 -q 2 -L 10000 -p 1 -f $zone -l 32000 -n 80 -d @disk_list -o 128" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script22 -t 23 -q 3 -L 10000 -p 1 -f $zone -l 32000 -n 80 -d @disk_list -o 128" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script23 -t 23 -q 4 -L 10000 -p 1 -f $zone -l 32000 -n 80 -d @disk_list -o 128" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script24 -t -1 -d @disk_list" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );

    if ( $drid eq "all" ) {
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => "$time" );
        $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual runscript -d @disk_list" );
        sleep(60);
        foreach (@disk_list) {
            my $out = $Api_Set_Obj->execute_raw_command( 'command' => "" );
            if ( $out =~ /PANIC/ ) {
                die "Filer PANIC during disk_qual test";
            }
        }
        while (1) {
            my $output = disk_qual_Status( API => $Api_Set_Obj );
            if ( ( $output =~ /Ending script execution/ ) || ( $output =~ /idle/ ) ) {
                logcomment("**DEBUG** : Ending script execution");
                last;
            }
        }
        foreach my $disk (@disk_list) {
            $Api_Set_Obj->set_timeout( "connectrec-timeout" => "$time" );
            $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual summary -d $disk" );
            sleep(120);
            disk_qual_Status( API => $Api_Set_Obj );
            $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
            $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
        }
    } else {
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => "$time" );
        $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual runscript -d $drid" );
        sleep(60);
        my $out = $Api_Set_Obj->execute_raw_command( 'command' => "" );
        if ( $out =~ /PANIC/ ) {
            die "Filer PANIC during disk_qual test";
        }
        $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
        while (1) {
            my $output = disk_qual_Status( API => $Api_Set_Obj );
            if ( ( $output =~ /Ending script execution/ ) || ( $output =~ /idle/ ) ) {
                logcomment("**DEBUG** : Ending script execution");
                last;
            }
        }
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => "$time" );
        $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual summary -d $drid" );
        sleep(120);
        disk_qual_Status( API => $Api_Set_Obj );
        $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
        $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    }
} ## end sub run_dq_perfm_10_12_Cmode

#######################################################################################################
# Author - himangin@netapp.com
# Description - Performance Test: T13; NEAR SEQUENTIAL READ PERF; Full Disk; QUEUE 1-8; Transfers 4K - 8K Skip 4K 12K 24K
# Supported Mode - CMode/7mode Maintenance
#######################################################################################################

sub run_dq_perfm_13_Cmode {
    my (%opts) = validate(
        @_,
        {
            Node      => { type => OBJECT },
            API       => { type => OBJECT },
            MODE      => { type => SCALAR, default => "MAINT" },
            fw        => { type => SCALAR, optional => 1 },
            drid      => { type => SCALAR },
            disk_list => { type => ARRAYREF },
        }
    );
    my $node        = $opts{Node};
    my $Api_Set_Obj = $opts{API};
    my $MODE        = $opts{MODE};
    my $fw          = $opts{fw};
    my $drid        = $opts{drid};
    my @disk_list   = @{ $opts{disk_list} };
    my $Filer       = $node->name();

    my $time = get_max_timeout( node_present => [$node] );
    $Api_Set_Obj->set_timeout( 'connectrec-timeout' => 7200 );

    #pre_commands_perf($Node, $API, $MODE, $drid);
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual remarks -d @disk_list -o 'T13; NEAR SEQUENTIAL READ PERF; Full Disk; QUEUE 1-8; Transfers 4K Skip 4K 12K 24K; $drid drive; $fw FW'" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual setparam SyncScripting 5" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual setparam ForceUnitAccess 0" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual setparam ContinueOnError 1" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual setparam Relocate03Error 1" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "setflag disk_qual_time_limit 90000" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );

    ## 4K transfer, skip distance 4K
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script0 -t 22 -q 1 -L 10000 -p 1 -f 0 -l end -n 8 -d @disk_list -o 16" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script1 -t 22 -q 2 -L 10000 -p 1 -f 0 -l end -n 8 -d @disk_list -o 16" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script2 -t 22 -q 3 -L 10000 -p 1 -f 0 -l end -n 8 -d @disk_list -o 16" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script3 -t 22 -q 4 -L 10000 -p 1 -f 0 -l end -n 8 -d @disk_list -o 16" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script4 -t 22 -q 5 -L 10000 -p 1 -f 0 -l end -n 8 -d @disk_list -o 16" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script5 -t 22 -q 6 -L 10000 -p 1 -f 0 -l end -n 8 -d @disk_list -o 16" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script6 -t 22 -q 7 -L 10000 -p 1 -f 0 -l end -n 8 -d @disk_list -o 16" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script7 -t 22 -q 8 -L 10000 -p 1 -f 0 -l end -n 8 -d @disk_list -o 16" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );

    ## 4K transfer, skip distance 12K
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script8 -t 22 -q 1 -L 10000 -p 1 -f 0 -l end -n 8 -d @disk_list -o 32" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script9 -t 22 -q 2 -L 10000 -p 1 -f 0 -l end -n 8 -d @disk_list -o 32" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script10 -t 22 -q 3 -L 10000 -p 1 -f 0 -l end -n 8 -d @disk_list -o 32" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script11 -t 22 -q 4 -L 10000 -p 1 -f 0 -l end -n 8 -d @disk_list -o 32" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script12 -t 22 -q 5 -L 10000 -p 1 -f 0 -l end -n 8 -d @disk_list -o 32" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script13 -t 22 -q 6 -L 10000 -p 1 -f 0 -l end -n 8 -d @disk_list -o 32" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script14 -t 22 -q 7 -L 10000 -p 1 -f 0 -l end -n 8 -d @disk_list -o 32" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script15 -t 22 -q 8 -L 10000 -p 1 -f 0 -l end -n 8 -d @disk_list -o 32" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );

    ## 4K transfer, skip distance 24K
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script16 -t 22 -q 1 -L 10000 -p 1 -f 0 -l end -n 8 -d @disk_list -o 56" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script17 -t 22 -q 2 -L 10000 -p 1 -f 0 -l end -n 8 -d @disk_list -o 56" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script18 -t 22 -q 3 -L 10000 -p 1 -f 0 -l end -n 8 -d @disk_list -o 56" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script19 -t 22 -q 4 -L 10000 -p 1 -f 0 -l end -n 8 -d @disk_list -o 56" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script20 -t 22 -q 5 -L 10000 -p 1 -f 0 -l end -n 8 -d @disk_list -o 56" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script21 -t 22 -q 6 -L 10000 -p 1 -f 0 -l end -n 8 -d @disk_list -o 56" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script22 -t 22 -q 7 -L 10000 -p 1 -f 0 -l end -n 8 -d @disk_list -o 56" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script23 -t 22 -q 8 -L 10000 -p 1 -f 0 -l end -n 8 -d @disk_list -o 56" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script24 -t -1 -d @disk_list" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );

    if ( $drid eq "all" ) {
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => "$time" );
        $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual runscript -d @disk_list" );
        sleep(60);
        foreach (@disk_list) {
            my $out = $Api_Set_Obj->execute_raw_command( 'command' => "" );
            if ( $out =~ /PANIC/ ) {
                die "Filer PANIC during disk_qual test";
            }
        }
        while (1) {
            my $output = disk_qual_Status( API => $Api_Set_Obj );
            if ( ( $output =~ /Ending script execution/ ) || ( $output =~ /idle/ ) ) {
                logcomment("**DEBUG** : Ending script execution");
                last;
            }
        }
        foreach my $disk (@disk_list) {
            $Api_Set_Obj->set_timeout( "connectrec-timeout" => "$time" );
            $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual summary -d $disk" );
            sleep(120);
            disk_qual_Status( API => $Api_Set_Obj );
            $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
            $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
        }
    } else {
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => "$time" );
        $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual runscript -d $drid" );
        sleep(60);
        my $out = $Api_Set_Obj->execute_raw_command( 'command' => "" );
        if ( $out =~ /PANIC/ ) {
            die "Filer PANIC during disk_qual test";
        }
        $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
        while (1) {
            my $output = disk_qual_Status( API => $Api_Set_Obj );
            if ( ( $output =~ /Ending script execution/ ) || ( $output =~ /idle/ ) ) {
                logcomment("**DEBUG** : Ending script execution");
                last;
            }
        }
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => "$time" );
        $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual summary -d $drid" );
        sleep(120);
        disk_qual_Status( API => $Api_Set_Obj );
        $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
        $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    }
} ## end sub run_dq_perfm_13_Cmode

#######################################################################################################
# Author - himangin@netapp.com
# Description - Performance Test: T14; NEAR SEQUENTIAL READ PERF; Full Disk; QUEUE 1-8; Transfers 4K - 8K Skip 4K 12K 24K
# Supported Mode - CMode/7mode Maintenance
#######################################################################################################
sub run_dq_perfm_14_Cmode {
    my (%opts) = validate(
        @_,
        {
            Node      => { type => OBJECT },
            API       => { type => OBJECT },
            MODE      => { type => SCALAR, default => "MAINT" },
            fw        => { type => SCALAR, optional => 1 },
            drid      => { type => SCALAR },
            disk_list => { type => ARRAYREF },
        }
    );
    my $node        = $opts{Node};
    my $Api_Set_Obj = $opts{API};
    my $MODE        = $opts{MODE};
    my $fw          = $opts{fw};
    my $drid        = $opts{drid};
    my @disk_list   = @{ $opts{disk_list} };
    my $Filer       = $node->name();

    my $time = get_max_timeout( node_present => [$node] );
    $Api_Set_Obj->set_timeout( 'connectrec-timeout' => 7200 );

    #pre_commands_perf($Node, $API, $MODE, $drid);
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual remarks -d @disk_list -o 'T14; NEAR SEQUENTIAL READ PERF; Full Disk; QUEUE 1-8; Transfers 8K Skip 4K 12K 24K; $drid drive; $fw FW'" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual setparam SyncScripting 5" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual setparam ForceUnitAccess 0" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual setparam ContinueOnError 1" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual setparam Relocate03Error 1" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "setflag disk_qual_time_limit 90000" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );

    ## 8K transfer, skip distance 4K
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script0 -t 22 -q 1 -L 10000 -p 1 -f 0 -l end -n 16 -d @disk_list -o 16" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script1 -t 22 -q 2 -L 10000 -p 1 -f 0 -l end -n 16 -d @disk_list -o 16" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script2 -t 22 -q 3 -L 10000 -p 1 -f 0 -l end -n 16 -d @disk_list -o 16" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script3 -t 22 -q 4 -L 10000 -p 1 -f 0 -l end -n 16 -d @disk_list -o 16" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script4 -t 22 -q 5 -L 10000 -p 1 -f 0 -l end -n 16 -d @disk_list -o 16" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script5 -t 22 -q 6 -L 10000 -p 1 -f 0 -l end -n 16 -d @disk_list -o 16" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script6 -t 22 -q 7 -L 10000 -p 1 -f 0 -l end -n 16 -d @disk_list -o 16" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script7 -t 22 -q 8 -L 10000 -p 1 -f 0 -l end -n 16 -d @disk_list -o 16" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );

    ## 8K transfer, skip distance 12K
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script8 -t 22 -q 1 -L 10000 -p 1 -f 0 -l end -n 16 -d @disk_list -o 32" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script9 -t 22 -q 2 -L 10000 -p 1 -f 0 -l end -n 16 -d @disk_list -o 32" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script10 -t 22 -q 3 -L 10000 -p 1 -f 0 -l end -n 16 -d @disk_list -o 32" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script11 -t 22 -q 4 -L 10000 -p 1 -f 0 -l end -n 16 -d @disk_list -o 32" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script12 -t 22 -q 5 -L 10000 -p 1 -f 0 -l end -n 16 -d @disk_list -o 32" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script13 -t 22 -q 6 -L 10000 -p 1 -f 0 -l end -n 16 -d @disk_list -o 32" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script14 -t 22 -q 7 -L 10000 -p 1 -f 0 -l end -n 16 -d @disk_list -o 32" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script15 -t 22 -q 8 -L 10000 -p 1 -f 0 -l end -n 16 -d @disk_list -o 32" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );

    ## 8K transfer, skip distance 24K
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script16 -t 22 -q 1 -L 10000 -p 1 -f 0 -l end -n 16 -d @disk_list -o 56" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script17 -t 22 -q 2 -L 10000 -p 1 -f 0 -l end -n 16 -d @disk_list -o 56" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script18 -t 22 -q 3 -L 10000 -p 1 -f 0 -l end -n 16 -d @disk_list -o 56" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script19 -t 22 -q 4 -L 10000 -p 1 -f 0 -l end -n 16 -d @disk_list -o 56" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script20 -t 22 -q 5 -L 10000 -p 1 -f 0 -l end -n 16 -d @disk_list -o 56" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script21 -t 22 -q 6 -L 10000 -p 1 -f 0 -l end -n 16 -d @disk_list -o 56" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script22 -t 22 -q 7 -L 10000 -p 1 -f 0 -l end -n 16 -d @disk_list -o 56" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script23 -t 22 -q 8 -L 10000 -p 1 -f 0 -l end -n 16 -d @disk_list -o 56" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script24 -t -1 -d @disk_list" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );

    if ( $drid eq "all" ) {
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => "$time" );
        $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual runscript -d @disk_list" );
        sleep(60);
        foreach (@disk_list) {
            my $out = $Api_Set_Obj->execute_raw_command( 'command' => "" );
            if ( $out =~ /PANIC/ ) {
                die "Filer PANIC during disk_qual test";
            }
        }
        while (1) {
            my $output = disk_qual_Status( API => $Api_Set_Obj );
            if ( ( $output =~ /Ending script execution/ ) || ( $output =~ /idle/ ) ) {
                logcomment("**DEBUG** : Ending script execution");
                last;
            }
        }
        foreach my $disk (@disk_list) {
            $Api_Set_Obj->set_timeout( "connectrec-timeout" => "$time" );
            $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual summary -d $disk" );
            sleep(120);
            disk_qual_Status( API => $Api_Set_Obj );
            $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
            $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
        }
    } else {
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => "$time" );
        $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual runscript -d $drid" );
        sleep(60);
        my $out = $Api_Set_Obj->execute_raw_command( 'command' => "" );
        if ( $out =~ /PANIC/ ) {
            die "Filer PANIC during disk_qual test";
        }
        $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
        while (1) {
            my $output = disk_qual_Status( API => $Api_Set_Obj );
            if ( ( $output =~ /Ending script execution/ ) || ( $output =~ /idle/ ) ) {
                logcomment("**DEBUG** : Ending script execution");
                last;
            }
        }
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => "$time" );
        $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual summary -d $drid" );
        sleep(120);
        disk_qual_Status( API => $Api_Set_Obj );
        $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
        $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    }

} ## end sub run_dq_perfm_14_Cmode

#######################################################################################################
# Author - himangin@netapp.com
# Description - Performance Test: T15; RANDOM READ PERF; FULL DISK; QUEUE 1-4, QUEUE 5-8
# Supported Mode - CMode/7mode Maintenance
#######################################################################################################
sub run_dq_perfm_15_Cmode {
    my (%opts) = validate(
        @_,
        {
            Node      => { type => OBJECT },
            API       => { type => OBJECT },
            MODE      => { type => SCALAR, default => "MAINT" },
            fw        => { type => SCALAR, optional => 1 },
            drid      => { type => SCALAR },
            disk_list => { type => ARRAYREF },
        }
    );
    my $node        = $opts{Node};
    my $Api_Set_Obj = $opts{API};
    my $MODE        = $opts{MODE};
    my $fw          = $opts{fw};
    my $drid        = $opts{drid};
    my @disk_list   = @{ $opts{disk_list} };
    my $Filer       = $node->name();

    my $time = get_max_timeout( node_present => [$node] );
    $Api_Set_Obj->set_timeout( 'connectrec-timeout' => 7200 );

    #pre_commands_perf($Node, $API, $MODE, $drid);
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual remarks -d @disk_list -o 'T15; RANDOM READ PERF; FULL DISK; QUEUE 1-4; $drid drive; $fw FW'" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual setparam SyncScripting 5" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual setparam ForceUnitAccess 0" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual setparam ContinueOnError 1" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual setparam Relocate03Error 1" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "setflag disk_qual_time_limit 90000" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );

    ## FULL DISK RANDOM READ, -q 1 ##
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script0 -t 3 -q 1 -L 10000  -n 8 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script1 -t 3 -q 1 -L 10000  -n 16 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script2 -t 3 -q 1 -L 10000  -n 32 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script3 -t 3 -q 1 -L 10000  -n 64 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script4 -t 3 -q 1 -L 10000  -n 128 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script5 -t 3 -q 1 -L 10000  -n 256 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script6 -t 3 -q 1 -L 10000  -n 512 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );

    ## FULL DISK RANDOM READ, -q 2 ##
    ## FULL DISK RANDOM READ, -q 2 ##
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script7 -t 3 -q 2 -L 10000  -n 8 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script8 -t 3 -q 2 -L 10000  -n 16 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script9 -t 3 -q 2 -L 10000  -n 32 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script10 -t 3 -q 2 -L 10000  -n 64 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script11 -t 3 -q 2 -L 10000  -n 128 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script12 -t 3 -q 2 -L 10000  -n 256 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script13 -t 3 -q 2 -L 10000  -n 512 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );

    ## FULL DISK RANDOM READ, -q 3 ##
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script14 -t 3 -q 3 -L 10000  -n 8 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script15 -t 3 -q 3 -L 10000  -n 16 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script16 -t 3 -q 3 -L 10000  -n 32 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script17 -t 3 -q 3 -L 10000  -n 64 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script18 -t 3 -q 3 -L 10000  -n 128 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script19 -t 3 -q 3 -L 10000  -n 256 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script20 -t 3 -q 3 -L 10000  -n 512 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );

    ## FULL DISK RANDOM READ, -q 4 ##
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script21 -t 3 -q 4 -L 10000  -n 8 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script22 -t 3 -q 4 -L 10000  -n 16 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script23 -t 3 -q 4 -L 10000  -n 32 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script24 -t 3 -q 4 -L 10000  -n 64 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script25 -t 3 -q 4 -L 10000  -n 128 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script26 -t 3 -q 4 -L 10000  -n 256 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script27 -t 3 -q 4 -L 10000  -n 512 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script28 -t -1 -d @disk_list" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );

    if ( $drid eq "all" ) {
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => "$time" );
        $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual runscript -d @disk_list" );
        sleep(60);
        foreach (@disk_list) {
            my $out = $Api_Set_Obj->execute_raw_command( 'command' => "" );
            if ( $out =~ /PANIC/ ) {
                die "Filer PANIC during disk_qual test";
            }
        }
        while (1) {
            my $output = disk_qual_Status( API => $Api_Set_Obj );
            if ( ( $output =~ /Ending script execution/ ) || ( $output =~ /idle/ ) ) {
                logcomment("**DEBUG** : Ending script execution");
                last;
            }
        }
        foreach my $disk (@disk_list) {
            $Api_Set_Obj->set_timeout( "connectrec-timeout" => "$time" );
            $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual summary -d $disk" );
            sleep(120);
            disk_qual_Status( API => $Api_Set_Obj );
            $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
            $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
        }
    } else {
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => "$time" );
        $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual runscript -d $drid" );
        sleep(60);
        my $out = $Api_Set_Obj->execute_raw_command( 'command' => "" );
        if ( $out =~ /PANIC/ ) {
            die "Filer PANIC during disk_qual test";
        }
        while (1) {
            my $output = disk_qual_Status( API => $Api_Set_Obj );
            if ( ( $output =~ /Ending script execution/ ) || ( $output =~ /idle/ ) ) {
                logcomment("**DEBUG** : Ending script execution");
                last;
            }
        }
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => "$time" );
        $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual summary -d $drid" );
        sleep(120);
        disk_qual_Status( API => $Api_Set_Obj );
        $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
        $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    }
} ## end sub run_dq_perfm_15_Cmode

#######################################################################################################
# Author - himangin@netapp.com
# Description - Performance Test: T16; RANDOM READ PERF; FULL DISK; QUEUE 1-4, QUEUE 5-8
# Supported Mode - CMode/7mode Maintenance
#######################################################################################################
sub run_dq_perfm_16_Cmode {
    my (%opts) = validate(
        @_,
        {
            Node      => { type => OBJECT },
            API       => { type => OBJECT },
            MODE      => { type => SCALAR, default => "MAINT" },
            fw        => { type => SCALAR, optional => 1 },
            drid      => { type => SCALAR },
            disk_list => { type => ARRAYREF },
        }
    );
    my $node        = $opts{Node};
    my $Api_Set_Obj = $opts{API};
    my $MODE        = $opts{MODE};
    my $fw          = $opts{fw};
    my $drid        = $opts{drid};
    my @disk_list   = @{ $opts{disk_list} };
    my $Filer       = $node->name();

    my $time = get_max_timeout( node_present => [$node] );
    $Api_Set_Obj->set_timeout( 'connectrec-timeout' => 7200 );

    #pre_commands_perf($Node, $API, $MODE, $drid);
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual remarks -d @disk_list -o 'T16; RANDOM READ PERF; FULL DISK; QUEUE 5-8; $drid drive; $fw FW'" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual setparam SyncScripting 5" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual setparam ForceUnitAccess 0" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual setparam ContinueOnError 1" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual setparam Relocate03Error 1" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "setflag disk_qual_time_limit 90000" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );

    ## FULL DISK RANDOM READ, -q 5 ##
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script0 -t 3 -q 5 -L 10000  -n 8 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script1 -t 3 -q 5 -L 10000  -n 16 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script2 -t 3 -q 5 -L 10000  -n 32 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script3 -t 3 -q 5 -L 10000  -n 64 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script4 -t 3 -q 5 -L 10000  -n 128 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script5 -t 3 -q 5 -L 10000  -n 256 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script6 -t 3 -q 5 -L 10000  -n 512 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );

    ## FULL DISK RANDOM READ, -q 6 ##
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script7 -t 3 -q 6 -L 10000  -n 8 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script8 -t 3 -q 6 -L 10000  -n 16 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script9 -t 3 -q 6 -L 10000  -n 32 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script10 -t 3 -q 6 -L 10000  -n 64 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script11 -t 3 -q 6 -L 10000  -n 128 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script12 -t 3 -q 6 -L 10000  -n 256 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script13 -t 3 -q 6 -L 10000  -n 512 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );

    ## FULL DISK RANDOM READ, -q 7 ##
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script14 -t 3 -q 7 -L 10000  -n 8 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script15 -t 3 -q 7 -L 10000  -n 16 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script16 -t 3 -q 7 -L 10000  -n 32 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script17 -t 3 -q 7 -L 10000  -n 64 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script18 -t 3 -q 7 -L 10000  -n 128 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script19 -t 3 -q 7 -L 10000  -n 256 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script20 -t 3 -q 7 -L 10000  -n 512 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );

    ## FULL DISK RANDOM READ, -q 8 ##
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script21 -t 3 -q 8 -L 10000  -n 8 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script22 -t 3 -q 8 -L 10000  -n 16 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script23 -t 3 -q 8 -L 10000  -n 32 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script24 -t 3 -q 8 -L 10000  -n 64 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script25 -t 3 -q 8 -L 10000  -n 128 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script26 -t 3 -q 8 -L 10000  -n 256 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script27 -t 3 -q 8 -L 10000  -n 512 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script28 -t -1 -d @disk_list" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );

    if ( $drid eq "all" ) {
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => "$time" );
        $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual runscript -d @disk_list" );
        sleep(60);
        foreach (@disk_list) {
            my $out = $Api_Set_Obj->execute_raw_command( 'command' => "" );
            if ( $out =~ /PANIC/ ) {
                die "Filer PANIC during disk_qual test";
            }
        }
        while (1) {
            my $output = disk_qual_Status( API => $Api_Set_Obj );
            if ( ( $output =~ /Ending script execution/ ) || ( $output =~ /idle/ ) ) {
                logcomment("**DEBUG** : Ending script execution");
                last;
            }
        }
        foreach my $disk (@disk_list) {
            $Api_Set_Obj->set_timeout( "connectrec-timeout" => "$time" );
            $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual summary -d $disk" );
            sleep(120);
            $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
            $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
        }
    } else {
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => "$time" );
        $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual runscript -d $drid" );
        sleep(60);
        my $out = $Api_Set_Obj->execute_raw_command( 'command' => "" );
        if ( $out =~ /PANIC/ ) {
            die "Filer PANIC during disk_qual test";
        }
        while (1) {
            my $output = disk_qual_Status( API => $Api_Set_Obj );
            if ( ( $output =~ /Ending script execution/ ) || ( $output =~ /idle/ ) ) {
                logcomment("**DEBUG** : Ending script execution");
                last;
            }
        }
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => "$time" );
        $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual summary -d $drid" );
        sleep(120);
        disk_qual_Status( API => $Api_Set_Obj );
        $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
        $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    }
} ## end sub run_dq_perfm_16_Cmode

#######################################################################################################
# Author - himangin@netapp.com
# Description - Performance Test: T17; MULTI-STREAM SEQUENTIAL READ PERF; FD/OD/MD/ID; QUEUE 1-6; Transfer 4K
# Supported Mode - CMode/7mode Maintenance
#######################################################################################################
sub run_dq_perfm_17_Cmode {
    my (%opts) = validate(
        @_,
        {
            Node      => { type => OBJECT },
            API       => { type => OBJECT },
            MODE      => { type => SCALAR, default => "MAINT" },
            fw        => { type => SCALAR, optional => 1 },
            drid      => { type => SCALAR },
            disk_list => { type => ARRAYREF },
        }
    );
    my $node        = $opts{Node};
    my $Api_Set_Obj = $opts{API};
    my $MODE        = $opts{MODE};
    my $fw          = $opts{fw};
    my $drid        = $opts{drid};
    my @disk_list   = @{ $opts{disk_list} };
    my $Filer       = $node->name();

    my $time = get_max_timeout( node_present => [$node] );
    $Api_Set_Obj->set_timeout( 'connectrec-timeout' => 7200 );

    #pre_commands_perf($Node, $API, $MODE, $drid);
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual remarks -d @disk_list -o 'T17; MULTI-STREAM SEQUENTIAL READ PERF; FD/OD/MD/ID; QUEUE 1-6; Transfer 4K; $drid drive; $fw FW'" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual setparam SyncScripting 5" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual setparam ForceUnitAccess 0" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual setparam ContinueOnError 1" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual setparam Relocate03Error 1" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "setflag disk_qual_time_limit 90000" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );

    ## FULL DISK
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script0 -t 24 -q 1 -L 10000 -p 1 -f 0 -l end -n 8 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script1 -t 24 -q 2 -L 10000 -p 1 -f 0 -l end -n 8 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script2 -t 24 -q 3 -L 10000 -p 1 -f 0 -l end -n 8 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script3 -t 24 -q 4 -L 10000 -p 1 -f 0 -l end -n 8 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script4 -t 24 -q 5 -L 10000 -p 1 -f 0 -l end -n 8 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script5 -t 24 -q 6 -L 10000 -p 1 -f 0 -l end -n 8 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );

    ## limit the STREAMS at OD
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script6 -t 24 -q 1 -L 10000 -p 1 -f od -n 8 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script7 -t 24 -q 2 -L 10000 -p 1 -f od -n 8 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script8 -t 24 -q 3 -L 10000 -p 1 -f od -n 8 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script9 -t 24 -q 4 -L 10000 -p 1 -f od -n 8 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script10 -t 24 -q 5 -L 10000 -p 1 -f od -n 8 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script11 -t 24 -q 6 -L 10000 -p 1 -f od -n 8 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );

    ## limit the STREAMS at MD
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script12 -t 24 -q 1 -L 10000 -p 1 -f md -n 8 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script13 -t 24 -q 2 -L 10000 -p 1 -f md -n 8 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script14 -t 24 -q 3 -L 10000 -p 1 -f md -n 8 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script15 -t 24 -q 4 -L 10000 -p 1 -f md -n 8 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script16 -t 24 -q 5 -L 10000 -p 1 -f md -n 8 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script17 -t 24 -q 6 -L 10000 -p 1 -f md -n 8 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );

    ## limit the STREAMS at ID
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script18 -t 24 -q 1 -L 10000 -p 1 -f id -n 8 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script19 -t 24 -q 2 -L 10000 -p 1 -f id -n 8 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script20 -t 24 -q 3 -L 10000 -p 1 -f id -n 8 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script21 -t 24 -q 4 -L 10000 -p 1 -f id -n 8 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script22 -t 24 -q 5 -L 10000 -p 1 -f id -n 8 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script23 -t 24 -q 6 -L 10000 -p 1 -f id -n 8 -d @disk_list -o noverify" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script24 -t -1 -d @disk_list" );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );

    if ( $drid eq "all" ) {
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => "$time" );
        $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual runscript -d @disk_list" );
        sleep(60);
        foreach (@disk_list) {
            my $out = $Api_Set_Obj->execute_raw_command( 'command' => "" );
            if ( $out =~ /PANIC/ ) {
                die "Filer PANIC during disk_qual test";
            }
        }
        while (1) {
            my $output = disk_qual_Status( API => $Api_Set_Obj );
            if ( ( $output =~ /Ending script execution/ ) || ( $output =~ /idle/ ) ) {
                logcomment("**DEBUG** : Ending script execution");
                last;
            }
        }
        foreach my $disk (@disk_list) {
            $Api_Set_Obj->set_timeout( "connectrec-timeout" => "$time" );
            $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual summary -d $disk" );
            sleep(120);
            disk_qual_Status( API => $Api_Set_Obj );
            $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
            $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
        }
    } else {
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => "$time" );
        $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual runscript -d $drid" );
        sleep(60);
        my $out = $Api_Set_Obj->execute_raw_command( 'command' => "" );
        if ( $out =~ /PANIC/ ) {
            die "Filer PANIC during disk_qual test";
        }
        while (1) {
            my $output = disk_qual_Status( API => $Api_Set_Obj );
            if ( ( $output =~ /Ending script execution/ ) || ( $output =~ /idle/ ) ) {
                logcomment("**DEBUG** : Ending script execution");
                last;
            }
        }
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => "$time" );
        $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual summary -d $drid" );
        sleep(120);
        disk_qual_Status( API => $Api_Set_Obj );
        $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
        $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    }
} ## end sub run_dq_perfm_17_Cmode

#######################################################################################################
# Author - vpankaj@netapp.com
# Description - Create run_dq_perfm_18
# Sequence of disk_qual operations are performed
# Supported Mode - Maintenance
#######################################################################################################
sub run_dq_perfm_18_Cmode {
    my (%opts) = validate(
        @_,
        {
            Node             => { type => OBJECT },
            API              => { type => OBJECT },
            MODE             => { type => SCALAR, default => "MAINT" },
            fw               => { type => SCALAR },
            drid             => { type => SCALAR },
            diskL_add_before => { type => ARRAYREF },
            loop_count       => { type => SCALAR, optional => 1 }
        }
    );
    my $node        = $opts{Node};
    my $Api_Set_Obj = $opts{API};
    my $MODE        = $opts{MODE};
    my $con_obj     = $opts{con_obj};
    my $fw          = $opts{fw};
    my $drid        = $opts{drid};
    my @diskL       = @{ $opts{diskL_add_before} };
    my $loop_count;
    my $Filer = $node->name();

    if ( !$opts{loop_count} ) {
        $loop_count = 5000;
    } else {
        $loop_count = $opts{loop_count};
    }
    my $time = get_max_timeout( node_present => [$node] );
    $Api_Set_Obj->set_timeout( 'connectrec-timeout' => 7200 );

    # pre_commands_perf( $host_obj, $con_obj, $MODE, $drid);

    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual remarks -d @diskL -o 'T18; DENSEIO SORTED READ PERF; QUEUE 1-16'" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );

    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script0 -t 30 -q 1 -L $loop_count -f 0 -l end -n 8 -d @diskL" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script1 -t 28 -q 1 -L $loop_count -f 0 -l end -n 8 -d @diskL -o sort" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script2 -t 28 -q 2 -L $loop_count -f 0 -l end -n 8 -d @diskL -o sort" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script3 -t 28 -q 3 -L $loop_count -f 0 -l end -n 8 -d @diskL -o sort" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script4 -t 28 -q 4 -L $loop_count -f 0 -l end -n 8 -d @diskL -o sort" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script5 -t 28 -q 5 -L $loop_count -f 0 -l end -n 8 -d @diskL -o sort" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script6 -t 28 -q 6 -L $loop_count -f 0 -l end -n 8 -d @diskL -o sort" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script7 -t 28 -q 7 -L $loop_count -f 0 -l end -n 8 -d @diskL -o sort" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script8 -t 28 -q 8 -L $loop_count -f 0 -l end -n 8 -d @diskL -o sort" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script9 -t 28 -q 9 -L $loop_count -f 0 -l end -n 8 -d @diskL -o sort" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script10 -t 28 -q 10 -L $loop_count -f 0 -l end -n 8 -d @diskL -o sort" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script11 -t 28 -q 11 -L $loop_count -f 0 -l end -n 8 -d @diskL -o sort" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script12 -t 28 -q 12 -L $loop_count -f 0 -l end -n 8 -d @diskL -o sort" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script13 -t 28 -q 13 -L $loop_count -f 0 -l end -n 8 -d @diskL -o sort" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script14 -t 28 -q 14 -L $loop_count -f 0 -l end -n 8 -d @diskL -o sort" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script15 -t 28 -q 15 -L $loop_count -f 0 -l end -n 8 -d @diskL -o sort" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script16 -t 28 -q 16 -L $loop_count -f 0 -l end -n 8 -d @diskL -o sort" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script17 -t -1 -d @diskL" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );

    if ( $drid eq "all" ) {
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => "$time" );
        $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual runscript -d @diskL" );
        sleep(60);
        foreach (@diskL) {
            my $out = $Api_Set_Obj->execute_raw_command( 'command' => "" );

            if ( $out =~ /PANIC/ ) {
                die "Filer PANIC  during disk_qual test";
            }
        }
        while (1) {
            my $output = disk_qual_Status( API => $Api_Set_Obj );
            if ( ( $output =~ /Ending script execution/ ) || ( $output =~ /idle/ ) ) {
                logcomment("**DEBUG** : Ending script execution");
                last;
            }
        }
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => "$time" );
        $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual summary -d @diskL" );
        sleep(120);
        $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
        $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    } else {
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => "$time" );
        my $out = $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual runscript -d $drid" );
        sleep(60);

        if ( $out =~ /PANIC/ ) {

            die "Filer PANIC  during disk_qual test";
        }
        while (1) {
            my $output = disk_qual_Status( API => $Api_Set_Obj );
            if ( ( $output =~ /Ending script execution/ ) || ( $output =~ /idle/ ) ) {
                logcomment("**DEBUG** : Ending script execution");
                last;
            }
        }
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => "$time" );
        $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual summary -d $drid" );
        sleep(120);
        $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
        $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    } ## end else [ if ($drid eq "all")
    disk_qual_Status( API => $Api_Set_Obj );
} ## end sub run_dq_perfm_18_Cmode

#######################################################################################################
# Author - vpankaj@netapp.com
# Description - Create run_dq_perfm_19
# Sequence of disk_qual operations are performed
# Supported Mode - Maintenance
#######################################################################################################
sub run_dq_perfm_19_Cmode {
    my (%opts) = validate(
        @_,
        {
            Node             => { type => OBJECT },
            API              => { type => OBJECT },
            MODE             => { type => SCALAR, default => "MAINT" },
            fw               => { type => SCALAR },
            drid             => { type => SCALAR },
            diskL_add_before => { type => ARRAYREF },
            loop_count       => { type => SCALAR, optional => 1 }
        }
    );
    my $node        = $opts{Node};
    my $Api_Set_Obj = $opts{API};
    my $MODE        = $opts{MODE};
    my $con_obj     = $opts{con_obj};
    my $fw          = $opts{fw};
    my $drid        = $opts{drid};
    my @diskL       = @{ $opts{diskL_add_before} };
    my $loop_count;
    my $Filer = $node->name();

    if ( !$opts{loop_count} ) {
        $loop_count = 5000;
    } else {
        $loop_count = $opts{loop_count};
    }

    my $time = get_max_timeout( node_present => [$node] );

    # pre_commands_perf( $host_obj, $con_obj, $MODE, $drid);
    $Api_Set_Obj->set_timeout( 'connectrec-timeout' => 7200 );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual remarks -d @diskL -o 'T19; DENSEIO SORTED WRITE PERF; QUEUE 1-16; ALL ; FW Rev xxxx'" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );

    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script0 -t 31 -q 1 -L $loop_count -f 0 -l end -n 8 -d @diskL" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script1 -t 29 -q 1 -L $loop_count -f 0 -l end -n 8 -d @diskL -o sort" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script2 -t 29 -q 2 -L $loop_count -f 0 -l end -n 8 -d @diskL -o sort" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script3 -t 29 -q 3 -L $loop_count -f 0 -l end -n 8 -d @diskL -o sort" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script4 -t 29 -q 4 -L $loop_count -f 0 -l end -n 8 -d @diskL -o sort" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script5 -t 29 -q 5 -L $loop_count -f 0 -l end -n 8 -d @diskL -o sort" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script6 -t 29 -q 6 -L $loop_count -f 0 -l end -n 8 -d @diskL -o sort" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script7 -t 29 -q 7 -L $loop_count -f 0 -l end -n 8 -d @diskL -o sort" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script8 -t 29 -q 8 -L $loop_count -f 0 -l end -n 8 -d @diskL -o sort" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script9 -t 29 -q 9 -L $loop_count -f 0 -l end -n 8 -d @diskL -o sort" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script10 -t 29 -q 10 -L $loop_count -f 0 -l end -n 8 -d @diskL -o sort" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script11 -t 29 -q 11 -L $loop_count -f 0 -l end -n 8 -d @diskL -o sort" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script12 -t 29 -q 12 -L $loop_count -f 0 -l end -n 8 -d @diskL -o sort" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script13 -t 29 -q 13 -L $loop_count -f 0 -l end -n 8 -d @diskL -o sort" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script14 -t 29 -q 14 -L $loop_count -f 0 -l end -n 8 -d @diskL -o sort" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script15 -t 29 -q 15 -L $loop_count -f 0 -l end -n 8 -d @diskL -o sort" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script16 -t 29 -q 16 -L $loop_count -f 0 -l end -n 8 -d @diskL -o sort" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script17 -t -1 -d @diskL" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );

    if ( $drid eq "all" ) {
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => "$time" );
        $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual runscript -d @diskL" );
        sleep(60);
        foreach (@diskL) {
            my $out = $Api_Set_Obj->execute_raw_command( 'command' => "" );

            if ( $out =~ /PANIC/ ) {
                die "Filer PANIC  during disk_qual test";
            }
        }
        while (1) {
            my $output = disk_qual_Status( API => $Api_Set_Obj );
            if ( ( $output =~ /Ending script execution/ ) || ( $output =~ /idle/ ) ) {
                logcomment("**DEBUG** : Ending script execution");
                last;
            }
        }
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => "$time" );
        $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual summary -d @diskL" );
        sleep(120);
        $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
        $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    } else {
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => "$time" );
        my $out = $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual runscript -d $drid" );
        sleep(60);

        if ( $out =~ /PANIC/ ) {

            die "Filer PANIC  during disk_qual test";
        }
        while (1) {
            my $output = disk_qual_Status( API => $Api_Set_Obj );
            if ( ( $output =~ /Ending script execution/ ) || ( $output =~ /idle/ ) ) {
                logcomment("**DEBUG** : Ending script execution");
                last;
            }
        }
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => "$time" );
        $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual summary -d $drid" );
        sleep(120);
        $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
        $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    } ## end else [ if ($drid eq "all")
    disk_qual_Status( API => $Api_Set_Obj );
} ## end sub run_dq_perfm_19_Cmode

#######################################################################################################
# Author - vpankaj@netapp.com
# Description - Create run_dq_perfm_20
# Sequence of disk_qual operations are performed
# Supported Mode - Maintenance
#######################################################################################################
sub run_dq_perfm_20_Cmode {
    my (%opts) = validate(
        @_,
        {
            Node             => { type => OBJECT },
            API              => { type => OBJECT },
            MODE             => { type => SCALAR, default => "MAINT" },
            fw               => { type => SCALAR },
            drid             => { type => SCALAR },
            diskL_add_before => { type => ARRAYREF },
            loop_count       => { type => SCALAR, optional => 1 }
        }
    );
    my $node        = $opts{Node};
    my $Api_Set_Obj = $opts{API};
    my $MODE        = $opts{MODE};
    my $con_obj     = $opts{con_obj};
    my $fw          = $opts{fw};
    my $drid        = $opts{drid};
    my @diskL       = @{ $opts{diskL_add_before} };
    my $loop_count;
    my $Filer = $node->name();

    if ( !$opts{loop_count} ) {
        $loop_count = 5000;
    } else {
        $loop_count = $opts{loop_count};
    }

    my $time = get_max_timeout( node_present => [$node] );
    $Api_Set_Obj->set_timeout( 'connectrec-timeout' => 7200 );

    # pre_commands_perf( $host_obj, $con_obj, $MODE, $drid);

    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual remarks -d @diskL -o 'T20; DENSEIO UNSORTED READ PERF; QUEUE 1-16; ALL drives; FW Nxxx'" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );

    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script0 -t 30 -q 1 -L $loop_count -f 0 -l end -n 8 -d @diskL" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script1 -t 28 -q 1 -L $loop_count -f 0 -l end -n 8 -d @diskL" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script2 -t 28 -q 2 -L $loop_count -f 0 -l end -n 8 -d @diskL" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script3 -t 28 -q 3 -L $loop_count -f 0 -l end -n 8 -d @diskL" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script4 -t 28 -q 4 -L $loop_count -f 0 -l end -n 8 -d @diskL" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script5 -t 28 -q 5 -L $loop_count -f 0 -l end -n 8 -d @diskL" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script6 -t 28 -q 6 -L $loop_count -f 0 -l end -n 8 -d @diskL" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script7 -t 28 -q 7 -L $loop_count -f 0 -l end -n 8 -d @diskL" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script8 -t 28 -q 8 -L $loop_count -f 0 -l end -n 8 -d @diskL" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script9 -t 28 -q 9 -L $loop_count -f 0 -l end -n 8 -d @diskL" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script10 -t 28 -q 10 -L $loop_count -f 0 -l end -n 8 -d @diskL" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script11 -t 28 -q 11 -L $loop_count -f 0 -l end -n 8 -d @diskL" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script12 -t 28 -q 12 -L $loop_count -f 0 -l end -n 8 -d @diskL" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script13 -t 28 -q 13 -L $loop_count -f 0 -l end -n 8 -d @diskL" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script14 -t 28 -q 14 -L $loop_count -f 0 -l end -n 8 -d @diskL" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script15 -t 28 -q 15 -L $loop_count -f 0 -l end -n 8 -d @diskL" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script16 -t 28 -q 16 -L $loop_count -f 0 -l end -n 8 -d @diskL" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script17 -t -1 -d @diskL" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );

    if ( $drid eq "all" ) {
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => "$time" );
        $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual runscript -d @diskL" );
        sleep(60);
        foreach (@diskL) {
            my $out = $Api_Set_Obj->execute_raw_command( 'command' => "" );

            if ( $out =~ /PANIC/ ) {
                die "Filer PANIC  during disk_qual test";
            }
        }
        while (1) {
            my $output = disk_qual_Status( API => $Api_Set_Obj );
            if ( ( $output =~ /Ending script execution/ ) || ( $output =~ /idle/ ) ) {
                logcomment("**DEBUG** : Ending script execution");
                last;
            }
        }
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => "$time" );
        $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual summary -d @diskL" );
        sleep(120);
        $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
        $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    } else {
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => "$time" );
        my $out = $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual runscript -d $drid" );
        sleep(60);

        if ( $out =~ /PANIC/ ) {

            die "Filer PANIC  during disk_qual test";
        }
        while (1) {
            my $output = disk_qual_Status( API => $Api_Set_Obj );
            if ( ( $output =~ /Ending script execution/ ) || ( $output =~ /idle/ ) ) {
                logcomment("**DEBUG** : Ending script execution");
                last;
            }
        }
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => "$time" );
        $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual summary -d $drid" );
        sleep(120);
        $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
        $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    } ## end else [ if ($drid eq "all")
    disk_qual_Status( API => $Api_Set_Obj );
} ## end sub run_dq_perfm_20_Cmode

#######################################################################################################
# Author - vpankaj@netapp.com
# Description - Create run_dq_perfm_21
# Sequence of disk_qual operations are performed
# Supported Mode - Maintenance
#######################################################################################################
sub run_dq_perfm_21_Cmode {
    my (%opts) = validate(
        @_,
        {
            Node             => { type => OBJECT },
            API              => { type => OBJECT },
            MODE             => { type => SCALAR, default => "MAINT" },
            fw               => { type => SCALAR },
            drid             => { type => SCALAR },
            diskL_add_before => { type => ARRAYREF },
            loop_count       => { type => SCALAR, optional => 1 }
        }
    );
    my $node        = $opts{Node};
    my $Api_Set_Obj = $opts{API};
    my $MODE        = $opts{MODE};
    my $con_obj     = $opts{con_obj};
    my $fw          = $opts{fw};
    my $drid        = $opts{drid};
    my @diskL       = @{ $opts{diskL_add_before} };
    my $loop_count;
    my $Filer = $node->name();

    if ( !$opts{loop_count} ) {
        $loop_count = 5000;
    } else {
        $loop_count = $opts{loop_count};
    }

    my $time = get_max_timeout( node_present => [$node] );
    $Api_Set_Obj->set_timeout( 'connectrec-timeout' => 7200 );

    # pre_commands_perf( $host_obj, $con_obj, $MODE, $drid);

    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual remarks -d @diskL -o 'T21; DENSEIO UNSORTED WRITE PERF; QUEUE 1-16; All drives; FW Nxxx'" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );

    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script0 -t 31 -q 1 -L $loop_count -f 0 -l end -n 8 -d @diskL" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script1 -t 29 -q 1 -L $loop_count -f 0 -l end -n 8 -d @diskL" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script2 -t 29 -q 2 -L $loop_count -f 0 -l end -n 8 -d @diskL" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script3 -t 29 -q 3 -L $loop_count -f 0 -l end -n 8 -d @diskL" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script4 -t 29 -q 4 -L $loop_count -f 0 -l end -n 8 -d @diskL" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script5 -t 29 -q 5 -L $loop_count -f 0 -l end -n 8 -d @diskL" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script6 -t 29 -q 6 -L $loop_count -f 0 -l end -n 8 -d @diskL" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script7 -t 29 -q 7 -L $loop_count -f 0 -l end -n 8 -d @diskL" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script8 -t 29 -q 8 -L $loop_count -f 0 -l end -n 8 -d @diskL" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script9 -t 29 -q 9 -L $loop_count -f 0 -l end -n 8 -d @diskL" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script10 -t 29 -q 10 -L $loop_count -f 0 -l end -n 8 -d @diskL" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script11 -t 29 -q 11 -L $loop_count -f 0 -l end -n 8 -d @diskL" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script12 -t 29 -q 12 -L $loop_count -f 0 -l end -n 8 -d @diskL" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script13 -t 29 -q 13 -L $loop_count -f 0 -l end -n 8 -d @diskL" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script14 -t 29 -q 14 -L $loop_count -f 0 -l end -n 8 -d @diskL" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script15 -t 29 -q 15 -L $loop_count -f 0 -l end -n 8 -d @diskL" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script16 -t 29 -q 16 -L $loop_count -f 0 -l end -n 8 -d @diskL" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script17 -t -1 -d @diskL" );
    disk_qual_Status( API => $Api_Set_Obj );
    $Api_Set_Obj->execute_raw_command( 'command' => "\013" );

    if ( $drid eq "all" ) {
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => "$time" );
        $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual runscript -d @diskL" );
        sleep(60);
        foreach (@diskL) {
            my $out = $Api_Set_Obj->execute_raw_command( 'command' => "" );

            if ( $out =~ /PANIC/ ) {
                die "Filer PANIC  during disk_qual test";
            }
        }
        while (1) {
            my $output = disk_qual_Status( API => $Api_Set_Obj );
            if ( ( $output =~ /Ending script execution/ ) || ( $output =~ /idle/ ) ) {
                logcomment("**DEBUG** : Ending script execution");
                last;
            }
        }
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => "$time" );
        $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual summary -d @diskL" );
        sleep(120);
        $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
        $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    } else {
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => "$time" );
        my $out = $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual runscript -d $drid" );
        sleep(60);

        if ( $out =~ /PANIC/ ) {

            die "Filer PANIC  during disk_qual test";
        }
        while (1) {
            my $output = disk_qual_Status( API => $Api_Set_Obj );
            if ( ( $output =~ /Ending script execution/ ) || ( $output =~ /idle/ ) ) {
                logcomment("**DEBUG** : Ending script execution");
                last;
            }
        }
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => "$time" );
        $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual summary -d $drid" );
        sleep(120);
        $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
        $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
    } ## end else [ if ($drid eq "all")
    disk_qual_Status( API => $Api_Set_Obj );
} ## end sub run_dq_perfm_21_Cmode

sub disk_qual_drive_assign_maint {
    my (%opts) = validate(
        @_,
        {
            Node_ref => { type => ARRAYREF },
            disk_ref => { type => ARRAYREF },
        }
    );
    my @Nodes        = @{ $opts{Node_ref} };
    my $FILER_C      = $Nodes[0]->name();
    my %Node_unowned = ();
    my @disks;
    if ( defined( $opts{disk_ref} ) ) {
        @disks = @{ $opts{disk_ref} };
    }

    foreach my $node (@Nodes) {
        my $FILER       = $node->name();
        my $Host        = host($FILER);
        my $console     = Tharn::connect("$FILER#console");
        my $Transit_obj = NACL::Transit->new( name => $FILER );
        my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
        logcomment("Filer state $filer_state ");
        my $sysid;

        # Set the properties for the Connectrec used for creating the APIset
        $console->{prompts}  = [qr/\*>/];
        $console->{max_idle} = "600";
        $console->{on_idle}  = sub { $console->execute(""); };
        my $API_obj = NACL::APISet->new(
            connection => $console,
            category   => "Node",
            interface  => "CLI",
            set        => "Maintenance"
        );
        $API_obj->set_timeout( 'connectrec-timeout' => 7200 );
        my @unowned_disks = keys %{ disk_show_n( Node => $node ) };
        if (@unowned_disks) {
            my $dsks = _print_array( \@unowned_disks );
            logcomment( "Total Number of drives which are currently unassigned are " . scalar @unowned_disks . " and the drives are:\n" . $dsks );
            logcomment("Executing sysconfig -v to capture system ID");
            my $after = $API_obj->execute_raw_command( 'command' => "sysconfig -v" );
            if ( ( $after =~ /\s*System ID:\s+(\d+)\s+/ ) ) {
                $sysid = $1;
            } else {
                logcomment("**FATAL** : Could NOT found the sysid for the filer $FILER");
                logresult( 'FATAL', "COULDN'T FOUND THE SYSID FOR THE FILER $FILER" );
            }

            if (@disks) {
                foreach my $disk (@disks) {
                    my $dsk_output = $API_obj->execute_raw_command( 'command' => "disk show -n $disk" );
                    if ( $dsk_output =~ /Not Owned/ ) {
                        $API_obj->execute_raw_command( 'command' => "disk remove_ownership -f $disk" );
                        sleep 10;
                        $API_obj->execute_raw_command( 'command' => "storage release disks -f" );
                        sleep 10;
                        logcomment("Assigning the drives $disk to filer $FILER");
                        $API_obj->execute_raw_command( 'command' => "disk assign $disk -o $FILER -s $sysid -f" );
                        sleep 60;
                        $API_obj->execute_raw_command( 'command' => "\013" );
                    }
                }
            } elsif (@unowned_disks) {
                foreach my $disk (@unowned_disks) {
                    my $dsk_output = $API_obj->execute_raw_command( 'command' => "disk show -n $disk" );
                    if ( $dsk_output =~ /Not Owned/ ) {
                        $API_obj->execute_raw_command( 'command' => "disk remove_ownership -f $disk" );
                        sleep 10;
                        $API_obj->execute_raw_command( 'command' => "storage release disks -f" );
                        sleep 10;
                        logcomment("Assigning the drives $disk to filer $FILER");
                        $API_obj->execute_raw_command( 'command' => "disk assign $disk -o $FILER -s $sysid -f" );
                        sleep 60;
                        $API_obj->execute_raw_command( 'command' => "\013" );
                    }
                }
            }
        }
    }
}

#######################################################################################################
# Author - aditis@netapp.com
# Description - Pre condition ssd drive (Maint mode)
#######################################################################################################
sub pre_condition_ssd_drive {
    my (%opts) = validate(
        @_,
        {
            disks => { type => ARRAYREF },
            node  => { type => OBJECT },
        }
    );
    my @disks   = @{ $opts{disks} };
    my $Node    = $opts{node};
    my $FILER_C = $Node->name();
    my $Host    = host($FILER_C);
    my $API_Ob  = NACL::APISet->new(
        hostobj   => $Host,
        category  => "Node",
        interface => "CLI",
        set       => "Maintenance"
    );
    $API_Ob->set_timeout( 'connectrec-timeout' => 7200 );
    my $SGL            = "bcs";
    my $time_out_temp  = 0;
    my $test_wait_time = 7200;
    my $flag;
    my %data_rate = ();
    my %rates     = ();

    #        foreach my $drv (@disks){
    logcomment("Preconditioning drives - @disks");

    # SSD - Precondition
    #--------------------------------------------------------------------------
    # clear FTL
    logcomment("Clear FTL for drives - @disks");
    my $diskqual = $API_Ob->execute_raw_command( command => "disk_qual start -t 9 -d @disks -o noverify nopattern unmap" );
    logcomment("Test will wait maximum of 2 hours for disk_qual to complete");
    sleep 120;
    $API_Ob->execute_raw_command( command => "\013" );
    $API_Ob->execute_raw_command( command => "\013" );
    while ( $time_out_temp < $test_wait_time ) {
        $flag = 0;
        my $status = $API_Ob->execute_raw_command( command => "disk_qual status" );
        if ( $status =~ /idle/g ) {
            logcomment("Disk_qual completed.");
            last;
        } else {
            $flag = 1;
        }
        sleep 300;
        $time_out_temp = $time_out_temp + 300;
    }
    if ( $flag == 1 ) {
        logcomment("**WARNING**: Disk_qual did NOT completed within the given time");
    }

    # determine data rate
    $API_Ob->execute_raw_command( command => "\013" );
    $API_Ob->execute_raw_command( command => "\013" );
    sleep 120;
    $API_Ob->execute_raw_command( command => "\013" );
    logcomment("Determine data rate");
    my $output = $API_Ob->execute_raw_command( command => "disk_latency -p seq_write -q 32 -t 60 -i 0 -m $SGL -l 832000 -s 133120 -f @disks" );
    logcomment("==============================================================\n");
    my @output_data = split( /\n/, $output );

    foreach my $line (@output_data) {
        if ( ( $line =~ /(\w+\.\w+\.\w+)\s+\d+\s+(\d+)\s+\d+\s+\d+\s+\d+$/ ) || ( $line =~ /(\w+\.\w+)\s+\d+\s+(\d+)\s+\d+\s+\d+\s+\d+$/ ) ) {    #Nvme
            my $dsk       = $1;
            my $data_rate = $2;
            push( @{ $rates{$FILER_C}{$data_rate} }, $dsk );
            last if ( $line =~ /^Latency Histogram:/i );
        }
    }
    my @rate_arr = keys %{ $rates{$FILER_C} };
    @rate_arr = sort { $a <=> $b } @rate_arr;
    my @arr_disk = @{ $rates{$FILER_C}{ $rate_arr[0] } };
    my $dsk_last = $arr_disk[0];
    my $drv;
    ($drv) = $dsk_last =~ /\w+\.(\S+)/;
    logcomment("Disk - $drv :: Data rate - $rate_arr[0]");
    my $ssd_capacity;
    sleep 60;
    my $disk_list_result = disk_list_data( API_Obj => $API_Ob );

    foreach my $dsk ( keys %$disk_list_result ) {
        if ( $disk_list_result->{$dsk}->{'DISK'} =~ /$drv$/ ) {
            my $disk_size = $disk_list_result->{$dsk}->{'BLOCKS'};
            my $bps       = $disk_list_result->{$dsk}->{'BPS'};
            $ssd_capacity = int( ( $disk_size * $bps ) / 1000000 );
            last;
        }
    }
    if ( $rate_arr[0] < 500 ) {
        logcomment("**WARNING** : $FILER_C : Data rate: $rate_arr[0]MB/s, Data rate is less than 500MB/s");
    }
    logcomment("Disk - $dsk_last :: Data rate - $rate_arr[0] :: Drive capacity - $ssd_capacity");
    my $precond_time = int( 1.5 * ( $ssd_capacity / $rate_arr[0] ) );
    logcomment(" Pre condition time - $precond_time");

    # perform sequential precondition (q=32, s=128KB)
    logcomment("Perform sequential precondition (q=32, s=128KB)");
    my $timeout = $precond_time + 7200;
    $API_Ob->set_timeout( "connectrec-timeout" => $timeout );
    $API_Ob->execute_raw_command( command => "disk_latency -p seq_write -q 32 -t $precond_time -i 0 -m $SGL -s 133120 -f @disks" );
    logcomment("Precondition completed");

    # }
}

#######################################################################################################
# Author - khosur@netapp.com
# Description - Sequential Pre condition ssd drive (Maint mode)
# disk_qual cmnds
# disk_qual start -t 9 -d  -o noverify nopattern unmap
# disk_qual start -t 5 -n 512 -p 2 -d  -o noverify nopattern
#######################################################################################################
sub seq_pre_condition_ssd_drive {
    my (%opts) = validate(
        @_,
        {
            disks => { type => ARRAYREF },
            node  => { type => OBJECT },
        }
    );
    my @disks   = @{ $opts{disks} };
    my $Node    = $opts{node};
    my $FILER_C = $Node->name();
    my $Host    = host($FILER_C);
    my $API_Ob  = NACL::APISet->new(
        hostobj   => $Host,
        category  => "Node",
        interface => "CLI",
        set       => "Maintenance"
    );
    $API_Ob->set_timeout( 'connectrec-timeout' => 10800 );
    my $SGL            = "bcs";
    my $time_out_temp  = 0;
    my $test_wait_time = 10800;
    my $flag;
    my %data_rate = ();
    my %rates     = ();

    logcomment("Preconditioning drives - @disks");

    # SSD - Precondition
    #--------------------------------------------------------------------------
    # clear FTL
    logcomment("Clear FTL for drives - @disks");
    ### Disk_qual test 9
    ### disk_qual start -t 9 -d  -o noverify nopattern unmap
    my $diskqual = $API_Ob->execute_raw_command( command => "disk_qual start -t 9 -d @disks -o noverify nopattern unmap" );
    logcomment("Test will wait maximum of 3 hours for disk_qual to complete");
    sleep 120;
    $API_Ob->execute_raw_command( command => "\013" );
    $API_Ob->execute_raw_command( command => "\013" );
    while ( $time_out_temp < $test_wait_time ) {
        $flag = 0;
        my $status = $API_Ob->execute_raw_command( command => "disk_qual status" );
        if ( $status =~ /idle/g ) {
            logcomment("Disk_qual completed.");
            last;
        } else {
            $flag = 1;
        }
        sleep 300;
        $time_out_temp = $time_out_temp + 300;
    }
    if ( $flag == 1 ) {

        # logcomment("**WARNING**: Disk_qual test 9 did NOT complete within the given time");
        logcomment("**WARNING**: Aborting seq disk_qual test 9,as it did NOT complete within the given time.");
        $API_Ob->execute_raw_command( command => "disk_qual stop -d all" );
        $API_Ob->execute_raw_command( command => "\013" );
        $API_Ob->execute_raw_command( command => "\013" );
        my $status = $API_Ob->execute_raw_command( command => "disk_qual status" );
        if ( $status =~ /idle/g ) {
            logcomment("Disk_qual aborted successfully.");
        }
    }

    ### disk_qual start -t 5 -n 512 -p 2 -d  -o noverify nopattern
    my $diskqual = $API_Ob->execute_raw_command( command => "disk_qual start -t 5 -n 512 -p 2 -d @disks -o noverify nopattern" );
    logcomment("Test will wait maximum of 3 hours for disk_qual to complete");
    sleep 120;
    $API_Ob->execute_raw_command( command => "\013" );
    $API_Ob->execute_raw_command( command => "\013" );
    while ( $time_out_temp < $test_wait_time ) {
        $flag = 0;
        my $status = $API_Ob->execute_raw_command( command => "disk_qual status" );
        if ( $status =~ /idle/g ) {
            logcomment("Disk_qual completed.");
            last;
        } else {
            $flag = 1;
        }
        sleep 300;
        $time_out_temp = $time_out_temp + 300;
    }
    if ( $flag == 1 ) {

        # logcomment("**WARNING**: Disk_qual test 5 did NOT complete within the given time");
        logcomment("**WARNING**: Aborting seq disk_qual test 5,as it did NOT complete within the given time.");
        $API_Ob->execute_raw_command( command => "disk_qual stop -d all" );
        $API_Ob->execute_raw_command( command => "\013" );
        $API_Ob->execute_raw_command( command => "\013" );
        my $status = $API_Ob->execute_raw_command( command => "disk_qual status" );
        if ( $status =~ /idle/g ) {
            logcomment("Disk_qual aborted successfully.");
        }

    }

    logcomment("Precondition completed");

}

#######################################################################################################
# Author - khosur@netapp.com
# Description - Random Pre condition ssd drive (Maint mode)
# disk_qual cmnds
# disk_qual start -t 9 -d  -o noverify nopattern unmap
# disk_qual start -t 7 -n 1 -p 1 -d  -o noverify nopattern
#######################################################################################################
sub rand_pre_condition_ssd_drive {
    my (%opts) = validate(
        @_,
        {
            disks => { type => ARRAYREF },
            node  => { type => OBJECT },
        }
    );
    my @disks   = @{ $opts{disks} };
    my $Node    = $opts{node};
    my $FILER_C = $Node->name();
    my $Host    = host($FILER_C);
    my $API_Ob  = NACL::APISet->new(
        hostobj   => $Host,
        category  => "Node",
        interface => "CLI",
        set       => "Maintenance"
    );
    $API_Ob->set_timeout( 'connectrec-timeout' => 10800 );
    my $SGL            = "bcs";
    my $time_out_temp  = 0;
    my $test_wait_time = 10800;
    my $flag;
    my %data_rate = ();
    my %rates     = ();

    logcomment("Preconditioning drives - @disks");

    # SSD - Precondition
    #--------------------------------------------------------------------------
    # clear FTL
    logcomment("Clear FTL for drives - @disks");

    ### disk_qual start -t 9 -d  -o noverify nopattern unmap
    my $diskqual = $API_Ob->execute_raw_command( command => "disk_qual start -t 9 -d @disks -o noverify nopattern unmap" );
    logcomment("Test will wait maximum of 3 hours for disk_qual to complete");
    sleep 120;
    $API_Ob->execute_raw_command( command => "\013" );
    $API_Ob->execute_raw_command( command => "\013" );
    while ( $time_out_temp < $test_wait_time ) {
        $flag = 0;
        my $status = $API_Ob->execute_raw_command( command => "disk_qual status" );
        if ( $status =~ /idle/g ) {
            logcomment("Disk_qual completed.");
            last;
        } else {
            $flag = 1;
        }
        sleep 300;
        $time_out_temp = $time_out_temp + 300;
    }
    if ( $flag == 1 ) {

        # logcomment("**WARNING**: Disk_qual test 9 did NOT complete within the given time");
        logcomment("**WARNING**: Aborting rand disk_qual test 9,as it did NOT complete within the given time.");
        $API_Ob->execute_raw_command( command => "disk_qual stop -d all" );
        $API_Ob->execute_raw_command( command => "\013" );
        $API_Ob->execute_raw_command( command => "\013" );
        my $status = $API_Ob->execute_raw_command( command => "disk_qual status" );
        if ( $status =~ /idle/g ) {
            logcomment("Disk_qual test 9 aborted successfully.");
        }

    }

    ### disk_qual start -t 7 -n 1 -p 1 -d  -o noverify nopattern
    my $diskqual = $API_Ob->execute_raw_command( command => "disk_qual start -t 7 -n 8 -p 1 -d @disks -o noverify nopattern" );
    logcomment("Test will wait maximum of 3 hours for disk_qual to complete");
    sleep 120;
    $API_Ob->execute_raw_command( command => "\013" );
    $API_Ob->execute_raw_command( command => "\013" );
    while ( $time_out_temp < $test_wait_time ) {
        $flag = 0;
        my $status = $API_Ob->execute_raw_command( command => "disk_qual status" );
        if ( $status =~ /idle/g ) {
            logcomment("Disk_qual completed.");
            last;
        } else {
            $flag = 1;
        }
        sleep 300;
        $time_out_temp = $time_out_temp + 300;
    }
    if ( $flag == 1 ) {

        # logcomment("**WARNING**: Disk_qual test 7 did NOT complete within the given time");
        logcomment("**WARNING**: Aborting rand disk_qual test 7,as it did NOT complete within the given time.");
        $API_Ob->execute_raw_command( command => "disk_qual stop -d all" );
        $API_Ob->execute_raw_command( command => "\013" );
        $API_Ob->execute_raw_command( command => "\013" );
        my $status = $API_Ob->execute_raw_command( command => "disk_qual status" );
        if ( $status =~ /idle/g ) {
            logcomment("Disk_qual test 7 aborted successfully.");
        }

    }

    logcomment("Precondition completed");

}

#######################################################################################################
# Author - aditis@netapp.com
# Description - Dump event and crash logs of BSAS|MSATA drives (CLI Mode)
#######################################################################################################

sub stsb_event_crash_log {
    my (%opts) = validate( @_, { Node => { type => OBJECT }, } );

    my $Node    = $opts{Node};
    my $FILER_C = $Node->name();
    my $Api_Set_Obj;
    my @disk_list;
    my $sto_show_data = {};
    my $type;
    $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
    $Api_Set_Obj->set_timeout( "connectrec-timeout" => '7200' );
    logcomment("Writing crash log and event log of BSAS or MSATA drives if present");
    my $raw_output = $Api_Set_Obj->execute_command( 'command' => "aggr status -r" );
    chomp( my @sysconf_lines = split( /\r?\n/, $raw_output ) );
    my $MSATA = 0;

    foreach my $line (@sysconf_lines) {
        if ( $line =~ /\S+\s+(\S+)\s+\S+\s+\d+\s+\d+\s+\S+\s+\S+\s+(\S+)\s+\d+\s+\S+\s+\S+/ ) {

            #                        	my $data = $1;
            $type = $2;
            last;
        }
    }
    if ( $type =~ /BSAS|MSATA/ ) {
        my $disk_output = $Api_Set_Obj->execute_command( 'command' => "disk show -o $FILER_C" );
        my @disk_lines = split( /\n/, $disk_output );
        foreach my $line (@disk_lines) {
            if ( $line !~ /DISK|OWNER|POOL|SERIAL NUMBER|HOME/ ) {
                if ( $line =~ /(\S+)\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+/ ) {
                    my $data = $1;
                    push( @disk_list, $data );
                }
            }
        }
    }
    if ( $type =~ /MSATA/ ) {
        $MSATA = 1;
    }
    if ( scalar(@disk_list) != 0 ) {
        my $Mode = $Node->mode();
        $sto_show_data = storage_show_disk_a_data( Node => $Node );
        logcomment("DEBUG:Checking Model number of the disks @disk_list");
        my %dr_id = ();
        foreach my $disk (@disk_list) {
            my $mdl = $sto_show_data->{$disk}->{'Model'};
            logcomment("Filer : $FILER_C : Model of disk $disk is $mdl");
            if ( ( $mdl =~ /(SA)$/ ) || ( $mdl =~ /(SM)$/ ) || ( $mdl =~ /(SDB)$/ ) ) {
                $dr_id{$disk} = $1;
                logcomment("Dongle type of disk $disk : $dr_id{$disk}");
                if ( $MSATA == 1 ) {
                    if ( $disk =~ /L1$/ ) {
                        logcomment("Dumping Dongle Crash Log and Event Log of disk $disk");
                        my $disk_without_lun_SA = $disk;
                        $disk_without_lun_SA =~ s/L\d+$//;
                        $Api_Set_Obj->execute_command( 'command' => "stsb get_event_log $disk_without_lun_SA" );
                        $Api_Set_Obj->execute_command( 'command' => "stsb get_crash_dump $disk_without_lun_SA" );
                    }
                } else {
                    logcomment("Dumping Dongle Crash Log and Event Log of disk $disk");
                    my $disk_without_lun_SA = $disk;
                    $disk_without_lun_SA =~ s/L\d+$//;
                    $Api_Set_Obj->execute_command( 'command' => "stsb get_event_log $disk_without_lun_SA" );
                    $Api_Set_Obj->execute_command( 'command' => "stsb get_crash_dump $disk_without_lun_SA" );
                }
            }
        }
    } else {
        logcomment("Skipping get_event_log and get_crash_dump as these steps are applicable only for SATA drives");
    }
}

#######################################################################################################
# Author - aditis@netapp.com
# Description -  returns hash consisting data of all disk attached to particular node (CLI Mode/Maint Mode)
#######################################################################################################

sub diskshow_filer {
    my (%opts) = validate( @_, { Node => { type => OBJECT }, } );

    my $Node    = $opts{Node};
    my $FILER_C = $Node->name();
    my $Api_Set_Obj;
    my $disk_output;
    my $dsk_result  = {};
    my $Transit_obj = NACL::Transit->new( name => $FILER_C );
    my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    if ( $filer_state =~ /MAINT/gi ) {
        my $Host = host($FILER_C);
        $Api_Set_Obj = NACL::APISet->new(
            hostobj   => $Host,
            category  => "Node",
            interface => "CLI",
            set       => "Maintenance"
        );
        $Api_Set_Obj->set_timeout( 'connectrec-timeout' => 7200 );
        $disk_output = $Api_Set_Obj->execute_raw_command( 'command' => "disk show -o $FILER_C" );
    } elsif ( $filer_state =~ /(CLI|UP)/gi ) {
        $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
        $Api_Set_Obj->set_timeout( 'connectrec-timeout' => 7200 );
        $disk_output = $Api_Set_Obj->execute_command( 'command' => "disk show -o $FILER_C" );
    }
    my @disk_lines = split( /\n/, $disk_output );
    foreach my $line (@disk_lines) {
        if ( $line !~ /DISK|OWNER|POOL|SERIAL NUMBER|HOME/ ) {
            if ( $line =~ /(\S+)\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+/ ) {
                my ( $disk, $owner, $pool, $serial_num, $home ) = ( $line =~ /(\w+\.\d+\.\d+)\s+(\S+)\s+\S+\s+(\S+)\s+(\S+)\s+(\S+)\s+\S+/ );
                $dsk_result->{$disk} = {
                    'DISK'   => $disk,
                    'OWNER'  => $owner,
                    'POOL'   => $pool,
                    'SERIAL' => $serial_num,
                    'HOME'   => $home
                };
            }
        }
    }
    return $dsk_result;
}

######################################################################################################
# author : nmamatha
# checking for the filer connection closed by foring host or not
#####################################################################################################
sub check_filer_connection {
    my (%opts) = validate( @_, { Filer_name => { type => ARRAYREF }, } );
    my $Home   = $ENV{HOME};
    my @Filers = @{ $opts{Filer_name} };
    {
        foreach my $Node (@Filers) {
            my $logfile = "$Home/NDATE/FILER_INFO/$Node";
            open( FH, "$logfile" ) || logresult( 'FATAL', "CANNOT OPEN THE FILE $logfile" );
            my @arr = ;
            close(FH);
            my ( $ip, $port );
            foreach (@arr) {
                if ( $_ =~ /conn console {conntype=serial;connhost=(\w+\.\w+\.\w+\.\w+);connport=(\w+);password=netapp1!}/ig ) { $ip = $1; $port = $2; }
            }
            my $cmd = "telnet $ip  $port";
            logcomment("Checking accessibility for Filer $Node with  IP : $ip and   Port : $port \n $cmd");
            my $flag    = 0;
            my $timeout = 1;
            my $spawn_ok;
            my $i;
            my $flag_fatal = 0;

            for ( $i = 0 ; $i <= 2 ; $i++ ) {
                $flag = 0;
                my $exp = Expect->spawn("telnet $ip $port") or logresult( 'FATL', "Cannot spawn telnet: $!\n" );
                my $timeout = 2;
                my $spawn_ok;
                $exp->expect(
                    $timeout,
                    [ 'Enter your option :', sub { $flag = 1; logcomment("$Node: Filer is in Use\n"); my $fh = shift; print $fh "3\n"; } ],
                    [ 'is being used by',    sub { $flag = 1; logcomment("$Node: Filer is in Use\n"); my $fh = shift; print $fh "3\n"; } ],
                    [
                        eof => sub {
                            $flag = 1;
                            if ($spawn_ok) {
                                logcomment("$Node: Filer is in Use.\n");
                            } else {
                                logcomment("$Node: Filer is in Use.\n");
                            }
                        }
                    ],
                    [ 'Connection closed by foreign host', sub { $flag = 1; logcomment("$Node: Filer is in Use\n"); } ],
                    [ timeout => sub { $flag = 0; logcomment("$Node: Filer is free\n"); } ],
                    '> $',
                );
                $exp->send("");
                $exp->soft_close();
                if ( $flag == 1 ) {
                    logcomment("$Node : Waiting for 2 min ");
                    if ( $i == 2 ) {
                        $flag_fatal = 1;
                        goto L1;
                    }
                    sleep(120);
                } else {
                    last;
                }
            }
          L1:
            if ( $flag_fatal == 1 ) {
                logcomment("Finished with Re-estabilishing Connection to Filer ");
                logcomment("**FATAL** : $Node : Filer is used by foreign host after waiting for 4 min");
                logresult( 'FATAL', " $Node : FILER IS USED BY FOREIGN HOST AFTER WAITING FOR 4 MIN" );
            }

        }
        logcomment("Finished with Re-estabilishing Connection to Filer ");
    }
    logcomment("Check State of Filer ");
    my @temp_nodes = NACL::C::Node->find();
    foreach my $Node (@temp_nodes) {
        my $FILER_C     = $Node->name();
        my $host        = Tharn::host($FILER_C);
        my $Transit_obj = NACL::Transit->new( name => $FILER_C );
        my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
        logcomment("Filer : $FILER_C is in $filer_state state");

        #Check for login prompt on filer, before proceeding and change
        if ( $filer_state =~ /CLI|UP/ ) {
            my $prompt_fw;
            my $ignore_strings = [ "MADIMM\\d+->", "DIMM\\d+->", "^T>" ];
            my $host           = Tharn::host($FILER_C);
            my $prompt_array   = $host->prompt_fw();
            my $prompts        = join( "|", @$prompt_array );
            $prompt_fw = "($prompts)";
            logcomment("DEBUG:This is the prompt regex: $prompt_fw");
            my $Server = new Server( no_cli => 1 );
            $Server->set_execution_server( -Server => $FILER_C );
            $Server->console(
                cmd                        => "set test",
                additional_prompts_timeout => 600,
                ignore                     => $ignore_strings,
                additional_prompts         => {
                    "$FILER_C\>"               => "FINAL_PROMPT",
                    "Do you want to continue?" => "y",
                    "$prompt_fw"               => "FINAL_PROMPT",
                    "::*>"                     => "FINAL_PROMPT",
                    "\.*\>"                    => "FINAL_PROMPT",
                    "\>"                       => "FINAL_PROMPT"
                }
            );
            logcomment("API Created");
            logcomment("Privilage level set to test - Console connection");
        }
    }
}

#----------------------------------------------------------------
# author : nmamatha
# Burt : 1033627, 1037194
# checking for Proper Firmware files in for test 400,407,501,506
# check1 : Add a check in test script, in setup subroutine, to check the existing firmware present on the drives.
# check 2 : If current drive FW rev is sub NQ49 or NA49, rename it to NQ49 and then copy to /etc/
#           If current drive FW rev is greater than NQ49 or NA49, rename it to NQ99 and then copy to /etc/
#----------------------------------------------------------------
sub check_existing_disk_firmware {
    my (%opts) = validate(
        @_,
        {
            Node             => { type => OBJECT },
            disk_fw_location => { type => SCALAR },
            timeout          => { type => SCALAR, default => 1200, optional => 1 },
        }
    );

    my $Home         = $ENV{HOME};
    my $Node         = $opts{Node};
    my $disk_fw_path = $opts{disk_fw_location};
    my $sudo         = "/usr/bin/sudo";
    my $Api_Set_Obj  = $Node->get_7m_or_nodescope_apiset();
    $Api_Set_Obj->set_timeout( 'connectrec-timeout' => 7200 );
    my $Mode          = $Node->mode();
    my $FILER_C       = $Node->name();
    my %new_disk_fw   = ();
    my $new_disk_fw_p = [];
    $new_disk_fw_p = \%new_disk_fw;
    my %model = ();
    my %rev   = ();
    my $ver   = $Api_Set_Obj->execute_raw_command( 'command' => "version" );
    my @disk_list;
    my @disk_fw;

    if ( defined $disk_fw_path ) {
        @disk_fw = `cd $opts{disk_fw_location};ls *.LOD`;
    } else {
        $disk_fw_path = "$Home/NDATE/FIRMWARE/DISKFW/HIGH";
        @disk_fw      = `cd $disk_fw_path;ls *.LOD`;
    }
    logcomment("Following Firmwares found in the directory $opts{disk_fw_location}:");
    logcomment("@disk_fw");

    if ( @disk_fw < 1 ) {
        logcomment("NO DISK FIRMWARE FILES are available");
        return ( 0, $new_disk_fw_p );
    }
    my @list_of_disk = list_of_disk( Node => $Node );
    foreach my $dsk (@list_of_disk) {
        if ( $dsk =~ /(P\d+)$/ ) {
            next;
        }
        push( @disk_list, $dsk );
    }
    my %sto_show_dsk = ();
    my %model_change = ();
    logcomment("Checking for existing firmware present on the drives");
    $sto_show_dsk{$Node} = storage_show_disk_a_data( Node => $Node );
    foreach my $disk (@disk_list) {
        my $mdl = $sto_show_dsk{$Node}->{$disk}->{'Model'};
        my $rvs = $sto_show_dsk{$Node}->{$disk}->{'Rev'};
        $model{$disk} = $mdl;
        $rev{$disk}   = $rvs;
    }
    my $flag      = 0;
    my @NT_fw_dsk = ();
    foreach my $dsk (@disk_list) {
        my $model_name = $model{$dsk};
        my $rev_num    = $rev{$dsk};
        $model_name =~ s/^\s+|\s+$//g;
        my $fw = $model_name . "\.$rev_num" . "\.LOD";
        logcomment("DEBUG: Disk : $dsk ::: Model : $model_name ::: Rev No : $rev_num");
        if ( !( $new_disk_fw{$dsk} ) ) {
            $new_disk_fw{$dsk} = $fw;
            if ( $rev_num =~ /(NA|NQ)(\d\d)/ ) {
                my $ver_num = $2;
                if ( $ver_num < 50 ) {
                    logcomment("DEBUG: Current drive FW rev is $rev_num, which is less than 50 so renaming as NQ49");
                    $model_change{$model_name} = $model_name . "\.NQ49" . "\.LOD";
                } elsif ( $ver_num >= 50 ) {
                    logcomment("DEBUG: Current drive FW rev is $rev_num, which is more than 49 so renaming as NQ99");
                    $model_change{$model_name} = $model_name . "\.NQ99" . "\.LOD";
                }
            } elsif ( $rev_num =~ /NT/ ) {
                my $msg = "**WARNING** : Disk $dsk Contains the NT Revision Number - $fw";
                push( @NT_fw_dsk, $msg );
                $flag = 1;    # NORUN if the NT files are present.
            }
        }
    }    ## foreach my $dsk (@disk_list)
    if ( $flag == 1 ) {
        grep { logcomment("$_") } @NT_fw_dsk;
        return ( 1, $new_disk_fw_p );
    }
    my @model_chnage = values %model_change;

    #----- creating the backup file
    my $firmware_backup = "BACK_UP_FIRMWARES_FILES_" . $FILER_C;
    logcomment("Creating directory $firmware_backup");
    my $src_file = "$Home/NDATE/FIRMWARE/DISKFW/$firmware_backup";
    if ( !( -d "$Home/NDATE/FIRMWARE/DISKFW/$firmware_backup" ) ) {
        logcomment("Directory $Home/NDATE/FIRMWARE/DISKFW/$firmware_backup does NOT exist");
        system("sudo mkdir $Home/NDATE/FIRMWARE/DISKFW/$firmware_backup");
        system("sudo chmod 777 $Home/NDATE/FIRMWARE/DISKFW/$firmware_backup");
    } else {
        logcomment("Directory $Home/NDATE/FIRMWARE/DISKFW/$firmware_backup already exist");
        system("sudo chmod 777 $Home/NDATE/FIRMWARE/DISKFW/$firmware_backup");
    }
    logcomment("Modifying and copying files @model_chnage to $firmware_backup ");

    #--------------Modifying the LOD files--------------------------------
    my $cnt_model = scalar @model_chnage;
    my $cnt       = 0;
    foreach my $model (@model_chnage) {
        logcomment("Copying the $model to the $src_file path");
        if ( $model =~ /LOD$/ ) {
            if ( $model =~ /(\w+)\.\w+\.LOD/ ) {
                my $mod    = $1;
                my $output = system("sudo cp -rf $disk_fw_path/$mod* $src_file/$model");
                if ( $output == 256 ) {
                    logcomment("**WARNING** : NO FIRMWARE FILE found with model number : $mod ");
                }
            }
        }
    }
    my $files_present = `ls $Home/NDATE/FIRMWARE/DISKFW/$firmware_backup/`;
    if ( !$files_present ) {

        #logcomment("**FAIL** : NO FIRMWARE FILES ARE COPIED TO $firmware_backup ");
        return ( 2, $new_disk_fw_p );
    }
    logcomment("After copying files present under  $src_file are \n $files_present");
    logcomment("Copying the Firmware Files to the /etc/ path");
    my @copied_firmwares = copy_FW_files_to_filer_directory( Node => $Node, Files_path => "$src_file", Files => [@model_chnage] );
    @copied_firmwares = sort @copied_firmwares;
    my @common = intersection( [ sort @model_chnage ], [@copied_firmwares] );
    my @diff   = array_diff(   [ sort @common ],       [ sort @model_chnage ] );
    if ( !@copied_firmwares ) {
        logcomment("Firmware files which are NOT copied :: @diff ") if (@diff);
        return ( 3, $new_disk_fw_p );
    } else {
        logcomment("All necessary firmware files :: @common :: to /mroot/etc/disk_fw are copied");
    }
    logcomment("Deleting folder $src_file");
    system("sudo rm -rf $src_file");
    if ( -d "$src_file" ) {
        logcomment("Error occured during the deletion of the folder $src_file");
    }

    return ( 4, $new_disk_fw_p );    # passed
}

#----------------------------------------------------------------
# author : kiranp1
# Burt : 1134959
# checking for Proper Firmware revision numbers ( Should not contain Alphabets )
#
#----------------------------------------------------------------

sub check_disk_firmware_revision_number {
    my (%opts) = validate(
        @_,
        {
            Node             => { type => OBJECT },
            disk_fw_location => { type => SCALAR },
            timeout          => { type => SCALAR, default => 1200, optional => 1 },
        }
    );

    my $Home         = $ENV{HOME};
    my $Node         = $opts{Node};
    my $disk_fw_path = $opts{disk_fw_location};
    my $sudo         = "/usr/bin/sudo";
    my $Api_Set_Obj  = $Node->get_7m_or_nodescope_apiset();
    $Api_Set_Obj->set_timeout( 'connectrec-timeout' => 7200 );
    my $Mode          = $Node->mode();
    my $FILER_C       = $Node->name();
    my %new_disk_fw   = ();
    my $new_disk_fw_p = [];
    $new_disk_fw_p = \%new_disk_fw;
    my %model = ();
    my %rev   = ();
    my $ver   = $Api_Set_Obj->execute_raw_command( 'command' => "version" );
    my @disk_list;
    my @disk_fw;

    my $dir_flag         = 0;
    my @invalid_dir_firm = ();

    if ( defined $disk_fw_path ) {
        @disk_fw = `cd $opts{disk_fw_location};ls *.LOD`;
    } else {
        $disk_fw_path = "$Home/NDATE/FIRMWARE/DISKFW/HIGH";
        @disk_fw      = `cd $disk_fw_path;ls *.LOD`;
    }
    logcomment("Following Firmwares found in the directory $opts{disk_fw_location}:");
    logcomment("@disk_fw");

    if ( @disk_fw < 1 ) {
        logcomment("NO DISK FIRMWARE FILES are available");
        return ( 0, $new_disk_fw_p );
    }

    foreach my $firmware (@disk_fw) {
        my @temp = split( /\./, $firmware );
        my $dir_rev_no = substr( $temp[1], 2, 3 );
        if ( $dir_rev_no =~ /[A-Z]/ ) {
            $dir_flag = 1;
            chomp($firmware);
            my $msg = "**NORUN** : Firmware : $firmware : Revision is Invalid as it conatains Alphabets - $dir_rev_no";
            push( @invalid_dir_firm, $msg );
        }
    }

    if ( $dir_flag == 1 ) {
        grep { logcomment("$_") } @invalid_dir_firm;
        return ( 1, $new_disk_fw_p );
    }

    my @list_of_disk = list_of_disk( Node => $Node );
    foreach my $dsk (@list_of_disk) {
        if ( $dsk =~ /(P\d+)$/ ) {
            next;
        }
        push( @disk_list, $dsk );
    }

    my %sto_show_dsk = ();
    my %model_change = ();
    $sto_show_dsk{$Node} = storage_show_disk_a_data( Node => $Node );
    foreach my $disk (@disk_list) {
        my $mdl = $sto_show_dsk{$Node}->{$disk}->{'Model'};
        my $rvs = $sto_show_dsk{$Node}->{$disk}->{'Rev'};
        $model{$disk} = $mdl;
        $rev{$disk}   = $rvs;
    }
    my $flag_nt        = 0;
    my $flag_invalid   = 0;
    my @Invalid_rev_no = ();
    my @NT_fw_dsk      = ();
    foreach my $dsk (@disk_list) {
        my $model_name = $model{$dsk};
        my $rev_num    = $rev{$dsk};
        $model_name =~ s/^\s+|\s+$//g;
        my $fw = $model_name . "\.$rev_num" . "\.LOD";
        logcomment("DEBUG: Disk : $dsk ::: Model : $model_name ::: Rev No : $rev_num");
        if ( !( $new_disk_fw{$dsk} ) ) {
            $new_disk_fw{$dsk} = $fw;
            my $rev_alpha = substr( $rev_num, 0, 2 );
            my $ver_num   = substr( $rev_num, 2, 3 );
            if ( $ver_num =~ /[A-Z]/ ) {
                my $msg = "**NORUN** : Disk $dsk Firmware revision is invalid as it conatains Alphabets - $ver_num";
                push( @Invalid_rev_no, $msg );
                $flag_invalid = 1;    #NORUN if the revision number contains Alphabets
            } elsif ( $rev_alpha =~ /NT/ ) {
                my $msg = "**NORUN** : Disk $dsk Contains the NT revision number - $fw";
                push( @NT_fw_dsk, $msg );
                $flag_nt = 1;         # NORUN if the NT files are present.
            }
        }

    }

    if ( $flag_invalid == 1 ) {
        grep { logcomment("$_") } @Invalid_rev_no;
        return ( 2, $new_disk_fw_p );
    } elsif ( $flag_nt == 1 ) {
        grep { logcomment("$_") } @NT_fw_dsk;
        return ( 3, $new_disk_fw_p );
    } else {
        return ( 4, $new_disk_fw_p );    #Pass
    }
}

#####################################################################
## Setup OKM for FIPS testing
## Burt :
## Author : arunak
#####################################################################
sub setup_okm {
    my (%opts) = validate( @_, { NODES => { type => ARRAYREF }, } );
    my $Home   = $ENV{HOME};
    my @Nodes  = @{ $opts{NODES} };

    {
        logcomment("User had selected to execute test on FIPS drives, Setting up On-board Key Manager - OKM");
        logcomment("On-board Key manager needs certain inputs from user, Checking user enterd information before setting up OKM");
        my $dir2rd         = "$Home/NDATE/SUPPORT_FILES/";
        my $okm_file_found = 0;
        my @dir_file       = `ls $dir2rd`;
        my $key;
        foreach (@dir_file) {
            if ( $_ =~ /^OKM/ ) {
                logcomment("OKM configuration file exist, Proceeding with OKM setup");
                $okm_file_found = 1;
            }
        }
        if ( $okm_file_found == 1 ) {
            my $okm_pass;
            my $OKM_file    = "$Home/NDATE/SUPPORT_FILES/OKM";
            my $okm_details = `cat $OKM_file`;
            foreach my $line ( split /\n/, $okm_details ) {
                if ( $line =~ /^\#/ ) {
                    next;    # skip overall result report starting with a '#'.
                } elsif ( $line =~ /^OKM_PASS\=(.*)/ ) {
                    $okm_pass = $1;
                }
            }
            logcomment("OKM password entered by user - $okm_pass");
            logcomment("Setting up OKM");
            $key = $okm_pass;

            #using Server oobject
            my ( $data_key, $fips_key );
            foreach my $Node (@Nodes) {
                my $FILER_C = $Node->name();
                my $prompt_fw;
                my $ignore_strings = [ "MADIMM\\d+->", "DIMM\\d+->", "^T>" ];
                my $host           = Tharn::host($FILER_C);
                my $prompt_array   = $host->prompt_fw();
                my $prompts        = join( "|", @$prompt_array );
                $prompt_fw = "($prompts)";
                logcomment("DEBUG:This is the prompt regex: $prompt_fw");
                logcomment("Setting up On-board Key Manager on filer $FILER_C");
                my $Server = new Server( no_cli => 1 );
                $Server->set_execution_server( -Server => $FILER_C );
                $Server->console(
                    cmd                        => "security key-manager setup",
                    additional_prompts_timeout => 600,
                    ignore                     => $ignore_strings,
                    additional_prompts         => {
                        ".*onboard key management?.*"              => 'yes',
                        ".*enter the passphrase.*"                 => $key,
                        ".*re-enter the cluster-wide passphrase.*" => $key,
                        ".*Re-enter the cluster-wide passphrase.*" => $key,
                        ".*Enter the cluster-wide passphrase.*"    => $key,
                        ".* for onboard key management.*"          => $key,
                        ".*otherwise type \"exit\".*"              => $key,
                        "$FILER_C\>"                               => "FINAL_PROMPT",
                        "run not found"                            => "FINAL_PROMPT",
                        "$prompt_fw"                               => "FINAL_PROMPT",
                        "takeover"                                 => "FINAL_PROMPT",
                        "\.*\>"                                    => "FINAL_PROMPT",
                        "\>"                                       => "FINAL_PROMPT"
                    }
                );
                logcomment("Completed setting OKM key");
                my $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset( connid => "console" );
                $Api_Set_Obj->set_timeout( 'connectrec-timeout' => 7200 );
                $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
                logcomment("Display security key-manager ");
                my $prompts_answers = [ "Press  to page down,  for next line, or 'q' to quit.*" => ' ' ];
                $Api_Set_Obj->execute_raw_command( 'command' => "security key-manager backup show", 'connectrec-match_table' => $prompts_answers );
                $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
                logcomment("Display key manager");
                $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
                my $prompts_answers = [ "Press  to page down,  for next line, or 'q' to quit.*" => ' ' ];
                my $output = $Api_Set_Obj->execute_raw_command( 'command' => "security key-manager key show", 'connectrec-match_table' => $prompts_answers );
                my @enc_keys;

                #Netapp Storage Encryption - authentication key ( NSE-AK)
                foreach my $line ( split /\n/, $output ) {
                    if ( $line =~ /NSE\-AK/ ) {
                        my ($key) = $line =~ /(\S+)\s+\S+/;
                        push( @enc_keys, $key );
                    }
                }
                my @data_fips_keys = unique(@enc_keys);
                $data_key = $data_fips_keys[0];
                $fips_key = $data_fips_keys[1];
                logcomment("Security manger setup completed");
                logcomment("Configured data-key : $data_key");
                logcomment("Configured fips-key : $fips_key");
                logcomment("key manager setup done ");
            }    #end of foreach

            logcomment("Display Available disk");
            my $Node    = $Nodes[0];
            my $FILER_C = $Node->name();
            logcomment("Setting key on node - $FILER_C will configure on all drives");
            my $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset( connid => "console" );
            $Api_Set_Obj->set_timeout( 'connectrec-timeout' => 7200 );
            my $prompts_answers = [ "Press  to page down,  for next line, or 'q' to quit.*" => ' ' ];
            my $dsk_output = $Api_Set_Obj->execute_raw_command( 'command' => "disk show", 'connectrec-match_table' => $prompts_answers );
            my @all_drvs;

            foreach my $line ( split /\n/, $dsk_output ) {
                if ( ( $line =~ /^\d+/ ) && ( $line !~ /entries/ ) ) {
                    my ($dsk) = $line =~ /(\S+)\s+\S+/;
                    push( @all_drvs, $dsk );
                }
            }
            logcomment("Encryption keys will be enabled on @all_drvs drives");
            logcomment("Modify data encryption key for all drives with key - $data_key");
            logcomment("Modify FIPS encryption key for all drives with key - $fips_key");
            $Api_Set_Obj->execute_raw_command( 'command' => "storage encryption disk modify -data-key-id $data_key -disk * " );
            $Api_Set_Obj->execute_raw_command( 'command' => "storage encryption disk modify -fips-key-id $fips_key -disk * " );

            logcomment("Modified data and FIPS encryption keys on all drives");
            logcomment("Display disk encryption status");
            $Api_Set_Obj->execute_raw_command( 'command' => "storage encryption disk show-status" );
            logcomment("Display drives with data key");
            $Api_Set_Obj->execute_raw_command( 'command' => "storage encryption disk show" );
            logcomment("Display drive with FIPS key ");
            $Api_Set_Obj->execute_raw_command( 'command' => "storage encryption disk show -fips" );
            logcomment("Check for encryption status for the drives");
            $Api_Set_Obj->execute_raw_command( 'command' => "run local disk encrypt show" );
            logcomment("Completed enabling On-board key manager");
        } else {
            logcomment("OKM filer NOT found ");
        }
    }    #end of seperation
}

sub check_encry_okm_lock_state {
    my (%opts) = validate( @_, { Node => { type => OBJECT }, } );
    my $Home   = $ENV{HOME};
    my $Node   = $opts{Node};
    my $data_key;
    my $FILER_C = $Node->name();
    my $false   = 0;
    my $drv;
    logcomment("Check lock state for SED drives");
    my $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset( connid => "console" );
    $Api_Set_Obj->set_timeout( 'connectrec-timeout' => 7200 );
    my $output = $Api_Set_Obj->execute_raw_command( 'command' => "run local disk encrypt show" );

    foreach my $line ( split /\n/, $output ) {
        if ( $line =~ /\S+\s+\S+\s+(No)/i ) {
            logcomment("SED encrypt Lock state is \"No\" ");
            logcomment("$line");
            if ( $line =~ /^\d+/ ) {
                my ( $drive, $data_k ) = $line =~ /(\S+)\s+(\S+)/;
                $data_key = $data_k;
                $drv      = $drive;
                $false    = 1;
                logcomment("Drive - $drive with data key $data_key is unlocked");
                logcomment("**WARNING** : $FILER_C $drive with data key $data_key is unlocked");
            }
        }
    }
    if ( $false == 1 ) {
        logcomment("SED drive unlocked - $drv with data key $data_key is unlocked");
        logcomment("Modifying data-key to rest lock");
        $Api_Set_Obj->execute_raw_command( 'command' => "storage encryption disk modify * -data-key-id $data_key" );
        logcomment("Modified data key for all drives");
        logcomment("Check lock state for SED drives");
        my $out = $Api_Set_Obj->execute_raw_command( 'command' => "run local disk encrypt show" );
        foreach my $line ( split /\n/, $out ) {
            if ( $line =~ /\S+\s+\S+\s+(No)/i ) {
                logcomment("**WARNING** : SED Drives CANNOT be re-locked or modify ");
                return 1;
            }
        }
    } else {
        logcomment("All SED drive state is locked");
        return 0;
    }
}

#Burt 1033916  nmamatha
sub check_valid_platform {
    my (%opts) = validate(
        @_,
        {
            Node => { type => OBJECT },
            Test => { type => OBJECT },
        }
    );
    my $Node = $opts{Node};
    my $Test = $opts{Test};
    my $Transit_obj;
    my $prompt_fw;
    my $params = NATE::ParamSet->new( global => 1 );
    my $LOGDIR = $params->get( 'LOGDIR', default => undef );
    {
        my $FILER_C     = $Node->name();
        my $host        = Tharn::host($FILER_C);
        my $Transit_obj = NACL::Transit->new( name => $FILER_C );
        my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
        logcomment("Filer : $FILER_C is in $filer_state state");

        #Check for login prompt on filer, before proceeding and change to CLI
        if ( $filer_state =~ /LOADER|FIRMWARE/i ) {
            try {
                $Transit_obj->set( 'change_state_timeout' => 7200 );
                $Transit_obj->change_state( to => "MAINT" );
            }
            catch NACL::Transit::Exceptions::Timeout with {
                logcomment("Expected: Caught a Timeout Exception");
                my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
            };
            my $logfile = $LOGDIR . "/check_valid_platform_$FILER_C" . "\.log";

            #            open( FH, "$logfile" ) || logresult( 'FATAL', " Cannot open the file $logfile" );
            open( FH, "$logfile" ) || logresult( 'FATAL', " CANNOT OPEN THE FILE $logfile" );
            my $arr1 = ;
            close(FH);
            if ( ( $arr1 =~ /This platform is not supported in this release/ ) && ( $arr1 =~ /The system will now halt/ ) ) {
                logcomment("**FATAL**: The platform is NOT supported in the release ");
                logresult( 'FATAL', "THE PLATFORM IS NOT SUPPORTED IN THE RELEASE" );
            }
        }
        my $Transit_obj = NACL::Transit->new( name => $FILER_C );
        my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
        logcomment("Booting the filer to check the battery issue if filer is in Loader");
        if ( $filer_state =~ /LOADER|FIRMWARE/i ) {
            try {
                $Transit_obj->set( 'change_state_timeout' => 7200 );
                $Transit_obj->change_state( to => "MAINT" );
            }
            catch NACL::Transit::Exceptions::Timeout with {
                logcomment("Expected: Caught a Timeout Exception");
                my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
            };
        } elsif ( $filer_state =~ /MAINT/i ) {
            try {
                $Transit_obj->set( 'change_state_timeout' => 7200 );
                $Transit_obj->change_state( to => "FIRMWARE" );
                $Transit_obj->change_state( to => "MAINT" );
            }
            catch NACL::Transit::Exceptions::Timeout with {
                logcomment("Expected: Caught a timeout exception");
                my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
            };
        } else {
            logcomment("Check for battery health is NOT needed as filer is in CLI");
        }
        my $logfile = $LOGDIR . "/check_valid_platform_$FILER_C" . "\.log";
        open( FH, "$logfile" ) || logresult( 'FATAL', " CANNOT OPEN THE FILE $logfile" );
        my $arr2 = ;
        close(FH);
        if ( $arr2 =~ /WARNING:  The battery is unfit to retain data/ig ) {
            logcomment("**FATAL**: The battery is UNFIT to retain data, Please resolve the battery issue before booting");
            logresult( 'FATAL', "THE BATTERY IS UNFIT TO RETAIN DATA, Please resolve the battery issue before booting" );
        }
    }
}

sub difference($$) {
    my %e = map { $_ => undef } @{ $_[1] };
    return grep { ( exists $e{$_} ) ? ( delete $e{$_} ) : (1) } @{ $_[0] };    #@{[ ( @arr ), keys %e ] };
}

#####################################################################
## New Spare policy for Aggreagte creation
## Burt : 1005520
## Author : aditis
#####################################################################

sub create_aggr_vol {
    my (%opts) = validate(
        @_,
        {
            Node           => { type => OBJECT },
            disk_list      => { type => ARRAYREF },
            size           => { type => SCALAR, optional => 1, default => '90' },
            flag_disk_list => { type => SCALAR, optional => 0, default => 0 },
            test           => { type => SCALAR, optional => 1, default => undef },
            partition      => { type => SCALAR, optional => 1, default => 'no' },
            API_Obj        => { type => OBJECT, default => undef, optional => 1 },
            aggr_name      => { type => SCALAR, optional => 1, default => undef },
            diskcount      => { type => SCALAR, optional => 1, default => undef },
        }
    );

    my $Node = $opts{Node};
    my $API_Obj;
    $API_Obj = $opts{API_Obj} if ( defined $opts{API_Obj} );
    my $filer       = $Node->name();
    my $FILER_C     = $filer;
    my $test_name   = $opts{test};
    my @spares      = @{ $opts{disk_list} };
    my @spares_temp = @spares;
    my $diskcount;

    if ( defined $opts{diskcount} ) {
        $diskcount = $opts{diskcount};
    } else {
        if ( $parse_id =~ /_ERT_Fsys$/i ) {
            $diskcount = 3;
        }
    }
    my $flag_disk_list;
    $flag_disk_list = $opts{flag_disk_list} if ( defined $opts{flag_disk_list} );
    $flag_disk_list = 1                     if ( $test_name =~ /706/ );
    $flag_disk_list = 1                     if ( $parse_id =~ /_ERT_Fsys/i );
    my $sysconfig_out;
    my $model_name;
    my $shelf_id;
    my $system_id;
    my $partition = 0;
    my %size;
    my $BOAB_check = 0;
    my $stask_vol;
    my $aggr_size;
    my $vol_size;
    my $disk_show_v;
    my %hash;
    my @drives_use_7    = ();
    my @disk_show_disks = ();
    my $disk_show_s;
    my @disk_show          = ();
    my $flag_aggr_creation = 0;
    my @total_no_drives    = ();
    my @numbr_drives       = ();
    my $max_size;
    my $raid;
    my $i = 1;

    my $Transit_obj = NACL::Transit->new( name => $filer );
    my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    logcomment("DEBUG:Filer $filer is in state : $filer_state");
    if ( $filer_state =~ /CLI|UP/i ) {
        $API_Obj = $Node->get_7m_or_nodescope_apiset();
        $API_Obj->set_timeout( "connectrec-timeout" => 7200 );
    } elsif ( $filer_state =~ /MAINT/ ) {
        my $Host = host($filer);
        $API_Obj = NACL::APISet->new(
            hostobj   => $Host,
            category  => "Node",
            interface => "CLI",
            set       => "Maintenance",
        );
        $API_Obj->set_timeout( "connectrec-timeout" => 7200 );
    }

    if ( $filer_state =~ /CLI|UP/i ) {
        logcomment("Executing sysconfig -v for checking the filer configuration");
        $sysconfig_out = $API_Obj->execute_command( 'command' => 'sysconfig -v', 'timeout' => 600 );
        logcomment("Executing disk show -v for checking total number of drives present");
        $disk_show_v = $API_Obj->execute_command( 'command' => 'disk show -v' );
    } elsif ( $filer_state =~ /MAINT/ ) {
        logcomment("Executing sysconfig -v for checking the filer configuration");
        $sysconfig_out = $API_Obj->execute_raw_command( 'command' => 'sysconfig -v' );
        logcomment("Executing disk show -v for checking total number of drives present");
        $disk_show_v = $API_Obj->execute_raw_command( 'command' => 'disk show -v' );

    }
    my $flag_size = 0;
    my @size_gb   = ();
    my @size_tb   = ();
    chomp( my @sysconf_lines = split( /\r?\n/, $sysconfig_out ) );
    foreach my $line (@sysconf_lines) {
        if ( $line =~ /Model Name:\s+(\S+)/ig ) {
            $model_name = $1 unless ( defined $model_name );
        }
        if ( $line =~ /Shelf\s*\d*:\s*(\S+)\s+Firmware rev/ ) {
            $shelf_id = $1;
        }
        if ( $line =~ /\s*System ID:\s+(\d+)\s+/ ) {
            $system_id = $1;
        }
        if ( $line =~ /ID\s+Vendor\s+Model\s+FW\s+Size/ig ) { $flag_size = 1; }
        if ( ( $line =~ /(\d+\.\w+)\s*\:\s*\S+\s*(\S+)\s*(\S+)\s*(\S+)\s*/ ) && ( $flag_size == 1 ) ) {
            my $size = $4;
            if ( $size =~ /GB$/ ) {
                push( @size_gb, $size );
            } elsif ( $size =~ /TB$/ ) {
                push( @size_tb, $size );
            }
        }
    }
    if (@size_tb) {
        $max_size = max @size_tb;
    } else {
        $max_size = max @size_gb;
        $max_size =~ s/GB//g;
        if ( $max_size >= 1000 ) {
            $max_size = $max_size / 1000;
            $max_size = sprintf( "%.1f", $max_size );
            $max_size = $max_size . "TB";
        } else {
            $max_size = $max_size . "GB";
        }
    }
    logcomment("Maximum drive capacity with available drives is : $max_size");
    if ( $max_size =~ /\S+GB/ ) {
        $raid = "raid_dp";
    } else {
        if ( $max_size < 8 ) {
            $raid = "raid_dp";
        } else {
            $raid = "raid_tec";
        }
    }
    if ( $DRIVE_TYPE =~ /SSD$/ ) {
        $raid = "raid_dp";
    }
    if ( $flag_disk_list != 1 ) {

        my @lines = split( /\n/, $disk_show_v );
        my $n = 0;
        while ( $n <= $#lines ) {
            last if ( $lines[$n] =~ /^-----/ );
            $n++;
        }
        $n++;
        foreach my $line ( @lines[ $n .. $#lines ] ) {
            if ( $line =~ /(\S+)\s+\S+\s*\(\d+/ ) {

                my $disk = $1;
                push( @numbr_drives, $disk );
            }
        }
        grep {
            if ( $_ !~ /P\d+/i ) { push( @total_no_drives, $_ ) }
        } @numbr_drives;
        foreach (@numbr_drives) {
            if ( $_ =~ /P\d+$/ ) {
                $partition = 1;
                logcomment("Setup is partitioned");
                last;
            }
            if ( $_ =~ /\w+\.\w+\.\w+L\d+$/ ) {
                $BOAB_check = 1;
            }

        }
        $disk_show_s = $API_Obj->execute_command( 'command' => "disk show -s $system_id" );
        my @lines1 = split( /\r*\n/, $disk_show_s );
        shift(@lines1);
        foreach (@lines1) {
            s/^\s*//;
            if (/^(\w+\.\w+\.\w+)\s+\S+\s*\(/) {
                push( @disk_show_disks, $1 );
            } elsif (/^(\w+\.\w+\.\w+)\s*\(\S+\)\s*\S+/) {
                push( @disk_show_disks, $1 );
            }
        } ## end foreach (@lines)
        grep {
            if ( $_ !~ /P\d+/i ) { push( @disk_show, $_ ) }
        } @disk_show_disks;
        logcomment("Drive_type: $DRIVE_TYPE");
        if ( $DRIVE_TYPE =~ /SSD$/ ) {
            my $part_string;
            my $num_phy_drives;
            if ( $partition == 1 ) {
                $part_string    = "PARTITIONED";
                $num_phy_drives = 8;
            } else {
                $part_string    = "UNPARTITIONED";
                $num_phy_drives = 14;
            }
            logcomment("Setup is $part_string");
            logcomment( "Total number of physical disks present : " . scalar @total_no_drives );
            logcomment( "Total number of drives attached to node $FILER_C : " . scalar @disk_show );
            logcomment( "Total number of spares available on node $FILER_C : " . scalar @spares_temp );
            logcomment("Maximum drive capacity with available drives is : $max_size");
            if ( scalar @total_no_drives < $num_phy_drives ) {
                logcomment( "**NORUN** : Total number of physical drives present : " . scalar @total_no_drives . " which is LESS THAN the required count $num_phy_drives" );
                return $TCD::FAIL;
            }
        } else {
            if ( $shelf_id =~ /DS4486/i ) {
                logcomment("Platform: BOAB(shelf ID:$shelf_id) | Model:$model_name ");
                logcomment( "Total number of physical disks present : " . scalar @total_no_drives );
                logcomment( "Total number of drives attached to node $FILER_C : " . scalar @disk_show );
                logcomment( "Total number of spares available on node $FILER_C : " . scalar @spares_temp );
                logcomment("Maximum drive capacity with available drives is : $max_size");
                if ( scalar @total_no_drives < 48 ) {
                    logcomment( "**NORUN** : Platform: BOAB(shelf ID:$shelf_id) | model:$model_name -- Total number of physical drives present : " . scalar @total_no_drives . " which is less than the required count 48" );
                    return $TCD::FAIL;

                    #                $flag_aggr_creation = 1;
                }
            } elsif ( $shelf_id =~ /DS4246/i ) {
                logcomment("Platform: SEQUOIA(shelf ID:$shelf_id) | model:$model_name ");
                logcomment( "Total number of physical disks present : " . scalar @total_no_drives );
                logcomment( "Total number of drives attached to node $FILER_C : " . scalar @disk_show );
                logcomment( "Total number of spares available on node $FILER_C : " . scalar @spares_temp );
                logcomment("Maximum drive capacity with available drives is : $max_size");
                if ( scalar @total_no_drives < 24 ) {
                    logcomment( "**NORUN** : Platform: SEQUOIA(shelf ID:$shelf_id) | model:$model_name -- Total number of physical drives present : " . scalar @total_no_drives . " which is less than the required count 24" );
                    return $TCD::FAIL;

                    #                $flag_aggr_creation = 1;
                }
            } elsif ( $model_name =~ /FAS2554/i ) {
                logcomment("Platform: ALPINE(shelf ID:$shelf_id) | model:$model_name ");
                logcomment( "Total number of physical disks present : " . scalar @total_no_drives );
                logcomment( "Total number of drives attached to node $FILER_C : " . scalar @disk_show );
                logcomment( "Total number of spares available on node $FILER_C : " . scalar @spares_temp );
                logcomment("Maximum drive capacity with available drives is : $max_size");
                if ( scalar @total_no_drives < 24 ) {
                    logcomment( "**NORUN** : Platform: ALPINE(shelf ID:$shelf_id) | model:$model_name -- Total number of physical drives present : " . scalar @total_no_drives . " which is less than the required count 24" );
                    return $TCD::FAIL;

                    #                $flag_aggr_creation = 1;
                }
            } elsif ( $model_name =~ /FAS2552/i ) {
                logcomment("Platform: TIOYA(shelf ID:$shelf_id) | model:$model_name");
                logcomment( "Total number of physical disks present : " . scalar @total_no_drives );
                logcomment( "Total number of drives attached to node $FILER_C : " . scalar @disk_show );
                logcomment( "Total number of spares available on node $FILER_C : " . scalar @spares_temp );
                logcomment("Maximum drive capacity with available drives is : $max_size");
                if ( scalar @total_no_drives < 24 ) {
                    logcomment( "**NORUN** : Platform: TIOYA(shelf ID:$shelf_id) | model:$model_name -- Total number of physical drives present : " . scalar @total_no_drives . " which is less than the required count 24" );
                    return $TCD::FAIL;

                    #                $flag_aggr_creation = 1;
                }
            } elsif ( $model_name =~ /FAS2520/i ) {
                logcomment("Platform: TENAYA(shelf ID:$shelf_id) | model:$model_name");
                logcomment( "Total number of physical disks present : " . scalar @total_no_drives );
                logcomment( "Total number of drives attached to node $FILER_C : " . scalar @disk_show );
                logcomment( "Total number of spares available on node $FILER_C : " . scalar @spares_temp );
                logcomment("Maximum drive capacity with available drives is : $max_size");
                if ( scalar @total_no_drives < 12 ) {
                    logcomment( "**NORUN** : Platform: TENAYA(shelf ID:$shelf_id) | model:$model_name -- Total number of physical drives present : " . scalar @total_no_drives . " which is less than the required count 12" );
                    return $TCD::FAIL;

                    #                $flag_aggr_creation = 1;
                }
            } elsif ( ( $shelf_id =~ /DS212-12/i ) && ( $model_name =~ /FAS2620/i ) ) {
                logcomment("Platform: RAZOR-MJ(shelf ID:$shelf_id) | model:$model_name");
                logcomment( "Total number of physical disks present : " . scalar @total_no_drives );
                logcomment( "Total number of drives attached to node $FILER_C : " . scalar @disk_show );
                logcomment( "Total number of spares available on node $FILER_C : " . scalar @spares_temp );
                logcomment("Maximum drive capacity with available drives is : $max_size");
                if ( scalar @total_no_drives < 12 ) {
                    logcomment( "**NORUN** : Platform: RAZOR-MJ(shelf ID:$shelf_id) | model:$model_name -- Total number of physical drives present : " . scalar @total_no_drives . " which is less than the required count 12" );
                    return $TCD::FAIL;
                }
            } elsif ( $shelf_id =~ /DS2246/i ) {
                logcomment("Platform: HACKBERRY(shelf ID:$shelf_id) | model:$model_name");
                logcomment( "Total number of physical disks present : " . scalar @total_no_drives );
                logcomment( "Total number of drives attached to node $FILER_C : " . scalar @disk_show );
                logcomment( "Total number of spares available on node $FILER_C : " . scalar @spares_temp );
                logcomment("Maximum drive capacity with available drives is : $max_size");
                if ( scalar @total_no_drives < 24 ) {
                    logcomment( "**NORUN** : PLATFORM: HACKBERRY(SHELF ID:$shelf_id) | MODEL:$model_name -- Total number of physical drives present : " . scalar @total_no_drives . " which is less than the required count 24" );
                    return $TCD::FAIL;

                    #                $flag_aggr_creation = 1;
                }
            } elsif ( ( $shelf_id =~ /DS212-12/i ) && ( $model_name !~ /FAS2620/i ) ) {
                logcomment("Platform: JOSHUA(shelf ID:$shelf_id) | model:$model_name");
                logcomment( "Total number of physical disks present : " . scalar @total_no_drives );
                logcomment( "Total number of drives attached to node $FILER_C : " . scalar @disk_show );
                logcomment( "Total number of spares available on node $FILER_C : " . scalar @spares_temp );
                logcomment("Maximum drive capacity with available drives is : $max_size");
                if ( scalar @total_no_drives < 24 ) {
                    logcomment( "**NORUN** : Platform: JOSHUA(shelf ID:$shelf_id) | model:$model_name -- Total number of physical drives present : " . scalar @total_no_drives . " which is less than the required count 24" );
                    return $TCD::FAIL;
                }
            } elsif ( $shelf_id =~ /DS224-12/i ) {
                logcomment("PLATFORM: ALDER(shelf ID:$shelf_id) | model:$model_name");
                logcomment( "Total number of physical disks present : " . scalar @total_no_drives );
                logcomment( "Total number of drives attached to node $FILER_C : " . scalar @disk_show );
                logcomment( "Total number of spares available on node $FILER_C : " . scalar @spares_temp );
                logcomment("Maximum drive capacity with available drives is : $max_size");
                if ( scalar @total_no_drives < 24 ) {
                    logcomment( "**NORUN** : Platform: ALDER(shelf ID:$shelf_id) | model:$model_name -- Total number of physical drives present : " . scalar @total_no_drives . " which is less than the required count 24" );
                    return $TCD::FAIL;

                    #    $flag_aggr_creation = 1;
                }
            } elsif ( $shelf_id =~ /DS46012/i ) {
                logcomment("Platform: TRAFFORD(shelf ID:$shelf_id) | model:$model_name");
                logcomment( "Total number of physical disks present : " . scalar @total_no_drives );
                logcomment( "Total number of drives attached to node $FILER_C : " . scalar @disk_show );
                logcomment( "Total number of spares available on node $FILER_C : " . scalar @spares_temp );
                logcomment("Maximum drive capacity with available drives is : $max_size");
                if ( scalar @total_no_drives < 60 ) {
                    logcomment( "**NORUN** : Platform: TRAFFORD(shelf ID:$shelf_id) | model:$model_name -- Total number of physical drives present : " . scalar @total_no_drives . " which is less than the required count 60" );
                    return $TCD::FAIL;
                }
            } else {
                logcomment("Platform: shelf ID:$shelf_id | model:$model_name");
                logcomment( "Total number of physical disks present : " . scalar @total_no_drives );
                logcomment( "Total number of drives attached to node $FILER_C : " . scalar @disk_show );
                logcomment( "Total number of spares available on node $FILER_C : " . scalar @spares_temp );
                logcomment("Maximum drive capacity with available drives is : $max_size");
                $flag_aggr_creation = 1;
            }
        }
    }
    while (@spares_temp) {
        @drives_use_7 = ();
        my @non_root_volumes = ();
        @non_root_volumes = check_non_root_volumes( Node => $Node );
        logcomment("Non root volumes are already present: @non_root_volumes, NOT proceeding for creating non-root aggregate") if ( scalar @non_root_volumes >= 2 );
        if ( $DRIVE_TYPE =~ /SSD$/i ) {
            last if ( scalar @non_root_volumes >= 1 );
        } else {
            if ( $partition == 1 ) {
                if ( ( $shelf_id =~ /DS4246/i ) || ( $model_name =~ /FAS2554/i ) || ( $model_name =~ /FAS2552/i ) || ( $shelf_id =~ /DS2246/i ) || ( $shelf_id =~ /DS224-12/i ) ) {
                    last if ( scalar @non_root_volumes >= 2 );
                } else {
                    last if ( scalar @non_root_volumes >= 1 );
                }
            } else {
                if ( $shelf_id =~ /DS46012/i ) {
                    last if ( scalar @non_root_volumes >= 2 );
                } elsif ( ( scalar @non_root_volumes >= $ERT_VOL ) && ( $parse_id =~ /_ERT_Fsys/i ) ) {
                    last;
                } else {
                    last if ( ( scalar @non_root_volumes >= 1 ) && ( $parse_id !~ /_ERT_Fsys/i ) );
                }
            }
        }
        if ( $flag_disk_list == 1 ) {
            @spares_temp = shuffle_array( \@spares_temp );
            if ( $test_name =~ /706/ ) {
                @drives_use_7 = splice( @spares_temp, 0, 7 );
            } else {
                @drives_use_7 = @spares_temp;
            }
            logcomment("Using random drives : @drives_use_7 to create aggregate");
        } else {
            my $disk_max_sup;
            if ( $BOAB_check == 1 ) {
                $disk_max_sup = 20;
            } else {
                $disk_max_sup = 13;
            }
            my $temp_disk;
            my $loop_no  = 0;
            my @spares_t = ();
            while ( $loop_no < $disk_max_sup ) {
                $temp_disk = pop(@spares_temp);
                push( @spares_t, $temp_disk );
                $loop_no++;
                last if ( !(@spares_temp) );
            }
            @spares_t = shuffle_array( \@spares_t );
            logcomment("Using random drives : @spares_t to create aggregate");
            my @boab_arr_disk = ();
            if ( $BOAB_check == 1 ) {
                my %sata;
                foreach my $dsk (@spares_t) {
                    if ( $dsk =~ /((\d+\.\d+\.\d+)\.\d+)/ ) {
                        push( @{ $sata{$2} }, $1 );
                    }
                }
                foreach my $key ( keys %sata ) {
                    my @arr = @{ $sata{$key} };
                    if ( scalar @arr > 1 ) {
                        push( @boab_arr_disk, $arr[0] );
                    } else {
                        push( @boab_arr_disk, @arr );
                    }
                }
                @boab_arr_disk = shuffle_array( \@boab_arr_disk );
                logcomment("Using random drives : @boab_arr_disk to create aggregate");
            }
            if ( $flag_aggr_creation == 1 ) {
                if ( $BOAB_check == 1 ) {
                    @drives_use_7 = splice( @boab_arr_disk, 0, 7 );    # Burt1024377
                    logcomment("Platform: BOAB(shelf ID:$shelf_id) | model:$model_name | total_aggregate_count : 1 | drive_used_in_aggregate : 7");
                    logcomment( "Spares using to create aggregate are : " . scalar @drives_use_7 . " and the spares are @drives_use_7" );
                } else {
                    @drives_use_7 = @spares_t;
                    logcomment( "Platform: shelf ID:$shelf_id | model name:$model_name | drive_used_in_aggregate : " . scalar @drives_use_7 );
                    logcomment( "Spares using to create aggregate are : " . scalar @drives_use_7 . " and the spares are @drives_use_7" );
                }

            } elsif ( $DRIVE_TYPE =~ /SSD$/i ) {
                if ( $partition == 1 ) {
                    @drives_use_7 = splice( @spares_t, 0, 6 );
                    logcomment( "drive_type - $DRIVE_TYPE | partitioned | total_aggregate_count : 1 | drive_used_in_aggregate : " . scalar @drives_use_7 );
                } else {
                    @drives_use_7 = splice( @spares_t, 0, 5 );
                    logcomment( "drive_type - $DRIVE_TYPE | unpartitioned | total_aggregate_count : 1 | drive_used_in_aggregate : " . scalar @drives_use_7 );
                }
            } else {
                if ( $shelf_id =~ /DS4486/i ) {
                    @drives_use_7 = splice( @boab_arr_disk, 0, 12 );
                    logcomment( "PLATFORM: BOAB(shelf ID: $shelf_id) | model:$model_name | total_aggregate_count : 1 | drive_used_in_aggregate : " . scalar @drives_use_7 );
                    logcomment( "Spares using to create aggregate are : " . scalar @drives_use_7 . " and the spares are @drives_use_7" );
                } elsif ( $shelf_id =~ /DS4246/i ) {
                    if ( $partition == 1 ) {
                        @drives_use_7 = splice( @spares_t, 0, 10 );
                        logcomment( "PARTITIONED:: PLATFORM: SEQUOIA(SHELF ID:$shelf_id) | MODEL:$model_name | TOTAL_AGGREGATE_COUNT : 2 | DRIVE_USED_IN_AGGREGATE : " . scalar @drives_use_7 );
                    } else {
                        if ( $max_size =~ /\S+GB/ ) {
                            @drives_use_7 = splice( @spares_t, 0, 6 );
                        } else {
                            if ( $max_size >= 8 ) {
                                logcomment("Maximum drive capacity is greater than or equal to 8TB");
                                @drives_use_7 = splice( @spares_t, 0, 7 );
                            } else {
                                @drives_use_7 = splice( @spares_t, 0, 6 );
                            }
                        }
                        logcomment( "Platform: SEQUOIA(shelf ID:$shelf_id) | model:$model_name | total_aggregate_count : 1 | drive_used_in_aggregate : " . scalar @drives_use_7 );
                    }
                    logcomment( "Spares using to create aggregate are : " . scalar @drives_use_7 . " and the spares are @drives_use_7" );
                } elsif ( $model_name =~ /FAS2554/i ) {
                    if ( $partition == 1 ) {
                        @drives_use_7 = splice( @spares_t, 0, 10 );
                        logcomment( "Partitioned:: platform: ALPINE(shelf ID:$shelf_id) | model name:$model_name | total_aggregate_count : 2 | drive_used_in_aggregate : " . scalar @drives_use_7 );
                    } else {
                        if ( $max_size =~ /\S+GB/ ) {
                            @drives_use_7 = splice( @spares_t, 0, 6 );
                        } else {
                            if ( $max_size >= 8 ) {
                                logcomment("Maximum drive capacity is greater than or equal to 8TB");
                                @drives_use_7 = splice( @spares_t, 0, 7 );
                            } else {
                                @drives_use_7 = splice( @spares_t, 0, 6 );
                            }
                        }
                        logcomment( "Platform: ALPINE(shelf ID:$shelf_id) | model name:$model_name | total_aggregate_count : 1 | drive_used_in_aggregate : " . scalar @drives_use_7 );
                    }
                    logcomment( "Spares using to create aggregate are : " . scalar @drives_use_7 . " and the spares are @drives_use_7" );
                } elsif ( $model_name =~ /FAS2552/i ) {
                    if ( $partition == 1 ) {
                        @drives_use_7 = splice( @spares_t, 0, 10 );
                        logcomment( "Partitioned:: PLATFORM: TIOYA(shelf ID:$shelf_id) | model name:$model_name | total_aggregate_count : 2 | drive_used_in_aggregate : " . scalar @drives_use_7 );
                    } else {
                        if ( $max_size =~ /\S+GB/ ) {
                            @drives_use_7 = splice( @spares_t, 0, 6 );
                        } else {
                            if ( $max_size >= 8 ) {
                                logcomment("Maximum drive capacity is greater than or equal to 8TB");
                                @drives_use_7 = splice( @spares_t, 0, 7 );
                            } else {
                                @drives_use_7 = splice( @spares_t, 0, 6 );
                            }
                        }
                        logcomment( "Platform: TIOYA(shelf ID:$shelf_id) | model name:$model_name | total_aggregate_count : 1 | drive_used_in_aggregate : " . scalar @drives_use_7 );
                    }
                    logcomment( "Spares using to create aggregate are : " . scalar @drives_use_7 . " and the spares are @drives_use_7" );
                } elsif ( $model_name =~ /FAS2520/i ) {
                    if ( $DRIVE_TYPE =~ /SSD$/i ) {
                        @drives_use_7 = splice( @spares_t, 0, 6 );
                    } else {
                        @drives_use_7 = splice( @spares_t, 0, 5 );
                    }
                    logcomment( "Partitioned:: platform: TENAYA(shelf ID:$shelf_id) | model name:$model_name | total_aggregate_count : 1 | drive_used_in_aggregate : " . scalar @drives_use_7 );
                    logcomment( "Spares using to create aggregate are : " . scalar @drives_use_7 . " and the spares are @drives_use_7" );
                } elsif ( ( $shelf_id =~ /DS212-12/i ) && ( $model_name !~ /FAS2620/i ) ) {
                    if ( $partition == 1 ) {
                        @drives_use_7 = splice( @spares_t, 0, 10 );
                        logcomment( "Partitioned:: platform: JOSHUA(shelf ID:$shelf_id) | model NAME:$model_name | total_aggregate_count : 1 | drive_used_in_aggregate : " . scalar @drives_use_7 );
                    } else {
                        if ( $max_size =~ /\S+GB/ ) {
                            @drives_use_7 = splice( @spares_t, 0, 6 );
                        } else {
                            if ( $max_size >= 8 ) {
                                logcomment("Maximum drive capacity is greater than or equal to 8TB");
                                @drives_use_7 = splice( @spares_t, 0, 7 );
                            } else {
                                @drives_use_7 = splice( @spares_t, 0, 6 );
                            }
                        }
                        logcomment( "Platform: JOSHUA(shelf ID:$shelf_id) | model name:$model_name | total_aggregate_count : 1 | drive_used_in_aggregate : " . scalar @drives_use_7 );
                    }
                    my $dsks = _print_array( \@drives_use_7 );
                    logcomment( "Spares using to create aggregate are : " . scalar @drives_use_7 . " and the spares are:\n" . $dsks );
                } elsif ( ( $shelf_id =~ /DS212-12/i ) && ( $model_name =~ /FAS2620/i ) ) {
                    if ( $partition == 1 ) {
                        @drives_use_7 = splice( @spares_t, 0, 6 );
                        logcomment( "Partitioned:: PLATFORM: RAZOR-MJ(shelf ID:$shelf_id) | model name:$model_name | total_aggregate_count : 1 | drive_used_in_aggregate : " . scalar @drives_use_7 );
                    }
                } elsif ( $shelf_id =~ /DS2246/i ) {
                    if ( $partition == 1 ) {
                        @drives_use_7 = splice( @spares_t, 0, 10 );
                        logcomment( "Partitioned:: PLATFORM: HACKBERRY(shelf ID:$shelf_id) | model name:$model_name | total_aggregate_count : 2 | drive_used_in_aggregate : " . scalar @drives_use_7 );
                    } else {
                        if ( $max_size =~ /\S+GB/ ) {
                            @drives_use_7 = splice( @spares_t, 0, 6 );
                        } else {
                            if ( $max_size >= 8 ) {
                                logcomment("Maximum drive capacity is greater than or equal to 8TB");
                                @drives_use_7 = splice( @spares_t, 0, 7 );
                            } else {
                                @drives_use_7 = splice( @spares_t, 0, 6 );
                            }
                        }
                        logcomment( "Platform: HACKBERRY(shelf ID:$shelf_id) | model name:$model_name | total_aggregate_count : 1 | drive_used_in_aggregate : " . scalar @drives_use_7 );
                    }
                    my $dsks = _print_array( \@drives_use_7 );
                    logcomment( "Spares using to create aggregate are : " . scalar @drives_use_7 . " and the spares are:\n" . $dsks );
                } elsif ( $shelf_id =~ /DS224-12/i ) {
                    if ( $partition == 1 ) {
                        @drives_use_7 = splice( @spares_t, 0, 10 );
                        logcomment( "Partitioned:: PLATFORM: ALDER(shelf ID:$shelf_id) | model name:$model_name | total_aggregate_count : 2 | drive_used_in_aggregate : " . scalar @drives_use_7 );
                    } else {
                        if ( $max_size =~ /\S+GB/ ) {
                            @drives_use_7 = splice( @spares_t, 0, 6 );
                        } else {
                            if ( $max_size >= 8 ) {
                                logcomment("Maximum drive capacity is greater than or equal to 8TB");
                                @drives_use_7 = splice( @spares_t, 0, 7 );
                            } else {
                                @drives_use_7 = splice( @spares_t, 0, 6 );
                            }
                        }
                        logcomment( "Platform: ALDER(shelf ID:$shelf_id) | model name:$model_name | total_aggregate_count : 1 | drive_used_in_aggregate : " . scalar @drives_use_7 );
                    }
                    my $dsks = _print_array( \@drives_use_7 );
                    logcomment( "Spares using to create aggregate are : " . scalar @drives_use_7 . " and the spares are:\n" . $dsks );
                } elsif ( $shelf_id =~ /DS46012/i ) {
                    @drives_use_7 = splice( @spares_t, 0, 12 );
                    logcomment( "Platform: TRAFFORD(shelf ID:$shelf_id) | model name:$model_name | total_aggregate_count : 2 | drive_used_in_aggregate : " . scalar @drives_use_7 );
                    my $dsks = _print_array( \@drives_use_7 );
                    logcomment( "Spares using to create aggregate are : " . scalar @drives_use_7 . " and the spares are:\n" . $dsks );
                }
            }
        }
        if ( $opts{partition} =~ /yes/i ) {
            %hash = ( partitionlist => [@drives_use_7] );
        } else {
            %hash = ( disklist => \@drives_use_7, node => $filer );
        }
        my $num = 0;
        my $vserver_name;
        my $append_name = $filer;
        if ( $filer =~ /\-/ ) {
            $append_name =~ s/\-/_/g;
        }
        my @temp;
        my $agg = "aggr_" . "$append_name" . "_1";
        my $job;
        my @aggrs = NACL::C::Aggregate->find( command_interface => $Node, filter => { nodes => [$filer] } );
        my ( @aggr_names, $num_aggr, @n_aggr, %num_obj );

        foreach my $aggr (@aggrs) {
            my $ag = $aggr->get_one_state_attribute('aggregate');
            push( @aggr_names, $ag );
            if ( $ag =~ /(\d+)$/g ) {
                push( @n_aggr, $1 );
                $num_obj{$1} = $aggr;
            }
        }
        @n_aggr = sort { $a <=> $b } @n_aggr;
        my $aggr_obj;
        $num_aggr = $n_aggr[-1];    ##the value will have maximum digit value
        logcomment("Current max suffix value of aggregates : $num_aggr");
        $aggr_obj = $num_obj{$num_aggr};
        logcomment( "$filer : Total number of aggregates present in the system are " . scalar @aggr_names . " and the aggregates are @aggr_names" );
        $AGGR_CNT->{$filer} = scalar @aggr_names;

        my ( @vol_names, $num_vol );
        my @vol = NACL::C::Volume->find( command_interface => $Node, filter => { node => $filer } );
        foreach my $vols (@vol) {
            my $vg = $vols->get_one_state_attribute('volume');
            push( @vol_names, $vg );
            if ( $vg =~ /(\d+)$/g ) {
                if ( $num_vol < $1 ) {
                    $num_vol = $1;
                }
            }
        }
        logcomment( "$filer : Total number of volumes present in the system are " . scalar @vol_names . " and the volumes are @vol_names" );
        my $vol_flag       = 0;
        my $other_vol_flag = 0;
        if ( defined $aggr_obj ) {
            my $agg_test = $aggr_obj->get_one_state_attribute('aggregate');
            logcomment("DEBUG:Finding the number of volumes present in the aggregate $agg_test");
            my @aggr_obj;
            try {
                @aggr_obj = $aggr_obj->get_volumes();
            }
            catch NATE::BaseException with {
                logcomment("NO VOLUMES found in the aggregate $agg_test");
                $vol_flag = 1;
            };
            foreach my $vol_obj (@aggr_obj) {
                my $vol_test = $vol_obj->get_one_state_attribute('volume');
                logcomment("Volume present on the aggregate $agg_test are : $vol_test");
                $vol_test =~ s/^\s+|\s+$//g;
                if ( $vol_test =~ /volvs/i ) {
                    logcomment("$filer : Vsever volume volvs found on the aggregate $agg_test");
                    $vol_flag = 1;
                } elsif ( $vol_test =~ /vol0/i ) {
                    logcomment("$filer : Root volume found on the aggregate $agg_test");
                    $other_vol_flag = 1;
                } else {
                    logcomment("$filer : Volume found with the name $vol_test on the aggregate $agg_test ");
                    $other_vol_flag = 1;
                }
            }
        }
        my $aggr_ret_flag = 0;

        # $num = $num_aggr;
        $num = $num_aggr + 1;
        logcomment("DEBUG:the number will get appended is to the aggregate name is : $num ") if ( !defined $opts{aggr_name} );
        try {
            if ( defined $opts{aggr_name} ) {
                $agg = "aggr_" . "$append_name" . "_" . $opts{aggr_name};
            } else {
                $agg = "aggr_" . "$append_name" . "_" . "$num";
            }
            if ( $test_name =~ /308|309/ ) {
                logcomment("Creating aggregate of name $agg");
                my $stask_aggr_obj = NACL::STask::Aggregate->create(
                    command_interface => $Node,
                    aggregate         => $agg,

                    #diskcount         => '7',
                    nacltask_if_exists => 'reuse',
                    nacltask_wait      => '1',
                    job_component      => \$job,
                    polling_interval   => '600',
                    raidtype           => $raid,
                    %hash,
                );
            } elsif ( $test_name =~ /706/ ) {
                logcomment("Creating aggregate of name $agg");
                my $stask_aggr_obj = NACL::STask::Aggregate->create(
                    command_interface => $Node,
                    aggregate         => $agg,

                    #                    diskcount          => '7',
                    nacltask_if_exists => 'reuse',
                    nacltask_wait      => '1',
                    job_component      => \$job,
                    polling_interval   => '600',
                    raidtype           => $raid,
                    %hash,

                    #                    node               => $filer,
                );
            } elsif ( $model_name =~ /FAS2520/i ) {
                my $stask_aggr_obj = NACL::STask::Aggregate->create(
                    command_interface  => $Node,
                    aggregate          => $agg,
                    nacltask_if_exists => 'reuse',
                    nacltask_wait      => '1',
                    job_component      => \$job,
                    polling_interval   => '600',
                    %hash,
                );
            } elsif ( $parse_id =~ /_ERT_Fsys/i ) {
                logcomment("Volume creation count $i");
                my $stask_aggr_obj = NACL::STask::Aggregate->create(
                    command_interface  => $Node,
                    aggregate          => $agg,
                    diskcount          => $diskcount,
                    nacltask_if_exists => 'reuse',
                    nacltask_wait      => '1',
                    job_component      => \$job,
                    polling_interval   => '600',
                    raidtype           => $raid,
                    node               => $filer,
                );
                $i++;
            } else {
                my $stask_aggr_obj = NACL::STask::Aggregate->create(
                    command_interface  => $Node,
                    aggregate          => $agg,
                    nacltask_if_exists => 'reuse',
                    nacltask_wait      => '1',
                    job_component      => \$job,
                    polling_interval   => '600',
                    raidtype           => $raid,
                    %hash,
                );

                #'allow-mixed-rpm'  =>'true',
            }
        }
        catch NACL::APISet::Exceptions::CommandFailedException with {
            logcomment("**WARNING** :: $filer : Script tries to create aggregate $agg , but FAILED");
            $aggr_ret_flag = 1;
        };
        if ( $aggr_ret_flag == 1 ) {
            logcomment("**WARNING** : $filer : Could NOT create aggregate $agg");
            return undef;
        }
        my $skip = 0;
        {
            my $root      = "volvs";
            my $aggr_v    = "$agg";
            my $ns        = "file";
            my $sec       = "mixed";
            my $vser_flag = 0;
            $vserver_name = "vser_$filer";
            try {
                my $name = NACL::STask::Vserver->find(
                    command_interface => $Node,
                    filter            => { vserver => $vserver_name },
                );
                if ( $name->get_one_state_attribute("vserver") =~ /^($vserver_name)$/ ) {
                    my $vol = $name->get_one_state_attribute("rootvolume");
                    logcomment("Vserver root volume is $vol");
                    $vol =~ s/^\s+$//;
                    if ( ( $vol =~ /^\-$/g ) || ( !$vol ) ) {
                        logcomment("For vserver : $vserver_name : NO VOLUME is there");
                        logcomment("Deleting the vserver $vserver_name");
                        $name->purge();    #deleting the Vserver if no volume present for the Vserver
                        $vser_flag = 1;
                    }
                }
            }
            catch NACL::Exceptions::NoElementsFound with {
                logcomment("NO VSERVER found with the name $vserver_name");
                $vser_flag = 1;
            };
            if ( $vser_flag == 1 ) {

                try {
                    my $vserver_obj = NACL::STask::Vserver->create(
                        command_interface           => $Node,
                        vserver                     => $vserver_name,
                        nacltask_if_exists          => 'reuse',
                        rootvolume                  => $root,
                        aggregate                   => $aggr_v,
                        "ns-switch"                 => $ns,
                        "rootvolume-security-style" => $sec
                    );
                }
                catch NACL::APISet::Exceptions::CommandFailedException with {
                    logcomment("**WARNING** : Could NOT create vserver $vserver_name, returning from the subroutine");
                    $skip = 1;
                };

            }
        }
        return undef if ($skip);

        #___---___---___---____---___---____---____---______---____---_____---____---______

        ##Calculating the aggregate size and calculating the volume size to create on the aggregate based on the user input
        my @aggrs = NACL::C::Aggregate->find( command_interface => $Node, );
        foreach my $aggr (@aggrs) {
            my $name = $aggr->aggregate();
            if ( $name eq $agg ) {
                $aggr_size = $aggr->get_one_state_attribute('availsize');

                #logcomment("Initial aggregate size $aggr_size bytes");
                $aggr_size = int( $aggr_size / ( 1024 * 1024 ) );
                my ($readable_size) = readable_disk_size( MB => $aggr_size );
                logcomment("Total size of aggregate $agg is $readable_size");
            }
        }
        if ( $aggr_size == 0 ) {
            logcomment("**WARNING** : Total size of aggregate : $agg : is zero , so CANNOT create volumes on this aggregate");
            return;
        }
        my $vol_size = 90;
        {
            if ( ($vol_size) > 100 ) {
                logcomment("Size of Volume cannot be created more than the Aggregate size so making the size of volume equal to 100% of Aggreagte");
                $vol_size = 100;
            }
            my $required_size = int( ( $vol_size / 100 ) * $aggr_size );
            if ( $required_size > 50000000 ) {
                logcomment("Volume size is coming more than 50TB, so restricting the volume size to 50TB");
                $required_size = '50000000';
            }
            my ($readable_vol_size) = readable_disk_size( MB => $required_size );
            logcomment("Size of volume which will get created on aggregate $agg is $readable_vol_size");
            $required_size = $required_size . "m";    ##treating in MB's
            %size = ( size => $required_size );
        }

        my $vol_name;
        if ( defined $opts{aggr_name} ) {
            $vol_name = "vol_" . "$append_name" . "_" . $opts{aggr_name};
        } else {
            $vol_name = "vol_" . "$append_name" . "_" . "$num";
        }
        $stask_vol = NACL::STask::Volume->create(
            command_interface  => $Node,
            vserver            => $vserver_name,
            volume             => $vol_name,
            nacltask_if_exists => 'reuse',
            nacltask_wait      => '1',
            aggregate          => $agg,
            if_exists          => "reuse",
            %size,
        );
        logcomment("DEBUG:Checking volume status");
        $API_Obj->execute_command( 'command' => "vol status" );
        logcomment("DEBUG:Checking aggregate status");
        my $result = $API_Obj->execute_command( 'command' => "aggr status" );
    }
}
#####################################################################
## disk_assign_partition : assigning 1st 2 partitioned drive, node each i.e., P1 to N1 and P2 to N2
## review link https://reviewboard.netapp.com/r/414077/diff/#
## Burt : NA
## Author : nmamatha
## INPUT : \@Nodes (which contains NODES OBJs) and should not execute on the SUBTEST.
## OUTOUT : hashref -> filer with partitioned and drives attached to the filer ($hash->$filer->$partition->$drives / 1 => unpatitioned drives
#################################################################################################

sub disk_assign_partition {
    my (%opts) = validate( @_, { Node => { type => ARRAYREF }, } );
    my @Nodes = @{ $opts{Node} };
    my $partition = 0;
    my %fil_owner = ();
    my $check     = 1;
    my $FILERB;
    my @parti = ();
    my $API_OBJ;

    # check 1 --> checking for the System is Partition or not
    my $disk_hash = disk_show_v( Node => $Nodes[0] );
    foreach my $dsk ( keys %{$disk_hash} ) {
        my $owner = $disk_hash->{$dsk}->{'OWNER'};
        if ( $dsk =~ /(P(\d+))$/ ) {
            $partition = 1;
            push( @parti,                      $2 );
            push( @{ $fil_owner{$owner}{$1} }, $dsk );
        }
    }
    @parti = sort( unique(@parti) );
    if ( $partition == 1 ) {
        logcomment("System is Partitioned and Available Partitions are @parti ");
    } else {
        logcomment("System is Unpartioned");
        return 1;
    }
    my @drives_assign = ();
    if ( $partition == 1 ) {
        foreach my $Node (@Nodes) {
            my $FILER_C     = $Node->name();
            my $Transit_obj = NACL::Transit->new( name => $FILER_C );
            my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );

            # check 2 --> Check all P1 and P2 are assigned to NodeA and NodeB . i.e P1 should be assigned to NodeA and P2 should be assigned to NodeB.
            $FILERB = $Nodes[1]->name() if ( $check == 1 );
            if ( $filer_state =~ /CLI/ ) {
                my %fil_owner = ();
                try {
                    my @disk_list = ();
                    my @disk_obj  = NACL::CS::StorageDiskPartition->fetch(
                        command_interface => $Node,
                        filter            => { "owner-node-name" => $FILER_C, 'container-type' => "spare" },
                        requested_fields  => [qw(partition)]
                    );
                    try {
                        my @disk_obj1 = NACL::CS::StorageDiskPartition->fetch(
                            command_interface => $Node,
                            filter            => { 'container-type' => "unassigned" },
                            requested_fields  => [qw(partition)]
                        );
                        push( @disk_obj, @disk_obj1 ) if (@disk_obj1);
                    }
                    catch NACL::Exceptions::NoElementsFound with {
                        logcomment("$FILER_C : NO UNASSIGNED DRIVES Found");
                    }
                    logcomment("$FILER_C is a partitioned system. Checking whether the partitions are assigned properly or not.");
                    foreach my $state_obj (@disk_obj) {
                        my $free_disk = $state_obj->partition();
                        my ( $temp, $part ) = $free_disk =~ /\w+\.(\d+\.\d+)\.(P\d)/;
                        push( @{ $fil_owner{$FILER_C}{$part} }, $free_disk );
                    }
                    my @partitions = keys $fil_owner{$FILER_C};
                    @partitions = sort(@partitions);
                    grep { logcomment(" $FILER_C : Drives belongs to partition $_ : @{$fil_owner{$FILER_C}{$_}}") } @partitions;

                    #Assigning P1 partitions to one Node2  and p2 to Node1.

                    my $prompts_answers = [ ".*Do you want to continue.*" => 'y' ];
                    my $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
                    $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
                    $Api_Set_Obj->execute_raw_command( 'command' => "set test", 'connectrec-match_table' => $prompts_answers );
                    if ( defined $fil_owner{$FILER_C}{"P$parti[$check]"} ) {
                        logcomment("$FILER_C : Partitions @partitions for the disks identfied in above should be owned by two nodes, one each.");
                        logcomment("$FILER_C : P$parti[$check] partitions are found, so removing and assigning the P$parti[$check] partitions to $FILERB");
                        grep { $Api_Set_Obj->execute_raw_command( 'command' => "storage disk partition removeowner -partition $_", 'connectrec-match_table' => $prompts_answers ); $Api_Set_Obj->execute_raw_command( 'command' => "storage disk partition assign $_ -o $FILERB" ); } @{ $fil_owner{$FILER_C}{"P$parti[$check]"} };
                    }
                    $FILERB = $FILER_C;
                    $check--;
                }
                catch NACL::Exceptions::NoElementsFound with {
                    logcomment("$FILER_C doesnot contain the Partition Drives");
                }
            } elsif ( $filer_state =~ /MAINT/ ) {
                my $Host_A    = host($FILER_C);
                my $API_Obj_A = NACL::APISet->new(
                    hostobj   => $Host_A,
                    category  => "Node",
                    interface => "CLI",
                    set       => "Maintenance",
                );
                $API_Obj_A->set_timeout( "connectrec-timeout" => 7200 );
                my @free_drives = keys %{ disk_show_n( Node => $Node ) };
                foreach my $dsk (@free_drives) {
                    my ($part) = ( $dsk =~ /(P\d+)$/ );
                    push( @{ $fil_owner{$FILER_C}{$part} }, $dsk );
                }
                my $Host_B    = host($FILERB);
                my $API_Obj_B = NACL::APISet->new(
                    hostobj   => $Host_B,
                    category  => "Node",
                    interface => "CLI",
                    set       => "Maintenance",
                );
                $API_Obj_B->set_timeout( "connectrec-timeout" => 7200 );
                my @free_drives = keys %{ disk_show_n( Node => $Node ) };
                foreach my $dsk (@free_drives) {
                    my ($part) = ( $dsk =~ /(P\d+)$/ );
                    push( @{ $fil_owner{$FILER_C}{$part} }, $dsk );
                }
                my @partitions = keys $fil_owner{$FILER_C};
                @partitions = sort(@partitions);
                grep { logcomment(" $FILER_C : Drives belongs to partition $_ : @{$fil_owner{$FILER_C}{$_}}") } @partitions;

                #Assigning P1 partitions to one Node2  and p2 to Node1.
                if ( defined $fil_owner{$FILER_C}{"P$parti[$check]"} ) {
                    logcomment("$FILER_C : Partitions @partitions for the disks identfied in above should be owned by two nodes, one each.");
                    logcomment("$FILER_C : P$parti[$check] partitions are found, so removing and assigning the P$parti[$check] partitions to $FILERB");
                    grep { $API_Obj_A->execute_raw_command( 'command' => "disk remove_ownership -f $_" ); $API_Obj_B->execute_raw_command( 'command' => "storage release disks -f" ); sleep 10; $API_Obj_B->execute_raw_command( 'command' => "disk assign $_ -o $FILERB" ); } @{ $fil_owner{$FILER_C}{"P$parti[$check]"} };
                    $FILERB = $FILER_C;
                    $check--;
                }
            }
        }
        my %fil_owner1 = ();
        foreach my $Node (@Nodes) {
            my $FILER_C     = $Node->name();
            my $Transit_obj = NACL::Transit->new( name => $FILER_C );
            my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
            if ( $filer_state =~ /CLI/ ) {
                try {
                    my @disk_list = ();
                    my @disk_obj  = NACL::CS::StorageDiskPartition->fetch(
                        command_interface => $Node,
                        filter            => { "owner-node-name" => $FILER_C, 'container-type' => "spare" },
                        requested_fields  => [qw(partition)]
                    );
                    foreach my $state_obj (@disk_obj) {
                        my $free_disk = $state_obj->partition();
                        my ( $temp, $part ) = $free_disk =~ /\w+\.(\d+\.\d+)\.(P\d)/;
                        push( @{ $fil_owner1{$FILER_C}{$part} }, $free_disk );
                    }

                    #Drives with partition @disk_list ,
                    my @partitions = keys $fil_owner1{$FILER_C};
                    grep { logcomment(" $FILER_C : Drives belongs to partition $_ : @{$fil_owner1{$FILER_C}{$_}}") } @partitions;
                }
                catch NACL::Exceptions::NoElementsFound with {
                    logcomment("$FILER_C does NOT have the partitioned drives");
                }
            } elsif ( $filer_state =~ /MAINT/ ) {
                my $disk_hash = disk_show_v( Node => $Nodes[0] );
                foreach my $dsk ( keys %{$disk_hash} ) {
                    my $owner = $disk_hash->{$dsk}->{'OWNER'};
                    if ( $dsk =~ /(P\d+)$/ ) {
                        push( @{ $fil_owner1{$owner}{$1} }, $dsk );
                    }
                }
                my @partitions = keys $fil_owner1{$FILER_C};
                grep { logcomment(" $FILER_C : Drives belongs to partition $_ : @{$fil_owner1{$FILER_C}{$_}}") } @partitions;
            }
        }
        return \%fil_owner1;
    }
}

#####################################################################################################
#Burt No ::859428
##author ::sags
##DEscripton : Prints disks/drives 5 for each line.
##Return :5 disks for each line.
#####################################################################################################

sub _print_array ($) {
    my $array_ref = shift;
    my @disks     = @$array_ref;
    my @dsks      = @disks;
    my $n         = 5;
    my $delim     = " ";
    my $local_str;
    my $str;
    while ( my @disk = splice @disks, 0, $n ) {
        $local_str = join( " ", @disk );
        $str = "$str" . "$local_str" . "\n";
    }
    return $str;
}

#####################################################################################################
##Burt No ::1031605
##author ::sags
##DEscripton : ndate4.1:disk_qual runscript for test 403 write read verify needs to be defined.
##
#####################################################################################################
sub run_default_dsk_ql_scpt {
    my (%opts) = validate(
        @_,
        {
            Node        => { type => OBJECT },
            disk_list_q => { type => ARRAYREF },
            drv_typ     => { type => SCALAR, optional => 1, default => 'normal' },    #1089479
        }
    );
    my $Node        = $opts{Node};
    my $drv_typ     = $opts{drv_typ};
    my $FILER_C     = $Node->name();
    my $Host        = host($FILER_C);
    my $Transit_obj = NACL::Transit->new( name => $FILER_C );
    my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    logcomment("DEBUG:Filer state is : $filer_state");
    my @disk_list = @{ $opts{disk_list_q} };
    my $Api_Set_Obj;
    my $filer_state_A;
    my $filer_state_B;

    if ( $filer_state =~ /MAINT/ ) {
        $Api_Set_Obj = NACL::APISet->new(
            hostobj   => $Host,
            category  => "Node",
            interface => "CLI",
            set       => "Maintenance"
        );
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
    } elsif ( $filer_state =~ /CLI|UP/i ) {
        $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset( connid => "console" );
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
        $filer_state_A = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
        if ( $filer_state_A !~ /DBLADECLI/i ) {
            $Api_Set_Obj->execute_raw_command( 'command' => 'run local' );
            $Api_Set_Obj->execute_raw_command( 'command' => 'priv set -q test' );
        }
    }
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script0 -t 5 -p 3 -f 0 -l 200 -q 3 -n 8 -d @disk_list -o noverify" );
    sleep(5);
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script1 -t 5 -p 3 -f 0 -l 200 -q 3 -n 8 -d @disk_list" );
    sleep(5);
    if ( $drv_typ !~ /NVMe/i ) {
        $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script2 -t 99 -d @disk_list " );
        sleep(5);
        $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script13 -t 19 -L 3200 -p 1 -f calc -l end -q 6 -n 128 -d @disk_list -o nobc" );
        sleep(5);
        $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script26 -t 0 -p 3 -f 0 -l 70000 -q 3 -n 128 -d @disk_list -o 1" );
        sleep(5);
        $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script27 -t 0 -p 3 -f 0 -l 70000 -q 3 -n 128 -d @disk_list -o 2" );
        sleep(5);
        $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script28 -t 0 -p 3 -f 0 -l 70000 -q 3 -n 128 -d @disk_list -o 3" );
        sleep(5);
        $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script29 -t 0 -p 3 -f 0 -l 70000 -q 3 -n 128 -d @disk_list -o 4" );
        sleep(5);
    }
    sleep(5);
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script3 -t 3 -p 3 -f 0 -l 200 -q 3 -n 8 -d @disk_list" );
    sleep(5);
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script4 -t 4 -p 3 -f 0 -l 200 -q 3 -n 8 -d @disk_list" );
    sleep(5);
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script5 -t 13 -p 3 -f 0 -l 200 -q 3 -n 8 -d @disk_list" );
    sleep(5);
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script6 -t 2 -p 3 -f 0 -l 200 -q 3 -n 8 -d @disk_list" );
    sleep(5);
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script7 -t 1 -p 3 -f 0 -l 200 -q 3 -n 8 -d @disk_list" );
    sleep(5);
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script8 -t 6 -L 200 -p 1 -f od -l end -q 3 -n 8 -d @disk_list -o noverify" );
    sleep(5);
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script9 -t 1 -L 200 -p 1 -f id -l end -q 3 -n 8 -d @disk_list -o noverify" );
    sleep(5);
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script10 -t 7 -L 200 -p 1 -f md -l end -q 3 -n 8 -d @disk_list -o noverify" );
    sleep(5);
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script11 -t 8 -p 3 -f 0 -l 200 -q 3 -n 8 -d @disk_list -o noverify" );
    sleep(5);
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script12 -t 1 -p 3 -f 0 -l 200 -q 3 -n 8 -d @disk_list " );
    sleep(5);
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script14 -t 5 -p 3 -f 0 -l 3200 -q 6 -n 128 -d @disk_list" );
    sleep(5);
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script15 -t 3 -p 3 -f 0 -l 3200 -q 6 -n 128 -d @disk_list " );
    sleep(5);
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script16 -t 4 -p 3 -f 0 -l 3200 -q 6 -n 128 -d @disk_list" );
    sleep(5);
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script17 -t 2 -p 3 -f 0 -l 3200 -q 6 -n 128 -d @disk_list" );
    sleep(5);
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script18 -t 13 -p 3 -f 0 -l 3200 -q 6 -n 128 -d @disk_list" );
    sleep(5);
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script19 -t 1 -p 3 -f 0 -l 3200 -q 6 -n 128 -d @disk_list" );
    sleep(5);
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script20 -t 6 -p 3 -f 0 -l 3200 -q 6 -n 128 -d @disk_list -o noverify" );
    sleep(5);
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script21 -t 1 -p 3 -f 0 -l 3200 -q 6 -n 128 -d @disk_list" );
    sleep(5);
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script22 -t 7 -p 3 -f 0 -l 3200 -q 6 -n 128 -d @disk_list -o noverify" );
    sleep(5);
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script23 -t 18 -p 3 -f 0 -l 81920 -q 3 -n 20480 -d @disk_list" );
    sleep(5);
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script24 -t 16 -p 3 -f 0 -l 3200 -q 3 -n 128 -d @disk_list" );
    sleep(5);
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script25 -t 11 -f 0 -l end -q 1 -n 1 -d 0@disk_list" );
    sleep(5);
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script30 -t 9 -f 0 -l 100000 -q 1 -n 128 -d @disk_list -o verify" );
    sleep(5);
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script31 -t 33 -f 0 -l 100000 -q 1 -n 128 -d @disk_list -o mute_vs_errors" );
    sleep(5);
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script32 -t 33 -f 0 -l 100000 -q 1 -n 128 -d @disk_list -o mute_vs_errors" );
    sleep(5);
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script33 -t 9 -f 0 -l 100000 -q 1 -n 128 -d @disk_list -o nopattern" );
    sleep(5);
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script34 -t 33 -f 0 -l 100000 -q 1 -n 128 -d @disk_list -o mute_vs_errors" );
    sleep(5);
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script35 -t 5 -p 3 -f 0 -l 200 -q 3 -n 8 -d @disk_list -o noverify" );
    sleep(5);
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script36 -t 5 -p 3 -f 35000 -l 35200 -q 3 -n 8 -d @disk_list -o noverify" );
    sleep(5);
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script37 -t 33 -f 0 -l 100000 -q 1 -n 128 -d @disk_list -o mute_vs_errors" );
    sleep(5);
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script38 -t 33 -f 0 -l 100000 -q 1 -n 128 -d @disk_list -o mute_vs_errors" );
    sleep(5);
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script39 -t 9 -f 0 -l 100000 -q 1 -n 128 -d @disk_list -o verify" );
    sleep(5);
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script40 -t 34 -f 0 -l 100000 -q 1 -n 128 -d @disk_list -o mute_vs_errors" );
    sleep(5);
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script41 -t 33 -f 0 -l 100000 -q 1 -n 128 -d @disk_list -o mute_vs_errors" );
    sleep(5);
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual script42 -t 34 -f 0 -l 100000 -q 1 -n 128 -d @disk_list -o mute_vs_errors" );
    sleep(5);
    $Api_Set_Obj->execute_raw_command( 'command' => "disk_qual status" );
    $filer_state_B = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );

    if ( $filer_state =~ /CLI|UP/i ) {
        if ( $filer_state_A !~ /$filer_state_B/ ) {
            $Transit_obj->set( 'change_state_timeout' => 7200 );
            $Transit_obj->change_state( to => $filer_state_A );
        }
    }
}
##################################################
## Author : Kriti Upadhyay
## Description : Printing scsi modesense data for all disks
## Inputs : Null
## Output : Null
##################################################
sub scsi_modesense_pages {
    my (%opts) = validate( @_, { Node => { type => OBJECT }, } );

    my @disk_list;
    my $Node       = $opts{Node};
    my $filer_name = $Node->name();
    my $Api_Set_Obj;
    my $after;
    my $Transit_obj = NACL::Transit->new( name => $filer_name );
    my $filer_state = $Transit_obj->get_state( 'timeout' => 3600, 'get_state_timeout' => 7200 );
    logcomment("DEBUG:Getting the disks of filer $filer_name");

    if ( $filer_state =~ /MAINT/gi ) {
        my $Host = host($filer_name);
        $Api_Set_Obj = NACL::APISet->new(
            hostobj   => $Host,
            category  => "Node",
            interface => "CLI",
            set       => "Maintenance"
        );
        $Api_Set_Obj->set_timeout( 'connectrec-timeout' => 7200 );
        $after = $Api_Set_Obj->execute_raw_command( 'command' => "storage show disk -T -x" );
    } elsif ( $filer_state =~ /(CLI|UP)/gi ) {
        $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
        $Api_Set_Obj->set_timeout( 'connectrec-timeout' => 7200 );
        $after = $Api_Set_Obj->execute_command( 'command' => "storage show disk -T -x" );
    }

    foreach my $line ( split( /\n/, $after ) ) {
        if ( $line =~ /(\w+.\w+.\w+)\s+(\d+)\s+(\d+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s*/ ) {
            my ( $Device, $SHELF, $BAY, $Serial, $Vendor, $Model, $Rev, $Type ) = ( $line =~ /(\w+.\w+.\w+)\s+(\d+)\s+(\d+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s*/ );
            push( @disk_list, $Device );
        }
    }
    foreach my $dsk (@disk_list) {
        my $cmd = "scsi modesense -p 0x02 -t current  $dsk";
        $Api_Set_Obj->set_timeout( "connectrec-timeout" => 1200 );
        if ( $filer_state =~ /MAINT/i ) {
            $Api_Set_Obj->execute_raw_command( 'command' => $cmd );
            $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
        } elsif ( $filer_state =~ /(CLI|UP)/i ) {
            $Api_Set_Obj->execute_command( 'command' => $cmd );
            $Api_Set_Obj->execute_raw_command( 'command' => "\013" );
        }
    }

}    #end of scsi_modesense_pages sub

#####################################################################################################
#Burt No ::1097361
##author ::aditis
##DEscripton : shuffle the elements of array .
##Return : shuffled array.
#####################################################################################################

sub shuffle_array {
    my $array_ref = shift;
    my @disks     = @$array_ref;
    @disks = shuffle @disks;
    return @disks;
}
#####################################################################################################
#Burt No :: 1095359
##author :: arunak
##DEscripton :: copy passed logs to data lake tub and into respective buckets using scp.
## 				Manual option 10 , is also present.
#####################################################################################################
sub push_data_lake {
    my (%opts) = validate(
        @_,
        {
            log_file => { type => SCALAR },
            handle   => { type => SCALAR, optional => 1, default => 'normal' },
        }
    );
    my $optional      = $opts{handle};
    my $copy_log_file = $opts{log_file};
    my $Home          = $ENV{HOME};
    my $config        = "$Home/NDATE/FILER_INFO/data_lake";
    my $src_inf       = "data_lake";
    my $PERF          = 0;
    my $NVME_PER      = 0;
    logcomment("Copy log - $copy_log_file to data lake , Config file used :$config");
    open( CNGFILE, "$config" ) or die "Failed opening configuration file : $config \n";
    my ( $host, $user, $password, $remote_path );
    my ( $SIP_BKT, $ERT_BKT, $HAMR_BKT, $LTDH_BKT, $NVMe_BKT, $DAFA_PERF, $NVMe_DAFA_PERF );
    my $retry_flg = 0;

    foreach my $line () {
        next if ( $line =~ /^\#/ );
        $host           = $1 if ( $line =~ /^default_ip=(.*)/ );
        $user           = $1 if ( $line =~ /^default_username=(.*)/ );
        $password       = $1 if ( $line =~ /^default_password=(.*)/ );
        $SIP_BKT        = $1 if ( $line =~ /^SIP_BKT=(.*)/ );
        $ERT_BKT        = $1 if ( $line =~ /^ERT_BKT=(.*)/ );
        $HAMR_BKT       = $1 if ( $line =~ /^HAMR_BKT=(.*)/ );
        $LTDH_BKT       = $1 if ( $line =~ /^LTDH_BKT=(.*)/ );
        $NVMe_BKT       = $1 if ( $line =~ /^NVMe_BKT=(.*)/ );
        $DAFA_PERF      = $1 if ( $line =~ /^DAFA_PERF=(.*)/ );
        $NVMe_DAFA_PERF = $1 if ( $line =~ /^NVMe_DAFA_PERF=(.*)/ );
    }
    logcomment("Data lake : Host: $host | User:$user | Pass:$password");
    logcomment("Data lake : buckets available ");
    logcomment("SIP : $SIP_BKT \n LTDH : $LTDH_BKT \n ERT : $ERT_BKT \n Stress/Hammer: $HAMR_BKT\n");
    logcomment("Check for log file name");
    if ( $copy_log_file =~ /NADQ02_ERT/ ) {
        logcomment("Add log to ERT bucket");
        $remote_path = $ERT_BKT;
    } elsif ( $copy_log_file =~ /NADQ02_Long_Term_Data_Handling|Long_Term_Data_Handling/ ) {
        logcomment("Add log to LTDH bucket");
        $remote_path = $LTDH_BKT;
    } elsif ( $copy_log_file =~ /NADQ02_Stress_Test_50_50|Stress_Test_50_50/ ) {
        logcomment("Add log to HAMER bucket");
        $remote_path = $HAMR_BKT;
    } elsif ( $copy_log_file =~ /NVMe/ ) {
        logcomment("Add log to NVMe bucket");
        $remote_path = $NVMe_BKT;
        if ( $copy_log_file =~ /NVMe_Client_IO/ ) {
            $NVME_PER = 1;
        }
    } else {
        logcomment("Add log file to SIP bucket");
        $remote_path = $SIP_BKT;
        if ( $copy_log_file =~ /Client_IO/ ) {
            logcomment("Add log to DAFA_PERF bucket");
            $PERF = 1;
        }
    }
    logcomment("Remote path or final destination : $remote_path");
    logcomment("Data lake : log filer to copy into data lake : $copy_log_file");
    my $scpe = Net::SCP::Expect->new(
        host         => $host,
        user         => $user,
        password     => $password,
        auto_yes     => 1,
        verbose      => 1,
        debug        => 1,
        timeout_auto => 2,
    );
    die "can't scp: $!\n" unless $scpe->scp( $copy_log_file, $remote_path );
    logcomment("Copied file $copy_log_file to $remote_path");
    if ( $PERF == 1 ) {
        logcomment("Copy to performance bucket");
        $remote_path = $DAFA_PERF;
        logcomment("Remote path or final destination : $remote_path");
        logcomment("Data lake : log filer to copy into data lake : $copy_log_file");
        my $scpe = Net::SCP::Expect->new(
            host         => $host,
            user         => $user,
            password     => $password,
            auto_yes     => 1,
            verbose      => 1,
            debug        => 1,
            timeout_auto => 2,
        );
        die "can't scp: $!\n" unless $scpe->scp( $copy_log_file, $remote_path );
        logcomment("Copied file $copy_log_file to $remote_path");
    }
    if ( $NVME_PER == 1 ) {
        logcomment("Copy to performance bucket");
        $remote_path = $NVMe_DAFA_PERF;
        logcomment("Remote path or final destination : $remote_path");
        logcomment("Data lake : log filer to copy into data lake : $copy_log_file");
        my $scpe = Net::SCP::Expect->new(
            host         => $host,
            user         => $user,
            password     => $password,
            auto_yes     => 1,
            verbose      => 1,
            debug        => 1,
            timeout_auto => 2,
        );
        die "can't scp: $!\n" unless $scpe->scp( $copy_log_file, $remote_path );
        logcomment("Copied file $copy_log_file to $remote_path");
    }
}
#####################################################################
#Subroutine for getting  shelf id for trafford
#Author: kritiu
#Burt: 1092343
#####################################################################

sub shelf_id_trafford {
    my (%opts) = validate( @_, { Node => { type => OBJECT }, } );
    my $Node = $opts{Node};
    my $FILER_C = $Node->name();
    $Node->refresh_command_interface();
    my $Api_Set_Obj = $Node->get_7m_or_nodescope_apiset();
    $Api_Set_Obj->set_timeout( "connectrec-timeout" => 7200 );
    my $power_struct = {};
    my $shelfid;
    my $adpters;

    my @expanders       = ();
    my @up_channels     = ();
    my @channel         = ();
    my $sasadmin_output = $Api_Set_Obj->execute_command( 'command' => "sasadmin expander_map" );
    foreach my $line ( split( /\n/, $sasadmin_output ) ) {
        if ( $line =~ /Expanders on channel\s+(\w+):/ ) {
            push( @expanders, $1 );
        }
        if ( $line =~ /Cannot Complete operation on channel\s+(\w+);/ ) {
            push( @channel, $1 );
        }
    }
    @up_channels = array_diff( [@expanders], [@channel] );
    foreach my $up (@up_channels) {
        my $output1 = $Api_Set_Obj->execute_raw_command( 'command' => "storage shelf show -fields shelf-id" );
        my @lines = split( /\n/, $output1 );
        my $n = 0;

        # skip to the start of table contents
        while ( $n <= $#lines ) {
            $lines[$n] =~ s/^\s*//;
            last if ( $lines[$n] =~ /^-----/ );
            $n++;
        }
        $n++;
        foreach my $line ( @lines[ $n .. $#lines ] ) {
            $line =~ s/^\s*//;

            if ( $line =~ /\S+\s+\d+\.\d+\s+(\d+)\s*/ ) {
                $shelfid = $1;
                $adpters = $up . "." . $shelfid;
            }
            $power_struct->{$adpters}->{Shelfid} = $adpters;
        }

    }

    return ($power_struct);
}

sub get_lif_from_config_file {
    my ( $file_2_read, $client_no ) = @_;
    my $start_ip;
    my $end_ip;
    my @LIF_IP;
    my $Home = $ENV{HOME};
    logcomment("Client number is $client_no");
    logcomment("Config File to Read : $file_2_read");
    open( READ, "$file_2_read" ) || print "FAILED to read the readme file\n";

    foreach my $line () {
        chomp($line);
        if ( $line =~ /START_IP_RANGE:(\S+)/ ) {
            $start_ip = $1;
            logcomment("Starting range IP : $start_ip");
        }
        if ( $line =~ /END_IP_RANGE:(\S+)/ ) {
            $end_ip = $1;
            logcomment("Ending rang IP : $end_ip");
        }
    }
    if ( ( $start_ip ne '' ) && ( $end_ip ne '' ) ) {
        logcomment("FORMAT 1 - RANGE is specified, Generating IP between those range\n");
        if ( $client_no == 2 ) {
            for ( my $i = 1 ; $i <= 80 ; $i++ ) {
                my ( $p1, $p2 ) = $start_ip =~ /(\d+\.\d+\.\d+)\.(\d+)/;
                my $ip = $p2 + $i;
                push( @LIF_IP, "$p1" . "." . "$ip" );
            }

        } elsif ( $client_no == 1 ) {
            for ( my $i = 1 ; $i <= 40 ; $i++ ) {
                my ( $p1, $p2 ) = $start_ip =~ /(\d+\.\d+\.\d+)\.(\d+)/;
                my $ip = $p2 + $i;
                push( @LIF_IP, "$p1" . "." . "$ip" );
            }

        }
    } else {
        logcomment("Range format is not valid, Proceeding with format 2 check\n");
        open( READ, "$Home/NDATE/FILER_INFO/NDATE_LIF_CONFIG.config" ) || print "FAILED to read the readme file\n";
        foreach my $line () {
            chomp($line);
            if ( $line =~ /IP_\d+\:(\S+)/ ) {
                push( @LIF_IP, $1 );
            }
        }
    }
    my $lif = _print_array( \@LIF_IP );
    logcomment( "LIF Captured" . $lif );
    return @LIF_IP;
}
1;