cisco_node_utils_mgx 2.1.0.1

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 (357) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/.rspec +2 -0
  4. data/.rubocop.yml +96 -0
  5. data/.travis.yml +17 -0
  6. data/CHANGELOG.md +676 -0
  7. data/CONTRIBUTING.md +43 -0
  8. data/Gemfile +10 -0
  9. data/LICENSE +201 -0
  10. data/README.md +246 -0
  11. data/Rakefile +44 -0
  12. data/SUPPORT.md +3 -0
  13. data/bin/.rubocop.yml +18 -0
  14. data/bin/check_metric_limits.rb +109 -0
  15. data/bin/git/hooks/commit-msg/enforce_style +89 -0
  16. data/bin/git/hooks/hook_lib +115 -0
  17. data/bin/git/hooks/hooks-wrapper +38 -0
  18. data/bin/git/hooks/post-flow-hotfix-start/update-version +24 -0
  19. data/bin/git/hooks/post-flow-release-finish/update-version +29 -0
  20. data/bin/git/hooks/post-flow-release-start/update-version +19 -0
  21. data/bin/git/hooks/post-merge/update-hooks +6 -0
  22. data/bin/git/hooks/post-rewrite/update-hooks +6 -0
  23. data/bin/git/hooks/pre-commit/check_unstaged_changes +18 -0
  24. data/bin/git/hooks/pre-commit/rubocop +25 -0
  25. data/bin/git/hooks/pre-commit/validate-diffs +45 -0
  26. data/bin/git/hooks/pre-commit/validate-yaml +18 -0
  27. data/bin/git/hooks/pre-push/check-changelog +24 -0
  28. data/bin/git/hooks/pre-push/rubocop +7 -0
  29. data/bin/git/update-hooks +123 -0
  30. data/bin/show_running_yang.rb +233 -0
  31. data/cisco_node_utils.gemspec +41 -0
  32. data/docs/README-develop-best-practices.md +521 -0
  33. data/docs/README-develop-node-utils-APIs.md +570 -0
  34. data/docs/README-maintainers.md +77 -0
  35. data/docs/README-test-execution.md +57 -0
  36. data/docs/README-utilities.md +14 -0
  37. data/docs/agent_files.png +0 -0
  38. data/docs/cisco_node_utils.yaml.example +36 -0
  39. data/docs/template-router.rb +123 -0
  40. data/docs/template-test_router.rb +104 -0
  41. data/ext/mkrf_conf.rb +63 -0
  42. data/lib/.rubocop.yml +18 -0
  43. data/lib/cisco_node_utils/aaa_authentication_login.rb +95 -0
  44. data/lib/cisco_node_utils/aaa_authentication_login_service.rb +138 -0
  45. data/lib/cisco_node_utils/aaa_authorization_service.rb +156 -0
  46. data/lib/cisco_node_utils/ace.rb +467 -0
  47. data/lib/cisco_node_utils/acl.rb +101 -0
  48. data/lib/cisco_node_utils/banner.rb +63 -0
  49. data/lib/cisco_node_utils/bfd_global.rb +305 -0
  50. data/lib/cisco_node_utils/bgp.rb +988 -0
  51. data/lib/cisco_node_utils/bgp_af.rb +545 -0
  52. data/lib/cisco_node_utils/bgp_af_aggr_addr.rb +207 -0
  53. data/lib/cisco_node_utils/bgp_neighbor.rb +527 -0
  54. data/lib/cisco_node_utils/bgp_neighbor_af.rb +780 -0
  55. data/lib/cisco_node_utils/bridge_domain.rb +178 -0
  56. data/lib/cisco_node_utils/bridge_domain_vni.rb +206 -0
  57. data/lib/cisco_node_utils/cisco_cmn_utils.rb +444 -0
  58. data/lib/cisco_node_utils/client/client.rb +238 -0
  59. data/lib/cisco_node_utils/client/grpc/client.rb +395 -0
  60. data/lib/cisco_node_utils/client/grpc/ems.proto +148 -0
  61. data/lib/cisco_node_utils/client/grpc/ems.rb +111 -0
  62. data/lib/cisco_node_utils/client/grpc/ems_services.rb +49 -0
  63. data/lib/cisco_node_utils/client/grpc.rb +33 -0
  64. data/lib/cisco_node_utils/client/nxapi/client.rb +368 -0
  65. data/lib/cisco_node_utils/client/nxapi.rb +31 -0
  66. data/lib/cisco_node_utils/client/utils.rb +180 -0
  67. data/lib/cisco_node_utils/client.rb +35 -0
  68. data/lib/cisco_node_utils/cmd_ref/README_YAML.md +590 -0
  69. data/lib/cisco_node_utils/cmd_ref/aaa_auth_login_service.yaml +25 -0
  70. data/lib/cisco_node_utils/cmd_ref/aaa_authentication_login.yaml +38 -0
  71. data/lib/cisco_node_utils/cmd_ref/aaa_authorization_service.yaml +40 -0
  72. data/lib/cisco_node_utils/cmd_ref/acl.yaml +48 -0
  73. data/lib/cisco_node_utils/cmd_ref/banner.yaml +11 -0
  74. data/lib/cisco_node_utils/cmd_ref/bfd_global.yaml +117 -0
  75. data/lib/cisco_node_utils/cmd_ref/bgp.yaml +383 -0
  76. data/lib/cisco_node_utils/cmd_ref/bgp_af.yaml +223 -0
  77. data/lib/cisco_node_utils/cmd_ref/bgp_af_aa.yaml +38 -0
  78. data/lib/cisco_node_utils/cmd_ref/bgp_neighbor.yaml +174 -0
  79. data/lib/cisco_node_utils/cmd_ref/bgp_neighbor_af.yaml +236 -0
  80. data/lib/cisco_node_utils/cmd_ref/bridge_domain.yaml +49 -0
  81. data/lib/cisco_node_utils/cmd_ref/bridge_domain_vni.yaml +33 -0
  82. data/lib/cisco_node_utils/cmd_ref/dhcp_relay_global.yaml +128 -0
  83. data/lib/cisco_node_utils/cmd_ref/dnsclient.yaml +55 -0
  84. data/lib/cisco_node_utils/cmd_ref/encapsulation.yaml +25 -0
  85. data/lib/cisco_node_utils/cmd_ref/evpn_multicast.yaml +12 -0
  86. data/lib/cisco_node_utils/cmd_ref/evpn_multisite.yaml +18 -0
  87. data/lib/cisco_node_utils/cmd_ref/evpn_stormcontrol.yaml +18 -0
  88. data/lib/cisco_node_utils/cmd_ref/evpn_vni.yaml +48 -0
  89. data/lib/cisco_node_utils/cmd_ref/fabricpath.yaml +183 -0
  90. data/lib/cisco_node_utils/cmd_ref/fabricpath_topology.yaml +40 -0
  91. data/lib/cisco_node_utils/cmd_ref/feature.yaml +126 -0
  92. data/lib/cisco_node_utils/cmd_ref/hostname.yaml +8 -0
  93. data/lib/cisco_node_utils/cmd_ref/hsrp_global.yaml +25 -0
  94. data/lib/cisco_node_utils/cmd_ref/images.yaml +8 -0
  95. data/lib/cisco_node_utils/cmd_ref/interface.yaml +781 -0
  96. data/lib/cisco_node_utils/cmd_ref/interface_channel_group.yaml +45 -0
  97. data/lib/cisco_node_utils/cmd_ref/interface_evpn_multisite.yaml +17 -0
  98. data/lib/cisco_node_utils/cmd_ref/interface_hsrp_group.yaml +120 -0
  99. data/lib/cisco_node_utils/cmd_ref/interface_ospf.yaml +112 -0
  100. data/lib/cisco_node_utils/cmd_ref/interface_portchannel.yaml +87 -0
  101. data/lib/cisco_node_utils/cmd_ref/interface_service_vni.yaml +42 -0
  102. data/lib/cisco_node_utils/cmd_ref/inventory.yaml +45 -0
  103. data/lib/cisco_node_utils/cmd_ref/ip_multicast.yaml +22 -0
  104. data/lib/cisco_node_utils/cmd_ref/itd_device_group.yaml +83 -0
  105. data/lib/cisco_node_utils/cmd_ref/itd_service.yaml +119 -0
  106. data/lib/cisco_node_utils/cmd_ref/memory.yaml +24 -0
  107. data/lib/cisco_node_utils/cmd_ref/ntp_auth_key.yaml +10 -0
  108. data/lib/cisco_node_utils/cmd_ref/ntp_config.yaml +27 -0
  109. data/lib/cisco_node_utils/cmd_ref/ntp_server.yaml +34 -0
  110. data/lib/cisco_node_utils/cmd_ref/object_group.yaml +32 -0
  111. data/lib/cisco_node_utils/cmd_ref/ospf.yaml +91 -0
  112. data/lib/cisco_node_utils/cmd_ref/ospf_area.yaml +91 -0
  113. data/lib/cisco_node_utils/cmd_ref/ospf_area_vlink.yaml +88 -0
  114. data/lib/cisco_node_utils/cmd_ref/overlay_global.yaml +37 -0
  115. data/lib/cisco_node_utils/cmd_ref/pim.yaml +43 -0
  116. data/lib/cisco_node_utils/cmd_ref/portchannel_global.yaml +86 -0
  117. data/lib/cisco_node_utils/cmd_ref/radius_global.yaml +37 -0
  118. data/lib/cisco_node_utils/cmd_ref/radius_server.yaml +100 -0
  119. data/lib/cisco_node_utils/cmd_ref/radius_server_group.yaml +19 -0
  120. data/lib/cisco_node_utils/cmd_ref/route_map.yaml +601 -0
  121. data/lib/cisco_node_utils/cmd_ref/show_system.yaml +9 -0
  122. data/lib/cisco_node_utils/cmd_ref/show_version.yaml +84 -0
  123. data/lib/cisco_node_utils/cmd_ref/snmp_community.yaml +81 -0
  124. data/lib/cisco_node_utils/cmd_ref/snmp_group.yaml +9 -0
  125. data/lib/cisco_node_utils/cmd_ref/snmp_notification_receiver.yaml +74 -0
  126. data/lib/cisco_node_utils/cmd_ref/snmp_server.yaml +91 -0
  127. data/lib/cisco_node_utils/cmd_ref/snmp_user.yaml +57 -0
  128. data/lib/cisco_node_utils/cmd_ref/snmpnotification.yaml +23 -0
  129. data/lib/cisco_node_utils/cmd_ref/span_session.yaml +65 -0
  130. data/lib/cisco_node_utils/cmd_ref/stp_global.yaml +235 -0
  131. data/lib/cisco_node_utils/cmd_ref/syslog_facility.yaml +10 -0
  132. data/lib/cisco_node_utils/cmd_ref/syslog_server.yaml +34 -0
  133. data/lib/cisco_node_utils/cmd_ref/syslog_settings.yaml +45 -0
  134. data/lib/cisco_node_utils/cmd_ref/system.yaml +7 -0
  135. data/lib/cisco_node_utils/cmd_ref/tacacs_global.yaml +37 -0
  136. data/lib/cisco_node_utils/cmd_ref/tacacs_server.yaml +63 -0
  137. data/lib/cisco_node_utils/cmd_ref/tacacs_server_group.yaml +45 -0
  138. data/lib/cisco_node_utils/cmd_ref/tacacs_server_host.yaml +64 -0
  139. data/lib/cisco_node_utils/cmd_ref/upgrade.yaml +38 -0
  140. data/lib/cisco_node_utils/cmd_ref/vdc.yaml +52 -0
  141. data/lib/cisco_node_utils/cmd_ref/virtual_service.yaml +8 -0
  142. data/lib/cisco_node_utils/cmd_ref/vlan.yaml +106 -0
  143. data/lib/cisco_node_utils/cmd_ref/vpc.yaml +233 -0
  144. data/lib/cisco_node_utils/cmd_ref/vrf.yaml +86 -0
  145. data/lib/cisco_node_utils/cmd_ref/vrf_af.yaml +139 -0
  146. data/lib/cisco_node_utils/cmd_ref/vtp.yaml +32 -0
  147. data/lib/cisco_node_utils/cmd_ref/vxlan_vtep.yaml +114 -0
  148. data/lib/cisco_node_utils/cmd_ref/vxlan_vtep_vni.yaml +71 -0
  149. data/lib/cisco_node_utils/cmd_ref/yang.yaml +7 -0
  150. data/lib/cisco_node_utils/cmd_ref/yum.yaml +68 -0
  151. data/lib/cisco_node_utils/command_reference.rb +724 -0
  152. data/lib/cisco_node_utils/configparser_lib.rb +195 -0
  153. data/lib/cisco_node_utils/constants.rb +40 -0
  154. data/lib/cisco_node_utils/dhcp_relay_global.rb +302 -0
  155. data/lib/cisco_node_utils/dns_domain.rb +93 -0
  156. data/lib/cisco_node_utils/domain_name.rb +82 -0
  157. data/lib/cisco_node_utils/encapsulation.rb +112 -0
  158. data/lib/cisco_node_utils/environment.rb +110 -0
  159. data/lib/cisco_node_utils/evpn_multicast.rb +66 -0
  160. data/lib/cisco_node_utils/evpn_multisite.rb +96 -0
  161. data/lib/cisco_node_utils/evpn_stormcontrol.rb +84 -0
  162. data/lib/cisco_node_utils/evpn_vni.rb +159 -0
  163. data/lib/cisco_node_utils/exceptions.rb +140 -0
  164. data/lib/cisco_node_utils/fabricpath_global.rb +405 -0
  165. data/lib/cisco_node_utils/fabricpath_topology.rb +137 -0
  166. data/lib/cisco_node_utils/feature.rb +377 -0
  167. data/lib/cisco_node_utils/hostname.rb +62 -0
  168. data/lib/cisco_node_utils/hsrp_global.rb +97 -0
  169. data/lib/cisco_node_utils/interface.rb +2128 -0
  170. data/lib/cisco_node_utils/interface_channel_group.rb +142 -0
  171. data/lib/cisco_node_utils/interface_evpn_multisite.rb +72 -0
  172. data/lib/cisco_node_utils/interface_hsrp_group.rb +557 -0
  173. data/lib/cisco_node_utils/interface_ospf.rb +378 -0
  174. data/lib/cisco_node_utils/interface_portchannel.rb +180 -0
  175. data/lib/cisco_node_utils/interface_service_vni.rb +132 -0
  176. data/lib/cisco_node_utils/ip_multicast.rb +90 -0
  177. data/lib/cisco_node_utils/itd_device_group.rb +228 -0
  178. data/lib/cisco_node_utils/itd_device_group_node.rb +144 -0
  179. data/lib/cisco_node_utils/itd_service.rb +511 -0
  180. data/lib/cisco_node_utils/logger.rb +78 -0
  181. data/lib/cisco_node_utils/name_server.rb +64 -0
  182. data/lib/cisco_node_utils/node.rb +443 -0
  183. data/lib/cisco_node_utils/node_util.rb +111 -0
  184. data/lib/cisco_node_utils/ntp_auth_key.rb +67 -0
  185. data/lib/cisco_node_utils/ntp_config.rb +83 -0
  186. data/lib/cisco_node_utils/ntp_server.rb +86 -0
  187. data/lib/cisco_node_utils/object_group.rb +75 -0
  188. data/lib/cisco_node_utils/object_group_entry.rb +143 -0
  189. data/lib/cisco_node_utils/overlay_global.rb +142 -0
  190. data/lib/cisco_node_utils/pim.rb +131 -0
  191. data/lib/cisco_node_utils/pim_group_list.rb +109 -0
  192. data/lib/cisco_node_utils/pim_rp_address.rb +103 -0
  193. data/lib/cisco_node_utils/platform.rb +217 -0
  194. data/lib/cisco_node_utils/portchannel_global.rb +347 -0
  195. data/lib/cisco_node_utils/radius_global.rb +165 -0
  196. data/lib/cisco_node_utils/radius_server.rb +421 -0
  197. data/lib/cisco_node_utils/radius_server_group.rb +117 -0
  198. data/lib/cisco_node_utils/route_map.rb +2540 -0
  199. data/lib/cisco_node_utils/router_ospf.rb +77 -0
  200. data/lib/cisco_node_utils/router_ospf_area.rb +416 -0
  201. data/lib/cisco_node_utils/router_ospf_area_vlink.rb +313 -0
  202. data/lib/cisco_node_utils/router_ospf_vrf.rb +342 -0
  203. data/lib/cisco_node_utils/snmp_notification_receiver.rb +176 -0
  204. data/lib/cisco_node_utils/snmpcommunity.rb +109 -0
  205. data/lib/cisco_node_utils/snmpgroup.rb +54 -0
  206. data/lib/cisco_node_utils/snmpnotification.rb +57 -0
  207. data/lib/cisco_node_utils/snmpserver.rb +132 -0
  208. data/lib/cisco_node_utils/snmpuser.rb +403 -0
  209. data/lib/cisco_node_utils/span_session.rb +149 -0
  210. data/lib/cisco_node_utils/stp_global.rb +676 -0
  211. data/lib/cisco_node_utils/syslog_facility.rb +64 -0
  212. data/lib/cisco_node_utils/syslog_server.rb +146 -0
  213. data/lib/cisco_node_utils/syslog_settings.rb +174 -0
  214. data/lib/cisco_node_utils/tacacs_global.rb +137 -0
  215. data/lib/cisco_node_utils/tacacs_server.rb +173 -0
  216. data/lib/cisco_node_utils/tacacs_server_group.rb +149 -0
  217. data/lib/cisco_node_utils/tacacs_server_host.rb +216 -0
  218. data/lib/cisco_node_utils/upgrade.rb +122 -0
  219. data/lib/cisco_node_utils/vdc.rb +118 -0
  220. data/lib/cisco_node_utils/version.rb +21 -0
  221. data/lib/cisco_node_utils/vlan.rb +301 -0
  222. data/lib/cisco_node_utils/vpc.rb +466 -0
  223. data/lib/cisco_node_utils/vrf.rb +192 -0
  224. data/lib/cisco_node_utils/vrf_af.rb +327 -0
  225. data/lib/cisco_node_utils/vtp.rb +125 -0
  226. data/lib/cisco_node_utils/vxlan_vtep.rb +286 -0
  227. data/lib/cisco_node_utils/vxlan_vtep_vni.rb +331 -0
  228. data/lib/cisco_node_utils/yang.rb +160 -0
  229. data/lib/cisco_node_utils/yum.rb +213 -0
  230. data/lib/cisco_node_utils.rb +21 -0
  231. data/lib/minitest/environment_plugin.rb +31 -0
  232. data/lib/minitest/log_level_plugin.rb +41 -0
  233. data/spec/client_spec.rb +7 -0
  234. data/spec/environment_spec.rb +384 -0
  235. data/spec/grpc_client_spec.rb +23 -0
  236. data/spec/isolate/all_clients_spec.rb +9 -0
  237. data/spec/isolate/grpc_only_spec.rb +16 -0
  238. data/spec/isolate/no_clients_spec.rb +26 -0
  239. data/spec/isolate/nxapi_only_spec.rb +16 -0
  240. data/spec/nxapi_client_spec.rb +42 -0
  241. data/spec/schema.yaml +82 -0
  242. data/spec/shared_examples_for_clients.rb +14 -0
  243. data/spec/spec_helper.rb +91 -0
  244. data/spec/whitespace_spec.rb +10 -0
  245. data/spec/yaml_spec.rb +42 -0
  246. data/tests/.rubocop.yml +18 -0
  247. data/tests/CSCuxdublin-1.0.0-7.0.3.I3.1.lib32_n9000.rpm +0 -0
  248. data/tests/basetest.rb +243 -0
  249. data/tests/ciscotest.rb +577 -0
  250. data/tests/cmd_config.yaml +75 -0
  251. data/tests/cmd_config_invalid.yaml +16 -0
  252. data/tests/n9000_sample-1.0.0-7.0.3.x86_64.rpm +0 -0
  253. data/tests/noop.rb +7 -0
  254. data/tests/platform_info.rb +63 -0
  255. data/tests/tacacs_server.yaml.example +6 -0
  256. data/tests/test_aaa_authentication_login.rb +243 -0
  257. data/tests/test_aaa_authentication_login_service.rb +761 -0
  258. data/tests/test_aaa_authorization_service.rb +874 -0
  259. data/tests/test_ace.rb +304 -0
  260. data/tests/test_acl.rb +185 -0
  261. data/tests/test_banner.rb +85 -0
  262. data/tests/test_bfd_global.rb +272 -0
  263. data/tests/test_bgp_af.rb +875 -0
  264. data/tests/test_bgp_af_aa.rb +108 -0
  265. data/tests/test_bgp_neighbor.rb +596 -0
  266. data/tests/test_bgp_neighbor_af.rb +781 -0
  267. data/tests/test_bridge_domain.rb +198 -0
  268. data/tests/test_bridge_domain_vni.rb +109 -0
  269. data/tests/test_client_utils.rb +111 -0
  270. data/tests/test_cmn_utils.rb +76 -0
  271. data/tests/test_command_config.rb +206 -0
  272. data/tests/test_command_reference.rb +669 -0
  273. data/tests/test_dhcp_relay_global.rb +286 -0
  274. data/tests/test_dns_domain.rb +123 -0
  275. data/tests/test_domain_name.rb +96 -0
  276. data/tests/test_encapsulation.rb +75 -0
  277. data/tests/test_evpn_multicast.rb +65 -0
  278. data/tests/test_evpn_multisite.rb +70 -0
  279. data/tests/test_evpn_stormcontrol.rb +56 -0
  280. data/tests/test_evpn_vni.rb +131 -0
  281. data/tests/test_fabricpath_global.rb +246 -0
  282. data/tests/test_fabricpath_topology.rb +77 -0
  283. data/tests/test_feature.rb +272 -0
  284. data/tests/test_grpc.rb +166 -0
  285. data/tests/test_hostname.rb +64 -0
  286. data/tests/test_hsrp_global.rb +79 -0
  287. data/tests/test_interface.rb +1958 -0
  288. data/tests/test_interface_bdi.rb +80 -0
  289. data/tests/test_interface_channel_group.rb +131 -0
  290. data/tests/test_interface_evpn_multisite.rb +94 -0
  291. data/tests/test_interface_hsrp.rb +134 -0
  292. data/tests/test_interface_hsrp_group.rb +570 -0
  293. data/tests/test_interface_ospf.rb +820 -0
  294. data/tests/test_interface_portchannel.rb +135 -0
  295. data/tests/test_interface_private_vlan.rb +365 -0
  296. data/tests/test_interface_service_vni.rb +203 -0
  297. data/tests/test_interface_svi.rb +210 -0
  298. data/tests/test_interface_switchport.rb +468 -0
  299. data/tests/test_ip_multicast.rb +80 -0
  300. data/tests/test_itd_device_group.rb +145 -0
  301. data/tests/test_itd_device_group_node.rb +199 -0
  302. data/tests/test_itd_service.rb +314 -0
  303. data/tests/test_logger.rb +43 -0
  304. data/tests/test_name_server.rb +94 -0
  305. data/tests/test_node.rb +50 -0
  306. data/tests/test_node_ext.rb +406 -0
  307. data/tests/test_node_util.rb +119 -0
  308. data/tests/test_ntp_auth_key.rb +77 -0
  309. data/tests/test_ntp_config.rb +100 -0
  310. data/tests/test_ntp_server.rb +146 -0
  311. data/tests/test_nxapi.rb +236 -0
  312. data/tests/test_object_group.rb +122 -0
  313. data/tests/test_overlay_global.rb +108 -0
  314. data/tests/test_pim.rb +203 -0
  315. data/tests/test_pim_group_list.rb +147 -0
  316. data/tests/test_pim_rp_address.rb +155 -0
  317. data/tests/test_platform.rb +254 -0
  318. data/tests/test_portchannel_global.rb +322 -0
  319. data/tests/test_radius_global.rb +108 -0
  320. data/tests/test_radius_server.rb +377 -0
  321. data/tests/test_radius_server_group.rb +151 -0
  322. data/tests/test_route_map.rb +1479 -0
  323. data/tests/test_router_bgp.rb +1325 -0
  324. data/tests/test_router_ospf.rb +56 -0
  325. data/tests/test_router_ospf_area.rb +433 -0
  326. data/tests/test_router_ospf_area_vlink.rb +298 -0
  327. data/tests/test_router_ospf_vrf.rb +690 -0
  328. data/tests/test_snmp_notification_receiver.rb +169 -0
  329. data/tests/test_snmpcommunity.rb +422 -0
  330. data/tests/test_snmpgroup.rb +71 -0
  331. data/tests/test_snmpnotification.rb +91 -0
  332. data/tests/test_snmpserver.rb +251 -0
  333. data/tests/test_snmpuser.rb +666 -0
  334. data/tests/test_span_session.rb +155 -0
  335. data/tests/test_stp_global.rb +575 -0
  336. data/tests/test_syslog_facility.rb +80 -0
  337. data/tests/test_syslog_server.rb +119 -0
  338. data/tests/test_syslog_settings.rb +123 -0
  339. data/tests/test_tacacs_global.rb +109 -0
  340. data/tests/test_tacacs_server.rb +436 -0
  341. data/tests/test_tacacs_server_group.rb +434 -0
  342. data/tests/test_tacacs_server_host.rb +427 -0
  343. data/tests/test_upgrade.rb +105 -0
  344. data/tests/test_vdc.rb +64 -0
  345. data/tests/test_vlan.rb +386 -0
  346. data/tests/test_vlan_private.rb +656 -0
  347. data/tests/test_vpc.rb +548 -0
  348. data/tests/test_vrf.rb +248 -0
  349. data/tests/test_vrf_af.rb +288 -0
  350. data/tests/test_vtp.rb +278 -0
  351. data/tests/test_vxlan_vtep.rb +327 -0
  352. data/tests/test_vxlan_vtep_vni.rb +326 -0
  353. data/tests/test_yang.rb +369 -0
  354. data/tests/test_yum.rb +109 -0
  355. data/tests/upgrade_info.yaml.example +3 -0
  356. data/tests/yum_package.yaml +94 -0
  357. metadata +534 -0
