Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion lib/cisco_node_utils/cmd_ref/interface.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,11 @@ all_interfaces:
multiple:
ios_xr:
get_command: 'show running all-interfaces'
get_value: '/^interface (.*)/'
nexus:
get_command: "show running-config interface | section '^interface'"
get_value: '/(.*)/'
get_context: ~
get_value: '/^interface (.*)/'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mikewiebe section causes some issues for some providers; e.g. interface_service_vni. See my other comment below.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mikewiebe per IRC I'm going to add a separate all_interfaces getter specific to vni. That seems to be the only provider having issues.


bfd_echo:
_exclude: [ios_xr]
Expand All @@ -40,6 +43,13 @@ create:
set_context: ~
set_value: "interface <name>"

default:
multiple:
set_context: ~
set_value: "default interface <name>"
get_command: "show running interface <name>"
get_value: '/(.*)/'

description:
kind: string
get_value: '/^description (.*)/'
Expand Down
5 changes: 5 additions & 0 deletions lib/cisco_node_utils/cmd_ref/interface_ospf.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ _template:
get_command: 'show running interface all'
context: ["interface %s"]

all_interfaces:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this? We have the same property in interface.yaml (all_interfaces). can it be reused here?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

update: seems like you need it as you changed the object code to call the new yaml properties. what is the reason here? The yaml seems pretty much the same, may be something is missing. could you add a comment?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a pretty big difference now. The self.all_interfaces method in interface.rb uses the show running-config interface | section '^interface' command along with a filter get_value: '/(.*)/' that gets all of the interfaces and associated interface data. We need all of the data so that we can keep track of all interfaces and weather or not the interface is in a default state.

For the other objects interface_portchannel.rb and interface_ospf.rb we only need a simple list of interface names and not the additional data under each interface.

multiple:
get_context: ~
get_value: '/^interface (.*)/'

area:
get_value: '/^\s*ip router ospf (\S+) area (\S+)/'
set_value: "%s ip router ospf %s area %s"
Expand Down
5 changes: 5 additions & 0 deletions lib/cisco_node_utils/cmd_ref/interface_portchannel.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ _template:
get_context: ['/^interface %s$/i']
set_context: ["interface %s"]

all_interfaces:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see my comment above. applies here as well

multiple:
get_context: ~
get_value: '/^interface (.*)/'

bfd_per_link:
kind: boolean
get_value: '/^bfd per-link$/'
Expand Down
53 changes: 45 additions & 8 deletions lib/cisco_node_utils/interface.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# November 2015, Chris Van Heuveln
#
# Copyright (c) 2015-2016 Cisco and/or its affiliates.
# Copyright (c) 2015-2017 Cisco and/or its affiliates.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -51,15 +51,22 @@ class Interface < Cisco::InterfaceDeprecated
# Regexp to match various link bundle interface variants
PORTCHANNEL = Regexp.new('(port-channel|Bundle-Ether)', Regexp::IGNORECASE)

attr_reader :name
attr_reader :name, :state_default

def initialize(name, instantiate=true)
def initialize(name, instantiate=true, default_state=false)
fail TypeError unless name.is_a?(String)
fail ArgumentError unless name.length > 0
@name = name.downcase
@smr = config_get('interface', 'stp_mst_range')
@svr = config_get('interface', 'stp_vlan_range')
@match_found = false
# Keep track of default vs non-default state for
# interfaces that cannot be created/destroyed.
@state_default = nil
# Track ethernet but not sub-interfaces
if @name[/ethernet/] && !@name[/ethernet.*\.\d+/]
@state_default = default_state
end
create if instantiate
end

Expand All @@ -72,10 +79,23 @@ def self.interfaces(opt=nil)
intf_list = config_get('interface', 'all_interfaces')
return hash if intf_list.nil?

# Massage intf_list data into an array that is easy
# to work with.
intf_list.collect! { |x| x.strip || x }
intf_list.delete('')
intf_list = intf_list.join(' ').split('interface')
intf_list.delete('')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mikewiebe This massage doesn't work right with the section option.

      intf_list = node.config_get('interface', 'all_interfaces')
# => ["interface Ethernet5/48", "", "  service instance 22 vni", "", ""]

      intf_list.collect! { |x| x.strip || x }
      intf_list.delete('')
      intf_list = intf_list.join(' ').split('interface')
      intf_list.delete('')
      puts intf_list
# => [" Ethernet5/48 service instance 22 vni"]

There are also other NU providers that use all_interfaces (e.g. interface_service_vni) so this list massage needs to occur for all of those providers.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was a little hasty. This code looks okay here but interface_service_vni needs similar massage code.


intf_list.each do |id|
id = id.downcase
int_data = id.strip.split(' ')
next if int_data[0].nil?
id = int_data[0].downcase
next if opt && filter(opt, id)
hash[id] = Interface.new(id, false)
# If there are any additional options associated
# with this interface then it's in a non-default
# state.
default_state = int_data.size > 1 ? false : true
hash[id] = Interface.new(id, false, default_state)
end
hash
end
Expand Down Expand Up @@ -141,7 +161,16 @@ def create
end

def destroy
config_set('interface', 'destroy', name: @name)
if @name[/ethernet/] && !@name[/ethernet.*\.\d+/]
config_set('interface', 'default', name: @name)
else
config_set('interface', 'destroy', name: @name)
end
end

def default?
state = config_get('interface', 'default', name: @name)
state.nil? ? true : false
end

def pvlan_enable
Expand Down Expand Up @@ -579,6 +608,7 @@ def ipv4_dhcp_relay_info_trust
end

