cisco_node_utils 1.3.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (151) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/CHANGELOG.md +66 -0
  4. data/Gemfile +1 -0
  5. data/README.md +44 -43
  6. data/bin/.rubocop.yml +18 -0
  7. data/bin/show_running_yang.rb +233 -0
  8. data/cisco_node_utils.gemspec +1 -1
  9. data/docs/README-maintainers.md +1 -0
  10. data/docs/README-utilities.md +14 -0
  11. data/lib/.rubocop.yml +1 -1
  12. data/lib/cisco_node_utils/aaa_authentication_login_service.rb +8 -3
  13. data/lib/cisco_node_utils/aaa_authorization_service.rb +6 -0
  14. data/lib/cisco_node_utils/bfd_global.rb +300 -0
  15. data/lib/cisco_node_utils/bgp.rb +6 -4
  16. data/lib/cisco_node_utils/bgp_af.rb +2 -0
  17. data/lib/cisco_node_utils/bgp_neighbor.rb +14 -0
  18. data/lib/cisco_node_utils/bgp_neighbor_af.rb +4 -1
  19. data/lib/cisco_node_utils/cisco_cmn_utils.rb +126 -0
  20. data/lib/cisco_node_utils/client/client.rb +6 -2
  21. data/lib/cisco_node_utils/client/grpc/client.rb +120 -36
  22. data/lib/cisco_node_utils/client/nxapi/client.rb +6 -2
  23. data/lib/cisco_node_utils/cmd_ref/DEPRECATED.yaml +118 -0
  24. data/lib/cisco_node_utils/cmd_ref/aaa_authorization_service.yaml +14 -0
  25. data/lib/cisco_node_utils/cmd_ref/bfd_global.yaml +117 -0
  26. data/lib/cisco_node_utils/cmd_ref/bgp.yaml +7 -7
  27. data/lib/cisco_node_utils/cmd_ref/bgp_neighbor.yaml +7 -0
  28. data/lib/cisco_node_utils/cmd_ref/dhcp_relay_global.yaml +125 -0
  29. data/lib/cisco_node_utils/cmd_ref/feature.yaml +10 -0
  30. data/lib/cisco_node_utils/cmd_ref/interface.yaml +141 -49
  31. data/lib/cisco_node_utils/cmd_ref/interface_ospf.yaml +44 -0
  32. data/lib/cisco_node_utils/cmd_ref/interface_portchannel.yaml +6 -0
  33. data/lib/cisco_node_utils/cmd_ref/ospf.yaml +6 -0
  34. data/lib/cisco_node_utils/cmd_ref/ospf_area.yaml +91 -0
  35. data/lib/cisco_node_utils/cmd_ref/ospf_area_vlink.yaml +88 -0
  36. data/lib/cisco_node_utils/cmd_ref/overlay_global.yaml +0 -3
  37. data/lib/cisco_node_utils/cmd_ref/show_version.yaml +3 -3
  38. data/lib/cisco_node_utils/cmd_ref/snmp_community.yaml +39 -15
  39. data/lib/cisco_node_utils/cmd_ref/snmp_notification_receiver.yaml +43 -21
  40. data/lib/cisco_node_utils/cmd_ref/snmp_server.yaml +48 -19
  41. data/lib/cisco_node_utils/cmd_ref/snmp_user.yaml +0 -0
  42. data/lib/cisco_node_utils/cmd_ref/tacacs_global.yaml +30 -0
  43. data/lib/cisco_node_utils/cmd_ref/tacacs_server.yaml +18 -6
  44. data/lib/cisco_node_utils/cmd_ref/vdc.yaml +4 -0
  45. data/lib/cisco_node_utils/cmd_ref/virtual_service.yaml +1 -0
  46. data/lib/cisco_node_utils/cmd_ref/vlan.yaml +23 -10
  47. data/lib/cisco_node_utils/cmd_ref/vxlan_vtep.yaml +8 -2
  48. data/lib/cisco_node_utils/cmd_ref/yang.yaml +7 -0
  49. data/lib/cisco_node_utils/cmd_ref/yum.yaml +10 -1
  50. data/lib/cisco_node_utils/constants.rb +8 -1
  51. data/lib/cisco_node_utils/dhcp_relay_global.rb +302 -0
  52. data/lib/cisco_node_utils/exceptions.rb +29 -0
  53. data/lib/cisco_node_utils/feature.rb +28 -0
  54. data/lib/cisco_node_utils/interface.rb +493 -402
  55. data/lib/cisco_node_utils/interface_DEPRECATED.rb +513 -0
  56. data/lib/cisco_node_utils/interface_ospf.rb +126 -0
  57. data/lib/cisco_node_utils/interface_portchannel.rb +16 -0
  58. data/lib/cisco_node_utils/logger.rb +3 -0
  59. data/lib/cisco_node_utils/node.rb +29 -1
  60. data/lib/cisco_node_utils/overlay_global.rb +1 -12
  61. data/lib/cisco_node_utils/pim.rb +1 -0
  62. data/lib/cisco_node_utils/pim_group_list.rb +1 -0
  63. data/lib/cisco_node_utils/pim_rp_address.rb +1 -0
  64. data/lib/cisco_node_utils/platform.rb +9 -2
  65. data/lib/cisco_node_utils/router_ospf.rb +1 -1
  66. data/lib/cisco_node_utils/router_ospf_area.rb +416 -0
  67. data/lib/cisco_node_utils/router_ospf_area_vlink.rb +313 -0
  68. data/lib/cisco_node_utils/router_ospf_vrf.rb +17 -0
  69. data/lib/cisco_node_utils/snmp_notification_receiver.rb +27 -9
  70. data/lib/cisco_node_utils/snmpcommunity.rb +34 -8
  71. data/lib/cisco_node_utils/snmpserver.rb +4 -4
  72. data/lib/cisco_node_utils/snmpuser.rb +0 -0
  73. data/lib/cisco_node_utils/tacacs_global.rb +102 -0
  74. data/lib/cisco_node_utils/tacacs_server.rb +8 -7
  75. data/lib/cisco_node_utils/vdc.rb +25 -7
  76. data/lib/cisco_node_utils/version.rb +1 -1
  77. data/lib/cisco_node_utils/vlan.rb +30 -56
  78. data/lib/cisco_node_utils/vlan_DEPRECATED.rb +108 -0
  79. data/lib/cisco_node_utils/yang.rb +160 -0
  80. data/lib/cisco_node_utils/yum.rb +25 -32
  81. data/tests/.rubocop.yml +3 -0
  82. data/tests/ciscotest.rb +136 -19
  83. data/tests/cmd_config_invalid.yaml +1 -1
  84. data/tests/noop.rb +7 -0
  85. data/tests/tacacs_server.yaml.example +6 -0
  86. data/tests/test_aaa_authentication_login.rb +24 -1
  87. data/tests/test_aaa_authentication_login_service.rb +9 -16
  88. data/tests/test_aaa_authorization_service.rb +111 -84
  89. data/tests/test_bfd_global.rb +278 -0
  90. data/tests/test_bgp_neighbor.rb +20 -0
  91. data/tests/test_bridge_domain_vni.rb +2 -9
  92. data/tests/test_cmn_utils.rb +76 -0
  93. data/tests/test_dhcp_relay_global.rb +284 -0
  94. data/tests/test_dns_domain.rb +4 -4
  95. data/tests/test_domain_name.rb +2 -2
  96. data/tests/test_encapsulation.rb +2 -4
  97. data/tests/test_evpn_vni.rb +14 -7
  98. data/tests/test_fabricpath_global.rb +12 -13
  99. data/tests/test_feature.rb +35 -17
  100. data/tests/test_interface.rb +352 -127
  101. data/tests/test_interface_bdi.rb +2 -2
  102. data/tests/test_interface_channel_group.rb +1 -1
  103. data/tests/test_interface_ospf.rb +153 -23
  104. data/tests/test_interface_portchannel.rb +15 -6
  105. data/tests/test_interface_private_vlan.rb +200 -576
  106. data/tests/test_interface_svi.rb +5 -52
  107. data/tests/test_interface_switchport.rb +80 -240
  108. data/tests/test_itd_device_group.rb +2 -2
  109. data/tests/test_itd_device_group_node.rb +2 -2
  110. data/tests/test_itd_service.rb +1 -1
  111. data/tests/test_name_server.rb +3 -3
  112. data/tests/test_node_ext.rb +15 -17
  113. data/tests/test_ntp_config.rb +1 -1
  114. data/tests/test_ntp_server.rb +3 -3
  115. data/tests/test_nxapi.rb +1 -0
  116. data/tests/test_overlay_global.rb +15 -19
  117. data/tests/test_pim.rb +5 -5
  118. data/tests/test_pim_group_list.rb +1 -37
  119. data/tests/test_pim_rp_address.rb +1 -1
  120. data/tests/test_platform.rb +9 -11
  121. data/tests/test_portchannel_global.rb +43 -3
  122. data/tests/test_radius_server.rb +1 -1
  123. data/tests/test_radius_server_group.rb +1 -1
  124. data/tests/test_router_bgp.rb +17 -30
  125. data/tests/test_router_ospf_area.rb +433 -0
  126. data/tests/test_router_ospf_area_vlink.rb +298 -0
  127. data/tests/test_router_ospf_vrf.rb +17 -0
  128. data/tests/test_snmp_notification_receiver.rb +11 -11
  129. data/tests/test_snmpcommunity.rb +177 -69
  130. data/tests/test_snmpgroup.rb +7 -7
  131. data/tests/test_snmpserver.rb +164 -253
  132. data/tests/test_snmpuser.rb +73 -69
  133. data/tests/test_stp_global.rb +15 -15
  134. data/tests/test_syslog_settings.rb +1 -1
  135. data/tests/test_tacacs_global.rb +80 -0
  136. data/tests/test_tacacs_server.rb +129 -51
  137. data/tests/test_tacacs_server_group.rb +3 -29
  138. data/tests/test_tacacs_server_host.rb +24 -27
  139. data/tests/test_vlan.rb +57 -59
  140. data/tests/test_vlan_private.rb +271 -284
  141. data/tests/test_vpc.rb +10 -4
  142. data/tests/test_vrf.rb +2 -0
  143. data/tests/test_vrf_af.rb +2 -5
  144. data/tests/test_vtp.rb +5 -2
  145. data/tests/test_vxlan_vtep.rb +20 -44
  146. data/tests/test_vxlan_vtep_vni.rb +23 -16
  147. data/tests/test_yang.rb +369 -0
  148. data/tests/test_yum.rb +34 -42
  149. data/tests/yum_package.yaml +35 -0
  150. metadata +31 -4
  151. data/tests/test_vlan_mt_full.rb +0 -85
