cisco_node_utils 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (202) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -1
  3. data/CHANGELOG.md +126 -1
  4. data/README.md +19 -12
  5. data/Rakefile +1 -0
  6. data/bin/git/hooks/commit-msg/enforce_style +8 -0
  7. data/cisco_node_utils.gemspec +4 -3
  8. data/docs/README-develop-best-practices.md +127 -109
  9. data/docs/README-develop-node-utils-APIs.md +47 -39
  10. data/docs/template-router.rb +3 -7
  11. data/lib/.rubocop.yml +4 -4
  12. data/lib/cisco_node_utils.rb +1 -1
  13. data/lib/cisco_node_utils/aaa_authentication_login.rb +96 -0
  14. data/lib/cisco_node_utils/aaa_authentication_login_service.rb +133 -0
  15. data/lib/cisco_node_utils/aaa_authorization_service.rb +150 -0
  16. data/lib/cisco_node_utils/ace.rb +196 -0
  17. data/lib/cisco_node_utils/acl.rb +100 -0
  18. data/lib/cisco_node_utils/bgp.rb +301 -163
  19. data/lib/cisco_node_utils/bgp_af.rb +187 -19
  20. data/lib/cisco_node_utils/bgp_neighbor.rb +18 -33
  21. data/lib/cisco_node_utils/bgp_neighbor_af.rb +25 -48
  22. data/lib/cisco_node_utils/cisco_cmn_utils.rb +23 -4
  23. data/lib/cisco_node_utils/cmd_ref/README_YAML.md +593 -0
  24. data/lib/cisco_node_utils/cmd_ref/aaa_auth_login_service.yaml +22 -0
  25. data/lib/cisco_node_utils/cmd_ref/aaa_authentication_login.yaml +31 -0
  26. data/lib/cisco_node_utils/cmd_ref/aaa_authorization_service.yaml +22 -0
  27. data/lib/cisco_node_utils/cmd_ref/acl.yaml +43 -0
  28. data/lib/cisco_node_utils/cmd_ref/bgp.yaml +242 -0
  29. data/lib/cisco_node_utils/cmd_ref/bgp_af.yaml +164 -0
  30. data/lib/cisco_node_utils/cmd_ref/bgp_neighbor.yaml +131 -0
  31. data/lib/cisco_node_utils/cmd_ref/bgp_neighbor_af.yaml +179 -0
  32. data/lib/cisco_node_utils/cmd_ref/dnsclient.yaml +34 -0
  33. data/lib/cisco_node_utils/cmd_ref/evpn_vni.yaml +42 -0
  34. data/lib/cisco_node_utils/cmd_ref/fabricpath.yaml +172 -0
  35. data/lib/cisco_node_utils/cmd_ref/fabricpath_topology.yaml +35 -0
  36. data/lib/cisco_node_utils/cmd_ref/feature.yaml +42 -0
  37. data/lib/cisco_node_utils/cmd_ref/fex.yaml +9 -0
  38. data/lib/cisco_node_utils/cmd_ref/images.yaml +7 -0
  39. data/lib/cisco_node_utils/cmd_ref/interface.yaml +339 -0
  40. data/lib/cisco_node_utils/cmd_ref/interface_channel_group.yaml +28 -0
  41. data/lib/cisco_node_utils/cmd_ref/interface_ospf.yaml +61 -0
  42. data/lib/cisco_node_utils/cmd_ref/interface_portchannel.yaml +54 -0
  43. data/lib/cisco_node_utils/cmd_ref/interface_service_vni.yaml +32 -0
  44. data/lib/cisco_node_utils/cmd_ref/inventory.yaml +45 -0
  45. data/lib/cisco_node_utils/cmd_ref/memory.yaml +13 -0
  46. data/lib/cisco_node_utils/cmd_ref/ntp_config.yaml +7 -0
  47. data/lib/cisco_node_utils/cmd_ref/ntp_server.yaml +14 -0
  48. data/lib/cisco_node_utils/cmd_ref/ospf.yaml +74 -0
  49. data/lib/cisco_node_utils/cmd_ref/overlay_global.yaml +33 -0
  50. data/lib/cisco_node_utils/cmd_ref/pim.yaml +40 -0
  51. data/lib/cisco_node_utils/cmd_ref/portchannel_global.yaml +69 -0
  52. data/lib/cisco_node_utils/cmd_ref/radius_global.yaml +25 -0
  53. data/lib/cisco_node_utils/cmd_ref/radius_server.yaml +64 -0
  54. data/lib/cisco_node_utils/cmd_ref/radius_server_group.yaml +14 -0
  55. data/lib/cisco_node_utils/cmd_ref/show_system.yaml +5 -0
  56. data/lib/cisco_node_utils/cmd_ref/show_version.yaml +72 -0
  57. data/lib/cisco_node_utils/cmd_ref/snmp_community.yaml +23 -0
  58. data/lib/cisco_node_utils/cmd_ref/snmp_group.yaml +7 -0
  59. data/lib/cisco_node_utils/cmd_ref/snmp_notification_receiver.yaml +50 -0
  60. data/lib/cisco_node_utils/cmd_ref/snmp_server.yaml +51 -0
  61. data/lib/cisco_node_utils/cmd_ref/snmp_user.yaml +55 -0
  62. data/lib/cisco_node_utils/cmd_ref/snmpnotification.yaml +11 -0
  63. data/lib/cisco_node_utils/cmd_ref/syslog_server.yaml +18 -0
  64. data/lib/cisco_node_utils/cmd_ref/syslog_settings.yaml +7 -0
  65. data/lib/cisco_node_utils/cmd_ref/system.yaml +6 -0
  66. data/lib/cisco_node_utils/cmd_ref/tacacs_server.yaml +49 -0
  67. data/lib/cisco_node_utils/cmd_ref/tacacs_server_group.yaml +33 -0
  68. data/lib/cisco_node_utils/cmd_ref/tacacs_server_host.yaml +35 -0
  69. data/lib/cisco_node_utils/cmd_ref/vdc.yaml +38 -0
  70. data/lib/cisco_node_utils/cmd_ref/virtual_service.yaml +6 -0
  71. data/lib/cisco_node_utils/cmd_ref/vlan.yaml +56 -0
  72. data/lib/cisco_node_utils/cmd_ref/vni.yaml +76 -0
  73. data/lib/cisco_node_utils/cmd_ref/vpc.yaml +197 -0
  74. data/lib/cisco_node_utils/cmd_ref/vrf.yaml +88 -0
  75. data/lib/cisco_node_utils/cmd_ref/vtp.yaml +38 -0
  76. data/lib/cisco_node_utils/cmd_ref/vxlan_vtep.yaml +60 -0
  77. data/lib/cisco_node_utils/cmd_ref/vxlan_vtep_vni.yaml +39 -0
  78. data/lib/cisco_node_utils/cmd_ref/yum.yaml +13 -0
  79. data/lib/cisco_node_utils/command_reference.rb +359 -187
  80. data/lib/cisco_node_utils/configparser_lib.rb +1 -1
  81. data/lib/cisco_node_utils/dns_domain.rb +19 -5
  82. data/lib/cisco_node_utils/domain_name.rb +4 -8
  83. data/lib/cisco_node_utils/evpn_vni.rb +157 -0
  84. data/lib/cisco_node_utils/fabricpath_global.rb +388 -0
  85. data/lib/cisco_node_utils/fabricpath_topology.rb +150 -0
  86. data/lib/cisco_node_utils/feature.rb +111 -0
  87. data/lib/cisco_node_utils/interface.rb +390 -97
  88. data/lib/cisco_node_utils/interface_channel_group.rb +124 -0
  89. data/lib/cisco_node_utils/interface_ospf.rb +11 -34
  90. data/lib/cisco_node_utils/interface_portchannel.rb +157 -0
  91. data/lib/cisco_node_utils/interface_service_vni.rb +132 -0
  92. data/lib/cisco_node_utils/name_server.rb +1 -1
  93. data/lib/cisco_node_utils/node.rb +55 -249
  94. data/lib/cisco_node_utils/node_util.rb +5 -1
  95. data/lib/cisco_node_utils/ntp_config.rb +2 -2
  96. data/lib/cisco_node_utils/ntp_server.rb +14 -5
  97. data/lib/cisco_node_utils/overlay_global.rb +153 -0
  98. data/lib/cisco_node_utils/pim.rb +124 -0
  99. data/lib/cisco_node_utils/pim_group_list.rb +108 -0
  100. data/lib/cisco_node_utils/pim_rp_address.rb +102 -0
  101. data/lib/cisco_node_utils/platform.rb +8 -9
  102. data/lib/cisco_node_utils/portchannel_global.rb +277 -0
  103. data/lib/cisco_node_utils/radius_global.rb +9 -19
  104. data/lib/cisco_node_utils/radius_server.rb +31 -41
  105. data/lib/cisco_node_utils/radius_server_group.rb +117 -0
  106. data/lib/cisco_node_utils/router_ospf.rb +1 -1
  107. data/lib/cisco_node_utils/router_ospf_vrf.rb +14 -19
  108. data/lib/cisco_node_utils/snmp_notification_receiver.rb +158 -0
  109. data/lib/cisco_node_utils/snmpcommunity.rb +3 -5
  110. data/lib/cisco_node_utils/snmpgroup.rb +1 -1
  111. data/lib/cisco_node_utils/snmpnotification.rb +57 -0
  112. data/lib/cisco_node_utils/snmpserver.rb +8 -17
  113. data/lib/cisco_node_utils/snmpuser.rb +67 -28
  114. data/lib/cisco_node_utils/syslog_server.rb +3 -9
  115. data/lib/cisco_node_utils/syslog_settings.rb +2 -10
  116. data/lib/cisco_node_utils/tacacs_server.rb +9 -14
  117. data/lib/cisco_node_utils/tacacs_server_group.rb +145 -0
  118. data/lib/cisco_node_utils/tacacs_server_host.rb +5 -9
  119. data/lib/cisco_node_utils/vdc.rb +88 -0
  120. data/lib/cisco_node_utils/version.rb +5 -2
  121. data/lib/cisco_node_utils/vlan.rb +71 -8
  122. data/lib/cisco_node_utils/vni.rb +227 -0
  123. data/lib/cisco_node_utils/vpc.rb +377 -0
  124. data/lib/cisco_node_utils/vrf.rb +60 -9
  125. data/lib/cisco_node_utils/vrf_af.rb +191 -0
  126. data/lib/cisco_node_utils/vtp.rb +8 -6
  127. data/lib/cisco_node_utils/vxlan_vtep.rb +151 -0
  128. data/lib/cisco_node_utils/vxlan_vtep_vni.rb +234 -0
  129. data/lib/cisco_node_utils/yum.rb +1 -1
  130. data/tests/.rubocop.yml +1 -1
  131. data/tests/basetest.rb +16 -7
  132. data/tests/ciscotest.rb +55 -13
  133. data/tests/cmd_config.yaml +2 -2
  134. data/tests/platform_info.rb +3 -2
  135. data/tests/test_aaa_authentication_login.rb +219 -0
  136. data/tests/test_aaa_authentication_login_service.rb +759 -0
  137. data/tests/test_aaa_authorization_service.rb +1041 -0
  138. data/tests/test_ace.rb +160 -0
  139. data/tests/test_acl.rb +176 -0
  140. data/tests/test_bgp_af.rb +269 -13
  141. data/tests/test_bgp_neighbor.rb +38 -40
  142. data/tests/test_bgp_neighbor_af.rb +92 -32
  143. data/tests/test_command_config.rb +5 -5
  144. data/tests/test_command_reference.rb +284 -101
  145. data/tests/test_dns_domain.rb +1 -1
  146. data/tests/test_domain_name.rb +1 -1
  147. data/tests/test_evpn_vni.rb +106 -0
  148. data/tests/test_fabricpath_global.rb +243 -0
  149. data/tests/test_fabricpath_topology.rb +98 -0
  150. data/tests/test_interface.rb +292 -74
  151. data/tests/test_interface_channel_group.rb +74 -0
  152. data/tests/test_interface_ospf.rb +9 -4
  153. data/tests/test_interface_portchannel.rb +105 -0
  154. data/tests/test_interface_service_vni.rb +232 -0
  155. data/tests/test_interface_svi.rb +77 -62
  156. data/tests/test_interface_switchport.rb +17 -5
  157. data/tests/test_name_server.rb +1 -1
  158. data/tests/test_node.rb +1 -1
  159. data/tests/test_node_ext.rb +10 -20
  160. data/tests/test_ntp_config.rb +1 -1
  161. data/tests/test_ntp_server.rb +18 -6
  162. data/tests/test_overlay_global.rb +102 -0
  163. data/tests/test_pim.rb +177 -0
  164. data/tests/test_pim_group_list.rb +181 -0
  165. data/tests/test_pim_rp_address.rb +153 -0
  166. data/tests/test_platform.rb +3 -3
  167. data/tests/test_portchannel_global.rb +202 -0
  168. data/tests/test_radius_global.rb +1 -1
  169. data/tests/test_radius_server.rb +92 -57
  170. data/tests/test_radius_server_group.rb +149 -0
  171. data/tests/test_router_bgp.rb +283 -112
  172. data/tests/test_router_ospf.rb +2 -2
  173. data/tests/test_router_ospf_vrf.rb +4 -4
  174. data/tests/test_snmp_notification_receiver.rb +167 -0
  175. data/tests/test_snmpcommunity.rb +1 -1
  176. data/tests/test_snmpgroup.rb +1 -1
  177. data/tests/test_snmpnotification.rb +72 -0
  178. data/tests/test_snmpserver.rb +29 -105
  179. data/tests/test_snmpuser.rb +32 -30
  180. data/tests/test_syslog_server.rb +36 -10
  181. data/tests/test_syslog_settings.rb +1 -1
  182. data/tests/test_tacacs_server.rb +1 -1
  183. data/tests/test_tacacs_server_group.rb +405 -0
  184. data/tests/test_tacacs_server_host.rb +1 -1
  185. data/tests/test_vdc.rb +78 -0
  186. data/tests/test_vlan.rb +74 -19
  187. data/tests/test_vlan_mt_full.rb +95 -0
  188. data/tests/test_vni.rb +106 -0
  189. data/tests/test_vpc.rb +361 -0
  190. data/tests/test_vrf.rb +172 -29
  191. data/tests/test_vtp.rb +1 -1
  192. data/tests/test_vxlan_vtep.rb +214 -0
  193. data/tests/test_vxlan_vtep_vni.rb +201 -0
  194. data/tests/test_yum.rb +1 -1
  195. metadata +120 -11
  196. data/lib/cisco_node_utils/README_YAML.md +0 -325
  197. data/lib/cisco_node_utils/command_reference_common.yaml +0 -1051
  198. data/lib/cisco_node_utils/command_reference_common_bgp.yaml +0 -535
  199. data/lib/cisco_node_utils/command_reference_n3064.yaml +0 -13
  200. data/lib/cisco_node_utils/command_reference_n7k.yaml +0 -52
  201. data/lib/cisco_node_utils/command_reference_n9k.yaml +0 -26
  202. data/tests/platform_info.yaml +0 -10