def ipv4_dhcp_relay_info_trust=(state)
return false if !state && !Feature.dhcp_enabled?
Feature.dhcp_enable if state
config_set('interface', 'ipv4_dhcp_relay_info_trust',
name: @name, state: state ? '' : 'no')
Expand All @@ -593,6 +623,7 @@ def ipv4_dhcp_relay_src_addr_hsrp
end

def ipv4_dhcp_relay_src_addr_hsrp=(state)
return false if !state && !Feature.dhcp_enabled?
Feature.dhcp_enable if state
config_set('interface', 'ipv4_dhcp_relay_src_addr_hsrp',
name: @name, state: state ? '' : 'no')
Expand All @@ -611,8 +642,9 @@ def ipv4_dhcp_relay_src_intf

def ipv4_dhcp_relay_src_intf=(val)
state = val == default_ipv4_dhcp_relay_src_intf ? 'no' : ''
intf = val == default_ipv4_dhcp_relay_src_intf ? '' : val
return false if state == 'no' && !Feature.dhcp_enabled?
Feature.dhcp_enable if state.empty?
intf = val == default_ipv4_dhcp_relay_src_intf ? '' : val
config_set('interface', 'ipv4_dhcp_relay_src_intf',
name: @name, state: state, intf: intf)
end
Expand All @@ -626,6 +658,7 @@ def ipv4_dhcp_relay_subnet_broadcast
end

def ipv4_dhcp_relay_subnet_broadcast=(state)
return false if !state && !Feature.dhcp_enabled?
Feature.dhcp_enable if state
config_set('interface', 'ipv4_dhcp_relay_subnet_broadcast',
name: @name, state: state ? '' : 'no')
Expand All @@ -640,6 +673,7 @@ def ipv4_dhcp_smart_relay
end

def ipv4_dhcp_smart_relay=(state)
return false if !state && !Feature.dhcp_enabled?
Feature.dhcp_enable if state
config_set('interface', 'ipv4_dhcp_smart_relay',
name: @name, state: state ? '' : 'no')
Expand Down Expand Up @@ -788,8 +822,9 @@ def ipv6_dhcp_relay_src_intf

def ipv6_dhcp_relay_src_intf=(val)
state = val == default_ipv6_dhcp_relay_src_intf ? 'no' : ''
intf = val == default_ipv6_dhcp_relay_src_intf ? '' : val
return false if state == 'no' && !Feature.dhcp_enabled?
Feature.dhcp_enable if state.empty?
intf = val == default_ipv6_dhcp_relay_src_intf ? '' : val
config_set('interface', 'ipv6_dhcp_relay_src_intf',
name: @name, state: state, intf: intf)
end
Expand Down Expand Up @@ -1831,6 +1866,8 @@ def switchport_vtp
def switchport_vtp=(vtp_set)
# TODO: throw UnsupportedError instead of returning false?
return false unless switchport_vtp_mode_capable?
return false if !vtp_set && !Feature.vtp_enabled?
Feature.vtp_enable if vtp_set
no_cmd = (vtp_set) ? '' : 'no'
config_set('interface', 'vtp', name: @name, state: no_cmd)
end
Expand Down
4 changes: 2 additions & 2 deletions lib/cisco_node_utils/interface_ospf.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# March 2015, Alex Hunsberger
#
# Copyright (c) 2015-2016 Cisco and/or its affiliates.
# Copyright (c) 2015-2017 Cisco and/or its affiliates.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -53,7 +53,7 @@ def self.interfaces(ospf_name=nil)
fail TypeError unless ospf_name.is_a?(String) || ospf_name.nil?
ints = {}

intf_list = config_get('interface', 'all_interfaces')
intf_list = config_get('interface_ospf', 'all_interfaces')
return ints if intf_list.nil?
intf_list.each do |name|
match = config_get('interface_ospf', 'area', name)
Expand Down
4 changes: 2 additions & 2 deletions lib/cisco_node_utils/interface_portchannel.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# December 2015, Sai Chintalapudi
#
# Copyright (c) 2015-2016 Cisco and/or its affiliates.
# Copyright (c) 2015-2017 Cisco and/or its affiliates.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -38,7 +38,7 @@ def to_s

def self.interfaces
hash = {}
intf_list = config_get('interface', 'all_interfaces')
intf_list = config_get('interface_portchannel', 'all_interfaces')
return hash if intf_list.nil?

intf_list.each do |id|
Expand Down
4 changes: 2 additions & 2 deletions tests/test_bgp_af.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#
# Richard Wellum, August, 2015
#
# Copyright (c) 2015-2016 Cisco and/or its affiliates.
# Copyright (c) 2015-2017 Cisco and/or its affiliates.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -170,7 +170,7 @@ def check_test_exceptions(test_, os_, vrf_, af_)
# triggers a version check below.
if expect == :runtime
case Platform.image_version
when /8.0|8.1/
when /8.0|8.1|8.2/
expect = :success
when /I5.2|I5.3|I6/
expect = :success if test == :maximum_paths || test == :maximum_paths_ibgp
Expand Down
24 changes: 23 additions & 1 deletion tests/test_interface.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (c) 2013-2016 Cisco and/or its affiliates.
# Copyright (c) 2013-2017 Cisco and/or its affiliates.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -1837,6 +1837,28 @@ def test_load_interval_counter_3_delay
lb.destroy
end

def test_default_physical
name = interfaces[0]
int = Interface.new(name)
int.switchport_mode = :disabled

# Verify l3 -> default
int.description = 'default_pysical'
int.ipv4_addr_mask_set('192.168.0.1', '24')
refute(int.default?)

int.destroy
assert(int.default?)

# Verify l2 trunk -> default
int.switchport_mode = :access
int.switchport_autostate_exclude = true
refute(int.default?)

int.destroy
assert(int.default?)
end

def test_purge_config
name = interfaces[0]
int = Interface.new(name)
Expand Down