@@ -0,0 +1,160 @@
1
+ # June 2016, Charles Burkett
2
+ #
3
+ # Copyright (c) 2015-2016 Cisco and/or its affiliates.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require 'json'
18
+
19
+ module Cisco
20
+ # class Cisco::Yang
21
+ # Utility class mainly containing methods to compare YANG configurations
22
+ # in order to determine if the running config is in-sync with the
23
+ # desired config.
24
+ class Yang
25
+ # Is the specified yang string empty?
26
+ def self.empty?(yang)
27
+ !yang || yang.empty?
28
+ end
29
+
30
+ # Given target and current YANG configurations, returns true if
31
+ # the configurations are in-sync, relative to a "merge_config" action
32
+ # @param should [String] the should configuration in YANG JASON format
33
+ # @param is [String] the is configuration in YANG JASON format
34
+ def self.insync_for_merge?(should, is)
35
+ should_hash = self.empty?(should) ? {} : JSON.parse(should)
36
+ is_hash = self.empty?(is) ? {} : JSON.parse(is)
37
+
38
+ !needs_something?(:merge, should_hash, is_hash)
39
+ end
40
+
41
+ # Given a is and should YANG configuration, returns true if
42
+ # the configuration are in-sync, relative to a "replace_config" action
43
+ # @param should [String] the should configuration in YANG JASON format
44
+ # @param is [String] the is configuration in YANG JASON format
45
+ def self.insync_for_replace?(should, is)
46
+ should_hash = self.empty?(should) ? {} : JSON.parse(should)
47
+ is_hash = self.empty?(is) ? {} : JSON.parse(is)
48
+
49
+ !needs_something?(:replace, should_hash, is_hash)
50
+ end
51
+
52
+ # usage:
53
+ # needs_something?(op, should, run)
54
+ #
55
+ # op - symbol - If value is not :replace, it's assumed to be :merge.
56
+ # Indicates to the function whether to check for a
57
+ # possible merge vs. replace
58
+ #
59
+ # should - JSON - JSON tree representing target configuration
60
+ #
61
+ # is - JSON - JSON tree representing current configuration
62
+ #
63
+ #
64
+ # Needs merge will determine if should and is differ
65
+ # sufficiently to necessitate running the merge command.
66
+ #
67
+ # The logic here amounts to determining if should is a subtree
68
+ # of is, with a tiny bit of domain trickiness surrounding
69
+ # elements that are arrays that contain a single nil element
70
+ # that is required for "creating" certain configuration elements.
71
+ #
72
+ # There are ultimately 3 different types of elements in a json
73
+ # tree. Hashes, Arrays, and leaves. While hashes and array values
74
+ # are organized with an order, the logic here ignores the order.
75
+ # In fact, it specifically attempts to match assuming order
76
+ # doesn't matter. This is largely to allow users some freedom
77
+ # in specifying the target configuration. The gRPC interface
78
+ # doesn't seem to care about order. If that changes, then so
79
+ # should this code.
80
+ #
81
+ # Arrays and Hashes are compared by iterating over every element
82
+ # in should, and ensuring it is within is.
83
+ #
84
+ # Leaves are directly compared for equality, excepting the
85
+ # condition that the should leaf is in fact an array with one
86
+ # element that is nil.
87
+ #
88
+ # Needs replace will determine if should and is differ
89
+ # sufficiently to necessitate running the replace command.
90
+ #
91
+ # The logic is the same as merge, except when comparing
92
+ # hashes, if the is hash table has elements that are not
93
+ # in should, we ultimately indicate that replace is needed
94
+ def self.needs_something?(op, should, is)
95
+ !hash_equiv?(op, should, is)
96
+ end
97
+
98
+ def self.nil_array(elt)
99
+ elt.nil? || (elt.is_a?(Array) && elt.length == 1 && elt[0].nil?)
100
+ end
101
+
102
+ def self.sub_elt(op, should, is)
103
+ if should.is_a?(Hash) && is.is_a?(Hash)
104
+ return self.hash_equiv?(op, should, is)
105
+ elsif should.is_a?(Array) && is.is_a?(Array)
106
+ return self.array_equiv?(op, should, is)
107
+ else
108
+ return !(should != is && !nil_array(should))
109
+ end
110
+ end
111
+
112
+ def self.array_equiv?(op, should, is)
113
+ n = should.length
114
+ loop = lambda do|i|
115
+ if i == n
116
+ if op == :replace
117
+ is.length == should.length
118
+ else
119
+ true
120
+ end
121
+ else
122
+ should_elt = should[i]
123
+ is_elt = is.find do |elt|
124
+ sub_elt(op, should_elt, elt)
125
+ end
126
+ if is_elt.nil? && !nil_array(should_elt)
127
+ should_elt.nil?
128
+ else
129
+ loop.call(i + 1)
130
+ end
131
+ end
132
+ end
133
+ loop.call(0)
134
+ end
135
+
136
+ def self.hash_equiv?(op, should, is)
137
+ keys = should.keys
138
+ n = keys.length
139
+ loop = lambda do|i|
140
+ if i == n
141
+ if op == :replace
142
+ is.keys.length == should.keys.length
143
+ else
144
+ true
145
+ end
146
+ else
147
+ k = keys[i]
148
+ is_v = is[k]
149
+ should_v = should[k]
150
+ if is_v.nil? && !nil_array(should_v)
151
+ false
152
+ else
153
+ sub_elt(op, should_v, is_v) && loop.call(i + 1)
154
+ end
155
+ end
156
+ end
157
+ loop.call(0)
158
+ end
159
+ end # Yang
160
+ end # Cisco
@@ -22,38 +22,22 @@ require_relative 'node_util'
22
22
  module Cisco
