cisco_node_utils 1.2.0 → 1.3.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 (255) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.rspec +2 -0
  4. data/.rubocop.yml +13 -0
  5. data/.travis.yml +4 -1
  6. data/CHANGELOG.md +81 -2
  7. data/CONTRIBUTING.md +2 -17
  8. data/Gemfile +5 -0
  9. data/README.md +92 -47
  10. data/Rakefile +23 -1
  11. data/bin/git/hooks/hook_lib +7 -0
  12. data/bin/git/hooks/pre-commit/check_unstaged_changes +18 -0
  13. data/bin/git/hooks/pre-commit/rubocop +7 -2
  14. data/bin/git/hooks/pre-commit/validate-diffs +18 -4
  15. data/bin/git/hooks/pre-commit/validate-yaml +18 -0
  16. data/bin/git/update-hooks +64 -6
  17. data/cisco_node_utils.gemspec +9 -6
  18. data/docs/README-develop-best-practices.md +149 -50
  19. data/docs/README-develop-node-utils-APIs.md +92 -42
  20. data/docs/README-maintainers.md +7 -4
  21. data/docs/README-test-execution.md +57 -0
  22. data/docs/cisco_node_utils.yaml.example +30 -0
  23. data/docs/template-router.rb +4 -0
  24. data/ext/mkrf_conf.rb +63 -0
  25. data/lib/.rubocop.yml +2 -2
  26. data/lib/cisco_node_utils.rb +5 -0
  27. data/lib/cisco_node_utils/aaa_authentication_login.rb +5 -6
  28. data/lib/cisco_node_utils/aaa_authorization_service.rb +1 -1
  29. data/lib/cisco_node_utils/ace.rb +165 -12
  30. data/lib/cisco_node_utils/acl.rb +2 -1
  31. data/lib/cisco_node_utils/bgp.rb +184 -21
  32. data/lib/cisco_node_utils/bgp_af.rb +94 -249
  33. data/lib/cisco_node_utils/bgp_neighbor.rb +94 -14
  34. data/lib/cisco_node_utils/bgp_neighbor_af.rb +75 -8
  35. data/lib/cisco_node_utils/bridge_domain.rb +183 -0
  36. data/lib/cisco_node_utils/bridge_domain_vni.rb +206 -0
  37. data/lib/cisco_node_utils/cisco_cmn_utils.rb +85 -2
  38. data/lib/cisco_node_utils/client.rb +35 -0
  39. data/lib/cisco_node_utils/client/client.rb +234 -0
  40. data/lib/cisco_node_utils/client/grpc.rb +33 -0
  41. data/lib/cisco_node_utils/client/grpc/client.rb +311 -0
  42. data/lib/cisco_node_utils/client/grpc/ems.proto +148 -0
  43. data/lib/cisco_node_utils/client/grpc/ems.rb +111 -0
  44. data/lib/cisco_node_utils/client/grpc/ems_services.rb +49 -0
  45. data/lib/cisco_node_utils/client/nxapi.rb +31 -0
  46. data/lib/cisco_node_utils/client/nxapi/client.rb +305 -0
  47. data/lib/cisco_node_utils/client/utils.rb +164 -0
  48. data/lib/cisco_node_utils/cmd_ref/README_YAML.md +222 -254
  49. data/lib/cisco_node_utils/cmd_ref/aaa_auth_login_service.yaml +11 -8
  50. data/lib/cisco_node_utils/cmd_ref/aaa_authentication_login.yaml +22 -15
  51. data/lib/cisco_node_utils/cmd_ref/aaa_authorization_service.yaml +11 -8
  52. data/lib/cisco_node_utils/cmd_ref/acl.yaml +21 -16
  53. data/lib/cisco_node_utils/cmd_ref/bgp.yaml +239 -109
  54. data/lib/cisco_node_utils/cmd_ref/bgp_af.yaml +114 -55
  55. data/lib/cisco_node_utils/cmd_ref/bgp_neighbor.yaml +76 -52
  56. data/lib/cisco_node_utils/cmd_ref/bgp_neighbor_af.yaml +106 -62
  57. data/lib/cisco_node_utils/cmd_ref/bridge_domain.yaml +71 -0
  58. data/lib/cisco_node_utils/cmd_ref/bridge_domain_vni.yaml +33 -0
  59. data/lib/cisco_node_utils/cmd_ref/dnsclient.yaml +35 -14
  60. data/lib/cisco_node_utils/cmd_ref/encapsulation.yaml +25 -0
  61. data/lib/cisco_node_utils/cmd_ref/evpn_vni.yaml +23 -17
  62. data/lib/cisco_node_utils/cmd_ref/fabricpath.yaml +94 -83
  63. data/lib/cisco_node_utils/cmd_ref/fabricpath_topology.yaml +22 -17
  64. data/lib/cisco_node_utils/cmd_ref/feature.yaml +76 -26
  65. data/lib/cisco_node_utils/cmd_ref/images.yaml +3 -2
  66. data/lib/cisco_node_utils/cmd_ref/interface.yaml +381 -153
  67. data/lib/cisco_node_utils/cmd_ref/interface_channel_group.yaml +21 -11
  68. data/lib/cisco_node_utils/cmd_ref/interface_ospf.yaml +21 -21
  69. data/lib/cisco_node_utils/cmd_ref/interface_portchannel.yaml +30 -21
  70. data/lib/cisco_node_utils/cmd_ref/interface_service_vni.yaml +18 -13
  71. data/lib/cisco_node_utils/cmd_ref/inventory.yaml +26 -31
  72. data/lib/cisco_node_utils/cmd_ref/itd_device_group.yaml +83 -0
  73. data/lib/cisco_node_utils/cmd_ref/itd_service.yaml +119 -0
  74. data/lib/cisco_node_utils/cmd_ref/memory.yaml +17 -6
  75. data/lib/cisco_node_utils/cmd_ref/ntp_config.yaml +10 -3
  76. data/lib/cisco_node_utils/cmd_ref/ntp_server.yaml +17 -5
  77. data/lib/cisco_node_utils/cmd_ref/ospf.yaml +33 -29
  78. data/lib/cisco_node_utils/cmd_ref/overlay_global.yaml +12 -10
  79. data/lib/cisco_node_utils/cmd_ref/pim.yaml +16 -19
  80. data/lib/cisco_node_utils/cmd_ref/portchannel_global.yaml +40 -25
  81. data/lib/cisco_node_utils/cmd_ref/radius_global.yaml +17 -12
  82. data/lib/cisco_node_utils/cmd_ref/radius_server.yaml +71 -35
  83. data/lib/cisco_node_utils/cmd_ref/radius_server_group.yaml +10 -5
  84. data/lib/cisco_node_utils/cmd_ref/show_system.yaml +6 -2
  85. data/lib/cisco_node_utils/cmd_ref/show_version.yaml +47 -43
  86. data/lib/cisco_node_utils/cmd_ref/snmp_community.yaml +13 -11
  87. data/lib/cisco_node_utils/cmd_ref/snmp_group.yaml +4 -2
  88. data/lib/cisco_node_utils/cmd_ref/snmp_notification_receiver.yaml +23 -21
  89. data/lib/cisco_node_utils/cmd_ref/snmp_server.yaml +26 -22
  90. data/lib/cisco_node_utils/cmd_ref/snmp_user.yaml +19 -17
  91. data/lib/cisco_node_utils/cmd_ref/snmpnotification.yaml +18 -6
  92. data/lib/cisco_node_utils/cmd_ref/stp_global.yaml +234 -0
  93. data/lib/cisco_node_utils/cmd_ref/syslog_server.yaml +24 -9
  94. data/lib/cisco_node_utils/cmd_ref/syslog_settings.yaml +5 -3
  95. data/lib/cisco_node_utils/cmd_ref/system.yaml +4 -3
  96. data/lib/cisco_node_utils/cmd_ref/tacacs_server.yaml +22 -20
  97. data/lib/cisco_node_utils/cmd_ref/tacacs_server_group.yaml +27 -15
  98. data/lib/cisco_node_utils/cmd_ref/tacacs_server_host.yaml +45 -16
  99. data/lib/cisco_node_utils/cmd_ref/vdc.yaml +21 -11
  100. data/lib/cisco_node_utils/cmd_ref/virtual_service.yaml +3 -2
  101. data/lib/cisco_node_utils/cmd_ref/vlan.yaml +60 -32
  102. data/lib/cisco_node_utils/cmd_ref/vpc.yaml +118 -101
  103. data/lib/cisco_node_utils/cmd_ref/vrf.yaml +54 -58
  104. data/lib/cisco_node_utils/cmd_ref/vrf_af.yaml +118 -0
  105. data/lib/cisco_node_utils/cmd_ref/vtp.yaml +19 -25
  106. data/lib/cisco_node_utils/cmd_ref/vxlan_vtep.yaml +28 -18
  107. data/lib/cisco_node_utils/cmd_ref/vxlan_vtep_vni.yaml +34 -17
  108. data/lib/cisco_node_utils/cmd_ref/yum.yaml +6 -4
  109. data/lib/cisco_node_utils/command_reference.rb +261 -142
  110. data/lib/cisco_node_utils/constants.rb +33 -0
  111. data/lib/cisco_node_utils/encapsulation.rb +112 -0
  112. data/lib/cisco_node_utils/environment.rb +102 -0
  113. data/lib/cisco_node_utils/evpn_vni.rb +5 -3
  114. data/lib/cisco_node_utils/exceptions.rb +111 -0
  115. data/lib/cisco_node_utils/fabricpath_global.rb +52 -35
  116. data/lib/cisco_node_utils/fabricpath_topology.rb +44 -57
  117. data/lib/cisco_node_utils/feature.rb +165 -3
  118. data/lib/cisco_node_utils/interface.rb +1051 -260
  119. data/lib/cisco_node_utils/interface_channel_group.rb +11 -10
  120. data/lib/cisco_node_utils/interface_ospf.rb +1 -2
  121. data/lib/cisco_node_utils/interface_portchannel.rb +4 -12
  122. data/lib/cisco_node_utils/interface_service_vni.rb +7 -7
  123. data/lib/cisco_node_utils/itd_device_group.rb +248 -0
  124. data/lib/cisco_node_utils/itd_device_group_node.rb +144 -0
  125. data/lib/cisco_node_utils/itd_service.rb +523 -0
  126. data/lib/cisco_node_utils/logger.rb +75 -0
  127. data/lib/cisco_node_utils/node.rb +62 -192
  128. data/lib/cisco_node_utils/node_util.rb +56 -10
  129. data/lib/cisco_node_utils/overlay_global.rb +2 -2
  130. data/lib/cisco_node_utils/pim.rb +2 -13
  131. data/lib/cisco_node_utils/pim_group_list.rb +1 -1
  132. data/lib/cisco_node_utils/pim_rp_address.rb +1 -1
  133. data/lib/cisco_node_utils/platform.rb +52 -21
  134. data/lib/cisco_node_utils/portchannel_global.rb +89 -19
  135. data/lib/cisco_node_utils/radius_server.rb +168 -37
  136. data/lib/cisco_node_utils/router_ospf.rb +20 -35
  137. data/lib/cisco_node_utils/router_ospf_vrf.rb +4 -4
  138. data/lib/cisco_node_utils/snmpserver.rb +1 -6
  139. data/lib/cisco_node_utils/snmpuser.rb +6 -4
  140. data/lib/cisco_node_utils/stp_global.rb +676 -0
  141. data/lib/cisco_node_utils/syslog_server.rb +77 -18
  142. data/lib/cisco_node_utils/syslog_settings.rb +1 -1
  143. data/lib/cisco_node_utils/tacacs_server_group.rb +8 -4
  144. data/lib/cisco_node_utils/tacacs_server_host.rb +115 -25
  145. data/lib/cisco_node_utils/vdc.rb +12 -0
  146. data/lib/cisco_node_utils/version.rb +1 -1
  147. data/lib/cisco_node_utils/vlan.rb +147 -29
  148. data/lib/cisco_node_utils/vpc.rb +55 -3
  149. data/lib/cisco_node_utils/vrf.rb +72 -11
  150. data/lib/cisco_node_utils/vrf_af.rb +114 -29
  151. data/lib/cisco_node_utils/vtp.rb +34 -52
  152. data/lib/cisco_node_utils/vxlan_vtep.rb +34 -8
  153. data/lib/cisco_node_utils/vxlan_vtep_vni.rb +36 -4
  154. data/lib/minitest/environment_plugin.rb +31 -0
  155. data/lib/minitest/log_level_plugin.rb +41 -0
  156. data/spec/client_spec.rb +7 -0
  157. data/spec/environment_spec.rb +263 -0
  158. data/spec/grpc_client_spec.rb +23 -0
  159. data/spec/isolate/all_clients_spec.rb +9 -0
  160. data/spec/isolate/grpc_only_spec.rb +16 -0
  161. data/spec/isolate/no_clients_spec.rb +26 -0
  162. data/spec/isolate/nxapi_only_spec.rb +16 -0
  163. data/spec/nxapi_client_spec.rb +42 -0
  164. data/spec/schema.yaml +75 -0
  165. data/spec/shared_examples_for_clients.rb +14 -0
  166. data/spec/spec_helper.rb +91 -0
  167. data/spec/whitespace_spec.rb +10 -0
  168. data/spec/yaml_spec.rb +42 -0
  169. data/tests/.rubocop.yml +2 -2
  170. data/tests/CSCuxdublin-1.0.0-7.0.3.I3.1.lib32_n9000.rpm +0 -0
  171. data/tests/basetest.rb +96 -36
  172. data/tests/ciscotest.rb +220 -12
  173. data/tests/cmd_config.yaml +71 -49
  174. data/tests/cmd_config_invalid.yaml +1 -1
  175. data/tests/test_aaa_authentication_login.rb +1 -0
  176. data/tests/test_aaa_authentication_login_service.rb +9 -0
  177. data/tests/test_aaa_authorization_service.rb +173 -367
  178. data/tests/test_ace.rb +171 -100
  179. data/tests/test_acl.rb +10 -1
  180. data/tests/test_bgp_af.rb +395 -728
  181. data/tests/test_bgp_neighbor.rb +274 -115
  182. data/tests/test_bgp_neighbor_af.rb +178 -77
  183. data/tests/test_bridge_domain.rb +191 -0
  184. data/tests/test_bridge_domain_vni.rb +116 -0
  185. data/tests/test_client_utils.rb +111 -0
  186. data/tests/test_command_config.rb +9 -5
  187. data/tests/test_command_reference.rb +380 -102
  188. data/tests/test_dns_domain.rb +13 -3
  189. data/tests/test_domain_name.rb +13 -3
  190. data/tests/test_encapsulation.rb +77 -0
  191. data/tests/test_evpn_vni.rb +25 -7
  192. data/tests/test_fabricpath_global.rb +167 -163
  193. data/tests/test_fabricpath_topology.rb +12 -33
  194. data/tests/test_feature.rb +215 -0
  195. data/tests/test_grpc.rb +166 -0
  196. data/tests/test_interface.rb +585 -344
  197. data/tests/test_interface_bdi.rb +80 -0
  198. data/tests/test_interface_channel_group.rb +6 -3
  199. data/tests/test_interface_ospf.rb +26 -24
  200. data/tests/test_interface_portchannel.rb +1 -0
  201. data/tests/test_interface_private_vlan.rb +724 -0
  202. data/tests/test_interface_service_vni.rb +37 -66
  203. data/tests/test_interface_svi.rb +98 -101
  204. data/tests/test_interface_switchport.rb +419 -549
  205. data/tests/test_itd_device_group.rb +145 -0
  206. data/tests/test_itd_device_group_node.rb +199 -0
  207. data/tests/test_itd_service.rb +298 -0
  208. data/tests/test_logger.rb +43 -0
  209. data/tests/test_name_server.rb +11 -2
  210. data/tests/test_node.rb +16 -75
  211. data/tests/test_node_ext.rb +174 -163
  212. data/tests/test_node_util.rb +119 -0
  213. data/tests/test_ntp_config.rb +5 -1
  214. data/tests/test_ntp_server.rb +2 -2
  215. data/tests/test_nxapi.rb +221 -0
  216. data/tests/test_overlay_global.rb +47 -38
  217. data/tests/test_pim.rb +2 -0
  218. data/tests/test_pim_group_list.rb +2 -0
  219. data/tests/test_pim_rp_address.rb +2 -0
  220. data/tests/test_platform.rb +86 -39
  221. data/tests/test_portchannel_global.rb +211 -135
  222. data/tests/test_radius_global.rb +13 -5
  223. data/tests/test_radius_server.rb +256 -104
  224. data/tests/test_radius_server_group.rb +2 -0
  225. data/tests/test_router_bgp.rb +781 -485
  226. data/tests/test_router_ospf.rb +26 -103
  227. data/tests/test_router_ospf_vrf.rb +52 -57
  228. data/tests/test_snmp_notification_receiver.rb +2 -0
  229. data/tests/test_snmpcommunity.rb +2 -0
  230. data/tests/test_snmpgroup.rb +2 -0
  231. data/tests/test_snmpnotification.rb +40 -21
  232. data/tests/test_snmpserver.rb +2 -0
  233. data/tests/test_snmpuser.rb +2 -0
  234. data/tests/test_stp_global.rb +563 -0
  235. data/tests/test_syslog_server.rb +32 -8
  236. data/tests/test_syslog_settings.rb +22 -9
  237. data/tests/test_tacacs_server.rb +32 -27
  238. data/tests/test_tacacs_server_group.rb +100 -45
  239. data/tests/test_tacacs_server_host.rb +135 -43
  240. data/tests/test_vdc.rb +2 -16
  241. data/tests/test_vlan.rb +106 -54
  242. data/tests/test_vlan_mt_full.rb +11 -21
  243. data/tests/test_vlan_private.rb +669 -0
  244. data/tests/test_vpc.rb +312 -159
  245. data/tests/test_vrf.rb +122 -113
  246. data/tests/test_vrf_af.rb +238 -0
  247. data/tests/test_vtp.rb +58 -102
  248. data/tests/test_vxlan_vtep.rb +38 -17
  249. data/tests/test_vxlan_vtep_vni.rb +61 -9
  250. data/tests/test_yum.rb +49 -25
  251. metadata +122 -36
  252. data/lib/cisco_node_utils/cmd_ref/fex.yaml +0 -9
  253. data/lib/cisco_node_utils/cmd_ref/vni.yaml +0 -76
  254. data/lib/cisco_node_utils/vni.rb +0 -227
  255. data/tests/test_vni.rb +0 -106