@@ -0,0 +1,150 @@
1
+ # Fabricpath Topology provider class
2
+ #
3
+ # Deepak Cherian, November 2015
4
+ #
5
+ # Copyright (c) 2015-2016 Cisco and/or its affiliates.
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+
19
+ require_relative 'node_util'
20
+ require_relative 'fabricpath_global'
21
+
22
+ module Cisco
23
+ # node_utils class for fabricpath_topology
24
+ class FabricpathTopo < NodeUtil
25
+ attr_reader :topo_id
26
+
27
+ def initialize(topo_id, instantiate=true)
28
+ @topo_id = topo_id.to_s
29
+ @set_params = {}
30
+ fail ArgumentError, "Invalid value(non-numeric
31
+ Topo id #{@topo_id})" unless @topo_id[/^\d+$/]
32
+
33
+ create if instantiate
34
+ end
35
+
36
+ def self.topos
37
+ hash = {}
38
+ fabricpath = config_get('fabricpath', 'feature')
39
+ return hash if (:enabled != fabricpath.to_sym)
40
+ topo_list = config_get('fabricpath_topology', 'all_topos')
41
+ return hash if topo_list.nil?
42
+
43
+ topo_list.each do |id|
44
+ hash[id] = FabricpathTopo.new(id, false)
45
+ end
46
+ hash
47
+ end
48
+
49
+ def create
50
+ fabricpath_feature_set(:enabled) unless :enabled == fabricpath_feature
51
+ config_set('fabricpath_topology', 'create',
52
+ topo: @topo_id) unless @topo_id == '0'
53
+ end
54
+
55
+ def cli_error_check(result)
56
+ # The NXOS vlan cli does not raise an exception in some conditions and
57
+ # instead just displays a STDOUT error message; thus NXAPI does not detect
58
+ # the failure and we must catch it by inspecting the "body" hash entry
59
+ # returned by NXAPI. This vlan cli behavior is unlikely to change.
60
+ fail result[2]['body'] unless result[2]['body'].empty?
61
+ end
62
+
63
+ def destroy
64
+ config_set('fabricpath_topology', 'destroy', topo: @topo_id)
65
+ end
66
+
67
+ def fabricpath_feature
68
+ FabricpathGlobal.fabricpath_feature
69
+ end
70
+
71
+ def fabricpath_feature_set(fabricpath_set)
72
+ FabricpathGlobal.fabricpath_feature_set(fabricpath_set)
73
+ end
74
+
75
+ def state
76
+ result = config_get('fabricpath_topology', 'state', @topo_id)
77
+ return default_state if result.nil?
78
+ case result
79
+ when /Up/
80
+ return 'up'
81
+ when /Down/
82
+ return 'default'
83
+ end
84
+ end
85
+
86
+ def default_state
87
+ config_get_default('fabricpath_topology', 'state')
88
+ end
89
+
90
+ def member_vlans
91
+ str = config_get('fabricpath_topology', 'member_vlans', @topo_id)
92
+ return [] if str == '--'
93
+ str.gsub!('-', '..')
94
+ if /,/.match(str)
95
+ str.split(/\s*,\s*/)
96
+ else
97
+ str.lines.to_a
98
+ end
99
+ end
100
+
101
+ def member_vlans=(str)
102
+ debug "str is #{str} whose class is #{str.class}"
103
+ @set_params = {}
104
+ str = str.join(',') unless str.empty?
105
+ if str.empty?
106
+ @set_params[:topo] = @topo_id
107
+ @set_params[:state] = 'no'
108
+ @set_params[:vlan_range] = ''
109
+ else
110
+ str.gsub!('..', '-')
111
+ @set_params[:topo] = @topo_id
112
+ @set_params[:state] = ''
113
+ @set_params[:vlan_range] = str
114
+ end
115
+ result = config_set('fabricpath_topology', 'member_vlans', @set_params)
116
+ cli_error_check(result)
117
+ rescue CliError => e
118
+ raise "[topo #{@topo_id}] '#{e.command}' : #{e.clierror}"
119
+ end
120
+
121
+ def default_member_vlans
122
+ []
123
+ end
124
+
125
+ def topo_name
126
+ config_get('fabricpath_topology', 'description', @topo_id)
127
+ end
128
+
129
+ def topo_name=(desc)
130
+ fail TypeError unless desc.is_a?(String)
131
+ @set_params = {}
132
+ if desc.empty?
133
+ @set_params[:topo] = @topo_id
134
+ @set_params[:state] = 'no'
135
+ @set_params[:name] = ''
136
+ else
137
+ @set_params[:topo] = @topo_id
138
+ @set_params[:state] = ''
139
+ @set_params[:name] = desc
140
+ end
141
+ config_set('fabricpath_topology', 'description', @set_params)
142
+ rescue Cisco::CliError => e
143
+ raise "[#{@name}] '#{e.command}' : #{e.clierror}"
144
+ end
145
+
146
+ def default_topo_name
147
+ config_get_default('fabricpath_topology', 'description')
148
+ end
149
+ end # class
150
+ end # module
@@ -0,0 +1,111 @@
1
+ # January 2016, Robert W Gries
2
+ #
3
+ # Copyright (c) 2015-2016 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 'node_util'
18
+
19
+ module Cisco
20
+ # Feature - node util class for managing common features
21
+ class Feature < NodeUtil
22
+ # Note that in most cases the enable methods should only enable;
23
+ # however, for test purposes it is sometimes convenient to support
24
+ # feature disablement for cleanup purposes.
25
+ # ---------------------------
26
+ def self.bgp_enable
27
+ return if bgp_enabled?
28
+ config_set('feature', 'bgp')
29
+ end
30
+
31
+ def self.bgp_enabled?
32
+ config_get('feature', 'bgp')
33
+ end
34
+
35
+ # ---------------------------
36
+ def self.fabric_enable
37
+ # install feature-set and enable it
38
+ return if fabric_enabled?
39
+ config_set('feature', 'fabric', state: 'install') unless fabric_installed?
40
+ config_set('feature', 'fabric', state: '')
41
+ end
42
+
43
+ def self.fabric_enabled?
44
+ config_get('feature', 'fabric') =~ /^enabled/
45
+ end
46
+
47
+ def self.fabric_installed?
48
+ config_get('feature', 'fabric') !~ /^uninstalled/
49
+ end
50
+
51
+ def self.fabric_supported?
52
+ config_get('feature', 'fabric')
53
+ end
54
+
55
+ # ---------------------------
56
+ def self.fabric_forwarding_enable
57
+ return if fabric_forwarding_enabled?
58
+ Feature.fabric_enable if Feature.fabric_supported?
59
+ # The feature fabric-forwarding cli is required in some older nxos images
60
+ # but is not present in newer images because nv_overlay_evpn handles
61
+ # both features; therefore feature fabric-forwarding is best-effort
62
+ # and ignored on cli failure.
63
+ begin
64
+ config_set('feature', 'fabric_forwarding')
65
+ rescue Cisco::CliError
66
+ CiscoLogger.debug '"feature fabric forwarding" CLI was rejected'
67
+ end
68
+ end
69
+
70
+ def self.fabric_forwarding_enabled?
71
+ config_get('feature', 'fabric_forwarding')
72
+ end
73
+
74
+ # ---------------------------
75
+ def self.nv_overlay_enable
76
+ # Note: vdc platforms restrict this feature to F3 or newer linecards
77
+ return if nv_overlay_enabled?
78
+ config_set('feature', 'nv_overlay')
79
+ end
80
+
81
+ def self.nv_overlay_enabled?
82
+ config_get('feature', 'nv_overlay')
83
+ rescue Cisco::CliError => e
84
+ # cmd will syntax reject when feature is not enabled.
85
+ raise unless e.clierror =~ /Syntax error/
86
+ return false
87
+ end
88
+
89
+ # ---------------------------
90
+ def self.nv_overlay_evpn_enable
91
+ return if nv_overlay_evpn_enabled?
92
+ config_set('feature', 'nv_overlay_evpn')
93
+ end
94
+
95
+ def self.nv_overlay_evpn_enabled?
96
+ config_get('feature', 'nv_overlay_evpn')
97
+ end
98
+
99
+ # ---------------------------
100
+ def self.vn_segment_vlan_based_enable
101
+ return if vn_segment_vlan_based_enabled?
102
+ config_set('feature', 'vn_segment_vlan_based')
103
+ end
104
+
105
+ def self.vn_segment_vlan_based_enabled?
106
+ config_get('feature', 'vn_segment_vlan_based')
107
+ end
108
+
109
+ # ---------------------------
110
+ end
111
+ end
@@ -1,6 +1,6 @@
1
1
  # November 2015, Chris Van Heuveln