23
23
  # This Yum class provides cisco package management functions through nxapi.
24
24
  class Yum < NodeUtil
25
- def self.decompose_name(file_name)
26
- # ex: chef-12.0.0alpha.2+20150319.git.1.b6f-1.el5.x86_64.rpm
27
- name_ver_arch_regex = /^([\w\-\+]+)-(\d+\..*)\.(\w{4,})(?:\.rpm)?$/
28
-
29
- # ex n9000_sample-1.0.0-7.0.3.x86_64.rpm
30
- name_ver_arch_regex_nx = /^(.*)-([\d\.]+-[\d\.]+)\.(\w{4,})\.rpm$/
31
-
32
- # ex: b+z-ip2.x64_64
33
- name_arch_regex = /^([\w\-\+]+)\.(\w+)$/
34
-
35
- file_name.match(name_ver_arch_regex) ||
36
- file_name.match(name_ver_arch_regex_nx) ||
37
- file_name.match(name_arch_regex)
38
- end
39
-
40
- def self.validate(pkg)
41
- file_name = pkg.strip.tr(':', '/').split('/').last
42
- pkg_info = Yum.decompose_name(file_name)
43
- if pkg_info.nil?
44
- query_name = file_name
45
- else
46
- if pkg_info[3].nil?
47
- query_name = pkg_info[1]
48
- else
49
- query_name = "#{pkg_info[1]}.#{pkg_info[3]}"
25
+ def self.validate_installed(pkg)
26
+ # Sample data returned from config_get('yum', 'query_all')
27
+ # ["nxos.sample-n8k_EOR.lib32_nxos", "1.0.0-7.0.3.F1.1", "@patching"],
28
+ patch_data = config_get('yum', 'query_all')
29
+ patch_data.each do |name_arch, version, _state|
30
+ # Separate name and architecture
31
+ next if name_arch.rindex('.').nil?
32
+ arch = name_arch.slice!(name_arch.rindex('.')..-1).delete('.')
33
+ # Version/Architecture info not available when only pkg name specified.
34
+ version = arch = '' if name_arch == pkg
35
+ # Check for match
36
+ if pkg.match(name_arch) && pkg.match(version) && pkg.match(arch)
37
+ return true
50
38
  end
