# $Id: $ # # Copyright (c) 2013 NetApp, Inc., All Rights Reserved # Any use, modification, or distribution is prohibited # without prior written consent from NetApp, Inc. # ## @summary LunIgroup Task Module ## @author kathar.hidayath@netapp.com, dl-nacl-dev ## @status shared ## @pod here package NACL::STask::LunIgroup; use strict; use warnings; use base qw(NACL::C::LunIgroup NACL::STask::STask); 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 BOOLEAN SCALARREF); use NACL::C::Exceptions::LunIgroup::AlreadyExists (); use NACL::C::Exceptions::LunIgroup::DoesNotExist (); use NATE::Exceptions::Argument qw(:try); use NACL::APISet::Exceptions::ResponseException (); use NACL::Exceptions::VerifyFailure (); use NACL::ComponentUtils qw (_optional_scalars Dumper); use NACL::STask::Lun; use NACL::C::LunMapped; use NACL::C::Lun; =head1 NAME NACL::STask::LunIgroup =head1 DESCRIPTION C provides a number of well-defined but potentially complex or multi-step methods related to LunIgroup in ONTAP. It is created on top of C component Since it is derived class of C, we can use all the methods of C from the object of this task. =head1 ATTRIBUTES =head2 command_interface (Required) A component object that represents the node to which to send commands See L. =head2 vserver (Required) The name of the Vserver to be used =head2 igroup (Required) Name of the igroup to be created =head1 METHODS =head2 create my $igroup_obj = NACL::STask::LunIgroup->create( 'command_interface' => $ci, 'vserver' => $vserver, 'igroup' => $igroup, 'nacltask_if_exists' => $action, # default die %other_options, ); (Class Method) This method is used to create an lun igroup. If igroup already exists, it will perform the action based on "nacltask_if_exists" parameter. Default behavior would be "die". It returns the Task object for the created igroup. Uses CMode CLI/ZAPI, 7Mode CLI. =over =item Options =over =item C<< command_interface => $command_interface >> (Required) See L =item C<< 'vserver' => $vserver >> (Required) Name of the vserver to be used. =item C<< 'igroup' => $igroup >> (Required) Name of the igroup to be created =item C<< apiset_must => $ruleset >> (Optional) See L =item C<< apiset_should => $ruleset >> (Optional) See L =item C<< "nacltask_if_exists => $action" >> (Optional) What to do if the igroup to be created already exists. If $action is "die", then fail with an exception. If action is "purge", then purge the igroup(see the "purge" method, below) before creating a new one. If $action is "reuse", It will return the object of existing lun igroup. =item C<< "nacltask_verify => $action" >> (Optional) The user of this library can specify to verify whether the igroup is created or not. If the action is 0, which is default, it wont verify the creation. If the user sets the action to 1, it will verify the it using the component state of this library. =item C<< "_was_created => \$scalar" >> (Optional) When this option is provided with a reference to a scalar variable, the variable gets filled in with a boolean value describing whether the igroup was available (value will be 0; this scenario is possible when if_exists => "reuse") or whether the igroup was created (value will be 1). This is necessary to determine whether the lun igroup needs to be cleaned up later. my $was_created; my $igroup_obj = NACL::STask::LunIgroup->create( vserver => $vserver_name, igroup => $igroup, $nacltask_if_exists => 'reuse', _was_created => \$was_created, nacltask_to_cleanup => $boolean, %other_opts ); # Operate on $igroup_obj here # ... # Now determine whether to clean up the igroup, since we're not sure # whether we reused an existing igroup or created a new one if ($was_created) { # New lun igroup was created. Clean it up. $igroup_obj->purge(); } =item C<< nacltask_to_cleanup => 0|1 >> (Optional, defaults to 0(no to cleanup)) Flag indicating if this operation is to be cleaned up or not. =item C<< nacltask_cleanup_manager >> Cleanup manager to use for registering. Default : Will use the default cleanup manager. command_interface, apiset_must, apiset_should, mode, etc. All of the other various options to L<< NACL::C::LunIgroup->create|lib-NACL-C-LunIgroup-pm/create >> =back =over =item Exceptions =over =item C This type of exception is thrown when an attempt is made to create lun igroup that already exists. =item C This type of exception is thrown when verification fails for the created lun igroup. =back =cut sub create { $Log->enter() if $may_enter; my $pkg = shift; my %opts = $pkg->_common_validate_with( params => \@_, additional_spec => { nacltask_if_exists => $pkg->_if_exists_validate_spec(), nacltask_verify => { type => BOOLEAN, default => 0 }, _was_created => { type => SCALARREF, optional => 1 }, $pkg->_cleanup_validate_spec(), }, allow_extra => 1 ); # Transform %opts from the options we received into the options to # pass to the base class method. my ( $self, %common_opts, %nacltask_opts ); $pkg->_copy_common_component_params_with_ci( source => \%opts, target => \%common_opts ); my ( %opts_for_cleanup, %opts_for_register, $nacltask_to_cleanup ); $pkg->_move_common_cleanup_opts( source => \%opts, target => \%opts_for_cleanup, ); $pkg->_move_nacltask_options( source => \%opts, target => \%nacltask_opts ); my $was_created = delete $opts{_was_created}; $$was_created = 0; my $if_exists = $nacltask_opts{'nacltask_if_exists'}; my $verify = $nacltask_opts{'nacltask_verify'}; CREATE: { use warnings; try { $self = $pkg->SUPER::create(%opts); $$was_created = 1; } catch NACL::C::Exceptions::LunIgroup::AlreadyExists with { my $exception = shift; $Log->debug("The Igroup already Exists!"); $self = $pkg->_element_exists_handler( create_opts => \%opts, nacltask_if_exists => $if_exists, exception => $exception ); if ( !$self ) { no warnings qw(exiting); redo CREATE; } }; } if ($verify) { $pkg->verify_state(%opts); } # Register this resource with the Cleanup Manager for cleanup $pkg->_copy_common_opts_for_cleanup( 'source' => {%opts, %opts_for_cleanup}, 'target' => \%opts_for_register, 'nacltask_to_cleanup' => \$nacltask_to_cleanup, 'to_cleanup' => 'purge' ); $pkg->_register_for_cleanup(%opts_for_register) if ($nacltask_to_cleanup && $$was_created); $Log->exit() if $may_exit; return $self; } ## end sub create =head2 purge $igroup_obj->purge(); (or) NACL::STask::LunIgroup->purge( 'command_interface' => $ci, 'vserver' => $vserver_name, 'igroup' => $igroup, 'nacltask_verify' => 1, ); (Class or instance method) This method is used to delete the lun igroup. If the igroup is lun mapped, this method will unmap the lun and then will purge the igroup. Uses a CMode CLI/ZAPI, 7Mode CLI APISet. =over =item Options =over =item C<< command_interface => $ci >> (Required for class method, Not Applicable for instance method) A component object that represents the host which to send commands. See NACL::C::Component::command_interface =item C<< 'vserver' => $vserver >> (Required for class method, Not Applicable for instance method) Name of the vserver to be used. =item C<< 'igroup' => $igroup >> (Required for class method, Not Applicable for instance method) Name of the igroup to be deleted =item C<< nacltask_verify => $nacltask_verify_boolean >> (Optional) If '0' (default), verification will not be performed. If '1', verification will be performed to ensure that the deletion did happen successfully. =item C<< _was_deleted => \$scalar >> (Optional) When this option is provided a reference to a scalar variable, the variable gets filled in with a boolean value describing whether the igroup did not exist (value will be 0; this scenario is possible when nacltask_if_purged => "pass") or whether the igroup was deleted (value will be 1). =item C<< nacltask_if_purged => $nacltask_if_purged >> (Optional) If 'pass' (default), It will pass if the igroup is already deleted. If 'fail', It will fail if the igroup is already deleted. All of the other various options to L<< NACL::C::LunIgroup->delete|lib-NACL-C-LunIgroup-pm/delete >> =back =over =item Exceptions =over =item C This type of exception is thrown when an attempt is made to delete lun igroup that does not exists. =item C This type of exception is thrown when verification fails for the deleted lun igroup. =back =cut sub purge { $Log->enter() if $may_enter; my $pkg_or_obj = shift; my %orig_opts = @_; my $additional_spec = { nacltask_verify => { type => BOOLEAN, default => 0 }, nacltask_if_purged => { type => SCALAR, default => 'pass' }, _was_deleted => { type => SCALARREF, optional => 1 }, }; # Throw away options specific to the task $pkg_or_obj->_hash_move( source => \%orig_opts, target => {}, move => [ keys %{$additional_spec} ] ); my %opts = $pkg_or_obj->_common_validate_with( params => \@_, additional_spec => $additional_spec, ); my %common_opts; $pkg_or_obj->_copy_common_component_params_with_ci( source => \%opts, target => \%common_opts ); my $if_purged = delete $opts{nacltask_if_purged}; my $was_deleted = delete $opts{_was_deleted}; $$was_deleted = 0; AGAIN: { use warnings qw(exiting); try { $pkg_or_obj->SUPER::delete( force => 'true', %common_opts, %orig_opts ); $$was_deleted = 1; } catch NACL::C::Exceptions::LunIgroup::DoesNotExist with { my $exception = shift; $Log->debug("Entry Does Not Exists!"); if ( $if_purged !~ /pass/i ) { $Log->exit() if $may_exit; $exception->throw(); } } catch NACL::C::Exceptions::LunIgroup::MapExists with { my $exception = shift; my $map_obj = NACL::C::LunMapped->find( %common_opts, filter => { igroup => $orig_opts{'igroup'} }, ); NACL::STask::Lun->unmap( %common_opts, %orig_opts, lun => $map_obj->lun(), volume => $map_obj->volume(), ); no warnings qw(exiting); redo AGAIN; }; } if ( $opts{nacltask_verify} ) { $pkg_or_obj->_generic_purge_verify(%orig_opts); } $Log->exit() if $may_exit; } ## end sub purge # For 'add' functionality __PACKAGE__->create_method_builder(c_method_name => "add", stask_method_name => "add"); # For 'remove' functionality __PACKAGE__->purge_method_builder( c_method_name => "remove", stask_method_name => "remove"); # For 'bind' functionality __PACKAGE__->create_method_builder(c_method_name => "bind", stask_method_name => "bind", c_exception_name => 'AlreadyBound'); # For 'unbind' functionality __PACKAGE__->purge_method_builder(c_method_name => "unbind", stask_method_name => "unbind", c_exception_name => 'NotBound'); =head2 parents @parents = $Igroup_obj->parents(); ( Class or Instance method ) This method returns the list containing the names of the parent objects of this resource. Used for finding dependencies between resources. =cut sub parents { $Log->enter() if $may_enter; $Log->exit() if $may_exit; return qw(NACL::STask::Vserver); } 1;