2
2
  #
3
- # Copyright (c) 2015 Cisco and/or its affiliates.
3
+ # Copyright (c) 2015-2016 Cisco and/or its affiliates.
4
4
  #
5
5
  # Licensed under the Apache License, Version 2.0 (the "License");
6
6
  # you may not use this file except in compliance with the License.
@@ -14,7 +14,12 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
 
17
+ require_relative 'cisco_cmn_utils'
17
18
  require_relative 'node_util'
19
+ require_relative 'pim'
20
+ require_relative 'vrf'
21
+ require_relative 'vni'
22
+ require_relative 'overlay_global'
18
23
 
19
24
  # Add some interface-specific constants to the Cisco namespace
20
25
  module Cisco
@@ -24,6 +29,7 @@ module Cisco
24
29
  trunk: 'trunk',
25
30
  fex_fabric: 'fex-fabric',
26
31
  tunnel: 'dot1q-tunnel',
32
+ fabricpath: 'fabricpath',
27
33
  }
28
34
 
29
35
  # Interface - node utility class for general interface config management
@@ -64,9 +70,7 @@ module Cisco
64
70
  ########################################################
65
71
 
66
72
  def access_vlan
67
- vlan = config_get('interface', 'access_vlan', @name)
68
- return default_access_vlan if vlan.nil?
69
- vlan.shift.to_i
73
+ config_get('interface', 'access_vlan', @name)
70
74
  end
