# # Copyright (c) 2013 NetApp, Inc., All Rights Reserved # Any use, modification, or distribution is prohibited # without prior written consent from NetApp, Inc. # ## @summary Inplace-upgrade Task Module ## @author bruce.blinn@netapp.com ## @status shared ## @pod here package NACL::STask::StorageAggregate64bitUpgrade; use strict; use warnings; use base qw(NACL::C::StorageAggregate64bitUpgrade NACL::STask::STask); use Data::Dumper; use Params::Validate qw(validate SCALAR); use NATE::Exceptions::Argument qw(:try); use NACL::APISet::Exceptions::TimeoutException; use NATE::Log qw(log_global); my $Log = log_global(); my $may_enter = $Log->may_enter(); my $may_exit = $Log->may_exit(); # 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; my $CS_pkg = $pkg->get_CS_package_name(); my %common_opts = %opts; delete $common_opts{aggregate}; 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) { if ($percent_complete < 100) { my $aggr_info = $CS_pkg->fetch( %common_opts, filter => {aggregate => $opts{aggregate}}, ); my $cur_progress = $aggr_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 ($aggr_info->format() eq "64-bit") { # Don't care if the volumes are not complete in this case # because the caller is not waiting for 100% complete. $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; } } else { # The aggregate and its volumes may not all finish at the same # time, so you have to check them all; the following method does # that. if ($pkg->is_64bit_format(%opts)) { $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 " . "aggregate \"$opts{aggregate}\"."); } 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 %common_opts = %opts; delete $common_opts{aggregate}; # Get the aggregate state information. my $aggr_info = $pkg->get_CS_package_name()->fetch( %common_opts, filter => { aggregate => $opts{aggregate}, 'include-all-volumes' => "true"}, ); # Get format of aggregate. my $format = $aggr_info->format(); # Compare with the format of each volume in the aggregate. foreach my $vol ($aggr_info->volumes_64bit()) { if ($vol->format() ne $format) { $Log->exit("upgrading"); return "upgrading"; } } $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::StorageAggregate64bitUpgrade =head1 DESCRIPTION This module provides the task layer methods for controlling inplace-upgrade (IPU) on an aggregate. 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::StorageAggregate64bitUpgrade->wait_for_ipu( command_interface => $command_interface, aggregate => $aggr_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 aggregate 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 volumes and files in the aggregate, 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 problem 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<< aggregate => $aggr_name >> (Required for class method, not applicable for instance method.) This is the name of the aggregate where the upgrade scanner is running. =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 =back =over =item Exceptions =over =item C This type of exception is thrown when percentage of completion option is not in the range of 0-100. =back =back =cut =head2 is_32bit_format $ipu_obj->is_32bit_format(); NACL::STask::StorageAggregate64bitUpgrade->is_32bit_format( command_interface => $command_interface, aggregate => $aggr_name, ); This method will return true if the aggregate and all its volumes are using 32-bit block numbers; otherwise, it will return false, which implies the aggregate 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<< aggregate => $aggr_name >> (Required for class method, not applicable for instance method.) This is the name of the aggregate where you want to check the format. =back =back =cut =head2 is_64bit_format $ipu_obj->is_64bit_format(); NACL::STask::StorageAggregate64bitUpgrade->is_64bit_format( command_interface => $command_interface, aggregate => $aggr_name, ); This method will return true if the aggregate and all its volumes are using 64-bit block numbers; otherwise, it will return false, which implies the aggregate 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<< aggregate => $aggr_name >> (Required for class method, not applicable for instance method.) This is the name of the aggregate where you want to check the format. =back =back =cut =head2 is_mixed_format $ipu_obj->is_mixed_format(); NACL::STask::StorageAggregate64bitUpgrade->is_mixed_format( command_interface => $command_interface, aggregate => $aggr_name, ); This method will return true if the aggregate or any its volumes are using a combination of 32 and 64-bit block numbers; otherwise, it will return false, which implies the aggregate 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<< aggregate => $aggr_name >> (Required for class method, not applicable for instance method.) This is the name of the aggregate where you want to check the format. =back =back =cut 1;