# $Id$ # # Copyright (c) 2001-2012 NetApp, Inc., All Rights Reserved # Any use, modification, or distribution is prohibited # without prior written consent from NetApp, Inc. # ## @summary StorageAggregatePlex ComponentState Module (auto-generated by CGT) ## @author dl-nacl-dev@netapp.com ## @status shared ## @pod here =head1 NAME NACL::CS::StorageAggregatePlex =head1 DESCRIPTION C is a derived class of L. It represents the state of an ONTAP StorageAggregatePlex. A related class is L, which represents access to an ONTAP StorageAggregatePlex. =head1 ATTRIBUTES The individual pieces of data that are part of the state of the StorageAggregatePlex element are the attributes of the StorageAggregatePlex ComponentState. Additionally, the command_interface used to obtain the ComponentState object is also an attribute of the object. This makes it easier to obtain the component object corresponding to the CS object, using L. =over =item command_interface The command_interface with which the CS object was obtained. (Available in all CS objects regardless of requested_fields and the mode/interface) =item C<< plex_path >> Filled in for CMode CLI, 7Mode and Nodescope CLI. Maps to 'raid_name' of 'raid_config info listplex' for 7Mode and Nodescope CLI. =item C<< is_online >> Filled in for CMode CLI, 7Mode and Nodescope CLI. Maps to 'online' of 'raid_config info listplex' for 7Mode and Nodescope CLI. Returns true/false. =item C<< is_resyncing >> Filled in for CMode CLI, 7Mode and Nodescope CLI. Maps to 'resyncing' of 'raid_config info listplex' for 7Mode and Nodescope CLI. Returns true/false. =item C<< in_progress >> Filled in for CMode CLI, 7Mode and Nodescope CLI. Maps to 'resyncing' of 'raid_config info listplex' for 7Mode and Nodescope CLI. Returns true/false. =item C<< status >> Filled in for CMode CLI, 7Mode CLI, Nodescope CLI. This is obtained from the command 'aggr status -r' for 7Mode and Nodescope CLI. =item C<< resync_level >> Filled in for CMode CLI, 7Mode CLI, Nodescope CLI. Maps to 'resync_level' of 'raid_config info listplex' for 7Mode and Nodescope CLI. =item C<< plex >> Filled in for CMode CLI, 7Mode CLI, Nodescope CLI. This is obtained from the command 'raid_config info listplex' for 7Mode and Nodescope CLI. =item C<< pool >> Filled in for CMode CLI, 7Mode CLI, Nodescope CLI. This is obtained from the 'status' field of the command 'aggr status -r' for 7Mode and Nodescope CLI. =item C<< aggregate >> Filled in for CMode CLI, 7Mode CLI, Nodescope CLI. Maps to 'tree' of 'raid_config info listplex' for 7Mode and Nodescope CLI. =item C<< resyncing_percent >> Filled in for CMode CLI, 7Mode CLI, Nodescope CLI. Maps to 'resync_progress' of 'raid_config info listplex' for 7Mode and Nodescope CLI. =item 7Mode or Nodescope CLI only attributes The following is the list of attributes which are supported only for 7Mode or Nodescope CLI and these are filled by running the command 'raid_config listinfo plex'. tree, raid_size, raid_name, parent_id, plexid, cls_complete, id, ctime, outofdate, plex_time, fsm_state, cls_label, resyncing, online, plex_gen, parent_state_resync, plex_rightsize, type, resync_progress =back =cut package NACL::CS::StorageAggregatePlex; use strict; use warnings; use Params::Validate qw(validate validate_pos SCALAR); use NATE::Log qw(log_global); my $Log = log_global(); my $may_enter = $Log->may_enter(); my $may_exit = $Log->may_exit(); use Data::Dumper; use NACL::Exceptions::NoElementsFound qw(:try); use NATE::BaseException; use base 'NACL::CS::ComponentState::ONTAP'; use Class::MethodMaker [ scalar => [ { '-default_ctor' => sub { if ($_[0]->aggregate && $_[0]->plex) { return $_[0] ->_get_plex_path($_[0]->aggregate, $_[0]->plex); } }, }, 'plex_path' ], scalar => 'is_online', # SMF says is-resyncing is an alias for in-progress. scalar => [{'-default_ctor' => sub { $_[0]->in_progress },}, 'is_resyncing'], scalar => 'in_progress', scalar => 'status', scalar => 'plex', scalar => 'pool', scalar => 'aggregate', scalar => 'resyncing_percent', scalar => 'resync_level', # 7Mode or Nodescope CLI only fields # Some of the following fields are mapped to the option names as exposed # by the ngshell command 'storage aggregate plex show' as well but I have # also exposed all the attributes displayed by 'raid_config info listplex' # in the same name for the convenience of those who directly use # DBlade command for both CMode and 7Mode. scalar => 'tree', scalar => 'raid_size', scalar => 'raid_name', scalar => 'parent_id', scalar => 'plexid', scalar => 'cls_complete', scalar => 'id', scalar => 'ctime', scalar => 'outofdate', scalar => 'plex_time', scalar => 'fsm_state', scalar => 'cls_label', scalar => 'resyncing', scalar => 'online', scalar => 'plex_gen', scalar => 'parent_state_resync', scalar => 'plex_rightsize', scalar => 'type', scalar => 'resync_progress', ]; =head1 METHODS =head2 fetch my $StorageAggregatePlex_state = NACL::CS::StorageAggregatePlex->fetch(command_interface => $ci, ...); my @StorageAggregatePlex_states = NACL::CS::StorageAggregatePlex->fetch(command_interface => $ci, ...); (Class method) Discovers which elements are present and returns their state in ComponentState objects. Called in scalar context it returns only one state object, in list context it returns all state objects. See L for a more detailed description along with a complete explanation of the options it accepts. Uses a CMode CLI or Nodescope CLI or 7Mode CLI APISet. =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 @state_objs = $pkg->SUPER::fetch( @_, show_cmd => 'storage aggregate plex show', choices => [ { method => '_fetch_cmode_cli', interface => 'CLI', set => 'CMode' }, { method => '_fetch_7mode_cli', interface => 'CLI', set => '7Mode|Nodescope' } ], exception_text => 'No matching storage aggregate plex(s) found' ); $Log->exit() if $may_exit; return wantarray ? @state_objs : $state_objs[0]; } ## end sub fetch sub _fetch_cmode_cli { $Log->enter() if $may_enter; my $pkg = shift; my @state_objs = $pkg->SUPER::_fetch_cmode_cli(@_, api => 'storage_aggregate_plex_show',); $Log->exit() if $may_exit; return @state_objs; } ## end sub _fetch_cmode_cli sub _fetch_7mode_cli { my $pkg = shift; my %opts = validate @_, $pkg->_fetch_backend_validate_spec(); my $apiset = delete $opts{apiset}; my %cmd_opts; my ($response, $output, @state_objs, %new_hash, $raid_config_output, $raid_config_response, $req_field_filter, %plexes); my %copy_filter = %{$opts{filter}}; my @copy_requested_fields = @{$opts{requested_fields}}; my $filter = \%copy_filter; my $requested_fields = \@copy_requested_fields; $req_field_filter->{'requested_fields'} = $requested_fields; $req_field_filter->{'filter'} = \%copy_filter; # raid_config info listplex gives most of the details except for 'status' # attribute for which we will execute 'aggr status -r' conditionally my $raid_config_7m = [ qw (resync_level tree raid_size raid_name parent_id plexid cls_complete id ctime outofdate plex_time fsm_state cls_label resyncing online plex_gen parent_state_resync plex_rightsize type resync_progress ) ]; # The only server-side filtering possible in 7-mode is if the # caller limits to one specific plex of an aggregate, # then we can get info on just that plex. Otherwise, we get info # on all plexes and filter out undesired entries later. my %raid_config_args = (); if (defined($filter->{aggregate}) && defined($filter->{plex})) { $raid_config_args{'plex-name'} = $pkg->_get_plex_path($filter->{aggregate}, $filter->{plex}); } elsif (defined $filter->{'plex-path'}) { $raid_config_args{'plex-name'} = $filter->{'plex-path'}; } my $caught_exception = 0; try { $raid_config_response = $apiset->raid_config( 'info' => 'listplex', %raid_config_args ); } catch NACL::APISet::Exceptions::InvalidParamValueException with { # Indicates the specified plex doesn't exist $caught_exception = 1; }; if ($caught_exception) { $Log->exit() if $may_exit; return; } $raid_config_output = $raid_config_response->get_parsed_output(); my %mapping = ( 'resyncing' => 'in_progress', 'online' => 'is_online', 'tree' => 'aggregate', 'raid_name' => 'plex_path', 'resync_progress' => 'resyncing_percent', ); # need a generic place? my %bool_map = (0 => 'false', 1 => 'true'); foreach my $plex_entry (@$raid_config_output) { my $row_modified = {}; my $obj = $pkg->new(command_interface => $opts{command_interface}); $pkg->_hash_copy( source => $plex_entry, target => $row_modified, copy => $raid_config_7m, map => \%mapping ); foreach my $bool_opt ('in_progress', 'is_online') { $row_modified->{$bool_opt} = $bool_map{$row_modified->{$bool_opt}}; } if ($plex_entry->{raid_name} =~ /(plex\d+)$/) { $row_modified->{'plex'} = $1; } else { $Log->exit() if $may_exit; NATE::BaseException->throw("Failed to obtain plex name. " . "Unknown format: " . $plex_entry->{raid_name}); } $obj->_set_fields(row => $row_modified); if ($obj->resyncing_percent_isset) { if ($obj->resyncing_percent eq '-1') { # CMode gives '-' when there is no active transfer $obj->resyncing_percent('-'); } else { # CMode gives the resyncing percentage as % $obj->resyncing_percent($obj->resyncing_percent . '%'); } } push @state_objs, $obj; $plexes{$plex_entry->{raid_name}} = $obj; } if ($pkg->_want_any_field_of( %{$req_field_filter}, fields_filled_by_api => ['status', 'pool'] ) ) { my %aggr_status_args = (); if (defined $filter->{aggregate}) { $aggr_status_args{aggregate} = $filter->{aggregate}; } $response = $apiset->aggr_status('raid-disk' => 1, %aggr_status_args); $output = $response->get_parsed_output(); # The outer array in the output has only one element always foreach my $plex (@{$output->[0]->{'aggregate'}}) { foreach my $plex_info (@{$plex->{'plex'}}) { my $obj = $plexes{$plex_info->{'plex_name'}}; # Since we cannot request aggr status -r to give information # about specific plexes, we should ignore the information # about extra plexes. next unless ($obj); $obj->status($plex_info->{'status'}); if ($obj->status =~ /pool(\d)/) { $obj->pool($1); } } } } $Log->exit() if $may_exit; return @state_objs; } ## end sub _fetch_7mode_cli sub _get_plex_path { $Log->enter() if $may_enter; my $pkg_or_obj = shift; my ($aggr, $plex) = validate_pos(@_, {type => SCALAR}, {type => SCALAR}); my $path = '/' . $aggr . '/' . $plex; $Log->debug("Plex path is: $path"); $Log->exit() if $may_exit; return $path; } 1;