From 0dcb2b95dd3b12dd2f68b04b45e85fde3bc89e22 Mon Sep 17 00:00:00 2001 From: saichint Date: Wed, 26 Sep 2018 12:23:26 -0700 Subject: [PATCH 01/27] Fix interface default issues (#598) * fix vpc_peer_link * fix interface default issues --- lib/cisco_node_utils/interface.rb | 6 +++--- tests/test_interface.rb | 12 +++++------- tests/test_interface_private_vlan.rb | 12 ++++++++++++ tests/test_interface_switchport.rb | 6 +----- 4 files changed, 21 insertions(+), 15 deletions(-) diff --git a/lib/cisco_node_utils/interface.rb b/lib/cisco_node_utils/interface.rb index e2dd3d95..a91b2f39 100644 --- a/lib/cisco_node_utils/interface.rb +++ b/lib/cisco_node_utils/interface.rb @@ -1085,7 +1085,7 @@ def storm_control_multicast end def storm_control_multicast=(val) - return if val == storm_control_broadcast + return if val == storm_control_multicast state = val == default_storm_control_multicast ? 'no' : '' level = val == default_storm_control_multicast ? '' : val config_set('interface', 'storm_control_multicast', @@ -1102,7 +1102,7 @@ def storm_control_unicast end def storm_control_unicast=(val) - return if val == storm_control_broadcast + return if val == storm_control_unicast state = val == default_storm_control_unicast ? 'no' : '' level = val == default_storm_control_unicast ? '' : val config_set('interface', 'storm_control_unicast', @@ -2025,7 +2025,7 @@ def vpc_peer_link end def vpc_peer_link=(state) - return if vpc_peerlink == state + return if vpc_peer_link == state no_cmd = (state ? '' : 'no') config_set('interface', 'vpc_peer_link', name: @name, state: no_cmd) end diff --git a/tests/test_interface.rb b/tests/test_interface.rb index 8966b449..83ae2d6c 100755 --- a/tests/test_interface.rb +++ b/tests/test_interface.rb @@ -346,6 +346,8 @@ def validate_get_access_vlan(inttype_h) # Validate the collection inttype_h.each_value do |v| interface = v[:interface] + next if interface.name[/vlan|loopback/] + interface.switchport_mode = :access assert_equal(v[:access_vlan], interface.access_vlan, 'Error: Access vlan value not correct') @@ -353,6 +355,7 @@ def validate_get_access_vlan(inttype_h) # get_default check assert_equal(v[:default_access_vlan], interface.default_access_vlan, 'Error: Access vlan, default, value not correct') + interface.switchport_mode = :disabled end end @@ -856,8 +859,7 @@ def test_negotiate_auto_loopback config("interface #{int}") interface = Interface.new(int) - assert_equal(interface.negotiate_auto, ref.default_value, - "Error: #{int} negotiate auto value mismatch") + assert_nil(interface.negotiate_auto) assert_raises(Cisco::UnsupportedError) do interface.negotiate_auto = true @@ -1328,8 +1330,6 @@ def interface_test_data default_shutdown: true, switchport: :disabled, default_switchport: :disabled, - access_vlan: DEFAULT_IF_ACCESS_VLAN, - default_access_vlan: DEFAULT_IF_ACCESS_VLAN, vrf_new: 'test2', default_vrf: DEFAULT_IF_VRF, } @@ -1362,8 +1362,6 @@ def interface_test_data default_shutdown: false, switchport: platform == :ios_xr ? nil : :disabled, default_switchport: platform == :ios_xr ? nil : :disabled, - access_vlan: DEFAULT_IF_ACCESS_VLAN, - default_access_vlan: DEFAULT_IF_ACCESS_VLAN, vrf_new: 'test2', default_vrf: DEFAULT_IF_VRF, } @@ -1411,12 +1409,12 @@ def test_ipv4_all_interfaces validate_interfaces_not_empty validate_get_switchport(inttype_h) validate_description(inttype_h) - validate_get_access_vlan(inttype_h) unless platform == :ios_xr validate_ipv4_address(inttype_h) validate_ipv4_proxy_arp(inttype_h) validate_ipv4_redirects(inttype_h) validate_interface_shutdown(inttype_h) validate_vrf(inttype_h) + validate_get_access_vlan(inttype_h) unless platform == :ios_xr config(*cfg) interface_ethernet_default(interfaces[1]) rescue Minitest::Assertion diff --git a/tests/test_interface_private_vlan.rb b/tests/test_interface_private_vlan.rb index f4fda2bc..a4fbec5e 100755 --- a/tests/test_interface_private_vlan.rb +++ b/tests/test_interface_private_vlan.rb @@ -88,6 +88,7 @@ def test_switchport_pvlan_host return end + i.switchport_mode = :access assert_equal(i.default_switchport_pvlan_host, i.switchport_pvlan_host) @@ -96,6 +97,7 @@ def test_switchport_pvlan_host i.switchport_pvlan_host = false refute(i.switchport_pvlan_host) + i.switchport_mode = :disabled end def test_sw_pvlan_promiscuous @@ -107,6 +109,7 @@ def test_sw_pvlan_promiscuous return end + i.switchport_mode = :access assert_equal(i.default_switchport_pvlan_promiscuous, i.switchport_pvlan_promiscuous) @@ -115,6 +118,7 @@ def test_sw_pvlan_promiscuous i.switchport_pvlan_promiscuous = false refute(i.switchport_pvlan_promiscuous) + i.switchport_mode = :disabled end def test_sw_pvlan_trunk_promiscuous @@ -126,6 +130,7 @@ def test_sw_pvlan_trunk_promiscuous return end + i.switchport_mode = :access assert_equal(i.default_switchport_pvlan_trunk_promiscuous, i.switchport_pvlan_trunk_promiscuous) @@ -134,6 +139,7 @@ def test_sw_pvlan_trunk_promiscuous i.switchport_pvlan_trunk_promiscuous = false refute(i.switchport_pvlan_trunk_promiscuous) + i.switchport_mode = :disabled end def test_sw_pvlan_trunk_secondary @@ -145,6 +151,7 @@ def test_sw_pvlan_trunk_secondary return end + i.switchport_mode = :access assert_equal(i.default_switchport_pvlan_trunk_secondary, i.switchport_pvlan_trunk_secondary) @@ -153,6 +160,7 @@ def test_sw_pvlan_trunk_secondary i.switchport_pvlan_trunk_secondary = false refute(i.switchport_pvlan_trunk_secondary) + i.switchport_mode = :disabled end # Helper to setup vlan associations @@ -309,6 +317,7 @@ def test_sw_pvlan_trunk_allowed_vlan return end + i.switchport_mode = :access default = i.default_switchport_pvlan_trunk_allowed_vlan assert_equal(default, i.switchport_pvlan_trunk_allowed_vlan) @@ -325,6 +334,7 @@ def test_sw_pvlan_trunk_allowed_vlan vlans = '500-528,530,532,534,587,590-593,597-598,600,602,604' i.switchport_pvlan_trunk_allowed_vlan = vlans assert_equal(vlans, i.switchport_pvlan_trunk_allowed_vlan) + i.switchport_mode = :disabled end def test_sw_pvlan_trunk_native_vlan @@ -336,6 +346,7 @@ def test_sw_pvlan_trunk_native_vlan return end + i.switchport_mode = :access default = i.default_switchport_pvlan_trunk_native_vlan assert_equal(default, i.switchport_pvlan_trunk_native_vlan) @@ -344,5 +355,6 @@ def test_sw_pvlan_trunk_native_vlan i.switchport_pvlan_trunk_native_vlan = default assert_equal(default, i.switchport_pvlan_trunk_native_vlan) + i.switchport_mode = :disabled end end diff --git a/tests/test_interface_switchport.rb b/tests/test_interface_switchport.rb index 05bd5f1b..e3341229 100755 --- a/tests/test_interface_switchport.rb +++ b/tests/test_interface_switchport.rb @@ -80,11 +80,7 @@ def test_access_vlan def test_access_vlan_sw_disabled interface.switchport_mode = :disabled - if platform == :ios_xr - assert_nil(interface.access_vlan) - else - assert_equal(DEFAULT_IF_ACCESS_VLAN, interface.access_vlan) - end + assert_nil(interface.access_vlan) end def test_access_vlan_sw_trunk From a3fe991c94c0fe805fac7126b15842e363b73f5e Mon Sep 17 00:00:00 2001 From: saichint Date: Fri, 12 Oct 2018 12:32:24 -0700 Subject: [PATCH 02/27] Fixes for n9k-f and n3k-f (#599) * n9k vs n9k-f fix * n3k vs n3k-f * fix n3-f product_tag * fix fragments * vtp removed for fretta * ingress-replication removed for fretta * fix test_get_product_id * fix nxapi test_upsipported * fix upgrade test image regex * fix fm-r vs -r --- lib/cisco_node_utils/cisco_cmn_utils.rb | 8 ++++++ lib/cisco_node_utils/cmd_ref/acl.yaml | 2 +- lib/cisco_node_utils/cmd_ref/feature.yaml | 1 + lib/cisco_node_utils/cmd_ref/vtp.yaml | 2 +- .../cmd_ref/vxlan_vtep_vni.yaml | 4 +-- lib/cisco_node_utils/node.rb | 28 ++++--------------- tests/ciscotest.rb | 4 +-- tests/cmd_config.yaml | 2 -- tests/test_acl.rb | 2 +- tests/test_interface_switchport.rb | 5 ++-- tests/test_node_ext.rb | 2 +- tests/test_nxapi.rb | 24 +++++++++++----- tests/test_upgrade.rb | 2 +- 13 files changed, 44 insertions(+), 42 deletions(-) diff --git a/lib/cisco_node_utils/cisco_cmn_utils.rb b/lib/cisco_node_utils/cisco_cmn_utils.rb index 2e03cc04..a29420bd 100644 --- a/lib/cisco_node_utils/cisco_cmn_utils.rb +++ b/lib/cisco_node_utils/cisco_cmn_utils.rb @@ -113,6 +113,14 @@ def self.chassis_pid?(ver_regexp) return true if Platform.chassis['pid'][ver_regexp] end + def self.fretta? + require_relative 'platform' + Platform.slots.each do |_x, row| + return true if row['pid'][/-R/] + end + false + end + # Helper utility method for ip/prefix format networks. # For ip/prefix format '1.1.1.1/24' or '2000:123:38::34/64', # we need to mask the address using the prefix length so that they diff --git a/lib/cisco_node_utils/cmd_ref/acl.yaml b/lib/cisco_node_utils/cmd_ref/acl.yaml index 246229c6..4e47547e 100644 --- a/lib/cisco_node_utils/cmd_ref/acl.yaml +++ b/lib/cisco_node_utils/cmd_ref/acl.yaml @@ -36,7 +36,7 @@ all_acls: fragments: # Note: The ACL 'fragments' keyword is independent of ACE 'fragments' - _exclude: [N5k, N6k] + _exclude: [N5k, N6k, N3k-F, N9k-F] get_value: '/fragments (\S+)$/' set_value: ' fragments ' default_value: ~ diff --git a/lib/cisco_node_utils/cmd_ref/feature.yaml b/lib/cisco_node_utils/cmd_ref/feature.yaml index bd0fde8a..3b353278 100644 --- a/lib/cisco_node_utils/cmd_ref/feature.yaml +++ b/lib/cisco_node_utils/cmd_ref/feature.yaml @@ -113,6 +113,7 @@ vni: set_value: 'feature vn-segment-vlan-based' vtp: + _exclude: [N3k-F, N9k-F] kind: boolean get_value: '/^feature vtp$/' set_value: " feature vtp" diff --git a/lib/cisco_node_utils/cmd_ref/vtp.yaml b/lib/cisco_node_utils/cmd_ref/vtp.yaml index 03eff2ba..4e19559b 100644 --- a/lib/cisco_node_utils/cmd_ref/vtp.yaml +++ b/lib/cisco_node_utils/cmd_ref/vtp.yaml @@ -1,6 +1,6 @@ # vtp --- -_exclude: [ios_xr] +_exclude: [ios_xr, N3k-F, N9k-F] # VTP behaves differently across the various Nexus platforms and as a # result it's not currently possible to use a single 'show running' diff --git a/lib/cisco_node_utils/cmd_ref/vxlan_vtep_vni.yaml b/lib/cisco_node_utils/cmd_ref/vxlan_vtep_vni.yaml index 65bf23b3..9854e3b3 100644 --- a/lib/cisco_node_utils/cmd_ref/vxlan_vtep_vni.yaml +++ b/lib/cisco_node_utils/cmd_ref/vxlan_vtep_vni.yaml @@ -16,7 +16,7 @@ all_vnis: get_value: '/^member vni (\d+|\d+-\d+) ?(associate-vrf)?$/' ingress_replication: - _exclude: [N5k, N6k, N7k] + _exclude: [N3k-F, N5k, N6k, N7k, N9k-F] kind: string get_value: '/^ingress-replication protocol (\S+)$/' set_value: ' ingress-replication protocol ' @@ -35,7 +35,7 @@ multisite_ingress_replication: default_value: false peer_list: - _exclude: [N5k, N6k, N7k] + _exclude: [N3k-F, N5k, N6k, N7k, N9k-F] multiple: get_context: - '/^interface $/i' diff --git a/lib/cisco_node_utils/node.rb b/lib/cisco_node_utils/node.rb index bde05460..ae59e11e 100644 --- a/lib/cisco_node_utils/node.rb +++ b/lib/cisco_node_utils/node.rb @@ -357,33 +357,17 @@ def product_id def prod_qualifier(prod, inventory) case prod - when /N9K/ - # Two datapoints are used to determine if the current n9k - # platform is a fretta based n9k or non-fretta. + when /N(3|9)K/ + # one datapoint is used to determine if the current n9k/n3k + # platform is a fretta based or non-fretta. # - # 1) Image Version == 7.0(3)F* - # 2) Fabric Module == N9K-C9*-FM-R - if @cmd_ref - ver = os_version - else - ver = get(command: 'show version', - data_format: :nxapi_structured)['kickstart_ver_str'] - end - # Append -F for fretta platform. + # Module == *-R inventory.each do |row| - if row['productid'][/N9K-C9...-FM-R/] && ver[/7.0\(3\)F/] + if row['productid'][/-R/] + # Append -F for fretta platform. return prod.concat('-F') unless prod[/-F/] end end - when /N3K/ - if @cmd_ref - ver = os_version - else - ver = get(command: 'show version', - data_format: :nxapi_structured)['kickstart_ver_str'] - end - # Append -F for fretta platform. - return prod.concat('-F') if ver[/7.0\(3\)F/] && !prod[/-F/] end prod end diff --git a/tests/ciscotest.rb b/tests/ciscotest.rb index 6cd6ad27..37e8ba18 100644 --- a/tests/ciscotest.rb +++ b/tests/ciscotest.rb @@ -550,7 +550,7 @@ def product_tag when /N3K-C35/ tag = 'n35' when /N3/ - tag = Utils.image_version?(/7.0.3.F/) ? 'n3k-f' : 'n3k' + tag = Utils.fretta? ? 'n3k-f' : 'n3k' when /N5/ tag = 'n5k' when /N6/ @@ -558,7 +558,7 @@ def product_tag when /N7/ tag = 'n7k' when /N9/ - tag = Utils.image_version?(/7.0.3.F/) ? 'n9k-f' : 'n9k' + tag = Utils.fretta? ? 'n9k-f' : 'n9k' else fail "Unrecognized product_id: #{@product_id}" end diff --git a/tests/cmd_config.yaml b/tests/cmd_config.yaml index e7cbb992..f4b05497 100644 --- a/tests/cmd_config.yaml +++ b/tests/cmd_config.yaml @@ -12,7 +12,6 @@ nexus: feature hsrp feature lacp feature dhcp - feature vtp feature-disable: command: | @@ -25,7 +24,6 @@ nexus: no feature hsrp no feature lacp no feature dhcp - no feature vtp nvgen: false feature-snmp-comm-acl-ro: diff --git a/tests/test_acl.rb b/tests/test_acl.rb index a5438245..6e346664 100644 --- a/tests/test_acl.rb +++ b/tests/test_acl.rb @@ -169,7 +169,7 @@ def fragments(afi, acl_name) end def test_fragments - if node.product_id[/N(5|6)/] + if product_tag[/n(3k-f|5k|6k|9k-f)/] a = Acl.new('ipv4', 'acl_fragments') assert_nil(a.fragments) assert_nil(a.default_fragments) diff --git a/tests/test_interface_switchport.rb b/tests/test_interface_switchport.rb index e3341229..dc09ae08 100755 --- a/tests/test_interface_switchport.rb +++ b/tests/test_interface_switchport.rb @@ -410,12 +410,13 @@ class TestInterfaceSwVtp < TestInterfaceSwitchport def setup super - skip('VTP is not supported on IOS XR') if platform == :ios_xr + skip('VTP is not supported on IOS XR or fretta') if + platform == :ios_xr || product_tag[/n(3|9)k-f/] @vtp = Vtp.new(true) end def teardown - vtp.destroy unless platform == :ios_xr + vtp.destroy unless platform == :ios_xr || product_tag[/n(3|9)k-f/] super end diff --git a/tests/test_node_ext.rb b/tests/test_node_ext.rb index 590a411e..07a82641 100644 --- a/tests/test_node_ext.rb +++ b/tests/test_node_ext.rb @@ -142,7 +142,7 @@ def test_get_product_description def test_get_product_id # N3|9K Fretta product_id gets a '-F' appended so remove it for this check - if Utils.image_version?(/7.0.3.F/) + if product_tag[/n(3|9)k-f/] chassis = node.product_id.sub('-F', '') else chassis = node.product_id diff --git a/tests/test_nxapi.rb b/tests/test_nxapi.rb index ff8b1235..17c2c2e1 100644 --- a/tests/test_nxapi.rb +++ b/tests/test_nxapi.rb @@ -14,11 +14,11 @@ # See the License for the specific language governing permissions and # limitations under the License. -require_relative 'basetest' +require_relative 'ciscotest' require_relative '../lib/cisco_node_utils/node' # TestNxapi - NXAPI client unit tests -class TestNxapi < TestCase +class TestNxapi < CiscoTestCase @@client = nil # rubocop:disable Style/ClassVars def self.runnable_methods @@ -207,12 +207,22 @@ def client.password=(new) # rubocop:disable Style/TrivialAccessors def test_unsupported # Add a method to the NXAPI that sends a request of invalid type - def client.hello - req('hello', 'world') - end + if !product_tag[/n(3|9)k-f/] + def client.hello + req('hello', 'world') + end + + assert_raises Cisco::RequestNotSupported do + client.hello + end + else + def client.hello + req('hello', 'world') + end - assert_raises Cisco::RequestNotSupported do - client.hello + assert_raises Cisco::ClientError do + client.hello + end end end diff --git a/tests/test_upgrade.rb b/tests/test_upgrade.rb index 1f7d8c68..d83d75f0 100755 --- a/tests/test_upgrade.rb +++ b/tests/test_upgrade.rb @@ -71,7 +71,7 @@ def test_delete_negative def test_image_version version = Upgrade.image_version - assert_match(/^\d.\d\(\d\)\S+\(\S+\)$/, version) + assert_match(/^\d.\d\(\d(?:.\d+)?\)(?:\S+\(\S+\))?$/, version) end def test_box_online From 4e0e66d76dded6aa437993fd04748dde3db6ffaa Mon Sep 17 00:00:00 2001 From: Mike Wiebe Date: Wed, 24 Oct 2018 15:09:07 -0400 Subject: [PATCH 03/27] Add 7_0_3_I4_8_ label --- tests/yum_package.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/yum_package.yaml b/tests/yum_package.yaml index 1e209259..ebacccf1 100644 --- a/tests/yum_package.yaml +++ b/tests/yum_package.yaml @@ -43,6 +43,11 @@ name: 'nxos.sample-n9k_EOR' version: '1.0.0-7.0.3.I4.6' +7_0_3_I4_8_: + filename: 'nxos.sample-n9k_EOR-1.0.0-7.0.3.I4.8.lib32_n9000.rpm' + name: 'nxos.sample-n9k_EOR' + version: '1.0.0-7.0.3.I4.8' + 7_0_3_I5_1_: filename: 'nxos.sample-n9k_ALL-1.0.0-7.0.3.I5.1.lib32_n9000.rpm' name: 'nxos.sample-n9k_ALL' From 20adf44f1e353440c9d4c35d9eb0701afaee98b7 Mon Sep 17 00:00:00 2001 From: Dave Armstrong Date: Wed, 21 Nov 2018 14:03:05 +0000 Subject: [PATCH 04/27] Allow node cache to be reset. (#601) As each class inherits directly from `node_util`, each class has its own cache of `node`. This removes the per class cache. Additionally a reset has been added that can be called prior to `Environment` allowing the new environment settings to be used. --- CHANGELOG.md | 8 ++++++++ lib/cisco_node_utils/node.rb | 5 +++++ lib/cisco_node_utils/node_util.rb | 2 +- 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d9ebb746..0d6924b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,14 @@ Changelog ========= +## [Unreleased] + +### Added + * `reset_instance` method to node. Allows a single instance of nodeutils to reset the environment cache. + +### Removed + * Removed cache in `node_util.node`, which gave every inheriting class it's own cache. + ## [v1.10.0] ### New Cisco Resources diff --git a/lib/cisco_node_utils/node.rb b/lib/cisco_node_utils/node.rb index ae59e11e..b6a5d46d 100644 --- a/lib/cisco_node_utils/node.rb +++ b/lib/cisco_node_utils/node.rb @@ -237,6 +237,11 @@ def self.instance @instance ||= new end + # Allow instance cache to be reset + def self.reset_instance + @instance = nil + end + def initialize @client = Cisco::Client.create @cmd_ref = nil diff --git a/lib/cisco_node_utils/node_util.rb b/lib/cisco_node_utils/node_util.rb index b98ff87d..63bc3b6a 100644 --- a/lib/cisco_node_utils/node_util.rb +++ b/lib/cisco_node_utils/node_util.rb @@ -21,7 +21,7 @@ module Cisco # NodeUtil - generic functionality for node utility subclasses to use class NodeUtil def self.node - @node ||= Cisco::Node.instance + Cisco::Node.instance end def node From b64a643c02d322d8e3b4ab9182a524006e4529d7 Mon Sep 17 00:00:00 2001 From: saichint Date: Mon, 26 Nov 2018 10:21:56 -0800 Subject: [PATCH 05/27] Add new CLIs for Vxlan Vtep (#600) * add suppress_arp_disable to vni * doc * add vxlan_vtep global params * doc * fix nv overlay evpn req * copyright --- CHANGELOG.md | 15 +++- lib/cisco_node_utils/cmd_ref/vxlan_vtep.yaml | 30 +++++++ .../cmd_ref/vxlan_vtep_vni.yaml | 7 ++ lib/cisco_node_utils/vxlan_vtep.rb | 87 ++++++++++++++++++- lib/cisco_node_utils/vxlan_vtep_vni.rb | 33 ++++++- tests/test_vxlan_vtep.rb | 78 ++++++++++++++++- tests/test_vxlan_vtep_vni.rb | 30 ++++++- 7 files changed, 275 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d6924b0..418ecaf1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,12 +3,25 @@ Changelog ## [Unreleased] +### New Cisco Resources + ### Added - * `reset_instance` method to node. Allows a single instance of nodeutils to reset the environment cache. +* `reset_instance` method to node. Allows a single instance of nodeutils to reset the environment cache. +* Extend vxlan_vtep_vni with attribute: + * `suppress_arp_disable` +* Extend vxlan_vtep with attributes: + * `global_suppress_arp` + * `global_ingress_replication_bgp` + * `global_mcast_group_l2` + * `global_mcast_group_l3` ### Removed * Removed cache in `node_util.node`, which gave every inheriting class it's own cache. +### Changed + +### Removed + ## [v1.10.0] ### New Cisco Resources diff --git a/lib/cisco_node_utils/cmd_ref/vxlan_vtep.yaml b/lib/cisco_node_utils/cmd_ref/vxlan_vtep.yaml index 14ac75fc..e03a9c04 100644 --- a/lib/cisco_node_utils/cmd_ref/vxlan_vtep.yaml +++ b/lib/cisco_node_utils/cmd_ref/vxlan_vtep.yaml @@ -12,6 +12,36 @@ all_interfaces: get_context: ~ get_value: '/^interface (.*)$/' +global_ingress_replication_bgp: + _exclude: [N3k-F, N5k, N6k, N7k, N9k-F] + os_version: 'N9k:9.2' + kind: boolean + get_value: '/^global ingress-replication protocol bgp$/' + set_value: ' global ingress-replication protocol bgp' + default_value: false + +global_mcast_group_l2: + _exclude: [N3k-F, N5k, N6k, N7k] + os_version: 'N9k, N9k-F:9.2' + get_value: '/^global mcast-group (\S+) L2$/' + set_value: ' global mcast-group L2' + default_value: ~ + +global_mcast_group_l3: + _exclude: [N3k-F, N5k, N6k, N7k, N9k-F] + os_version: 'N9k:9.2' + get_value: '/^global mcast-group (\S+) L3$/' + set_value: ' global mcast-group L3' + default_value: ~ + +global_suppress_arp: + _exclude: [N3k-F, N5k, N6k, N7k] + os_version: 'N9k, N9k-F:9.2' + kind: boolean + get_value: '/^global suppress-arp$/' + set_value: ' global suppress-arp' + default_value: false + host_reachability: get_value: '/^host-reachability protocol (\S+)/' set_value: ' host-reachability protocol ' diff --git a/lib/cisco_node_utils/cmd_ref/vxlan_vtep_vni.yaml b/lib/cisco_node_utils/cmd_ref/vxlan_vtep_vni.yaml index 9854e3b3..d4f72ebd 100644 --- a/lib/cisco_node_utils/cmd_ref/vxlan_vtep_vni.yaml +++ b/lib/cisco_node_utils/cmd_ref/vxlan_vtep_vni.yaml @@ -55,6 +55,13 @@ suppress_arp: set_value: ' suppress-arp' default_value: false +suppress_arp_disable: + _exclude: [N3k-F, N5k, N6k, N7k] + os_version: 'N9k, N9k-F:9.2' + get_value: '/^suppress-arp disable$/' + set_value: ' suppress-arp disable' + default_value: ~ + suppress_uuc: _exclude: [N3k-F, N9k-F, N9k] os_version: 'N7k:8.1.1' diff --git a/lib/cisco_node_utils/vxlan_vtep.rb b/lib/cisco_node_utils/vxlan_vtep.rb index 0beb61c7..78389e8f 100644 --- a/lib/cisco_node_utils/vxlan_vtep.rb +++ b/lib/cisco_node_utils/vxlan_vtep.rb @@ -3,7 +3,7 @@ # # November 2015, Deepak Cherian # -# Copyright (c) 2015-2016 Cisco and/or its affiliates. +# Copyright (c) 2015-2018 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. @@ -197,5 +197,90 @@ def multisite_border_gateway_interface=(val) def default_multisite_border_gateway_interface config_get_default('vxlan_vtep', 'multisite_bg_intf') end + + def global_ingress_replication_bgp + config_get('vxlan_vtep', 'global_ingress_replication_bgp', name: @name) + end + + def global_ingress_replication_bgp=(state) + set_args = { name: @name } + if state + set_args[:state] = '' + # Host reachability must be enabled for this property + unless VxlanVtep.new(@name).host_reachability == 'evpn' + fail "Dependency: vxlan_vtep host_reachability must be 'evpn'." + end + config_set('vxlan_vtep', 'global_ingress_replication_bgp', set_args) + else + set_args[:state] = 'no' + config_set('vxlan_vtep', + 'global_ingress_replication_bgp', set_args) if + global_ingress_replication_bgp + end + end + + def default_global_ingress_replication_bgp + config_get_default('vxlan_vtep', 'global_ingress_replication_bgp') + end + + def global_suppress_arp + config_get('vxlan_vtep', 'global_suppress_arp', name: @name) + end + + def global_suppress_arp=(state) + set_args = { name: @name } + if state + set_args[:state] = '' + # Host reachability must be enabled for this property + unless VxlanVtep.new(@name).host_reachability == 'evpn' + fail "Dependency: vxlan_vtep host_reachability must be 'evpn'." + end + Feature.nv_overlay_evpn_enable if + Feature.nv_overlay_evpn_supported? && !Feature.nv_overlay_evpn_enabled? + config_set('vxlan_vtep', 'global_suppress_arp', set_args) + else + set_args[:state] = 'no' + config_set('vxlan_vtep', + 'global_suppress_arp', set_args) if global_suppress_arp + end + end + + def default_global_suppress_arp + config_get_default('vxlan_vtep', 'global_suppress_arp') + end + + def global_mcast_group_l2 + config_get('vxlan_vtep', 'global_mcast_group_l2', name: @name) + end + + def global_mcast_group_l2=(val) + if val + set_args = { name: @name, ip: val, state: '' } + else + set_args = { name: @name, ip: '', state: 'no' } + end + config_set('vxlan_vtep', 'global_mcast_group_l2', set_args) + end + + def default_global_mcast_group_l2 + config_get_default('vxlan_vtep', 'global_mcast_group_l2') + end + + def global_mcast_group_l3 + config_get('vxlan_vtep', 'global_mcast_group_l3', name: @name) + end + + def global_mcast_group_l3=(val) + if val + set_args = { name: @name, ip: val, state: '' } + else + set_args = { name: @name, ip: '', state: 'no' } + end + config_set('vxlan_vtep', 'global_mcast_group_l3', set_args) + end + + def default_global_mcast_group_l3 + config_get_default('vxlan_vtep', 'global_mcast_group_l3') + end end # Class end # Module diff --git a/lib/cisco_node_utils/vxlan_vtep_vni.rb b/lib/cisco_node_utils/vxlan_vtep_vni.rb index 913c7846..cc108b39 100644 --- a/lib/cisco_node_utils/vxlan_vtep_vni.rb +++ b/lib/cisco_node_utils/vxlan_vtep_vni.rb @@ -3,7 +3,7 @@ # # November 2015 Michael G Wiebe # -# Copyright (c) 2015-2016 Cisco and/or its affiliates. +# Copyright (c) 2015-2018 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. @@ -252,6 +252,37 @@ def default_suppress_arp config_get_default('vxlan_vtep_vni', 'suppress_arp') end + def suppress_arp_disable + # suppress_arp_disable is really a boolean kind, however, + # since the get is looking for a string with 'disable' + # we have to treat it as string first and then massage it + # to boolean + str = config_get('vxlan_vtep_vni', 'suppress_arp_disable', @get_args) + str.nil? ? false : true + end + + def suppress_arp_disable=(state) + if state + set_args_keys(state: '') + # Host reachability must be enabled for this property + unless VxlanVtep.new(@name).host_reachability == 'evpn' + fail "Dependency: vxlan_vtep host_reachability must be 'evpn'." + end + Feature.nv_overlay_evpn_enable if + Feature.nv_overlay_evpn_supported? && !Feature.nv_overlay_evpn_enabled? + config_set('vxlan_vtep_vni', 'suppress_arp_disable', @set_args) + else + set_args_keys(state: 'no') + # Remove suppress-arp-disable only if it is configured. + config_set('vxlan_vtep_vni', 'suppress_arp_disable', @set_args) if + suppress_arp_disable + end + end + + def default_suppress_arp_disable + config_get_default('vxlan_vtep_vni', 'suppress_arp_disable') + end + def suppress_uuc config_get('vxlan_vtep_vni', 'suppress_uuc', @get_args) end diff --git a/tests/test_vxlan_vtep.rb b/tests/test_vxlan_vtep.rb index a46a2757..8386bc42 100755 --- a/tests/test_vxlan_vtep.rb +++ b/tests/test_vxlan_vtep.rb @@ -1,4 +1,4 @@ -# Copyright (c) 2013-2016 Cisco and/or its affiliates. +# Copyright (c) 2013-2018 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. @@ -232,4 +232,80 @@ def test_source_interface_hold_down_time vtep.source_interface_hold_down_time = val assert_equal(val, vtep.source_interface_hold_down_time) end + + def test_global_ingress_replication_bgp + skip_incompat_version?('vxlan_vtep', 'global_ingress_replication_bgp') + + vtep = VxlanVtep.new('nve1') + vtep.host_reachability = 'evpn' + if validate_property_excluded?('vxlan_vtep', 'global_ingress_replication_bgp') + assert_raises(Cisco::UnsupportedError) { vtep.global_ingress_replication_bgp = true } + return + end + + # Test: Check global_ingress_replication_bgp is not configured. + refute(vtep.global_ingress_replication_bgp, 'global_ingress_replication_bgp should be disabled') + + # Test: Enable global_ingress_replication_bgp + vtep.global_ingress_replication_bgp = true + assert(vtep.global_ingress_replication_bgp, 'global_ingress_replication_bgp should be enabled') + # Test: Default + vtep.global_ingress_replication_bgp = vtep.default_global_ingress_replication_bgp + refute(vtep.global_ingress_replication_bgp, 'global_ingress_replication_bgp should be disabled') + end + + def test_global_suppress_arp + skip_incompat_version?('vxlan_vtep', 'global_suppress_arp') + + vtep = VxlanVtep.new('nve1') + vtep.host_reachability = 'evpn' + if validate_property_excluded?('vxlan_vtep', 'global_suppress_arp') + assert_raises(Cisco::UnsupportedError) { vtep.global_suppress_arp = true } + return + end + + # Test: Check global_suppress_arp is not configured. + refute(vtep.global_suppress_arp, 'global_suppress_arp should be disabled') + + # Test: Enable global_suppress_arp + vtep.global_suppress_arp = true + assert(vtep.global_suppress_arp, 'global_suppress_arp should be enabled') + # Test: Default + vtep.global_suppress_arp = vtep.default_global_suppress_arp + refute(vtep.global_suppress_arp, 'global_suppress_arp should be disabled') + end + + def test_global_mcast_group_l2 + vtep = VxlanVtep.new('nve1') + if validate_property_excluded?('vxlan_vtep', 'global_mcast_group_l2') + assert_raises(Cisco::UnsupportedError) do + vtep.global_mcast_group_l2 = '225.1.1.1' + end + return + end + skip_incompat_version?('vxlan_vtep', 'global_mcast_group_l2') + + assert_equal(vtep.global_mcast_group_l2, vtep.default_global_mcast_group_l2) + vtep.global_mcast_group_l2 = '225.1.1.1' + assert_equal('225.1.1.1', vtep.global_mcast_group_l2) + vtep.global_mcast_group_l2 = vtep.default_global_mcast_group_l2 + assert_equal(vtep.global_mcast_group_l2, vtep.default_global_mcast_group_l2) + end + + def test_global_mcast_group_l3 + vtep = VxlanVtep.new('nve1') + if validate_property_excluded?('vxlan_vtep', 'global_mcast_group_l3') + assert_raises(Cisco::UnsupportedError) do + vtep.global_mcast_group_l3 = '225.1.1.1' + end + return + end + skip_incompat_version?('vxlan_vtep', 'global_mcast_group_l3') + + assert_equal(vtep.global_mcast_group_l3, vtep.default_global_mcast_group_l3) + vtep.global_mcast_group_l3 = '225.1.1.1' + assert_equal('225.1.1.1', vtep.global_mcast_group_l3) + vtep.global_mcast_group_l3 = vtep.default_global_mcast_group_l3 + assert_equal(vtep.global_mcast_group_l3, vtep.default_global_mcast_group_l3) + end end diff --git a/tests/test_vxlan_vtep_vni.rb b/tests/test_vxlan_vtep_vni.rb index 4ec522fb..b46ab2b8 100644 --- a/tests/test_vxlan_vtep_vni.rb +++ b/tests/test_vxlan_vtep_vni.rb @@ -1,4 +1,4 @@ -# Copyright (c) 2013-2016 Cisco and/or its affiliates. +# Copyright (c) 2013-2018 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. @@ -237,6 +237,34 @@ def test_suppress_arp refute(vni.suppress_arp, 'suppress_arp should be disabled') end + def test_suppress_arp_disable + skip_incompat_version?('vxlan_vtep_vni', 'suppress_arp_disable') + vni = VxlanVtepVni.new('nve1', '6000') + VxlanVtep.new('nve1').host_reachability = 'evpn' + + if validate_property_excluded?('vxlan_vtep_vni', 'suppress_arp_disable') + assert_raises(Cisco::UnsupportedError) { vni.suppress_arp_disable = true } + return + end + + # Test: Check suppress_arp_disable is not configured. + refute(vni.suppress_arp_disable, 'suppress_arp_disable should be disabled') + + begin + # Test: Enable suppress_arp_disable + vni.suppress_arp_disable = true + assert(vni.suppress_arp_disable, 'suppress_arp_disable should be enabled') + rescue CliError => e + msg = 'TCAM reconfiguration required followed by reload' \ + " Skipping test case.\n#{e}" + skip(msg) if /ERROR: Please configure TCAM/.match(e.to_s) + end + + # Test: Default + vni.suppress_arp_disable = vni.default_suppress_arp_disable + refute(vni.suppress_arp_disable, 'suppress_arp_disable should be disabled') + end + def test_suppress_uuc vni = VxlanVtepVni.new('nve1', '6000') VxlanVtep.new('nve1').host_reachability = 'evpn' From 3d11ff50cd9f17bd13adc2e0182c81087f5760c8 Mon Sep 17 00:00:00 2001 From: saichint Date: Tue, 4 Dec 2018 06:41:19 -0800 Subject: [PATCH 06/27] Fix for route map src proto sorting (#602) --- lib/cisco_node_utils/route_map.rb | 2 +- tests/test_route_map.rb | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/lib/cisco_node_utils/route_map.rb b/lib/cisco_node_utils/route_map.rb index 977720f2..114a497d 100644 --- a/lib/cisco_node_utils/route_map.rb +++ b/lib/cisco_node_utils/route_map.rb @@ -309,7 +309,7 @@ def default_match_tag # match source-protocol tcp udp def match_src_proto str = config_get('route_map', 'match_src_proto', @get_args) - str.empty? ? default_match_src_proto : str.split + str.empty? ? default_match_src_proto : str.split.sort end def match_src_proto=(list) diff --git a/tests/test_route_map.rb b/tests/test_route_map.rb index 708ac191..c280b749 100644 --- a/tests/test_route_map.rb +++ b/tests/test_route_map.rb @@ -152,11 +152,9 @@ def test_match_tag def test_match_src_proto rm = create_route_map assert_equal(rm.default_match_src_proto, rm.match_src_proto) - array = %w(tcp udp igmp) + array = %w(tcp udp igmp).sort rm.match_src_proto = array - # Protocol order not maintained in running config starting Greensboro. - # Sorting arrays to check equality. - assert_equal(array.sort, rm.match_src_proto.sort) + assert_equal(array, rm.match_src_proto) rm.match_src_proto = rm.default_match_src_proto assert_equal(rm.default_match_src_proto, rm.match_src_proto) end From 0d7150e539b50b8ffd91edbdb76571e71cff1ed1 Mon Sep 17 00:00:00 2001 From: Chris Van Heuveln Date: Fri, 4 Jan 2019 12:58:51 -0500 Subject: [PATCH 07/27] Add 'redistribute' support to router_ospf_vrf (#604) * Add 'redistribute' support to router_ospf_vrf * 'redistribute maximum-prefix' is not currently supported * testing new travis settings * testing travis settings * travis take 3 --- .travis.yml | 2 + CHANGELOG.md | 2 + lib/cisco_node_utils/cmd_ref/ospf.yaml | 7 +++ lib/cisco_node_utils/router_ospf_vrf.rb | 54 ++++++++++++++++++++-- tests/test_router_ospf_vrf.rb | 61 +++++++++++++++++++++++++ 5 files changed, 121 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0bb32dd4..822d4ae3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,6 +7,8 @@ rvm: - 2.2.2 - 2.1.6 - 2.0.0-p648 # specify non-clang version of ruby +before_install: + - gem install bundler -v '< 2' script: - bundle exec rake diff --git a/CHANGELOG.md b/CHANGELOG.md index 418ecaf1..6a9e70f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ Changelog ### New Cisco Resources ### Added +* Extend router_ospf_vrf with attribute: + * `redistribute` * `reset_instance` method to node. Allows a single instance of nodeutils to reset the environment cache. * Extend vxlan_vtep_vni with attribute: * `suppress_arp_disable` diff --git a/lib/cisco_node_utils/cmd_ref/ospf.yaml b/lib/cisco_node_utils/cmd_ref/ospf.yaml index f5c468da..973b4707 100644 --- a/lib/cisco_node_utils/cmd_ref/ospf.yaml +++ b/lib/cisco_node_utils/cmd_ref/ospf.yaml @@ -39,6 +39,13 @@ process_initialized: get_command: "show ip ospf stat" get_value: '/^No SAP is registered/' # Ospf is not initialized when seen +redistribute: + # no support yet for redistribute maximum-prefix + multiple: true + get_value: '/^redistribute (\S+ ?\S+?) route-map (\S+)$/' + set_value: ' redistribute route-map ' + default_value: [] + router: multiple: true get_command: "show running ospf" diff --git a/lib/cisco_node_utils/router_ospf_vrf.rb b/lib/cisco_node_utils/router_ospf_vrf.rb index 1a3c8a97..c690f34b 100644 --- a/lib/cisco_node_utils/router_ospf_vrf.rb +++ b/lib/cisco_node_utils/router_ospf_vrf.rb @@ -41,11 +41,7 @@ def initialize(router, name, instantiate=true) @router = router @name = name @parent = {} - if @name == 'default' - @get_args = @set_args = { name: @router } - else - @get_args = @set_args = { name: @router, vrf: @name } - end + set_args_keys_default create if instantiate end @@ -87,6 +83,24 @@ def delete_set_args_keys(list) list.each { |key| @set_args.delete(key) } end + # + # Helper methods to delete @set_args hash keys + # + def set_args_keys_default + keys = { name: @router } + keys[:vrf] = @name unless @name == 'default' + @get_args = @set_args = keys + end + + def set_args_keys(hash={}) # rubocop:disable Style/AccessorMethodName + set_args_keys_default + @set_args = @get_args.merge!(hash) unless hash.empty? + end + + ######################################################## + # PROPERTIES # + ######################################################## + def auto_cost match = config_get('ospf', 'auto_cost', @get_args) return default_auto_cost if match.nil? @@ -168,6 +182,36 @@ def default_log_adjacency config_get_default('ospf', 'log_adjacency') end + # + # Redistribute + # + + # Build an array of all redistribute commands currently on the device + def redistribute + c = config_get('ospf', 'redistribute', @get_args) + c.nil? ? nil : c.each(&:compact!).sort + end + + # redistribute setter. + # Process a hash of redistribute commands from delta_add_remove(). + def redistribute=(should) + delta_hash = Utils.delta_add_remove(should, redistribute) + return if delta_hash.values.flatten.empty? + [:add, :remove].each do |action| + Cisco::Logger.debug("redistribute delta #{@get_args}\n #{action}: " \ + "#{delta_hash[action]}") + delta_hash[action].each do |protocol, route_map| + state = (action == :add) ? '' : 'no' + set_args_keys(state: state, protocol: protocol, route_map: route_map) + config_set('ospf', 'redistribute', @set_args) + end + end + end + + def default_redistribute + config_get_default('ospf', 'redistribute') + end + def router_id config_get('ospf', 'router_id', @get_args) end diff --git a/tests/test_router_ospf_vrf.rb b/tests/test_router_ospf_vrf.rb index 60c646e4..65376d05 100644 --- a/tests/test_router_ospf_vrf.rb +++ b/tests/test_router_ospf_vrf.rb @@ -32,6 +32,67 @@ def teardown super end + def test_redistribute + routers = %w(alpha beta) + vrfs = %w(default zed) + routers.each do |rtr| + vrfs.each do |vrf| + dbg = sprintf('[RTR %s VRF %s]', rtr, vrf) + af = RouterOspfVrf.new(rtr, vrf) + redistribute_cmd(af, dbg) + end + end + end + + def redistribute_cmd(af, dbg) + # rubocop:disable Style/WordArray + # Initial 'should' state + master = [['direct', 'rm_direct'], + ['lisp', 'rm_lisp'], + ['static', 'rm_static'], + ['eigrp 1', 'rm_eigrp'], + ['isis 2', 'rm_isis'], + ['ospf 3', 'rm_ospf'], + ['rip 4', 'rm_rip'], + ['bgp 5', 'rm_bgp']] + # rubocop:enable Style/WordArray + + # Test: Add all protocols w/route-maps when no cmds are present + should = master.clone + af.redistribute = should + result = af.redistribute + assert_equal(should.sort, result.sort, + "#{dbg} Test 1. From empty, to all protocols") + + # Test: remove half of the protocols + should.shift(4) + af.redistribute = should + result = af.redistribute + assert_equal(should.sort, result.sort, + "#{dbg} Test 2. Remove half of the protocols") + + # Test: restore the removed protocols + should = master.clone + af.redistribute = should + result = af.redistribute + assert_equal(should.sort, result.sort, + "#{dbg} Test 3. Restore the removed protocols") + + # Test: Change route-maps on existing commands + should = master.map { |prot_only, rm| [prot_only, "#{rm}_2"] } + af.redistribute = should + result = af.redistribute + assert_equal(should.sort, result.sort, + "#{dbg} Test 4. Change route-maps on existing commands") + + # Test: 'default' + should = af.default_redistribute + af.redistribute = should + result = af.redistribute + assert_equal(should.sort, result.sort, + "#{dbg} Test 5. 'Default'") + end + def assert_match_vrf_line(routername, vrfname, cmd=nil) match_vrf_line(routername, vrfname, cmd, true) end From 9b3e7ac13614e93f07432fbc84968db8b856e9d2 Mon Sep 17 00:00:00 2001 From: Chris Van Heuveln Date: Fri, 11 Jan 2019 13:37:24 -0500 Subject: [PATCH 08/27] interface_service_vni: Create 'all_interfaces' key (#606) This change adds an `all_interfaces` lookup specific to `interface_service_vni`. Interface lookups were failing due to this change: https://github.com/cisco/cisco-network-node-utils/pull/562/files#diff-c49e70266ca94441d6f0a1a11ab9d52dR87 --- lib/cisco_node_utils/cmd_ref/interface_service_vni.yaml | 5 +++++ lib/cisco_node_utils/interface_service_vni.rb | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/cisco_node_utils/cmd_ref/interface_service_vni.yaml b/lib/cisco_node_utils/cmd_ref/interface_service_vni.yaml index 1a88504e..394a7cc3 100644 --- a/lib/cisco_node_utils/cmd_ref/interface_service_vni.yaml +++ b/lib/cisco_node_utils/cmd_ref/interface_service_vni.yaml @@ -11,6 +11,11 @@ _template: - 'interface ' - 'service instance vni' +all_interfaces: + multiple: + get_context: ~ + get_value: '/^interface (.*)/' + all_service_vni_ids: multiple: get_context: diff --git a/lib/cisco_node_utils/interface_service_vni.rb b/lib/cisco_node_utils/interface_service_vni.rb index 027c3202..106890c3 100644 --- a/lib/cisco_node_utils/interface_service_vni.rb +++ b/lib/cisco_node_utils/interface_service_vni.rb @@ -36,7 +36,7 @@ def to_s def self.svc_vni_ids hash = {} - intf_list = config_get('interface', 'all_interfaces') + intf_list = config_get('interface_service_vni', 'all_interfaces') return hash if intf_list.nil? intf_list.each do |intf| From fc865dfc30918c7d4001b186c8b70340bc55446b Mon Sep 17 00:00:00 2001 From: Thomas Franklin Date: Tue, 15 Jan 2019 18:55:00 +0000 Subject: [PATCH 09/27] Extend nxapi client with https support (#605) * `transport` will control if `use_ssl` is true or not * `verify_mode` has been added for when https mode is used, it selects based on `verify_mode` param being set to either 'none', 'peer', 'fail-no-peer' and 'client-once' The following environment tests were used to verify https/http and host:port combinations. ``` nxapi_remote_http: host: localhost port: 7070 telnet_port: 2222 username: vagrant password: vagrant host_and_port: host: localhost:7070 telnet_port: 2222 username: vagrant password: vagrant nxapi_remote_https: host: localhost telnet_port: 2222 transport: https port: 4431 transport: https username: vagrant password: vagrant ``` --- CHANGELOG.md | 3 ++ lib/cisco_node_utils/client/nxapi/client.rb | 46 ++++++++++++++++++--- tests/basetest.rb | 44 ++++++++++++++++++-- 3 files changed, 83 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a9e70f6..6a2bdf12 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ Changelog ### New Cisco Resources ### Added +* Extend nxapi client for https support + * `use_ssl` will be true when `transport` is `https` + * now makes use of `port` for custom nxapi ports * Extend router_ospf_vrf with attribute: * `redistribute` * `reset_instance` method to node. Allows a single instance of nodeutils to reset the environment cache. diff --git a/lib/cisco_node_utils/client/nxapi/client.rb b/lib/cisco_node_utils/client/nxapi/client.rb index b2a63957..1df28a55 100644 --- a/lib/cisco_node_utils/client/nxapi/client.rb +++ b/lib/cisco_node_utils/client/nxapi/client.rb @@ -2,7 +2,7 @@ # # November 2014, Glenn F. Matthews # -# Copyright (c) 2014-2016 Cisco and/or its affiliates. +# Copyright (c) 2014-2019 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. @@ -60,7 +60,11 @@ def initialize(**kwargs) else # Remote connection. This is primarily expected # when running e.g. from a Unix server as part of Minitest. - @http = Net::HTTP.new(@host) + @transport = kwargs[:transport] || 'http' + @verify_mode = kwargs[:verify_mode] || 'none' + @port.nil? ? @port = '' : @port = ":#{@port}" + uri = URI.parse("#{@transport}://#{@host}#{@port}") + @http = Net::HTTP.new(uri.host, uri.port) end # The default read time out is 60 seconds, which may be too short for # scaled configuration to apply. Change it to 300 seconds, which is @@ -205,14 +209,18 @@ def req(type, command_or_list) request = build_http_request(type, command) # send the request and get the response - debug("Sending HTTP request to NX-API at #{@http.address}:\n" \ + debug("Sending #{@transport} request to NX-API at #{@http.address}:\n" \ "#{request.to_hash}\n#{request.body}") read_timeout_check(request) tries = 2 begin - # Explicitly use http to avoid EOFError - # http://stackoverflow.com/a/23080693 - @http.use_ssl = false + if @transport == 'https' + debug('Setting use_ssl to true') + @http.use_ssl = true + @http.verify_mode = handle_verify_mode(@verify_mode) + else + @http.use_ssl = false + end response = @http.request(request) rescue Errno::ECONNREFUSED, Errno::ECONNRESET emsg = 'Connection refused or reset. Is the NX-API feature enabled?' @@ -268,6 +276,32 @@ def build_http_request(type, command_string) end private :build_http_request + # Returns the OpenSSL verify mode based on the verify_mode arguments + # + # @raise if verify_mode param is not `peer`, `client-once`, `fail-no-peer` + # or `none` + # + # @param String verify mode to use + # + # @return OpenSSL::SSL verification mode + def handle_verify_mode(verify_mode) + case verify_mode + when 'peer' + OpenSSL::SSL::VERIFY_PEER + when 'client-once' + OpenSSL::SSL::VERIFY_CLIENT_ONCE + when 'fail-no-peer' + OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT + when 'none' + OpenSSL::SSL::VERIFY_NONE + else + fail "#{verify_mode} is not a valid mode, " \ + 'valid modes are: "none", "peer", ' \ + '"client-once", "fail-no-peer"' + end + end + private :handle_verify_mode + def handle_http_response(response) debug("HTTP Response: #{response.message}\n#{response.body}") case response diff --git a/tests/basetest.rb b/tests/basetest.rb index 4a0a67af..bc29fa68 100644 --- a/tests/basetest.rb +++ b/tests/basetest.rb @@ -85,6 +85,38 @@ def password self.class.password end + def self.telnet_port + Cisco::Environment.environment[:telnet_port] || 23 + end + + def telnet_port + self.class.telnet_port + end + + def self.port + Cisco::Environment.environment[:port] || address.split(':')[1] + end + + def port + self.class.port + end + + def self.transport + Cisco::Environment.environment[:transport] || 'http' + end + + def transport + self.class.transport + end + + def self.verify_mode + Cisco::Environment.environment[:verify_mode] || 'none' + end + + def verify_mode + self.class.verify_mode + end + def setup # Hack - populate environment from user-entered values from basetest.rb if Cisco::Environment.environments.empty? @@ -92,13 +124,17 @@ class << Cisco::Environment attr_writer :environments end Cisco::Environment.environments['default'] = { - host: address.split(':')[0], - port: address.split(':')[1], - username: username, - password: password, + host: address.split(':')[0], + port: port, + telnet_port: telnet_port, + transport: transport, + verify_mode: verify_mode, + username: username, + password: password, } end @device = Net::Telnet.new('Host' => address.split(':')[0], + 'Port' => telnet_port, 'Timeout' => 240, # NX-OS has a space after '#', IOS XR does not 'Prompt' => /[$%#>] *\z/n, From aa7b0c8b689640417c05cfbc57e6b3f2364c2ada Mon Sep 17 00:00:00 2001 From: Chris Van Heuveln Date: Thu, 17 Jan 2019 16:51:35 -0500 Subject: [PATCH 10/27] Minitest fixes (#609) * MT: bgp_af * MT: snmpserver * MT: vtp * MT: tacacs_global * MT: interface_svi * route_map.yaml: regex cleanup ruby was raising a warning on this regex: warning: nested repeat operator '+' and '?' was replaced with '*' in regular expression: /^set extcomm-list (\S+)(?:\s+)? delete$/ --- lib/cisco_node_utils/cmd_ref/route_map.yaml | 2 +- tests/test_bgp_af.rb | 3 +++ tests/test_interface_svi.rb | 2 +- tests/test_snmpserver.rb | 2 +- tests/test_tacacs_global.rb | 8 ++++++-- tests/test_vtp.rb | 4 ++-- 6 files changed, 14 insertions(+), 7 deletions(-) diff --git a/lib/cisco_node_utils/cmd_ref/route_map.yaml b/lib/cisco_node_utils/cmd_ref/route_map.yaml index 42b80567..93018ccb 100644 --- a/lib/cisco_node_utils/cmd_ref/route_map.yaml +++ b/lib/cisco_node_utils/cmd_ref/route_map.yaml @@ -361,7 +361,7 @@ set_distance_local: # there is more than one space before delete on some platforms set_extcomm_list: - get_value: '/^set extcomm-list (\S+)(?:\s+)? delete$/' + get_value: '/^set extcomm-list (\S+)\s+delete$/' set_value: " set extcomm-list delete" default_value: false diff --git a/tests/test_bgp_af.rb b/tests/test_bgp_af.rb index 4dae7284..d888d0a1 100644 --- a/tests/test_bgp_af.rb +++ b/tests/test_bgp_af.rb @@ -170,6 +170,9 @@ def check_test_exceptions(test_, os_, vrf_, af_) # triggers a version check below. if expect == :runtime case Platform.image_version + when /7\.3/ + expect = :success if test == :additional_paths_send || + test == :additional_paths_receive when /8.0|8.1|8.2|8.3|F3.2/ expect = :success expect = :runtime if test == :additional_paths_receive && Platform.image_version[/8.0|8.1/] diff --git a/tests/test_interface_svi.rb b/tests/test_interface_svi.rb index f3456e7a..3e79d0bb 100644 --- a/tests/test_interface_svi.rb +++ b/tests/test_interface_svi.rb @@ -195,7 +195,7 @@ def test_description def test_sys_def_svi_autostate skip_autostate_test? - skip_legacy_defect?('8.0.1|8.1.1', 'CSC: Behavior change after helsinki') + skip_legacy_defect?('8.0.1|8.1.1|8\.3', 'CSC: Behavior change after helsinki') interface = Interface.new(interfaces[0]) system_default_svi_autostate('no ') diff --git a/tests/test_snmpserver.rb b/tests/test_snmpserver.rb index 24723db3..fceb25f4 100644 --- a/tests/test_snmpserver.rb +++ b/tests/test_snmpserver.rb @@ -155,7 +155,7 @@ def test_location_special_chars end def test_packet_size - skip_legacy_defect?('7.0.3.I2.2e|7.0.3.I2.5|7.0.3.I3.1', + skip_legacy_defect?('7.0.3.I2.2e|7.0.3.I2.5|7.0.3.I3.1|7.3.2.D', 'CSCuz14217: CLI shows default snmp packet-size incorrectly as 0') if validate_property_excluded?('snmp_server', 'packet_size') diff --git a/tests/test_tacacs_global.rb b/tests/test_tacacs_global.rb index a232e7d5..6eb8bd60 100644 --- a/tests/test_tacacs_global.rb +++ b/tests/test_tacacs_global.rb @@ -75,7 +75,9 @@ def test_tacacs_global global.encryption_key_set(nil, key) # Device encypts key - verify return value assert_equal(7, global.key_format) - assert_equal('"WAWY_NZB"', global.key) + key = 'WAWY_NZB' + key = "\"#{key}\"" unless Platform.image_version[/7\.3/] + assert_equal(key, global.key) skip_versions = ['7.0.3.(I2|I3)', '7.0.3.I4.[1-7]'] if step_unless_legacy_defect(skip_versions, 'CSCvh72911: Cannot configure tacacs-server key 6') @@ -85,7 +87,9 @@ def test_tacacs_global key = 'JDYkqyIFWeBvzpljSfWmRZrmRSRE8' global.encryption_key_set(key_format, key) assert_equal(key_format, global.key_format) - assert_equal("\"#{key}\"", global.key) + + key = "\"#{key}\"" unless Platform.image_version[/7\.3/] + assert_equal(key, global.key) end # Remove global key diff --git a/tests/test_vtp.rb b/tests/test_vtp.rb index aa7b26da..84dd4f61 100755 --- a/tests/test_vtp.rb +++ b/tests/test_vtp.rb @@ -175,10 +175,10 @@ def test_password_valid end # this fails on n7k running 7.3(0)D1.1 image but it - # is fixed in later releases. The bugID is CSCuy87970 + # is fixed in some later releases. The bugID is CSCuy87970 # which is already verified. def test_password_special_characters - skip_legacy_defect?('7.3.0.(N1|D1).1.bin', + skip_legacy_defect?('7.3.[012].(N1|D1)', 'CSCuy87970: NXAPI incorrect backslash escape') vtp = vtp_domain('password') vtp.password = 'hello!//\\#%$x' From 15a7429db9f1600c6bb7e94e93b5dd5b226de718 Mon Sep 17 00:00:00 2001 From: Mike Wiebe Date: Thu, 17 Jan 2019 17:16:16 -0500 Subject: [PATCH 11/27] Fix multisite_border_gateway_interface property (#608) --- lib/cisco_node_utils/vxlan_vtep.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/cisco_node_utils/vxlan_vtep.rb b/lib/cisco_node_utils/vxlan_vtep.rb index 78389e8f..c720bfdd 100644 --- a/lib/cisco_node_utils/vxlan_vtep.rb +++ b/lib/cisco_node_utils/vxlan_vtep.rb @@ -181,10 +181,10 @@ def multisite_border_gateway_interface def multisite_border_gateway_interface=(val) set_args = { name: @name } set_args[:state] = val.empty? ? 'no' : '' - set_args[:lpbk_intf] = val.empty? ? 'loopback0' : val + # rubocop:disable LineLength + set_args[:lpbk_intf] = val.empty? ? multisite_border_gateway_interface : val + # rubocop:enable LineLength if set_args[:state] == 'no' - # 'no multisite border-gateway' doesn't work without interface - # defaulting to 'loopback0' still clears any configuration intf = multisite_border_gateway_interface unless intf == default_multisite_border_gateway_interface config_set('vxlan_vtep', 'multisite_bg_intf', set_args) From b324f5fca2a6db2b2023f47164164e4915a23ffa Mon Sep 17 00:00:00 2001 From: Mike Wiebe Date: Fri, 1 Feb 2019 12:06:14 -0500 Subject: [PATCH 12/27] Add needed test skips (#610) --- tests/test_vxlan_vtep.rb | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/tests/test_vxlan_vtep.rb b/tests/test_vxlan_vtep.rb index 8386bc42..ed4d9ce1 100755 --- a/tests/test_vxlan_vtep.rb +++ b/tests/test_vxlan_vtep.rb @@ -268,7 +268,11 @@ def test_global_suppress_arp refute(vtep.global_suppress_arp, 'global_suppress_arp should be disabled') # Test: Enable global_suppress_arp - vtep.global_suppress_arp = true + begin + vtep.global_suppress_arp = true + rescue CliError => e + skip(e.to_s) if /ERROR: Please configure TCAM/.match(e.to_s) + end assert(vtep.global_suppress_arp, 'global_suppress_arp should be enabled') # Test: Default vtep.global_suppress_arp = vtep.default_global_suppress_arp @@ -303,7 +307,13 @@ def test_global_mcast_group_l3 skip_incompat_version?('vxlan_vtep', 'global_mcast_group_l3') assert_equal(vtep.global_mcast_group_l3, vtep.default_global_mcast_group_l3) - vtep.global_mcast_group_l3 = '225.1.1.1' + + begin + # global_mcast_group_l3 is only supported on certain vxlan capable N9ks + vtep.global_mcast_group_l3 = '225.1.1.1' + rescue CliError => e + skip(e.to_s) if /TRM not supported on this platform/.match(e.to_s) + end assert_equal('225.1.1.1', vtep.global_mcast_group_l3) vtep.global_mcast_group_l3 = vtep.default_global_mcast_group_l3 assert_equal(vtep.global_mcast_group_l3, vtep.default_global_mcast_group_l3) From 1b5697e3d7d95c73b76aebbdec5ba47c8679bf57 Mon Sep 17 00:00:00 2001 From: Mike Wiebe Date: Fri, 1 Feb 2019 16:22:02 -0500 Subject: [PATCH 13/27] Rel200/fix radius global (#611) * Use single instead of double quotes * Check for leading single and double quotes Check looks for both leading double and single quotes in the add_quotes method and does not add more if they already exist. * radius global fixes * Additional radius global fixes * radius and tacacs global fixes * Add nil check in add_quotes method --- lib/cisco_node_utils/cisco_cmn_utils.rb | 6 +++--- lib/cisco_node_utils/radius_global.rb | 6 +++--- lib/cisco_node_utils/tacacs_global.rb | 3 +-- tests/test_radius_global.rb | 5 +++-- tests/test_tacacs_global.rb | 2 -- 5 files changed, 10 insertions(+), 12 deletions(-) diff --git a/lib/cisco_node_utils/cisco_cmn_utils.rb b/lib/cisco_node_utils/cisco_cmn_utils.rb index a29420bd..a98146dc 100644 --- a/lib/cisco_node_utils/cisco_cmn_utils.rb +++ b/lib/cisco_node_utils/cisco_cmn_utils.rb @@ -370,9 +370,9 @@ def self.merge_range(range) end # merge_range def self.add_quotes(value) - return value if image_version?(/7.3/) - value = "\"#{value}\"" unless - value.start_with?('"') && value.end_with?('"') + return value if image_version?(/7.3.[0-1]/) || value.nil? + value = "'#{value}'" unless + value.start_with?('"', "'") && value.end_with?('"', "'") value end # add_quotes diff --git a/lib/cisco_node_utils/radius_global.rb b/lib/cisco_node_utils/radius_global.rb index 2d15d73b..0995cb9c 100644 --- a/lib/cisco_node_utils/radius_global.rb +++ b/lib/cisco_node_utils/radius_global.rb @@ -103,8 +103,7 @@ def key_format def key str = config_get('radius_global', 'key') return if str.nil? - str = str.strip - Utils.add_quotes(str) + str.strip end def key_set(value, format) @@ -119,10 +118,11 @@ def key_set(value, format) end if value.nil? && !key.nil? + value = Utils.add_quotes(key) config_set('radius_global', 'key', state: 'no', - key: "#{key_format} #{key}") + key: "#{key_format} #{value}") elsif !format.nil? value = Utils.add_quotes(value) config_set('radius_global', diff --git a/lib/cisco_node_utils/tacacs_global.rb b/lib/cisco_node_utils/tacacs_global.rb index 28a9398a..b147e7dc 100644 --- a/lib/cisco_node_utils/tacacs_global.rb +++ b/lib/cisco_node_utils/tacacs_global.rb @@ -79,8 +79,7 @@ def key return nil unless Feature.tacacs_enabled? str = config_get('tacacs_global', 'key') return TacacsGlobal.default_key if str.empty? - str = str[1].strip - Utils.add_quotes(str) + str[1].strip.gsub(/\"/, '') end # Get default encryption password diff --git a/tests/test_radius_global.rb b/tests/test_radius_global.rb index dca2abe8..65a422b9 100644 --- a/tests/test_radius_global.rb +++ b/tests/test_radius_global.rb @@ -66,8 +66,8 @@ def test_radius_global 2) if platform == :nexus - key = '44444444' - global.key_set(key, nil) + key = 'aaaAAAGGTTYTYY 44444444 72' + global.key_set(key, 7) assert_match(/#{key}/, global.key) assert_match(/#{key}/, Cisco::RadiusGlobal.radius_global[id].key) assert_equal(7, global.key_format) @@ -93,6 +93,7 @@ def test_radius_global assert_nil(global.key) # Default source interface + global.source_interface = global.default_source_interface assert_nil(global.source_interface) # Set source interface diff --git a/tests/test_tacacs_global.rb b/tests/test_tacacs_global.rb index 6eb8bd60..0dcf397c 100644 --- a/tests/test_tacacs_global.rb +++ b/tests/test_tacacs_global.rb @@ -76,7 +76,6 @@ def test_tacacs_global # Device encypts key - verify return value assert_equal(7, global.key_format) key = 'WAWY_NZB' - key = "\"#{key}\"" unless Platform.image_version[/7\.3/] assert_equal(key, global.key) skip_versions = ['7.0.3.(I2|I3)', '7.0.3.I4.[1-7]'] @@ -88,7 +87,6 @@ def test_tacacs_global global.encryption_key_set(key_format, key) assert_equal(key_format, global.key_format) - key = "\"#{key}\"" unless Platform.image_version[/7\.3/] assert_equal(key, global.key) end From 175beb302677e7fec062f2a665fdde1da9b8dc30 Mon Sep 17 00:00:00 2001 From: Mike Wiebe Date: Mon, 4 Feb 2019 11:45:18 -0500 Subject: [PATCH 14/27] Add C3064 exclude for feature-set fex (#612) --- lib/cisco_node_utils/cmd_ref/feature.yaml | 2 +- lib/cisco_node_utils/command_reference.rb | 4 ++-- spec/schema.yaml | 2 ++ 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/cisco_node_utils/cmd_ref/feature.yaml b/lib/cisco_node_utils/cmd_ref/feature.yaml index 3b353278..571bfa5a 100644 --- a/lib/cisco_node_utils/cmd_ref/feature.yaml +++ b/lib/cisco_node_utils/cmd_ref/feature.yaml @@ -32,7 +32,7 @@ fabric_forwarding: set_value: "feature fabric forwarding" fex: - _exclude: [C3064, C3132, N5k, N6k, N3k-F, N9k-F] + _exclude: [C3048, C3064, C3132, N5k, N6k, N3k-F, N9k-F] get_command: "show feature-set" get_value: '/^fex[\s\d]+(\w+)/' set_value: " feature-set fex" diff --git a/lib/cisco_node_utils/command_reference.rb b/lib/cisco_node_utils/command_reference.rb index e138a91c..ec3ff5ec 100644 --- a/lib/cisco_node_utils/command_reference.rb +++ b/lib/cisco_node_utils/command_reference.rb @@ -437,8 +437,8 @@ def debug(text) puts "DEBUG: #{text}" if @@debug end - KNOWN_PLATFORMS = %w(C3064 C3132 C3172 N35 N3k N3k-F N5k N6k N7k N9k N9k-F - XRv9k) + KNOWN_PLATFORMS = %w(C3048 C3064 C3132 C3172 N35 N3k N3k-F N5k N6k N7k N9k + N9k-F XRv9k) def self.platform_to_filter(platform) if KNOWN_PLATFORMS.include?(platform) diff --git a/spec/schema.yaml b/spec/schema.yaml index 34119e37..2c3da2c5 100644 --- a/spec/schema.yaml +++ b/spec/schema.yaml @@ -12,6 +12,7 @@ mapping: - 'ios_xr' - 'nexus' # Product IDs + - 'C3048' - 'C3064' - 'C3132' - 'C3172' @@ -31,6 +32,7 @@ mapping: # Platform and product filters ios_xr: *base nexus: *base + C3048: *base C3064: *base C3132: *base C3172: *base From 03d15f9f319aaed4de52f4140887584aa25f2c58 Mon Sep 17 00:00:00 2001 From: Mike Wiebe Date: Mon, 4 Feb 2019 13:51:43 -0500 Subject: [PATCH 15/27] Fix dhcp_relay_global getter (#613) * Fix dhcp_relay_global getter * Remove unneeded comment --- lib/cisco_node_utils/dhcp_relay_global.rb | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/cisco_node_utils/dhcp_relay_global.rb b/lib/cisco_node_utils/dhcp_relay_global.rb index 89017a7c..e5fb8365 100644 --- a/lib/cisco_node_utils/dhcp_relay_global.rb +++ b/lib/cisco_node_utils/dhcp_relay_global.rb @@ -172,7 +172,6 @@ def default_ipv4_src_addr_hsrp def ipv4_src_intf intf = config_get('dhcp_relay_global', 'ipv4_src_intf') - # Normalize by downcasing and removing white space intf = intf.downcase.delete(' ') if intf intf end @@ -207,10 +206,7 @@ def default_ipv4_sub_option_circuit_id_custom def ipv4_sub_option_circuit_id_string str = config_get('dhcp_relay_global', 'ipv4_sub_option_circuit_id_string') # Normalize by removing white space and add quotes - if str - str.strip! - str = Utils.add_quotes(str) - end + str.strip! if str.kind_of?(String) str end From b65bf56813d32f6a31e7cf7cb1dd485ab1209970 Mon Sep 17 00:00:00 2001 From: Chris Van Heuveln Date: Tue, 5 Feb 2019 08:23:28 -0500 Subject: [PATCH 16/27] New def values for n6k banner yaml (#614) --- lib/cisco_node_utils/cmd_ref/banner.yaml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/cisco_node_utils/cmd_ref/banner.yaml b/lib/cisco_node_utils/cmd_ref/banner.yaml index 149b0b11..45591298 100644 --- a/lib/cisco_node_utils/cmd_ref/banner.yaml +++ b/lib/cisco_node_utils/cmd_ref/banner.yaml @@ -1,7 +1,11 @@ # banner --- motd: - default_value: "User Access Verification\n" + N5k: &N6000 + default_value: "Nexus 6000 Switch\n" + N6k: *N6000 + else: + default_value: "User Access Verification\n" get_command: 'show banner motd' get_value: '/^.*$/m' set_value: ' banner motd ' From f3149e0bfea75883f24ab96ce067f52e0cabd2dd Mon Sep 17 00:00:00 2001 From: Mike Wiebe Date: Tue, 5 Feb 2019 14:40:08 -0500 Subject: [PATCH 17/27] Rel200/release prep (#616) * Update CHANGELOG.md * Update version info --- CHANGELOG.md | 3 ++- lib/cisco_node_utils/version.rb | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a2bdf12..142dfa21 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ Changelog ========= -## [Unreleased] +## [v2.0.0] ### New Cisco Resources @@ -613,6 +613,7 @@ Cisco::Environment.add_env('default', env) [git-flow]: https://github.com/petervanderdoes/gitflow-avh [SimpleCov]: https://github.com/colszowka/simplecov +[v2.0.0]: https://github.com/cisco/cisco-network-node-utils/compare/v1.10.0...v2.0.0 [v1.10.0]: https://github.com/cisco/cisco-network-node-utils/compare/v1.9.0...v1.10.0 [v1.9.0]: https://github.com/cisco/cisco-network-node-utils/compare/v1.8.0...v1.9.0 [v1.8.0]: https://github.com/cisco/cisco-network-node-utils/compare/v1.7.0...v1.8.0 diff --git a/lib/cisco_node_utils/version.rb b/lib/cisco_node_utils/version.rb index 60a7c43c..67b249a6 100644 --- a/lib/cisco_node_utils/version.rb +++ b/lib/cisco_node_utils/version.rb @@ -14,7 +14,7 @@ # Container module for version number only. module CiscoNodeUtils - VERSION = '1.10.0' + VERSION = '2.0.0' gem_version = Gem::Version.new(Gem::VERSION) min_gem_version = Gem::Version.new('2.1.0') fail 'Required rubygems version >= 2.1.0' if gem_version < min_gem_version From 22a9cfece868d90027d78101982b3385bd08181b Mon Sep 17 00:00:00 2001 From: Chris Van Heuveln Date: Tue, 5 Feb 2019 14:53:28 -0500 Subject: [PATCH 18/27] vrf/vlan fixes for n6k test failures (#615) * New def values for n6k banner yaml * test_vlan: check for existing mapped_vni before deleting * test_vtp: n6k doesn't handle slashes well * test_feature: n6k fix for vni * restore the feature('vni') call in test_feature.rb * n6k show inventory versionid (yaml) fix * test_nxapi: n6k: fix test_get_nxapi_structured_unsupported --- lib/cisco_node_utils/cmd_ref/inventory.yaml | 2 +- lib/cisco_node_utils/vlan.rb | 2 +- tests/test_feature.rb | 6 +++--- tests/test_nxapi.rb | 2 +- tests/test_vtp.rb | 6 ++++-- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/lib/cisco_node_utils/cmd_ref/inventory.yaml b/lib/cisco_node_utils/cmd_ref/inventory.yaml index d7a5905c..f4589e83 100644 --- a/lib/cisco_node_utils/cmd_ref/inventory.yaml +++ b/lib/cisco_node_utils/cmd_ref/inventory.yaml @@ -41,5 +41,5 @@ versionid: nexus: get_value: ["name \"Chassis\"", "vendorid"] N5k: &vendorid5k - get_value: ["name Chassis", "serialnum"] + get_value: ["name Chassis", "vendorid"] N6k: *vendorid5k diff --git a/lib/cisco_node_utils/vlan.rb b/lib/cisco_node_utils/vlan.rb index d00d73fc..deb860a6 100644 --- a/lib/cisco_node_utils/vlan.rb +++ b/lib/cisco_node_utils/vlan.rb @@ -229,7 +229,7 @@ def mapped_vni=(vni) Feature.vn_segment_vlan_based_enable # Remove the existing mapping first as cli doesn't support overwriting. config_set('vlan', 'mapped_vni', vlan: @vlan_id, - state: 'no', vni: vni) + state: 'no', vni: vni) unless mapped_vni.to_s.empty? # Configure the new mapping state = vni == default_mapped_vni ? 'no' : '' config_set('vlan', 'mapped_vni', vlan: @vlan_id, diff --git a/tests/test_feature.rb b/tests/test_feature.rb index 14026b94..90e77500 100755 --- a/tests/test_feature.rb +++ b/tests/test_feature.rb @@ -178,9 +178,9 @@ def test_vn_segment_vlan_based end def test_vni - if node.product_id[/N(5|6)/] - Feature.nv_overlay_enable - else + # 7k: 'feature vni'; All others: 'feature vn-segment-vlan-based'. + # Dependencies: 5/6k: feature-set fabricpath; 3/9k: feature nv overlay + if node.product_id[/N7/] # vni can't be removed if nv overlay is present config_no_warn('no feature nv overlay') vdc_limit_f3_no_intf_needed(:set) diff --git a/tests/test_nxapi.rb b/tests/test_nxapi.rb index 17c2c2e1..e36b2980 100644 --- a/tests/test_nxapi.rb +++ b/tests/test_nxapi.rb @@ -161,7 +161,7 @@ def test_get_nxapi_structured_unsupported cmd = { command: 'show snmp internal globals', data_format: :nxapi_structured } if @product_id[/N(5|6)/] - assert_empty(client.get(cmd)) + assert_empty(client.get(cmd).to_s) else assert_raises(Cisco::RequestNotSupported) { client.get(cmd) } end diff --git a/tests/test_vtp.rb b/tests/test_vtp.rb index 84dd4f61..6c92de16 100755 --- a/tests/test_vtp.rb +++ b/tests/test_vtp.rb @@ -180,9 +180,11 @@ def test_password_valid def test_password_special_characters skip_legacy_defect?('7.3.[012].(N1|D1)', 'CSCuy87970: NXAPI incorrect backslash escape') + # N6k output may triple-escape forward slashes. For now simplify pattern. + test_pass = node.product_id[/N[56]/] ? 'hello!//#%$x' : 'hello!//\\#%$x' vtp = vtp_domain('password') - vtp.password = 'hello!//\\#%$x' - assert_equal('hello!//\\#%$x', vtp.password) + vtp.password = test_pass + assert_equal(test_pass, vtp.password) end def test_filename_valid From 73e5ad5e3defe96a075680d16ae67116918b5fa2 Mon Sep 17 00:00:00 2001 From: Chris Van Heuveln Date: Tue, 5 Feb 2019 15:42:02 -0500 Subject: [PATCH 19/27] test_feature: n6k: test_nv_overlay needs check for unsupported hardware (#617) * test_feature: n6k fix for vni * restore the feature('vni') call in test_feature.rb * test_feature: n6k: test_nv_overlay, hw unsupp check * rubocop fix for feature.rb --- lib/cisco_node_utils/feature.rb | 13 +++++++++---- tests/ciscotest.rb | 1 + tests/test_feature.rb | 2 ++ 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/lib/cisco_node_utils/feature.rb b/lib/cisco_node_utils/feature.rb index 575b90af..95324768 100644 --- a/lib/cisco_node_utils/feature.rb +++ b/lib/cisco_node_utils/feature.rb @@ -183,7 +183,8 @@ def self.ngmvpn_disable def self.nv_overlay_enable # Note: vdc platforms restrict this feature to F3 or newer linecards return if nv_overlay_enabled? - config_set('feature', 'nv_overlay', state: '') + result = config_set('feature', 'nv_overlay', state: '') + cli_error_check(result) sleep 1 end @@ -311,14 +312,18 @@ def self.cli_error_check(result) # instead just displays a STDOUT error message; thus NXAPI does not detect # the failure and we must catch it by inspecting the "body" hash entry # returned by NXAPI. This cli behavior is unlikely to change soon. + patterns = [ + 'Hardware is not capable of supporting', + 'is unsupported on this node', + 'Feature NOT supported on this Platform', + ] fail result[2]['body'] if result[2].is_a?(Hash) && - /Hardware is not capable of supporting/.match(result[2]['body'].to_s) + result[2]['body'].to_s[Regexp.union(patterns)] # Some test environments get result as a string instead of a hash fail result if - result.is_a?(String) && - /Hardware is not capable of supporting/.match(result) + result.is_a?(String) && result[Regexp.union(patterns)] end # --------------------------- diff --git a/tests/ciscotest.rb b/tests/ciscotest.rb index 37e8ba18..dbddcd29 100644 --- a/tests/ciscotest.rb +++ b/tests/ciscotest.rb @@ -156,6 +156,7 @@ def address_match?(int_ip) def hardware_supports_feature?(message) patterns = ['Hardware is not capable of supporting', 'is unsupported on this node', + 'Feature NOT supported on this Platform', ] skip('Skip test: Feature is unsupported on this device') if message[Regexp.union(patterns)] diff --git a/tests/test_feature.rb b/tests/test_feature.rb index 90e77500..1fc07f55 100755 --- a/tests/test_feature.rb +++ b/tests/test_feature.rb @@ -84,6 +84,8 @@ def feature(feat) # Return testbed to pre-clean state config("no feature #{feat_str}") unless pre_clean_enabled + rescue RuntimeError => e + hardware_supports_feature?(e.message) end ################### From 7be1a2088e33674014d76f8f1f4e3d3832508541 Mon Sep 17 00:00:00 2001 From: Chris Van Heuveln Date: Wed, 6 Feb 2019 14:30:35 -0500 Subject: [PATCH 20/27] Minitest: router_bgp fixes for n6k (#618) * Minitest: router_bgp fixes for n6k * `rd` needs `nv overlay evpn` to expose cli * nexus does not support nsr * added a common method to check for attrs that are excluded from cmd_ref * `cmd_ref.lookup` returns type `UnsupportedCmdRef` * Minitest: add n6k skips to interface_pvlan tests --- lib/cisco_node_utils/bgp.rb | 2 +- tests/ciscotest.rb | 6 ++++++ tests/test_interface_private_vlan.rb | 7 ++++++- tests/test_router_bgp.rb | 24 ++++++++++-------------- 4 files changed, 23 insertions(+), 16 deletions(-) diff --git a/lib/cisco_node_utils/bgp.rb b/lib/cisco_node_utils/bgp.rb index 44c87f34..c1d62489 100644 --- a/lib/cisco_node_utils/bgp.rb +++ b/lib/cisco_node_utils/bgp.rb @@ -827,7 +827,7 @@ def route_distinguisher=(rd) # explicit values when removing the rd command. These restrictions are # not not needed in I3 and newer images. Feature.nv_overlay_evpn_enable if - Utils.nexus_i2_image || node.product_id[/N7/] + Utils.nexus_i2_image || node.product_id[/N[567]/] if rd == default_route_distinguisher return if route_distinguisher.empty? diff --git a/tests/ciscotest.rb b/tests/ciscotest.rb index dbddcd29..88c695c1 100644 --- a/tests/ciscotest.rb +++ b/tests/ciscotest.rb @@ -214,6 +214,12 @@ def skip_incompat_version?(feature, property) Gem::Version.new(lim) < Gem::Version.new(ver) end + def skip_if_UnsupportedCmdRef(feature_name, attribute_name) # rubocop:disable Style/MethodName + # Check if attr is excluded by the cmd_ref yaml + skip("UnsupportedCmdRef attribute: '#{attribute_name}'") if + cmd_ref.lookup(feature_name, attribute_name).is_a?(UnsupportedCmdRef) + end + def skip_nexus_i2_image? skip("This property is not supported on Nexus 'I2' images") if Utils.nexus_i2_image diff --git a/tests/test_interface_private_vlan.rb b/tests/test_interface_private_vlan.rb index a4fbec5e..995362c1 100755 --- a/tests/test_interface_private_vlan.rb +++ b/tests/test_interface_private_vlan.rb @@ -196,6 +196,9 @@ def test_sw_pvlan_host_association end def test_sw_pvlan_trunk_association + # N6k trunk association does not update primary-secondary associations automatically + skip('Test behavior not supported on device') if node.product_id[/N(5|6)/] + # Supports multiple instances of [[pri, sec], [pri2, sec2]] if validate_property_excluded?('interface', 'switchport_pvlan_trunk_association') @@ -254,6 +257,9 @@ def test_sw_pvlan_mapping end def test_sw_pvlan_mapping_trunk + # N6k mapping trunk does not update primary-secondary associations automatically + skip('Test behavior not supported on device') if node.product_id[/N(5|6)/] + if validate_property_excluded?('interface', 'switchport_pvlan_mapping_trunk') assert_raises(Cisco::UnsupportedError) do @@ -269,7 +275,6 @@ def test_sw_pvlan_mapping_trunk assert_equal([['2', '4-8,10-11']], i.switchport_pvlan_mapping_trunk) # Same primary, but change range - i.switchport_pvlan_mapping_trunk = ['2', '11,4-6,8'] assert_equal([['2', '4-6,8,11']], i.switchport_pvlan_mapping_trunk) diff --git a/tests/test_router_bgp.rb b/tests/test_router_bgp.rb index d55be1da..a557feaf 100644 --- a/tests/test_router_bgp.rb +++ b/tests/test_router_bgp.rb @@ -55,7 +55,8 @@ def setup_default end def setup_vrf - @asnum = 99 + # nexus does not support multiple BGP instances; VRF AS must be same as default AS + @asnum = platform == :nexus ? 55 : 99 @vrf = 'yamllll' create_bgp_vrf(@asnum, @vrf) end @@ -256,24 +257,18 @@ def test_asnum_dot end def test_nsr + skip_if_UnsupportedCmdRef('bgp', 'nsr') nsr(setup_default) nsr(setup_vrf) end def nsr(bgp) - if (platform == :nexus) || (platform == :ios_xr && !@vrf[/default/]) - if platform == :nexus - assert_nil(bgp.default_nsr, - 'default bgp nsr should be nil on Nexus') - assert_nil(bgp.nsr, - 'bgp nsr should be nil on Nexus') - else - assert_nil(bgp.default_nsr, - 'default bgp nsr should return nil on XR with non-default' \ - ' vrf') - assert_nil(bgp.nsr, - 'bgp nsr should return nil on XR with non-default vrf') - end + if platform == :ios_xr && !@vrf[/default/] + assert_nil(bgp.default_nsr, + 'default bgp nsr should return nil on XR with non-default' \ + ' vrf') + assert_nil(bgp.nsr, + 'bgp nsr should return nil on XR with non-default vrf') assert_raises(Cisco::UnsupportedError) do bgp.nsr = true end @@ -1100,6 +1095,7 @@ def test_reconnect_interval_default assert_nil(bgp.reconnect_interval, 'reconnect_interval should return nil on XR') else + skip_if_UnsupportedCmdRef('bgp', 'reconnect_interval') skip_incompat_version?('bgp', 'reconnect_interval') assert_equal(bgp.default_reconnect_interval, bgp.reconnect_interval, "reconnect_interval should be set to default value of '60'") From 1d9ae359241c841ead867ed9dd763c5851590d09 Mon Sep 17 00:00:00 2001 From: Mike Wiebe Date: Thu, 7 Feb 2019 13:15:29 -0500 Subject: [PATCH 21/27] Add additional props to success matrix (#620) --- tests/test_bgp_af.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/test_bgp_af.rb b/tests/test_bgp_af.rb index d888d0a1..9c07a2aa 100644 --- a/tests/test_bgp_af.rb +++ b/tests/test_bgp_af.rb @@ -172,7 +172,10 @@ def check_test_exceptions(test_, os_, vrf_, af_) case Platform.image_version when /7\.3/ expect = :success if test == :additional_paths_send || - test == :additional_paths_receive + test == :additional_paths_receive || + test == :additional_paths_selection || + test == :maximum_paths || + test == :maximum_paths_ibgp when /8.0|8.1|8.2|8.3|F3.2/ expect = :success expect = :runtime if test == :additional_paths_receive && Platform.image_version[/8.0|8.1/] From 5616c63513f2b7caa2fba80f16a28292b096e58b Mon Sep 17 00:00:00 2001 From: Chris Van Heuveln Date: Thu, 7 Feb 2019 13:24:39 -0500 Subject: [PATCH 22/27] minitest n6k: test_vni dependency (#619) * minitest n6k: test_vni dependency * n6k has feature-set fabricpath dependency * Added getter/setter to feature.rb * test_vrf.rb: test_route_distinguisher: hardware_supports check added --- lib/cisco_node_utils/cmd_ref/feature.yaml | 6 ++++++ lib/cisco_node_utils/feature.rb | 21 ++++++++++++++++++ tests/test_feature.rb | 26 ++++++++++++++++++++++- tests/test_vrf.rb | 2 ++ 4 files changed, 54 insertions(+), 1 deletion(-) diff --git a/lib/cisco_node_utils/cmd_ref/feature.yaml b/lib/cisco_node_utils/cmd_ref/feature.yaml index 571bfa5a..91fd215c 100644 --- a/lib/cisco_node_utils/cmd_ref/feature.yaml +++ b/lib/cisco_node_utils/cmd_ref/feature.yaml @@ -31,6 +31,12 @@ fabric_forwarding: get_value: '/^feature fabric forwarding$/' set_value: "feature fabric forwarding" +fabricpath: + _exclude: [N3k, N3k-F, N9k-F, N9k] + get_command: "show feature-set" + get_value: '/^fabricpath[\s\d]+(\w+)/' + set_value: " feature-set fabricpath" + fex: _exclude: [C3048, C3064, C3132, N5k, N6k, N3k-F, N9k-F] get_command: "show feature-set" diff --git a/lib/cisco_node_utils/feature.rb b/lib/cisco_node_utils/feature.rb index 95324768..e941f2b6 100644 --- a/lib/cisco_node_utils/feature.rb +++ b/lib/cisco_node_utils/feature.rb @@ -80,6 +80,27 @@ def self.fabric_supported? config_get('feature', 'fabric') end + # --------------------------- + def self.fabricpath_enable + # install feature-set and enable it + return if fabricpath_enabled? + config_set('feature', 'fabricpath', state: 'install') unless + fabricpath_installed? + config_set('feature', 'fabricpath', state: '') + end + + def self.fabricpath_enabled? + config_get('feature', 'fabricpath') =~ /^enabled/ + end + + def self.fabricpath_installed? + config_get('feature', 'fabricpath') !~ /^uninstalled/ + end + + def self.fabricpath_supported? + config_get('feature', 'fabricpath') + end + # --------------------------- def self.fabric_forwarding_enable return if fabric_forwarding_enabled? diff --git a/tests/test_feature.rb b/tests/test_feature.rb index 1fc07f55..d8327fba 100755 --- a/tests/test_feature.rb +++ b/tests/test_feature.rb @@ -173,7 +173,8 @@ def test_tacacs def test_vn_segment_vlan_based vxlan_linecard? - Feature.nv_overlay_enable unless node.product_id[/N3/] + Feature.fabricpath_enable if node.product_id[/N(5|6)/] + Feature.nv_overlay_enable unless node.product_id[/N(3|5|6)/] feature('vn_segment_vlan_based') rescue RuntimeError => e hardware_supports_feature?(e.message) @@ -187,6 +188,7 @@ def test_vni config_no_warn('no feature nv overlay') vdc_limit_f3_no_intf_needed(:set) end + Feature.fabricpath_enable if node.product_id[/N(5|6)/] feature('vni') rescue RuntimeError => e hardware_supports_feature?(e.message) @@ -222,6 +224,28 @@ def test_feature_set_fabric assert(Feature.fabric_enabled?, "(#{fs}) is not enabled") end + def test_feature_set_fabricpath + if node.product_id[/N(3|8|9)/] + assert_nil(Feature.fabricpath_enabled?) + assert_raises(Cisco::UnsupportedError) { Feature.fabricpath_enable } + return + end + vdc_limit_f3_no_intf_needed(:set) + fs = 'feature-set fabricpath' + # Get current state of the feature-set + feature_set_installed = Feature.fabricpath_installed? + + config("no #{fs} ; no install #{fs}") if feature_set_installed + refute_show_match( + command: "show running | i '^install #{fs}$'", + pattern: /^install #{fs}$/, + msg: "(#{fs}) is still configured", + ) + + Feature.fabricpath_enable + assert(Feature.fabricpath_enabled?, "(#{fs}) is not enabled") + end + def test_feature_set_fex if validate_property_excluded?('feature', 'fex') assert_nil(Feature.fex_enabled?) diff --git a/tests/test_vrf.rb b/tests/test_vrf.rb index e8994235..44300acd 100755 --- a/tests/test_vrf.rb +++ b/tests/test_vrf.rb @@ -222,6 +222,8 @@ def test_route_distinguisher assert_empty(v.route_distinguisher, 'v route_distinguisher should *NOT* be configured') v.destroy + rescue RuntimeError => e + hardware_supports_feature?(e.message) end def test_vpn_id From 5b7f483e68f78b5aa7834b93fc33e7b5b5f381d7 Mon Sep 17 00:00:00 2001 From: Chris Van Heuveln Date: Thu, 7 Feb 2019 13:51:04 -0500 Subject: [PATCH 23/27] vxlan minitest fixes (#621) * minitest n6k: test_vni dependency * n6k has feature-set fabricpath dependency * Added getter/setter to feature.rb * test_vrf.rb: test_route_distinguisher: hardware_supports check added * vxlan minitest fixes - skip unsupported hardware --- tests/ciscotest.rb | 9 ++++++--- tests/test_vxlan_vtep.rb | 6 ++++++ tests/test_vxlan_vtep_vni.rb | 6 ++++++ 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/tests/ciscotest.rb b/tests/ciscotest.rb index 88c695c1..0fb06e99 100644 --- a/tests/ciscotest.rb +++ b/tests/ciscotest.rb @@ -153,13 +153,16 @@ def address_match?(int_ip) # Some NXOS hardware is not capable of supporting certain features even # though the platform family in general includes support. In these cases # the NU feature setter will raise a RuntimeError. - def hardware_supports_feature?(message) + # Default behavior is to skip/flunk. + def hardware_supports_feature?(message, status_only: false) patterns = ['Hardware is not capable of supporting', 'is unsupported on this node', 'Feature NOT supported on this Platform', ] - skip('Skip test: Feature is unsupported on this device') if - message[Regexp.union(patterns)] + if message[Regexp.union(patterns)] + return true if status_only + skip('Skip test: Feature is unsupported on this device') + end flunk(message) end diff --git a/tests/test_vxlan_vtep.rb b/tests/test_vxlan_vtep.rb index ed4d9ce1..196f0e63 100755 --- a/tests/test_vxlan_vtep.rb +++ b/tests/test_vxlan_vtep.rb @@ -24,9 +24,11 @@ class TestVxlanVtep < CiscoTestCase @skip_unless_supported = 'vxlan_vtep' @@pre_clean_needed = true # rubocop:disable Style/ClassVars + @@feature_unsupported = false # rubocop:disable Style/ClassVars def setup super + skip('setup: Feature is unsupported on this device') if @@feature_unsupported skip('Platform does not support MT-full or MT-lite') unless VxlanVtep.mt_full_support || VxlanVtep.mt_lite_support Interface.interfaces(:nve).each { |_nve, obj| obj.destroy } @@ -34,6 +36,10 @@ def setup feature_cleanup if @@pre_clean_needed Feature.nv_overlay_enable @@pre_clean_needed = false # rubocop:disable Style/ClassVars + rescue RuntimeError => e + # Skip locally to shortcut the dependencies above for the next test + @@feature_unsupported = hardware_supports_feature?(e.message, status_only: true) # rubocop:disable Style/ClassVars + @@feature_unsupported ? skip(e.message) : raise(e.message) end def teardown diff --git a/tests/test_vxlan_vtep_vni.rb b/tests/test_vxlan_vtep_vni.rb index b46ab2b8..840060fe 100644 --- a/tests/test_vxlan_vtep_vni.rb +++ b/tests/test_vxlan_vtep_vni.rb @@ -23,15 +23,21 @@ class TestVxlanVtepVni < CiscoTestCase @skip_unless_supported = 'vxlan_vtep_vni' @@pre_clean_needed = true # rubocop:disable Style/ClassVars + @@feature_unsupported = false # rubocop:disable Style/ClassVars def setup super + skip('setup: Feature is unsupported on this device') if @@feature_unsupported vdc_limit_f3_no_intf_needed(:set) if VxlanVtep.mt_full_support Interface.interfaces(:nve).each { |_nve, obj| obj.destroy } feature_cleanup if @@pre_clean_needed Feature.nv_overlay_enable config_no_warn('feature vn-segment-vlan-based') if VxlanVtep.mt_lite_support @@pre_clean_needed = false # rubocop:disable Style/ClassVars + rescue RuntimeError => e + # Skip locally to shortcut the dependencies above for the next test + @@feature_unsupported = hardware_supports_feature?(e.message, status_only: true) # rubocop:disable Style/ClassVars + @@feature_unsupported ? skip(e.message) : raise(e.message) end def teardown From 6050ce15811f06067d71db2be415c0e746bd9db7 Mon Sep 17 00:00:00 2001 From: Mike Wiebe Date: Thu, 7 Feb 2019 16:42:50 -0500 Subject: [PATCH 24/27] Remove add_quotes call from getters (#622) --- lib/cisco_node_utils/radius_server.rb | 3 +-- lib/cisco_node_utils/tacacs_server.rb | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/cisco_node_utils/radius_server.rb b/lib/cisco_node_utils/radius_server.rb index fadf0d7b..e4d20efd 100644 --- a/lib/cisco_node_utils/radius_server.rb +++ b/lib/cisco_node_utils/radius_server.rb @@ -372,8 +372,7 @@ def key return if val.nil? || val.empty? index = val.index('auth-port') val = val[0..index - 2] unless index.nil? - val = val.strip - Utils.add_quotes(val) + val.strip end def key_set(value, format) diff --git a/lib/cisco_node_utils/tacacs_server.rb b/lib/cisco_node_utils/tacacs_server.rb index 0f83c483..98996f7b 100644 --- a/lib/cisco_node_utils/tacacs_server.rb +++ b/lib/cisco_node_utils/tacacs_server.rb @@ -143,8 +143,7 @@ def self.default_encryption_type def encryption_password str = config_get('tacacs_server', 'encryption_password') return TacacsServer.default_encryption_password if str.empty? - str = str[1].strip - Utils.add_quotes(str) + str[1].strip end # Get default encryption password From 8e6a92ffa9fddf4f68a221f9b1662de2a6852dbf Mon Sep 17 00:00:00 2001 From: mikewiebe Date: Fri, 8 Feb 2019 11:26:14 -0500 Subject: [PATCH 25/27] Remove add_quotes call from getter --- lib/cisco_node_utils/tacacs_server_host.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/cisco_node_utils/tacacs_server_host.rb b/lib/cisco_node_utils/tacacs_server_host.rb index 1a29b971..558c3739 100644 --- a/lib/cisco_node_utils/tacacs_server_host.rb +++ b/lib/cisco_node_utils/tacacs_server_host.rb @@ -147,8 +147,7 @@ def encryption_password return str if str.nil? || str.empty? index = str.index('port') str = str[0..index - 2] unless index.nil? - str = str.strip - Utils.add_quotes(str) + str.strip end def self.default_encryption_password From 18d58bda34d3054f83515c9e74f52e2032c3ec36 Mon Sep 17 00:00:00 2001 From: Mike Wiebe Date: Fri, 8 Feb 2019 13:34:00 -0500 Subject: [PATCH 26/27] Remove redundant section --- CHANGELOG.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 142dfa21..0abf66b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,8 +25,6 @@ Changelog ### Changed -### Removed - ## [v1.10.0] ### New Cisco Resources From b2e4a1de7134d06de6456525bc82bcd3fd4c3606 Mon Sep 17 00:00:00 2001 From: Chris Van Heuveln Date: Tue, 12 Feb 2019 11:38:50 -0500 Subject: [PATCH 27/27] MT: n6k cleanups vrf_af, interface_ospf (#623) * The ospf changes fix these two warnings: TestInterfaceOspf#test_collect_mult_intf = /Users/cvanheuv/git/cisco-network-node-utils/lib/cisco_node_utils/client/utils.rb:127: warning: nested repeat operator '+' and '?' was replaced with '*' in regular expression: /^\s*ip ospf bfd *(?:\S+)?$/ WARN -- : DEPRECATED: Use assert_nil if expecting nil from test_interface_ospf.rb:600. This will fail in Minitest 6. --- lib/cisco_node_utils/cmd_ref/interface_ospf.yaml | 2 +- tests/test_interface_ospf.rb | 6 +++++- tests/test_vrf_af.rb | 2 ++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/cisco_node_utils/cmd_ref/interface_ospf.yaml b/lib/cisco_node_utils/cmd_ref/interface_ospf.yaml index 7fcf8843..a2c78fb6 100644 --- a/lib/cisco_node_utils/cmd_ref/interface_ospf.yaml +++ b/lib/cisco_node_utils/cmd_ref/interface_ospf.yaml @@ -21,7 +21,7 @@ bfd: # no config at all so need to grab the optional # match to get the whole config for checking # the mode - get_value: '/^\s*ip ospf bfd *(?:\S+)?$/' + get_value: '/^\s*ip ospf bfd *(?:\S*)$/' set_value: '%s ip ospf bfd %s' default_value: ~ diff --git a/tests/test_interface_ospf.rb b/tests/test_interface_ospf.rb index 992c8e8d..5ba79583 100644 --- a/tests/test_interface_ospf.rb +++ b/tests/test_interface_ospf.rb @@ -597,7 +597,11 @@ def test_collect_mult_intf msg: "Error: ip router ospf #{name} area #{hv[:area]} "\ "not found under #{ifname}") - assert_equal(hv[:bfd], interface.bfd, 'Error: get bfd failed') + if hv[:bfd].nil? + assert_nil(interface.bfd, 'Error: get bfd is not nil') + else + assert_equal(hv[:bfd], interface.bfd, 'Error: get bfd failed') + end assert_equal(hv[:cost], interface.cost, 'Error: get cost failed') assert_equal(hv[:hello], interface.hello_interval, 'Error: get hello interval failed') diff --git a/tests/test_vrf_af.rb b/tests/test_vrf_af.rb index 12c22341..c82bc336 100755 --- a/tests/test_vrf_af.rb +++ b/tests/test_vrf_af.rb @@ -210,6 +210,8 @@ def route_target(af, _test_mvpn=false) should = v.default_route_target_import route_target_tester(v, af, opts, should, 'Test 4') v.destroy + rescue RuntimeError => e + hardware_supports_feature?(e.message) end def route_target_tester(v, af, opts, should, test_id)