71
75
 
72
76
  def access_vlan=(vlan)
@@ -75,14 +79,90 @@ module Cisco
75
79
  raise "[#{@name}] '#{e.command}' : #{e.clierror}"
76
80
  end
77
81
 
82
+ def ipv4_acl_in
83
+ config_get('interface', 'ipv4_acl_in', @name)
84
+ end
85
+
86
+ def ipv4_acl_in=(val)
87
+ if val != ''
88
+ state = ''
89
+ else
90
+ state = 'no'
91
+ val = ipv4_acl_in
92
+ end
93
+
94
+ return unless val && val != ''
95
+ config_set('interface', 'ipv4_acl_in', @name, state, val)
96
+ end
97
+
98
+ def default_ipv4_acl_in
99
+ config_get_default('interface', 'ipv4_acl_in')
100
+ end
101
+
102
+ def ipv4_acl_out
103
+ config_get('interface', 'ipv4_acl_out', @name)
104
+ end
105
+
106
+ def ipv4_acl_out=(val)
107
+ if val != ''
108
+ state = ''
109
+ else
110
+ state = 'no'
111
+ val = ipv4_acl_out
112
+ end
113
+
114
+ return unless val && val != ''
115
+ config_set('interface', 'ipv4_acl_out', @name, state, val)
116
+ end
117
+
118
+ def default_ipv4_acl_out
119
+ config_get_default('interface', 'ipv4_acl_out')
120
+ end
121
+
122
+ def ipv6_acl_in
123
+ config_get('interface', 'ipv6_acl_in', @name)
124
+ end
125
+
126
+ def ipv6_acl_in=(val)
127
+ if val != ''
128
+ state = ''
129
+ else
130
+ state = 'no'
131
+ val = ipv6_acl_in
132
+ end
133
+ return unless val && val != ''
134
+ config_set('interface', 'ipv6_acl_in', @name, state, val)
135
+ end
136
+
137
+ def default_ipv6_acl_in
138
+ config_get_default('interface', 'ipv6_acl_in')
139
+ end
140
+
141
+ def ipv6_acl_out
142
+ config_get('interface', 'ipv6_acl_out', @name)
143
+ end
144
+
145
+ def ipv6_acl_out=(val)
146
+ if val != ''
147
+ state = ''
148
+ else
149
+ state = 'no'
150
+ val = ipv6_acl_out
151
+ end
152
+ return unless val && val != ''
153
+ config_set('interface', 'ipv6_acl_out', @name, state, val)
154
+ end
155
+
156
+ def default_ipv6_acl_out
157
+ config_get_default('interface', 'ipv6_acl_out')
158
+ end
159
+
78
160
  def default_access_vlan