data/tests/test_pim.rb CHANGED
@@ -45,6 +45,8 @@ include Cisco
45
45
 
46
46
  # TestPim - Minitest for Pim Feature
47
47
  class TestPim < CiscoTestCase
48
+ @skip_unless_supported = 'pim'
49
+
48
50
  @@pre_clean_needed = true # rubocop:disable Style/ClassVars
49
51
 
50
52
  # Enables feature pim
@@ -32,6 +32,8 @@ include Cisco
32
32
 
33
33
  # TestPim - Minitest for PimGrouplist
34
34
  class TestPimGroupList < CiscoTestCase
35
+ @skip_unless_supported = 'pim'
36
+
35
37
  # Enables feature pim
36
38
  #--------------------
37
39
  def setup
@@ -31,6 +31,8 @@ include Cisco
31
31
 
32
32
  # TestPimRpAddress - Minitest for PimRpAddress
33
33
  class TestPimRpAddress < CiscoTestCase
34
+ @skip_unless_supported = 'pim'
35
+
34
36
  # Enables feature pim
35
37
  #--------------------
36
38
  def setup
@@ -17,15 +17,40 @@ require_relative '../lib/cisco_node_utils/platform'
17
17
 
18
18
  # TestPlatform - Minitest for Platform class
19
19
  class TestPlatform < CiscoTestCase
