cisco_node_utils 1.2.0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
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