79
161
  config_get_default('interface', 'access_vlan')
80
162
  end
81
163
 
82
164
  def description
83
- desc = config_get('interface', 'description', @name)
84
- return '' if desc.nil?
85
- desc.shift.strip
165
+ config_get('interface', 'description', @name)
86
166
  end
87
167
 
88
168
  def description=(desc)
@@ -101,9 +181,7 @@ module Cisco
101
181
  end
102
182
 
103
183
  def encapsulation_dot1q
104
- val = config_get('interface', 'encapsulation_dot1q', @name)
105
- return default_encapsulation_dot1q if val.nil?
106
- val.shift.strip.to_i
184
+ config_get('interface', 'encapsulation_dot1q', @name)
107
185
  end
108
186
 
109
187
  def encapsulation_dot1q=(val)
@@ -120,10 +198,43 @@ module Cisco
120
198
  config_get_default('interface', 'encapsulation_dot1q')
121
199
  end
122
200
 
201
+ def fabricpath_feature
202
+ FabricpathGlobal.fabricpath_feature
203
+ end
204
+
205
+ def fabricpath_feature_set(fabricpath_set)
206
+ FabricpathGlobal.fabricpath_feature_set(fabricpath_set)
207
+ end
208
+
209
+ def fabric_forwarding_anycast_gateway
210
+ config_get('interface', 'fabric_forwarding_anycast_gateway', @name)
211
+ end
212
+
213
+ def fabric_forwarding_anycast_gateway=(state)
214
+ no_cmd = (state ? '' : 'no')
215
+ config_set('interface',
216
+ 'fabric_forwarding_anycast_gateway', @name, no_cmd)
217
+ fail if fabric_forwarding_anycast_gateway.to_s != state.to_s
218
+ rescue Cisco::CliError => e
219
+ info = "[#{@name}] '#{e.command}' : #{e.clierror}"
220
+ raise "#{info} 'fabric_forwarding_anycast_gateway' can only be " \
221
+ 'configured on a vlan interface' unless /vlan/.match(@name)
222
+ anycast_gateway_mac = OverlayGlobal.new.anycast_gateway_mac
223
+ if anycast_gateway_mac.nil? || anycast_gateway_mac.empty?
224
+ raise "#{info} Anycast gateway mac must be configured " \
225
+ 'before configuring forwarding mode under interface'
226
+ end
227
+ raise info
228
+ end
229
+
230
+ def default_fabric_forwarding_anycast_gateway
231
+ config_get_default('interface', 'fabric_forwarding_anycast_gateway')
232
+ end
233
+
123
234
  def fex_feature
124
235
  fex = config_get('fex', 'feature')
125
236
  fail 'fex_feature not found' if fex.nil?
126
- fex.shift.to_sym
237
+ fex.to_sym
127
238
  end
128
239
 
129
240
  def fex_feature_set(fex_set)
@@ -147,47 +258,127 @@ module Cisco
147
258
  raise "[#{@name}] '#{e.command}' : #{e.clierror}"
148
259
  end
149
260
 
150
- def ipv4_addr_mask
151
- config_get('interface', 'ipv4_addr_mask', @name)
152
- end
153
-
154
- def ipv4_addr_mask_set(addr, mask)
261
+ def ipv4_addr_mask_set(addr, mask, secondary=false)
155
262
  check_switchport_disabled
263
+ sec = secondary ? 'secondary' : ''
156
264
  if addr.nil? || addr == default_ipv4_address
157
- config_set('interface', 'ipv4_addr_mask', @name, 'no', '')
265
+ state = 'no'
266
+ if secondary
267
+ return if ipv4_address_secondary == default_ipv4_address_secondary
268
+ # We need address and mask to remove.
269
+ am = "#{ipv4_address_secondary}/#{ipv4_netmask_length_secondary}"
270
+ else
271
+ return if ipv4_address == default_ipv4_address
272
+ am = "#{ipv4_address}/#{ipv4_netmask_length}"
273
+ end
158
274
  else
159
- config_set('interface', 'ipv4_addr_mask', @name, '',
160
- "#{addr}/#{mask}")
275
+ state = ''
276
+ am = "#{addr}/#{mask}"
161
277
  end
278
+ config_set('interface', 'ipv4_addr_mask', @name, state, am, sec)
162
279
  rescue Cisco::CliError => e
163
280
  raise "[#{@name}] '#{e.command}' : #{e.clierror}"
164
281
  end
165
282
 
