# # # Copyright (c) 2011 NetApp, Inc., All Rights Reserved # Any use, modification, or distribution is prohibited # without prior written consent from NetApp, Inc. # # ## @summary Interface ComponentState Module ## @author rawat@netapp.com, nayankumar.patel@netapp.com, dl-nacl-dev@netapp.com ## @status shared ## @pod here ################################################################################ =head1 NAME NACL::CS::Switch::Interface =head1 DESCRIPTION C is a derived class of L. It represents the state of Interface element. A related class is L, which represents access to a Interface element. =head1 ATTRIBUTES The individual pieces of data that are part of the state of the Interface element are the individual attributes of the Interface ComponentState =over =item C<< 'interface-num' >> number of the interface is required on which action will be performed =item C<< 'interface-type' >> type of the interface is required on which action will be performed =item C<< "interface" >> =item C<< "speed" >> =item C<< "duplex" >> =item C<< "running_config" >> (array) =item C<< "status" >> =item C<< "port" >> =item C<< "vlan" >> =item C<< "type" >> =item C<< "tx_fc_admin" >> =item C<< "tx_fc_oper" >> =item C<< "rx_fc_admin" >> =item C<< "rx_fc_oper" >> =item C<< "rx_pause" >> =item C<< "tx_pause" >> =item C<< "name" >> =item C<< "mtu" >> =item C<< "reliability" >> =item C<< "dly" >> =item C<< "hardware" >> =item C<< "switchport_monitor" >> =item C<< "address" >> =item C<< "rxload" >> =item C<< "input_flow_control" >> =item C<< "encapsulation" >> =item C<< "bia" >> =item C<< "media_type" >> =item C<< "output_flow_control" >> =item C<< "txload" >> =item C<< "last_clearing_of_show_interface_counters" >> =item C<< "bw" >> =item C<< "interface_resets" >> =item C<< "tx_collision" >> =item C<< "tx_bytes" >> =item C<< "tx_lost_carrier" >> =item C<< "tx_output_packets" >> =item C<< "tx_late_collision" >> =item C<< "tx_output_errors" >> =item C<< "tx_babble" >> =item C<< "tx_no_carrier" >> =item C<< "tx_deferred" >> =item C<< "rx_bytes" >> =item C<< "rx_underrun" >> =item C<< "rx_giants" >> =item C<< "rx_multicast_packets" >> =item C<< "rx_input_packets" >> =item C<< "rx_no_buffer" >> =item C<< "rx_input_with_dribble" >> =item C<< "rx_crc" >> =item C<< "rx_ignored" >> =item C<< "rx_overrun" >> =item C<< "rx_watchdog" >> =item C<< "rx_input_error" >> =item C<< "rx_runts" >> =item C<< "rx_broadcast_packets" >> # Following are Only Supported on Nexus =item C<< "ethertype" >> =item C<< "port_mode" >> =item C<< "rate_mode" >> =item C<< "description" >> =item C<< "load_interval" >> =item C<< "last_link_flapped" >> =item C<< "beacon" >> =item C<< "_30_seconds_output_rate" >> (array) =item C<< "_30_seconds_input_rate" >> (array) =item C<< "output_rate" >> (array) =item C<< "input_rate" >> (array) =item C<< "tx_unicast_packets" >> =item C<< "tx_multicast_packets" >> =item C<< "tx_jumbo_packets" >> =item C<< "tx_broadcast_packets" >> =item C<< "rx_bad_proto_drop" >> =item C<< "rx_input_discard" >> =item C<< "rx_unicast_packets" >> =item C<< "rx_jumbo_packets" >> =item C<< "rx_short_frame" >> =item C<< "rx_if_down_drop" >> =item C<< "rx_bad_etype_drop" >> =item C<< "rx_storm_suppression_packets" >> # Following are Only Supported on IOS =item C<< "arp_timeout" >> =item C<< "loopback" >> =item C<< "clock_mode" >> =item C<< "output" >> =item C<< "input_queue_drops" >> =item C<< "input_queue_max" >> =item C<< "input_queue_flushes" >> =item C<< "input_queue_size" >> =item C<< "output_hang" >> =item C<< "output_queue_max" >> =item C<< "output_queue_size" >> =item C<< "rx_frame" >> =item C<< "_5_minute_input_rate" >> (array) =item C<< "_5_minute_output_rate" >> (array) =item C<< "output_buffer_failures" >> =item C<< "last_input" >> =item C<< "rx_throttles" >> =item C<< "output_buffers_swapped_out" >> =item C<< "arp_type" >> =item C<< "total_output_drops" >> =item C<< "queueing_strategy" >> =item C<< "keepalive" >> =item C<< "line_protocol" >> =item C<< "link_trap" >> =item C<< "flow_mode" >> =item C<< "lacp_mode" >> =item C<< "link_status" >> =item C<< "physical_mode" >> =item C<< "protocol" >> =item C<< "ok" >> =item C<< "method" >> =item C<< "ip_address" >> =item C<< "link_trap" >> =item C<< "lacp_mode" >> =item C<< "link_status" >> =item C<< "physical_mode" >> =item C<< "ip_ssh_server" >> =item C<< "spanning_tree_configuration" >> =item C<< "snmp_server_community" >> =item C<< "snmp_server_sysname" >> =item C<< "lines" >> =item C<< "line" >> =item C<< "current_sntp_synchronized_time" >> =item C<< "password" >> =item C<< "interfaces" >> =item C<< "rcf_version" >> =item C<< "sntp_server" >> =item C<< "additional_packages" >> =item C<< "sshcon_timeout" >> =item C<< "port_channel" >> =item C<< "system_up_time" >> =item C<< "serviceport_protocol" >> =item C<< "set_prompt" >> =item C<< "enable_password" >> =item C<< "serviceport_ip" >> =item C<< "username" >> =item C<< "system_description" >> =item C<< "system_software_version" >> =item C<< "sntp_client_mode" >> =item C<< "level">> =item C<< "ip_name_server" >> =item C<< "sntp_server_status">> =item C<< "ip_domain_name" >> =item C<< "isdp_timer" >> =item C<< "spanning_tree" >> =back =cut ################### # Package package NACL::CS::Switch::Interface; ################### # Everytime use strict; use warnings; ################### # Module includes use NATE::Log qw(log_global); my $Log = log_global(); my $may_enter = $Log->may_enter(); my $may_exit = $Log->may_exit(); use Params::Validate qw (validate); use NACL::ComponentUtils qw (_dump_one); use NACL::Exceptions::NoElementsFound qw(:try); use NACL::APISet::Exceptions::InvalidParamValueException qw(:try); use base 'NACL::CS::ComponentState::Switch'; use Class::MethodMaker [ new => [ '-hash', 'new' ], # Common for NetAppNetwork and CiscoNetwork Switches scalar => "interface", scalar => "type", # supported on IOS and Nexus scalar => "interface_num", scalar => "interface_type", scalar => "speed", scalar => "duplex", array => "running_config", scalar => "status", scalar => "port", scalar => "vlan", scalar => "tx_fc_admin", scalar => "tx_fc_oper", scalar => "rx_fc_admin", scalar => "rx_fc_oper", scalar => "rx_pause", scalar => "tx_pause", scalar => "name", scalar => "mtu", scalar => "reliability", scalar => "dly", scalar => "hardware", scalar => "switchport_monitor", scalar => "address", scalar => "rxload", scalar => "input_flow_control", scalar => "encapsulation", scalar => "bia", scalar => "media_type", scalar => "output_flow_control", scalar => "txload", scalar => "last_clearing_of_show_interface_counters", scalar => "bw", scalar => "interface_resets", scalar => "tx_collision", scalar => "tx_bytes", scalar => "tx_lost_carrier", scalar => "tx_output_packets", scalar => "tx_late_collision", scalar => "tx_output_errors", scalar => "tx_babble", scalar => "tx_no_carrier", scalar => "tx_deferred", scalar => "rx_bytes", scalar => "rx_underrun", scalar => "rx_giants", scalar => "rx_multicast_packets", scalar => "rx_input_packets", scalar => "rx_no_buffer", scalar => "rx_input_with_dribble", scalar => "rx_crc", scalar => "rx_ignored", scalar => "rx_overrun", scalar => "rx_watchdog", scalar => "rx_input_error", scalar => "rx_runts", scalar => "rx_broadcast_packets", # Only Supported on Nexus scalar => "ethertype", scalar => "port_mode", scalar => "rate_mode", scalar => "description", scalar => "load_interval", scalar => "last_link_flapped", scalar => "beacon", array => "_30_seconds_output_rate", array => "_30_seconds_input_rate", array => "output_rate", array => "input_rate", scalar => "tx_unicast_packets", scalar => "tx_multicast_packets", scalar => "tx_jumbo_packets", scalar => "tx_broadcast_packets", scalar => "rx_bad_proto_drop", scalar => "rx_input_discard", scalar => "rx_unicast_packets", scalar => "rx_jumbo_packets", scalar => "rx_short_frame", scalar => "rx_if_down_drop", scalar => "rx_bad_etype_drop", scalar => "rx_storm_suppression_packets", scalar => "port_ch_no", scalar => "mode", scalar => "reason", scalar => "interface_range", # Only Supported on IOS scalar => "arp_timeout", scalar => "loopback", scalar => "clock_mode", scalar => "output", scalar => "input_queue_drops", scalar => "input_queue_max", scalar => "input_queue_flushes", scalar => "input_queue_size", scalar => "output_hang", scalar => "output_queue_max", scalar => "output_queue_size", scalar => "rx_frame", array => "_5_minute_input_rate", array => "_5_minute_output_rate", scalar => "output_buffer_failures", scalar => "last_input", scalar => "rx_throttles", scalar => "output_buffers_swapped_out", scalar => "arp_type", scalar => "total_output_drops", scalar => "queueing_strategy", scalar => "keepalive", scalar => "line_protocol", # Common for both CN1601 and CN1610 NetAppNetwork Switches scalar => "link_trap", scalar => "lacp_mode", scalar => "physical_mode", scalar => "physical_status", scalar => "admin_mode", scalar => "ip_ssh_server", scalar => "spanning_tree_configuration", scalar => "snmp_server_community", scalar => "snmp_server_sysname", array => "lines", scalar => "line", scalar => "current_sntp_synchronized_time", scalar => "password", array => "interfaces", scalar => "rcf_version", scalar => "sntp_server", array => "additional_packages", scalar => "sshcon_timeout", scalar => "port_channel", scalar => "system_up_time", scalar => "serviceport_protocol", scalar => "set_prompt", scalar => "enable_password", array => "serviceport_ip", scalar => "username", scalar => "system_description", scalar => "system_software_version", scalar => "sntp_client_mode", scalar => "level", scalar => "ip_name_server", scalar => "sntp_server_status", scalar => "ip_domain_name", scalar => "isdp_timer", scalar => "spanning_tree", scalar => [ { '-default_ctor' => sub { $_[0] => status(); }, }, 'link_status', ], # Only Supported on CN1601 scalar => "actor_timeout", # Only Supported on CN1610 scalar => "flow_mode", ]; =head1 METHODS =head2 fetch my $mount_state = NACL::CS::Switch::Interface->fetch(command_interface=>$ci,...); my @mount_states = NACL::CS::Switch::Interface->fetch(command_interface=>$ci,...); see L =cut sub fetch { $Log->enter() if $may_enter; my ($pkg, @opts) = @_; my @state_objs = $pkg->SUPER::fetch( @opts, choices => [ { method => "_fetch_cisconetwork_cli", interface => "CLI", set => "CiscoNetwork" }, { method => "_fetch_netappnetwork_cli", interface => "CLI", set => "NetAppNetwork" }, ], exception_text => 'No matching elements found' ); $Log->exit() if $may_exit; return wantarray ? @state_objs : $state_objs[0]; } ## end sub fetch sub _fetch_cisconetwork_cli { $Log->enter() if $may_enter; my ($pkg, @opts) = @_; my %opts = validate @opts, $pkg->_fetch_backend_validate_spec(); my $apiset = $opts{apiset}; $pkg->_remove_relational_regex_filters( filter => $opts{filter}, requested_fields => $opts{requested_fields} ); my $requested_fields = $opts{requested_fields}; my $filter = $opts{filter}; my %req_field_filter = ( requested_fields => $requested_fields, filter => $filter ); # define variables my ( @output, @state_objs, $response, $obj, $method, $row, $final_output); # get method name based on Switch firmware type my $hosttype = $opts{command_interface}->hostrec()->hosttype(); if ( $hosttype =~ /ios/i ) { $method = "show_interfaces"; } elsif ( $hosttype =~ /nxos/i ) { $method = "show_interface"; } my $i = -1; # provide filter to command itself if primary key is available in filter my %show_args = (); $pkg->_exit_config_modes_cisconetwork(apiset => $apiset); if ( defined( $opts{filter}{'interface-num'} ) && defined( $opts{filter}{'interface-type'} ) ) { # If the user specified the interface-num as range # for example 1/1-4 then command will display all the 4 interfaces # information if ($opts{filter}{'interface-num'} =~/\d+-\d+/) { $show_args{'entity-name'} = delete $opts{filter}{'interface-num'}; $show_args{'entity-type'} = $opts{filter}{'interface-type'}; } else { $show_args{'entity-name'} = $opts{filter}{'interface-num'}; $show_args{'entity-type'} = $opts{filter}{'interface-type'}; } } # get all status attributes my @fields_in_status = qw(name status vlan duplex speed type port ); if ($pkg->_want_any_field_of( %req_field_filter, fields_filled_by_api => \@fields_in_status, ) ) { # get status fields $response = $apiset->$method( field => "status", %show_args, ); $i++; $output[$i] = $response->get_parsed_output(); foreach $row ( @{ $output[$i] } ) { $row->{interface_type} = $pkg->_expand_interface_type( $row->{interface_type} ); } } # get all flowcontrol attribute my @fields_in_fc = qw(tx_fc_admin tx_fc_oper rx_fc_admin rx_fc_oper rx_pause tx_pause); if ($pkg->_want_any_field_of( %req_field_filter, fields_filled_by_api => \@fields_in_fc, ) ) { $response = $apiset->$method( field => "flowcontrol", %show_args, ); $i++; $output[$i] = $response->get_parsed_output(); foreach $row ( @{ $output[$i] } ) { $row->{interface_type} = $pkg->_expand_interface_type( $row->{interface_type} ); $row->{tx_fc_admin} = $row->{fc_send}->{admin}; $row->{tx_fc_oper} = $row->{fc_send}->{oper}; delete $row->{fc_send}; $row->{rx_fc_admin} = $row->{fc_receive}->{admin}; $row->{rx_fc_oper} = $row->{fc_receive}->{oper}; delete $row->{fc_receive}; } } # get running_config attributes my @fields_in_rc = qw(running_config rcf_version); if ( $pkg->_want_any_field_of(%req_field_filter, fields_filled_by_api => \@fields_in_rc) ) { if (defined $show_args{'entity-type'}) { $show_args{entity} = "interface"; } $response = $apiset->show_running_config( %show_args, ); $i++; $output[$i] = $response->get_parsed_output(); foreach $row ( @{ $output[$i] } ) { if ( defined( $row->{interface_type} ) ) { $row->{interface_type} = $pkg->_expand_interface_type( $row->{interface_type} ); } $row->{running_config} = delete $row->{running_conf}; } } my @fields_in_show_brief = qw(port_ch_no mode reason ); if ($pkg->_want_any_field_of( %req_field_filter, fields_filled_by_api => \@fields_in_show_brief, ) ) { if ( $hosttype =~ /nxos/i ) { $response = $apiset->$method(field => "brief",%show_args); $i++; $output[$i] = $response->get_parsed_output(); foreach $row ( @{ $output[$i] } ) { $row->{interface_type} = $pkg->_expand_interface_type( $row->{interface_type} ); } } } # get all counter and other attributes my @fields = qw( mtu reliability dly rate_mode hardware switchport_monitor address description rxload input_flow_control encapsulation load_interval bia media_type output_flow_control port_mode txload last_clearing_of_show_interface_counters bw interface_resets tx_collision tx_bytes tx_lost_carrier tx_output_packets tx_late_collision tx_output_errors tx_babble tx_no_carrier rx_bytes rx_underrun rx_giants rx_multicast_packets rx_input_packets rx_no_buffer rx_input_with_dribble rx_crc rx_ignored rx_overrun rx_watchdog rx_input_error rx_runts ethertype last_link_flapped beacon _30_seconds_output_rate _30_seconds_input_rate output_rate input_rate tx_unicast_packets tx_multicast_packets tx_jumbo_packets tx_broadcast_packets rx_bad_proto_drop rx_input_discard rx_unicast_packets rx_jumbo_packets rx_short_frame rx_if_down_drop rx_bad_etype_drop rx_storm_suppression_packets arp_timeout loopback clock_mode output input_queue_drops input_queue_max input_queue_flushes input_queue_size output_hang output_queue_max output_queue_size rx_frame _5_minute_input_rate _5_minute_output_rate output_buffer_failures last_input rx_throttles output_buffers_swapped_out arp_type total_output_drops queueing_strategy keepalive line_protocol tx_deferred rx_broadcast_packets interface inetrface interface_type interface_num); if ($pkg->_want_any_field_of( %req_field_filter, fields_filled_by_api => \@fields, ) ) { $response = $apiset->$method(%show_args); $i++; $output[$i] = $response->get_parsed_output(); foreach $row ( @{ $output[$i] } ) { if ( defined( $row->{interface_type} ) ) { $row->{interface_type} = $pkg->_expand_interface_type( $row->{interface_type} ); } foreach my $direction ( 'tx', 'rx' ) { if ( defined( $row->{$direction} ) ) { foreach my $counter ( keys %{ $row->{$direction}->[0] } ) { my $field = $direction . "_" . $counter; $row->{$field} = $row->{$direction}->[0]->{$counter}; } delete $row->{$direction}; } } foreach my $queue ( 'input_queue', 'output_queue' ) { if ( defined( $row->{$queue} ) ) { foreach my $q_stat ( keys %{ $row->{$queue}->[0] } ) { my $field = $queue . "_" . $q_stat; $row->{$field} = $row->{$queue}->[0]->{$q_stat}; } delete $row->{$queue}; } } # rename the field value in row my $rename_row_fields = $pkg->_hash_move( source => $row, map => { '5_minute_input_rate' => '_5_minute_input_rate', '5_minute_output_rate' => '_5_minute_output_rate', '30_seconds_output_rate' => '_30_seconds_output_rate', '30_seconds_input_rate' => '_30_seconds_input_rate', collisions => 'tx_collision', output_bytes => 'tx_bytes', lost_carrier => 'tx_lost_carrier', output_packets => 'tx_output_packets', late_collision => 'tx_late_collision', deferred => 'tx_deferred', output_errors => 'tx_output_errors', babbles => 'tx_babble', no_carrier => 'tx_no_carrier', input_bytes => 'rx_bytes', underruns => 'rx_underrun', giants => 'rx_giants', multicasts_received => 'rx_multicast_packets', input_packets => 'rx_input_packets', no_buffer => 'rx_no_buffer', crc => 'rx_crc', ignored => 'rx_ignored', overrun => 'rx_overrun', watchdog => 'rx_watchdog', input_errors => 'rx_input_error', runts => 'rx_runts', broadcasts_received => 'rx_broadcast_packets', frame => 'rx_frame', throttles => 'rx_throttles', input_packets_with_dribble_condition_detected => 'rx_input_with_dribble', }, ); # copy all to $row %{$row} = ( %{$row}, %{$rename_row_fields} ); } } my @ifc; my $first_output = shift(@output); foreach $row ( @{$first_output} ) { foreach my $data (@output) { if (@ifc = grep( ( defined( $_->{interface_type} ) && $_->{interface_type} =~ /$row->{interface_type}/ && $_->{interface_num} =~ /$row->{interface_num}/ ), @{$data} ) ) { %{$row} = ( %{$row}, %{ $ifc[0] } ); } } if ( defined( $row->{port} ) ) { $row->{interface} = $row->{port}; } push( @{$final_output}, $row ); } foreach $row ( @{$final_output} ) { $obj = $pkg->new( command_interface => $opts{command_interface} ); $obj->_set_fields( row => $row ); push @state_objs, $obj; } $Log->exit() if $may_exit; return @state_objs; } ## end sub _fetch_cisconetwork_cli sub _fetch_netappnetwork_cli { $Log->enter() if $may_enter; my ($pkg,@args) = @_; my %opts = validate @args, $pkg->_fetch_backend_validate_spec(); my $apiset = $opts{apiset}; $pkg->_remove_relational_regex_filters( filter => $opts{filter}, requested_fields => $opts{requested_fields} ); my $requested_fields = $opts{requested_fields}; my $filter = $opts{filter}; my %req_field_filter = ( requested_fields => $requested_fields, filter => $filter ); # define variables my @state_objs; # provide filter to command itself if primary key is available in filter my %show_args = (); if ( defined( $opts{filter}{'interface-num'} ) ) { $show_args{'interface'} = $opts{filter}{'interface-num'}; } else { $show_args{'all'} = 1; } my %new_hash; # get all port attributes my @fields_in_port = qw( link_trap flow_mode lacp_mode link_status physical_mode interface_num); if ( $pkg->_want_any_field_of( %req_field_filter, fields_filled_by_api => \@fields_in_port, ) ) { # get port fields my $show_port_response = $apiset->show_port(%show_args); my $output = $show_port_response->get_parsed_output(); foreach my $row ( @{$output} ) { my $interface = $row->{interface}; if (exists($new_hash{$interface})) { %{$new_hash{$interface}} = (%{$new_hash{$interface}}, %{$row}); } else { %{$new_hash{$interface}} = %{$row}; } } } # get all running config attributes # This will not accept any filter fields since command is only 'show running-config'. my @fields_in_running_config = qw(ip_ssh_server spanning_tree_configuration snmp_server_community snmp_server_sysname lines line current_sntp_synchronized_time password interfaces running_config rcf_version sntp_server additional_packages sshcon_timeout port_channel system_up_time serviceport_protocol set_prompt enable_password serviceport_ip username system_description system_software_version sntp_client_mode level ip_name_server sntp_server_status ip_domain_name isdp_timer spanning_tree); if ( $pkg->_want_any_field_of( %req_field_filter, fields_filled_by_api => \@fields_in_running_config, ) ) { my $show_config_response = $apiset->show_running_config(); my $running_config_output = $show_config_response->get_parsed_output(); my $interface; foreach my $row ($running_config_output) { foreach my $interfaces (@{$row->[0]{interfaces}}) { $interface = $interfaces->{interface}; if (exists($new_hash{$interface})) { %{$new_hash{$interface}} = (%{$new_hash{$interface}}, %{$interfaces}); } else { %{$new_hash{$interface}} = %{$interfaces}; } %{$new_hash{$interface}} = (%{$new_hash{$interface}}, %{$row->[0]}); delete $new_hash{$interface}->{interfaces}; } } } my $copy = $pkg->_copy_helper(); my $map = $pkg->_map_helper(); while (my ($key, $value) = each %new_hash) { if ( defined $filter->{'interface-num'}) { if ($filter->{'interface-num'} =~/$value->{interface}/){ my $final_attributes = $pkg->_hash_copy( source => $value, copy => $copy, map => $map ); my $obj = $pkg->new(command_interface => $opts{command_interface}); $obj->_set_fields(row => $final_attributes); push @state_objs, $obj; } } else { my $final_attributes = $pkg->_hash_copy( source => $value, copy => $copy, map => $map ); my $obj = $pkg->new(command_interface => $opts{command_interface}); $obj->_set_fields(row => $final_attributes); push @state_objs, $obj; } } $Log->exit() if $may_exit; return @state_objs; } sub _copy_helper { $Log->enter() if $may_enter; my $copy = [ qw( link_trap flow_mode lacp_mode link_status physical_mode ip_ssh_server spanning_tree_configuration snmp_server_community snmp_server_sysname lines line current_sntp_synchronized_time password running_config rcf_version sntp_server additional_packages sshcon_timeout port_channel system_up_time serviceport_protocol set_prompt enable_password serviceport_ip username system_description system_software_version sntp_client_mode level ip_name_server sntp_server_status ip_domain_name isdp_timer spanning_tree) ]; $Log->exit() if $may_exit; return $copy; } sub _map_helper { $Log->enter() if $may_enter; my $map = { 'interface' => 'interface_num', 'type' => 'interface_type', }; $Log->exit() if $may_exit; return $map; } 1;