51
39
  end
52
- should_ver = pkg_info[2] if pkg_info && pkg_info[3]
53
- ver = query(query_name)
54
- if ver.nil? || (!should_ver.nil? && should_ver != ver)
55
- fail 'Failed to install the requested rpm'
56
- end
40
+ fail 'Failed to install the requested rpm'
57
41
  end
58
42
 
59
43
  def self.detect_vrf
@@ -61,6 +45,7 @@ module Cisco
61
45
  inode = File::Stat.new('/proc/self/ns/net').ino
62
46
  # -L reqd for guestshell's find command
63
47
  vrfname = File.basename(`find -L /var/run/netns/ -inum #{inode}`.chop)
48
+
64
49
  vrf = 'vrf ' + vrfname unless vrfname.empty?
65
50
  vrf
66
51
  end
@@ -73,7 +58,7 @@ module Cisco
73
58
  # which may fail at a later stage yet return a false positive;
74
59
  # therefore a post-validation check is needed here to verify the
75
60
  # actual outcome.
76
- validate(pkg)
61
+ validate_installed(pkg)
77
62
  end
78
63
 
79
64
  # returns version of package, or false if package doesn't exist
@@ -86,7 +71,15 @@ module Cisco
86
71
  end
87
72
 
88
73
  def self.remove(pkg)
