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
@@ -15,25 +15,14 @@
15
15
  require_relative 'ciscotest'
16
16
  require_relative '../lib/cisco_node_utils/acl'
17
17
  require_relative '../lib/cisco_node_utils/interface'
18
+ require_relative '../lib/cisco_node_utils/interface_channel_group'
19
+ require_relative '../lib/cisco_node_utils/cisco_cmn_utils'
18
20
  require_relative '../lib/cisco_node_utils/overlay_global'
19
21
 
20
22
  include Cisco
21
23
 
22
24
  # TestInterface - Minitest for general functionality of the Interface class.
23
25
  class TestInterface < CiscoTestCase
24
- # rubocop:disable Style/AlignHash
25
- SWITCHPORT_SHUTDOWN_HASH = {
26
- 'shutdown_ethernet_switchport_shutdown' =>
27
- ['system default switchport', 'system default switchport shutdown'],
28
- 'shutdown_ethernet_switchport_noshutdown' =>
29
- ['system default switchport', 'no system default switchport shutdown'],
30
- 'shutdown_ethernet_noswitchport_shutdown' =>
31
- ['no system default switchport', 'system default switchport shutdown'],
32
- 'shutdown_ethernet_noswitchport_noshutdown' =>
33
- ['no system default switchport', 'no system default switchport shutdown'],
34
- }
35
- # rubocop:enable Style/AlignHash
36
-
37
26
  DEFAULT_IF_ACCESS_VLAN = 1
38
27
  DEFAULT_IF_DESCRIPTION = ''
39
28
  DEFAULT_IF_IP_ADDRESS = nil
@@ -43,32 +32,103 @@ class TestInterface < CiscoTestCase
43
32
  DEFAULT_IF_VRF = ''
44
33
  IF_VRF_MAX_LENGTH = 32
45
34
 
35
+ def setup
36
+ super
37
+ interface_ethernet_default(interfaces[0])
38
+ if platform == :nexus
39
+ @port_channel = 'port-channel'
40
+ # rubocop:disable Style/AlignHash
41
+ @switchport_shutdown_hash = {
42
+ 'shutdown_ethernet_switchport_shutdown' =>
43
+ ['system default switchport',
44
+ 'system default switchport shutdown'],
45
+ 'shutdown_ethernet_switchport_noshutdown' =>
46
+ ['system default switchport',
47
+ 'no system default switchport shutdown'],
48
+ 'shutdown_ethernet_noswitchport_shutdown' =>
49
+ ['no system default switchport',
50
+ 'system default switchport shutdown'],
51
+ 'shutdown_ethernet_noswitchport_noshutdown' =>
52
+ ['no system default switchport',
53
+ 'no system default switchport shutdown'],
54
+ }
55
+ # rubocop:enable Style/AlignHash
56
+ elsif platform == :ios_xr
57
+ @port_channel = 'Bundle-Ether'
58
+ @switchport_shutdown_hash = {
59
+ # Not really applicable to XR
60
+ 'shutdown_ethernet_noswitchport_shutdown' => []
61
+ }
62
+ end
63
+ end
64
+
65
+ def teardown
66
+ interface_ethernet_default(interfaces[0])
67
+ super
68
+ end
69
+
70
+ def ipv4
71
+ if platform == :nexus
72
+ 'ip'
73
+ elsif platform == :ios_xr
74
+ 'ipv4'
75
+ end
76
+ end
77
+
78
+ def ipv4_address_pattern(address, length, secondary=false)
79
+ if platform == :nexus
80
+ if secondary
81
+ %r{^\s+ip address #{address}/#{length} secondary$}
82
+ else
83
+ %r{^\s+ip address #{address}/#{length}$}
84
+ end
85
+ elsif platform == :ios_xr
86
+ mask = Utils.length_to_bitmask(length)
87
+ if secondary
88
+ /^\s+ipv4 address #{address} #{mask} secondary$/
89
+ else
90
+ /^\s+ipv4 address #{address} #{mask}$/
91
+ end
92
+ end
93
+ end
94
+
46
95
  def interface_ipv4_config(ifname, address, length,
47
96
  do_config=true, secip=false)
48
97
  if do_config
98
+ config_no_warn("interface #{ifname}",
99
+ 'no switchport') if platform == :nexus
49
100
  if !secip
50
101
  config("interface #{ifname}",
51
- 'no switchport',
52
- "ip address #{address}/#{length}")
102
+ "#{ipv4} address #{address}/#{length}")
53
103
  else
54
104
  config("interface #{ifname}",
55
- 'no switchport',
56
- "ip address #{address}/#{length} secondary")
105
+ "#{ipv4} address #{address}/#{length} secondary")
57
106
  end
58
107
  else
59
108
  config("interface #{ifname}",
60
- 'no ip address', # This will remove both primary and secondary
61
- 'switchport')
109
+ "no #{ipv4} address", # This will remove both primary and secondary
110
+ )
111
+ config("interface #{ifname}",
112
+ 'switchport') if platform == :nexus
62
113
  end
63
114
  end
64
115
 
65
116
  def show_cmd(name)
66
- all = (name =~ /port-channel\d/ && node.product_id =~ /N7/) ? '' : 'all'
67
- "show run interface #{name} #{all} | no-more"
117
+ if platform == :nexus
118
+ all = (name =~ /port-channel\d/ && node.product_id =~ /N7/) ? '' : 'all'
119
+ "show run interface #{name} #{all} | no-more"
120
+ else
121
+ "show run interface #{name}"
122
+ end
68
123
  end
69
124
 
70
125
  def interface_count
71
- output = @device.cmd('show run interface all | inc interface | no-more')
126
+ if platform == :nexus
127
+ cmd = 'show run interface all | inc interface | no-more'
128
+ elsif platform == :ios_xr
129
+ cmd = 'show run interface | inc interface'
130
+ end
131
+ output = @device.cmd(cmd)
72
132
  # Next line needs to be done because sh run interface all also shows
73
133
  # ospf interface related config
74
134
  arr = output.split("\n").select { |str| str.start_with?('interface') }
@@ -77,15 +137,34 @@ class TestInterface < CiscoTestCase
77
137
  arr.count
78
138
  end
79
139
 
80
- # Helper to check for misc speed change disallowed error messages.
81
- def speed_change_disallowed(message)
82
- patterns = ['port doesn t support this speed',
83
- 'Changing interface speed is not permitted',
84
- 'requested config change not allowed',
85
- /does not match the (transceiver speed|port capability)/]
86
- skip('Skip test: Interface type does not allow config change') if
87
- message[Regexp.union(patterns)]
88
- flunk(message)
140
+ def test_capabilities
141
+ if validate_property_excluded?('interface', 'capabilities')
142
+ assert_empty(Interface.capabilities(interfaces[0]))
143
+ else
144
+ refute_empty(Interface.capabilities(interfaces[0], :hash),
145
+ 'A valid interface should return a non-empty hash')
146
+ assert_empty(Interface.capabilities('foo', :hash),
147
+ 'An Invalid interface should return an empty hash')
148
+
149
+ refute_empty(Interface.capabilities(interfaces[0], :raw),
150
+ 'A valid interface should return a non-empty array')
151
+ assert_empty(Interface.capabilities('foo', :raw),
152
+ 'An Invalid interface should return an empty array')
153
+ end
154
+ end
155
+
156
+ # Helper to get valid speeds for port
157
+ def capable_speed_values(interface)
158
+ speed_capa = Interface.capabilities(interface.name)['Speed']
159
+ return [] if speed_capa.nil?
160
+ speed_capa.split(',')
161
+ end
162
+
163
+ # Helper to get valid duplex values for port
164
+ def capable_duplex_values(interface)
165
+ duplex_capa = Interface.capabilities(interface.name)['Duplex']
166
+ return [] if duplex_capa.nil?
167
+ duplex_capa.split(',')
89
168
  end
90
169
 
91
170
  def create_interface(ifname=interfaces[0])
@@ -93,8 +172,47 @@ class TestInterface < CiscoTestCase
93
172
  Interface.new(ifname)
94
173
  end
95
174
 