283
+ def ipv4_addr_mask
284
+ config_get('interface', 'ipv4_addr_mask', @name)
285
+ end
286
+
287
+ def select_ipv4_attribute(attribute)
288
+ d = ipv4_addr_mask.flatten unless ipv4_addr_mask.nil?
289
+ # (d)ata format after flatten: ['addr', 'mask', 'addr', 'mask secondary']
290
+ case attribute
291
+ when :v4_addr
292
+ v = d.nil? ? default_ipv4_address : d[0]
293
+ when :v4_mask
294
+ v = d.nil? ? default_ipv4_netmask_length : d[1].to_i
295
+ when :v4_addr_secondary
296
+ v = (d.nil? || d.size < 4) ? default_ipv4_address : d[2]
297
+ when :v4_mask_secondary
298
+ if d.nil? || d.size < 4
299
+ v = default_ipv4_netmask_length
300
+ else
301
+ v = d[3][0, 2].to_i
302
+ end
303
+ end
304
+ v
305
+ end
306
+
166
307
  def ipv4_address
167
- val = ipv4_addr_mask
168
- return default_ipv4_address if val.nil?
169
- # val is [[addr, mask]] - we just want the addr
170
- val.shift.first
308
+ select_ipv4_attribute(:v4_addr)
309
+ end
310
+
311
+ def ipv4_address_secondary
312
+ select_ipv4_attribute(:v4_addr_secondary)
313
+ end
314
+
315
+ def ipv4_netmask_length
316
+ select_ipv4_attribute(:v4_mask)
317
+ end
318
+
319
+ def ipv4_netmask_length_secondary
320
+ select_ipv4_attribute(:v4_mask_secondary)
171
321
  end
172
322
 
173
323
  def default_ipv4_address
174
324
  config_get_default('interface', 'ipv4_address')
175
325
  end
176
326
 
177
- def ipv4_netmask_length
178
- val = ipv4_addr_mask
179
- return default_ipv4_netmask_length if val.nil?
180
- # val is [[addr, mask]] - we just want the mask
181
- val.shift.last.to_i
327
+ def default_ipv4_address_secondary
328
+ default_ipv4_address
182
329
  end
183
330
 
184
331
  def default_ipv4_netmask_length
185
332
  config_get_default('interface', 'ipv4_netmask_length')
186
333
  end
187
334
 
335
+ def default_ipv4_netmask_length_secondary
336
+ default_ipv4_netmask_length
337
+ end
338
+
339
+ def ipv4_arp_timeout_lookup_string
340
+ case @name
341
+ when /vlan/i
342
+ return 'ipv4_arp_timeout'
343
+ else
344
+ return 'ipv4_arp_timeout_non_vlan_interfaces'
345
+ end
346
+ end
347
+
348
+ def ipv4_arp_timeout
349
+ config_get('interface', ipv4_arp_timeout_lookup_string, @name)
350
+ end
351
+
352
+ def ipv4_arp_timeout=(timeout)
353
+ fail "'ipv4 arp timeout' can ony be configured on a vlan interface" unless
354
+ /vlan/.match(@name)
355
+ state = (timeout == default_ipv4_arp_timeout) ? 'no' : ''
356
+ config_set('interface', 'ipv4_arp_timeout', @name, state, timeout)
357
+ end
358
+
359
+ def default_ipv4_arp_timeout
360
+ config_get_default('interface', ipv4_arp_timeout_lookup_string)
361
+ end
362
+
363
+ def ipv4_pim_sparse_mode
364
+ config_get('interface', 'ipv4_pim_sparse_mode', @name)
365
+ end
366
+
367
+ def ipv4_pim_sparse_mode=(state)
368
+ check_switchport_disabled
369
+ Pim.feature_enable unless Pim.feature_enabled
370
+ config_set('interface', 'ipv4_pim_sparse_mode', @name,
371
+ state ? '' : 'no')
372
+ rescue Cisco::CliError => e
373
+ raise "[#{@name}] '#{e.command}' : #{e.clierror}"
374
+ end
375
+
376
+ def default_ipv4_pim_sparse_mode
377
+ config_get_default('interface', 'ipv4_pim_sparse_mode')
378
+ end
379
+
188
380
  def ipv4_proxy_arp
189
- state = config_get('interface', 'ipv4_proxy_arp', @name)
190
- state.nil? ? false : true
381
+ config_get('interface', 'ipv4_proxy_arp', @name)
191
382
  end
192
383
 
193
384
  def ipv4_proxy_arp=(proxy_arp)
@@ -210,24 +401,13 @@ module Cisco
210
401
  end
211
402
 
212
403
  def ipv4_redirects
213
- begin
214
- state = config_get('interface',
215
- ipv4_redirects_lookup_string, @name)
216
- rescue IndexError
217
- state = nil
218
- end
219
- # We return default state for the platform if the platform doesn't support
220
- # the command
221
- return default_ipv4_redirects if state.nil? || state.empty?
222
- state.shift[/^ip redirects$/] ? true : false
404
+ config_get('interface', ipv4_redirects_lookup_string, @name)
223
405
  end
224
406
 
225
407
  def ipv4_redirects=(redirects)
226
408
  check_switchport_disabled
227
409
  no_cmd = (redirects ? '' : 'no')
228
410
  config_set('interface', ipv4_redirects_lookup_string, @name, no_cmd)
229
- rescue IndexError
230
- raise "ipv4 redirects not supported on #{@name}"
231
411
  end
232
412
 
233
413
  def default_ipv4_redirects
@@ -235,7 +415,7 @@ module Cisco
235
415
  end
236
416
 
237
417
  def feature_lacp?
238
- !config_get('interface', 'feature_lacp').nil?
418
+ config_get('interface', 'feature_lacp')
239
419
  end
240
420
 
241
421
  def feature_lacp_set(val)
@@ -244,9 +424,7 @@ module Cisco
244
424
  end
245
425
 
246
426
  def mtu
247
- mtu = config_get('interface', 'mtu', @name)
248
- return default_mtu if mtu.nil?
249
- mtu.shift.strip.to_i
427
+ config_get('interface', 'mtu', @name)
250
428
  end
251
429
 
252
430
  def mtu=(val)
@@ -260,6 +438,40 @@ module Cisco
260
438
  config_get_default('interface', 'mtu')
261
439
  end
262
440
 
