# Copyright (c) 2013 NetApp, Inc., All Rights Reserved # Any use, modification, or distribution is prohibited # without prior written consent from NetApp, Inc. # ## @summary Aggregate Fill Upto Percentage Task Module ## @author rbasavar@netapp.com ## @status shared ## @pod here package NACL::MTask::AggregateGrowth; use strict; use warnings; use base qw(NACL::STask::Aggregate); 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 :types); use NACL::STask::Aggregate; use NACL::CS::Aggregate; use NATE::BaseException qw(:try); use NACL::STask::Volume; use NACL::STask::Vserver; use NACL::ComponentUtils qw(Dumper); use Class::MethodMaker [ scalar => 'vserver', scalar => 'percent_to_fill', scalar => 'aggregate', ]; =head1 NAME NACL::MTask::AggregateGrowth =head1 DESCRIPTION C This task is used to create aggregate and fill aggregate with volumes to specified percentage. It can be also used to modify the percentage space to be filled in same Aggregate. Maximum value that can be passed nacltask_percent_to_fill is 97 , based on assumption that we can not fill 100% of aggregate since some space is used for aggregate snapshots and volume metadata . If any value which does not exceed 20mb is passed , Command Failed Exception is thrown. Eg : If value passed is 1% and 1% of size of aggregate is not more than 20mb , CommanFailed Exception is thrown. =head1 METHOD : create_and_fill =head2 Usage use NACL::MTask::AggregateGrowth; my $aggr_obj = NACL::MTask::AggregateGrowth->create_and_fill( command_interface => $command_interface, aggregate => $aggregate, diskcount => $num_disks, nacltask_percent_to_fill => $percent, %other_options ); (Class method) Creates an aggregate and fills it with volume upto some percentage specified as a parameter . =head2 Parameters =over =item C<< command_interface => $command_interface >> (Required) As C. A component object that represents the host to which to send commands. =item C<< aggregate => $aggregate >> (Optional) If this is not specified, a random name is generated using L. =item C<< diskcount => $diskcount >> (Optional) If both diskcount and disklist are not specified, diskcount will be autoassigned based on the raidtype(when raidtype is not specified, 'raid_dp' will be considered as default). =item C<< percent_to_fill => $percent >> (Required) This attribute reprsents the percentage of total size of aggregate which needs to be filled before returning Aggregate Object . For eg: If value of this attribute passed as 50% and aggregate is of size 2gb , an aggregate object is returned with 1 gb filled in it . =item C<< other_options => %other_options >> These are the options which will be passed to L. These are apiset_must, apiset_should, method-timeout etc . =back =head2 Returns: Aggregate Object with specified percent filled. =head2 Exceptions: Throws the following exceptions directly: NACL::Exceptions::MissingArg and other exceptions as well. =cut sub create_and_fill { $Log->enter() if $may_enter; my ( $pkg, @args ) = @_; my %opts = $pkg->_common_validate_with( params => \@args, additional_spec => { percent_to_fill => { type => SCALAR, optional => 0 }, }, allow_extra => 1, ignore_primary_keys => 1, ); my ( $percent, $command_interface, $aggr_obj, $vs_obj, $volume_size, $vol_obj, $self ); $percent = delete $opts{percent_to_fill}; if ( $percent > 97 ) { $Log->exit() if $may_exit; NATE::BaseException->throw( "Error: Given percent to fill number must " . "be less than 97. You gave $percent" ); } ## end if ( $percent_to_fill ...) $command_interface = $opts{command_interface}; $aggr_obj = NACL::STask::Aggregate->create(%opts); $volume_size = int( $aggr_obj->state->size() * ( $percent / 100 ) ); if ( $volume_size < 20971520 ) { $Log->exit() if $may_exit; $aggr_obj->purge(); NATE::BaseException->throw( "Percentage passed is too small to create Volume"); } $vs_obj = NACL::STask::Vserver->create( command_interface => $command_interface, aggregate => $aggr_obj->aggregate ); $volume_size = $volume_size - $aggr_obj->state->usedsize(); NACL::STask::Volume->create( command_interface => $command_interface, vserver => $vs_obj->vserver, size => $volume_size, aggregate => $aggr_obj->aggregate, ); $opts{aggregate} = $aggr_obj->aggregate; $opts{percent_to_fill} = $percent; $opts{vserver} = $vs_obj->vserver; my %args; $pkg->_hash_copy( source => \%opts, copy => [qw(vserver aggregate command_interface)], target => \%args, ); $self = $pkg->new(%args); $Log->exit() if $may_exit; return $self; } =head1 METHOD : modify =head2 Usage $aggr_obj->modify( nacltask_percent_to_fill => $percent,); (Instance method) Modifies percentage of Aggregate to be filled . =head2 Parameters =over =item C<< percent_to_fill => $percent >> (Required) This attribute reprsents the percentage of total size of aggregate which needs to be filled . For eg: If value of this attribute passed as 50% and aggregate is of size 2gb , an aggregate object is returned with 1 gb filled in it . =back =head2 Returns: None. =head2 Exceptions: Throws the following exceptions directly: NACL::Exceptions::MissingArg and other exceptions as well. =cut sub modify { $Log->enter() if $may_enter; my ( $pkg, @args ) = @_; my %opts = $pkg->_common_validate_with( params => \@args, additional_spec => { percent_to_fill => { type => SCALAR, optional => 0 }, }, allow_extra => 1, ignore_primary_keys => 1, ); my ( $vserver, $command_interface, $percent, $vs_obj, $volume_size ); $opts{vserver} = $pkg->vserver; $opts{aggregate} = $pkg->aggregate; $command_interface = $opts{command_interface}; $percent = $opts{percent_to_fill}; if ( $percent > 97 ) { $Log->exit() if $may_exit; NATE::BaseException->throw( "Error: Given percent to fill number must " . "be less than 97. You gave $percent" ); } ## end if ( $percent_to_fill ...) my $aggr_obj = NACL::CS::Aggregate->fetch( command_interface => $command_interface, filter => { aggregate => $opts{aggregate}, }, requested_fields => [qw(size usedsize percent-used availsize)], ); $volume_size = int( $aggr_obj->size() * ( $percent / 100 ) ); if ( $volume_size < 20971520 ) { $Log->exit() if $may_exit; $aggr_obj->purge(); NATE::BaseException->throw( "Percentage passed is too small to create Volume"); } $vserver = $opts{vserver}; NACL::STask::Vserver->purge( command_interface => $command_interface, vserver => $vserver, ); $vs_obj = NACL::STask::Vserver->create( command_interface => $command_interface, aggregate => $opts{aggregate}, vserver => $vserver, ); $aggr_obj = NACL::CS::Aggregate->fetch( command_interface => $command_interface, filter => { aggregate => $opts{aggregate}, }, requested_fields => [qw(size usedsize percent-used availsize)], ); $volume_size = int( $aggr_obj->size() * ( $percent / 100 ) - $aggr_obj->usedsize()); NACL::STask::Volume->create( command_interface => $command_interface, vserver => $vs_obj->vserver, size => $volume_size, aggregate => $opts{aggregate}, ); $Log->exit() if $may_exit; } =head1 METHOD : purge =head2 Usage $aggr_obj->purge(); (Instance method) Deletes the aggregate , vserver and volumes created by create_and_fill method . =head2 Parameters None =head2 Returns: None. =head2 Exceptions =over =item C This type of exception is thrown when verification fails for the deleted aggregate. =item C This type of exception is thrown when vserver has volumes on another aggregate. =back =cut sub purge { $Log->enter() if $may_enter; my $aggr_obj = shift; my ( $vserver, $aggregate, $command_interface ); $vserver = $aggr_obj->vserver; $aggregate = $aggr_obj->aggregate; $command_interface = $aggr_obj->command_interface; NACL::STask::Vserver->purge( command_interface => $command_interface, vserver => $vserver, ); NACL::STask::Aggregate->purge( command_interface => $command_interface, aggregate => $aggregate, ); $Log->exit() if $may_exit; } sub new { my ( $pkg, %opts ) = @_; my $self = bless {}, $pkg; while ( my ( $key, $value ) = each %opts ) { $self->$key($value); } return $self; } 1;