# $Id: //depot/prod/test/nacldev/lib/NACL/CS/LunGeometry.pm#10 $ # # Copyright (c) 2001-2011 NetApp, Inc., All Rights Reserved # Any use, modification, or distribution is prohibited # without prior written consent from NetApp, Inc. # ## @summary LunGeometry ComponentState Module ## @author anbumozh@netapp.com dl-nacl-dev@netapp.com ## @status shared ## @pod here =head1 NAME NACL::CS::LunGeometry =head1 DESCRIPTION C is a derived class of L. A related class is L, which represents access to an ONTAP LunGeometry. =head1 ATTRIBUTES This module does not represent the state of any element, but is an object repesentation of the output obtained when the lun geometry is queried =over =item C<< "lun" >> =item C<< "tracks_per_cylinder" >> =item C<< "qtree" >> =item C<< "sectors_per_cylinder" >> =item C<< "max_resize_size" >> =item C<< "sectors_per_track" >> =item C<< "sectors" >> =item C<< "cyl_size" >> =item C<< "size" >> =item C<< "volume" >> =item C<< "cylinders" >> =item C<< "bytes_per_sector" >> =item C<< "vserver" >> =item C<< "dev_size" >> =item C<< "path" >> =back =cut package NACL::CS::LunGeometry; use strict; use warnings; use Params::Validate qw(validate); use NACL::ComponentUtils qw(_dump_one Dumper); use NACL::C::_Mixins::Lun qw(:all); 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 NACL::Exceptions::InvalidChoice; use base 'NACL::CS::ComponentState::ONTAP'; use Class::MethodMaker [ scalar => 'vserver', scalar => 'path', scalar => 'volume', scalar => 'qtree', scalar => 'lun', scalar => 'size', scalar => 'bytes_per_sector', scalar => 'sectors_per_track', scalar => 'tracks_per_cylinder', scalar => 'sectors_per_cylinder', scalar => 'cylinders', scalar => 'max_resize_size', scalar => 'sectors', scalar => 'cyl_size', scalar => 'dev_size', ]; =head1 METHODS =head2 fetch my $LunGeometry_state = NACL::CS::LunGeometry->fetch(command_interface => $ci, ...); my @LunGeometry_states = NACL::CS::LunGeometry->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. Supports CMode CLI, CMode ZAPI, 7Mode CLI. Maps to lun-get-geometry for CMode ZAPI and 'lun geometry' for 7Mode CLI. NOTE: If you are writing mode agnostic scripts, then you have to specify the 'path' input in the filter mandatorily so as to get your script working in both the modes. This is because 7M needs lun path as mandatory input to invoke 'lun geometry' command. If you are writing interface agnostic script which runs on CMode (CLI/ZAPI) only, then this limitation will have no effect on you. =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. =item C When apiset_must choice for interface is provided as 'ZAPI' and if the method is invoked without specifying 'path' in the 'filter' or if the method is invoked without specifying 'vserver' in the filter when the command_interface is not of type NACL::C::Vserver or if the method is invoked with special query characters in the filter, then this exception will be thrown. =back =back =cut sub fetch { $Log->enter() if $may_enter; my ($pkg, @args) = @_; my @state_objs = $pkg->SUPER::fetch( @args, choices => [ { method => '_fetch_cmode_cli', interface => 'CLI', set => 'CMode' }, { method => '_fetch_cmode_zapi', interface => 'ZAPI', set => 'CMode', check => '_fetch_zapi_check' }, { method => '_fetch_7mode_cli', interface => 'CLI', set => '7Mode' }, ], exception_text => 'No matching lun geometry(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 => 'lun_geometry'); $Log->exit() if $may_exit; return @state_objs; } ## end sub _fetch_cmode_cli sub _fetch_cmode_zapi { $Log->enter() if $may_enter; my $pkg = shift; my %opts = validate @_, $pkg->_fetch_backend_validate_spec(); my $apiset = $opts{apiset}; my $filter = $opts{filter}; my $lun_response; my %cmd_args = (path => $filter->{path}); my $vserver = $pkg->_handle_zapi_vserver_context( api_opts => \%cmd_args, vserver => $filter->{vserver}, command_interface => $opts{command_interface} ); # Get the geometry of the specified lun $lun_response = $apiset->lun_get_geometry(%cmd_args); my $lun_output = $lun_response->get_parsed_output(); my @state_objs; foreach my $row (@{$lun_output}) { my $state_fields = $pkg->_zapi_hash_copy( source => $row, source_has_extra_arrays => 1, copy => [ qw(path cylinders size max-resize-size bytes-per-sector sectors-per-track tracks-per-cylinder) ], ); $state_fields->{vserver} = $vserver; my $obj = $pkg->new(command_interface => $opts{command_interface}); $obj->_set_fields(row => $state_fields); push @state_objs, $obj; } ## end foreach my $row ( @{$lun_output... $Log->exit() if $may_exit; return @state_objs; } ## end sub _fetch_cmode_zapi 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 %copy_filter = %{$opts{filter}}; my @copy_requested_fields = @{$opts{requested_fields}}; my $deleted_filter = $pkg->_remove_relational_regex_filters( filter => \%copy_filter, requested_fields => \@copy_requested_fields ); my $filter = \%copy_filter; my $requested_fields = \@copy_requested_fields; my $lun_response; my $lun_list_info_args; $lun_list_info_args = $pkg->_hash_copy( source => $filter, map => {'path' => 'lun-path',}, ); $lun_response = $apiset->lun_geometry(%$lun_list_info_args); my $lun_output = $lun_response->get_parsed_output(); my @state_objs; foreach my $row (@{$lun_output}) { my $state_fields = $pkg->_hash_copy( source => $row, copy => [ qw(sectors cylinders max_resize_size bytes_per_sector sectors_per_track tracks_per_cylinder sectors_per_cylinder ) ], map => { 'cylinder_size' => 'cyl_size', 'device_size' => 'dev_size', } ); $$state_fields{'path'} = $lun_list_info_args->{'lun-path'}; if ($$state_fields{'path'} =~ /\/vol\/(\w+)\/(\w+)/) { $$state_fields{'volume'} = $1; $$state_fields{'lun'} = $2; } my $obj = $pkg->new(command_interface => $opts{command_interface}); $obj->_set_fields(row => $state_fields); push @state_objs, $obj; } ## end foreach my $row ( @{$lun_output... $Log->exit() if $may_exit; return @state_objs; } ## end sub _fetch_7mode_cli sub _fetch_zapi_check { $Log->enter() if $may_enter; my ($pkg, %opts) = @_; my %copy_filter = %{$opts{filter}}; try { $pkg->_construct_path(params => \%copy_filter); } catch NATE::Exceptions::Argument with { my $ex = shift; unless ($ex->text() =~ /When 'path' is not provided, then both 'volume' and 'lun' must be provided/ ) { $ex->throw; } }; # If the filter has special characters or if any of 'vserver' # or 'path' input is missing, then we cannot select ZAPI. my $reason = ''; unless (exists $copy_filter{path}) { $reason .= "\nIt needs 'path' as mandatory input whereas" . ' it is missing in \'filter\''; } unless ($opts{command_interface}->isa('NACL::C::Vserver') || exists $opts{filter}{vserver}) { $reason .= "\nZAPI belongs to ontap-vserver family and specifying " . 'vserver name in the filter is mandatory when the ' . 'command_interface is not of type NACL::C::Vserver'; } my $deleted_filter = $pkg->_remove_relational_regex_filters(filter => \%copy_filter); if (scalar %$deleted_filter) { $reason .= "\nIt doesn't support special characters in the filter"; } if ($reason) { $Log->exit() if $may_exit; NACL::Exceptions::InvalidChoice->throw('Could not use ZAPI ' . '\'lun-get-geometry\', because:' . $reason); } $Log->exit() if $may_exit; } ## end sub _fetch_zapi_check 1;