# Copyright (c) 2014-2016 NetApp, Inc., All Rights Reserved # Any use, modification, or distribution is prohibited # without prior written consent from NetApp, Inc. # ## @summary BSDInstall MTask Module ## @author dl-nacl-dev@netapp.com ## @status public ## @pod here =head1 NAME NACL::MTask::BSDInstall =head1 DESCRIPTION C provides a series of well-defined methods related to installing, uninstalling, renaming binaries on the BSD shell of the filer. =head1 ATTRIBUTES =head2 command_interface command interface object for the node on which binaries will be installed. =head2 filer_binary_install_path A scalar, the path where binaries have to be installed. =head2 binaries An arrayref which contains binaries to be installed. =head2 binaries_installed An arrayref which contains binaries currently installed on the filer. =cut package NACL::MTask::BSDInstall; use strict; use warnings; use NATE::Log qw(log_global); use NACL::APISet::Exceptions::ConnectionFailedException qw(:try); use NACL::Exceptions::VerifyFailure; use NATE::BaseException; use NATE::Exceptions::Argument; use NACL::APISet::Exceptions::ResponseException; use NACL::APISet::Exceptions::TimeoutException; use Params::Validate qw/validate validate_with SCALAR SCALARREF BOOLEAN OBJECT ARRAYREF HASHREF/; use Data::Dumper; use TestUtils; use TracePkg; my $Trace = new TracePkg(); use Class::MethodMaker [ scalar => [ { -type => 'NACL::C::CommandInterface' }, 'command_interface' ], scalar => 'filer_binary_install_path', scalar => 'binaries', scalar => 'binaries_installed', ]; my $Log = log_global(); my $may_enter = $Log->may_enter(); my $may_exit = $Log->may_exit(); my $Default_Install_Path = '/mroot/test_binaries'; =head1 METHODS =head2 install_binaries my $binary_filer_path = NACL::MTask::BSDInstall->install_binaries( command_interface => $ci, binaries => [ qw( dt hammer iozone ) ], source_path => '/x/eng/localtest/arch/path/to/bin', filer_binary_install_path => '/mroot/binaries', #defaults to /mroot/test_binaries path nacltask_if_exists => 'die', #defaults to die nacltask_verify => 1, #defaults to 1 ); (Class method) This method will copy the binary file from source path to the destination path and modify the permissions to "755" for the binary files. =over =item Options =over =item C<< "command_interface=>Node" >> (Required) The command interface (NACL::C::CommandInterface object) of the filer on which this task is performed. =item C<< "binaries=>[ $bin1 $bin2 ]" >> (Required, Arrayref) The list of binaries which need to be installed on the filer. =item C<< "source_path=>$path1" >> (Optional, Scalar) the path of the binary's off-box location. The different examples of passing the source_path & binaries combination is given as follows : =over =item * For example the user wants to copy binaries 'dt','hammer' & 'iozone' from the source path /usr/software/test/bin, the call should be made as, my $path = '/usr/software/test/bin/'; my $binary_filer_path = NACL::MTask::BSDInstall->install_binaries( command_interface => $ci, binaries => [ qw( dt hammer iozone ) ], source_path => $path, filer_binary_install_path => '/mroot/', ); So all the binaries should be present at the source path '/usr/software/test/bin/'. =item * Another example is if the user is not specifying the source_path, in that case the default value will be taken according to build of the filer. my $binary_filer_path = NACL::MTask::BSDInstall->install_binaries( command_interface => $ci, binaries => [ $bin1 $bin2 ], filer_binary_install_path => '/mroot/', ); In the above call, the 'source_path' is defaulted based on the node's version of OnTap. Defaulted to '/x/eng/localtest/arch/amd64-bsd-freebsd9/bin/' for v8.4 (LongBoard). =back =item C<< "filer_binary_install_path=>$filer_binary_install_path" >> (Optional) The destination path on the BSD shell of the filer to which the binary needs to be copied. Defaults to "/mroot/test_binaries". If filer_binary_install_path is not present it will be created. =item C<< "nacltask_if_exists=>$nacltask_if_exists" >> (Optional) If the value of this parameter is of the following - =over =item C NATE::BaseException is thrown which says that the binary is already installed on the filer. =item C The installation is skipped and the existing binary is used. The existing binary will be moved to the filer_binary_install_path. =item C Remove the existing binary and copy from the source-path again. =back Defaults to "die". If there are multiple binaries which is to be installed, the method will do a pre-check and find all the binaries existing in the filer and compares with the binaries passed from the user. So after this check there will be two types of binaries, existent & non-existent.(w.r.t to filer side) For non-existent binaries the method will install them as requested. For the existent binaries, for the value passed to nacltask_if_exists the following steps takes place: =over =item C NATE::BaseException is thrown with the names of the binaries which are already installed. =item C The installation is skipped, existing binary will be moved to filer_binary_install_path. =item C Remove the existing binaries and copy from the source-path again. =back =item C<< "server" >> (Optional) The server which is used to download the binary to filer. Defaults to "web.rtp.netapp.com" =item C<< "timeout" >> (Optional) A custom timeout for installing binaries. Default = 60 seconds =item C<< "nacltask_verify=>$verify" >> (Optional) This is a boolean value which is used to check if the binary which is copied to the bsd shell is of the same size as that present at the source path. Defaults to 1. This check will be done after copying all binaries. If the size is different a exception is raised to notify that the copied file-size is not equal to that present at the source site. If file size vary after installation installed file will not be purged, only exception will be thrown. =back =back =over =item Exceptions =over =item C<< NATE::BaseException >> This exception is thrown when =over =item * Binary is not found at the source =item * Binary is already found on the filer =item * On failure of command execution =back =item C<< NACL::Exceptions::VerifyFailure >> This type of exception is thrown when verification fails for the installed binaries. =back =back =cut sub install_binaries { $Log->enter() if $may_enter; my ( $pkg, @args ) = @_; my %opts = validate_with( params => \@args, spec => { command_interface => { type => OBJECT, isa => 'NACL::C::CommandInterface' }, binaries => { type => ARRAYREF }, source_path => { type => SCALAR, default => '/x/eng/localtest/arch/amd64-bsd-freebsd9/bin' }, filer_binary_install_path => { type => SCALAR, default => $Default_Install_Path }, server => { type => SCALAR, optional => 1}, timeout => { type => SCALAR, default => 60 }, nacltask_if_exists => { type => SCALAR, default => 'die' }, nacltask_verify => { type => SCALAR, default => 1 }, }, ); my $ci = $opts{command_interface}; my $binaries = $opts{binaries}; my $source_path = $opts{source_path}; my $filer_binary_install_path = $opts{filer_binary_install_path}; my $nacltask_if_exists = $opts{nacltask_if_exists}; my $nacltask_verify = $opts{nacltask_verify}; my $server; #if correct ip address value along with correct install_proto value #is passed then we can directly use it inside $server like #http://172.26.133.28 if ( defined $opts{server} ) { $server = $opts{server}; } else { $server = $pkg->_get_web_server(node => $ci); } my $obj; my @binaries_list_opts = @{$binaries}; my ( @binaries_that_exist, @binaries_list, @binary_sources, @binaries_installed, @bad_binaries, @commands, @non_existing_binaries, @binaries_purge_list, @binaries_not_exist, @binaries_to_copy ); my %timeout = (timeout => $opts{timeout}); delete $opts{timeout}; my $version_manager = $ci->get_version_manager(); # Create connection object my $api_set_obj = $ci->apiset( category => 'Node', interface => 'CLI', set => 'Systemshell', ); $api_set_obj->set_privilege( 'privilege-level' => "root" ); # Create filer path $api_set_obj->mkdir( 'paths' => $filer_binary_install_path, 'make-parents' => 1, ); # Build the complete path of binaries for verification foreach my $binary ( @{$binaries} ) { push @binary_sources, "$source_path/$binary"; } # Check whether binary exists in the source specified. # Binary will be searched in the local file system and if not found # exception will be thrown. # The default path '/x/eng/localtest/arch/amd64-bsd-freebsd9/bin' # will be available always. If source_path is choosed other than this # then user has to make sure that the source_path is there # on the NFS mount and shared. foreach my $binary (@binary_sources) { if ( !( -e $binary ) ) { push @non_existing_binaries, $binary; } } if ( scalar(@non_existing_binaries) ) { my $error = "Following binaries are not found at source:\n"; $error .= join( "\n", @non_existing_binaries ); $error .= "\n Please make sure source path is available on shared NFS mounts."; $Log->exit() if $may_exit; NATE::BaseException->throw($error); } # Check whether the binary is already installed on filer and take proper # action based on value for 'nacltask_if_exists' $pkg->_check_for_files_exist_and_donot_exist( command_interface => $ci, binaries_list_opts => \@binaries_list_opts, binaries_that_exist => \@binaries_that_exist, binaries_not_exist => \@binaries_not_exist, ); push( @binaries_list, @binaries_not_exist ); if ( @binaries_that_exist ) { $pkg->_handle_if_exists_action( command_interface => $ci, nacltask_if_exists => $nacltask_if_exists, binaries_list => \@binaries_list, binaries_that_exist => \@binaries_that_exist, binaries_to_copy => \@binaries_to_copy, filer_binary_install_path => $filer_binary_install_path, binaries_installed => \@binaries_installed, ); } # Installs the non existing binaries $Log->debug('Installing the non-existing binaries'); my $flag_default_server; INSTALL_BINARY_ON_DEFAULT_SERVER: { foreach my $binary (@binaries_list) { my $wget_flag = 0; my ($cmd,$wget_output); try { $cmd = $pkg->_build_install_commands( server => $server, source_path => $source_path, binary => $binary, destination_path => $filer_binary_install_path, ); $wget_output = $api_set_obj->execute_command( command => $cmd, %timeout ); if($wget_output =~ /Connecting\s+to.*failed:.*/) { $flag_default_server = 1; } } catch NACL::APISet::Exceptions::TimeoutException with { $flag_default_server = 1; }; if ($flag_default_server) { $Log->debug("Using default server web.rtp.netapp.com as getting $wget_output from $server "); $server = 'web.rtp.netapp.com'; $flag_default_server = 0; goto INSTALL_BINARY_ON_DEFAULT_SERVER; } my $wget_rc = $api_set_obj->execute_command( command => 'echo $?' ); chomp $wget_rc; if ($wget_rc != 0) { # installation seems to have failed. # wget creates a 0-byte file locally even if it fails $Log->debug('Installation failed, removing any temp files created by wget'); $api_set_obj->execute_command( command => "sudo rm -f $filer_binary_install_path/$binary" ); throw NATE::BaseException( "Failed to install $binary using wget!\n"); } else { # binary installed, let's change permissions to allow execution my $chmod_resp = $api_set_obj->chmod( 'paths' => "$filer_binary_install_path/$binary", 'mode' => 755, ); $Log->debug('chmod command status:' . $chmod_resp->get_execution_status()); push @binaries_installed, "$filer_binary_install_path/$binary"; } } } if ( scalar(@binaries_to_copy) ) { $Log->debug('Reusing the binaries that already exist'); foreach my $binary (@binaries_to_copy) { my $cp_output = $api_set_obj->cp( force => 1, source => "$Default_Install_Path/$binary", dest => $filer_binary_install_path, ); my $chmod_resp = $api_set_obj->chmod( 'paths' => "$filer_binary_install_path/$binary", 'mode' => 755, ); $Log->debug('chmod command status:' . $chmod_resp->get_execution_status()); push @binaries_installed, "$filer_binary_install_path/$binary"; } } # Verify the installed binaries my $pattern_for_matching_file_size = qr /\s*\d+\s+[-\w]+\s+\d+\s+\w+\s+\w+\s+(\d+)\s+\w+.*/; if ($nacltask_verify) { for my $binary_count ( 0 .. scalar( @{$binaries} ) - 1 ) { my ( $dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $binary_original_size, $atime, $mtime, $ctime, $blksize, $blocks ) = stat( $binary_sources[$binary_count] ); my $list_destination = $api_set_obj->execute_command( command => "ls -ls $filer_binary_install_path/$binaries_list_opts[$binary_count]" ); if ( $binary_original_size == 0 ) { $Log->warn( "File size is zero at the source for the file:" . "$binary_sources[$binary_count]" ); } my $file_size = ( $list_destination =~ /$pattern_for_matching_file_size/ ? $1 : "" ); if ( $binary_original_size != $file_size ) { $Log->error("$binaries_list_opts[$binary_count]: " . "Was expecting binary size [$binary_original_size], " . "but found installed size [$file_size]."); push @bad_binaries, $binaries_list_opts[$binary_count]; } } if ( scalar(@bad_binaries) ) { my $error = "Binary size vary for following binaries:\n"; $error .= join( "\n", @bad_binaries ); $Log->exit() if $may_exit; NACL::Exceptions::VerifyFailure->throw($error); } else { $Log->debug('All binaries are verified and installed properly'); } } $obj = $pkg->new( 'command_interface' => $opts{command_interface}, 'binaries' => $opts{binaries}, 'filer_binary_install_path' => $opts{filer_binary_install_path}, 'binaries_installed' => \@binaries_installed, ); $Log->exit() if $may_exit; return $obj; } ## end sub install_binaries =head2 uninstall_binaries NACL::MTask::BSDInstall->uninstall_binaries( command_interface => $ci, filer_binary_install_path => $filer_binary_install_path, binaries => [ qw( dt hammer iozone ) ], nacltask_if_purged => 'pass', #defaults to "pass" ); (or) #Instance call $BSDInstall_obj->uninstall_binaries(); (Class or Instance Method) This method can be used to uninstall the binaries from the filer_binary_install_path passed. =over =item Options =over =item C<< command_interface => $node >> (Mandatory for Class call, Optional for Instance Class) The command interface of the filer on which this task is performed. =item C<< filer_binary_install_path=>$filer_binary_install_path >> (Mandatory for Class call, Optional for Instance Class) The path on the BSD shell of the filer on which the binary needs to be uninstalled. =item C<< binaries=>[ $bin1 $bin2 ] >> (Mandatory for Class call, Optional for Instance Class) The list of binaries which needs to be uninstalled on the filer. =over =item * If the user has made a class call or if the user wants to explicitly mention the path of the filer & binaries which needs to be deleted, the call should be made in the below form : NACL::MTask::BSDInstall->uninstall_binaries( command_interface => $ci, filer_binary_install_path => $path, binaries => [ $bin1 $bin2 ], ); binaries $bin1 & $bin2 should be present in the $path1. =back =item C<< nacltask_if_purged=>$die >> (Optional) This option accepts values "die" or "pass". Defaults to "pass". If value is "die" and delete operation failed because binary was not present, "NATE::BaseException" is thrown. If value is "pass", the exception is not thrown when the operation fails. If there are multiple binaries which is to be deleted, for existent binaries the method will delete them as requested. For the non-existent binaries, for the value passed to nacltask_if_purged the following steps takes place, =over =item C NATE::BaseException is thrown with the names of the binaries which are already purged. =item C Exception is not thrown. =back =back =over =item Exceptions =over =item C<< NATE::BaseException >> This exception is thrown when =over =item * Binary to be uninstalled is not found on the filer =item * On failure of command execution =back =back =back =back =cut sub uninstall_binaries { $Log->enter() if $may_enter; my ( $pkg, @args ) = @_; my %opts = validate_with( params => \@args, spec => { command_interface => { type => OBJECT, isa => 'NACL::C::CommandInterface', optional => 1 }, filer_binary_install_path => { type => SCALAR, default => $Default_Install_Path }, binaries => { type => ARRAYREF, optional => 1 }, nacltask_if_purged => { type => SCALAR, default => 'pass', optional => 1 }, }, ); my $ci = $opts{command_interface} || $pkg->{command_interface}; my $filer_binary_install_path = $opts{filer_binary_install_path} || $pkg->{filer_binary_install_path}; my $binaries = $opts{binaries} || $pkg->{binaries}; my $nacltask_if_purged = $opts{nacltask_if_purged}; my @binaries_list = @{$binaries}; my $output; my $apiset = $ci->apiset( category => 'Node', interface => 'CLI', set => 'Systemshell', ); $apiset->set_privilege( 'privilege-level' => "root" ); my $error_string; foreach my $binary (@binaries_list) { try { $apiset->rm( 'paths' => "$filer_binary_install_path/$binary", ); } catch NATE::BaseException with { my $err_obj = shift; my $output = $err_obj->text(); $error_string .= "* '$binary'" . " cmd output-> $output" if ( $output =~ /rm:\s+.+:\s+No\s+such\s+file\s+or\s+directory/i ); }; } if ( ( $nacltask_if_purged eq 'die' ) && ( defined($error_string) ) ) { $error_string = "Following binaries are not found on the filer\n" . $error_string; $Log->exit() if $may_exit; NATE::BaseException->throw("$error_string"); } else { $Log->debug('uninstall_binaries passed, all binaries were removed'); } $Log->exit() if $may_exit; return; } ## end sub uninstall_binaries =head2 rename_binaries NACL::MTask::BSDInstall->rename_binaries( command_interface => $ci, filer_binary_install_path => $filer_binary_install_path, #defaults to /mroot/test_binaries rename_mapping => {$oldname1 => $newname1, $oldname2 => $newname2,}, nacltask_verify => 1, #defaults to 1 ); (Class Method) This method can be used to rename the binary in filer. =over =item Options =over =item C<< "command_interface=>$Node" >> (Required) The command interface (NACL::C::CommandInterface object) of the filer on which this task is performed. =item C<< "filer_binary_install_path=>$filer_binary_install_path" >> (Optional) The path on the BSD shell of the filer where binary is located. Defaults to '/mroot/' =item C<< "rename_mapping=>{$oldname1 => $newname1}" >> (Required, Hashref) This hash reference contains the binary to be renamed and new name for the binary. If the user wants to rename the binary "binary_old" as "binary_new", the call should be in the form, NACL::MTask::BSDInstall->rename_binaries( command_interface => $ci, filer_binary_install_path => $filer_binary_install_path, rename_mapping => {'binary_old' => 'binary_new'}, ); =item C<< "nacltask_verify=>$verify" >> (Optional) This is a boolean value which is used to check whether the binary has been renamed. Defaults to 1. If the operation is not successful exception is raised to notify that the binary has not been renamed. =back =back =over =item Exceptions =over =item C<< NATE::BaseException >> This exception is thrown when =over =item * Binary to be renamed is not found on the filer =item * On failure of command execution =back =item C<< NACL::Exceptions::VerifyFailure >> This type of exception is thrown when verification fails for the renamed binaries. =back =back =cut sub rename_binaries { $Log->enter() if $may_enter; my ( $pkg, @args ) = @_; my %opts = validate_with( params => \@args, spec => { command_interface => { type => OBJECT, isa => 'NACL::C::CommandInterface' }, filer_binary_install_path => { type => SCALAR, default => $Default_Install_Path }, nacltask_verify => { type => SCALAR, default => 1 }, rename_mapping => { type => HASHREF }, }, ); my $ci = $opts{command_interface}; my $filer_binary_install_path = $opts{filer_binary_install_path}; my $nacltask_verify = $opts{nacltask_verify}; my $rename_mapping = $opts{rename_mapping}; #Create connection object my $api_set_obj = $ci->apiset( category => 'Node', interface => 'CLI', set => 'Systemshell', ); $api_set_obj->set_privilege( 'privilege-level' => "root" ); my $bad_binaries; # Rename the binaries foreach my $binary ( keys %{$rename_mapping} ) { my $list_output = $api_set_obj->execute_command( command => "ls -ls $filer_binary_install_path/$binary" ); $bad_binaries .= "* '$binary'" . " cmd output-> $list_output" if ( $list_output =~ /No\s+such\s+file\s+or\s+directory/i ); } if ( defined($bad_binaries) ) { $bad_binaries = "Following binaries are not found at filer binary install path\n" . $bad_binaries; $bad_binaries .= "rename_binaries failed, no binaries are renamed."; $Log->exit() if $may_exit; NATE::BaseException->throw($bad_binaries); } else { foreach my $binary ( keys %{$rename_mapping} ) { $api_set_obj->mv( 'force' => 1, 'source' => "$filer_binary_install_path/$binary", 'target' => "$filer_binary_install_path/$rename_mapping->{$binary}", ); } } # Verify the renamed binaries if ($nacltask_verify) { my $bad_binaries; foreach my $binary ( keys %{$rename_mapping} ) { my $verify_output = $api_set_obj->execute_command( command => "ls -ls $filer_binary_install_path/$rename_mapping->{$binary}" ); $bad_binaries .= $binary . "\n" if ( $verify_output =~ /No\s+such\s+file\s+or\s+directory/i ); } if ( defined($bad_binaries) ) { $bad_binaries = "Failed to rename following binaries:\n" . $bad_binaries; $Log->exit() if $may_exit; NACL::Exceptions::VerifyFailure->throw($bad_binaries); } else { $Log->debug('Renaming binaries went successful'); } } $Log->exit() if $may_exit; return; } ## end sub rename_binaries #=============================================================================== # Method-Name : new # Description : constructor #=============================================================================== sub new { my ( $pkg, @opts ) = @_; my %opts = validate_with( params => \@opts, spec => { command_interface => { type => OBJECT, isa => 'NACL::C::CommandInterface' }, binaries => { type => ARRAYREF, optional => 1 }, binaries_installed => { type => ARRAYREF, optional => 1 }, filer_binary_install_path => { type => SCALAR, optional => 1 }, }, ); my $self = bless {}, $pkg; while ( my ( $key, $value ) = each %opts ) { $self->$key($value); } return $self; } ## end sub new #=============================================================================== # Method-Name : _build_install_commands # Description : This method builds commands #=============================================================================== sub _build_install_commands { my ( $pkg, @args ) = @_; my %opts = validate( @args, { server => { type => SCALAR }, source_path => { type => SCALAR }, destination_path => { type => SCALAR }, binary => { type => SCALAR }, }, ); my $server = $opts{server}; my $source_path = $opts{source_path}; my $dest_path = $opts{destination_path}; my $binary = $opts{binary}; my $cmd = 'wget ' . $server . $source_path . '/' . $binary . ' -O ' . $dest_path . '/' . $binary; return $cmd; } ## end sub _build_install_commands #=============================================================================== # Method-Name : _handle_if_exists_action # Description : This method desides to throw exception or remove binary or copy # the binary based on value for nacltask_if_exists. #=============================================================================== sub _handle_if_exists_action { my ( $pkg, @args ) = @_; my %opts = validate( @args, { nacltask_if_exists => { type => SCALAR }, binaries_list => { type => ARRAYREF }, binaries_that_exist => { type => ARRAYREF }, binaries_to_copy => { type => ARRAYREF }, command_interface => { type => OBJECT, isa => 'NACL::C::CommandInterface' }, filer_binary_install_path => { type => SCALAR }, binaries_installed => { type => ARRAYREF }, }, ); my $nacltask_if_exists = $opts{nacltask_if_exists}; my $binaries_list = $opts{binaries_list}; my $binaries_that_exist = $opts{binaries_that_exist}; my $ci = $opts{command_interface}; my $binaries_to_copy = $opts{binaries_to_copy}; my $filer_binary_install_path = $opts{filer_binary_install_path}; my $binaries_installed = $opts{binaries_installed}; # Throw exception for existing binaries if nacltask_if_exists is die if ( ( @{$binaries_that_exist} ) && ( $nacltask_if_exists eq 'die' ) ) { my $error = "Following binaries are already found on the filer\n"; $error .= join( "\n", @{$binaries_that_exist} ); $Log->exit() if $may_exit; NATE::BaseException->throw("$error"); } if ( ( @{$binaries_that_exist} ) && ( $nacltask_if_exists eq 'purge' ) ) { my $api_set_obj = $ci->apiset( category => 'Node', interface => 'CLI', set => 'Systemshell', ); $api_set_obj->set_privilege( 'privilege-level' => "root" ); foreach my $binary ( @{$binaries_that_exist} ) { $api_set_obj->rm( 'force' => 1, 'paths' => "$Default_Install_Path/$binary", ); } push( @{$binaries_list}, @{$binaries_that_exist} ); } if ( ( @{$binaries_that_exist} ) && ( $nacltask_if_exists eq 'reuse' ) ) { foreach my $binary ( @{$binaries_that_exist} ) { if ( $filer_binary_install_path ne $Default_Install_Path ) { push @{$binaries_to_copy}, $binary; } else { push @{$binaries_installed}, $filer_binary_install_path . '/' . $binary; } } } return; } ## end sub _handle_if_exists_action #=============================================================================== # Method-Name : _check_for_files_exist_and_donot_exist # Description : This method checks whether the binary is already installed on the # filer. #=============================================================================== sub _check_for_files_exist_and_donot_exist { my ( $pkg, @args ) = @_; my %opts = validate( @args, { command_interface => { type => OBJECT, isa => 'NACL::C::CommandInterface' }, binaries_list_opts => { type => ARRAYREF }, binaries_that_exist => { type => ARRAYREF }, binaries_not_exist => { type => ARRAYREF }, } ); my $binaries_that_exist = $opts{binaries_that_exist}; my $binaries_not_exist = $opts{binaries_not_exist}; my $ci = $opts{command_interface}; my @binaries_list_opts = @{ $opts{binaries_list_opts} }; my $api_set_obj = $ci->apiset( category => 'Node', interface => 'CLI', set => 'Systemshell', ); foreach my $binary (@binaries_list_opts) { my $list_op = $api_set_obj->execute_command( command => "ls -ls $Default_Install_Path/$binary" ); if ( $list_op =~ /No\s+such\s+file\s+or\s+directory/i ) { push @{$binaries_not_exist}, $binary; } else { push @{$binaries_that_exist}, $binary; } } return; } ## end sub _check_for_files_exist_and_donot_exist # return web_server value based on smoke site SITE_FILE/SITE_WINDOWS mapping sub _get_web_server{ $Log->enter() if $may_enter; my ($pkg, @opts) = @_; my %args = Params::Validate::validate_with( params => \@opts, spec => { node => {isa => 'NACL::C::Node' }, }, ); my $node = delete $args{node}; my $node_name = $node->node(); #============================================================= # Step-1: find out which site we are in my $host = $node->hostrec(); # 1: try and guess the site my $site = TestUtils::guess_site($host); if (!defined $site or (defined $site and $site eq '')) { # no site was returned? throw NATE::BaseException( "TestUtils::guess_site() returned nothing for 'site'!\n" . "I don't know where to get the binary from.\n" ); } $Log->debug("\nNode $node_name seems to be at site [$site]\n"); #============================================================= # Step-2: get general site info my %SiteInfo = &_get_site_info(); my @sites = keys %SiteInfo; $Log->debug(sub { "\nList of available sites:\n" . Dumper(\@sites) . "\n" }); if (!@sites) { # no sites were returned? throw NATE::BaseException( "$pkg::&_get_site_info() returned nothing!\n" ); } #============================================================= # Step-3: pull the web server info my $local_site_data = $SiteInfo{$site}; $Log->debug(sub { "\nSite info for site $site:\n" . Dumper($local_site_data) . "\n" }); if (!defined $$local_site_data{install_proto} or !defined $$local_site_data{install_server}) { throw NATE::BaseException( "$pkg::&_get_site_info() returned 'undefined' for " . "'install_proto' and/or 'install_server'.\n" . "Please check file pointed by SITE_FILE/SITE_FILE_WINDOWS\n". " or TestUtils/site_info.dat for these values for site [$site]\n". "List of available sites\n". Dumper(\@sites) . "\n" ); } #============================================================= # Step-4: build the web server string and save it my $web_server = $local_site_data->{install_proto} . "://"; $web_server .= $local_site_data->{install_server}; $Log->debug("\nTestUtils says the web server root is [$web_server]\n"); unless ( defined $web_server and $web_server ne '' ) { throw NATE::BaseException( "BSDInstall::_get_web_server() - failed to get web server root" . " for node [$node_name] at site [$site]\n" ); } $Log->exit() if $may_exit; return $web_server; } ## end sub _get_web_server_root sub _get_site_info { $Log->enter() if $may_enter; my ($file, $return,); our %Siteinfo = (); # retrieve site file location if ( $^O =~ /win32/i) { $file = NATE::ParamSet::param_global()->get('SITE_FILE_WINDOWS'); } else { $file = NATE::ParamSet::param_global()->get('SITE_FILE'); } unless ( defined $file ) { $file = 'TestUtils/site_info.dat'; } my $code = NATE::Inc::get_file($file); if (!defined $code) { $Trace->fatal( result => "CONFIG", msg => "Could not find SITE_FILE '$file'\n" ); } eval $code; if ($@) { $Trace->fatal( result => "CONFIG", msg => "Could not eval SITE_FILE '$file': $@\n" ); } if (!keys %Siteinfo) { $Trace->fatal( result => "CONFIG", msg => "SITE_FILE '$file' did not have a \%Siteinfo hash\n" ); } $Trace->trace(msg => "Read site file: " . $file); # return site content as hash $Trace->debug(msg => "Site Info: " . Dumper(\%Siteinfo)); $Log->exit() if $may_exit; return %Siteinfo; } ## end sub _get_site_info 1;