20
+ def test_image_version
21
+ case platform
22
+ when :ios_xr
23
+ refute_empty(Platform.image_version)
24
+
25
+ when :nexus
26
+ # Supported Images:
27
+ # N3/9k: 7.0(3)I2(*), 7.0(3)I3(1)
28
+ # N7k: 7.3(1)D1(1)
29
+ # N5/6k: 7.3(0)N1(1)
30
+
31
+ in_pat = '(^ NXOS: version |^ system: version)'
32
+ s = @device.cmd("show version | i '#{in_pat}'")
33
+
34
+ out_pat = %r{/(\d\.\d\(\d\)[IDN])\d\(\d\)/}
35
+ show = s.match(out_pat).to_s
36
+ plat = Platform.image_version.match(out_pat).to_s
37
+ assert_equal(show, plat)
38
+ end
39
+ end
40
+
20
41
  def test_system_image
21
- s = @device.cmd('show version | i image').scan(/ (\S+)$/).flatten.first
22
- assert_equal(s, Platform.system_image)
42
+ if platform == :ios_xr
43
+ assert_nil(Platform.system_image)
44
+ elsif platform == :nexus
45
+ s = @device.cmd('show version | i image').scan(/ (\S+)$/).flatten.first
46
+ assert_equal(s, Platform.system_image)
47
+ end
23
48
  end