89
- config_set('yum', 'remove', pkg)
74
+ config_set('yum', 'deactivate', pkg)
75
+ # May not be able to remove the package immediately after
76
+ # deactivation.
77
+ while (try ||= 1) < 20
78
+ o = config_set('yum', 'remove', pkg)
79
+ break unless o[/operation is in progress, please try again later/]
80
+ sleep 1
81
+ try += 1
82
+ end
90
83
  end
91
84
  end
92
85
  end
data/tests/.rubocop.yml CHANGED
@@ -13,3 +13,6 @@ Metrics/MethodLength:
13
13
 
14
14
  Metrics/PerceivedComplexity:
15
15
  Max: 17
16
+
17
+ Metrics/LineLength:
18
+ Max: 120
data/tests/ciscotest.rb CHANGED
@@ -16,10 +16,11 @@ require 'ipaddr'
16
16
  require 'resolv'
17
17
  require_relative 'basetest'
18
18
  require_relative 'platform_info'
19
+ require_relative '../lib/cisco_node_utils/bridge_domain'
19
20
  require_relative '../lib/cisco_node_utils/interface'
20
21
  require_relative '../lib/cisco_node_utils/node'
22
+ require_relative '../lib/cisco_node_utils/platform'
21
23
  require_relative '../lib/cisco_node_utils/vlan'