441
+ def speed
442
+ config_get('interface', 'speed', @name)
443
+ end
444
+
445
+ def speed=(val)
446
+ if node.product_id =~ /C31\d\d/
447
+ fail 'Changing interface speed is not permitted on this platform'
448
+ end
449
+ config_set('interface', 'speed', @name, val)
450
+ rescue Cisco::CliError => e
451
+ raise "[#{@name}] '#{e.command}' : #{e.clierror}"
452
+ end
453
+
454
+ def default_speed
455
+ config_get_default('interface', 'speed')
456
+ end
457
+
458
+ def duplex
459
+ config_get('interface', 'duplex', @name)
460
+ end
461
+
462
+ def duplex=(val)
463
+ if node.product_id =~ /C31\d\d/
464
+ fail 'Changing interface duplex is not permitted on this platform'
465
+ end
466
+ config_set('interface', 'duplex', @name, val)
467
+ rescue Cisco::CliError => e
468
+ raise "[#{@name}] '#{e.command}' : #{e.clierror}"
469
+ end
470
+
471
+ def default_duplex
472
+ config_get_default('interface', 'duplex')
473
+ end
474
+
263
475
  def negotiate_auto_lookup_string
264
476
  case @name
265
477
  when /Ethernet/i
@@ -272,29 +484,13 @@ module Cisco
272
484
  end
273
485
 
274
486
  def negotiate_auto
275
- lookup = negotiate_auto_lookup_string
276
- begin
277
- state = config_get('interface', lookup, @name)
278
- rescue IndexError
279
- # We return default state even if the config_get is not supported
280
- # for this platform / interface type. This is done so that we can set
281
- # the manifest to 'default' so there is a 'workaround' for the
282
- # unsupported attribute
283
- return default_negotiate_auto
284
- end
285
- state.nil? ? false : true
487
+ config_get('interface', negotiate_auto_lookup_string, @name)
286
488
  end
287
489
 
288
490
  def negotiate_auto=(negotiate_auto)
289
491
  lookup = negotiate_auto_lookup_string
290
492
  no_cmd = (negotiate_auto ? '' : 'no')
291
- begin
292
- config_set('interface', lookup, @name, no_cmd)
293
- rescue Cisco::CliError => e
294
- raise "[#{@name}] '#{e.command}' : #{e.clierror}"
295
- rescue IndexError
296
- raise "[#{@name}] negotiate_auto is not supported on this interface"
297
- end
493
+ config_set('interface', lookup, @name, no_cmd)
298
494
  end
299
495
 
300
496
  def default_negotiate_auto
@@ -302,8 +498,7 @@ module Cisco
302
498
  end
303
499
 
304
500
  def shutdown
305
- state = config_get('interface', 'shutdown', @name)
306
- state ? true : false
501
+ config_get('interface', 'shutdown', @name)
307
502
  end
308
503
 
309
504
  def shutdown=(state)
@@ -348,8 +543,7 @@ module Cisco
348
543
 
349
544
  def switchport
350
545
  # This is "switchport", not "switchport mode"
351
- sw = config_get('interface', 'switchport', @name)
352
- sw.nil? ? false : true
546
+ config_get('interface', 'switchport', @name)
353
547
  end
354
548
 
355
549
  def switchport_enable(val=true)
@@ -358,8 +552,8 @@ module Cisco
358
552
 
359
553
  # switchport_autostate_exclude is exclusive to switchport interfaces
360
554
  def switchport_autostate_exclude
361
- !config_get('interface',
362
- 'switchport_autostate_exclude', @name).nil?
555
+ config_get('interface',
556
+ 'switchport_autostate_exclude', @name)
363
557
  end
364
558
 
365
559
  def switchport_autostate_exclude=(val)
@@ -389,7 +583,7 @@ module Cisco
389
583
  def switchport_mode
390
584
  mode = config_get('interface', switchport_mode_lookup_string, @name)
391
585
 
392
- return mode.nil? ? :disabled : IF_SWITCHPORT_MODE.key(mode.shift)
586
+ return mode.nil? ? :disabled : IF_SWITCHPORT_MODE.key(mode)
393
587
 
394
588
  rescue IndexError
395
589
  # Assume this is an interface that doesn't support switchport.
@@ -401,8 +595,10 @@ module Cisco
401
595
  def switchport_enable_and_mode(mode_set)
402
596
  switchport_enable unless switchport
403
597
 
404
- if (:fex_fabric == mode_set)
405
- fex_feature_set(:enabled) unless (:enabled == fex_feature)
598
+ if :fabricpath == mode_set
599
+ fabricpath_feature_set(:enabled) unless :enabled == fabricpath_feature
600
+ elsif :fex_fabric == mode_set
601
+ fex_feature_set(:enabled) unless :enabled == fex_feature
406
602
  end
407
603
  config_set('interface', switchport_mode_lookup_string, @name, '',
408
604
  IF_SWITCHPORT_MODE[mode_set])
@@ -447,10 +643,7 @@ module Cisco
447
643
  end
448
644
 
449
645
  def switchport_trunk_allowed_vlan
450
- val = config_get(
451
- 'interface', 'switchport_trunk_allowed_vlan', @name)
452
- return default_switchport_trunk_allowed_vlan if val.nil?
453
- val.shift.strip
646
+ config_get('interface', 'switchport_trunk_allowed_vlan', @name)
454
647
  end
455
648
 
456
649
  def switchport_trunk_allowed_vlan=(val)
@@ -470,10 +663,7 @@ module Cisco
470
663
  end
471
664
 
472
665
  def switchport_trunk_native_vlan
473
- val = config_get(
474
- 'interface', 'switchport_trunk_native_vlan', @name)
475
- return default_switchport_trunk_native_vlan if val.nil?
476
- val.shift.strip.to_i
666
+ config_get('interface', 'switchport_trunk_native_vlan', @name)
477
667
  end
478
668
 
479
669
  def switchport_trunk_native_vlan=(val)
@@ -488,28 +678,103 @@ module Cisco
488
678
  raise "[#{@name}] '#{e.command}' : #{e.clierror}"
489
679
  end
490
680
 
