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
@@ -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