@@ -0,0 +1,2128 @@
1
+ # November 2015, Chris Van Heuveln
2
+ #
3
+ # Copyright (c) 2015-2018 Cisco and/or its affiliates.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require_relative 'cisco_cmn_utils'
18
+ require_relative 'node_util'
19
+ require_relative 'vrf'
20
+ require_relative 'overlay_global'
21
+
22
+ # Cisco provider module
23
+ module Cisco
24
+ IF_SWITCHPORT_MODE = {
25
+ disabled: '',
26
+ access: 'access',
27
+ trunk: 'trunk',
28
+ fex_fabric: 'fex-fabric',
29
+ tunnel: 'dot1q-tunnel',
30
+ fabricpath: 'fabricpath',
31
+ }
32
+
33
+ # Interface - node utility class for general interface config management
34
+ class Interface < NodeUtil
35
+ # Regexp to match various Ethernet interface variants:
36
+ # Ethernet
37
+ # GigabitEthernet
38
+ # TenGigE
39
+ # HundredGigE
40
+ # MgmtEth
41
+ ETHERNET = Regexp.new('(Ethernet|GigE|MgmtEth)', Regexp::IGNORECASE)
42
+ # Regexp to match various link bundle interface variants
43
+ PORTCHANNEL = Regexp.new('(port-channel|Bundle-Ether)', Regexp::IGNORECASE)
44
+
45
+ attr_reader :name, :state_default, :show_name
46
+
47
+ def initialize(name, instantiate=true, default_state=false, show_name=nil)
48
+ fail TypeError unless name.is_a?(String)
49
+ fail ArgumentError unless name.length > 0
50
+
51
+ # @name is used for context: keys only
52
+ # @show_name is used for get_command: keys; allows callers to limit
53
+ # show command to a single interface
54
+ @name = name.downcase
55
+ @show_name = show_name.nil? ? '' : Utils.normalize_intf_pattern(show_name)
56
+ @get_args = { name: @name, show_name: @show_name }
57
+ @smr = config_get('interface', 'stp_mst_range')
58
+ @svr = config_get('interface', 'stp_vlan_range')
59
+ @match_found = false
60
+ # Keep track of default vs non-default state for
61
+ # interfaces that cannot be created/destroyed.
62
+ @state_default = nil
63
+ # Track ethernet but not sub-interfaces
64
+ if @name[/ethernet/] && !@name[/ethernet.*\.\d+/]
65
+ @state_default = default_state
66
+ end
67
+ create if instantiate
68
+ end
69
+
70
+ def to_s
71
+ "interface #{name}"
72
+ end
73
+
74
+ def self.interface_count
75
+ config_get('interface', 'all_count').to_i
76
+ end
77
+
78
+ def self.interfaces(opt=nil, show_name=nil)
79
+ hash = {}
80
+ show_name = Utils.normalize_intf_pattern(show_name)
81
+ begin
82
+ intf_list = config_get('interface', 'all_interfaces',
83
+ show_name: show_name)
84
+ rescue CliError => e
85
+ raise unless show_name
86
+ # ignore logical interfaces that do not exist
87
+ debug 'Interface.interfaces ignoring CliError => ' + e.to_s
88
+ end
89
+ return hash if intf_list.nil?
90
+
91
+ # Massage intf_list data into an array that is easy to work with.
92
+ # Use a MARKER to hide pesky 'interface' substrings
93
+ intf_list.collect! { |x| x.strip || x }
94
+ intf_list.delete('')
95
+ intf_list.collect! { |x| (x.sub('interface', '~!MARKER!~') unless x[/^interface /]) || x } # rubocop:disable Metrics/LineLength
96
+ intf_list = intf_list.join(' ').split('interface')
97
+ intf_list.delete('')
98
+ # Restore 'interface' substrings
99
+ intf_list.collect! { |x| x.sub('~!MARKER!~', 'interface') }
100
+
101
+ intf_list.each do |id|
102
+ int_data = id.strip.split(' ')
103
+ next if int_data[0].nil?
104
+ id = int_data[0].downcase
105
+ next if opt && filter(opt, id, show_name)
106
+ # If there are any additional options associated
107
+ # with this interface then it's in a non-default
108
+ # state.
109
+ default_state = int_data.size > 1 ? false : true
110
+ hash[id] = Interface.new(id, false, default_state, show_name)
111
+ end
112
+ hash
113
+ end
114
+
115
+ # General-purpose filter for Interface.interfaces().
116
+ # filter: This may be overloaded in the future to allow a hash of filters.
117
+ # id: The interface name
118
+ # show_name: needed for get_command: <show_name>
119
+ # Return: true if the interface should be filtered out, false to keep it.
120
+ def self.filter(filter, id, show_name)
121
+ case filter
122
+ when :pvlan_any
123
+ return false if config_get('interface', 'pvlan_any',
124
+ name: id, show_name: show_name)
125
+
126
+ else
127
+ # Just a basic pattern filter (:ethernet, :loopback, etc)
128
+ return false if id.match(filter.to_s)
129
+ end
130
+ true
131
+ end
132
+
133
+ # 'capabilities' is a getter-only helper for minitest and beaker.
134
+ # mode values:
135
+ # :hash = Transform the output into a hash
136
+ # :raw = The raw output from 'show int capabilities'. Some multi-line
137
+ # values do not translate easily so this option allows the
138
+ # caller to extract the data it needs.
139
+ #
140
+ # Sample cli output:
141
+ # Model: N7K-M132XP-12L
142
+ # Type (SFP capable): 10Gbase-SR
143
+ # Speed: 10,100,1000
144
+ #
145
+ # Sample hash output:
146
+ # {"Model"=>"N7K-M132XP-12L", "Type"=>"10Gbase-SR", "Speed"=>"10,100,1000"}
147
+ #
148
+ def self.capabilities(intf, mode=:hash)
149
+ array = []
150
+ begin
151
+ array = config_get('interface', 'capabilities', name: intf)
152
+ rescue CliError => e
153
+ raise unless e.clierror[/(Invalid command|Cmd exec error)/]
154
+ end
155
+ return array if mode == :raw
156
+ hash = {}
157
+ if array
158
+ array.delete('')
159
+ array.each do |line|
160
+ k, v = line.split(':')
161
+ next if k.nil? || v.nil?
162
+ k.gsub!(/ \(.*\)/, '') # Remove any parenthetical text from key
163
+ v.strip!
164
+ v.gsub!(%r{half/full}, 'half,full') if k == 'Duplex'
165
+ hash[k] = v
166
+ end
167
+ end
168
+ hash
169
+ end
170
+
171
+ def create
172
+ feature_vlan_set(true) if @name[/(vlan|bdi)/i]
173
+ config_set('interface', 'create', name: @name)
174
+ rescue Cisco::CliError
175
+ # Some XR platforms do not support channel-group configuration
176
+ # on some OS versions. Since this is an OS version difference and not
177
+ # a platform difference, we can't handle this in the YAML.
178
+ raise unless PORTCHANNEL =~ @name && platform == :ios_xr
179
+ raise Cisco::UnsupportedError.new('interface', @name, 'create')
180
+ end
181
+
182
+ def destroy
183
+ if @name[/ethernet/] && !@name[/ethernet.*\.\d+/]
184
+ config_set('interface', 'default', name: @name)
185
+ else
186
+ config_set('interface', 'destroy', name: @name)
187
+ end
188
+ end
189
+
190
+ def default?
191
+ state = config_get('interface', 'default', @get_args)
192
+ state.nil? ? true : false
193
+ end
194
+
195
+ def pvlan_enable
196
+ switchport_enable
197
+ Feature.private_vlan_enable
198
+ end
199
+
200
+ ########################################################
201
+ # PROPERTIES #
202
+ ########################################################
203
+
204
+ # For range based attributes, a new attribute purge will
205
+ # be added in future. When purge is set to true, all the
206
+ # ranges which are specified in the manifest will be set
207
+ # to the desired values and those which are not specified
208
+ # in the manifest will be set to default. When purge is
209
+ # false, only the ranges specified in the manifest will
210
+ # be set to the values given in the manifest and others
211
+ # are left untouched.
212
+
213
+ def lacp_rate_shut_needed?
214
+ config_get('interface', 'lacp_rate_shut_needed')
215
+ end
216
+
217
+ def lacp_rate
218
+ config_get('interface', 'lacp_rate', @get_args)
219
+ end
220
+
221
+ def lacp_rate=(val)
222
+ if val
223
+ state = ''
224
+ else
225
+ return unless lacp_rate
226
+ state = 'no'
227
+ val = lacp_rate
228
+ end
229
+ int = Interface.new(@name, false)
230
+ current_state = int.shutdown
231
+ int.shutdown = true if lacp_rate_shut_needed? && !current_state
232
+ config_set('interface', 'lacp_rate', name: @name,
233
+ state: state, type: val)
234
+ int.shutdown = current_state unless current_state == int.shutdown
235
+ end
236
+
237
+ def default_lacp_rate
238
+ config_get_default('interface', 'lacp_rate')
239
+ end
240
+
241
+ def access_vlan
242
+ return nil if switchport_mode == :disabled
243
+ config_get('interface', 'access_vlan', @get_args)
244
+ end
245
+
246
+ def access_vlan=(vlan)
247
+ config_set('interface', 'access_vlan', name: @name, vlan: vlan)
248
+ end
249
+
250
+ def default_access_vlan
251
+ config_get_default('interface', 'access_vlan')
252
+ end
253
+
254
+ def bfd_echo
255
+ return nil unless Feature.bfd_enabled?
256
+ return nil if @name[/loop/i]
257
+ config_get('interface', 'bfd_echo', @get_args)
258
+ end
259
+
260
+ def bfd_echo=(val)
261
+ fail ArgumentError, 'Interface cannot be loopback' if
262
+ @name[/loop/i]
263
+ return if val == bfd_echo
264
+ state = (val ? '' : 'no')
265
+ Feature.bfd_enable
266
+ config_set('interface', 'bfd_echo',
267
+ name: @name, state: state)
268
+ end
269
+
270
+ def default_bfd_echo
271
+ return nil unless Feature.bfd_enabled?
272
+ return nil if @name[/loop/i]
273
+ config_get_default('interface', 'bfd_echo')
274
+ end
275
+
276
+ def description
277
+ config_get('interface', 'description', @get_args)
278
+ end
279
+
280
+ def description=(desc)
281
+ fail TypeError unless desc.is_a?(String)
282
+ if desc.strip.empty?
283
+ config_set('interface', 'description',
284
+ name: @name, state: 'no', desc: '')
285
+ else
286
+ config_set('interface', 'description',
287
+ name: @name, state: '', desc: desc)
288
+ end
289
+ end
290
+
291
+ def default_description
292
+ config_get_default('interface', 'description')
293
+ end
294
+
295
+ def encapsulation_dot1q
296
+ config_get('interface', 'encapsulation_dot1q', @get_args)
297
+ end
298
+
299
+ def encapsulation_dot1q=(val)
300
+ if val.to_s.empty?
301
+ config_set('interface', 'encapsulation_dot1q',
302
+ name: @name, state: 'no', vlan: '')
303
+ else
304
+ config_set('interface', 'encapsulation_dot1q',
305
+ name: @name, state: '', vlan: val)
306
+ end
307
+ end
308
+
309
+ def default_encapsulation_dot1q
310
+ config_get_default('interface', 'encapsulation_dot1q')
311
+ end
312
+
313
+ def fabricpath_feature
314
+ FabricpathGlobal.fabricpath_feature
315
+ end
316
+
317
+ def fabricpath_feature_set(fabricpath_set)
318
+ FabricpathGlobal.fabricpath_feature_set(fabricpath_set)
319
+ end
320
+
321
+ def fabric_forwarding_anycast_gateway
322
+ config_get('interface', 'fabric_forwarding_anycast_gateway', @get_args)
323
+ end
324
+
325
+ def fabric_forwarding_anycast_gateway=(state)
326
+ return if fabric_forwarding_anycast_gateway == state
327
+ no_cmd = (state ? '' : 'no')
328
+ config_set('interface',
329
+ 'fabric_forwarding_anycast_gateway',
330
+ name: @name, state: no_cmd)
331
+ fail if fabric_forwarding_anycast_gateway.to_s != state.to_s
332
+ rescue Cisco::CliError => e
333
+ raise "#{e} 'fabric_forwarding_anycast_gateway' can only be " \
334
+ 'configured on a vlan interface' unless /vlan/.match(@name)
335
+ anycast_gateway_mac = OverlayGlobal.new.anycast_gateway_mac
336
+ if anycast_gateway_mac.nil? || anycast_gateway_mac.empty?
337
+ raise "#{e} Anycast gateway mac must be configured " \
338
+ 'before configuring forwarding mode under interface'
339
+ end
340
+ raise
341
+ end
342
+
343
+ def default_fabric_forwarding_anycast_gateway
344
+ config_get_default('interface', 'fabric_forwarding_anycast_gateway')
345
+ end
346
+
347
+ def hsrp_bfd
348
+ config_get('interface', 'hsrp_bfd', @get_args)
349
+ end
350
+
351
+ def hsrp_bfd=(val)
352
+ return if val == hsrp_bfd
353
+ state = val ? '' : 'no'
354
+ if val
355
+ Feature.hsrp_enable
356
+ Feature.bfd_enable
357
+ end
358
+ config_set('interface', 'hsrp_bfd', name: @name, state: state)
359
+ end
360
+
361
+ def default_hsrp_bfd
362
+ config_get_default('interface', 'hsrp_bfd')
363
+ end
364
+
365
+ # hsrp delay minimum and reload are in the same CLI
366
+ # hsrp delay minimum 0 reload 0
367
+ def hsrp_delay
368
+ match = config_get('interface', 'hsrp_delay', @get_args)
369
+ match.nil? ? default_hsrp_delay : match.collect(&:to_i)
370
+ end
371
+
372
+ def default_hsrp_delay
373
+ [default_hsrp_delay_minimum, default_hsrp_delay_reload]
374
+ end
375
+
376
+ def hsrp_delay_minimum
377
+ return nil if switchport_mode != :disabled || @name[/loop/i]
378
+ minimum, _reload = hsrp_delay
379
+ minimum.nil? ? default_hsrp_delay_minimum : minimum
380
+ end
381
+
382
+ # hsrp delay minimum and reload are in the same CLI
383
+ # but both can be set independent of each other
384
+ def hsrp_delay_minimum=(val)
385
+ Feature.hsrp_enable if val
386
+ config_set('interface', 'hsrp_delay', name: @name,
387
+ minimum: 'minimum', min: val, reload: '', rel: '')
388
+ end
389
+
390
+ def default_hsrp_delay_minimum
391
+ config_get_default('interface', 'hsrp_delay_minimum')
392
+ end
393
+
394
+ def hsrp_delay_reload
395
+ return nil if switchport_mode != :disabled || @name[/loop/i]
396
+ _minimum, reload = hsrp_delay
397
+ reload.nil? ? default_hsrp_delay_reload : reload
398
+ end
399
+
400
+ # hsrp delay minimum and reload are in the same CLI
401
+ # but both can be set independent of each other
402
+ def hsrp_delay_reload=(val)
403
+ Feature.hsrp_enable if val
404
+ config_set('interface', 'hsrp_delay', name: @name,
405
+ minimum: '', min: '', reload: 'reload', rel: val)
406
+ end
407
+
408
+ def default_hsrp_delay_reload
409
+ config_get_default('interface', 'hsrp_delay_reload')
410
+ end
411
+
412
+ def hsrp_mac_refresh
413
+ config_get('interface', 'hsrp_mac_refresh', @get_args)
414
+ end
415
+
416
+ def hsrp_mac_refresh=(val)
417
+ state = val ? '' : 'no'
418
+ time = val ? val : ''
419
+ Feature.hsrp_enable if val
420
+ config_set('interface', 'hsrp_mac_refresh', name: @name,
421
+ state: state, timeout: time)
422
+ end
423
+
424
+ def default_hsrp_mac_refresh
425
+ config_get_default('interface', 'hsrp_mac_refresh')
426
+ end
427
+
428
+ def hsrp_use_bia
429
+ match = config_get('interface', 'hsrp_use_bia', @get_args)
430
+ return default_hsrp_use_bia unless match
431
+ match.include?('scope') ? :use_bia_intf : :use_bia
432
+ end
433
+
434
+ def hsrp_use_bia=(val)
435
+ # Return early if device already set to the correct value
436
+ return if val == hsrp_use_bia
437
+ # need to reset before set
438
+ if val
439
+ Feature.hsrp_enable
440
+ if val == :use_bia
441
+ config_set('interface', 'hsrp_use_bia', name: name,
442
+ state: 'no', scope: ' scope interface')
443
+ config_set('interface', 'hsrp_use_bia', name: name,
444
+ state: '', scope: '')
445
+ else
446
+ config_set('interface', 'hsrp_use_bia', name: name,
447
+ state: 'no', scope: '')
448
+ config_set('interface', 'hsrp_use_bia', name: name,
449
+ state: '', scope: ' scope interface')
450
+ end
451
+ else
452
+ if hsrp_use_bia == :use_bia
453
+ config_set('interface', 'hsrp_use_bia', name: name,
454
+ state: 'no', scope: '')
455
+ else
456
+ config_set('interface', 'hsrp_use_bia', name: name,
457
+ state: 'no', scope: ' scope interface')
458
+ end
459
+ end
460
+ end
461
+
462
+ def default_hsrp_use_bia
463
+ config_get_default('interface', 'hsrp_use_bia')
464
+ end
465
+
466
+ def hsrp_version
467
+ return nil if switchport_mode != :disabled || @name[/loop/i]
468
+ config_get('interface', 'hsrp_version', @get_args)
469
+ end
470
+
471
+ def hsrp_version=(val)
472
+ Feature.hsrp_enable if val
473
+ config_set('interface', 'hsrp_version', name: name, ver: val)
474
+ end
475
+
476
+ def default_hsrp_version
477
+ config_get_default('interface', 'hsrp_version')
478
+ end
479
+
480
+ def ipv4_acl_in
481
+ config_get('interface', 'ipv4_acl_in', @get_args)
482
+ end
483
+
484
+ def ipv4_acl_in=(val)
485
+ if val != ''
486
+ state = ''
487
+ else
488
+ state = 'no'
489
+ val = ipv4_acl_in
490
+ end
491
+
492
+ return unless val && val != ''
493
+ config_set('interface', 'ipv4_acl_in',
494
+ name: @name, state: state, acl: val)
495
+ end
496
+
497
+ def default_ipv4_acl_in
498
+ config_get_default('interface', 'ipv4_acl_in')
499
+ end
500
+
501
+ def ipv4_acl_out
502
+ config_get('interface', 'ipv4_acl_out', @get_args)
503
+ end
504
+
505
+ def ipv4_acl_out=(val)
506
+ if val != ''
507
+ state = ''
508
+ else
509
+ state = 'no'
510
+ val = ipv4_acl_out
511
+ end
512
+
513
+ return unless val && val != ''
514
+ config_set('interface', 'ipv4_acl_out',
515
+ name: @name, state: state, acl: val)
516
+ end
517
+
518
+ def default_ipv4_acl_out
519
+ config_get_default('interface', 'ipv4_acl_out')
520
+ end
521
+
522
+ def ipv4_addr_mask_set(addr, mask, secondary=false)
523
+ check_switchport(:disabled)
524
+ sec = secondary ? 'secondary' : ''
525
+ if addr.nil? || addr == default_ipv4_address
526
+ state = 'no'
527
+ if secondary
528
+ return if ipv4_address_secondary == default_ipv4_address_secondary
529
+ # We need address and mask to remove.
530
+ am = "#{ipv4_address_secondary}/#{ipv4_netmask_length_secondary}"
531
+ else
532
+ return if ipv4_address == default_ipv4_address
533
+ am = "#{ipv4_address}/#{ipv4_netmask_length}"
534
+ end
535
+ else
536
+ state = ''
537
+ am = "#{addr}/#{mask}"
538
+ end
539
+ config_set('interface', 'ipv4_addr_mask',
540
+ name: @name, state: state, addr: am, secondary: sec)
541
+ end
542
+
543
+ def ipv4_addr_mask
544
+ val = config_get('interface', 'ipv4_addr_mask', @get_args)
545
+ if val && platform == :ios_xr
546
+ # IOS XR reports address as <address> <bitmask> [secondary] but we
547
+ # want <address>/<length> [secondary]
548
+ val.each_with_index do |entry, i|
549
+ mask = entry[1].split(' ')
550
+ mask[0] = Utils.bitmask_to_length(mask[0])
551
+ val[i][1] = mask.join(' ')
552
+ end
553
+ end
554
+ val
555
+ end
556
+
557
+ def select_ipv4_attribute(attribute)
558
+ d = ipv4_addr_mask.flatten unless ipv4_addr_mask.nil?
559
+ # (d)ata format after flatten: ['addr', 'mask', 'addr', 'mask secondary']
560
+ case attribute
561
+ when :v4_addr
562
+ v = d.nil? ? default_ipv4_address : d[0]
563
+ when :v4_mask
564
+ v = d.nil? ? default_ipv4_netmask_length : d[1].to_i
565
+ when :v4_addr_secondary
566
+ v = (d.nil? || d.size < 4) ? default_ipv4_address : d[2]
567
+ when :v4_mask_secondary
568
+ if d.nil? || d.size < 4
569
+ v = default_ipv4_netmask_length
570
+ else
571
+ v = d[3][0, 2].to_i
572
+ end
573
+ end
574
+ v
575
+ end
576
+
577
+ def ipv4_address
578
+ select_ipv4_attribute(:v4_addr)
579
+ end
580
+
581
+ def ipv4_address_secondary
582
+ select_ipv4_attribute(:v4_addr_secondary)
583
+ end
584
+
585
+ def ipv4_netmask_length
586
+ select_ipv4_attribute(:v4_mask)
587
+ end
588
+
589
+ def ipv4_netmask_length_secondary
590
+ select_ipv4_attribute(:v4_mask_secondary)
591
+ end
592
+
593
+ def default_ipv4_address
594
+ config_get_default('interface', 'ipv4_address')
595
+ end
596
+
597
+ def default_ipv4_address_secondary
598
+ default_ipv4_address
599
+ end
600
+
601
+ def default_ipv4_netmask_length
602
+ config_get_default('interface', 'ipv4_netmask_length')
603
+ end
604
+
605
+ def default_ipv4_netmask_length_secondary
606
+ default_ipv4_netmask_length
607
+ end
608
+
609
+ def ipv4_arp_timeout_lookup_string
610
+ case @name
611
+ when /vlan/i
612
+ return 'ipv4_arp_timeout'
613
+ else
614
+ return 'ipv4_arp_timeout_non_vlan_interfaces'
615
+ end
616
+ end
617
+
618
+ def ipv4_arp_timeout
619
+ config_get('interface', ipv4_arp_timeout_lookup_string, @get_args)
620
+ end
621
+
622
+ def ipv4_arp_timeout=(timeout)
623
+ fail "'ipv4 arp timeout' can ony be configured on a vlan interface" unless
624
+ /vlan/.match(@name)
625
+ state = (timeout == default_ipv4_arp_timeout) ? 'no' : ''
626
+ config_set('interface', 'ipv4_arp_timeout',
627
+ name: @name, state: state, timeout: timeout)
628
+ end
629
+
630
+ def default_ipv4_arp_timeout
631
+ config_get_default('interface', ipv4_arp_timeout_lookup_string)
632
+ end
633
+
634
+ def ipv4_dhcp_relay_addr
635
+ config_get('interface', 'ipv4_dhcp_relay_addr', @get_args)
636
+ end
637
+
638
+ def ipv4_dhcp_relay_addr=(list)
639
+ cur_list = ipv4_dhcp_relay_addr
640
+ # remove the current addresses first
641
+ unless cur_list.empty?
642
+ cur_list.each do |addr|
643
+ config_set('interface', 'ipv4_dhcp_relay_addr',
644
+ name: @name, state: 'no', addr: addr)
645
+ end
646
+ end
647
+ Feature.dhcp_enable unless list.empty?
648
+ list.each do |addr|
649
+ config_set('interface', 'ipv4_dhcp_relay_addr',
650
+ name: @name, state: '', addr: addr)
651
+ end
652
+ end
653
+
654
+ def default_ipv4_dhcp_relay_addr
655
+ config_get_default('interface', 'ipv4_dhcp_relay_addr')
656
+ end
657
+
658
+ def ipv4_dhcp_relay_info_trust
659
+ return nil if @name[/loop/i] || switchport_mode != :disabled
660
+ config_get('interface', 'ipv4_dhcp_relay_info_trust', @get_args)
661
+ end
662
+
663
+ def ipv4_dhcp_relay_info_trust=(state)
664
+ return false if !state && !Feature.dhcp_enabled?
665
+ Feature.dhcp_enable if state
666
+ config_set('interface', 'ipv4_dhcp_relay_info_trust',
667
+ name: @name, state: state ? '' : 'no')
668
+ end
669
+
670
+ def default_ipv4_dhcp_relay_info_trust
671
+ config_get_default('interface', 'ipv4_dhcp_relay_info_trust')
672
+ end
673
+
674
+ def ipv4_dhcp_relay_src_addr_hsrp
675
+ config_get('interface', 'ipv4_dhcp_relay_src_addr_hsrp', @get_args)
676
+ end
677
+
678
+ def ipv4_dhcp_relay_src_addr_hsrp=(state)
679
+ return false if !state && !Feature.dhcp_enabled?
680
+ Feature.dhcp_enable if state
681
+ config_set('interface', 'ipv4_dhcp_relay_src_addr_hsrp',
682
+ name: @name, state: state ? '' : 'no')
683
+ end
684
+
685
+ def default_ipv4_dhcp_relay_src_addr_hsrp
686
+ config_get_default('interface', 'ipv4_dhcp_relay_src_addr_hsrp')
687
+ end
688
+
689
+ def ipv4_dhcp_relay_src_intf
690
+ intf = config_get('interface', 'ipv4_dhcp_relay_src_intf', @get_args)
691
+ # Normalize by downcasing and removing white space
692
+ intf = intf.downcase.delete(' ') if intf
693
+ intf
694
+ end
695
+
696
+ def ipv4_dhcp_relay_src_intf=(val)
697
+ state = val == default_ipv4_dhcp_relay_src_intf ? 'no' : ''
698
+ return false if state == 'no' && !Feature.dhcp_enabled?
699
+ Feature.dhcp_enable if state.empty?
700
+ intf = val == default_ipv4_dhcp_relay_src_intf ? '' : val
701
+ config_set('interface', 'ipv4_dhcp_relay_src_intf',
702
+ name: @name, state: state, intf: intf)
703
+ end
704
+
705
+ def default_ipv4_dhcp_relay_src_intf
706
+ config_get_default('interface', 'ipv4_dhcp_relay_src_intf')
707
+ end
708
+
709
+ def ipv4_dhcp_relay_subnet_broadcast
710
+ return nil if @name[/loop/i] || switchport_mode != :disabled
711
+ config_get('interface', 'ipv4_dhcp_relay_subnet_broadcast', @get_args)
712
+ end
713
+
714
+ def ipv4_dhcp_relay_subnet_broadcast=(state)
715
+ return false if !state && !Feature.dhcp_enabled?
716
+ Feature.dhcp_enable if state
717
+ config_set('interface', 'ipv4_dhcp_relay_subnet_broadcast',
718
+ name: @name, state: state ? '' : 'no')
719
+ end
720
+
721
+ def default_ipv4_dhcp_relay_subnet_broadcast
722
+ config_get_default('interface', 'ipv4_dhcp_relay_subnet_broadcast')
723
+ end
724
+
725
+ def ipv4_dhcp_smart_relay
726
+ return nil if @name[/loop/i] || switchport_mode != :disabled
727
+ config_get('interface', 'ipv4_dhcp_smart_relay', @get_args)
728
+ end
729
+
730
+ def ipv4_dhcp_smart_relay=(state)
731
+ return false if !state && !Feature.dhcp_enabled?
732
+ Feature.dhcp_enable if state
733
+ config_set('interface', 'ipv4_dhcp_smart_relay',
734
+ name: @name, state: state ? '' : 'no')
735
+ end
736
+
737
+ def default_ipv4_dhcp_smart_relay
738
+ config_get_default('interface', 'ipv4_dhcp_smart_relay')
739
+ end
740
+
741
+ def ipv4_forwarding
742
+ config_get('interface', 'ipv4_forwarding', @get_args)
743
+ end
744
+
745
+ def ipv4_forwarding=(state)
746
+ return if state == ipv4_forwarding
747
+ config_set('interface', 'ipv4_forwarding',
748
+ name: @name, state: state ? '' : 'no')
749
+ end
750
+
751
+ def default_ipv4_forwarding
752
+ config_get_default('interface', 'ipv4_forwarding')
753
+ end
754
+
755
+ def ipv4_pim_sparse_mode
756
+ return nil unless switchport_mode == :disabled
757
+ config_get('interface', 'ipv4_pim_sparse_mode', @get_args)
758
+ end
759
+
760
+ def ipv4_pim_sparse_mode=(state)
761
+ check_switchport(:disabled)
762
+ Feature.pim_enable unless platform == :ios_xr
763
+ config_set('interface', 'ipv4_pim_sparse_mode',
764
+ name: @name, state: state ? '' : 'no')
765
+ end
766
+
767
+ def default_ipv4_pim_sparse_mode
768
+ config_get_default('interface', 'ipv4_pim_sparse_mode')
769
+ end
770
+
771
+ def ipv4_proxy_arp
772
+ return nil if @name[/loop/i] || switchport_mode != :disabled
773
+ config_get('interface', 'ipv4_proxy_arp', @get_args)
774
+ end
775
+
776
+ def ipv4_proxy_arp=(proxy_arp)
777
+ check_switchport(:disabled)
778
+ no_cmd = (proxy_arp ? '' : 'no')
779
+ config_set('interface', 'ipv4_proxy_arp', name: @name, state: no_cmd)
780
+ end
781
+
782
+ def default_ipv4_proxy_arp
783
+ config_get_default('interface', 'ipv4_proxy_arp')
784
+ end
785
+
786
+ def ipv4_redirects_lookup_string
787
+ case @name
788
+ when /loopback/i
789
+ return 'ipv4_redirects_loopback'
790
+ else
791
+ return 'ipv4_redirects_other_interfaces'
792
+ end
793
+ end
794
+
795
+ def ipv4_redirects
796
+ return nil unless switchport_mode == :disabled
797
+ config_get('interface', ipv4_redirects_lookup_string, @get_args)
798
+ end
799
+
800
+ def ipv4_redirects=(redirects)
801
+ check_switchport(:disabled)
802
+ no_cmd = (redirects ? '' : 'no')
803
+ config_set('interface', ipv4_redirects_lookup_string,
804
+ name: @name, state: no_cmd)
805
+ end
806
+
807
+ def default_ipv4_redirects
808
+ config_get_default('interface', ipv4_redirects_lookup_string)
809
+ end
810
+
811
+ def ipv6_acl_in
812
+ config_get('interface', 'ipv6_acl_in', @get_args)
813
+ end
814
+
815
+ def ipv6_acl_in=(val)
816
+ if val != ''
817
+ state = ''
818
+ else
819
+ state = 'no'
820
+ val = ipv6_acl_in
821
+ end
822
+ return unless val && val != ''
823
+ config_set('interface', 'ipv6_acl_in',
824
+ name: @name, state: state, acl: val)
825
+ end
826
+
827
+ def default_ipv6_acl_in
828
+ config_get_default('interface', 'ipv6_acl_in')
829
+ end
830
+
831
+ def ipv6_acl_out
832
+ config_get('interface', 'ipv6_acl_out', @get_args)
833
+ end
834
+
835
+ def ipv6_acl_out=(val)
836
+ if val != ''
837
+ state = ''
838
+ else
839
+ state = 'no'
840
+ val = ipv6_acl_out
841
+ end
842
+ return unless val && val != ''
843
+ config_set('interface', 'ipv6_acl_out',
844
+ name: @name, state: state, acl: val)
845
+ end
846
+
847
+ def default_ipv6_acl_out
848
+ config_get_default('interface', 'ipv6_acl_out')
849
+ end
850
+
851
+ def ipv6_dhcp_relay_addr
852
+ config_get('interface', 'ipv6_dhcp_relay_addr', @get_args)
853
+ end
854
+
855
+ def ipv6_dhcp_relay_addr=(list)
856
+ cur_list = ipv6_dhcp_relay_addr
857
+ # remove the current addresses first
858
+ unless cur_list.empty?
859
+ cur_list.each do |addr|
860
+ config_set('interface', 'ipv6_dhcp_relay_addr',
861
+ name: @name, state: 'no', addr: addr)
862
+ end
863
+ end
864
+ Feature.dhcp_enable unless list.empty?
865
+ list.each do |addr|
866
+ config_set('interface', 'ipv6_dhcp_relay_addr',
867
+ name: @name, state: '', addr: addr)
868
+ end
869
+ end
870
+
871
+ def default_ipv6_dhcp_relay_addr
872
+ config_get_default('interface', 'ipv6_dhcp_relay_addr')
873
+ end
874
+
875
+ def ipv6_dhcp_relay_src_intf
876
+ intf = config_get('interface', 'ipv6_dhcp_relay_src_intf', @get_args)
877
+ # Normalize by downcasing and removing white space
878
+ intf = intf.downcase.delete(' ') if intf
879
+ intf
880
+ end
881
+
882
+ def ipv6_dhcp_relay_src_intf=(val)
883
+ state = val == default_ipv6_dhcp_relay_src_intf ? 'no' : ''
884
+ return false if state == 'no' && !Feature.dhcp_enabled?
885
+ Feature.dhcp_enable if state.empty?
886
+ intf = val == default_ipv6_dhcp_relay_src_intf ? '' : val
887
+ config_set('interface', 'ipv6_dhcp_relay_src_intf',
888
+ name: @name, state: state, intf: intf)
889
+ end
890
+
891
+ def default_ipv6_dhcp_relay_src_intf
892
+ config_get_default('interface', 'ipv6_dhcp_relay_src_intf')
893
+ end
894
+
895
+ def ipv6_redirects
896
+ return nil if @name[/loop/i] || switchport_mode != :disabled
897
+ config_get('interface', 'ipv6_redirects', @get_args)
898
+ end
899
+
900
+ def ipv6_redirects=(redirects)
901
+ check_switchport(:disabled)
902
+ no_cmd = (redirects ? '' : 'no')
903
+ config_set('interface', 'ipv6_redirects',
904
+ name: @name, state: no_cmd)
905
+ end
906
+
907
+ def default_ipv6_redirects
908
+ config_get_default('interface', 'ipv6_redirects')
909
+ end
910
+
911
+ def feature_lacp?
912
+ config_get('interface', 'feature_lacp')
913
+ end
914
+
915
+ def feature_lacp_set(val)
916
+ return if feature_lacp? == val
917
+ config_set('interface', 'feature_lacp', state: val ? '' : 'no')
918
+ end
919
+
920
+ def load_interval_counter_1_delay
921
+ return nil if @name[/loop/] || @name[/ethernet.*\S+\.\d+$/]
922
+ config_get('interface', 'load_interval_counter_1_delay', @get_args)
923
+ end
924
+
925
+ def load_interval_counter_1_delay=(val)
926
+ fail ArgumentError, 'Interface cannot be sub-intf or loopback' if
927
+ @name[/loop/] || @name[/ethernet.*\S+\.\d+$/]
928
+ config_set('interface', 'load_interval_counter_1_delay',
929
+ name: @name, delay: val)
930
+ end
931
+
932
+ def default_load_interval_counter_1_delay
933
+ # for vlan and bdi the default is 60
934
+ if @name[/(vlan|bdi)/i]
935
+ config_get_default('interface',
936
+ 'load_interval_counter_1_delay_vlan_bdi')
937
+ else
938
+ config_get_default('interface', 'load_interval_counter_1_delay')
939
+ end
940
+ end
941
+
942
+ def load_interval_counter_2_delay
943
+ return nil if @name[/loop/] || @name[/ethernet.*\S+\.\d+$/]
944
+ config_get('interface', 'load_interval_counter_2_delay', @get_args)
945
+ end
946
+
947
+ def load_interval_counter_2_delay=(val)
948
+ fail ArgumentError, 'Interface cannot be sub-intf or loopback' if
949
+ @name[/loop/] || @name[/ethernet.*\S+\.\d+$/]
950
+ config_set('interface', 'load_interval_counter_2_delay',
951
+ name: @name, delay: val)
952
+ end
953
+
954
+ def default_load_interval_counter_2_delay
955
+ config_get_default('interface', 'load_interval_counter_2_delay')
956
+ end
957
+
958
+ def load_interval_counter_3_delay
959
+ return nil if @name[/loop/] || @name[/ethernet.*\S+\.\d+$/]
960
+ config_get('interface', 'load_interval_counter_3_delay', @get_args)
961
+ end
962
+
963
+ def load_interval_counter_3_delay=(val)
964
+ fail ArgumentError, 'Interface cannot be sub-intf or loopback' if
965
+ @name[/loop/] || @name[/ethernet.*\S+\.\d+$/]
966
+ state = val ? '' : 'no'
967
+ delay = val ? val : ''
968
+ config_set('interface', 'load_interval_counter_3_delay',
969
+ name: @name, state: state, delay: delay)
970
+ end
971
+
972
+ def default_load_interval_counter_3_delay
973
+ config_get_default('interface', 'load_interval_counter_3_delay')
974
+ end
975
+
976
+ def mtu_lookup_string
977
+ case @name
978
+ when /loopback/i
979
+ return 'mtu_loopback'
980
+ else
981
+ return 'mtu_other_interfaces'
982
+ end
983
+ end
984
+
985
+ def mtu
986
+ config_get('interface', mtu_lookup_string, @get_args)
987
+ end
988
+
989
+ def mtu=(val)
990
+ return if mtu == val
991
+ check_switchport(:disabled)
992
+ config_set('interface', mtu_lookup_string,
993
+ name: @name, state: '', mtu: val)
994
+ end
995
+
996
+ def default_mtu
997
+ config_get_default('interface', mtu_lookup_string)
998
+ end
999
+
1000
+ def speed
1001
+ return nil if @name[/loop|vlan/i]
1002
+ config_get('interface', 'speed', @get_args)
1003
+ end
1004
+
1005
+ def speed=(val)
1006
+ config_set('interface', 'speed', name: @name, speed: val)
1007
+ end
1008
+
1009
+ def default_speed
1010
+ config_get_default('interface', 'speed')
1011
+ end
1012
+
1013
+ def duplex
1014
+ return nil if @name[/loop|vlan/i]
1015
+ config_get('interface', 'duplex', @get_args)
1016
+ end
1017
+
1018
+ def duplex=(val)
1019
+ config_set('interface', 'duplex', name: @name, duplex: val)
1020
+ end
1021
+
1022
+ def default_duplex
1023
+ config_get_default('interface', 'duplex')
1024
+ end
1025
+
1026
+ def negotiate_auto_lookup_string
1027
+ case @name
1028
+ when ETHERNET
1029
+ return 'negotiate_auto_ethernet'
1030
+ when PORTCHANNEL
1031
+ return 'negotiate_auto_portchannel'
1032
+ else
1033
+ return 'negotiate_auto_other_interfaces'
1034
+ end
1035
+ end
1036
+
1037
+ def negotiate_auto
1038
+ return nil if @name[/loop|vlan/]
1039
+ config_get('interface', negotiate_auto_lookup_string, @get_args)
1040
+ end
1041
+
1042
+ def negotiate_auto=(negotiate_auto)
1043
+ lookup = negotiate_auto_lookup_string
1044
+ no_cmd = (negotiate_auto ? '' : 'no')
1045
+ config_set('interface', lookup, name: @name, state: no_cmd)
1046
+ end
1047
+
1048
+ def default_negotiate_auto
1049
+ config_get_default('interface', negotiate_auto_lookup_string)
1050
+ end
1051
+
1052
+ def shutdown
1053
+ config_get('interface', 'shutdown', @get_args)
1054
+ end
1055
+
1056
+ def shutdown=(state)
1057
+ no_cmd = (state ? '' : 'no')
1058
+ config_set('interface', 'shutdown', name: @name, state: no_cmd)
1059
+ end
1060
+
1061
+ def default_shutdown
1062
+ case @name
1063
+ when ETHERNET
1064
+ def_sw = system_default_switchport
1065
+ def_shut = system_default_switchport_shutdown
1066
+
1067
+ if def_sw && def_shut
1068
+ lookup = 'shutdown_ethernet_switchport_shutdown'
1069
+ elsif def_sw && !def_shut
1070
+ lookup = 'shutdown_ethernet_switchport_noshutdown'
1071
+ elsif !def_sw && def_shut
1072
+ lookup = 'shutdown_ethernet_noswitchport_shutdown'
1073
+ elsif !def_sw && !def_shut
1074
+ lookup = 'shutdown_ethernet_noswitchport_noshutdown'
1075
+ else
1076
+ fail "Error: def_sw #{def_sw}, def_shut #{def_shut}"
1077
+ end
1078
+
1079
+ when /loopback/i
1080
+ lookup = 'shutdown_loopback'
1081
+
1082
+ when PORTCHANNEL
1083
+ lookup = 'shutdown_ether_channel'
1084
+
1085
+ when /Vlan/i
1086
+ lookup = 'shutdown_vlan'
1087
+
1088
+ else
1089
+ lookup = 'shutdown_unknown'
1090
+ end
1091
+ config_get_default('interface', lookup)
1092
+ end
1093
+
1094
+ def pim_bfd
1095
+ config_get('interface', 'pim_bfd', @get_args)
1096
+ end
1097
+
1098
+ def pim_bfd=(val)
1099
+ return if val == pim_bfd
1100
+ state = val ? '' : 'no'
1101
+ if val
1102
+ Feature.pim_enable
1103
+ Feature.bfd_enable
1104
+ end
1105
+ config_set('interface', 'pim_bfd', name: @name, state: state)
1106
+ end
1107
+
1108
+ def default_pim_bfd
1109
+ config_get_default('interface', 'pim_bfd')
1110
+ end
1111
+
1112
+ def storm_control_broadcast
1113
+ return nil if @name[/loop|vlan/i]
1114
+ config_get('interface', 'storm_control_broadcast', @get_args)
1115
+ end
1116
+
1117
+ def storm_control_broadcast=(val)
1118
+ return if val == storm_control_broadcast
1119
+ state = val == default_storm_control_broadcast ? 'no' : ''
1120
+ level = val == default_storm_control_broadcast ? '' : val
1121
+ config_set('interface', 'storm_control_broadcast',
1122
+ name: @name, state: state, level: level)
1123
+ end
1124
+
1125
+ def default_storm_control_broadcast
1126
+ config_get_default('interface', 'storm_control_broadcast')
1127
+ end
1128
+
1129
+ def storm_control_multicast
1130
+ return nil if @name[/loop|vlan/i]
1131
+ config_get('interface', 'storm_control_multicast', @get_args)
1132
+ end
1133
+
1134
+ def storm_control_multicast=(val)
1135
+ return if val == storm_control_multicast
1136
+ state = val == default_storm_control_multicast ? 'no' : ''
1137
+ level = val == default_storm_control_multicast ? '' : val
1138
+ config_set('interface', 'storm_control_multicast',
1139
+ name: @name, state: state, level: level)
1140
+ end
1141
+
1142
+ def default_storm_control_multicast
1143
+ config_get_default('interface', 'storm_control_multicast')
1144
+ end
1145
+
1146
+ def storm_control_unicast
1147
+ return nil if @name[/loop|vlan/i]
1148
+ config_get('interface', 'storm_control_unicast', @get_args)
1149
+ end
1150
+
1151
+ def storm_control_unicast=(val)
1152
+ return if val == storm_control_unicast
1153
+ state = val == default_storm_control_unicast ? 'no' : ''
1154
+ level = val == default_storm_control_unicast ? '' : val
1155
+ config_set('interface', 'storm_control_unicast',
1156
+ name: @name, state: state, level: level)
1157
+ end
1158
+
1159
+ def default_storm_control_unicast
1160
+ config_get_default('interface', 'storm_control_unicast')
1161
+ end
1162
+
1163
+ def stp_bpdufilter
1164
+ config_get('interface', 'stp_bpdufilter', @get_args)
1165
+ end
1166
+
1167
+ def stp_bpdufilter=(val)
1168
+ check_switchport([:access, :trunk])
1169
+ if val
1170
+ state = ''
1171
+ else
1172
+ state = 'no'
1173
+ val = ''
1174
+ end
1175
+ config_set('interface',
1176
+ 'stp_bpdufilter', name: @name, state: state, filter: val)
1177
+ end
1178
+
1179
+ def default_stp_bpdufilter
1180
+ config_get_default('interface', 'stp_bpdufilter')
1181
+ end
1182
+
1183
+ def stp_bpduguard
1184
+ config_get('interface', 'stp_bpduguard', @get_args)
1185
+ end
1186
+
1187
+ def stp_bpduguard=(val)
1188
+ if val
1189
+ state = ''
1190
+ else
1191
+ state = 'no'
1192
+ val = ''
1193
+ end
1194
+ config_set('interface',
1195
+ 'stp_bpduguard', name: @name, state: state, guard: val)
1196
+ end
1197
+
1198
+ def default_stp_bpduguard
1199
+ config_get_default('interface', 'stp_bpduguard')
1200
+ end
1201
+
1202
+ def stp_cost
1203
+ return nil if switchport_mode == :disabled
1204
+ cost = config_get('interface', 'stp_cost', @get_args)
1205
+ cost == 'auto' ? cost : cost.to_i
1206
+ end
1207
+
1208
+ def stp_cost=(val)
1209
+ check_switchport([:access, :trunk])
1210
+ config_set('interface', 'stp_cost', name: @name, cost: val)
1211
+ end
1212
+
1213
+ def default_stp_cost
1214
+ config_get_default('interface', 'stp_cost')
1215
+ end
1216
+
1217
+ def stp_guard
1218
+ config_get('interface', 'stp_guard', @get_args)
1219
+ end
1220
+
1221
+ def stp_guard=(val)
1222
+ check_switchport([:access, :trunk])
1223
+ if val
1224
+ state = ''
1225
+ else
1226
+ state = 'no'
1227
+ val = ''
1228
+ end
1229
+ config_set('interface', 'stp_guard', name: @name, state: state,
1230
+ guard: val)
1231
+ end
1232
+
1233
+ def default_stp_guard
1234
+ config_get_default('interface', 'stp_guard')
1235
+ end
1236
+
1237
+ def stp_link_type
1238
+ return nil if switchport_mode == :disabled
1239
+ config_get('interface', 'stp_link_type', @get_args)
1240
+ end
1241
+
1242
+ def stp_link_type=(val)
1243
+ check_switchport([:access, :trunk])
1244
+ config_set('interface', 'stp_link_type', name: @name, type: val)
1245
+ end
1246
+
1247
+ def default_stp_link_type
1248
+ config_get_default('interface', 'stp_link_type')
1249
+ end
1250
+
1251
+ def stp_port_priority
1252
+ return nil if switchport_mode == :disabled
1253
+ config_get('interface', 'stp_port_priority', @get_args)
1254
+ end
1255
+
1256
+ def stp_port_priority=(val)
1257
+ check_switchport([:access, :trunk])
1258
+ config_set('interface', 'stp_port_priority', name: @name, pp: val)
1259
+ end
1260
+
1261
+ def default_stp_port_priority
1262
+ config_get_default('interface', 'stp_port_priority')
1263
+ end
1264
+
1265
+ # Getter: Builds an array of mst cost commands currently
1266
+ # on the device.
1267
+ # cli: spanning-tree mst 0,2-4,6,8-12 cost 1000
1268
+ # spanning-tree mst 4000-4020 cost 2568
1269
+ # array: [['0,2-4,6,8-12', '1000'], ['4000-4020', '2568']]
1270
+ #
1271
+ def stp_mst_cost
1272
+ config_get('interface', 'stp_mst_cost', @get_args)
1273
+ end
1274
+
1275
+ def stp_mst_cost=(list)
1276
+ check_switchport([:access, :trunk])
1277
+ config_set('interface', 'stp_mst_cost',
1278
+ name: @name, state: 'no', range: @smr,
1279
+ val: '') if list.empty?
1280
+ set_range_based_params(list, 'stp_mst_cost')
1281
+ end
1282
+
1283
+ def default_stp_mst_cost
1284
+ config_get_default('interface', 'stp_mst_cost')
1285
+ end
1286
+
1287
+ # Getter: Builds an array of mst port-priority commands
1288
+ # currently on the device.
1289
+ # cli: spanning-tree mst 0,2-4,6,8-12 port-priority 64
1290
+ # spanning-tree mst 4000-4020 port-priority 160
1291
+ # array: [['0,2-4,6,8-12', '64'], ['4000-4020', '160']]
1292
+ #
1293
+ def stp_mst_port_priority
1294
+ config_get('interface', 'stp_mst_port_priority', @get_args)
1295
+ end
1296
+
1297
+ def stp_mst_port_priority=(list)
1298
+ check_switchport([:access, :trunk])
1299
+ config_set('interface', 'stp_mst_port_priority',
1300
+ name: @name, state: 'no', range: @smr,
1301
+ val: '') if list.empty?
1302
+ set_range_based_params(list, 'stp_mst_port_priority')
1303
+ end
1304
+
1305
+ def default_stp_mst_port_priority
1306
+ config_get_default('interface', 'stp_mst_port_priority')
1307
+ end
1308
+
1309
+ def stp_port_type
1310
+ config_get('interface', 'stp_port_type', @get_args)
1311
+ end
1312
+
1313
+ def stp_port_type=(val)
1314
+ if val
1315
+ state = ''
1316
+ else
1317
+ return unless stp_port_type
1318
+ state = 'no'
1319
+ val = stp_port_type
1320
+ end
1321
+ config_set('interface', 'stp_port_type', name: @name,
1322
+ state: state, type: val)
1323
+ end
1324
+
1325
+ def default_stp_port_type
1326
+ config_get_default('interface', 'stp_port_type')
1327
+ end
1328
+
1329
+ # Getter: Builds an array of vlan cost commands currently
1330
+ # on the device.
1331
+ # cli: spanning-tree vlan 1-4,6,8-12 cost 1000
1332
+ # spanning-tree vlan 3000-3960 cost 2568
1333
+ # array: [['1-4,6,8-12', '1000'], ['3000-3960', '2568']]
1334
+ #
1335
+ def stp_vlan_cost
1336
+ config_get('interface', 'stp_vlan_cost', @get_args)
1337
+ end
1338
+
1339
+ def stp_vlan_cost=(list)
1340
+ check_switchport([:access, :trunk])
1341
+ config_set('interface', 'stp_vlan_cost',
1342
+ name: @name, state: 'no',
1343
+ range: @svr, val: '') if list.empty?
1344
+ set_range_based_params(list, 'stp_vlan_cost')
1345
+ end
1346
+
1347
+ def default_stp_vlan_cost
1348
+ config_get_default('interface', 'stp_vlan_cost')
1349
+ end
1350
+
1351
+ # Getter: Builds an array of vlan port-priority commands
1352
+ # currently on the device.
1353
+ # cli: spanning-tree vlan 1-4,6,8-12 port-priority 64
1354
+ # spanning-tree vlan 3000-3960 port-priority 160
1355
+ # array: [['1-4,6,8-12', '64'], ['3000-3960', '160']]
1356
+ #
1357
+ def stp_vlan_port_priority
1358
+ config_get('interface', 'stp_vlan_port_priority', @get_args)
1359
+ end
1360
+
1361
+ def stp_vlan_port_priority=(list)
1362
+ check_switchport([:access, :trunk])
1363
+ config_set('interface', 'stp_vlan_port_priority',
1364
+ name: @name, state: 'no',
1365
+ range: @svr, val: '') if list.empty?
1366
+ set_range_based_params(list, 'stp_vlan_port_priority')
1367
+ end
1368
+
1369
+ def default_stp_vlan_port_priority
1370
+ config_get_default('interface', 'stp_vlan_port_priority')
1371
+ end
1372
+
1373
+ def switchport
1374
+ # This is "switchport", not "switchport mode"
1375
+ config_get('interface', 'switchport', @get_args)
1376
+ end
1377
+
1378
+ def switchport_enable(val=true)
1379
+ config_set('interface', 'switchport', name: @name, state: val ? '' : 'no')
1380
+ end
1381
+
1382
+ # switchport_autostate_exclude is exclusive to switchport interfaces
1383
+ def switchport_autostate_exclude
1384
+ return nil if switchport_mode == :disabled
1385
+ config_get('interface', 'switchport_autostate_exclude', @get_args)
1386
+ end
1387
+
1388
+ def switchport_autostate_exclude=(val)
1389
+ if platform == :nexus
1390
+ # cannot configure autostate unless feature vlan is enabled
1391
+ fail('switchport mode must be configured before ' \
1392
+ 'switchport autostate') unless switchport
1393
+ feature_vlan_set(true)
1394
+ end
1395
+ config_set('interface', 'switchport_autostate_exclude',
1396
+ name: @name, state: val ? '' : 'no')
1397
+ end
1398
+
1399
+ def default_switchport_autostate_exclude
1400
+ config_get_default('interface', 'switchport_autostate_exclude')
1401
+ end
1402
+
1403
+ def switchport_mode_lookup_string
1404
+ case @name
1405
+ when ETHERNET
1406
+ return 'switchport_mode_ethernet'
1407
+ when PORTCHANNEL
1408
+ return 'switchport_mode_port_channel'
1409
+ else
1410
+ return 'switchport_mode_other_interfaces'
1411
+ end
1412
+ end
1413
+
1414
+ def switchport_mode
1415
+ return nil if platform == :ios_xr
1416
+ mode = config_get('interface', switchport_mode_lookup_string, @get_args)
1417
+
1418
+ return mode.nil? ? :disabled : IF_SWITCHPORT_MODE.key(mode)
1419
+
1420
+ rescue IndexError
1421
+ # Assume this is an interface that doesn't support switchport.
1422
+ # Do not raise exception since the providers will prefetch this property
1423
+ # regardless of interface type.
1424
+ # TODO: this should probably be nil instead
1425
+ return :disabled
1426
+ end
1427
+
1428
+ def switchport_enable_and_mode(mode_set)
1429
+ switchport_enable
1430
+
1431
+ if :fabricpath == mode_set
1432
+ fabricpath_feature_set(:enabled) unless :enabled == fabricpath_feature
1433
+ elsif :fex_fabric == mode_set
1434
+ Feature.fex_enable
1435
+ end
1436
+ config_set('interface', switchport_mode_lookup_string,
1437
+ name: @name, state: '', mode: IF_SWITCHPORT_MODE[mode_set])
1438
+ end
1439
+
1440
+ def switchport_mode=(mode_set)
1441
+ # no system default switchport
1442
+ # int e1/1
1443
+ # switchport
1444
+ # switchport mode [access|trunk|fex|...]
1445
+ fail ArgumentError unless IF_SWITCHPORT_MODE.keys.include? mode_set
1446
+ case mode_set
1447
+ when :disabled
1448
+ if switchport
1449
+ # Note: turn off switchport command, not switchport mode
1450
+ config_set('interface', 'switchport', name: @name, state: 'no')
1451
+ end
1452
+
1453
+ when :default
1454
+ if :disabled == default_switchport_mode
1455
+ config_set('interface', switchport_mode_lookup_string,
1456
+ name: @name, state: 'no', mode: '')
1457
+ else
1458
+ switchport_enable_and_mode(mode_set)
1459
+ end
1460
+
1461
+ else
1462
+ switchport_enable_and_mode(mode_set)
1463
+ end # case
1464
+ end
1465
+
1466
+ def default_switchport_mode
1467
+ return nil if platform == :ios_xr
1468
+ return :disabled unless system_default_switchport
1469
+ IF_SWITCHPORT_MODE.key(
1470
+ config_get_default('interface', switchport_mode_lookup_string))
1471
+ end
1472
+
1473
+ def switchport_trunk_allowed_vlan
1474
+ return nil if switchport_mode == :disabled
1475
+ vlans = config_get('interface', 'switchport_trunk_allowed_vlan',
1476
+ @get_args)
1477
+ vlans = vlans.join(',') if vlans.is_a?(Array)
1478
+ vlans = Utils.normalize_range_array(vlans, :string) unless vlans == 'none'
1479
+ vlans
1480
+ end
1481
+
1482
+ def switchport_trunk_allowed_vlan=(val)
1483
+ if val.nil?
1484
+ config_set('interface', 'switchport_trunk_allowed_vlan',
1485
+ name: @name, state: 'no', vlan: '')
1486
+ else
1487
+ config_set('interface', 'switchport_trunk_allowed_vlan',
1488
+ name: @name, state: '', vlan: val)
1489
+ end
1490
+ end
1491
+
1492
+ def default_switchport_trunk_allowed_vlan
1493
+ config_get_default('interface', 'switchport_trunk_allowed_vlan')
1494
+ end
1495
+
1496
+ def switchport_trunk_native_vlan
1497
+ return nil if switchport_mode == :disabled
1498
+ config_get('interface', 'switchport_trunk_native_vlan', @get_args)
1499
+ end
1500
+
1501
+ def switchport_trunk_native_vlan=(val)
1502
+ if val.nil?
1503
+ config_set('interface', 'switchport_trunk_native_vlan',
1504
+ name: @name, state: 'no', vlan: '')
1505
+ else
1506
+ config_set('interface', 'switchport_trunk_native_vlan',
1507
+ name: @name, state: '', vlan: val)
1508
+ end
1509
+ end
1510
+
1511
+ # --------------------------
1512
+ def cli_error_check(result)
1513
+ # Check for messages that can be safely ignored.
1514
+ # The NXOS interface private-vlan cli does not raise an exception
1515
+ # in some conditions and instead just displays a STDOUT error message
1516
+ # thus NXAPI does not detect the failure.
1517
+ # We must catch it by inspecting the "body" hash entry returned by NXAPI.
1518
+ # This vlan cli behavior is unlikely to change.
1519
+
1520
+ errors = /(ERROR:|VLAN:|Eth)/
1521
+ return unless
1522
+ result[1].is_a?(Hash) && errors.match(result[1]['body'].to_s)
1523
+ # Split errors into a list, but keep the delimiter as part of the message.
1524
+ error_list =
1525
+ (result[1]['body'].split(errors) - ['']).each_slice(2).map(&:join)
1526
+ error_list.each do |_msg|
1527
+ fail result[1]['body']
1528
+ end
1529
+ end
1530
+
1531
+ # --------------------------
1532
+ # <state> switchport mode private-vlan host
1533
+ def switchport_pvlan_host
1534
+ return nil if switchport_mode == :disabled
1535
+ config_get('interface', 'switchport_pvlan_host', @get_args)
1536
+ end
1537
+
1538
+ def switchport_pvlan_host=(state)
1539
+ pvlan_enable
1540
+ config_set('interface', 'switchport_pvlan_host',
1541
+ name: @name, state: state ? '' : 'no')
1542
+ end
1543
+
1544
+ def default_switchport_pvlan_host
1545
+ config_get_default('interface', 'switchport_pvlan_host')
1546
+ end
1547
+
1548
+ # --------------------------
1549
+ # <state> switchport mode private-vlan promiscuous
1550
+ def switchport_pvlan_promiscuous
1551
+ return nil if switchport_mode == :disabled
1552
+ config_get('interface', 'switchport_pvlan_promiscuous', @get_args)
1553
+ end
1554
+
1555
+ def switchport_pvlan_promiscuous=(state)
1556
+ pvlan_enable
1557
+ config_set('interface', 'switchport_pvlan_promiscuous',
1558
+ name: @name, state: state ? '' : 'no')
1559
+ end
1560
+
1561
+ def default_switchport_pvlan_promiscuous
1562
+ config_get_default('interface', 'switchport_pvlan_promiscuous')
1563
+ end
1564
+
1565
+ # --------------------------
1566
+ # <state> switchport private-vlan host-association <pri> <sec>
1567
+ # Note this is NOT a multiple, unlike trunk association.
1568
+ def switchport_pvlan_host_association
1569
+ config_get('interface', 'switchport_pvlan_host_association', @get_args)
1570
+ end
1571
+
1572
+ # Input: An array of primary and secondary vlans: ['44', '244']
1573
+ def switchport_pvlan_host_association=(pri_and_sec)
1574
+ pvlan_enable
1575
+
1576
+ state = pri_and_sec.empty? ? 'no' : ''
1577
+ pri, sec = pri_and_sec
1578
+ cli_error_check(
1579
+ config_set('interface', 'switchport_pvlan_host_association',
1580
+ name: @name, state: state, pri: pri, sec: sec))
1581
+ end
1582
+
1583
+ def default_switchport_pvlan_host_association
1584
+ config_get_default('interface', 'switchport_pvlan_host_association')
1585
+ end
1586
+
1587
+ # --------------------------
1588
+ # <state> switchport private-vlan mapping <primary> <vlan>
1589
+ def switchport_pvlan_mapping
1590
+ config_get('interface', 'switchport_pvlan_mapping', @get_args)
1591
+ end
1592
+
1593
+ # Input: An array of primary vlan and range of vlans: ['44', '3-4,6']
1594
+ def switchport_pvlan_mapping=(primary_and_range)
1595
+ switchport_pvlan_mapping_delta(primary_and_range)
1596
+ end
1597
+
1598
+ def default_switchport_pvlan_mapping
1599
+ config_get_default('interface', 'switchport_pvlan_mapping')
1600
+ end
1601
+
1602
+ # --------------------------
1603
+ # Find the is/should delta and add/remove commands as needed.
1604
+ #
1605
+ # Inputs:
1606
+ # primary_and_range: An array of primary vlan and range of vlans
1607
+ def switchport_pvlan_mapping_delta(primary_and_range)
1608
+ # Enable switchport mode and feature private-vlan
1609
+ pvlan_enable
1610
+ primary, should_range = primary_and_range
1611
+
1612
+ # primary changes require removing the entire command first
1613
+ is_range = switchport_pvlan_mapping_remove?(primary)
1614
+
1615
+ # convert ranges to individual elements
1616
+ is = Utils.dash_range_to_elements(is_range)
1617
+ should = Utils.dash_range_to_elements(should_range)
1618
+
1619
+ # create the delta hash and apply the changes
1620
+ delta_hash = Utils.delta_add_remove(should, is)
1621
+ Cisco::Logger.debug('switchport_pvlan_mapping_delta: '\
1622
+ "#{primary}: #{delta_hash}")
1623
+ [:add, :remove].each do |action|
1624
+ delta_hash[action].each do |vlan|
1625
+ state = (action == :add) ? '' : 'no'
1626
+ cli_error_check(
1627
+ config_set('interface', 'switchport_pvlan_mapping',
1628
+ name: @name, state: state, primary: primary, vlan: vlan))
1629
+ end
1630
+ end
1631
+ end
1632
+
1633
+ # --------------------------
1634
+ # switchport_pvlan_mapping_remove?
1635
+ # This is a helper to check if command needs to be removed entirely.
1636
+ #
1637
+ # should_primary: the new primary vlan value
1638
+ # Returns: the current vlan range
1639
+ def switchport_pvlan_mapping_remove?(should_primary)
1640
+ is_primary, is_range = switchport_pvlan_mapping
1641
+
1642
+ if (is_primary != should_primary) && !is_primary.nil?
1643
+ cli_error_check(
1644
+ config_set('interface', 'switchport_pvlan_mapping',
1645
+ name: @name, state: 'no', primary: '', vlan: ''))
1646
+ is_range = []
1647
+ end
1648
+ is_range
1649
+ end
1650
+
1651
+ # --------------------------
1652
+ # <state> switchport private-vlan mapping trunk <primary> <vlan>
1653
+ def switchport_pvlan_mapping_trunk
1654
+ config_get('interface', 'switchport_pvlan_mapping_trunk', @get_args)
1655
+ end
1656
+
1657
+ # Input: A nested array of primary vlan and range of vlans:
1658
+ # [['44', '3-4,6'], ['99', '199']]
1659
+ def switchport_pvlan_mapping_trunk=(should)
1660
+ switchport_pvlan_mapping_trunk_delta(should)
1661
+ end
1662
+
1663
+ def default_switchport_pvlan_mapping_trunk
1664
+ config_get_default('interface', 'switchport_pvlan_mapping_trunk')
1665
+ end
1666
+
1667
+ # --------------------------
1668
+ # switchport_pvlan_mapping_trunk_delta(should)
1669
+ #
1670
+ # Find the is/should delta and add/remove commands as needed.
1671
+ # The 'should' value is a nested array of primary vlan and secondary
1672
+ # ranges; e.g.:
1673
+ # [['44', '144-145'], ['99', '199-201']
1674
+ #
1675
+ def switchport_pvlan_mapping_trunk_delta(should)
1676
+ # Enable switchport mode and feature private-vlan
1677
+ pvlan_enable
1678
+
1679
+ # Handle single-level arrays if found: [pri, range] -> [[pri,range]]
1680
+ should = [should] if !should.empty? && (Utils.depth(should) == 1)
1681
+
1682
+ is = switchport_pvlan_mapping_trunk
1683
+ delta_hash = Utils.delta_add_remove(should, is, :updates_not_allowed)
1684
+ Cisco::Logger.debug("switchport_pvlan_mapping_trunk_delta: #{delta_hash}")
1685
+ [:remove, :add].each do |action|
1686
+ delta_hash[action].each do |pri_and_range|
1687
+ pri, range = pri_and_range
1688
+ if action == :add
1689
+ state = ''
1690
+ else
1691
+ state = 'no'
1692
+ range = ''
1693
+ end
1694
+ cli_error_check(
1695
+ config_set('interface', 'switchport_pvlan_mapping_trunk',
1696
+ name: @name, state: state, primary: pri, range: range))
1697
+ end
1698
+ end
1699
+ end
1700
+
1701
+ # --------------------------
1702
+ # <state> switchport private-vlan association trunk <pri> <sec>
1703
+ # Supports multiple.
1704
+ def switchport_pvlan_trunk_association
1705
+ config_get('interface', 'switchport_pvlan_trunk_association', @get_args)
1706
+ end
1707
+
1708
+ # Input: A nested array of primary and secondary vlans:
1709
+ # [['44', '244'], ['99', '299']]
1710
+ def switchport_pvlan_trunk_association=(should)
1711
+ pvlan_enable
1712
+
1713
+ # Handle single-level arrays if found: [pri, sec] -> [[pri,sec]]
1714
+ should = [should] if !should.empty? && (Utils.depth(should) == 1)
1715
+
1716
+ is = switchport_pvlan_trunk_association
1717
+ pvlan_trunk_association_delta(is, should)
1718
+ end
1719
+
1720
+ def pvlan_trunk_association_delta(is, should)
1721
+ delta_hash = Utils.delta_add_remove(should, is)
1722
+ Cisco::Logger.debug("pvlan_trunk_association_delta: #{delta_hash}")
1723
+ [:remove, :add].each do |action|
1724
+ delta_hash[action].each do |pri_and_sec|
1725
+ state = (action == :add) ? '' : 'no'
1726
+ pri, sec = pri_and_sec
1727
+
1728
+ # Cli does not like removals that specify the secondary
1729
+ sec = '' if action[/remove/]
1730
+ cli_error_check(
1731
+ config_set('interface', 'switchport_pvlan_trunk_association',
1732
+ name: @name, state: state, pri: pri, sec: sec))
1733
+ end
1734
+ end
1735
+ end
1736
+
1737
+ def default_switchport_pvlan_trunk_association
1738
+ config_get_default('interface', 'switchport_pvlan_trunk_association')
1739
+ end
1740
+
1741
+ # --------------------------
1742
+ # <state> switchport mode private-vlan trunk promiscuous
1743
+ def switchport_pvlan_trunk_promiscuous
1744
+ return nil if switchport_mode == :disabled
1745
+ config_get('interface', 'switchport_pvlan_trunk_promiscuous', @get_args)
1746
+ end
1747
+
1748
+ def switchport_pvlan_trunk_promiscuous=(state)
1749
+ pvlan_enable
1750
+ config_set('interface', 'switchport_pvlan_trunk_promiscuous',
1751
+ name: @name, state: state ? '' : 'no')
1752
+ end
1753
+
1754
+ def default_switchport_pvlan_trunk_promiscuous
1755
+ config_get_default('interface', 'switchport_pvlan_trunk_promiscuous')
1756
+ end
1757
+
1758
+ # --------------------------
1759
+ # <state> switchport mode private-vlan trunk secondary
1760
+ def switchport_pvlan_trunk_secondary
1761
+ return nil if switchport_mode == :disabled
1762
+ config_get('interface', 'switchport_pvlan_trunk_secondary', @get_args)
1763
+ end
1764
+
1765
+ def switchport_pvlan_trunk_secondary=(state)
1766
+ pvlan_enable
1767
+ config_set('interface', 'switchport_pvlan_trunk_secondary',
1768
+ name: @name, state: state ? '' : 'no')
1769
+ end
1770
+
1771
+ def default_switchport_pvlan_trunk_secondary
1772
+ config_get_default('interface', 'switchport_pvlan_trunk_secondary')
1773
+ end
1774
+
1775
+ # --------------------------
1776
+ # <state> switchport private-vlan trunk allowed vlan <range>
1777
+ # Note that range is handled as a string because the entire range is
1778
+ # replaced instead of individually adding or removing vlans from the range.
1779
+ def switchport_pvlan_trunk_allowed_vlan
1780
+ return nil if switchport_mode == :disabled
1781
+ vlans = config_get('interface', 'switchport_pvlan_trunk_allowed_vlan',
1782
+ @get_args)
1783
+ vlans = vlans.join(',') if vlans.is_a?(Array)
1784
+ vlans = Utils.normalize_range_array(vlans, :string) unless vlans == 'none'
1785
+ vlans
1786
+ end
1787
+
1788
+ def switchport_pvlan_trunk_allowed_vlan=(range)
1789
+ pvlan_enable
1790
+
1791
+ range = Utils.normalize_range_array(range, :string) unless
1792
+ range == default_switchport_pvlan_trunk_allowed_vlan
1793
+
1794
+ config_set('interface', 'switchport_pvlan_trunk_allowed_vlan',
1795
+ name: @name, range: range)
1796
+ end
1797
+
1798
+ def default_switchport_pvlan_trunk_allowed_vlan
1799
+ config_get_default('interface', 'switchport_pvlan_trunk_allowed_vlan')
1800
+ end
1801
+
1802
+ # --------------------------
1803
+ # <state> switchport trunk native vlan <vlan>
1804
+ def switchport_pvlan_trunk_native_vlan
1805
+ return nil if switchport_mode == :disabled
1806
+ config_get('interface', 'switchport_pvlan_trunk_native_vlan', @get_args)
1807
+ end
1808
+
1809
+ def switchport_pvlan_trunk_native_vlan=(vlan)
1810
+ pvlan_enable
1811
+ config_set('interface', 'switchport_pvlan_trunk_native_vlan',
1812
+ name: @name, vlan: vlan)
1813
+ end
1814
+
1815
+ def default_switchport_pvlan_trunk_native_vlan
1816
+ config_get_default('interface', 'switchport_pvlan_trunk_native_vlan')
1817
+ end
1818
+
1819
+ # --------------------------
1820
+ # This is an SVI property.
1821
+ # <state> private-vlan mapping <range> # ex. range = ['2-4,9']
1822
+ # Always returns an array.
1823
+ def pvlan_mapping
1824
+ range = config_get('interface', 'pvlan_mapping', @get_args)
1825
+ return default_pvlan_mapping if range.nil?
1826
+ range.empty? ? range : [range.delete(' ')]
1827
+ end
1828
+
1829
+ def pvlan_mapping=(range)
1830
+ feature_vlan_set
1831
+ Feature.private_vlan_enable
1832
+
1833
+ is = Utils.dash_range_to_elements(pvlan_mapping)
1834
+ should = Utils.dash_range_to_elements(range)
1835
+
1836
+ pvlan_mapping_delta(is, should)
1837
+ end
1838
+
1839
+ def pvlan_mapping_delta(is, should)
1840
+ delta_hash = Utils.delta_add_remove(should, is)
1841
+ Cisco::Logger.debug("pvlan_mapping_delta: #{delta_hash}")
1842
+ [:remove, :add].each do |action|
1843
+ delta_hash[action].each do |vlan|
1844
+ state = (action == :add) ? '' : 'no'
1845
+ cli_error_check(
1846
+ config_set('interface', 'pvlan_mapping',
1847
+ name: @name, state: state, vlan: vlan))
1848
+ end
1849
+ end
1850
+ end
1851
+
1852
+ def default_pvlan_mapping
1853
+ config_get_default('interface', 'pvlan_mapping')
1854
+ end
1855
+
1856
+ # --------------------------
1857
+ # vlan_mapping & vlan_mapping_enable
1858
+ # Hardware & Cli Dependencies:
1859
+ # - F3 linecards only
1860
+ # - vdc
1861
+ # - limit-resource
1862
+ # - bridge-domain
1863
+ # - feature vni
1864
+ # - switchport mode
1865
+
1866
+ # Getter: Builds an array of vlan_mapping commands currently
1867
+ # on the device.
1868
+ # cli: switchport vlan mapping 2 200
1869
+ # switchport vlan mapping 4 400
1870
+ # array: [['2', '200'], ['4', '400']]
1871
+ #
1872
+ def default_vlan_mapping
1873
+ config_get_default('interface', 'vlan_mapping')
1874
+ end
1875
+
1876
+ def vlan_mapping
1877
+ match = config_get('interface', 'vlan_mapping', @get_args)
1878
+ match.each(&:compact!) unless match.nil?
1879
+ match
1880
+ end
1881
+
1882
+ def vlan_mapping=(should_list)
1883
+ Feature.vni_enable
1884
+
1885
+ # Process a hash of vlan_mapping cmds from delta_add_remove().
1886
+ # The vlan_mapping cli does not allow commands to be updated, they must
1887
+ # first be removed if there is a change.
1888
+ delta_hash = Utils.delta_add_remove(should_list, vlan_mapping,
1889
+ :updates_not_allowed)
1890
+ return if delta_hash.values.flatten.empty?
1891
+ # Process :remove first to ensure "update" commands will not fail.
1892
+ [:remove, :add].each do |action|
1893
+ Cisco::Logger.debug("vlan_mapping delta #{@get_args}\n"\
1894
+ "#{action}: #{delta_hash[action]}")
1895
+ delta_hash[action].each do |original, translated|
1896
+ state = (action == :add) ? '' : 'no'
1897
+ config_set('interface', 'vlan_mapping', name: @name,
1898
+ state: state, original: original, translated: translated)
1899
+ end
1900
+ end
1901
+ end
1902
+
1903
+ # cli: switchport vlan mapping enable
1904
+ def default_vlan_mapping_enable
1905
+ config_get_default('interface', 'vlan_mapping_enable')
1906
+ end
1907
+
1908
+ def vlan_mapping_enable
1909
+ config_get('interface', 'vlan_mapping_enable', @get_args)
1910
+ end
1911
+
1912
+ def vlan_mapping_enable=(state)
1913
+ config_set('interface', 'vlan_mapping_enable',
1914
+ name: @name, state: state ? '' : 'no')
1915
+ end
1916
+
1917
+ def default_switchport_trunk_native_vlan
1918
+ config_get_default('interface', 'switchport_trunk_native_vlan')
1919
+ end
1920
+
1921
+ def system_default_switchport
1922
+ # This command is a user-configurable system default.
1923
+ #
1924
+ # Note: This is a simple boolean state but there is a bug on some
1925
+ # platforms that causes the cli to nvgen twice; this causes config_get to
1926
+ # raise an error when it encounters the multiple. Therefore we define it
1927
+ # as a multiple to avoid the raise and handle the array if necessary.
1928
+ #
1929
+ val = config_get('interface', 'system_default_switchport')
1930
+ return (val[0][/^no /] ? false : true) if val.is_a?(Array)
1931
+ val
1932
+ end
1933
+
1934
+ def system_default_switchport_shutdown
1935
+ # This command is a user-configurable system default.
1936
+ config_get('interface', 'system_default_switchport_shutdown')
1937
+ end
1938
+
1939
+ def system_default_svi_autostate
1940
+ # This command is a user-configurable system default.
1941
+ #
1942
+ # This property behaves differently on an n7k vs ni(3|9)k and therefore
1943
+ # needs special handling.
1944
+ # N7K: When enabled, does not nvgen.
1945
+ # When disabled, does nvgen, but differently then n(3|9)k.
1946
+ # Return true for the disabled case, false otherwise.
1947
+ # N(3|9)K: When enabled, does nvgen.
1948
+ # When disabled, does nvgen.
1949
+ # Return true for the enabled case, false otherwise.
1950
+ result = config_get('interface', 'system_default_svi_autostate')
1951
+ /N7K/.match(node.product_id) ? !result : result
1952
+ end
1953
+
1954
+ def switchport_vtp_mode_capable?
1955
+ !switchport_mode.to_s.match(/(access|trunk)/).nil?
1956
+ end
1957
+
1958
+ def switchport_vtp
1959
+ return nil unless switchport_vtp_mode_capable?
1960
+ config_get('interface', 'vtp', @get_args)
1961
+ end
1962
+
1963
+ def switchport_vtp=(vtp_set)
1964
+ # TODO: throw UnsupportedError instead of returning false?
1965
+ return false unless switchport_vtp_mode_capable?
1966
+ return false if !vtp_set && !Feature.vtp_enabled?
1967
+ Feature.vtp_enable if vtp_set
1968
+ no_cmd = (vtp_set) ? '' : 'no'
1969
+ config_set('interface', 'vtp', name: @name, state: no_cmd)
1970
+ end
1971
+
1972
+ def svi_cmd_allowed?(cmd)
1973
+ fail "[#{@name}] Invalid interface type for command [#{cmd}]" unless
1974
+ @name[/vlan/i]
1975
+ end
1976
+
1977
+ # svi_autostate is exclusive to svi interfaces
1978
+ def svi_autostate
1979
+ return nil unless @name[/^vlan/i]
1980
+ config_get('interface', 'svi_autostate', @get_args)
1981
+ end
1982
+
1983
+ def svi_autostate=(val)
1984
+ check_switchport(:disabled)
1985
+ svi_cmd_allowed?('autostate')
1986
+ config_set('interface', 'svi_autostate',
1987
+ name: @name, state: val ? '' : 'no')
1988
+ end
1989
+
1990
+ def default_svi_autostate
1991
+ system_default_svi_autostate
1992
+ end
1993
+
1994
+ def feature_vlan?
1995
+ config_get('interface', 'feature_vlan')
1996
+ end
1997
+
1998
+ def feature_vlan_set(val=true)
1999
+ # 'feature interface-vlan'
2000
+ # TBD: Replace this with Feature.interface_vlan_enable
2001
+ return if feature_vlan? == val
2002
+ config_set('interface', 'feature_vlan', state: val ? '' : 'no')
2003
+ end
2004
+
2005
+ # svi_management is exclusive to svi interfaces
2006
+ def svi_management
2007
+ return nil unless @name[/^vlan/i]
2008
+ config_get('interface', 'svi_management', @get_args)
2009
+ end
2010
+
2011
+ def svi_management=(val)
2012
+ check_switchport(:disabled)
2013
+ svi_cmd_allowed?('management')
2014
+ config_set('interface', 'svi_management',
2015
+ name: @name, state: val ? '' : 'no')
2016
+ end
2017
+
2018
+ def default_svi_management
2019
+ config_get_default('interface', 'svi_management')
2020
+ end
2021
+
2022
+ def default_switchport_vtp
2023
+ return nil unless switchport_vtp_mode_capable?
2024
+ config_get_default('interface', 'vtp')
2025
+ end
2026
+
2027
+ def switchport_vtp_feature?
2028
+ config_get('vtp', 'feature')
2029
+ end
2030
+
2031
+ def switchport_status?(status)
2032
+ case status
2033
+ when :disabled
2034
+ return true if switchport_mode == status || switchport_mode.nil?
2035
+ when :access, :trunk
2036
+ return switchport_mode == status
2037
+ when Array
2038
+ return status.include?(switchport_mode)
2039
+ else
2040
+ return false
2041
+ end
2042
+ end
2043
+
2044
+ def check_switchport(status)
2045
+ return if switchport_status?(status)
2046
+ fail("#{caller[0][/`.*'/][1..-2]} cannot be set unless " \
2047
+ "switchport mode is #{status}")
2048
+ end
2049
+
2050
+ def vpc_id
2051
+ config_get('interface', 'vpc_id', @get_args)
2052
+ end
2053
+
2054
+ def vpc_id=(num)
2055
+ if num
2056
+ config_set('interface', 'vpc_id', name: @name, state: '', id: num)
2057
+ else
2058
+ # 'no vpc' doesn't work for phy ports, so do a get
2059
+ num = vpc_id
2060
+ config_set('interface', 'vpc_id', name: @name, state: 'no', id: num)
2061
+ end
2062
+ end
2063
+
2064
+ def default_vpc_id
2065
+ config_get_default('interface', 'vpc_id')
2066
+ end
2067
+
2068
+ def vpc_peer_link
2069
+ return nil unless @name[/port-channel/i] && switchport_mode != :disabled
2070
+ config_get('interface', 'vpc_peer_link', @get_args)
2071
+ end
2072
+
2073
+ def vpc_peer_link=(state)
2074
+ return if vpc_peer_link == state
2075
+ no_cmd = (state ? '' : 'no')
2076
+ config_set('interface', 'vpc_peer_link', name: @name, state: no_cmd)
2077
+ end
2078
+
2079
+ def default_vpc_peer_link
2080
+ config_get_default('interface', 'vpc_peer_link')
2081
+ end
2082
+
2083
+ def vrf
2084
+ config_get('interface', 'vrf', @get_args)
2085
+ end
2086
+
2087
+ def vrf=(v)
2088
+ fail TypeError unless v.is_a?(String)
2089
+ return if v == vrf
2090
+ # Changing the VRF can result in loss of IP address, so cache it
2091
+ addr_1 = ipv4_address
2092
+ mask_1 = ipv4_netmask_length
2093
+ addr_2 = ipv4_address_secondary
2094
+ mask_2 = ipv4_netmask_length_secondary
2095
+ # XR actually blocks you from changing the VRF if IP addr is present
2096
+ unless platform == :nexus
2097
+ ipv4_addr_mask_set(nil, nil, false) unless addr_1.nil?
2098
+ ipv4_addr_mask_set(nil, nil, true) unless addr_2.nil?
2099
+ end
2100
+ if v.empty?
2101
+ config_set('interface', 'vrf', name: @name, state: 'no', vrf: '')
2102
+ else
2103
+ config_set('interface', 'vrf', name: @name, state: '', vrf: v)
2104
+ end
2105
+ ipv4_addr_mask_set(addr_1, mask_1, false) unless addr_1.nil?
2106
+ ipv4_addr_mask_set(addr_2, mask_2, true) unless addr_2.nil?
2107
+ end
2108
+
2109
+ def default_vrf
2110
+ config_get_default('interface', 'vrf')
2111
+ end
2112
+
2113
+ def set_range_based_params(list, param_name)
2114
+ list.each do |range, property_value|
2115
+ # if a particular range is set to default, use 'no' cmd
2116
+ if property_value == 'default'
2117
+ config_set('interface', param_name,
2118
+ name: @name, state: 'no',
2119
+ range: range, val: '')
2120
+ else
2121
+ config_set('interface', param_name,
2122
+ name: @name, state: '',
2123
+ range: range, val: property_value)
2124
+ end
2125
+ end
2126
+ end
2127
+ end # Class
2128
+ end # Module