# # Copyright (c) 2011-2013 NetApp, Inc., All Rights Reserved # Any use, modification, or distribution is prohibited # without prior written consent from NetApp, Inc. # ## @summary Volume inplace-upgrade task module ## @author bruce.blinn@netapp.com ## @status shared ## @pod here package NACL::STask::Volume64bitUpgrade; use strict; use warnings; use base qw(NACL::C::Volume64bitUpgrade NACL::STask::STask); use Data::Dumper; use NATE::Log qw(log_global); my $Log = log_global(); my $may_enter = $Log->may_enter(); my $may_exit = $Log->may_exit(); use Params::Validate qw(validate SCALAR); use NATE::Exceptions::Argument qw(:try); use NACL::APISet::Exceptions::TimeoutException; use NACL::C::Volume; use NACL::CS::StorageAggregate64bitUpgrade; use NACL::CS::Volume64bitUpgrade; # # This method returns the state information for the inplace-upgrade on a # volume. # sub _vol_64bit_upgrade_status { $Log->enter() if $may_enter; my $pkg_or_obj = shift; my $pkg = ref($pkg_or_obj) || $pkg_or_obj; my %opts = $pkg_or_obj->_common_validate_with(params => \@_); my $ci = $opts{command_interface}; my $CS_pkg = $pkg->get_CS_package_name(); my %common_opts = %opts; delete $common_opts{volume}; delete $common_opts{vserver}; my %filter; if ($ci->is_7mode()) { my $vol_cs = NACL::CS::Volume->fetch( %common_opts, command_interface => $ci, filter => { volume => $opts{volume}, vserver => $opts{vserver}, }, ); $filter{aggregate} = $vol_cs->aggregate(); } my $vol_info = NACL::CS::Volume64bitUpgrade->fetch( %common_opts, command_interface => $ci, filter => { vserver => $opts{vserver}, %filter }, ); $Log->exit() if $may_exit; return $vol_info; } # The large default value for the method-timeout (2 hours) was chosen because # the timeout should not occur unless there is a problem with the product or # test (something for which you would file a BURT). The method-timeout option # allows the caller to change this value to suit their needs. use constant DEFAULT_TIMEOUT => 7200; use constant POLL_DELTA => 5; sub wait_for_ipu { $Log->enter() if $may_enter; my $pkg_or_obj = shift; my $pkg = ref($pkg_or_obj) || $pkg_or_obj; my %opts = $pkg_or_obj->_common_validate_with( params => \@_, additional_spec => { percent_complete => { type => SCALAR, default => 100 }, polling_interval => { type => SCALAR, default => POLL_DELTA }, }, allow_extra => 1, ); my $percent_complete = delete $opts{percent_complete}; my $polling_interval = delete $opts{polling_interval}; my $timeout = $opts{"method-timeout"} || DEFAULT_TIMEOUT; my $endtime = time() + $timeout; if (($percent_complete < 0) || ($percent_complete > 100)) { $Log->exit() if $may_exit; NATE::Exceptions::Argument->throw( "The \"percent_complete\" option should be in the range 0-100."); } while (time() < $endtime) { my $vol_info = $pkg->_vol_64bit_upgrade_status(%opts); my $cur_progress = $vol_info->scan_percent_completed(); $Log->trace("wait_for_ipu(): current progress = \"$cur_progress\""); # A hyphen implies the upgrade is not running, so it is either not # started or already finished. if (($cur_progress eq "-") || ($cur_progress eq "")) { if ($vol_info->format() eq "64-bit") { $Log->exit() if $may_exit; return 1; } $cur_progress = 0; } $cur_progress =~ s/%//; if ($cur_progress >= $percent_complete) { $Log->exit() if $may_exit; return 1; } Tharn::sleep($polling_interval); } $Log->exit() if $may_exit; NACL::APISet::Exceptions::TimeoutException->throw( "Timed out waiting for inplace-upgrade to complete on " . "volume \"$opts{volume}\"."); } sub _get_format { $Log->enter() if $may_enter; my $pkg_or_obj = shift; my $pkg = ref($pkg_or_obj) || $pkg_or_obj; my %opts = $pkg_or_obj->_common_validate_with(params => \@_); my $vol_info = $pkg->_vol_64bit_upgrade_status(%opts); my $format = $vol_info->format(); $Log->exit("$format"); return $format; } sub is_32bit_format { _get_format(@_) eq "32-bit" ? 1 : 0 } sub is_64bit_format { _get_format(@_) eq "64-bit" ? 1 : 0 } sub is_mixed_format { _get_format(@_) eq "upgrading" ? 1 : 0 } =head1 NAME NACL::STask::Volume64bitUpgrade =head1 DESCRIPTION This module provides the task layer methods for controlling inplace-upgrade (IPU) on a volume. IPU is the online conversion of 32-bit block numbers to 64-bit block numbers. This module inherits from L. =head1 METHODS =head2 wait_for_ipu $ipu_obj->wait_for_ipu( percent_complete => $percent, polling_interval => $interval, "method-timeout" => $timeout, ); NACL::STask::Volume64bitUpgrade->wait_for_ipu( command_interface => $command_interface, volume => $volume_name, vserver => $vserver_name, percent_complete => $percent, polling_interval => $interval, "method-timeout" => $timeout, ); This method will wait for the inplace-upgrade to complete or to reach the specified percentage of completion. When waiting for the upgrade to reach a certain percentage of completion, there are a few situations where this method may not behave as expected. 1. If the volume is small and there is not much work for the upgrade to do, the upgrade can complete before this method has had a chance to check on the progress. You may be able to solve this by slowing the upgrade scanner while this method is executing: $nodescope_or_7mode_apiset->wafl_scan_speed(speed => 10); 2. If there are very few files in the volume, there will not be much for the upgrade to do and the granularity of the scan percentage will be large, thus, the scan percentage can jump in large increments. Adding more files will reduce or eliminate this problem. 3. This method checks the progress of the upgrade every few seconds (see the polling_interval option). Due to the two problems mentioned above, this could be long enough for the scan to complete unexpectedly in some situation. =over =item Options =over =item C<< command_interface => $command_interface >> (Required for class method, not applicable for instance method.) See L. =item C<< volume => $volume_name >> (Required for class method, not applicable for instance method.) This is the name of the volume where the upgrade scanner is running. =item C<< vserver => $vserver_name >> (Required for class method, not applicable for instance method.) This is the name of the vserver containing the volume. =item C<< percent_complete => $percent >> (Optional) If this option is specified, it is the percent of completion of the upgrade that you want to wait for (it should not include a percent sign). If this option is not specified, this method will wait until the upgrade scan is 100% complete. This method will wait until the upgrade progress meets or exceeds the specified percentage, and then it returns. It will return upon completion or throw an exception if the timeout is exceeded. =item C<< polling_interval => $interval >> (Optional) This method checks the progress of the upgrade every few seconds. This option allows you to specify how many seconds to wait between checks. If this option is not specified, it will check every five seconds. =item C<< "method-timeout" => $timeout >> (Optional) This is the maximum number of seconds to wait for the upgrade to complete. If the timeout is exceeded, this method will throw a NACL::APISet::Exceptions::TimeoutException exception. If this parameter is not specified, the timeout will be 7200 seconds. =back =over =item Exceptions =over =item C This type of exception is thrown when percent complete value is not in the range of 0-100. =item C This type of exception is thrown when inplace-upgrade on volume has not completed with in $timeout seconds. =back =head2 is_32bit_format $ipu_obj->is_32bit_format(); NACL::STask::Volume64bitUpgrade->is_32bit_format( command_interface => $command_interface, volume => $volume_name, vserver => $vserver_name, ); This method will return true if the volume is using 32-bit block numbers; otherwise, it will return false, which implies the volume is either 64-bit or mixed format. =over =item Options =over =item C<< command_interface => $command_interface >> (Required for class method, not applicable for instance method.) See L. =item C<< volume => $volume_name >> (Required for class method, not applicable for instance method.) This is the name of the volume where you want to check the format. =item C<< vserver => $vserver_name >> (Required for class method, not applicable for instance method.) This is the name of the vserver containing the volume. =back =back =head2 is_64bit_format $ipu_obj->is_64bit_format(); NACL::STask::Volume64bitUpgrade->is_64bit_format( command_interface => $command_interface, volume => $volume_name, vserver => $vserver_name, ); This method will return true if the volume is using 64-bit block numbers; otherwise, it will return false, which implies the volume is either 32-bit or mixed format. =over =item Options =over =item C<< command_interface => $command_interface >> (Required for class method, not applicable for instance method.) See L. =item C<< volume => $volume_name >> (Required for class method, not applicable for instance method.) This is the name of the volume where you want to check the format. =item C<< vserver => $vserver_name >> (Required for class method, not applicable for instance method.) This is the name of the vserver containing the volume. =back =back =head2 is_mixed_format $ipu_obj->is_mixed_format(); NACL::STask::Volume64bitUpgrade->is_mixed_format( command_interface => $command_interface, volume => $volume_name, vserver => $vserver_name, ); This method will return true if the volume is using a combination of 32 and 64-bit block numbers; otherwise, it will return false, which implies the volume is either completely 32 or 64-bit format. =over =item Options =over =item C<< command_interface => $command_interface >> (Required for class method, not applicable for instance method.) See L. =item C<< volume => $volume_name >> (Required for class method, not applicable for instance method.) This is the name of the volume where you want to check the format. =item C<< vserver => $vserver_name >> (Required for class method, not applicable for instance method.) This is the name of the vserver containing the volume. =back =back =cut 1;