22
- require_relative '../lib/cisco_node_utils/bridge_domain'
23
24
 
24
25
  include Cisco
25
26
 
@@ -29,7 +30,8 @@ class CiscoTestCase < TestCase
29
30
  @@node = nil
30
31
  @@interfaces = nil
31
32
  @@interfaces_id = nil
32
- # rubocop:enable Style/ClassVars
33
+ @@testcases = []
34
+ @@testcase_teardowns = 0
33
35
 
34
36
  # The feature (lib/cisco_node_utils/cmd_ref/<feature>.yaml) that this
35
37
  # test case is associated with, if applicable.
@@ -43,6 +45,7 @@ class CiscoTestCase < TestCase
43
45
  end
44
46
 
45
47
  def self.runnable_methods
48
+ @@testcases = super
46
49
  return super if skip_unless_supported.nil?
47
50
  return super if node.cmd_ref.supports?(skip_unless_supported)
48
51
  # If the entire feature under test is unsupported,
@@ -52,6 +55,20 @@ class CiscoTestCase < TestCase
52
55
  [:all_skipped]
53
56
  end
54
57
 
58
+ def first_or_last_teardown
59
+ # Return true if this is the first or last teardown call.
60
+ # This hack is needed to prevent excessive post-test cleanups from
61
+ # occurring: e.g. a non-F3 N7k test class may require an expensive setup
62
+ # and teardown to enable/disable vdc settings; ideally this vdc setup
63
+ # would occur prior to the first test and vdc teardown only after the
64
+ # final test. Checks for first test case because we have to handle the
65
+ # -n option, which filters the list of runnable testcases.
66
+ # Note that Minitest.after_run is not a solution for this problem.
67
+ @@testcase_teardowns += 1
68
+ (@@testcase_teardowns == 1) || (@@testcase_teardowns == @@testcases.size)
69
+ end
70
+ # rubocop:enable Style/ClassVars
71
+
55
72
  def all_skipped
56
73
  skip("Skipping #{self.class}; feature " \
57
74
  "'#{self.class.skip_unless_supported}' is unsupported on this node")
@@ -100,7 +117,7 @@ class CiscoTestCase < TestCase
100
117
 
101
118
  def config_and_warn_on_match(warn_match, *args)
102
119
  if node.client.platform == :ios_xr
103
- result = super(warn_match, *args, 'commit best-effort')
120
+ result = super(warn_match, *args, 'commit')
104
121
  else
105
122
  result = super
106
123
  end
@@ -108,6 +125,11 @@ class CiscoTestCase < TestCase
108
125
  result
109
126
  end
110
127
 
128
+ # Check exception and only fail if it does not contain message
129
+ def check_and_raise_error(exception, message)
130
+ fail exception unless exception.message.include?(message)
131
+ end
132
+
111
133
  def ip_address?(ip)
112
134
  return IPAddr.new(ip).ipv4?
113
135
  rescue IPAddr::InvalidAddressError
@@ -139,6 +161,13 @@ class CiscoTestCase < TestCase
139
161
  flunk(message)
140
162
  end
141
163
 
164
+ def incompatible_interface?(msg)
165
+ patterns = ['switchport_mode is not supported on this interface',
166
+ 'Configuration does not match the port capability']
167
+ assert_match(Regexp.union(patterns), msg,
168
+ 'Msg does not match known incompatibility messages')
169
+ end
170
+
142
171
  def validate_property_excluded?(feature, property)
143
172
  !node.cmd_ref.supports?(feature, property)
144
173
  end
@@ -148,13 +177,22 @@ class CiscoTestCase < TestCase
148
177
  Utils.nexus_i2_image
149
178
  end
150
179
 
