#!/usr/software/bin/perl # $Id: ## ## Copyright (c) 2005 Network Appliance, Inc. ## All rights reserved ## ## @summary Mode ## Create mini_disk . ## ## @description ## Create mini disk ## ## ## ## ## @status Automated ## @auther arjun.lavu@netapp.com ## @change YY/MM/DD from auther: Description of the change ## ############################################################################# # Compiler directives. use strict; use warnings; # # Module import. # use Subtest; # # Import exceptions # use Storage::Common_Lib; use Storage::Common_Lib_Cmode; # Subroutines sub _intersect(\@\@); sub _unique(@); sub _array_diff(\@\@); ######################################## ### Initialization/declaration ######################################### use vars qw( $FILER $STEST_DEBUG $STEST_FILE $LOGLVL $LOGDIR $MAIL_TO $MAIL_FROM $MAIL_MSG $EMAIL $TEST_SUITE_NAME $TEST_CONFIG $FILERA $FILERB $FILER_CONN $TEST_SETUP $MODE $MINI_CREATE_SIZE $MINI_CREATE $FILER_TYPE $BOOT_MODE $FILER_PROMPT $BOOT_TYPE $EOE $Primary_Node ); param( 'FILER', '-mesg', 'HostID of filer' ); param( "FILERA", '-default', '' ); param( "FILERB", '-default', '' ); param( "FILER_CONN", '-default', '#rsh' ); param( "MODE", '-default', 'normal' ); param( 'TEST_SETUP', '-default', 'FC' ); param( 'TEST_CONFIG', '-default', 'D' ); param( 'BOOT_MODE', '-default', '1' ); param( 'FILER_TYPE', '-default', 'BR' ); param( 'MINI_CREATE_SIZE', '-default', '1' ); param( 'MINI_CREATE', '-default', 'n' ); param( 'STEST_DEBUG', '-default', '1' ); param( 'STEST_FILE', '-mesg', 'Runlist file' ); param( 'LOGDIR', '-default', '' ); param( 'LOGLVL', '-default', '2' ); param( 'MAIL_TO', '-default', 'default' ); param( 'MAIL_FROM', '-default', 'default' ); param( 'MAIL_MSG', '-default', 'n' ); param( 'EMAIL', '-default', 'n' ); param( 'TEST_SUITE_NAME', '-mesg', 'Test_Suite_Name' ); param( "FILER_PROMPT", '-default', '\*>' ); param( 'BOOT_TYPE', '-default', 'A'); param( 'EOE', '-default', 'default' ); param( 'Primary_Node', '-default', 'N' ); my $email_subject; my $email_body; my $host; my $hostB; my $filer; my $filerB; my $filer_con; my $filer_conB; my $filerip; my $fileripB; my $bootfile; my $bootfileB; my $gateway; my $gatewayB; my @filers; my @hosts; my @filers_rsh; my $filer_con_rsh = ""; my $filer_conB_rsh = ""; my $priv = "test"; my $def_password; my $def_passwordB; my $bootup; my $complete_setup = 0; #####################################################333 my $Mode; my @Nodes; my $test_status = 0; #Set test fail parameter to 0 my $filer_names; my %Node_Api; my @create_mini; my %node_ckeck; my @Nodes_all; my @boot_4d; my $numberofvols = 1; my $numraidgroups = 1; my $spares = 1; my $bootmode = "5"; my $netmask = "255.255.0.0"; ######################################### ## Pre-test processes ######################################### my $TC_name = "MINI_DISK_CREATE"; my @Testcases = ( MINI_DISK => "MINI_DISK CREATION" ); &main(); sub main { # Debug break point $DB::single = 2; # Create Test Case Driver object $Test = new TCD( -testcases => [@Testcases] ); if ( $Test->error ) { $Test->log( $Test->errmsg ); $test_status = 1; $email_subject = "$TC_name : Test FAILED: FAIL"; $email_body = "Failed to instantiate Test object.\nLog Location : $LOGDIR\n"; send_message( mail_subject => $email_subject, mail_body => $email_body, MAIL_FROM => $MAIL_FROM, MAIL_TO => $MAIL_TO, EOE => $EOE, EMAIL => $EMAIL ); return $TCD::FAIL; } # Performs method callbacks $Test->run_test(); if ( $Test->error ) { $Test->log( $Test->errmsg ); return $TCD::FAIL; } exit(0); } ## end sub main ############################################################################## # Function: init # Purpose: init() is automatically called before executing tests to get test # parameters and to create any needed resources ############################################################################## sub init() { return $TCD::PASS if( $BOOT_TYPE eq "N"); $Test->description( "Initialising all required variables and FILER connections " ); $filer_names = $Test->get_param("FILER"); # Capturing Filer names from the param(Test_Suite) ##Check for duplicate node object and push unique node object in Nodes array. 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; } @Nodes = values(%nodes_filer); # Contains Node object used for test execution. @Nodes_all = @Nodes; $Mode = $Nodes[0]->mode(); # gets mode(7mode/cmode) of the nodes used in test execution. if(("$TEST_CONFIG" eq 'E')&&($Primary_Node!~/^N$/)){ modify_cmode_as_dual(Node_ref =>\@Nodes,Test => $Test,primary_filer_name => $Primary_Node); logcomment("Test will run only on node $Primary_Node"); } return $TCD::PASS; } # end init() ############################################################################## # Function: setup # Purpose: setup() is automatically called before executing tests ############################################################################## sub setup() { return $TCD::PASS if( $BOOT_TYPE eq "N"); #return if user selects the BOOT_TYPE option N; $Test->description( "Inside SETUP Checking if any un-assigned disks and changing the filer state to MAINT if required"); disk_remv_assign_ownership(Node_ref =>\@Nodes); if ( $Mode eq '7Mode' ) { if ( "$TEST_CONFIG" eq "C" ) { $host = host($FILERA); $filer_con = connect("$FILERA#console"); $hostB = host($FILERB); $filer_conB = connect("$FILERB#console"); $FILER = $FILERA; $filer_con->timeout("1200"); $filer_con->prompts($FILER_PROMPT); $filer_conB->timeout("1200"); $filer_conB->prompts($FILER_PROMPT); $filer = $host->hostname; $filerip = $host->default_ip(); $gateway = $host->{GATEWAY}; $filerB = $hostB->hostname; $fileripB = $hostB->default_ip(); $def_password = $host->{default_password}; $def_passwordB = $hostB->{default_password}; if ( $FILER_TYPE eq "IC" ) { $bootfileB = $hostB->bootimage(); $bootfile = $host->bootimage(); } elsif ( $FILER_TYPE eq "BR" ) { $bootfile = $host->{BOOT_IMAGE}; $bootfileB = $hostB->{BOOT_IMAGE}; } $gatewayB = $hostB->{GATEWAY}; push( @filers, $filer_con ); push( @filers, $filer_conB ); push( @hosts, $host ); push( @hosts, $hostB ); } else { $host = host($FILER); $filer = $host->hostname; $filerip = $host->default_ip(); $def_password = $host->{default_password}; if ( $FILER_TYPE eq "IC" ) { $bootfile = $host->bootimage(); } elsif ( $FILER_TYPE eq "BR" ) { $bootfile = $host->{BOOT_IMAGE}; } $gateway = $host->{GATEWAY}; $filer_con = connect("$FILER#console"); $filer_con->timeout("1200"); $filer_con->prompts($FILER_PROMPT); push( @filers, $filer_con ); push( @hosts, $host ); } } foreach my $node(@Nodes){ my(@mini_disk,@normal_disk,@disks); 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); $Api_Set_Obj->execute_raw_command( 'command' => "\013" ); $Api_Set_Obj->execute_raw_command( 'command' => "\013" ); if($filer_state =~/(CLI|UP)/i){ logcomment("FILER state is $filer_state, Checking whether mini_disks already present or not"); my $Api_Set_Obj = $node->get_7m_or_nodescope_apiset(); my $prompts_answers = ['Do you want to continue? {y|n}:'=> 'y']; $Api_Set_Obj->execute_raw_command('command' =>"set test",'connectrec-match_table' => $prompts_answers) if ($Mode =~/CMode/i); $Api_Set_Obj->execute_raw_command('command' =>"priv set -q test") if ($Mode =~/7Mode/i); my $result = $Api_Set_Obj->mini_disk_list(); my @disks = @{$result->get_parsed_output()}; foreach my $disk (@disks) { if($disk->{type} ne "NORMAL disk") { push(@mini_disk,$disk->{disk}); }elsif($disk->{type} eq "NORMAL disk"){ push(@normal_disk,$disk->{disk}); } } logcomment("$FILER : Total number of mini-disks are ".scalar @mini_disk." and the disks are @mini_disk")if (@mini_disk); logcomment("$FILER : Total number of normal_disk are ".scalar @normal_disk." and the disks are @normal_disk")if (@normal_disk) ; if((!@mini_disk)&&(!@normal_disk)){ logcomment("WARNING : $FILER : No Normal disks and no Mini_disks found, mini_disk list command is not working in Filesystem mode, Checking in Maintenance mode"); next; } my $disk_ref = disk_show_drive_maint(API_Obj =>$Api_Set_Obj,Filer=>$FILER); my @disks_filer = @{$disk_ref->{'driveA'}}; if(@disks_filer){ logcomment("$FILER : Total number of disks are ".scalar @disks_filer." and the disks are @disks_filer, out of these disks checking whether all are mini-disks or not"); } my @matched_mini_disks =_intersect(@disks_filer,@mini_disk); my @res = _array_diff(@matched_mini_disks,@disks_filer); if(!@res){ logcomment("$FILER : all the disks are already mini_disks"); $node_ckeck{$node} = 1; my $cmd; if($Mode=~/CMode/i){ $cmd = "run local aggr status -r"; }else{ $cmd = "aggr status -r"; } logcomment("$FILER : Checking whether disks are zeroed or not"); my $output = $Api_Set_Obj->execute_raw_command('command' =>$cmd); if($output=~/not zeroed|zeroing/ ) { logcomment("$FILER : Some of the disks are not Zeroed|Zeroing so booting the filer in 4d "); push(@boot_4d,$node); } }else{ logcomment("$FILER : disks @res which belongs to filer are not mini_disks, So booting the filer in MAINT mode, creating minidsks and booting in 4d"); #$node_ckeck{$node} = 0; } } } my @change_states; foreach my $node(@Nodes){ next if(defined $node_ckeck{$node}); ##Already mini-disk are present, so ignoring checking 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); $Api_Set_Obj->execute_raw_command( 'command' => "\013" ); $Api_Set_Obj->execute_raw_command( 'command' => "\013" ); if($filer_state =~/(UP|CLI)/i){ $Test->nlog("Filer state $filer_state"); $Test->nlog("$FILER : Filer is not in Maintenance Mode, So booting in Maintenance mode"); push(@change_states,$FILER); ##array @change_states contains the filer names which has to boot in maintenance mode }elsif($filer_state =~/MAINT/i){ $Test->nlog("$FILER : Filer is already in Maintenance Mode"); }else{ push(@change_states,$FILER); } } my @subtests; foreach my $filer_name (@change_states){ push(@subtests, subtest( \&boot_filer_in_req_state, -runid, "boot_filer_in_MAINT_" . "$filer_name", -bg, "--", Test => $Test, filer_name => $filer_name, change_state_to => "MAINT", ) ); } $Test->nlog("Subtest @subtests"); Subtest::wait_finish( subtest => [@subtests] ); foreach my $node(@Nodes){ my $FILER = $node->name(); 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} = 5; $console->{on_idle} = sub { $console->execute(""); }; my $API_obj = NACL::APISet->new(connection => $console, category => "Node", interface => "CLI", set => "Maintenance"); $Node_Api{$node}=$API_obj; } return $TCD::PASS; } sub MINI_DISK { return $TCD::PASS if( $BOOT_TYPE eq "N"); $Test->description("Creating mini_disks if not present"); #Deletion of mini disk if present based on the user input foreach my $node(@Nodes){ next if(defined $node_ckeck{$node}); ##don't check for mini-disks my $FILER_C = $node->name(); my $status = delete_mini_disk(node => $node,verify => 'Y'); if($status =~/ignore/i){ logcomment("$FILER_C : Already mini disks present in the filer, So ignoring mini-disks creation"); my $API = $Node_Api{$node}; my $output = $API->execute_raw_command('command' =>"aggr status -r"); if( $output =~ /No root aggregate or root traditional volume found|No root aggregate|not zeroed|zeroing/){ push(@boot_4d,$node); } next; }else{ ##Creating MINI_DISKS logcomment("$FILER_C : Creating mini_disks"); create_mini_disk(node => $node,size => $MINI_CREATE_SIZE); push(@boot_4d,$node); ##Booting in 4d after mini_disk creation } } return $TCD::PASS; } sub cleanup() { return $TCD::PASS if( $BOOT_TYPE eq "N"); $Test->description("Booting the filer in 4d if mini_disks are created"); my @subtests; @boot_4d = _unique(@boot_4d); if(@boot_4d){ ##If Mini-disks are created, @boot_4d array contains the nodes, which will be booted in 4d if($Mode=~/7Mode/i){ if(scalar @boot_4d == 1){ my $FILER_C = $boot_4d[0]->name(); $Test->nlog("Booting the filer $FILER_C in 4d"); my $FILER_C_con = connect("$FILER_C#console"); push(@subtests, subtest(\&bootitgood, -runid, "boot_4d_$FILER", -bg, "--", $FILER_C_con,$bootfile,'4d',$numberofvols,$spares,$numraidgroups, $FILER_C, $filerip, $gateway, $netmask,$FILER_TYPE, $def_password, $host) ); Subtest::wait_finish( subtest => [@subtests] ); }elsif(scalar @boot_4d == 2){ $Test->description("Booting the filer $FILER in 4d"); $Test->description("Booting the filer $FILERB in 4d"); push(@subtests, subtest(\&bootitgood, -runid, "boot_4d_$FILER", -bg, "--", $filer_con,$bootfile,'4d',$numberofvols,$spares,$numraidgroups, $FILER, $filerip, $gateway, $netmask,$FILER_TYPE, $def_password, $host) ); push(@subtests, subtest(\&bootitgood, -runid, "boot_4d_$FILERB", -bg, "--", $filer_conB,$bootfileB,'4d', $numberofvols,$spares,$numraidgroups,$FILERB, $fileripB, $gateway, $netmask,$FILER_TYPE, $def_passwordB, $hostB) ); } Subtest::wait_finish( subtest => [@subtests] ); }else{ if($BOOT_MODE == 1){ logcomment("Complete setup of filers"); setup_cmode_filers(node_present => \@Nodes_all,Test =>$Test,delete_mini_disk =>'NO',remove_assign_disk => 'NO'); }else{ foreach(@boot_4d){ my $Filer = $_->name(); $Test->nlog("$Filer : Booting the filer in 4d"); push(@subtests, subtest(\&boot_filer_in_4d, -runid, "boot_filer_in_4d_" . "$Filer", -bg, "--", node => $_, ) ); } logcomment("Subtest @subtests"); Subtest::wait_finish( subtest => [@subtests] ); } } } @subtests =(); ##If No mini-disks created then the filer will be booted in file-system mode my $mode; if( $BOOT_MODE == 1){ $mode = 'CLI'; }else{ $mode = 'MAINT'; } # $mode = 'CLI' if( $BOOT_MODE == 1); # $mode = 'MAINT' if( $BOOT_MODE == 5); logcomment("Mini-disks are already present/Created, so filer is booting in $mode mode if necessary"); foreach my $node (@Nodes){ 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); $Api_Set_Obj->execute_raw_command( 'command' => "\013" ); $Api_Set_Obj->execute_raw_command( 'command' => "\013" ); if($filer_state=~/$mode/i){ logcomment("$FILER : Filer is in required state i,e $mode"); next; }else{ push(@subtests, subtest( \&boot_filer_in_req_state, -runid, "boot_filer_in_".$mode."_"."$FILER", -bg, "--", Test => $Test, filer_name => $FILER, change_state_to => $mode,) ); $Test->nlog("$FILER : Changing Filer state changed to $mode"); } } Subtest::wait_finish(subtest => [@subtests]); return $TCD::PASS; } sub _intersect(\@\@) { my %e = map { $_ => undef } @{$_[0]}; return grep { exists( $e{$_} ) } @{$_[1]}; } sub _unique(@) { my %nodes_filer; foreach my $Node(@_){ my $FILER_C = $Node->name(); $nodes_filer{$FILER_C}=$Node; } return values(%nodes_filer); } sub _array_diff(\@\@) { my %e = map { $_ => undef } @{ $_[1] }; return @{ [ ( grep { ( exists $e{$_} ) ? ( delete $e{$_} ) : (1) } @{ $_[0] } ), keys %e ] }; }