# $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 VolumeQuotaPolicyRule ComponentState Module ## @author Dheeraj.K@netapp.com, dl-nacl-dev@netapp.com , raghaveb@netapp.com ## @status shared ## @pod here =head1 NAME NACL::CS::VolumeQuotaPolicyRule =head1 DESCRIPTION C is a derived class of L. It represents the state of Volume Quota Policy Rule on an ONTAP Volume. A related class is L, which represents access to an ONTAP VolumeQuotaPolicyRule. =head1 ATTRIBUTES The individual pieces of data that are part of the state of the VolumeQuotaPolicyRule element are the attributes of the VolumeQuotaPolicyRule ComponentState. =over =item C<< vserver >> Filled in for CMode CLI/ZAPI Name of the vserver in which the volume resides =item C<< volume >> Filled in for CMode CLI/ZAPI Name of the volume for which the quota policy rule is created =item C<< "policy_name " >> Filled in for CMode CLI/ZAPI this maps to policy-name in CMode ZAPI. =item C<< "type" >> Filled in for CMode CLI/ZAPI this maps to quota-type in CMode ZAPI. =item C<< "target" >> Filled in for CMode CLI/ZAPI this maps to quota-target in CMode ZAPI. =item C<< "disk_limit" >> Filled in for CMode CLI/ZAPI =item C<< "file_limit" >> Filled in for CMode CLI/ZAPI =item C<< "threshold" >> Filled in for CMode CLI/ZAPI =item C<< "soft_disk_limit" >> Filled in for CMode CLI/ZAPI =item C<< "soft_file_limit" >> Filled in for CMode CLI/ZAPI =item C<< "qtree" >> =item C<< "quota_error" >> =item C<< "user_mapping" >> Filled in for CMode CLI/ZAPI this maps to perform-user-mapping in CMode ZAPI. =item C<< "zapi_user_mapping" >> =item C<< "zapi_err_errno" >> =item C<< "zapi_err_reason" >> =item C<< "zapi_err_detail" >> =item C<< "policyid" >> =item C<< "msid" >> =back =cut package NACL::CS::VolumeQuotaPolicyRule; use strict; use warnings; use Params::Validate qw(validate); use NATE::Log qw(log_global); my $Log = log_global(); my $may_enter = $Log->may_enter(); my $may_exit = $Log->may_exit(); use base 'NACL::CS::ComponentState::ONTAP'; use NACL::ComponentUtils qw (Dumper); use Class::MethodMaker [ # These fields are from the C Mode "volume quota policy rule show" scalar => 'vserver', scalar => 'policy_name', scalar => 'volume', scalar => 'type', scalar => 'target', scalar => 'disk_limit', scalar => 'file_limit', scalar => 'threshold', scalar => 'soft_disk_limit', scalar => 'soft_file_limit', scalar => 'user_mapping', scalar => 'zapi_user_mapping', scalar => 'zapi_err_errno', scalar => 'zapi_err_reason', scalar => 'zapi_err_detail', scalar => 'policyid', scalar => 'msid', # These fields are from 7 Mode ZAPI "quota list entries" scalar => 'qtree', array => 'quota_error', ]; sub isa { $Log->enter() if $may_enter; my ($pkg_or_obj, $kind) = @_; my $isa = $pkg_or_obj->_build_isa( kind => $kind, alias => 'NACL::CS::QuotaPolicyRule' ); $Log->exit() if $may_exit; return $isa; } ## end sub isa =head1 METHODS =head2 fetch my $quotapolicyrule_state = NACL::CS::VolumeQuotaPolicyRule->fetch(command_interface=>$ci,...); my @quotapolicyrule_states = NACL::CS::VolumeQuotaPolicyRule->fetch(command_interface=>$ci,...); see L Uses a CMode CLI or a CMode ZAPI or a 7Mode ZAPI APISet. This method invokes quota-list-entries-iter command for CMode ZAPI =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 => 'volume quota policy rule show', choices => [ { method => '_fetch_cmode_cli', interface => 'CLI', set => 'CMode', }, { method => '_fetch_7mode_cli', interface => 'CLI', set => '7Mode', }, { method => '_fetch_7mode_zapi', interface => 'ZAPI', set => '7Mode', }, { method => '_fetch_cmode_zapi', interface => 'ZAPI', set => 'CMode', }, ], exception_text => 'No matching volume quota policy rule(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 => 'volume_quota_policy_rule_show'); $Log->exit() if $may_exit; return @state_objs; } ## end sub _fetch_cmode_cli sub _fetch_7mode_zapi { $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}; # get a list of all the quota rules present. my $response = $apiset->quota_list_entries(); my $output = $response->get_parsed_output(); my $list_output = $output->[0]{'quota-entries'}[0]{'quota-entry'}; my @quotas; foreach my $row (@$list_output) { if (ref($row->{qtree}) eq "ARRAY") { $row->{qtree} = ""; } my $quota = $pkg->_hash_copy( source => $row, copy => [qw(qtree quota-target quota-type volume)], ); push(@quotas, $quota); } ## end foreach my $row (@$list_output) my @state_objs; # get info about each quota rule. foreach my $row (@quotas) { my $get_entry_response = $apiset->quota_get_entry(%$row); my $get_entry_output = $get_entry_response->get_parsed_output(); my $quota_info = $get_entry_output->[0]; my %_quota_info = (%$quota_info, %$row); my $final_quota_info = $pkg->_hash_copy( source => \%_quota_info, copy => [ qw(qtree volume disk-limit file-limit quota-error perform-user-mapping soft-disk-limit soft-file-limit threshold) ], map => { 'quota-target' => 'target', 'quota-type' => 'type', }, ); my $obj = $pkg->new(command_interface => $opts{command_interface}); $obj->_set_fields(row => $final_quota_info); if ($obj->{target} =~ /\/vol\//) { my @arr = split(/\//, $obj->{target}); $obj->{target} = $arr[3]; } push @state_objs, $obj; } ## end foreach my $row (@quotas) $Log->exit() if $may_exit; return @state_objs; } ## end sub _fetch_7mode_zapi sub _fetch_cmode_zapi { $Log->enter() if $may_enter; my ($pkg, @args) = @_; my %opts = validate @args, $pkg->_fetch_backend_validate_spec(); if ( defined($opts{filter}{type}) && defined($opts{filter}{volume}) && defined($opts{filter}{target}) ) { $opts{filter}{target} = $pkg->_zapi_input_translate_target( $opts{filter}{type}, $opts{filter}{volume}, $opts{filter}{target}, ); } ## end if ( defined( $opts{filter...})) my @states = $pkg->SUPER::_fetch_cmode_zapi( %opts, api => 'quota_list_entries_iter', copy => [ qw(vserver volume disk-limit file-limit threshold soft-disk-limit soft-file-limit qtree) ], map => { 'policy-name' => ['policy'], 'type' => ['quota-type'], 'target' => ['quota-target'], 'user-mapping' => ['perform-user-mapping'], }, ); $Log->exit() if $may_exit; return @states; } ## 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 $requested_fields = $opts{requested_fields}; my $filter = $opts{filter}; my @state_objs; # get a list of all the quota rules present. my $response = $apiset->rdfile(file => "/etc/quotas"); my $output = $response->get_parsed_output(); if ($output->[0]->{contents}) { my @rows = split(/\n/, $output->[0]->{contents}); my $user_mapping; foreach my $row (@rows) { my %quota_hash; my $vol_path; next if $row =~ /^\s*#/; if ($row =~ /QUOTA_TARGET_DOMAIN/) { next; } if ($row =~ /QUOTA_PERFORM_USER_MAPPING ON/) { $user_mapping = "on"; next; } if ($row =~ /QUOTA_PERFORM_USER_MAPPING OFF/) { $user_mapping = "off"; next; } my @column = split(/\s+/, $row); $quota_hash{user_mapping} = $user_mapping; $quota_hash{target} = $column[0]; $quota_hash{type} = (split(/@/, $column[1]))[0]; if ($quota_hash{type} eq "tree") { my @arr1 = split(/\//, $column[1]); $quota_hash{volume} = $arr1[2]; unless (defined $quota_hash{volume}) { $quota_hash{volume} = (split(/\//, $column[0]))[2]; } $quota_hash{qtree} = ""; } else { $vol_path = (split(/@/, $column[1]))[1]; ($quota_hash{volume}, $quota_hash{qtree}) = (split /\//, $vol_path)[2, 3]; $quota_hash{qtree} = defined $quota_hash{qtree} ? $quota_hash{qtree} : ""; } ## end else [ if ( $quota_hash{type}...)] $quota_hash{disk_limit} = $column[2]; $quota_hash{file_limit} = $column[3]; $quota_hash{threshold} = $column[4]; $quota_hash{soft_disk_limit} = $column[5]; $quota_hash{soft_file_limit} = $column[6]; my $obj = $pkg->new(command_interface => $opts{command_interface}); $obj->_set_fields(row => \%quota_hash); if ($obj->{target} =~ /\/vol\//) { my @arr = split(/\//, $obj->{target}); $obj->{target} = $arr[3]; } push @state_objs, $obj; } ## end foreach my $row (@rows) } ## end if ( $output->[0]->{contents...}) $Log->exit() if $may_exit; return @state_objs; } ## end sub _fetch_7mode_cli sub _update_state_objs_cmode_zapi { my ($pkg, %opts) = @_; $pkg->SUPER::_update_state_objs_cmode_zapi( %opts, hash_map_translations => { 'user-mapping' => { fields_to_translate => [qw(user-mapping)], hash_map => { 'true' => 'on', 'false' => 'off', }, }, }, additional_translations => { size_to_bytes => { method => '_zapi_output_translate_size', fields_to_translate => [ 'disk-limit', 'soft-disk-limit', 'threshold' ] }, }, ); # rewrite target (with dependency on type, volume) foreach my $state_obj (@{$opts{state_objs}}) { $state_obj->target( $pkg->_zapi_output_translate_target( $state_obj->type(), $state_obj->volume(), $state_obj->target(), ) ); } } # ZAPI returns field in terms of KBytes. Normalize to Bytes. sub _zapi_output_translate_size { my ($pkg, $val) = @_; $val *= 1024; return $val; } sub _zapi_output_translate_target { my ($pkg, $type, $volume, $target) = @_; if ($type eq 'tree') { if ($target =~ qr/^\/vol\/($volume)\/(.+)$/) { # $2 is the qtree name return $2; } elsif ($target =~ qr/^\"\/vol\/($volume)\/(.+)\"$/) { # "$2" is the qtree name return '"'.$2.'"'; # with quoting } } return $target; } sub _zapi_input_translate_target { my ($pkg, $type, $volume, $target) = @_; if (($target eq "*") || ($target eq "") || ($target eq '""')) { return $target; } if ($type eq 'tree') { if ($target =~ qr/^\"(.*)\"$/) { $target = $1; # without quoting } return "/vol/" . $volume . "/" . $target; } return $target; } 1;