180
+ def system_image
181
+ @image ||= Platform.system_image
182
+ end
183
+
184
+ def skip_legacy_defect?(pattern, msg)
185
+ msg = "Defect in legacy image: [#{msg}]"
186
+ skip(msg) if system_image.match(Regexp.new(pattern))
187
+ end
188
+
151
189
  def interfaces
152
190
  unless @@interfaces
153
191
  # Build the platform_info, used for interface lookup
154
192
  # rubocop:disable Style/ClassVars
155
193
  @@interfaces = []
156
194
  Interface.interfaces.each do |int, obj|
157
- next unless /ethernet/.match(int)
195
+ next unless int[%r{ethernet[\d/]+$}] # exclude dot1q & non-eth
158
196
  next if address_match?(obj.ipv4_address)
159
197
  @@interfaces << int
160
198
  end
@@ -165,19 +203,6 @@ class CiscoTestCase < TestCase
165
203
  @@interfaces
166
204
  end
167
205
 
168
- def interfaces_id
169
- unless @@interfaces_id
170
- # rubocop:disable Style/ClassVars
171
- @@interfaces_id = []
172
- interfaces.each do |interface|
173
- id = interface.split('ethernet')[1]
174
- @@interfaces_id << id
175
- end
176
- # rubocop:enable Style/ClassVars
177
- end
178
- @@interfaces_id
179
- end
180
-
181
206
  # Remove all router bgps.
182
207
  def remove_all_bgps
183
208
  require_relative '../lib/cisco_node_utils/bgp'
@@ -202,16 +227,25 @@ class CiscoTestCase < TestCase
202
227
  # This testcase will remove all the bds existing in the system
203
228
  # specifically in cleanup for minitests
204
229
  def remove_all_bridge_domains
205
- config 'system bridge-domain none' if /N7/ =~ node.product_id
230
+ return unless /N7/ =~ node.product_id
206
231
  BridgeDomain.bds.each do |_bd, obj|
207
232
  obj.destroy
208
233
  end
234
+ config 'system bridge-domain none'
235
+ end
236
+
237
+ def remove_all_svis
238
+ Interface.interfaces(:vlan).each do |svi, obj|
239
+ next if svi == 'vlan1'
240
+ obj.destroy
241
+ end
209
242
  end
210
243
 
211
244
  # This testcase will remove all the vlans existing in the system
212
245
  # specifically in cleanup for minitests
213
246
  def remove_all_vlans
214
247
  remove_all_bridge_domains
248
+ remove_all_svis
215
249
  Vlan.vlans.each do |vlan, obj|
216
250
  # skip reserved vlan
217
251
  next if vlan == '1'
@@ -225,6 +259,8 @@ class CiscoTestCase < TestCase
225
259
  require_relative '../lib/cisco_node_utils/vrf'
226
260
  Vrf.vrfs.each do |vrf, obj|
227
261
  next if vrf[/management/]
262
+ # TBD: Remove vrf workaround below after CSCuz56697 is resolved
263
+ config 'vrf context ' + vrf if node.product_id[/N8/]
228
264
  obj.destroy
229
265
  end
230
266
  end
@@ -235,6 +271,86 @@ class CiscoTestCase < TestCase
235
271
  config(*cfg)
236
272
  end
237
273
 
