# # # Copyright (c) 2009-2011 NetApp Inc. # All rights reserved. # ## @summary Provide an exception class that is a subclass of ## NATE::BaseException that will be thrown when an aggregate ## cannot be purged because it has a root volume of a vserver ## which has volumes on another aggregate ## ## @author dl-nacl-dev@netapp.com ## @status Shared ## @pod here =head1 NAME NACL::Exceptions::VserverHasVolumesOnAnotherAggregate =head1 DESCRIPTION NACL::STask::Aggregate->purge() fails when the aggregate contains the root volume of a vserver which has volumes on another aggregate. (This is because to purge a root-volume we need to be delete all the other volumes in that vserver first, but deleting volumes on another aggregate is stepping outside the scope of Aggregate->purge) =head1 EXAMPLES =head2 Throwing exception use NACL::Exceptions::VserverHasVolumesOnAnotherAggregate qw(:try); # $error_text should ideally also contain the vserver name, the # aggregate name and the volumes on that vserver NACL::Exceptions::VserverHasVolumesOnAnotherAggregate->throw( text => $error_text, command_interface => $command_interface, volumes => \@names_of_volumes_on_vserver, vserver => $vserver_name, aggregate => $aggregate_name ); =head2 Catching and handling exception use NACL::Exceptions::VserverHasVolumesOnAnotherAggregate qw(:try); try { NACL::STask::Aggregate->purge(%opts); } catch NACL::Exceptions::VserverHasVolumesOnAnotherAggregate with { my $e = shift; $Log->comment("Error was:\n" . $e->text()); # Extracting the details of the volumes on the vserver which are # on another aggregate my @volumes_details = $e->volumes(); foreach my $single_volume (@volumes_details) { $Log->comment('Volume ' . $single_volume->{volume} . 'is on ' . 'aggregate ' . $single_volume->{aggregate}); } # This is not necessarily how it *has* to be handled but is # just an example of how it could be handled. # Here we're going to purge the vserver and then re-try the purge NACL::STask::Vserver->purge( command_interface => $e->command_interface(), vserver => $e->vserver() ); NACL::STask::Aggregate->purge(%opts); }; =head1 ATTRIBUTES The values of each of the attributes can be accessed using the accessor methods. Using the C attribute as an example, its value can be accessed by doing: my $aggregate_name = $exception_obj->aggregate(); =over =item C<< command_interface => $cmd_int >> The command interface on which the aggregate purge was being performed. =item C<< aggregate => $aggr_name >> The name of the aggregate which could not be purged. =item C<< vserver => $vserver_name >> The name of the vserver which contains volumes on another aggregate. =item C<< volumes => [ { volume => $vol_name, aggregate => $aggr_name }, { ... }, ... ] >> (Array) This array-field contains the details of all of the volumes in this vserver but on a different aggregate. Each entry in the array is a hash-reference which contains two keys: =over =item C< volume > The name of the volume =item C< aggregate > The aggregate on which that volume is present =back Being an array-field, this can be accessed in either scalar or list context. my $array_reference = $exception_obj->volumes(); or my @array = $exception_obj->volumes(); Assuming we have an array we can access the fields like: foreach my $entry (@array) { $Log->comment('Volume ' . $entry->{volume} . 'is on aggregate ' . $entry->{aggregate}); } =back =cut package NACL::Exceptions::VserverHasVolumesOnAnotherAggregate; use base qw(NATE::BaseException); use Params::Validate qw(validate SCALAR ARRAYREF OBJECT); use Class::MethodMaker [ scalar => 'aggregate', scalar => 'vserver', array => 'volumes', scalar => [ { -type => 'NACL::C::CommandInterface::ONTAP' }, 'command_interface', ], ]; sub new { my ( $self, %args ) = @_; my $text = delete $args{text}; my $obj = $self->SUPER::new( $text, %args ); $obj->init(%args); return $obj; } ## end sub new sub init { my $self = shift; # Validate, since all of them are mandatory for throwing this # type of exception my %args = validate( @_, { aggregate => { type => SCALAR }, vserver => { type => SCALAR }, volumes => { type => ARRAYREF }, command_interface => { type => OBJECT, isa => 'NACL::C::CommandInterface::ONTAP' } } ); foreach my $attribute (qw(aggregate vserver command_interface)) { $self->$attribute( $args{$attribute} ); } # Array fields need to be provided as arrays to the accessor methods $self->volumes( @{ $args{volumes} } ); } ## end sub init 1;