96
- def interface_ethernet_default(ethernet_id)
97
- config("default interface ethernet #{ethernet_id}")
175
+ def interface_ethernet_default(ethernet_intf)
176
+ config("default interface #{ethernet_intf}")
177
+ end
178
+
179
+ def interface_supports_property?(intf, message)
180
+ patterns = ['requested config change not allowed',
181
+ '% Invalid command']
182
+ skip("Interface '#{intf}' does not support property") if
183
+ message[Regexp.union(patterns)]
184
+ flunk(message)
185
+ end
186
+
187
+ # Helper to find first valid speed that isn't "auto"
188
+ def valid_speed_set(interface)
189
+ valid_speed = nil
190
+ speeds = capable_speed_values(interface)
191
+ speeds.each do |value|
192
+ next if value == 'auto'
193
+ begin
194
+ interface.speed = value
195
+ assert_equal(value, interface.speed)
196
+ rescue Cisco::CliError => e
197
+ next if speed_change_disallowed?(e.message)
198
+ raise
199
+ end
200
+ # Exit loop once proper speed is found
201
+ valid_speed = value
202
+ break
203
+ end
204
+ valid_speed
205
+ end
206
+
207
+ # Helper to check for misc speed change disallowed error messages.
208
+ def speed_change_disallowed?(message)
209
+ patterns = ['port doesn t support this speed',
210
+ 'Changing interface speed is not permitted',
211
+ 'requested config change not allowed',
212
+ /does not match the (transceiver speed|port capability)/,
213
+ 'but the transceiver doesn t support this speed',
214
+ '% Ambiguous parameter']
215
+ message[Regexp.union(patterns)]
98
216
  end
99
217
 
100
218
  def validate_interfaces_not_empty
@@ -109,6 +227,7 @@ class TestInterface < CiscoTestCase
109
227
 
110
228
  def system_default_switchport_shutdown
111
229
  state = []
230
+ return state if platform == :ios_xr
112
231
  s = @device.cmd("sh run all | in \"system default switchport\"")
113
232
 
114
233
  s.split("\n")[1..-2].each do |line|
@@ -124,7 +243,7 @@ class TestInterface < CiscoTestCase
124
243
  inttype_h.each do |k, v|
125
244
  interface = v[:interface]
126
245
 
127
- SWITCHPORT_SHUTDOWN_HASH.each do |lookup_string, config_array|
246
+ @switchport_shutdown_hash.each do |lookup_string, config_array|
128
247
  # puts "lookup_string: #{lookup_string}"
129
248
 
130
249
  # Configure the system default shwitchport and shutdown settings
@@ -178,7 +297,7 @@ class TestInterface < CiscoTestCase
178
297
  "Error: #{interface.name}, switchport mode, default, " \
179
298
  'not correct')
180
299
  end
181
- rescue RuntimeError => e
300
+ rescue Cisco::CliError => e
182
301
  skip('NX-OS defect: system default switchport nvgens twice') if
183
302
  e.message[/Expected zero.one value/]
184
303
  flunk(e.message)
@@ -228,7 +347,7 @@ class TestInterface < CiscoTestCase
228
347
  address = v[:address_len].split('/').first
229
348
  length = v[:address_len].split('/').last.to_i
230
349
 
