# # Copyright (c) 2001-2010 NetApp, Inc., All Rights Reserved # Any use, modification, or distribution is prohibited # without prior written consent from NetApp, Inc. # ## @summary StorageAggregate64bitUpgrade ComponentState Module ## @author dl-nacl-dev@netapp.com ## @status shared ## @pod here =head1 NAME NACL::CS::StorageAggregate64bitUpgrade =head1 DESCRIPTION C is a derived class of L. It represents the state of an ONTAP StorageAggregate64bitUpgrade. A related class is L, which represents access to an ONTAP Aggregate. =head1 ATTRIBUTES The individual pieces of data that are part of the state of the StorageAggregate64bitUpgrade element are the attributes of the StorageAggregate64bitUpgrade ComponentState. =over =item C<< aggregate => $string >> The name of the aggregate being upgraded. Note that it is mandatory to provide aggregate in the filter since there is no mechanism to get the upgrade status of all aggregates. Not providing the aggregate in the filter results in a C exception being thrown. # This results in an exception NACL::CS::StorageAggregate64bitUpgrade->fetch(command_interface => $node); # This is the way it should be invoked NACL::CS::StorageAggregate64bitUpgrade->fetch( command_interface => $node, filter => { aggregate => $aggr_name } ); =item C<< space_estimate_complete => $string >> =item C<< scan_time_to_complete => $string >> =item C<< vsID => $string >> =item C<< scan_progress => $string >> =item C<< uuid => $string >> =item C<< scan_percent_completed => $string >> =item C<< estimated_used_space => $string >> =item C<< size_fixed => $string >> =item C<< is_aggr => $string >> =item C<< estimated_available_space => $string >> =item C<< total_size => $string >> =item C<< estimated_percent_used_space => $string >> =item C<< format => $string >> =item C<< scanner_status => $string >> =item C<< estimated_grow_vol_size_by => $string >> =item C<< volumes_64bit => @array >> The details of the volumes in the aggregate being upgraded to 64-bit. Each element in this array is of type L. Example: # Assume we have a StorageAggreate64bitUpgrade CS object called $cs my @vol_64bit_cs = $cs->volumes_64bit(); $Log->comment('Space-estimate-complete of first volume: ' . $vol_64bit_cs[0]->space_estimate_complete() ); This field is filled in by default. To not fill in this field, we should provide "include-all-volumes" in the filter to be "false" Example: NACL::CS::StorageAggregate64bitUpgrade->fetch( command_interface => $node, filter => { aggregate => $aggr_name, 'include-all-volumes' => 'false' } ); Note that the C field cannot be provided in the filter (providing it in the filter results in an exception) since we cannot really filter on the volume details. =back =cut package NACL::CS::StorageAggregate64bitUpgrade; use strict; use warnings; use Params::Validate qw(validate); use NACL::ComponentUtils qw(_dump_one Dumper); use NATE::Log qw(log_global); my $Log = log_global(); my $may_enter = $Log->may_enter(); my $may_exit = $Log->may_exit(); use NACL::Exceptions::NoElementsFound qw(:try); use NATE::Exceptions::Argument qw(:try); use NACL::CS::Volume64bitUpgrade; use base 'NACL::CS::ComponentState::ONTAP'; use Class::MethodMaker [ scalar => "space_estimate_complete", scalar => "scan_time_to_complete", scalar => "vsID", scalar => "scan_progress", scalar => "uuid", scalar => "scan_percent_completed", scalar => "estimated_used_space", scalar => "size_fixed", scalar => "aggregate", scalar => "is_aggr", scalar => "total_size", scalar => "estimated_percent_used_space", scalar => "format", scalar => "scanner_status", scalar => "estimated_grow_vol_size_by", array => "volumes_64bit", ]; =head1 METHODS =head2 fetch my $st_aggr_64bit_upgrade_state = NACL::CS::StorageAggregate64bitUpgrade->fetch(command_interface=>$ci,...); my @st_aggr_64bit_upgrade_states = NACL::CS::StorageAggregate64bitUpgrade->fetch(command_interface=>$ci,...); Note that though this method accepts C and C like all other CS modules, there are some limitations due to limitations in the command. =over =item * Cannot fetch details for all aggregates This command can only fetch the upgrade details for one aggregate at a time. For this reason, aggregate B to be provided in the filter. Failure to do so results in a C exception being thrown. # This results in an exception NACL::CS::StorageAggregate64bitUpgrade->fetch(command_interface => $node); # This is the way it should be invoked NACL::CS::StorageAggregate64bitUpgrade->fetch( command_interface => $node, filter => { aggregate => $aggr_name } ); =back =over =item Use of C The way to get the details of the volumes contained in the aggregate being upgraded is through the C field. Each element in this array is of type L. Example: # Assume we have a StorageAggreate64bitUpgrade CS object called $cs my @vol_64bit_cs = $cs->volumes_64bit(); $Log->comment('Space-estimate-complete of first volume: ' . $vol_64bit_cs[0]->space_estimate_complete() ); =over =item Restriction on use of volumes_64bit in filter Note that the C field cannot be provided in the filter since this is an additional field introduced for the volume details and there is no way to really filter on the volumes. Providing this in the filter results in a C exception being thrown. # Results in NATE::Exceptions::Argument being thrown NACL::CS::StorageAggregate64bitUpgrade->fetch( command_interface => $node, filter => { volumes_64bit => $some_val aggregate => $aggr_name } ); =back =back =over =item Use of C The default behavior is to fetch the details of all the volumes contained in the aggregate being upgraded. Doing this will have the same effect, though it is redundant considering the default is to fetch details of all volumes. NACL::CS::StorageAggregate64bitUpgrade->fetch( command_interface => $node, filter => { 'include-all-volumes' => 'true', aggregate => $aggr_name } ); The way to switch off getting the details of included volumes is shown below (note that certain builds of ONTAP don't seem to honor this field, which could lead to volume details still being obtained): NACL::CS::StorageAggregate64bitUpgrade->fetch( command_interface => $node, filter => { 'include-all-volumes' => 'true', aggregate => $aggr_name } ); =over =item Restriction on use of include-all-volumes in requested_fields Note that while C can be provided in the filter, it cannot be provided in requested_fields. Doing so will result in a C exception being thrown. # Results in NATE::Exceptions::Argument being thrown NACL::CS::StorageAggregate64bitUpgrade->fetch( command_interface => $node, filter => { aggregate => $aggr_name }, requested_fields => [ 'include-all-volumes' ] ); =back =back =over =item Exceptions =over =item C When there are no elements matching the query specified or elements of that type doesn't exist, then this exception will be thrown. =back =back =cut sub fetch { $Log->enter() if $may_enter; my $pkg = shift; my %opts = validate @_, $pkg->_fetch_validate_spec(); my %filter = %{ $opts{filter} }; if ( !defined $filter{aggregate} ) { $Log->exit() if $may_exit; NATE::Exceptions::Argument->throw( 'It is mandatory to provide aggregate in the filter for ' . 'StorageAggregate64bitUpgrade::fetch' ); } if ( defined $filter{volumes_64bit} || defined $filter{'volumes-64bit'} ) { $Log->exit() if $may_exit; NATE::Exceptions::Argument->throw( "'volumes_64bit' cannot be " . 'provided as a filter field, it can only be provided in ' . 'requested_fields' ); } if ( !@{ $opts{requested_fields} } && !defined $filter{'include-all-volumes'} ) { $filter{'include-all-volumes'} = 'true'; } elsif ( grep { /volumes[_-]64bit/ } @{ $opts{requested_fields} } ) { if ( !defined $filter{'include-all-volumes'} ) { $filter{'include-all-volumes'} = 'true'; } my @requested_fields = @{ $opts{requested_fields} }; my @modified_requested_fields; foreach my $orig_req_field (@requested_fields) { next if ( $orig_req_field =~ /volumes[_-]64bit/ ); push @modified_requested_fields, $orig_req_field; } $opts{requested_fields} = \@modified_requested_fields; } my @state_objs = $pkg->SUPER::fetch( %opts, filter => \%filter, choices => [ { method => '_fetch_cmode_cli', interface => 'CLI', set => 'CMode', }, { method => '_fetch_7mode_cli', interface => 'CLI', set => '7Mode|Nodescope', }, ], exception_text => 'No matching storage aggregate64bit upgrade(s) found', show_cmd => 'storage aggregate 64bit-upgrade status', ); $Log->exit() if $may_exit; return wantarray ? @state_objs : $state_objs[0]; } sub _fetch_7mode_cli { $Log->enter() if $may_enter; my $pkg = shift; my %opts = validate @_, $pkg->_fetch_backend_validate_spec(); my $apiset = $opts{apiset}; my ( $response, $caught_exception, @state_objs, %input, $aggr_obj ); my $requested_fields = $opts{requested_fields} || []; $input{'aggregate'} = $opts{filter}->{aggregate}; my $include_all_volumes = $opts{filter}->{'include-all-volumes'}; # Check if the user wants data regarding the volumes in the aggregate if ( defined $include_all_volumes && $include_all_volumes =~ /true/i ) { $input{'all'} = 1; } try { $response = $apiset->aggr_64bit_upgrade_status(%input); } catch NACL::APISet::Exceptions::InvalidParamValueException with { if ( $Log->may_trace() ) { my $exception = shift; $Log->trace( 'Error occured while running ' . "aggr_64bit_upgrade_status:\n" . $exception->text() ); } $caught_exception = 1; }; if ($caught_exception) { $Log->exit() if $may_exit; return; } my $output = $response->get_parsed_output(); my $not_seen_aggr_line = 1; my @vol_objs; foreach my $row (@$output) { my $final_attributes = $pkg->_hash_copy( source => $row, copy => [qw( volume format scanner_status )], map => { "percent_completed", => "scan_percent_completed", "time_to_completion" => "scan_time_to_complete", "progress" => "scan_progress" } ); # The output has one line for the aggregate details. The remaining # lines are for the volume details. if ($not_seen_aggr_line) { $aggr_obj = $pkg->new( command_interface => $opts{command_interface} ); $aggr_obj->_set_fields( row => $final_attributes ); $aggr_obj->aggregate( $input{aggregate} ); $not_seen_aggr_line = 0; } else { my $vol_obj = NACL::CS::Volume64bitUpgrade->new( command_interface => $opts{command_interface} ); $vol_obj->_set_fields( row => $final_attributes ); push( @vol_objs, $vol_obj ); } } $aggr_obj->volumes_64bit(@vol_objs); push @state_objs, $aggr_obj; $Log->exit() if $may_exit; return @state_objs; } ## end sub _fetch_7mode_cli sub _fetch_cmode_cli { $Log->enter() if $may_enter; my $pkg = shift; my %opts = validate @_, $pkg->_fetch_backend_validate_spec(); my $apiset = $opts{apiset}; my $requested_fields = $opts{requested_fields}; my $filter = $opts{filter}; my $test_fields = $opts{test_fields}; my $command_interface = $opts{command_interface}; my $api = 'storage_aggregate_64bit_upgrade_status'; my $cdef = $apiset->get_command_definition( command => $api ); my $api_opts = {}; my @new_requested_fields; my %copy_filter = %{ $filter }; my @copy_requested_fields = @{ $requested_fields }; foreach my $key ( keys %copy_filter ) { if ( !$cdef->{alias_params}->{$key} ) { delete $copy_filter{$key}; } } foreach (@copy_requested_fields) { push( @new_requested_fields, $_ ) if ( $cdef->{alias_params}->{$_} ); } $api_opts = $pkg->_compute_cmode_cli_options( filter => \%copy_filter, requested_fields => \@new_requested_fields, command_interface => $command_interface, ); $Log->debug( sub { "API options:\n" . Dumper($api_opts) } ); my @state_objs; # The API call may throw an exception as a result of no entries matching # the query being found or because of an invalid filter field or invalid # requested field being passed. If no entries matching the query are # found, a "NoMatchingEntriesException" is thrown. We just catch it and # do nothing. The 'fetch' frontend decides whether to throw a # NoElementFound exception based on the value of allow_empty. # If an exception occured as a result of the other cases, then an # InvalidParamException is thrown, we catch this and turn it into # an InvalidFilterField exception (performed by the method # _throw_cmode_cli_invalid_filter). try { my $response = $apiset->$api( %{$api_opts} ); my $output = $response->get_parsed_output(); my @output = @{$output}; my $aggr_row = shift @output; my $obj = $pkg->new( command_interface => $command_interface ); $obj->_set_fields( row => $aggr_row ); my @vol_objs; foreach my $row ( @{output} ) { my $vol_obj = NACL::CS::Volume64bitUpgrade->new( command_interface => $command_interface ); $vol_obj->_set_fields( row => $row ); push @vol_objs, $vol_obj; } ## end foreach my $row (@$output) $obj->volumes_64bit(@vol_objs); # Check that $obj is defined because we could have reached this point # if a NoMatchingEntriesException was thrown, in which case $obj would be # undef. This would mean @state_objs would be [ undef ] rather than [] push @state_objs, $obj if ( defined $obj ); } catch NACL::APISet::Exceptions::NoMatchingEntriesException with { $Log->debug('No entries found matching the query'); } catch NACL::APISet::Exceptions::InvalidParamException with { $Log->exit() if $may_exit; $pkg->_throw_cmode_cli_invalid_filter(@_); }; $Log->exit() if $may_exit; return @state_objs; } # Overriding because "include-all-volumes" is not an attribute of the # object but this field can be provided in the filter sub _extra_filter_fields { $Log->enter() if $may_enter; $Log->exit() if $may_exit; return ['include-all-volumes']; } 1;