From 594524a30cfdf07acb68a3c25b38c84a62a16804 Mon Sep 17 00:00:00 2001 From: Chris Van Heuveln Date: Fri, 12 Aug 2016 14:23:26 -0400 Subject: [PATCH] Minitest: Handle N7k F3-features w/o compat LCs (#463) * test_vpc needs rescue for incompat intf * Handle N7k F3-features w/o compat LCs * The vrf_af route_target tests were failing because feature nv overlay failed - because our n7k does not have an F3 linecard: ``` 1) There are some features that refuse to load unless the VDC is limited to F3 only, but they will actually load if the config is present, despite the fact that there are no physical F3s. 2) We have some tests that need these features but don't need interfaces. ``` * Solution: Enable the vdc config for F3 but don't fail if the physical LC is not present * Prior to this solution I had created a couple of methods to find an appropriate interface based on the feature-to-LC requirements. This works but is only useful for features that also require an interface (unlike the vrf_af test). Eventually I would like to remove the other one-off methods (e.g. `fabricpath_testenv_setup`, `vxlan_linecard?`, etc) that do similar functions and convert the callers to use this common one instead. Since there are no current callers for it I just commented it out. * Tested on n7k (no F3 card) and N9K. * /if-else/case/ --- lib/cisco_node_utils/cmd_ref/vdc.yaml | 4 ++ lib/cisco_node_utils/vdc.rb | 6 ++ tests/ciscotest.rb | 80 +++++++++++++++++++++++++++ tests/test_vrf_af.rb | 7 +-- 4 files changed, 92 insertions(+), 5 deletions(-) diff --git a/lib/cisco_node_utils/cmd_ref/vdc.yaml b/lib/cisco_node_utils/cmd_ref/vdc.yaml index 0738b783..debbfd86 100644 --- a/lib/cisco_node_utils/cmd_ref/vdc.yaml +++ b/lib/cisco_node_utils/cmd_ref/vdc.yaml @@ -16,6 +16,10 @@ all_vdcs: get_context: ~ get_value: '/^vdc (\S+) id/' +allocate_interface: + get_value: '/^allocate interface (.*)/' + default_value: ~ + allocate_interface_unallocated: kind: boolean set_value: 'allocate interface unallocated-interfaces' diff --git a/lib/cisco_node_utils/vdc.rb b/lib/cisco_node_utils/vdc.rb index 7c8a5a19..99cc6eef 100644 --- a/lib/cisco_node_utils/vdc.rb +++ b/lib/cisco_node_utils/vdc.rb @@ -65,6 +65,12 @@ def ==(other) # PROPERTIES # ######################################################## + def allocate_interface + # TBD: This property is only partially implemented because it is currently + # only used for minitest & beaker. + config_get('vdc', 'allocate_interface', vdc: @vdc) + end + def limit_resource_module_type str = config_get('vdc', 'limit_resource_module_type', vdc: @vdc) str.strip! unless str.nil? diff --git a/tests/ciscotest.rb b/tests/ciscotest.rb index e41ece95..1a9d0554 100644 --- a/tests/ciscotest.rb +++ b/tests/ciscotest.rb @@ -233,6 +233,86 @@ def interface_cleanup(intf_name) config(*cfg) end + # TBD: -- The following methods are a WIP -- + # + # def find_compatible_intf(feature, opt=:raise_skip) + # # Some platforms require specific linecards before allowing a feature to + # # be enabled. This method will find a compatible interface or optionally + # # raise a skip. + # # TBD: This wants to become a common "compatible interface" checker to + # # eventually replace all of the single-use methods. + # intf = compatible_intf(feature) + # if intf.nil? && opt[/raise_skip/] + # skip("Unable to find compatible interface for 'feature #{feature}'") + # end + # intf + # end + + # def compatible_intf(feature) + # # The feat hash contains module restrictions for a given feature. + # # :mods - (optional) The module ids used in the 'limit-resource' config + # # :pids - A regex pattern for the line module product IDs (ref: 'sh mod') + # feat = {} + # if node.product_id[/N7K/] + # feat = { + # # nv overlay raises error unless solely F3 + # 'nv overlay' => { mods: 'f3', pids: 'N7[K7]-F3' } + # } + # end + # patterns = feat[feature] + # return interfaces[0] if patterns.nil? # No restrictions for this platform + + # # Check if module is present and usable; i.e. 'ok' + # pids = patterns[:pids] + # sh_mod_string = @device.cmd("show mod | i '^[0-9]+.*#{pids}.*ok'") + # sh_mod = sh_mod_string[/^(\d+)\s.*#{pids}/] + # slot = sh_mod.nil? ? nil : Regexp.last_match[1] + # return nil if slot.nil? + # intf = "ethernet#{slot}/1" + + # # Check/Set VDC config. VDC platforms restrict module usage per vdc. + # mods = patterns[:mods] + # return intf if mods.nil? || !node.product_id[/N7K/] + # vdc = Vdc.new(Vdc.default_vdc_name) + # unless mods == vdc.limit_resource_module_type + # # Update the allowed module types in this vdc + # vdc.limit_resource_module_type = mods + # end + + # # Return the first interface found in 'allocate interface' config, or nil + # vdc.allocate_interface[%r{Ethernet#{slot}\/(\d+)}] + # end + + def vdc_limit_f3_no_intf_needed(action=:set) + # This is a special-use method for N7Ks that don't have a physical F3. + # 1) There are some features that refuse to load unless the VDC is + # limited to F3 only, but they will actually load if the config is + # present, despite the fact that there are no physical F3s. + # 2) We have some tests that need these features but don't need interfaces. + # + # action = :set (enable limit F3 config), :clear (default limit config) + # + # The limit config should be removed after testing if the device does not + # have an actual F3. + return unless node.product_id[/N7K/] + vdc = Vdc.new(Vdc.default_vdc_name) + case action + when :set + return if vdc.limit_resource_module_type == 'f3' + vdc.limit_resource_module_type = 'f3' + + when :clear + # Remove the config if there are no physical F3 cards + pids = 'N7[K7]-F3' + sh_mod_string = @device.cmd("show mod | i '^[0-9]+.*#{pids}'") + sh_mod = sh_mod_string[/^(\d+)\s.*#{pids}/] + if sh_mod.nil? + # It's safe to remove the config + vdc.limit_resource_module_type = '' + end + end + end + # setup fabricpath env if possible and populate the interfaces array # otherwise cause a global skip def fabricpath_testenv_setup diff --git a/tests/test_vrf_af.rb b/tests/test_vrf_af.rb index 96fd392c..4a8f1b31 100755 --- a/tests/test_vrf_af.rb +++ b/tests/test_vrf_af.rb @@ -111,15 +111,12 @@ def route_policy(af) end def test_route_target + vdc_limit_f3_no_intf_needed(:set) [%w(ipv4 unicast), %w(ipv6 unicast)].each { |af| route_target(af) } + vdc_limit_f3_no_intf_needed(:clear) end def route_target(af) - # - # TBD: The evpn parts of this test need to check for compatible linecards to - # skip the evpn portions. Don't use vxlan_linecard? as that will cause all - # tests to be skipped. - # # Common tester for route-target properties. Tests evpn and non-evpn. # route_target_both_auto # route_target_both_auto_evpn