# $Id$ # This is a prototype. It needs documentation. # # Copyright (c) 2001-2012 NetApp, Inc., All Rights Reserved # Any use, modification, or distribution is prohibited # without prior written consent from NetApp, Inc. # ## @summary NetworkInterface ComponentState Module ## @author Rupamjyoti.Baruah@netapp.com, dl-nacl-dev@netapp.com ## @status shared ## @pod here =head1 NAME NACL::CS::NetworkInterface =head1 DESCRIPTION C is a derived class of L. It represents the state of a Network Interface. A related class is L, which represents access to a Network Interface. =head1 ATTRIBUTES The individual pieces of data that are part of the state of the element are the attributes of the ComponentState. =over =item C<< vserver >> Vserver Name Filled in for CMode CLI/ZAPI. Maps to: CMode ZAPI: For "requested_fields", "filter" and Output mapping: $value =item C<< server >> Filled in for CMode CLI/ZAPI. Maps to: CMode ZAPI: For "requested_fields", "filter" and Output mapping: $value =item C<< lif >> Logical NetworkInterface Filled in for CMode CLI/ZAPI. Maps to: CMode ZAPI: For "requested_fields", "filter" and Output mapping: $value =item C<< role >> Role. Possible Values: cluster; data; node-mgmt; intercluster; cluster-mgmt Filled in for CMode CLI/ZAPI. Maps to: CMode ZAPI: For "requested_fields", "filter" and Output mapping: $value =item C<< home_node >> Nodename of the home node Filled in for CMode CLI/ZAPI. Maps to: CMode ZAPI: For "requested_fields", "filter" and Output mapping: $value =item C<< home_port >> Filled in for CMode CLI/ZAPI. Maps to: CMode ZAPI: For "requested_fields", "filter" and Output mapping: $value =item C<< curr_node >> Nodename of the current node Filled in for CMode CLI/ZAPI. Maps to: CMode ZAPI: For "requested_fields", "filter" and Output mapping: $value =item C<< curr_port >> Current port Filled in for CMode CLI/ZAPI. Maps to: CMode ZAPI: For "requested_fields", "filter" and Output mapping: $value =item C<< status_oper >> Operational Status Possible values: up; down Filled in for CMode CLI/ZAPI. Maps to: CMode ZAPI: For "requested_fields", "filter" and Output mapping: $value =item C<< is_home >> Is Home? Possible Values: true; false Filled in for CMode CLI/ZAPI. Maps to: CMode ZAPI: For "requested_fields", "filter" and Output mapping: $value =item C<< address >> Network Address (IP Address) Filled in for CMode CLI/ZAPI. Maps to: CMode ZAPI: For "requested_fields", "filter" and Output mapping:
$value
=item C<< netmask >> Netmask Filled in for CMode CLI/ZAPI. Maps to: CMode ZAPI: For "requested_fields", "filter" and Output mapping: $value =item C<< netmask_length >> Bits in the Netmask Filled in for CMode CLI/ZAPI. Maps to: CMode ZAPI: For "requested_fields", "filter" and Output mapping: $value =item C<< routing_group >> Routing Group Name Filled in for CMode CLI/ZAPI. Maps to: CMode ZAPI: For "requested_fields", "filter" and Output mapping: $value =item C<< status_admin >> Administrative Status Possible Values: up; down Filled in for CMode CLI/ZAPI. Maps to: CMode ZAPI: For "requested_fields", "filter" and Output mapping: $value =item C<< failover_policy >> Failover Policy Possible Values: nextavail; priority; disabled Filled in for CMode CLI/ZAPI. Maps to: CMode ZAPI: For "requested_fields", "filter" and Output mapping: $value =item C<< firewall_policy >> Firewall Policy Filled in for CMode CLI/ZAPI. Maps to: CMode ZAPI: For "requested_fields", "filter" and Output mapping: $value =item C<< auto_revert >> Auto Revert Possible Values: true; false Filled in for CMode CLI/ZAPI. Maps to: CMode ZAPI: For "requested_fields", "filter" and Output mapping: $value =item C<< use_failover_group >> Use Failover Group Possible Values: system-defined; enabled; disabled Filled in for CMode CLI/ZAPI. Maps to: CMode ZAPI: For "requested_fields", "filter" and Output mapping: $value =item C<< dns_zone >> DNS Zone Filled in for CMode CLI/ZAPI. Maps to: CMode ZAPI: For "requested_fields", "filter" and Output mapping: $value =item C<< failover_group >> Failover Group Filled in for CMode CLI/ZAPI. Maps to: CMode ZAPI: For "requested_fields", "filter" and Output mapping: $value =item C<< data_protocol >> (array) Data Protocol Possible Values: nfs; cifs; iscsi; fcp; fcache; none Filled in for CMode CLI/ZAPI. Maps to: CMode ZAPI: For "requested_fields", "filter" and Output mapping: @values =item C<< status_extended >> Extended Status =item C<< numeric_id >> Numeric ID Filled in for CMode CLI. =item C<< auto >> IPv4 Link Local Possible Values: true; false =item C<< sticky >> Sticky Flag Possible Values: true; false Filled in for CMode CLI/ZAPI. Maps to: CMode ZAPI: For "requested_fields", "filter" and Output mapping: $value =item C<< allow_lb_migrate >> Load Balancing Migrate Allowed Possible Values: true; false Filled in for CMode CLI/ZAPI. Maps to: CMode ZAPI: For "requested_fields", "filter" and Output mapping: $value =item C<< lb_weight >> Load Balancing Weight Filled in for CMode CLI/ZAPI. Maps to: CMode ZAPI: For "requested_fields", "filter" and Output mapping: $value =item C<< wwpn >> FCP WWPN =item C<< current_rtpid >> Filled in for CMode CLI. =item C<< default_rtpid >> Filled in for CMode CLI. =item C<< address_str >> Filled in for CMode CLI. =item C<< lif_uuid >> Filled in for CMode CLI. =item C<< failover_targets >> (array) Note that for array fields, the accessor method can be invoked in either scalar or list context my $failover_targets = $obj->failover_targets(); # $failover_targets contains a reference to the array of values my @failover_targets = $obj->failover_targets(); # @failover_targets contains the array of values Filled in for CMode CLI. =item C<< current_tpgt >> Filled in for CMode CLI. =item C<< home_node_str >> Filled in for CMode CLI. =item C<< vserver_uuid >> Filled in for CMode CLI. =item C<< port_address >> Filled in for CMode CLI. =item C<< default_tpgt >> Filled in for CMode CLI. =item C<< status_vserver >> Filled in for CMode CLI. =item C<< comment >> Filled in for CMode CLI. =item C<< curr_node_str >> Filled in for CMode CLI. =item C<< listen_for_dns_query >> Filled in for CMode CLI. =item C<< rtpid >> Filled in for CMode CLI. =item C<< address_family >> Filled in for CMode CLI/ZAPI. Maps to: CMode ZAPI: For "requested_fields", "filter" and Output mapping: $value =item C<< ipspace >> Filled in for CMode CLI. =item C<< fabric_name >> Port Fabric name Filled in for CMode CLI. =item C<< speed_oper >> Speed Operational possible value(s) are, auto,10,100,1000,10000 Filled in for CMode CLI. =item C<< fc_port_speed >> Speed of port possible value(s) are, 1,2,4,8,10,auto Filled in for CMode CLI. =item C<< vlan_tag >> VLAN Tag Filled in for CMode CLI. =item C<< port_type >> Port Type possible value(s) are, physical,if-group,vlan Filled in for CMode CLI. =item C<< alua_tpgid >> ALUA tpgid for iSCSI and FCP LIF Filled in for CMode CLI. =item C<< adapter_type >> Port Adapter type possible value(s) are, fc,cna,nic Filled in for CMode CLI. =item C<< auto_configuration >> Use Address Autoconfiguration Filled in for CMode CLI. =item C<< preferred_lifetime >> Preferred Lifetime (autoconf) Filled in for CMode CLI. =item C<< valid_lifetime >> Valid Lifetime (autoconf) Filled in for CMode CLI. =item C<< unassign_only >> unassign-only or delete possible value(s) are, true,false Filled in for CMode CLI. =item C<< is_verify >> Verify LIF Placement possible value(s) are, true,false Filled in for CMode CLI. =item C<< ipv6_address_expiry >> IPv6 address expiry possible value(s) are, true,false Filled in for CMode CLI. =item C<< subnet_name >> Subnet Name Filled in for CMode CLI. =back =cut package NACL::CS::NetworkInterface; use strict; use warnings; use Params::Validate qw(validate validate_with ARRAYREF OBJECT); use NATE::Log qw(log_global); my $Log = log_global(); my $may_enter = $Log->may_enter(); my $may_exit = $Log->may_exit(); use NACL::ComponentUtils qw(Dumper); use NACL::CS::ComponentState::ZapiSkip qw(make_zapi_skip); use NACL::CS::ComponentState::ZapiArray qw(make_zapi_array); use NACL::Global; use base 'NACL::CS::ComponentState::ONTAP'; use Class::MethodMaker [ # These fields are from the C Mode "network interface show" scalar => 'vserver', scalar => 'server', scalar => 'lif', scalar => 'role', scalar => 'home_node', scalar => 'home_port', scalar => 'curr_node', scalar => 'curr_port', scalar => 'status_oper', scalar => 'is_home', scalar => 'address', scalar => 'netmask', scalar => 'netmask_length', scalar => 'routing_group', scalar => 'status_admin', scalar => 'failover_policy', scalar => 'firewall_policy', scalar => 'auto_revert', scalar => 'use_failover_group', scalar => 'dns_zone', scalar => 'failover_group', array => 'data_protocol', scalar => 'status_extended', scalar => 'numeric_id', scalar => 'auto', scalar => 'sticky', scalar => 'allow_lb_migrate', scalar => 'lb_weight', scalar => 'wwpn', scalar => 'vif', scalar => 'current_rtpid', scalar => 'default_rtpid', scalar => 'address_str', scalar => 'lif_uuid', array => 'failover_targets', scalar => 'current_tpgt', scalar => 'home_node_str', scalar => 'vserver_uuid', scalar => 'port_address', scalar => 'default_tpgt', scalar => 'status_vserver', scalar => 'comment', scalar => 'curr_node_str', scalar => 'listen_for_dns_query', scalar => 'rtpid', scalar => 'address_family', scalar => 'ipspace', scalar => 'fabric_name', scalar => 'speed_oper', scalar => 'fc_port_speed', scalar => 'vlan_tag', scalar => 'port_type', scalar => 'alua_tpgid', scalar => 'adapter_type', scalar => 'auto_configuration', scalar => 'valid_lifetime', scalar => 'preferred_lifetime', scalar => 'unassign_only', scalar => 'is_verify', scalar => 'ipv6_address_expiry', scalar => 'subnet_name', scalar => 'is_dns_update_enabled', ]; sub isa { $Log->enter() if $may_enter; my ($pkg_or_obj, $kind) = @_; my $isa = $pkg_or_obj->_build_isa( kind => $kind, alias => 'NACL::CS::Interface' ); $Log->exit() if $may_exit; return $isa; } =head1 METHODS =head2 fetch my $interface_state = NACL::CS::NetworkInterface->fetch(command_interface=>$ci,...); my @interface_states = NACL::CS::NetworkInterface->fetch(command_interface=>$ci,...); see L. Supports CMode CLI/ZAPI. Invokes "net-interface-get-iter" API for CMode ZAPI. Note that in addition to the arguments normally accepted, the fetch() method of this particular CS package accepts some additional options, listed below. =over =item Additional Options =over =item C<< local_to => $obj >> (Optional, should be a Component or ComponentState object) Get interfaces local to the element provided. For example, if local_to => $vol_c_obj Then those interfaces which are local to the volume (i.e. on the same node as the volume) are returned. Note that objects can be provided only if a C method is implemented on the respective component package. =item C<< remote_to => $obj >> (Optional) The type of value provided follows the same restrictions listed for C. When this argument is provided, then those interfaces which are remote to the element (i.e. not on the same node) are returned. =item C<< interfaces_for_volume => $vol_obj >> (Optional, should be a Volume Component or ComponentState object) If provided, returns all interfaces through which the volume can be accessed. =back =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, @args) = @_; my %opts = validate(@args, $pkg->_fetch_validate_spec()); my %extra_opts; $pkg->_hash_move( source => \%opts, target => \%extra_opts, move => [qw(remote_to local_to interfaces_for_volume)] ); if (defined $extra_opts{remote_to} && defined $extra_opts{local_to}) { my $me = (caller(0))[3]; $Log->exit() if $may_exit; NATE::Exceptions::Argument->throw('Either of the arguments ' . "'remote_to' or 'local_to' can be provided in the call to " . "$me but both were"); } my %filter = %{$opts{filter}}; foreach my $opt (qw(remote_to local_to)) { my $value = $extra_opts{$opt}; my $c_obj; if (defined $value) { if ($value->isa('NACL::C::Component::ONTAP')) { $c_obj = $value; } elsif ($value->isa('NACL::CS::ComponentState::ONTAP')) { $c_obj = $value->get_component_instance(); } else { $Log->exit() if $may_exit; NATE::Exceptions::Argument->throw("The value of the '$opt' " . 'argument should have been a Component or CS ' . 'object but was instead provided as a ' . ref($value) . "\n. Dumper of value provided:\n" . Dumper($value)); } if ($c_obj->can('get_local_node_name')) { my $node = $c_obj->get_local_node_name(); if ($opt eq 'local_to') { $filter{'curr-node'} ||= $node; } else { $filter{'curr-node'} ||= "!$node"; } } else { $Log->exit() if $may_exit; NATE::Exceptions::Argument->throw('An object of type ' . ref($value) . " was provided as the value of '$opt' but the " . 'respective component does not have the method ' . "'get_local_node_name' implemented so the node name " . 'could not be determined'); } } } if (defined $extra_opts{interfaces_for_volume}) { $filter{vserver} ||= $extra_opts{interfaces_for_volume}->vserver(); } my @state_objs = $pkg->SUPER::fetch( %opts, show_cmd => 'network interface show', filter => \%filter, choices => [ { method => '_fetch_cmode_cli', interface => 'CLI', set => 'CMode', }, { method => '_fetch_cmode_zapi', interface => 'ZAPI', set => 'CMode', check => '_check_cmode_zapi' }, ], exception_text => 'No matching network interface(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, @args) = @_; my @state_objs = $pkg->SUPER::_fetch_cmode_cli(@args, api => 'network_interface_show'); $Log->exit() if $may_exit; return @state_objs; } ## end sub _fetch_cmode_cli sub _fetch_cmode_zapi { $Log->enter() if $may_enter; my ($pkg, @args) = @_; my @states = $pkg->SUPER::_fetch_cmode_zapi( @args, api => 'net_interface_get_iter', copy => [ qw(role home-node home-port is-home address address-family netmask netmask-length failover-policy firewall-policy sticky use-failover-group lb-weight allow-lb-migrate failover-group vserver subnet-name lif-uuid is-dns-update-enabled ipspace wwpn ) ], map => { 'server' => ['vserver'], 'lif' => ['interface-name'], 'vif' => ['interface-name'], 'curr-node' => ['current-node'], 'curr-port' => ['current-port'], 'status-oper' => ['operational-status'], 'routing-group' => ['routing-group-name'], 'status-admin' => ['administrative-status'], 'auto-revert' => ['is-auto-revert'], 'dns-zone' => ['dns-domain-name'], 'data-protocol' => [ make_zapi_array('data-protocols'), make_zapi_skip('data-protocol') ], }, ); # ZAPI returns the values with underscores while CLI returns # them as hyphenated. Translate the values here. foreach my $state (@states) { my @keys_with_underscored_vals = qw(role failover_policy); foreach my $key (@keys_with_underscored_vals) { my $value = $state->$key(); if (defined $value) { $value =~ s/_/-/g; $state->$key($value); } } } $Log->exit() if $may_exit; return @states; } ## end sub _fetch_cmode_zapi sub _check_cmode_zapi { $Log->enter() if $may_enter; my ( $pkg, %opts ) = @_; if($opts{'command_interface'}->version_manager()->is_version_lt( release => $NACL::Global::ONTAP_Release_Longboard_0 )){ my @invalid_fields = $pkg->_invalid_fields_check( filter => $opts{filter}, requested_fields => $opts{requested_fields}, _fields => [qw( ipspace)] ); if (@invalid_fields) { my $msg = 'The following fields provided ' . 'in the call to NACL::CS::SecurityCertificate->fetch() ' . 'are not returned by the ZAPI, so the ZAPI back-end is being ' . "skipped:\n" . join (', ', @invalid_fields); $Log->comment($msg); $Log->exit() if $may_exit; NACL::Exceptions::InvalidChoice->throw($msg); } } $Log->exit() if $may_exit; } =head1 CANNED FILTERS See http://thebrewery-web.corp.netapp.com/Brewery/brewery/QA/TestAutomation/NACL/UsersGuide/ComponentLayerUsersGuide/index.html#Canned_filters for a description of canned filters. =head2 up_interfaces Returns those interfaces which are up, i.e. "status-admin" and "status-oper" are both "up". =cut sub _canned_filter_up_interfaces { $Log->enter() if $may_enter; $Log->exit() if $may_exit; return {'status-admin' => 'up', 'status-oper' => 'up'}; } =head2 data_interfaces Returns the data interfaces (i.e. role = "data" ) =cut sub _canned_filter_data_interfaces { $Log->enter() if $may_enter; $Log->exit() if $may_exit; return {role => 'data'}; } =head2 up_data_interfaces Returns the data interfaces which are up. (see above for definitions of "up" and "data") =cut sub _canned_filter_up_data_interfaces { $Log->enter() if $may_enter; my ($pkg, @args) = @_; my $up = $pkg->_canned_filter_up_interfaces(@args); my $data = $pkg->_canned_filter_data_interfaces(@args); my $hash = {%$up, %$data}; $Log->exit() if $may_exit; return $hash; } =head2 up_data_nfs_interfaces Returns the up data interfaces (see above) which have nfs as one of their supported data protocols. =cut sub _canned_filter_up_data_nfs_interfaces { $Log->enter() if $may_enter; my ($pkg, @args) = @_; my $hash = $pkg->_up_data_helper(@args, 'data-protocol' => ['nfs']); $Log->exit() if $may_exit; return $hash; } =head2 up_data_cifs_interfaces Returns the up data interfaces (see above) which have cifs as one of their supported data protocols. =cut sub _canned_filter_up_data_cifs_interfaces { $Log->enter() if $may_enter; my ($pkg, @args) = @_; my $hash = $pkg->_up_data_helper(@args, 'data-protocol' => ['cifs']); $Log->exit() if $may_exit; return $hash; } =head2 up_data_iscsi_interfaces Returns the up data interfaces (see above) which have iscsi as one of their supported data protocols. =cut sub _canned_filter_up_data_iscsi_interfaces { $Log->enter() if $may_enter; my ($pkg, @args) = @_; my $hash = $pkg->_up_data_helper(@args, 'data-protocol' => ['iscsi']); $Log->exit() if $may_exit; return $hash; } =head2 up_data_fcache_interfaces Returns the up data interfaces (see above) which have fcache as one of their supported data protocols. =cut sub _canned_filter_up_data_fcache_interfaces { $Log->enter() if $may_enter; my ($pkg, @args) = @_; my $hash = $pkg->_up_data_helper(@args, 'data-protocol' => ['fcache']); $Log->exit() if $may_exit; return $hash; } sub _up_data_helper { $Log->enter() if $may_enter; my ($pkg, @args) = @_; my %opts = validate_with( params => \@args, spec => {'data-protocol' => {type => ARRAYREF}}, # The command_interface is also passed in by default, but we # don't need it yet allow_extra => 1 ); my %data_protocol = ('data-protocol' => delete $opts{'data-protocol'}); my $hash = $pkg->_canned_filter_up_data_interfaces(%opts); $hash = {%$hash, %data_protocol}; $Log->exit() if $may_exit; return $hash; } sub _fetch_validate_spec { $Log->enter() if $may_enter; my $pkg = $_[0]; my $single_spec = {type => OBJECT, optional => 1}; my $super_spec = $pkg->SUPER::_fetch_validate_spec(); $Log->exit() if $may_exit; return { remote_to => $single_spec, local_to => $single_spec, interfaces_for_volume => $single_spec, %$super_spec }; } 1;