24
49
 
25
50
  def test_packages
26
51
  # [['pack1', 'state1'], ['pack2', 'state2'], ...]
27
52
  # 'state' should always be a variant of Active or Inactive
28
- pkgs = @device.cmd('sh inst patch | no-more')
53
+ pkgs = @device.cmd('sh inst patch')
29
54
  .scan(/\n(\S+)\s+(\S*[aA]ctive.*)\n/)
30
55
  # convert to hash with key pkg_name and value pkg_state
31
56
  pkg_hsh = {}
@@ -34,7 +59,13 @@ class TestPlatform < CiscoTestCase
34
59
  end
35
60
 
36
61
  def test_hardware_type
37
- s = @device.cmd('sh ver | no-m').scan(/Hardware\n\s+(.*)\n/).flatten.first
62
+ if platform == :ios_xr
63
+ s = @device.cmd('show inv | inc "Rack 0"').scan(/DESCR: "(.*)"/)
64
+ elsif platform == :nexus
65
+ s = @device.cmd('sh ver').scan(/Hardware\n\s+(.*)\n/)
66
+ end
67
+ s = s.flatten.first
68
+ refute_empty(Platform.hardware_type)
38
69
  # hardware type returns a different value depending on whether you use the
39
70
  # ascii or show output of nxapi, but show appears to be substring of ascii