274
+ # TBD: -- The following methods are a WIP --
275
+ #
276
+ # def find_compatible_intf(feature, opt=:raise_skip)
277
+ # # Some platforms require specific linecards before allowing a feature to
278
+ # # be enabled. This method will find a compatible interface or optionally
279
+ # # raise a skip.
280
+ # # TBD: This wants to become a common "compatible interface" checker to
281
+ # # eventually replace all of the single-use methods.
282
+ # intf = compatible_intf(feature)
283
+ # if intf.nil? && opt[/raise_skip/]
284
+ # skip("Unable to find compatible interface for 'feature #{feature}'")
285
+ # end
286
+ # intf
287
+ # end
288
+
289
+ # def compatible_intf(feature)
290
+ # # The feat hash contains module restrictions for a given feature.
291
+ # # :mods - (optional) The module ids used in the 'limit-resource' config
292
+ # # :pids - A regex pattern for the line module product IDs (ref: 'sh mod')
293
+ # feat = {}
294
+ # if node.product_id[/N7K/]
295
+ # feat = {
296
+ # # nv overlay raises error unless solely F3
297
+ # 'nv overlay' => { mods: 'f3', pids: 'N7[K7]-F3' }
298
+ # }
299
+ # end
300
+ # patterns = feat[feature]
301
+ # return interfaces[0] if patterns.nil? # No restrictions for this platform
302
+
303
+ # # Check if module is present and usable; i.e. 'ok'
304
+ # pids = patterns[:pids]
305
+ # sh_mod_string = @device.cmd("show mod | i '^[0-9]+.*#{pids}.*ok'")
306
+ # sh_mod = sh_mod_string[/^(\d+)\s.*#{pids}/]
307
+ # slot = sh_mod.nil? ? nil : Regexp.last_match[1]
308
+ # return nil if slot.nil?
309
+ # intf = "ethernet#{slot}/1"
310
+
311
+ # # Check/Set VDC config. VDC platforms restrict module usage per vdc.
312
+ # mods = patterns[:mods]
313
+ # return intf if mods.nil? || !node.product_id[/N7K/]
314
+ # vdc = Vdc.new(Vdc.default_vdc_name)
315
+ # unless mods == vdc.limit_resource_module_type
316
+ # # Update the allowed module types in this vdc
317
+ # vdc.limit_resource_module_type = mods
318
+ # end
319
+
320
+ # # Return the first interface found in 'allocate interface' config, or nil
321
+ # vdc.allocate_interface[%r{Ethernet#{slot}\/(\d+)}]
322
+ # end
323
+
324
+ def vdc_limit_f3_no_intf_needed(action=:set)
325
+ # This is a special-use method for N7Ks that don't have a physical F3.
326
+ # 1) There are some features that refuse to load unless the VDC is
327
+ # limited to F3 only, but they will actually load if the config is
328
+ # present, despite the fact that there are no physical F3s.
329
+ # 2) We have some tests that need these features but don't need interfaces.
330
+ #
331
+ # action = :set (enable limit F3 config), :clear (default limit config)
332
+ #
333
+ # The limit config should be removed after testing if the device does not
334
+ # have an actual F3.
335
+ return unless node.product_id[/N7K/]
336
+ vdc = Vdc.new(Vdc.default_vdc_name)
337
+ case action
338
+ when :set
339
+ return if vdc.limit_resource_module_type == 'f3'
340
+ vdc.limit_resource_module_type = 'f3'
341
+
342
+ when :clear
343
+ # Remove the config if there are no physical F3 cards
344
+ pids = 'N7[K7]-F3'
345
+ sh_mod_string = @device.cmd("show mod | i '^[0-9]+.*#{pids}'")
346
+ sh_mod = sh_mod_string[/^(\d+)\s.*#{pids}/]
347
+ if sh_mod.nil?
348
+ # It's safe to remove the config
349
+ vdc.limit_resource_module_type = ''
350
+ end
351
+ end
352
+ end
353
+
238
354
  # setup fabricpath env if possible and populate the interfaces array
239
355
  # otherwise cause a global skip
240
356
  def fabricpath_testenv_setup
@@ -291,9 +407,10 @@ class CiscoTestCase < TestCase
291
407
  # '9 12 10/40 Gbps Ethernet Module N77-F312FQ-25 ok'
292
408
  # '2 6 Nexus 6xQSFP Ethernet Module N5K-C5672UP-M6Q ok'
293
409
  # '2 6 Nexus xxQSFP Ethernet Module N6K-C6004-96Q/EF ok'
410
+ # '2 4 Nexus 4xQSFP Ethernet Module N6K-C6001-M4Q ok'
294
411
  if node.product_id[/N(5|6)K/]
295
412
  sh_mod_string = @device.cmd("sh mod | i '^[0-9]+.*N[56]K-C[56]'")
296
- sh_mod = sh_mod_string[/^(\d+)\s.*N[56]K-C(56|6004)/]
413
+ sh_mod = sh_mod_string[/^(\d+)\s.*N[56]K-C(56|600[14])/]
297
414
  skip('Unable to find compatible interface in chassis') if sh_mod.nil?
298
415
  elsif node.product_id[/N7K/]
299
416
  mt_full_interface?