681
+ # vlan_mapping & vlan_mapping_enable
682
+ # Hardware & Cli Dependencies:
683
+ # - F3 linecards only
684
+ # - vdc
685
+ # - limit-resource
686
+ # - bridge-domain
687
+ # - feature vni
688
+ # - switchport mode
689
+
690
+ # Getter: Builds an array of vlan_mapping commands currently
691
+ # on the device.
692
+ # cli: switchport vlan mapping 2 200
693
+ # switchport vlan mapping 4 400
694
+ # array: [['2', '200'], ['4', '400']]
695
+ #
696
+ def default_vlan_mapping
697
+ config_get_default('interface', 'vlan_mapping')
698
+ end
699
+
700
+ def vlan_mapping
701
+ match = config_get('interface', 'vlan_mapping', @name)
702
+ match.each(&:compact!) unless match.nil?
703
+ match
704
+ end
705
+
706
+ def vlan_mapping=(should_list)
707
+ Vni.feature_vni_enable unless Vni.feature_vni_enabled
708
+
709
+ # Process a hash of vlan_mapping cmds from delta_add_remove().
710
+ # The vlan_mapping cli does not allow commands to be updated, they must
711
+ # first be removed if there is a change.
712
+ delta_hash = Utils.delta_add_remove(should_list, vlan_mapping,
713
+ :updates_not_allowed)
714
+ return if delta_hash.values.flatten.empty?
715
+ # Process :remove first to ensure "update" commands will not fail.
716
+ [:remove, :add].each do |action|
717
+ CiscoLogger.debug("vlan_mapping delta #{@get_args}\n"\
718
+ "#{action}: #{delta_hash[action]}")
719
+ delta_hash[action].each do |original, translated|
720
+ state = (action == :add) ? '' : 'no'
721
+ config_set('interface', 'vlan_mapping', @name,
722
+ state, original, translated)
723
+ end
724
+ end
725
+ rescue Cisco::CliError => e
726
+ raise "[#{@name}] '#{e.command}' : #{e.clierror}"
727
+ end
728
+
729
+ # cli: switchport vlan mapping enable
730
+ def default_vlan_mapping_enable
731
+ config_get_default('interface', 'vlan_mapping_enable')
732
+ end
733
+
734
+ def vlan_mapping_enable
735
+ config_get('interface', 'vlan_mapping_enable', @name)
736
+ end
737
+
738
+ def vlan_mapping_enable=(state)
739
+ config_set('interface', 'vlan_mapping_enable', @name,
740
+ state ? '' : 'no')
741
+ end
742
+
491
743
  def default_switchport_trunk_native_vlan
492
744
  config_get_default('interface', 'switchport_trunk_native_vlan')
493
745
  end
494
746
 
495
747
  def system_default_switchport
496
748
  # This command is a user-configurable system default.
497
- sys_def = config_get('interface', 'system_default_switchport')
498
- sys_def.nil? ? false : true
749
+ #
750
+ # Note: This is a simple boolean state but there is a bug on some
751
+ # platforms that causes the cli to nvgen twice; this causes config_get to
752
+ # raise an error when it encounters the multiple. Therefore we define it
753
+ # as a multiple to avoid the raise and handle the array if necessary.
754
+ #
755
+ val = config_get('interface', 'system_default_switchport')
756
+ return (val[0][/^no /] ? false : true) if val.is_a?(Array)
757
+ val
499
758
  end
500
759
 
501
760
  def system_default_switchport_shutdown
502
761
  # This command is a user-configurable system default.
503
- sys_def = config_get('interface',
504
- 'system_default_switchport_shutdown')
505
- sys_def.nil? ? false : true
762
+ config_get('interface', 'system_default_switchport_shutdown')
506
763
  end
507
764
 
508
765
  def system_default_svi_autostate
509
766
  # This command is a user-configurable system default.
510
- sys_def = config_get('interface',
511
- 'system_default_svi_autostate')
512
- sys_def.nil? ? false : true
767
+ #
768
+ # This property behaves differently on an n7k vs ni(3|9)k and therefore
769
+ # needs special handling.
770
+ # N7K: When enabled, does not nvgen.
771
+ # When disabled, does nvgen, but differently then n(3|9)k.
772
+ # Return true for the disabled case, false otherwise.
773
+ # N(3|9)K: When enabled, does nvgen.
774
+ # When disabled, does nvgen.
775
+ # Return true for the enabled case, false otherwise.
776
+ result = config_get('interface', 'system_default_svi_autostate')
777
+ /N7K/.match(node.product_id) ? !result : result
513
778
  end
514
779
 
515
780
  def switchport_vtp_mode_capable?
@@ -518,8 +783,7 @@ module Cisco
518
783
 
519
784
  def switchport_vtp
520
785
  return false unless switchport_vtp_mode_capable?
521
- vtp = config_get('interface', 'vtp', @name)
522
- vtp.nil? ? false : true
786
+ config_get('interface', 'vtp', @name)
523
787
  end
524
788
 
525
789
  def switchport_vtp=(vtp_set)
@@ -538,7 +802,7 @@ module Cisco
538
802
  # svi_autostate is exclusive to svi interfaces
539
803
  def svi_autostate
540
804
  return nil unless @name[/^vlan/i]
541
- !config_get('interface', 'svi_autostate', @name).nil?
805
+ config_get('interface', 'svi_autostate', @name)
542
806
  end
543
807
 
544
808
  def svi_autostate=(val)
@@ -552,7 +816,7 @@ module Cisco
552
816
  end
553
817
 
554
818
  def feature_vlan?
555
- !config_get('interface', 'feature_vlan').nil?
819
+ config_get('interface', 'feature_vlan')
556
820
  end
557
821
 
558
822
  def feature_vlan_set(val)
@@ -563,7 +827,7 @@ module Cisco
563
827
  # svi_management is exclusive to svi interfaces
564
828
  def svi_management
565
829
  return nil unless @name[/^vlan/i]
566
- !config_get('interface', 'svi_management', @name).nil?
830
+ config_get('interface', 'svi_management', @name)
567
831
  end
568
832
 
569
833
  def svi_management=(val)
@@ -589,10 +853,39 @@ module Cisco
589
853
  ' is disabled' unless switchport_mode == :disabled
590
854
  end
591
855
 
856
+ def vpc_id
857
+ config_get('interface', 'vpc_id', @name)
858
+ end
859
+
860
+ def vpc_id=(num)
861
+ if num
862
+ config_set('interface', 'vpc_id', @name, '', num)
863
+ else
864
+ # 'no vpc' doesn't work for phy ports, so do a get
865
+ num = vpc_id
866
+ config_set('interface', 'vpc_id', @name, 'no', num)
867
+ end
868
+ end
869
+
870
+ def default_vpc_id
871
+ config_get_default('interface', 'vpc_id')
872
+ end
873
+
874
+ def vpc_peer_link
875
+ config_get('interface', 'vpc_peer_link', @name)
876
+ end
877
+
878
+ def vpc_peer_link=(state)
879
+ no_cmd = (state ? '' : 'no')
880
+ config_set('interface', 'vpc_peer_link', @name, no_cmd)
881
+ end
882
+
883
+ def default_vpc_peer_link
884
+ config_get_default('interface', 'vpc_peer_link')
885
+ end
886
+
592
887
  def vrf
593
- vrf = config_get('interface', 'vrf', @name)
594
- return '' if vrf.nil?
595
- vrf.shift.strip
888
+ config_get('interface', 'vrf', @name)
596
889
  end
597
890
 
598
891
  def vrf=(vrf)