231
- pattern = %r{^\s+ip address #{address}/#{length}}
350
+ pattern = ipv4_address_pattern(address, length)
232
351
  assert_show_match(command: show_cmd(interface.name),
233
352
  pattern: pattern)
234
353
  assert_equal(address, interface.ipv4_address,
@@ -248,7 +367,6 @@ class TestInterface < CiscoTestCase
248
367
  # Unconfigure ipaddress
249
368
  interface.ipv4_addr_mask_set(interface.default_ipv4_address,
250
369
  interface.default_ipv4_netmask_length)
251
- pattern = %r{^\s+ip address #{address}/#{length}}
252
370
  refute_show_match(command: show_cmd(interface.name),
253
371
  pattern: pattern,
254
372
  msg: "ipv4 address still present in CLI for #{k}")
@@ -270,7 +388,11 @@ class TestInterface < CiscoTestCase
270
388
  cmd = show_cmd(interface.name)
271
389
 
272
390
  # puts "value - #{v[:proxy_arp]}"
273
- pattern = (/^\s+ip proxy-arp/)
391
+ if platform == :nexus
392
+ pattern = /^\s+ip proxy-arp/
393
+ elsif platform == :ios_xr
394
+ pattern = /^\s+proxy-arp/
395
+ end
274
396
  if v[:proxy_arp]
275
397
  assert_show_match(command: cmd, pattern: pattern)
276
398
  else
@@ -322,15 +444,15 @@ class TestInterface < CiscoTestCase
322
444
  assert_equal(ref.default_value, interface.default_ipv4_redirects,
323
445
  "ipv4 redirects default incorrect for interface #{k}")
324
446
 
325
- if ref.config_set?
447
+ if ref.setter?
326
448
  cmd = show_cmd(interface.name)
327
449
  interface.ipv4_redirects = true
328
450
  assert(interface.ipv4_redirects, "Couldn't set redirects to true")
329
- refute_show_match(command: cmd, pattern: ref.test_config_get_regex[1])
451
+ refute_show_match(command: cmd, pattern: /^\s+no #{ipv4} redirects/)
330
452
 
331
453
  interface.ipv4_redirects = false
332
454
  refute(interface.ipv4_redirects, "Couldn't set redirects to false")
333
- refute_show_match(command: cmd, pattern: ref.test_config_get_regex[0])
455
+ refute_show_match(command: cmd, pattern: /^#{ipv4} redirects/)
334
456
  else
335
457
  # Getter should return same value as default if setter isn't supported
336
458
  assert_equal(interface.ipv4_redirects, interface.default_ipv4_redirects,
@@ -405,38 +527,18 @@ class TestInterface < CiscoTestCase
405
527
  description = 'This is a test description ! '
406
528
  interface.description = description
407
529
  assert_equal(description.rstrip, interface.description)
408
- interface_ethernet_default(interfaces_id[0])
409
530
  end
410
531
 
411
- def test_interface_encapsulation_dot1q_change
532
+ def test_encapsulation_dot1q
412
533
  interface = Interface.new(interfaces[0])
413
- interface.switchport_mode = :disabled
534
+ interface.switchport_mode = :disabled if platform == :nexus
414
535
  subif = Interface.new(interfaces[0] + '.1')
415
-
536
+ assert_raises(Cisco::CliError) { subif.encapsulation_dot1q = 'hello' }
416
537
  subif.encapsulation_dot1q = 20
417
538
  assert_equal(20, subif.encapsulation_dot1q)
418
539
  subif.encapsulation_dot1q = 25
419
540
  assert_equal(25, subif.encapsulation_dot1q)
420
- interface_ethernet_default(interfaces_id[0])
421
- end
422
-
423
- def test_interface_encapsulation_dot1q_invalid
424
- interface = Interface.new(interfaces[0])
425
- interface.switchport_mode = :disabled
426
- subif = Interface.new(interfaces[0] + '.1')
427
-
428
- assert_raises(RuntimeError) { subif.encapsulation_dot1q = 'hello' }
429
- interface_ethernet_default(interfaces_id[0])
430
- end
431
-
432
- def test_interface_encapsulation_dot1q_valid
433
- interface = Interface.new(interfaces[0])
434
- interface.switchport_mode = :disabled
435
- subif = Interface.new(interfaces[0] + '.1')
436
-
437
- subif.encapsulation_dot1q = 20
438
- assert_equal(20, subif.encapsulation_dot1q)
439
- interface_ethernet_default(interfaces_id[0])
541
+ subif.destroy
440
542
  end
441
543
 
442
544
  def test_interface_mtu_change
@@ -446,13 +548,14 @@ class TestInterface < CiscoTestCase
446
548
  assert_equal(1520, interface.mtu)
447
549
  interface.mtu = 1580
448
550
  assert_equal(1580, interface.mtu)
449
- interface_ethernet_default(interfaces_id[0])
551
+ interface.mtu = interface.default_mtu
552
+ assert_equal(interface.default_mtu, interface.mtu)
450
553
  end
451
554
 
452
555
  def test_interface_mtu_invalid
453
556
  interface = Interface.new(interfaces[0])
454
557
  interface.switchport_mode = :disabled
455
- assert_raises(RuntimeError) { interface.mtu = 'hello' }
558
+ assert_raises(Cisco::CliError) { interface.mtu = 'hello' }
456
559
  end
457
560
 
458
561
  def test_interface_mtu_valid
@@ -460,65 +563,83 @@ class TestInterface < CiscoTestCase
460
563
  interface.switchport_mode = :disabled
461
564
  interface.mtu = 1550
462
565
  assert_equal(1550, interface.mtu)
463
- interface_ethernet_default(interfaces_id[0])
566
+ interface.mtu = interface.default_mtu
567
+ assert_equal(interface.default_mtu, interface.mtu)
464
568
  end
465
569
 
466
- def test_interface_speed_change
467
- interface = Interface.new(interfaces[0])
468
- begin
469
- interface.speed = 100
470
- assert_equal('100', interface.speed)
471
- interface.speed = 1000
472
- assert_equal('1000', interface.speed)
473
- interface_ethernet_default(interfaces_id[0])
474
- rescue RuntimeError => e
475
- speed_change_disallowed(e.message)
476
- end
570
+ def test_mtu_invalid_loopback
571
+ # Loopback interfaces don't permit MTU configuration
572
+ interface = Interface.new('loopback100')
573
+ assert_nil(interface.mtu)
574
+ assert_nil(interface.default_mtu)
575
+ assert_raises(Cisco::UnsupportedError) { interface.mtu = 1550 }
576
+ interface.destroy
477
577
  end
478
578
 
479
- def test_interface_speed_invalid
579
+ def test_speed
480
580
  interface = Interface.new(interfaces[0])
481
- assert_raises(RuntimeError) { interface.speed = 'hello' }
482
- end
581
+ if validate_property_excluded?('interface', 'speed')
582
+ assert_nil(interface.speed)
583
+ assert_nil(interface.default_speed)
584
+ assert_raises(Cisco::UnsupportedError) { interface.speed = 1000 }
585
+ return
586
+ end
483
587
 
484
- def test_interface_speed_valid
485
- interface = Interface.new(interfaces[0])
486
- interface.speed = 1000
487
- assert_equal('1000', interface.speed)
488
- interface_ethernet_default(interfaces_id[0])
489
- rescue RuntimeError => e
490
- speed_change_disallowed(e.message)
491
- end
588
+ # Test invalid speed
589
+ assert_raises(RuntimeError, Cisco::CliError) { interface.speed = 'hello' }
590
+
591
+ # Test up to two non-default values
592
+ speed_values = capable_speed_values(interface)
593
+ warn("No valid speeds found on #{interface.name}") if speed_values.empty?
594
+ successful_runs = 0
595
+ speed_values.each do |value|
596
+ break if successful_runs >= 2
597
+ begin
598
+ interface.speed = value
599
+ assert_equal(value, interface.speed)
600
+ successful_runs += 1
601
+ rescue Cisco::CliError => e
602
+ # Many of the 'capable' speeds are actually not valid values
603
+ # Try next available speed value if CLI rejects current value
604
+ next if speed_change_disallowed?(e.message)
605
+ raise
606
+ end
607
+ end
492
608
 
493
- def test_interface_duplex_change
494
- interface = Interface.new(interfaces[0])
495
- interface.speed = 1000
496
- interface.duplex = 'full'
497
- assert_equal('full', interface.duplex)
498
- interface.duplex = 'auto'
499
- assert_equal('auto', interface.duplex)
500
- interface_ethernet_default(interfaces_id[0])
501
- rescue RuntimeError => e
502
- speed_change_disallowed(e.message)
609
+ # Test default speed value
610
+ interface.speed = interface.default_speed
611
+ assert_equal(interface.speed, interface.default_speed)
503
612
  end
504
613
 
505
- def test_interface_duplex_invalid
614
+ def test_duplex
506
615
  interface = Interface.new(interfaces[0])
507
- interface.speed = 1000
508
- assert_raises(RuntimeError) { interface.duplex = 'hello' }
509
- interface_ethernet_default(interfaces_id[0])
510
- rescue RuntimeError => e
511
- speed_change_disallowed(e.message)
512
- end
616
+ if validate_property_excluded?('interface', 'duplex')
617
+ assert_nil(interface.duplex)
618
+ assert_nil(interface.default_duplex)
619
+ assert_raises(Cisco::UnsupportedError) { interface.duplex = 'full' }
620
+ return
621
+ end
513
622
 
514
- def test_interface_duplex_valid
515
- interface = Interface.new(interfaces[0])
516
- interface.speed = 1000
517
- interface.duplex = 'full'
518
- assert_equal('full', interface.duplex)
519
- interface_ethernet_default(interfaces_id[0])
520
- rescue RuntimeError => e
521
- speed_change_disallowed(e.message)
623
+ # Test invalid duplex
624
+ assert_raises(RuntimeError, Cisco::CliError) { interface.duplex = 'hello' }
625
+
626
+ # Ensure speed is non-auto value
627
+ if interface.default_speed == 'auto'
628
+ valid_speed = valid_speed_set(interface)
629
+ skip('Cannot configure non-auto speed') if valid_speed.nil?
630
+ end
631
+
632
+ # Test non-default values
633
+ duplex_values = capable_duplex_values(interface)
634
+ warn("No valid duplex found on #{interface.name}") if duplex_values.empty?
635
+ duplex_values.each do |value|
636
+ interface.duplex = value
637
+ assert_equal(value, interface.duplex)
638
+ end
639
+
640
+ # Test default duplex value
641
+ interface.duplex = interface.default_duplex
642
+ assert_equal(interface.duplex, interface.default_duplex)
522
643
  end
523
644
 
524
645
  def test_interface_shutdown_valid
@@ -528,30 +649,14 @@ class TestInterface < CiscoTestCase
528
649
 
529
650
  interface.shutdown = false
530
651
  refute(interface.shutdown, 'Error: shutdown state is not false')
531
- interface_ethernet_default(interfaces_id[0])
532
- end
533
-
534
- def test_interface_get_access_vlan
535
- interface = Interface.new(interfaces[0])
536
- interface.switchport_mode = :disabled
537
- interface.switchport_mode = :access
538
- assert_equal(DEFAULT_IF_ACCESS_VLAN, interface.access_vlan)
539
- interface_ethernet_default(interfaces_id[0])
540
- end
541
-
542
- def test_interface_get_access_vlan_switchport_disabled
543
- interface = Interface.new(interfaces[0])
544
- interface.switchport_mode = :disabled
545
- assert_equal(DEFAULT_IF_ACCESS_VLAN, interface.access_vlan)
546
- interface_ethernet_default(interfaces_id[0])
547
652
  end
548
653
 
549
- def test_interface_get_access_vlan_switchport_trunk
550
- interface = Interface.new(interfaces[0])
551
- interface.switchport_mode = :disabled
552
- interface.switchport_mode = :trunk
553
- assert_equal(DEFAULT_IF_ACCESS_VLAN, interface.access_vlan)
554
- interface_ethernet_default(interfaces_id[0])
654
+ def test_svi_prop_nil_when_ethernet
655
+ intf = Interface.new(interfaces[0])
656
+ assert_nil(intf.svi_autostate,
657
+ 'Error: svi_autostate should be nil when interface is ethernet')
658
+ assert_nil(intf.svi_management,
659
+ 'Error: svi_management should be nil when interface is ethernet')
555
660
  end
556
661
 
557
662
  # def test_interface_get_prefix_list_when_switchport
@@ -559,13 +664,12 @@ class TestInterface < CiscoTestCase
559
664
  # interface.switchport_mode = :access
560
665
  # addresses = interface.prefixes
561
666
  # assert_empty(addresses)
562
- # interface_ethernet_default(interfaces_id[0])
563
667
  # end
564
668
  #
565
669
  # def test_interface_get_prefix_list_with_ipv4_address_assignment
566
670
  # interface = Interface.new(interfaces[0])
567
671
  # interface.switchport_mode = :access
568
- # interface.switchport_mode = :disabled
672
+ # interface.switchport_mode = :disabled if platform == :nexus
569
673
  # config("interface #{interfaces[0]}",
570
674
  # 'ip address 192.168.1.100 255.255.255.0')
571
675
  # prefixes = interface.prefixes
@@ -573,13 +677,12 @@ class TestInterface < CiscoTestCase
573
677
  # assert(prefixes.has_key?("192.168.1.100"))
574
678
  # interface.switchport_mode = :access
575
679
  # prefixes = nil
576
- # interface_ethernet_default(interfaces_id[0])
577
680
  # end
578
681
  #
579
682
  # def test_interface_get_prefix_list_with_ipv6_address_assignment
580
683
  # interface = Interface.new(interfaces[0] )
581
684
  # interface.switchport_mode = :access
582
- # interface.switchport_mode = :disabled
685
+ # interface.switchport_mode = :disabled if platform == :nexus
583
686
  # config("interface #{interfaces[0]}",
584
687
  # 'ipv6 address fd56:31f7:e4ad:5585::1/64")
585
688
  # prefixes = interface.prefixes
@@ -587,13 +690,12 @@ class TestInterface < CiscoTestCase
587
690
  # assert(prefixes.has_key?("fd56:31f7:e4ad:5585::1"))
588
691
  # interface.switchport_mode = :access
589
692
  # prefixes = nil
590
- # interface_ethernet_default(interfaces_id[0])
591
693
  # end
592
694
  #
593
695
  # def test_interface_prefix_list_with_both_ip4_and_ipv6_address_assignments
594
696
  # interface = Interface.new(interfaces[0])
595
697
  # interface.switchport_mode = :access
596
- # interface.switchport_mode = :disabled
698
+ # interface.switchport_mode = :disabled if platform == :nexus
597
699
  # config("interface #{interfaces[0]}",
598
700
  # 'ip address 192.168.1.100 255.255.255.0',
599
701
  # 'ipv6 address fd56:31f7:e4ad:5585::1/64')
@@ -603,127 +705,131 @@ class TestInterface < CiscoTestCase
603
705
  # assert(prefixes.has_key?("fd56:31f7:e4ad:5585::1"))
604
706
  # interface.switchport_mode = :access
605
707
  # prefixes = nil
606
- # interface_ethernet_default(interfaces_id[0])
607
708
  # end
608
709
 
609
- def negotiate_auto_helper(interface, default, cmd_ref)
710
+ def negotiate_auto_helper(interface, default, speed)
711
+ if validate_property_excluded?('interface',
712
+ interface.negotiate_auto_lookup_string)
713
+ assert_raises(Cisco::UnsupportedError) { interface.negotiate_auto = true }
714
+ return
715
+ end
716
+ # Check current default state before any other changes
610
717
  inf_name = interface.name
611
-
612
- # Test default
613
718
  assert_equal(default, interface.default_negotiate_auto,
614
719
  "Error: #{inf_name} negotiate auto default value mismatch")
615
720
 
616
- interface.negotiate_auto = default
617
- # Delay as this change is sometimes too quick for some interfaces
618
- sleep 1 unless default == interface.negotiate_auto
619
- node.cache_flush
620
- assert_equal(default, interface.negotiate_auto,
621
- "Error: #{inf_name} negotiate auto value " \
622
- 'should be same as default')
623
-
624
- unless cmd_ref.config_set?
625
- # check the set for unsupported platforms
626
- assert_raises(RuntimeError) do
627
- interface.negotiate_auto = true
628
- end
629
- return
721
+ # Test non-defaults: Note that 'speed' and 'negotiate' are tightly coupled
722
+ # on some platforms. Some platforms need the speed command to be toggled
723
+ # before negotiate will work without raising an error; while others just
724
+ # need a non-'auto' speed value or may not support 'auto' at all; therefore
725
+ # just set a static speed value before setting any negotiate settings.
726
+ if default == true
727
+ negotiate_false(interface, speed)
728
+ negotiate_true(interface, speed)
729
+ else
730
+ negotiate_true(interface, speed)
731
+ negotiate_false(interface, speed)
630
732
  end
733
+ end
631
734
 
632
- interface.negotiate_auto = default
633
- assert_equal(default, interface.negotiate_auto,
634
- "Error: #{inf_name} negotiate auto value not #{default}")
635
-
636
- pattern = cmd_ref.test_config_get_regex[default ? 1 : 0]
637
- assert_show_match(pattern: pattern)
638
-
639
- non_default = !default
735
+ def negotiate_true(interface, speed)
736
+ # puts " true: 'speed #{speed}', 'negotiate auto'"
737
+ intf = interface.name
738
+ interface.speed = speed
739
+ interface.negotiate_auto = true
740
+ assert(interface.negotiate_auto,
741
+ "#{intf} negotiate auto value should be true")
742
+ assert_show_match(pattern: /^\s+negotiate auto/)
743
+ rescue Cisco::CliError => e
744
+ # 10G+ interfaces do not support negotiation
745
+ interface_supports_property?(intf, e.message)
746
+ end
747
+
748
+ # Yes, this method is nearly identical to negotiate_true.
749
+ # The negotiate property is evil to troubleshoot. Keep them separate.
750
+ def negotiate_false(interface, speed)
751
+ # puts "false: 'speed #{speed}', 'no negotiate auto'"
752
+ intf = interface.name
753
+ interface.speed = speed
754
+ interface.negotiate_auto = false
755
+ refute(interface.negotiate_auto,
756
+ "#{intf} negotiate auto value should be false")
757
+ assert_show_match(pattern: /^\s+no negotiate auto/)
758
+ rescue Cisco::CliError => e
759
+ # 10G+ interfaces do not support negotiation
760
+ interface_supports_property?(intf, e.message)
761
+ end
640
762
 
641
- # Some 'supported' platforms let us set the negotiate value to its
642
- # default but not actually change it.
763
+ def test_negotiate_auto_portchannel
764
+ # Create interface member of this group (required for XR)
765
+ member = InterfaceChannelGroup.new(interfaces[0])
643
766
  begin
644
- interface.negotiate_auto = non_default
645
- rescue RuntimeError
646
- assert_equal(default, interface.negotiate_auto,
647
- "Error: #{inf_name} negotiate auto value not #{default}")
648
- return
767
+ member.channel_group = 10
768
+ rescue Cisco::UnsupportedError
769
+ # Some XR platform/version combinations don't support port-channel intfs
770
+ skip('bundle id config not supported on this node') if platform == :ios_xr
771
+ raise
649
772
  end
650
773
 
651
- # Delay as this change is sometimes too quick for some interfaces
652
- sleep 1 unless non_default == interface.negotiate_auto
653
- node.cache_flush
654
-
655
- assert_equal(non_default, interface.negotiate_auto,
656
- "Error: #{inf_name} negotiate auto value not #{non_default}")
657
-
658
- pattern = cmd_ref.test_config_get_regex[non_default ? 1 : 0]
659
- assert_show_match(pattern: pattern)
660
-
661
- # Clean up after ourselves
662
- interface.negotiate_auto = default
663
- assert_equal(default, interface.negotiate_auto,
664
- "Error: #{inf_name} negotiate auto value not #{default}")
774
+ # Clean up any stale config first
775
+ inf_name = "#{@port_channel}10"
776
+ Interface.new(inf_name).destroy
665
777
 
666
- pattern = cmd_ref.test_config_get_regex[default ? 1 : 0]
667
- assert_show_match(pattern: pattern)
668
- end
669
-
670
- def test_negotiate_auto_portchannel
671
- ref = cmd_ref.lookup('interface',
672
- 'negotiate_auto_portchannel')
673
- assert(ref, 'Error, reference not found')
674
-
675
- inf_name = 'port-channel10'
676
- config('interface port-channel 10')
677
778
  interface = Interface.new(inf_name)
678
- default = ref.default_value
679
- @default_show_command = show_cmd(inf_name)
779
+ if validate_property_excluded?('interface', 'negotiate_auto_portchannel')
780
+ assert_nil(interface.negotiate_auto)
781
+ assert_nil(interface.default_negotiate_auto)
782
+ assert_raises(Cisco::UnsupportedError) do
783
+ interface.negotiate_auto = false
784
+ end
785
+ else
786
+ default = interface.default_negotiate_auto
787
+ @default_show_command = show_cmd(inf_name)
680
788
 
681
- # Test with switchport
682
- negotiate_auto_helper(interface, default, ref)
789
+ # Port-channels will raise an error on some platforms unless they
790
+ # have a static speed value set first.
791
+ speed = '100'
683
792
 
684
- # Test with no switchport
685
- config('interface port-channel 10', 'no switchport')
686
- negotiate_auto_helper(interface, default, ref)
793
+ # Test with switchport
794
+ interface.switchport_mode = :access
795
+ negotiate_auto_helper(interface, default, speed)
796
+
797
+ # Test with no switchport
798
+ interface.switchport_mode = :disabled
799
+ negotiate_auto_helper(interface, default, speed)
800
+ end
687
801
 
688
802
  # Cleanup
689
- config('no interface port-channel 10')
803
+ interface.destroy
690
804
  end
691
805
 
692
806
  def test_negotiate_auto_ethernet
693
- ref = cmd_ref.lookup('interface',
694
- 'negotiate_auto_ethernet')
695
- assert(ref, 'Error, reference not found')
696
-
697
- # Cleanup
698
- interface_ethernet_default(interfaces_id[0])
699
-
700
- # Some platforms does not support negotiate auto
701
- # if so then we abort the test.
702
-
703
807
  inf_name = interfaces[0]
704
808
  interface = Interface.new(inf_name)
705
809
 
706
- # Some platforms/interfaces/versions do not support negotiation changes
707
- begin
708
- interface.negotiate_auto = false
709
- rescue CliError => e
710
- skip('Skip test: Interface type does not allow config change') if
711
- e.message[/requested config change not allowed/]
712
- flunk(e.message)
810
+ if validate_property_excluded?('interface', 'negotiate_auto_ethernet')
811
+ assert_nil(interface.negotiate_auto)
812
+ assert_nil(interface.default_negotiate_auto)
813
+ assert_raises(Cisco::UnsupportedError) do
814
+ interface.negotiate_auto = false
815
+ end
816
+ return
713
817
  end
714
818
 
715
- default = ref.default_value
819
+ # Find a static speed. Some platforms will raise an error unless
820
+ # speed is configured before setting negotiate auto.
821
+ speed = valid_speed_set(interface)
822
+
823
+ default = interface.default_negotiate_auto
716
824
  @default_show_command = show_cmd(inf_name)
717
825
 
718
826
  # Test with switchport
719
- negotiate_auto_helper(interface, default, ref)
827
+ interface.switchport_mode = :access
828
+ negotiate_auto_helper(interface, default, speed)
720
829
 
721
830
  # Test with no switchport
722
- config("interface #{interfaces[0]}", 'no switchport')
723
- negotiate_auto_helper(interface, default, ref)
724
-
725
- # Cleanup
726
- interface_ethernet_default(interfaces_id[0])
831
+ interface.switchport_mode = :disabled
832
+ negotiate_auto_helper(interface, default, speed)
727
833
  end
728
834
 
729
835
  def test_negotiate_auto_loopback
@@ -731,12 +837,12 @@ class TestInterface < CiscoTestCase
731
837
  'negotiate_auto_other_interfaces')
732
838
  assert(ref, 'Error, reference not found')
733
839
 
734
- inf_name = 'loopback2'
735
- config('interface loopback 2')
736
- interface = Interface.new(inf_name)
840
+ int = 'loopback2'
841
+ config("interface #{int}")
842
+ interface = Interface.new(int)
737
843
 
738
844
  assert_equal(interface.negotiate_auto, ref.default_value,
739
- "Error: #{inf_name} negotiate auto value mismatch")
845
+ "Error: #{int} negotiate auto value mismatch")
740
846
 
741
847
  assert_raises(Cisco::UnsupportedError) do
742
848
  interface.negotiate_auto = true
@@ -746,7 +852,7 @@ class TestInterface < CiscoTestCase
746
852
  end
747
853
 
748
854
  # Cleanup
749
- config('no interface loopback 2')
855
+ config("no interface #{int}")
750
856
  end
751
857
 
752
858
  def test_interfaces_not_empty
@@ -755,20 +861,18 @@ class TestInterface < CiscoTestCase
755
861
 
756
862
  def test_interface_ipv4_addr_mask_set_address_invalid
757
863
  interface = create_interface
758
- interface.switchport_mode = :disabled
759
- assert_raises(RuntimeError) do
864
+ interface.switchport_mode = :disabled if platform == :nexus
865
+ assert_raises(Cisco::CliError) do
760
866
  interface.ipv4_addr_mask_set('', 14)
761
867
  end
762
- interface_ethernet_default(interfaces_id[0])
763
868
  end
764
869
 
765
870
  def test_interface_ipv4_addr_mask_set_netmask_invalid
766
871
  interface = create_interface
767
- interface.switchport_mode = :disabled
768
- assert_raises(RuntimeError) do
872
+ interface.switchport_mode = :disabled if platform == :nexus
873
+ assert_raises(Cisco::CliError) do
769
874
  interface.ipv4_addr_mask_set('8.1.1.2', DEFAULT_IF_IP_NETMASK_LEN)
770
875
  end
771
- interface_ethernet_default(interfaces_id[0])
772
876
  end
773
877
 
774
878
  def test_ipv4_acl
@@ -781,9 +885,13 @@ class TestInterface < CiscoTestCase
781
885
 
782
886
  # create acls first
783
887
  %w(v4acl1 v4acl2 v4acl3 v4acl4).each do |acl_name|
784
- Acl.new('ipv4', acl_name)
888
+ if platform == :nexus
889
+ Acl.new('ipv4', acl_name)
890
+ else
891
+ # TODO: Acl is not yet supported on XR
892
+ config("ipv4 access-list #{acl_name} 1 permit any")
893
+ end
785
894
  end
786
- interface_ethernet_default(interfaces[0])
787
895
  intf = Interface.new(interfaces[0])
788
896
 
789
897
  intf.ipv4_acl_in = 'v4acl1'
@@ -803,7 +911,7 @@ class TestInterface < CiscoTestCase
803
911
 
804
912
  # delete acls
805
913
  %w(v4acl1 v4acl2 v4acl3 v4acl4).each do |acl_name|
806
- config('no ip access-list ' + acl_name)
914
+ config("no #{ipv4} access-list #{acl_name}")
807
915
  end
808
916
  end
809
917
 
@@ -814,12 +922,16 @@ class TestInterface < CiscoTestCase
814
922
  # ipv6 traffic-filter v6acl1 in
815
923
  # ipv6 traffic-filter v6acl2 out
816
924
  #
817
- interface_ethernet_default(interfaces[0])
818
925
  intf = Interface.new(interfaces[0])
819
926
 
820
927
  # create acls first
821
928
  %w(v6acl1 v6acl2 v6acl3 v6acl4).each do |acl_name|
822
- Acl.new('ipv6', acl_name)
929
+ if platform == :nexus
930
+ Acl.new('ipv6', acl_name)
931
+ else
932
+ # TODO: Acl is not yet supported on XR
933
+ config("ipv6 access-list #{acl_name} 1 permit any any")
934
+ end
823
935
  end
824
936
 
825
937
  intf.ipv6_acl_in = 'v6acl1'
@@ -845,7 +957,7 @@ class TestInterface < CiscoTestCase
845
957
 
846
958
  def test_interface_ipv4_address
847
959
  interface = create_interface
848
- interface.switchport_mode = :disabled
960
+ interface.switchport_mode = :disabled if platform == :nexus
849
961
  address = '8.7.1.1'
850
962
  sec_addr = '10.5.5.1'
851
963
  secondary = true
@@ -853,7 +965,7 @@ class TestInterface < CiscoTestCase
853
965
 
854
966
  # Primary: setter, getter
855
967
  interface.ipv4_addr_mask_set(address, length)
856
- pattern = %r{^\s+ip address #{address}/#{length}}
968
+ pattern = ipv4_address_pattern(address, length)
857
969
  assert_show_match(pattern: pattern,
858
970
  msg: 'Error: ipv4 address missing in CLI')
859
971
  assert_equal(address, interface.ipv4_address,
@@ -863,12 +975,12 @@ class TestInterface < CiscoTestCase
863
975
 
864
976
  # Secondary: setter, getter
865
977
  interface.ipv4_addr_mask_set(sec_addr, length, secondary)
866
- pattern = %r{^\s+ip address #{sec_addr}/#{length} secondary}
978
+ pattern = ipv4_address_pattern(sec_addr, length, secondary)
867
979
  assert_show_match(pattern: pattern,
868
980
  msg: 'Error: ipv4 address missing in CLI')
869
981
  assert_equal(sec_addr, interface.ipv4_address_secondary,
870
982
  'Error: ipv4 address get value mismatch')
871
- assert_equal(length, interface.ipv4_netmask_length,
983
+ assert_equal(length, interface.ipv4_netmask_length_secondary,
872
984
  'Error: ipv4 netmask length get value mismatch')
873
985
 
874
986
  # get default
@@ -888,7 +1000,7 @@ class TestInterface < CiscoTestCase
888
1000
  interface.ipv4_addr_mask_set(interface.default_ipv4_address, length,
889
1001
  secondary)
890
1002
  interface.ipv4_addr_mask_set(interface.default_ipv4_address, length)
891
- pattern = (/^\s+ip address (.*)/)
1003
+ pattern = (/^\s+ip(v4)? address (.*)/)
892
1004
  refute_show_match(pattern: pattern,
893
1005
  msg: 'Error: ipv4 address still present in CLI')
894
1006
  assert_equal(DEFAULT_IF_IP_ADDRESS, interface.ipv4_address,
@@ -896,8 +1008,6 @@ class TestInterface < CiscoTestCase
896
1008
  assert_equal(DEFAULT_IF_IP_NETMASK_LEN,
897
1009
  interface.ipv4_netmask_length,
898
1010
  'Error: ipv4 netmask length default get value mismatch')
899
-
900
- interface_ethernet_default(interfaces_id[0])
901
1011
  end
902
1012
 
903
1013
  def test_interface_ipv4_address_getter_with_preconfig
@@ -915,7 +1025,6 @@ class TestInterface < CiscoTestCase
915
1025
  'Error: ipv4 netmask length get value mismatch')
916
1026
  # unconfigure ipaddress
917
1027
  interface_ipv4_config(ifname, address, length, false)
918
- interface_ethernet_default(interfaces_id[0])
919
1028
  end
920
1029
 
921
1030
  def test_interface_ipv4_address_getter_with_preconfig_secondary
@@ -937,31 +1046,81 @@ class TestInterface < CiscoTestCase
937
1046
  'Error: ipv4 netmask length get value mismatch')
938
1047
  # unconfigure ipaddress includign secondary
939
1048
  interface_ipv4_config(ifname, address, length, false, false)
940
- interface_ethernet_default(interfaces_id[0])
941
1049
  end
942
1050
 
943
1051
  def test_interface_ipv4_arp_timeout
944
- # Setup
945
- config('no interface vlan11')
946
- int = Interface.new('vlan11')
947
-
948
- # Test default
949
- assert_equal(int.default_ipv4_arp_timeout, int.ipv4_arp_timeout)
950
- # Test non-default
951
- int.ipv4_arp_timeout = 300
952
- assert_equal(300, int.ipv4_arp_timeout)
953
- # Set back to default
954
- int.ipv4_arp_timeout = int.default_ipv4_arp_timeout
955
- assert_equal(int.default_ipv4_arp_timeout, int.ipv4_arp_timeout)
956
-
1052
+ unless platform == :ios_xr
1053
+ # Setup
1054
+ config_no_warn('no interface vlan11')
1055
+ int = Interface.new('vlan11')
1056
+
1057
+ # Test default
1058
+ assert_equal(int.default_ipv4_arp_timeout, int.ipv4_arp_timeout)
1059
+ # Test non-default
1060
+ int.ipv4_arp_timeout = 300
1061
+ assert_equal(300, int.ipv4_arp_timeout)
1062
+ # Set back to default
1063
+ int.ipv4_arp_timeout = int.default_ipv4_arp_timeout
1064
+ assert_equal(int.default_ipv4_arp_timeout, int.ipv4_arp_timeout)
1065
+ end
957
1066
  # Attempt to configure on a non-vlan interface
958
1067
  nonvlanint = create_interface
959
1068
  assert_raises(RuntimeError) { nonvlanint.ipv4_arp_timeout = 300 }
960
1069
  end
961
1070
 
1071
+ def test_interface_ipv4_forwarding
1072
+ intf = interfaces[0]
1073
+ i = Interface.new(intf)
1074
+
1075
+ if platform == :ios_xr
1076
+ assert_nil(i.default_ipv4_forwarding)
1077
+ assert_nil(i.ipv4_forwarding)
1078
+ assert_raises(Cisco::UnsupportedError) { i.ipv4_forwarding = false }
1079
+ return
1080
+ end
1081
+
1082
+ assert_equal(i.default_ipv4_forwarding, i.ipv4_forwarding)
1083
+ begin
1084
+ i.switchport_mode = :disabled
1085
+ i.ipv4_forwarding = true
1086
+ rescue RuntimeError, CliError => e
1087
+ # RuntimeError when switchport_mode fails (some lc's, e.g. N7K-F248XP-25E)
1088
+ # CliError when ipv4_forwarding fails
1089
+ interface_supports_property?(intf, e.message)
1090
+ end
1091
+ assert(i.ipv4_forwarding)
1092
+
1093
+ i.ipv4_forwarding = false
1094
+ refute(i.ipv4_forwarding)
1095
+
1096
+ i.ipv4_forwarding = true
1097
+ assert(i.ipv4_forwarding)
1098
+ i.ipv4_forwarding = i.default_ipv4_forwarding
1099
+ assert_equal(i.default_ipv4_forwarding, i.ipv4_forwarding)
1100
+ end
1101
+
962
1102
  def test_interface_fabric_forwarding_anycast_gateway
1103
+ # Ensure N7k has compatible interface
1104
+ mt_full_interface? if node.product_id[/N7/]
1105
+
1106
+ if validate_property_excluded?('overlay_global', 'anycast_gateway_mac')
1107
+ assert_raises(Cisco::UnsupportedError) do
1108
+ OverlayGlobal.new.anycast_gateway_mac = '1223.3445.5668'
1109
+ end
1110
+ return
1111
+ end
1112
+ if validate_property_excluded?('interface',
1113
+ 'fabric_forwarding_anycast_gateway')
1114
+ int = Interface.new('vlan11')
1115
+ OverlayGlobal.new.anycast_gateway_mac = '1223.3445.5668'
1116
+ assert_raises(Cisco::UnsupportedError) do
1117
+ int.fabric_forwarding_anycast_gateway = true
1118
+ end
1119
+ return
1120
+ end
1121
+
963
1122
  # Setup
964
- config('no interface vlan11')
1123
+ config_no_warn('no interface vlan11')
965
1124
  int = Interface.new('vlan11')
966
1125
  foo = OverlayGlobal.new
967
1126
  foo.anycast_gateway_mac = '1223.3445.5668'
@@ -986,17 +1145,26 @@ class TestInterface < CiscoTestCase
986
1145
 
987
1146
  # 5. Attempt to set 'fabric forwarding anycast gateway' while the
988
1147
  # overlay gateway mac is not set.
989
- foo.anycast_gateway_mac = foo.default_anycast_gateway_mac
990
- assert_raises(RuntimeError) { int.fabric_forwarding_anycast_gateway = true }
1148
+ int.destroy
1149
+ int = Interface.new('vlan11')
1150
+ bar = OverlayGlobal.new
1151
+ bar.anycast_gateway_mac = bar.default_anycast_gateway_mac
1152
+ assert_raises(RuntimeError) do
1153
+ int.fabric_forwarding_anycast_gateway = true
1154
+ end
991
1155
  end
992
1156
 
993
1157
  def test_interface_ipv4_proxy_arp
994
1158
  interface = create_interface
995
- interface.switchport_mode = :disabled
1159
+ interface.switchport_mode = :disabled if platform == :nexus
996
1160
 
997
1161
  # set with value true
998
1162
  interface.ipv4_proxy_arp = true
999
- pattern = (/^\s+ip proxy-arp/)
1163
+ if platform == :nexus
1164
+ pattern = /^\s+ip proxy-arp/
1165
+ elsif platform == :ios_xr
1166
+ pattern = /^\s+proxy-arp/
1167
+ end
1000
1168
  assert_show_match(pattern: pattern,
1001
1169
  msg: 'Error: ip proxy-arp enable missing in CLI')
1002
1170
  assert(interface.ipv4_proxy_arp,
@@ -1021,59 +1189,68 @@ class TestInterface < CiscoTestCase
1021
1189
  assert_equal(DEFAULT_IF_IP_PROXY_ARP,
1022
1190
  interface.ipv4_proxy_arp,
1023
1191
  'Error: ip proxy-arp default get value mismatch')
1024
-
1025
- interface_ethernet_default(interfaces_id[0])
1026
1192
  end
1027
1193
 
1028
1194
  def test_interface_ipv4_redirects
1029
1195
  interface = create_interface
1030
- interface.switchport_mode = :disabled
1196
+ interface.switchport_mode = :disabled if platform == :nexus
1197
+
1198
+ ref = cmd_ref.lookup('interface', 'ipv4_redirects_other_interfaces')
1199
+ assert(ref, 'Error, reference not found')
1200
+
1201
+ # check default value
1202
+ assert_equal(interface.default_ipv4_redirects, interface.ipv4_redirects,
1203
+ 'Error: ip redirects default get value mismatch')
1031
1204
 
1032
1205
  # set with value false
1033
1206
  interface.ipv4_redirects = false
1034
- pattern = (/^\s+no ip redirects/)
1035
- assert_show_match(pattern: pattern,
1036
- msg: 'Error: ip redirects disable missing in CLI')
1207
+ if interface.default_ipv4_redirects == true
1208
+ assert_show_match(pattern: /^\s+no #{ipv4} redirects/,
1209
+ msg: 'Error: ip redirects disable missing in CLI')
1210
+ end
1211
+ refute_show_match(pattern: /^\s+#{ipv4} redirects/)
1037
1212
  refute(interface.ipv4_redirects,
1038
1213
  "Error: ip redirects get value 'false' mismatch")
1039
1214
 
1040
1215
  # set with value true
1041
1216
  interface.ipv4_redirects = true
1042
- refute_show_match(pattern: pattern,
1217
+ if interface.default_ipv4_redirects == false
1218
+ assert_show_match(pattern: /^\s+#{ipv4} redirects/)
1219
+ end
1220
+ refute_show_match(pattern: /^\s+no #{ipv4} redirects/,
1043
1221
  msg: 'Error: ip redirects enable missing in CLI')
1044
1222
  assert(interface.ipv4_redirects,
1045
1223
  "Error: ip redirects get value 'true' mismatch")
1046
1224
 
1047
- # get default
1048
- assert_equal(DEFAULT_IF_IP_REDIRECTS,
1049
- interface.default_ipv4_redirects,
1050
- 'Error: ip redirects get default value mismatch')
1051
-
1052
1225
  # get default and set
1053
1226
  interface.ipv4_redirects = interface.default_ipv4_redirects
1054
- refute_show_match(pattern: pattern,
1227
+ if interface.default_ipv4_redirects
1228
+ pat = /^\s+no #{ipv4} redirects/
1229
+ else
1230
+ pat = /^\s+#{ipv4} redirects/
1231
+ end
1232
+ refute_show_match(pattern: pat,
1055
1233
  msg: 'Error: default ip redirects set failed')
1056
- assert_equal(DEFAULT_IF_IP_REDIRECTS, interface.ipv4_redirects,
1234
+ assert_equal(interface.default_ipv4_redirects, interface.ipv4_redirects,
1057
1235
  'Error: ip redirects default get value mismatch')
1058
-
1059
- interface_ethernet_default(interfaces_id[0])
1060
1236
  end
1061
1237
 
1062
1238
  def config_from_hash(inttype_h)
1063
1239
  inttype_h.each do |k, v|
1064
- # puts "TEST: pre-config hash key : #{k}"
1065
1240
  config('feature interface-vlan') if (/^Vlan\d./).match(k.to_s)
1066
1241
 
1067
- # puts "TEST: pre-config k: v '#{k} : #{v}'"
1068
1242
  cfg = ["interface #{k}"]
1069
- if !(/^Ethernet\d.\d/).match(k.to_s).nil? ||
1070
- !(/^port-channel\d/).match(k.to_s).nil?
1071
- cfg << 'no switchport'
1243
+
1244
+ switchport_intfs = Regexp.union(/ethernet/i, @port_channel)
1245
+ cfg << 'no switchport' if platform == :nexus && k =~ switchport_intfs
1246
+
1247
+ cfg << "#{ipv4} address #{v[:address_len]}" unless v[:address_len].nil?
1248
+ if platform == :nexus
1249
+ cfg << 'ip proxy-arp' if v[:proxy_arp]
1250
+ elsif platform == :ios_xr
1251
+ cfg << 'proxy-arp' if v[:proxy_arp]
1072
1252
  end
1073
- # puts "k: #{k}, k1: #{k1}, address #{v1[:address_len]}"
1074
- cfg << "ip address #{v[:address_len]}" unless v[:address_len].nil?
1075
- cfg << 'ip proxy-arp' if v[:proxy_arp]
1076
- cfg << 'ip redirects' if v[:redirects]
1253
+ cfg << '#{ipv4} redirects' if v[:redirects]
1077
1254
  cfg << "description #{v[:description]}" unless v[:description].nil?
1078
1255
  config(*cfg)
1079
1256
 
@@ -1083,9 +1260,7 @@ class TestInterface < CiscoTestCase
1083
1260
  inttype_h
1084
1261
  end
1085
1262
 
1086
- # NOTE - Changes to this method may require new validation methods
1087
- # to be created or existing ones to be modified.
1088
- def test_interface_ipv4_all_interfaces
1263
+ def interface_test_data
1089
1264
  inttype_h = {}
1090
1265
  inttype_h[interfaces[0]] = {
1091
1266
  address_len: '8.7.1.1/15',
@@ -1097,31 +1272,33 @@ class TestInterface < CiscoTestCase
1097
1272
  shutdown: false,
1098
1273
  change_shutdown: true,
1099
1274
  default_shutdown: false,
1100
- switchport: :disabled,
1101
- default_switchport: :disabled,
1102
- access_vlan: DEFAULT_IF_ACCESS_VLAN,
1103
- default_access_vlan: DEFAULT_IF_ACCESS_VLAN,
1104
- vrf_new: 'test2',
1105
- default_vrf: DEFAULT_IF_VRF,
1106
- }
1107
- inttype_h['Vlan45'] = {
1108
- address_len: '9.7.1.1/15',
1109
- proxy_arp: true,
1110
- redirects: false,
1111
- description: 'Company A',
1112
- description_new: 'Mini Me',
1113
- default_description: DEFAULT_IF_DESCRIPTION,
1114
- shutdown: true,
1115
- change_shutdown: false,
1116
- default_shutdown: true,
1117
- switchport: :disabled,
1118
- default_switchport: :disabled,
1275
+ switchport: platform == :ios_xr ? nil : :disabled,
1276
+ default_switchport: platform == :ios_xr ? nil : :disabled,
1119
1277
  access_vlan: DEFAULT_IF_ACCESS_VLAN,
1120
1278
  default_access_vlan: DEFAULT_IF_ACCESS_VLAN,
1121
1279
  vrf_new: 'test2',
1122
1280
  default_vrf: DEFAULT_IF_VRF,
1123
1281
  }
1124
- inttype_h['port-channel48'] = {
1282
+ unless platform == :ios_xr
1283
+ inttype_h['Vlan45'] = {
1284
+ address_len: '9.7.1.1/15',
1285
+ proxy_arp: true,
1286
+ redirects: false,
1287
+ description: 'Company A',
1288
+ description_new: 'Mini Me',
1289
+ default_description: DEFAULT_IF_DESCRIPTION,
1290
+ shutdown: true,
1291
+ change_shutdown: false,
1292
+ default_shutdown: true,
1293
+ switchport: :disabled,
1294
+ default_switchport: :disabled,
1295
+ access_vlan: DEFAULT_IF_ACCESS_VLAN,
1296
+ default_access_vlan: DEFAULT_IF_ACCESS_VLAN,
1297
+ vrf_new: 'test2',
1298
+ default_vrf: DEFAULT_IF_VRF,
1299
+ }
1300
+ end
1301
+ inttype_h["#{@port_channel}48"] = {
1125
1302
  address_len: '10.7.1.1/15',
1126
1303
  proxy_arp: false,
1127
1304
  redirects: false,
@@ -1131,8 +1308,8 @@ class TestInterface < CiscoTestCase
1131
1308
  shutdown: false,
1132
1309
  change_shutdown: true,
1133
1310
  default_shutdown: false,
1134
- switchport: :disabled,
1135
- default_switchport: :disabled,
1311
+ switchport: platform == :ios_xr ? nil : :disabled,
1312
+ default_switchport: platform == :ios_xr ? nil : :disabled,
1136
1313
  access_vlan: DEFAULT_IF_ACCESS_VLAN,
1137
1314
  default_access_vlan: DEFAULT_IF_ACCESS_VLAN,
1138
1315
  vrf_new: 'test2',
@@ -1147,8 +1324,8 @@ class TestInterface < CiscoTestCase
1147
1324
  shutdown: false,
1148
1325
  change_shutdown: true,
1149
1326
  default_shutdown: false,
1150
- switchport: :disabled,
1151
- default_switchport: :disabled,
1327
+ switchport: platform == :ios_xr ? nil : :disabled,
1328
+ default_switchport: platform == :ios_xr ? nil : :disabled,
1152
1329
  access_vlan: DEFAULT_IF_ACCESS_VLAN,
1153
1330
  default_access_vlan: DEFAULT_IF_ACCESS_VLAN,
1154
1331
  vrf_new: 'test2',
@@ -1156,52 +1333,71 @@ class TestInterface < CiscoTestCase
1156
1333
  }
1157
1334
  # Skipping mgmt0 interface since that interface is our 'path' to
1158
1335
  # master should revisit this later
1336
+ inttype_h
1337
+ end
1338
+
1339
+ # NOTE - Changes to this method may require new validation methods
1340
+ # to be created or existing ones to be modified.
1341
+ def test_interface_ipv4_all_interfaces
1342
+ inttype_h = interface_test_data
1159
1343
 
1160
1344
  # Set system defaults to "factory" values prior to initial test.
1161
1345
  config(*
1162
- SWITCHPORT_SHUTDOWN_HASH['shutdown_ethernet_noswitchport_shutdown'])
1346
+ @switchport_shutdown_hash['shutdown_ethernet_noswitchport_shutdown'])
1163
1347
 
1164
1348
  # pre-configure
1349
+ begin
1350
+ interface_ethernet_default(interfaces[1])
1351
+ InterfaceChannelGroup.new(interfaces[1]).channel_group = 48
1352
+ rescue Cisco::UnsupportedError
1353
+ raise unless platform == :ios_xr
1354
+ # Some XR platform/version combos don't support port-channels
1355
+ inttype_h.delete("#{@port_channel}48")
1356
+ end
1357
+
1165
1358
  inttype_h = config_from_hash(inttype_h)
1166
1359
 
1167
1360
  # Steps to cleanup the preload configuration
1168
1361
  cfg = []
1169
1362
  inttype_h.each_key do |k|
1170
- cfg << "#{/^Ethernet/.match(k) ? 'default' : 'no'} interface #{k}"
1363
+ if /ethernet/.match(k)
1364
+ # leave interface there, but unconfigure it
1365
+ cfg.push(*get_interface_cleanup_config(k))
1366
+ else
1367
+ # remove interface
1368
+ cfg << "no interface #{k}"
1369
+ end
1171
1370
  end
1172
- cfg << 'no feature interface-vlan'
1371
+ cfg << 'no feature interface-vlan' unless platform == :ios_xr
1173
1372
 
1174
1373
  begin
1175
1374
  # Validate the collection
1176
1375
  validate_interfaces_not_empty
1177
1376
  validate_get_switchport(inttype_h)
1178
1377
  validate_description(inttype_h)
1179
- validate_get_access_vlan(inttype_h)
1378
+ validate_get_access_vlan(inttype_h) unless platform == :ios_xr
1180
1379
  validate_ipv4_address(inttype_h)
1181
1380
  validate_ipv4_proxy_arp(inttype_h)
1182
1381
  validate_ipv4_redirects(inttype_h)
1183
1382
  validate_interface_shutdown(inttype_h)
1184
1383
  validate_vrf(inttype_h)
1185
1384
  config(*cfg)
1385
+ interface_ethernet_default(interfaces[1])
1186
1386
  rescue Minitest::Assertion
1187
1387
  # clean up before failing
1188
1388
  config(*cfg)
1389
+ interface_ethernet_default(interfaces[1])
1189
1390
  raise
1190
1391
  end
1191
1392
  end
1192
1393
 
1193
1394
  def test_interface_vrf_default
1194
- config('interface loopback1', 'vrf member foo')
1195
1395
  interface = Interface.new('loopback1')
1396
+ assert_empty(interface.vrf)
1397
+ interface.vrf = 'foo'
1398
+ assert_equal(interface.vrf, 'foo')
1196
1399
  interface.vrf = interface.default_vrf
1197
- assert_equal(DEFAULT_IF_VRF, interface.vrf)
1198
- end
1199
-
1200
- def test_interface_vrf_empty
1201
- config('interface loopback1', 'vrf member foo')
1202
- interface = Interface.new('loopback1')
1203
- interface.vrf = DEFAULT_IF_VRF
1204
- assert_equal(DEFAULT_IF_VRF, interface.vrf)
1400
+ assert_equal(interface.vrf, interface.default_vrf)
1205
1401
  end
1206
1402
 
1207
1403
  def test_interface_vrf_invalid_type
@@ -1212,7 +1408,7 @@ class TestInterface < CiscoTestCase
1212
1408
  def test_interface_vrf_exceeds_max_length
1213
1409
  interface = Interface.new('loopback1')
1214
1410
  long_string = 'a' * (IF_VRF_MAX_LENGTH + 1)
1215
- assert_raises(RuntimeError) { interface.vrf = long_string }
1411
+ assert_raises(Cisco::CliError) { interface.vrf = long_string }
1216
1412
  end
1217
1413
 
1218
1414
  def test_interface_vrf_override
@@ -1233,14 +1429,59 @@ class TestInterface < CiscoTestCase
1233
1429
  interface.destroy
1234
1430
  end
1235
1431
 
1432
+ def test_vrf_change_with_ip_addr
1433
+ interface = Interface.new('loopback1')
1434
+ address = '192.168.100.1'
1435
+ length = 24
1436
+ interface_ipv4_config('loopback1', address, length)
1437
+ assert_equal(address, interface.ipv4_address)
1438
+ assert_equal(length, interface.ipv4_netmask_length)
1439
+
1440
+ vrf1 = 'test1'
1441
+ interface.vrf = vrf1
1442
+ assert_equal(address, interface.ipv4_address,
1443
+ 'IPv4 address wrong after changing from vrf default => test1')
1444
+ assert_equal(length, interface.ipv4_netmask_length,
1445
+ 'IPv4 mask wrong after changing from vrf default => test1')
1446
+ assert_equal(vrf1, interface.vrf)
1447
+
1448
+ vrf2 = 'test2'
1449
+ interface.vrf = vrf2
1450
+ assert_equal(address, interface.ipv4_address,
1451
+ 'IPv4 address wrong after changing from vrf test1 => test2')
1452
+ assert_equal(length, interface.ipv4_netmask_length,
1453
+ 'IPv4 mask wrong after changing from vrf test1 => test2')
1454
+ assert_equal(vrf2, interface.vrf)
1455
+
1456
+ interface.vrf = DEFAULT_IF_VRF
1457
+ assert_equal(address, interface.ipv4_address,
1458
+ 'IPv4 address wrong after changing from vrf test2 => default')
1459
+ assert_equal(length, interface.ipv4_netmask_length,
1460
+ 'IPv4 mask wrong after changing from vrf test2 => default')
1461
+ assert_equal(DEFAULT_IF_VRF, interface.vrf)
1462
+ end
1463
+
1236
1464
  def test_ipv4_pim_sparse_mode
1465
+ config('no feature pim') if platform == :nexus
1466
+ i = Interface.new(interfaces[0])
1467
+ if platform == :ios_xr
1468
+ assert_nil(i.ipv4_pim_sparse_mode)
1469
+ assert_nil(i.default_ipv4_pim_sparse_mode)
1470
+ assert_raises(Cisco::UnsupportedError) { i.ipv4_pim_sparse_mode = true }
1471
+ return
1472
+ end
1473
+ begin
1474
+ i.switchport_mode = :disabled
1475
+ rescue Cisco::CliError => e
1476
+ skip_message = 'Interface does not support switchport disable'
1477
+ skip(skip_message) if e.message['requested config change not allowed']
1478
+ raise
1479
+ end
1237
1480
  # Sample cli:
1238
1481
  #
1239
1482
  # interface Ethernet1/1
1240
1483
  # ip pim sparse-mode
1241
1484
  #
1242
- config('no feature pim')
1243
- i = Interface.new(interfaces[0])
1244
1485
  i.ipv4_pim_sparse_mode = false
1245
1486
  refute(i.ipv4_pim_sparse_mode)
1246
1487