40
71
  assert(s.include?(Platform.hardware_type),
@@ -42,45 +73,60 @@ class TestPlatform < CiscoTestCase
42
73
  end
43
74
 
44
75
  def test_cpu
45
- s = @device.cmd('sh ver | no-m').scan(
76
+ s = @device.cmd('sh ver').scan(
46
77
  /Hardware\n\s+.*\n\s+(.*) with/).flatten.first
47
78
  assert_equal(s, Platform.cpu)
48
79
  end
49
80
 
50
81
  def test_memory
51
- arr = @device.cmd('sh sys reso').scan(
52
- /(\S+) total.* (\S+) used.* (\S+) free/).flatten
53
- mem_hsh = { 'total' => arr[0],
54
- 'used' => arr[1],
55
- 'free' => arr[2] }
56
- # used and free memory change rapidly, compare total and sums of free + used
82
+ if platform == :ios_xr
83
+ arr = @device.cmd('sh mem summ').scan(
84
+ /Physical Memory: (\S+) total.*\((\S+) available/).flatten
85
+ mem_hsh = { 'total' => arr[0],
86
+ 'used' => nil,
87
+ 'free' => arr[1] }
88
+ elsif platform == :nexus
89
+ arr = @device.cmd('sh sys reso').scan(
90
+ /(\S+) total.* (\S+) used.* (\S+) free/).flatten
91
+ mem_hsh = { 'total' => arr[0],
92
+ 'used' => arr[1],
93
+ 'free' => arr[2] }
94
+ end
57
95
  assert_equal(mem_hsh['total'], Platform.memory['total'])
58
- assert_equal(mem_hsh['used'].to_i + mem_hsh['free'].to_i,
59
- Platform.memory['used'].to_i + Platform.memory['free'].to_i)
60
- # assert(Platform.memory.has_key?('used'),
61
- # "Platform memory has no key 'used'")
62
- # assert(Platform.memory.has_key?('free'),
63
- # "Platform memory has no key 'free'")
96
+ if platform == :nexus
97
+ # used and free mem change rapidly, compare total and sums of free + used
98
+ assert_equal(mem_hsh['used'].to_i + mem_hsh['free'].to_i,
99
+ Platform.memory['used'].to_i + Platform.memory['free'].to_i)
100
+ end
101
+ assert(Platform.memory.key?('used'),
102
+ "Platform memory has no key 'used'")
103
+ assert(Platform.memory.key?('free'),
104
+ "Platform memory has no key 'free'")
64
105
  end
65
106
 
66
107
  def test_board
67
- s = @device.cmd('sh ver | no-m').scan(/Board ID (\S+)/).flatten.first
108
+ s = @device.cmd('sh ver').scan(/Board ID (\S+)/).flatten.first
68
109
  assert_equal(s, Platform.board)
69
110
  end
70
111
 
71
112
  def test_uptime
72
- s = @device.cmd('sh ver | no-m').scan(/uptime is (.*)/).flatten.first
113
+ s = @device.cmd('sh ver').scan(/uptime is (.*)/).flatten.first
73
114
  # compare without seconds
74
115
  assert_equal(s.gsub(/\d+ sec/, ''), Platform.uptime.gsub(/\d+ sec/, ''))
75
116
  end
76
117
 
77
118
  def test_last_reset
78
- s = @device.cmd('sh ver | no-m').scan(/usecs after\s+(.*)/).flatten.first
79
- assert_equal(s, Platform.last_reset)
119
+ s = @device.cmd('sh ver').scan(/usecs after\s+(.*)/).flatten.first
120
+ if Utils.nexus_i2_image
121
+ # Platform issue CSCuy72214, uncertain if this will ever be fixed in I2
122
+ assert_nil(Platform.last_reset)
123
+ else
124
+ assert_equal(s, Platform.last_reset)
125
+ end
80
126
  end
81
127
 
82
128
  def test_reset_reason
83
- s = @device.cmd('sh ver | no-m').scan(/Reason: (.*)/).flatten.first
129
+ s = @device.cmd('sh ver').scan(/Reason: (.*)/).flatten.first
84
130
  assert_equal(s, Platform.reset_reason)
85
131
  end
86
132
 
@@ -103,25 +149,34 @@ class TestPlatform < CiscoTestCase
103
149
  # Everything from DESCR onwards follows the same general format so we
104
150
  # can define a single base regexp and extend it as needed for Chassis, Slot,
105
151
  # Power Supply, and Fan inventory entries.
106
- def inv_cmn_re
107
- /.*DESCR:\s+"(.*)"\s*\nPID:\s+(\S+).*VID:\s+(\S+).*SN:\s+(\S+)/
152
+ #
153
+ # On some platforms, some fields may be empty:
154
+ # NAME: "Chassis", DESCR: "NX-OSv Chassis"
155
+ # PID: N9K-NXOSV , VID: , SN:
156
+ def inv_cmn_re(name_expr)
157
+ /NAME:\s+"#{name_expr}",\s+
158
+ DESCR:\s+"(.*)"\s*
159
+ \n
160
+ PID:\s+(\S*)\s*,\s*
161
+ VID:\s+(\S*)\s*,\s*
162
+ SN:\s+(\S*)\s*
163
+ $/x
108
164
  end
109
165
 
110
166
  def test_chassis
111
- arr = @device.cmd('sh inv | no-m').scan(/NAME:\s+"Chassis"#{inv_cmn_re}/)
167
+ arr = @device.cmd('sh inv').scan(inv_cmn_re('Chassis'))
112
168
  arr = arr.flatten
113
169
  # convert to hash
114
170
  chas_hsh = { 'descr' => arr[0],
115
171
  'pid' => arr[1],
116
172
  'vid' => arr[2],
117
173
  'sn' => arr[3],
118
- }
174
+ } unless arr.empty?
119
175
  assert_equal(chas_hsh, Platform.chassis)
120
176
  end
121
177
 
122
178
  def test_slots
123
- slots_arr_arr = @device.cmd('sh inv | no-m')
124
- .scan(/NAME:\s+"(Slot \d+)"#{inv_cmn_re}/)
179
+ slots_arr_arr = @device.cmd('sh inv').scan(inv_cmn_re('(Slot\s+\d+)'))
125
180
  # convert to array of slot hashes
126
181
  slots_hsh_hsh = {}
127
182
  slots_arr_arr.each do |slot|
@@ -135,10 +190,8 @@ class TestPlatform < CiscoTestCase
135
190
  end
136
191
 
137
192
  def test_power_supplies
138
- pwr_arr_arr = @device.cmd('sh inv | no-m')
139
- .scan(/NAME:\s+"(Power Supply \d+)"#{inv_cmn_re}/)
140
- refute_empty(pwr_arr_arr,
141
- 'Regex scan failed to match show inventory output')
193
+ pwr_arr_arr = @device.cmd('sh inv')
194
+ .scan(inv_cmn_re('(Power\s+Supply\s+\d+)'))
142
195
 
143
196
  # convert to array of power supply hashes
144
197
  pwr_hsh_hsh = {}
@@ -153,10 +206,7 @@ class TestPlatform < CiscoTestCase
153
206
  end
154
207
 
155
208
  def test_fans
156
- fan_arr_arr = @device.cmd('sh inv | no-m')
157
- .scan(/NAME:\s+"(Fan \d+)"#{inv_cmn_re}/)
158
- refute_empty(fan_arr_arr,
159
- 'Regex scan failed to match show inventory output')
209
+ fan_arr_arr = @device.cmd('sh inv').scan(inv_cmn_re('(Fan\s+\d+)'))
160
210
 
161
211
  # convert to array of fan hashes
162
212
  fan_hsh_hsh = {}
@@ -171,9 +221,6 @@ class TestPlatform < CiscoTestCase
171
221
  end
172
222
 
173
223
  def test_virtual_services
174
- skip('Skip test: No virtual-services installed') unless
175
- @device.cmd('show virtual-service list')[/Name\s+Status\s+Package Name/]
176
-
177
224
  # this would be beyond ugly to parse from ascii, utilize config_get
178
225
  vir_arr = node.config_get('virtual_service', 'services')
179
226
  vir_arr = [vir_arr] if vir_arr.is_a? Hash
@@ -17,24 +17,26 @@ require_relative '../lib/cisco_node_utils/portchannel_global'
17
17
 
18
18
  # TestX__CLASS_NAME__X - Minitest for X__CLASS_NAME__X node utility class
19
19
  class TestPortchannelGlobal < CiscoTestCase
20
- # TESTS
21
-
20
+ @skip_unless_supported = 'portchannel_global'
21
+ @@cleaned = false # rubocop:disable Style/ClassVars
22
22
  DEFAULT_NAME = 'default'
23
23
 
24
24
  def setup
25
25
  super
26
- config 'no port-channel load-balance' unless n6k_platform?
27
- config 'no port-channel load-balance ethernet' unless
28
- n9k_platform? || n7k_platform?
26
+ cleanup unless @@cleaned
27
+ @@cleaned = true # rubocop:disable Style/ClassVars
29
28
  end
30
29
 
31
30
  def teardown
32
- config 'no port-channel load-balance' unless n6k_platform?
33
- config 'no port-channel load-balance ethernet' unless
34
- n9k_platform? || n7k_platform?
31
+ cleanup
35
32
  super
36
33
  end
37
34
 
35
+ def cleanup
36
+ ethernet = node.product_id[/N(3|7|8|9)/] ? '' : 'ethernet'
37
+ config_no_warn "no port-channel load-balance #{ethernet}"
38
+ end
39
+
38
40
  def n3k_in_n3k_mode?
39
41
  return unless /N3/ =~ node.product_id
40
42
  mode = config('show system switch-mode')
@@ -44,159 +46,233 @@ class TestPortchannelGlobal < CiscoTestCase
44
46
  mode[Regexp.union(patterns)] ? true : false
45
47
  end
46
48
 
47
- def n7k_platform?
48
- /N7/ =~ node.product_id
49
- end
50
-
51
- def n9k_platform?
52
- /N(3|9)/ =~ node.product_id
53
- end
54
-
55
- def n6k_platform?
56
- /N(5|6)/ =~ node.product_id
57
- end
58
-
59
49
  def create_portchannel_global(name=DEFAULT_NAME)
60
50
  PortChannelGlobal.new(name)
61
51
  end
62
52
 
63
- def test_get_hash_distribution
64
- skip('Platform does not support this property') if n6k_platform? ||
65
- n9k_platform?
66
- @global = create_portchannel_global
67
- @global.hash_distribution = 'fixed'
68
- assert_equal('fixed', @global.hash_distribution)
69
- @global.hash_distribution =
70
- @global.default_hash_distribution
71
- assert_equal(@global.default_hash_distribution,
72
- @global.hash_distribution)
53
+ def test_hash_distribution
54
+ global = create_portchannel_global
55
+ if validate_property_excluded?('portchannel_global', 'hash_distribution')
56
+ assert_raises(Cisco::UnsupportedError) do
57
+ global.hash_distribution = 'fixed'
58
+ end
59
+ assert_nil(global.hash_distribution)
60
+ else
61
+ global.hash_distribution = 'fixed'
62
+ assert_equal('fixed', global.hash_distribution)
63
+ global.hash_distribution =
64
+ global.default_hash_distribution
65
+ assert_equal(global.default_hash_distribution,
66
+ global.hash_distribution)
67
+ end
73
68
  end
74
69
 
75
- def test_get_set_load_defer
76
- skip('Platform does not support this property') if n6k_platform? ||
77
- n9k_platform?
78
- @global = create_portchannel_global
79
- @global.load_defer = 1000
80
- assert_equal(1000, @global.load_defer)
81
- @global.load_defer =
82
- @global.default_load_defer
83
- assert_equal(@global.default_load_defer,
84
- @global.load_defer)
70
+ def test_load_defer
71
+ global = create_portchannel_global
72
+ if validate_property_excluded?('portchannel_global', 'load_defer')
73
+ assert_raises(Cisco::UnsupportedError) do
74
+ global.load_defer = 1000
75
+ end
76
+ assert_nil(global.load_defer)
77
+ else
78
+ global.load_defer = 1000
79
+ assert_equal(1000, global.load_defer)
80
+ global.load_defer =
81
+ global.default_load_defer
82
+ assert_equal(global.default_load_defer,
83
+ global.load_defer)
84
+ end
85
85
  end
86
86
 
87
- def test_get_set_resilient
88
- skip('Platform does not support this property') if n6k_platform? ||
89
- n7k_platform?
90
- @global = create_portchannel_global
91
- @global.resilient = true
92
- assert_equal(true, @global.resilient)
93
- @global.resilient = @global.default_resilient
94
- assert_equal(@global.default_resilient, @global.resilient)
87
+ def test_resilient
88
+ global = create_portchannel_global
89
+ if validate_property_excluded?('portchannel_global', 'resilient')
90
+ assert_raises(Cisco::UnsupportedError) { global.resilient = true }
91
+ assert_nil(global.resilient)
92
+ return
93
+ end
94
+
95
+ # Verify that hardware supports feature. Unfortunately the current cli
96
+ # only displays a warning and does not raise an error so we have to
97
+ # test for it explicitly.
98
+ cmd = 'port-channel load-balance resilient'
99
+ skip('Skip test: Feature is not supported on this device') if
100
+ config(cmd)[/Resilient Hashing Mode unsupported/]
101
+ global = create_portchannel_global
102
+ # For n3k the default is different from n9k
103
+ if n3k_in_n3k_mode?
104
+ global.resilient = false
105
+ refute(global.resilient)
106
+ global.resilient = global.default_resilient
107
+ assert_equal(global.default_resilient, global.resilient)
108
+ else
109
+ config('no ' + cmd)
110
+ global = create_portchannel_global
111
+ global.resilient = true
112
+ assert(global.resilient)
113
+ global.resilient = global.default_resilient
114
+ assert_equal(global.default_resilient, global.resilient)
115
+ end
95
116
  end
96
117
 
97
- def test_get_set_port_channel_load_balance_sym_concat_rot
98
- skip('Platform does not support this property') if
99
- n6k_platform? || n7k_platform? || n3k_in_n3k_mode?
100
- @global = create_portchannel_global
101
- @global.send(:port_channel_load_balance=,
102
- 'src-dst', 'ip-l4port', nil, nil, true, true, 4)
118
+ def test_load_balance_no_rotate
119
+ skip('Test not supported on this platform') unless n3k_in_n3k_mode?
120
+
121
+ global = create_portchannel_global
122
+ global.send(:port_channel_load_balance=,
123
+ 'src-dst', 'ip-only', nil, nil, true, nil, nil)
103
124
  assert_equal('src-dst',
104
- @global.bundle_select)
105
- assert_equal('ip-l4port',
106
- @global.bundle_hash)
107
- assert_equal(true, @global.symmetry)
108
- assert_equal(true, @global.concatenation)
109
- assert_equal(4, @global.rotate)
110
- @global.send(
125
+ global.bundle_select)
126
+ assert_equal('ip-only',
127
+ global.bundle_hash)
128
+ assert_equal(true, global.symmetry)
129
+ global.send(
111
130
  :port_channel_load_balance=,
112
- @global.default_bundle_select,
113
- @global.default_bundle_hash,
131
+ global.default_bundle_select,
132
+ global.default_bundle_hash,
114
133
  nil,
115
134
  nil,
116
- @global.default_symmetry,
117
- @global.default_concatenation,
118
- @global.default_rotate)
119
- assert_equal(
120
- @global.default_bundle_select,
121
- @global.bundle_select)
135
+ global.default_symmetry,
136
+ nil,
137
+ nil)
122
138
  assert_equal(
123
- @global.default_bundle_hash,
124
- @global.bundle_hash)
139
+ global.default_bundle_select,
140
+ global.bundle_select)
125
141
  assert_equal(
126
- @global.default_symmetry,
127
- @global.symmetry)
142
+ global.default_bundle_hash,
143
+ global.bundle_hash)
128
144
  assert_equal(
129
- @global.default_concatenation,
130
- @global.concatenation)
131
- assert_equal(@global.default_rotate,
132
- @global.rotate)
145
+ global.default_symmetry,
146
+ global.symmetry)
133
147
  end
134
148
 
135
- def test_get_set_port_channel_load_balance_hash_poly
136
- skip('Platform does not support this property') if n7k_platform? ||
137
- n9k_platform?
138
- @global = create_portchannel_global
139
- @global.send(:port_channel_load_balance=,
140
- 'src-dst', 'ip-only', 'CRC10c', nil, nil, nil, nil)
141
- assert_equal('src-dst',
142
- @global.bundle_select)
143
- assert_equal('ip-only',
144
- @global.bundle_hash)
145
- assert_equal('CRC10c', @global.hash_poly)
146
- @global.send(:port_channel_load_balance=,
147
- 'dst', 'mac', 'CRC10a', nil, nil, nil, nil)
148
- assert_equal('dst',
149
- @global.bundle_select)
150
- assert_equal('mac',
151
- @global.bundle_hash)
152
- assert_equal('CRC10a', @global.hash_poly)
153
- @global.send(
154
- :port_channel_load_balance=,
155
- @global.default_bundle_select,
156
- @global.default_bundle_hash,
157
- @global.default_hash_poly,
158
- nil, nil, nil, nil)
159
- assert_equal(
160
- @global.default_bundle_select,
161
- @global.bundle_select)
162
- assert_equal(
163
- @global.default_bundle_hash,
164
- @global.bundle_hash)
165
- assert_equal(@global.default_hash_poly,
166
- @global.hash_poly)
167
- end
149
+ def test_load_balance_sym_concat_rot
150
+ # rubocop:disable Style/MultilineOperationIndentation
151
+ skip('Test not supported on this platform') if n3k_in_n3k_mode? ||
152
+ validate_property_excluded?('portchannel_global', 'symmetry')
153
+ # rubocop:enable Style/MultilineOperationIndentation
168
154
 
169
- def test_get_set_port_channel_load_balance_asym_rot
170
- skip('Platform does not support this property') if n6k_platform? ||
171
- n9k_platform?
172
- @global = create_portchannel_global
173
- @global.send(:port_channel_load_balance=,
174
- 'src-dst', 'ip-vlan', nil, true, nil, nil, 4)
155
+ global = create_portchannel_global
156
+ global.send(:port_channel_load_balance=,
157
+ 'src-dst', 'ip-l4port', nil, nil, true, true, 4)
175
158
  assert_equal('src-dst',
176
- @global.bundle_select)
177
- assert_equal('ip-vlan',
178
- @global.bundle_hash)
179
- assert_equal(true, @global.asymmetric)
180
- assert_equal(4, @global.rotate)
181
- @global.send(
159
+ global.bundle_select)
160
+ assert_equal('ip-l4port',
161
+ global.bundle_hash)
162
+ assert_equal(true, global.symmetry)
163
+ assert_equal(true, global.concatenation)
164
+ assert_equal(4, global.rotate)
165
+ global.send(
182
166
  :port_channel_load_balance=,
183
- @global.default_bundle_select,
184
- @global.default_bundle_hash,
167
+ global.default_bundle_select,
168
+ global.default_bundle_hash,
185
169
  nil,
186
- @global.default_asymmetric,
187
170
  nil,
188
- nil,
189
- @global.default_rotate)
171
+ global.default_symmetry,
172
+ global.default_concatenation,
173
+ global.default_rotate)
174
+ assert_equal(
175
+ global.default_bundle_select,
176
+ global.bundle_select)
190
177
  assert_equal(
191
- @global.default_bundle_select,
192
- @global.bundle_select)
178
+ global.default_bundle_hash,
179
+ global.bundle_hash)
193
180
  assert_equal(
194
- @global.default_bundle_hash,
195
- @global.bundle_hash)
181
+ global.default_symmetry,
182
+ global.symmetry)
196
183
  assert_equal(
197
- @global.default_asymmetric,
198
- @global.asymmetric)
199
- assert_equal(@global.default_rotate,
200
- @global.rotate)
184
+ global.default_concatenation,
185
+ global.concatenation)
186
+ assert_equal(global.default_rotate,
187
+ global.rotate)
188
+ end
189
+
190
+ # assert_hash_poly_crc
191
+ # Depending on the chipset, hash_poly may have have a different
192
+ # default value within the same platform family (this is done to
193
+ # avoid polarization) but there is currently no command available
194
+ # to dynamically determine the default state. As a result the
195
+ # getter simply hard-codes a default value which means it may
196
+ # encounter occasional idempotence issues.
197
+ # For testing purposes this becomes a best-effort test; i.e. we expect the
198
+ # hash_poly test to pass for all asserts except the one that matches the
199
+ # default value for that chipset.
200
+ def assert_hash_poly_crc(exp, actual)
201
+ assert_equal(exp, actual) if exp == actual
202
+ end
203
+
204
+ def test_load_balance_hash_poly
205
+ global = create_portchannel_global
206
+ if validate_property_excluded?('portchannel_global', 'hash_poly')
207
+ skip('Test not supported on this platform')
208
+ return
209
+ end
210
+
211
+ global.send(:port_channel_load_balance=,
212
+ 'src-dst', 'ip-only', 'CRC10c', nil, nil, nil, nil)
213
+ assert_equal('src-dst', global.bundle_select)
214
+ assert_equal('ip-only', global.bundle_hash)
215
+ assert_hash_poly_crc('CRC10c', global.hash_poly)
216
+
217
+ global.send(:port_channel_load_balance=,
218
+ 'dst', 'mac', 'CRC10a', nil, nil, nil, nil)
219
+ assert_equal('dst', global.bundle_select)
220
+ assert_equal('mac', global.bundle_hash)
221
+ assert_hash_poly_crc('CRC10a', global.hash_poly)
222
+
223
+ global.send(:port_channel_load_balance=,
224
+ global.default_bundle_select,
225
+ global.default_bundle_hash,
226
+ 'CRC10b', nil, nil, nil, nil)
227
+ assert_equal(global.default_bundle_select, global.bundle_select)
228
+ assert_equal(global.default_bundle_hash, global.bundle_hash)
229
+ assert_hash_poly_crc('CRC10b', global.hash_poly)
230
+ end
231
+
232
+ def test_load_balance_asym_rot
233
+ global = create_portchannel_global
234
+ if validate_property_excluded?('portchannel_global', 'asymmetric')
235
+ skip('Test not supported on this platform')
236
+ return
237
+ end
238
+
239
+ global.send(:port_channel_load_balance=,
240
+ 'src-dst', 'ip-vlan', nil, true, nil, nil, 4)
241
+ assert_equal('src-dst', global.bundle_select)
242
+ assert_equal('ip-vlan', global.bundle_hash)
243
+ assert_equal(true, global.asymmetric)
244
+ assert_equal(4, global.rotate)
245
+
246
+ global.send(:port_channel_load_balance=,
247
+ global.default_bundle_select,
248
+ global.default_bundle_hash,
249
+ nil, global.default_asymmetric,
250
+ nil, nil, global.default_rotate)
251
+ assert_equal(global.default_bundle_select, global.bundle_select)
252
+ assert_equal(global.default_bundle_hash, global.bundle_hash)
253
+ assert_equal(global.default_asymmetric, global.asymmetric)
254
+ assert_equal(global.default_rotate, global.rotate)
255
+ end
256
+
257
+ def test_load_balance_no_hash_rot
258
+ global = create_portchannel_global
259
+ if validate_property_excluded?('portchannel_global', 'rotate')
260
+ skip('Test not supported on this platform')
261
+ return
262
+ end
263
+ global.send(:port_channel_load_balance=,
264
+ 'src-dst', 'ip-vlan', nil, nil, nil, nil, 4)
265
+ assert_equal('src-dst', global.bundle_select)
266
+ assert_equal('ip-vlan', global.bundle_hash)
267
+ assert_equal(4, global.rotate)
268
+
269
+ global.send(:port_channel_load_balance=,
270
+ global.default_bundle_select,
271
+ global.default_bundle_hash,
272
+ nil, nil,
273
+ nil, nil, global.default_rotate)
274
+ assert_equal(global.default_bundle_select, global.bundle_select)
275
+ assert_equal(global.default_bundle_hash, global.bundle_hash)
276
+ assert_equal(global.default_rotate, global.rotate)
201
277
  end
202
278
  end