cisco_node_utils 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +2 -0
  3. data/.rubocop.yml +3 -0
  4. data/.rubocop_todo.yml +293 -0
  5. data/CHANGELOG.md +5 -0
  6. data/CONTRIBUTING.md +31 -0
  7. data/Gemfile +4 -0
  8. data/LICENSE +201 -0
  9. data/README.md +113 -0
  10. data/Rakefile +4 -0
  11. data/cisco_node_utils.gemspec +30 -0
  12. data/lib/cisco_node_utils.rb +33 -0
  13. data/lib/cisco_node_utils/README_YAML.md +333 -0
  14. data/lib/cisco_node_utils/cisco_cmn_utils.rb +92 -0
  15. data/lib/cisco_node_utils/command_reference.rb +415 -0
  16. data/lib/cisco_node_utils/command_reference_common.yaml +845 -0
  17. data/lib/cisco_node_utils/command_reference_n3064.yaml +13 -0
  18. data/lib/cisco_node_utils/command_reference_n7k.yaml +48 -0
  19. data/lib/cisco_node_utils/command_reference_n9k.yaml +35 -0
  20. data/lib/cisco_node_utils/configparser_lib.rb +196 -0
  21. data/lib/cisco_node_utils/interface.rb +501 -0
  22. data/lib/cisco_node_utils/interface_ospf.rb +241 -0
  23. data/lib/cisco_node_utils/node.rb +673 -0
  24. data/lib/cisco_node_utils/platform.rb +184 -0
  25. data/lib/cisco_node_utils/platform_info.rb +58 -0
  26. data/lib/cisco_node_utils/platform_info.yaml +10 -0
  27. data/lib/cisco_node_utils/router_ospf.rb +96 -0
  28. data/lib/cisco_node_utils/router_ospf_vrf.rb +258 -0
  29. data/lib/cisco_node_utils/snmpcommunity.rb +91 -0
  30. data/lib/cisco_node_utils/snmpgroup.rb +55 -0
  31. data/lib/cisco_node_utils/snmpserver.rb +150 -0
  32. data/lib/cisco_node_utils/snmpuser.rb +342 -0
  33. data/lib/cisco_node_utils/tacacs_server.rb +175 -0
  34. data/lib/cisco_node_utils/tacacs_server_host.rb +128 -0
  35. data/lib/cisco_node_utils/version.rb +17 -0
  36. data/lib/cisco_node_utils/vlan.rb +153 -0
  37. data/lib/cisco_node_utils/vtp.rb +127 -0
  38. data/lib/cisco_node_utils/yum.rb +84 -0
  39. data/tests/basetest.rb +93 -0
  40. data/tests/ciscotest.rb +136 -0
  41. data/tests/cmd_config.yaml +51 -0
  42. data/tests/cmd_config_invalid.yaml +16 -0
  43. data/tests/test_all_cisco.rb +46 -0
  44. data/tests/test_command_config.rb +192 -0
  45. data/tests/test_command_reference.rb +222 -0
  46. data/tests/test_interface.rb +1017 -0
  47. data/tests/test_interface_ospf.rb +763 -0
  48. data/tests/test_interface_svi.rb +267 -0
  49. data/tests/test_interface_switchport.rb +722 -0
  50. data/tests/test_node.rb +108 -0
  51. data/tests/test_node_ext.rb +450 -0
  52. data/tests/test_platform.rb +188 -0
  53. data/tests/test_router_ospf.rb +164 -0
  54. data/tests/test_router_ospf_vrf.rb +753 -0
  55. data/tests/test_snmpcommunity.rb +344 -0
  56. data/tests/test_snmpgroup.rb +71 -0
  57. data/tests/test_snmpserver.rb +443 -0
  58. data/tests/test_snmpuser.rb +803 -0
  59. data/tests/test_tacacs_server.rb +388 -0
  60. data/tests/test_tacacs_server_host.rb +391 -0
  61. data/tests/test_vlan.rb +264 -0
  62. data/tests/test_vtp.rb +319 -0
  63. data/tests/test_yum.rb +106 -0
  64. metadata +188 -0
@@ -0,0 +1,13 @@
1
+ # Command Reference N3K, 3064 specific model
2
+ #
3
+ # For documentation please see these files for fields and defaults:
4
+ # - README_YAML.md
5
+ # - command_reference_common.yaml
6
+ #
7
+ ---
8
+ interface:
9
+ negotiate_auto_ethernet:
10
+ config_set: ~
11
+ config_get: ~
12
+ config_get_token: ~
13
+ default_value: false
@@ -0,0 +1,48 @@
1
+ # Command Reference N7K
2
+ #
3
+ # For documentation please see these files for fields and defaults:
4
+ # - README_YAML.md
5
+ # - command_reference_common.yaml
6
+ #
7
+ ---
8
+ interface:
9
+ admin_state_ethernet_noswitchport_shutdown:
10
+ default_value: "shutdown"
11
+
12
+ ipv4_redirects_loopback:
13
+ default_value: false
14
+ config_set: ~
15
+ config_get: ~
16
+ config_get_token: ~
17
+ test_config_result:
18
+ false: RuntimeError
19
+ true: RuntimeError
20
+
21
+ negotiate_auto_ethernet:
22
+ config_set: ~
23
+ config_get: ~
24
+ config_get_token: ~
25
+ default_value: false
26
+
27
+ negotiate_auto_portchannel:
28
+ config_set: ~
29
+ config_get: ~
30
+ config_get_token:
31
+ default_value: false
32
+
33
+
34
+ inventory:
35
+ inventory:
36
+ test_config_get_regex: [!ruby/regexp '/.*\nNAME: "(.+)",\s+DESCR: "(.+)"\s+\nPID: (\S+)\s+,\s+VID: (.+) ,\s+SN: (.+)\s+\n/', !ruby/regexp '/.*NAME: "(.+)",\s+DESCR: "(.+)"\s+PID: (\S+)\s+,\s+VID: (.+) ,\s+SN: (.+)\s+\n/']
37
+
38
+
39
+ show_version:
40
+ description:
41
+ test_config_get_regex: !ruby/regexp '/.*Hardware\n cisco (\w+ \w+ \(\w+ \w+\) \w+).*/'
42
+
43
+
44
+ vtp:
45
+ version:
46
+ test_config_result:
47
+ 3: 3
48
+
@@ -0,0 +1,35 @@
1
+ # Command Reference N9K
2
+ #
3
+ # For documentation please see these files for fields and defaults:
4
+ # - README_YAML.md
5
+ # - command_reference_common.yaml
6
+ #
7
+ ---
8
+
9
+ inventory:
10
+ inventory:
11
+ test_config_get_regex: [!ruby/regexp '/.*\nNAME: "(.+)",\s+DESCR: "(.+)"\s+\nPID: (\S+)\s+,\s+VID: (.+) ,\s+SN: (.+)\s+\n/', !ruby/regexp '/.*NAME: "(.+)",\s+DESCR: "(.+)"\s+PID: (\S+)\s+,\s+VID: (.+) ,\s+SN: (.+)\s+\n/']
12
+
13
+
14
+ show_version:
15
+ boot_image:
16
+ test_config_get_regex: !ruby/regexp '/.*NXOS image file is: (.*)$.*/'
17
+
18
+ system_image:
19
+ config_get_token: "kick_file_name"
20
+ test_config_get_regex: !ruby/regexp '/.*NXOS image file is: (.*)$.*/'
21
+
22
+ snmp_user:
23
+ auth_protocol:
24
+ config_get_token: "auth"
25
+
26
+ groups:
27
+ config_get_token: "group"
28
+
29
+ priv_protocol:
30
+ config_get_token: "priv"
31
+
32
+ vlan:
33
+ name:
34
+ test_config_result:
35
+ 32: "Long VLAN name knob is not enabled"
@@ -0,0 +1,196 @@
1
+ # Shared Library to compare configurations.
2
+ #
3
+ # Copyright (c) 2013-2015 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
+ # Current | Target | Configuration Case
18
+ # no command | no command | to Match Existing
19
+ # ------------------------------------------
20
+ # - - | - a | (no match or trans match)
21
+ # - - | y a | no match nor base match
22
+ # - a | - a | match
23
+ # - a | y a | (base match)
24
+ # y a | - a | (base match)
25
+ # y a | y a | match
26
+ # - b | - a | trans match
27
+ # - b | y a | (base match)
28
+ # y b | - a | (base match)
29
+ # y b | y a | trans match)
30
+
31
+ module Cisco
32
+ module ConfigParser
33
+ class Configuration
34
+ attr_accessor :configuration
35
+
36
+ # Constructor for Configuration
37
+ #
38
+ # @raise [ArgumentError] if config_str is not a String
39
+ # @param config_str [String] to parse
40
+ def initialize(config_str)
41
+ raise ArgumentError, "Argument is not a String." unless config_str.kind_of? String
42
+
43
+ @configuration = {}
44
+ @ordered_keys = []
45
+ @indent = ""
46
+ parse(config_str)
47
+ end # initialize
48
+
49
+ # build_min_config_hash
50
+ #
51
+ # Build a config hash of the minimum keys that would be needed to update
52
+ # current config to all of the changes in the "must" config. Each hash key
53
+ # is a configuration command; some keys have subconfigs which must be
54
+ # checked before dismissing top-level keys as present. This method is
55
+ # used primarily by the free-form command_config providers.
56
+ #
57
+ # @param current [Hash] superset of running-config & must config
58
+ # @param must [Hash] pending config from recipe, manifest, etc
59
+ # @param min_config [Hash] in-progress recursion-built minimum config
60
+ # @return min_config [Hash] in-progress recursion-built minimum config
61
+ #
62
+ def Configuration.build_min_config_hash(current, must, min_config={})
63
+ return {} if must.empty? # base case
64
+ must.each { |k, v| # check each must{k} is present in current{}
65
+ if current.key?(k) # if cmd is in current then compare subconfig
66
+ min_config[k] = Configuration.new("")
67
+ min_config[k].configuration =
68
+ build_min_config_hash(current[k].configuration,
69
+ v.configuration, {})
70
+ if min_config[k].configuration.empty?
71
+ # no differing subconfigs, so empty hash is returned
72
+ min_config.delete(k)
73
+ end
74
+ else # command NOT in current, apply it + all subcommands
75
+ min_config[k] = v
76
+ end
77
+ }
78
+ min_config
79
+ end # build_min_config_hash
80
+
81
+ def Configuration.config_hash_to_str(cmd_hash, str="")
82
+ return "" if cmd_hash.empty?
83
+ cmd_hash.each { |k, v|
84
+ str += k + "\n"
85
+ str += config_hash_to_str(v.configuration, "")
86
+ }
87
+ str
88
+ end # config_hash_to_str
89
+
90
+ # Get base command and prefix
91
+ #
92
+ # @param command [String]
93
+ # @return [String, String] containing prefix (if any) and
94
+ # base command.
95
+ def base_commands(command)
96
+ prefix, base = command.match(/^(no )?(.*)$/).captures
97
+ prefix = "" if prefix.nil?
98
+ [prefix, base]
99
+ end # base_commands
100
+
101
+ # Compare ConfigParser::Configuration objects
102
+ #
103
+ # @param config [ConfigParser::Configuration] obj to search
104
+ # for match.
105
+ # @return [String] containing match, empty if no match found.
106
+ def compare_with(config)
107
+ return nil if config.nil?
108
+ existing = ""
109
+ @ordered_keys.each { |config_line|
110
+ command = config_line.strip
111
+ submode = @configuration[command]
112
+ raise StopIteration, "Could not find submode." if submode.nil?
113
+
114
+ if special_command?(command)
115
+ # match special exit/end command
116
+ existing << config_line
117
+ break
118
+ elsif config.include_command?(command)
119
+ # match whole command
120
+ existing << config_line
121
+ config_submode = config.submode_config(command)
122
+ existing << submode.compare_with(config_submode)
123
+ next
124
+ end # if
125
+
126
+ prefix, base = base_commands(command)
127
+ if prefix != "" and !config.include_command?(base)
128
+ existing << config_line
129
+ next
130
+ end
131
+ }
132
+ existing
133
+ end # compare_with
134
+
135
+ # @return [Array] containing command with leading/trailing
136
+ # whitespace removed.
137
+ def mode_configuration
138
+ @ordered_keys.collect(&:strip)
139
+ end # mode_configuration
140
+
141
+ # Check command [Array] for test command
142
+ #
143
+ # @param command [String] test command
144
+ # @return [Boolean] true if command found, else false
145
+ def include_command?(command)
146
+ commands = mode_configuration()
147
+ commands.include?(command)
148
+ end # include_command?
149
+
150
+ # Parse each config command line and create a
151
+ # hash of ConfigParser::Configuration objects
152
+ #
153
+ # @param config_str [String] Config command
154
+ def parse(config_str)
155
+ config_str += "\n"
156
+ config_str.gsub!(/^\s*$\n/, '')
157
+ # ignore leading ! or # (comments)
158
+ config_str.gsub!(/^\s*[!#].*$\n/, '')
159
+ if config_str.match(/^ *\t/)
160
+ highlight_str = config_str.gsub(/\t/, '[TAB]')
161
+ raise "Tab character detected in indentation area:\n" + highlight_str
162
+ end
163
+ indent_level = config_str.match(/^\s*/)
164
+ @indent = indent_level.to_s # capture indentation of level
165
+ escaped_indent = Regexp.escape(@indent)
166
+ @ordered_keys = config_str.scan(/^#{escaped_indent}\S.*\n/) # find current configuration mode lines
167
+ @ordered_keys.each { |config_line|
168
+ command = config_line.strip
169
+ escaped_cmd = Regexp.escape(config_line)
170
+ submode_string = config_str.match(/^(?:#{escaped_cmd})((?:#{escaped_indent}\s.+\n)*)/).captures.join
171
+ @configuration[command] = Configuration.new(submode_string)
172
+ }
173
+ end # parse
174
+
175
+ # Process 'exit' and 'end' commands
176
+ #
177
+ # @param command [String] Configuration command.
178
+ # @return [Boolean] true when command is
179
+ # 'exit' or 'end', else false
180
+ def special_command?(command)
181
+ (/^(?:exit|end)/ === command)
182
+ end # special_command?
183
+
184
+ # Fetch ConfigParser::Configuration object containing config_line
185
+ #
186
+ # @param config_line [String]
187
+ # @return [ConfigParser::Configuration] containing config_line
188
+ def submode_config(config_line)
189
+ command = config_line.strip
190
+ @configuration[command]
191
+ end # submode_config
192
+
193
+ private :base_commands, :parse, :special_command?
194
+ end # Configuration
195
+ end # ConfigParser
196
+ end # Cisco
@@ -0,0 +1,501 @@
1
+ #
2
+ # NXAPI implementation of Interface class
3
+ #
4
+ # November 2015, Chris Van Heuveln
5
+ #
6
+ # Copyright (c) 2015 Cisco and/or its affiliates.
7
+ #
8
+ # Licensed under the Apache License, Version 2.0 (the "License");
9
+ # you may not use this file except in compliance with the License.
10
+ # You may obtain a copy of the License at
11
+ #
12
+ # http://www.apache.org/licenses/LICENSE-2.0
13
+ #
14
+ # Unless required by applicable law or agreed to in writing, software
15
+ # distributed under the License is distributed on an "AS IS" BASIS,
16
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
+ # See the License for the specific language governing permissions and
18
+ # limitations under the License.
19
+
20
+ require File.join(File.dirname(__FILE__), 'node')
21
+
22
+ module Cisco
23
+ IF_SWITCHPORT_MODE = {
24
+ :disabled => "",
25
+ :access => "access",
26
+ :trunk => "trunk",
27
+ :fex_fabric => "fex-fabric",
28
+ :tunnel => "dot1q-tunnel",
29
+ }
30
+
31
+ class Interface
32
+ attr_reader :name
33
+
34
+ @@node = Cisco::Node.instance
35
+
36
+ def initialize(name, instantiate=true)
37
+ raise TypeError unless name.is_a?(String)
38
+ raise ArgumentError unless name.length > 0
39
+ @name = name.downcase
40
+
41
+ create if instantiate
42
+ end
43
+
44
+ def Interface.interfaces
45
+ hash = {}
46
+ intf_list = @@node.config_get("interface", "all_interfaces")
47
+ return hash if intf_list.nil?
48
+
49
+ intf_list.each do |id|
50
+ id = id.downcase
51
+ hash[id] = Interface.new(id, false)
52
+ end
53
+ hash
54
+ end
55
+
56
+ def create
57
+ feature_vlan_set(true) if @name[/vlan/i]
58
+ @@node.config_set("interface", "create", @name)
59
+ end
60
+
61
+ def destroy
62
+ @@node.config_set("interface", "destroy", @name)
63
+ end
64
+
65
+ ########################################################
66
+ # PROPERTIES #
67
+ ########################################################
68
+
69
+ def access_vlan
70
+ vlan = @@node.config_get("interface", "access_vlan", @name)
71
+ return default_access_vlan if vlan.nil?
72
+ vlan.shift.to_i
73
+ end
74
+
75
+ def access_vlan=(vlan)
76
+ @@node.config_set("interface", "access_vlan", @name, vlan)
77
+ rescue Cisco::CliError => e
78
+ raise "[#{@name}] '#{e.command}' : #{e.clierror}"
79
+ end
80
+
81
+ def default_access_vlan
82
+ @@node.config_get_default("interface", "access_vlan")
83
+ end
84
+
85
+ def description
86
+ desc = @@node.config_get("interface", "description", @name)
87
+ return "" if desc.nil?
88
+ desc.shift.strip
89
+ end
90
+
91
+ def description=(desc)
92
+ raise TypeError unless desc.is_a?(String)
93
+ desc.empty? ?
94
+ @@node.config_set("interface", "description", @name, "no", "") :
95
+ @@node.config_set("interface", "description", @name, "", desc)
96
+ rescue Cisco::CliError => e
97
+ raise "[#{@name}] '#{e.command}' : #{e.clierror}"
98
+ end
99
+
100
+ def default_description
101
+ @@node.config_get_default("interface", "description")
102
+ end
103
+
104
+ def fex_feature
105
+ fex = @@node.config_get("fex", "feature")
106
+ raise "fex_feature not found" if fex.nil?
107
+ fex.shift.to_sym
108
+ end
109
+
110
+ def fex_feature_set(fex_set)
111
+ curr = fex_feature
112
+ return if curr == fex_set
113
+
114
+ case fex_set
115
+ when :enabled
116
+ @@node.config_set("fex", "feature_install", "") if curr == :uninstalled
117
+ @@node.config_set("fex", "feature", "")
118
+ when :disabled
119
+ @@node.config_set("fex", "feature", "no") if curr == :enabled
120
+ return
121
+ when :installed
122
+ @@node.config_set("fex", "feature_install", "") if curr == :uninstalled
123
+ when :uninstalled
124
+ @@node.config_set("fex", "feature", "no") if curr == :enabled
125
+ @@node.config_set("fex", "feature_install", "no")
126
+ end
127
+ rescue Cisco::CliError => e
128
+ raise "[#{@name}] '#{e.command}' : #{e.clierror}"
129
+ end
130
+
131
+ def ipv4_addr_mask
132
+ @@node.config_get("interface", "ipv4_addr_mask", @name)
133
+ end
134
+
135
+ def ipv4_addr_mask_set(addr, mask)
136
+ check_switchport_disabled
137
+ if addr.nil? or addr == default_ipv4_address
138
+ @@node.config_set("interface", "ipv4_addr_mask", @name, "no", "")
139
+ else
140
+ @@node.config_set("interface", "ipv4_addr_mask", @name, "",
141
+ "#{addr}/#{mask}")
142
+ end
143
+ rescue Cisco::CliError => e
144
+ raise "[#{@name}] '#{e.command}' : #{e.clierror}"
145
+ end
146
+
147
+ def ipv4_address
148
+ val = ipv4_addr_mask
149
+ return default_ipv4_address if val.nil?
150
+ addr, mask = val.shift
151
+ addr
152
+ end
153
+
154
+ def default_ipv4_address
155
+ @@node.config_get_default("interface", "ipv4_address")
156
+ end
157
+
158
+ def ipv4_netmask_length
159
+ val = ipv4_addr_mask
160
+ return default_ipv4_netmask_length if val.nil?
161
+ addr, mask = val.shift
162
+ mask.to_i
163
+ end
164
+
165
+ def default_ipv4_netmask_length
166
+ @@node.config_get_default("interface", "ipv4_netmask_length")
167
+ end
168
+
169
+ def ipv4_proxy_arp
170
+ state = @@node.config_get("interface", "ipv4_proxy_arp", @name)
171
+ state.nil? ? false : true
172
+ end
173
+
174
+ def ipv4_proxy_arp=(proxy_arp)
175
+ check_switchport_disabled
176
+ no_cmd = (proxy_arp ? "" : "no")
177
+ @@node.config_set("interface", "ipv4_proxy_arp", @name, no_cmd)
178
+ end
179
+
180
+ def default_ipv4_proxy_arp
181
+ @@node.config_get_default("interface", "ipv4_proxy_arp")
182
+ end
183
+
184
+ def ipv4_redirects_lookup_string
185
+ case @name
186
+ when /loopback/i
187
+ return "ipv4_redirects_loopback"
188
+ else
189
+ return "ipv4_redirects_other_interfaces"
190
+ end
191
+ end
192
+
193
+ def ipv4_redirects
194
+ begin
195
+ state = @@node.config_get("interface",
196
+ ipv4_redirects_lookup_string, @name)
197
+ rescue IndexError
198
+ state = nil
199
+ end
200
+ # We return default state for the platform if the platform doesn't support
201
+ # the command
202
+ return default_ipv4_redirects if state.nil? or state.empty?
203
+ state.shift[/^ip redirects$/] ? true : false
204
+ end
205
+
206
+ def ipv4_redirects=(redirects)
207
+ check_switchport_disabled
208
+ no_cmd = (redirects ? "" : "no")
209
+ @@node.config_set("interface", ipv4_redirects_lookup_string, @name, no_cmd)
210
+ rescue IndexError
211
+ raise "ipv4 redirects not supported on #{@name}"
212
+ end
213
+
214
+ def default_ipv4_redirects
215
+ @@node.config_get_default("interface", ipv4_redirects_lookup_string)
216
+ end
217
+
218
+ def negotiate_auto_lookup_string
219
+ case @name
220
+ when /Ethernet/i
221
+ return "negotiate_auto_ethernet"
222
+ when /port-channel/i # Ether-channel
223
+ return "negotiate_auto_portchannel"
224
+ else
225
+ return "negotiate_auto_other_interfaces"
226
+ end
227
+ end
228
+
229
+ def negotiate_auto
230
+ lookup = negotiate_auto_lookup_string
231
+ begin
232
+ state = @@node.config_get("interface", lookup, @name)
233
+ rescue IndexError
234
+ # We return default state even if the config_get is not supported
235
+ # for this platform / interface type. This is done so that we can set
236
+ # the manifest to 'default' so there is a 'workaround' for the
237
+ # unsupported attribute
238
+ return default_negotiate_auto
239
+ end
240
+ state.nil? ? false : true
241
+ end
242
+
243
+ def negotiate_auto=(negotiate_auto)
244
+ lookup = negotiate_auto_lookup_string
245
+ no_cmd = (negotiate_auto ? "" : "no")
246
+ begin
247
+ @@node.config_set("interface", lookup, @name, no_cmd)
248
+ rescue Cisco::CliError => e
249
+ raise "[#{@name}] '#{e.command}' : #{e.clierror}"
250
+ rescue IndexError
251
+ raise "[#{@name}] negotiate_auto is not supported on this interface"
252
+ end
253
+ end
254
+
255
+ def default_negotiate_auto
256
+ @@node.config_get_default("interface", negotiate_auto_lookup_string)
257
+ end
258
+
259
+ def shutdown
260
+ state = @@node.config_get("interface", "shutdown", @name)
261
+ state ? true : false
262
+ end
263
+
264
+ def shutdown=(state)
265
+ no_cmd = (state ? "" : "no")
266
+ @@node.config_set("interface", "shutdown", @name, no_cmd)
267
+ rescue Cisco::CliError => e
268
+ raise "[#{@name}] '#{e.command}' : #{e.clierror}"
269
+ end
270
+
271
+ def default_shutdown
272
+ case @name
273
+ when /Ethernet/i
274
+ def_sw = system_default_switchport
275
+ def_shut = system_default_switchport_shutdown
276
+
277
+ if def_sw and def_shut
278
+ lookup = "shutdown_ethernet_switchport_shutdown"
279
+ elsif def_sw and not def_shut
280
+ lookup = "shutdown_ethernet_switchport_noshutdown"
281
+ elsif not def_sw and def_shut
282
+ lookup = "shutdown_ethernet_noswitchport_shutdown"
283
+ elsif not def_sw and not def_shut
284
+ lookup = "shutdown_ethernet_noswitchport_noshutdown"
285
+ else
286
+ raise "Error: def_sw #{def_sw}, def_shut #{def_shut}"
287
+ end
288
+
289
+ when /loopback/i
290
+ lookup = "shutdown_loopback"
291
+
292
+ when /port-channel/i # EtherChannel
293
+ lookup = "shutdown_ether_channel"
294
+
295
+ when /Vlan/i
296
+ lookup = "shutdown_vlan"
297
+
298
+ else
299
+ lookup = "shutdown_unknown"
300
+ end
301
+ @@node.config_get_default("interface", lookup)
302
+ end
303
+
304
+ def switchport
305
+ # This is "switchport", not "switchport mode"
306
+ sw = @@node.config_get("interface", "switchport", @name)
307
+ sw.nil? ? false : true
308
+ end
309
+
310
+ def switchport_enable(val=true)
311
+ @@node.config_set("interface", "switchport", @name, val ? "" : "no")
312
+ end
313
+
314
+ # switchport_autostate_exclude is exclusive to switchport interfaces
315
+ def switchport_autostate_exclude
316
+ not @@node.config_get("interface",
317
+ "switchport_autostate_exclude", @name).nil?
318
+ end
319
+
320
+ def switchport_autostate_exclude=(val)
321
+ # cannot configure autostate unless feature vlan is enabled
322
+ raise "switchport mode must be configured before switchport autostate" unless
323
+ switchport
324
+ feature_vlan_set(true)
325
+ @@node.config_set("interface", "switchport_autostate_exclude",
326
+ @name, val ? "" : "no")
327
+ end
328
+
329
+ def default_switchport_autostate_exclude
330
+ @@node.config_get_default("interface", "switchport_autostate_exclude")
331
+ end
332
+
333
+ def switchport_mode_lookup_string
334
+ case @name
335
+ when /Ethernet/i
336
+ return "switchport_mode_ethernet"
337
+ when /port-channel/i
338
+ return "switchport_mode_port_channel"
339
+ else
340
+ return "switchport_mode_other_interfaces"
341
+ end
342
+ end
343
+
344
+ def switchport_mode
345
+ mode = @@node.config_get("interface", switchport_mode_lookup_string, @name)
346
+
347
+ return mode.nil? ? :disabled : IF_SWITCHPORT_MODE.key(mode.shift)
348
+
349
+ rescue IndexError
350
+ # Assume this is an interface that doesn't support switchport.
351
+ # Do not raise exception since the providers will prefetch this property
352
+ # regardless of interface type.
353
+ return :disabled
354
+ end
355
+
356
+ def switchport_enable_and_mode(mode_set)
357
+ switchport_enable unless switchport
358
+
359
+ if (:fex_fabric == mode_set)
360
+ fex_feature_set(:enabled) unless (:enabled == fex_feature)
361
+ end
362
+ @@node.config_set("interface", switchport_mode_lookup_string, @name, "",
363
+ IF_SWITCHPORT_MODE[mode_set])
364
+
365
+ rescue RuntimeError
366
+ raise "[#{@name}] switchport_mode is not supported on this interface"
367
+ end
368
+
369
+ def switchport_mode=(mode_set)
370
+ # no system default switchport
371
+ # int e1/1
372
+ # switchport
373
+ # switchport mode [access|trunk|fex|...]
374
+ raise ArgumentError unless IF_SWITCHPORT_MODE.keys.include? mode_set
375
+ case mode_set
376
+ when :disabled
377
+ if switchport
378
+ # Note: turn off switchport command, not switchport mode
379
+ @@node.config_set("interface", "switchport", @name, "no")
380
+ end
381
+
382
+ when :default
383
+ if :disabled == default_switchport_mode
384
+ @@node.config_set("interface", switchport_mode_lookup_string,
385
+ @name, "no", "")
386
+ else
387
+ switchport_enable_and_mode(mode_set)
388
+ end
389
+
390
+ else
391
+ switchport_enable_and_mode(mode_set)
392
+ end # case
393
+
394
+ rescue Cisco::CliError => e
395
+ raise "[#{@name}] '#{e.command}' : #{e.clierror}"
396
+ end
397
+
398
+ def default_switchport_mode
399
+ return :disabled unless system_default_switchport
400
+ IF_SWITCHPORT_MODE.key(
401
+ @@node.config_get_default("interface", switchport_mode_lookup_string))
402
+ end
403
+
404
+ def system_default_switchport
405
+ # This command is a user-configurable system default.
406
+ sys_def = @@node.config_get("interface", "system_default_switchport")
407
+ sys_def.nil? ? false : true
408
+ end
409
+
410
+ def system_default_switchport_shutdown
411
+ # This command is a user-configurable system default.
412
+ sys_def = @@node.config_get("interface",
413
+ "system_default_switchport_shutdown")
414
+ sys_def.nil? ? false : true
415
+ end
416
+
417
+ def system_default_svi_autostate
418
+ # This command is a user-configurable system default.
419
+ sys_def = @@node.config_get("interface",
420
+ "system_default_svi_autostate")
421
+ sys_def.nil? ? false : true
422
+ end
423
+
424
+ def switchport_vtp_mode_capable?
425
+ not switchport_mode.to_s.match(/(access|trunk)/).nil?
426
+ end
427
+
428
+ def switchport_vtp
429
+ return false unless switchport_vtp_mode_capable?
430
+ vtp = @@node.config_get("interface", "vtp", @name)
431
+ vtp.nil? ? false : true
432
+ end
433
+
434
+ def switchport_vtp=(vtp_set)
435
+ return false unless switchport_vtp_mode_capable?
436
+ no_cmd = (vtp_set) ? "" : "no"
437
+ @@node.config_set("interface", "vtp", @name, no_cmd)
438
+ rescue Cisco::CliError => e
439
+ raise "[#{@name}] '#{e.command}' : #{e.clierror}"
440
+ end
441
+
442
+ def svi_cmd_allowed?(cmd)
443
+ raise "[#{@name}] Invalid interface type for command [#{cmd}]" unless
444
+ @name[/vlan/i]
445
+ end
446
+
447
+ # svi_autostate is exclusive to svi interfaces
448
+ def svi_autostate
449
+ return nil unless @name[/^vlan/i]
450
+ not @@node.config_get("interface", "svi_autostate", @name).nil?
451
+ end
452
+
453
+ def svi_autostate=(val)
454
+ check_switchport_disabled
455
+ svi_cmd_allowed?('autostate')
456
+ @@node.config_set("interface", "svi_autostate", @name, val ? "" : "no")
457
+ end
458
+
459
+ def default_svi_autostate
460
+ system_default_svi_autostate
461
+ end
462
+
463
+ def feature_vlan?
464
+ not @@node.config_get("interface", "feature_vlan").nil?
465
+ end
466
+
467
+ def feature_vlan_set(val)
468
+ return if feature_vlan? == val
469
+ @@node.config_set("interface", "feature_vlan", val ? "" : "no")
470
+ end
471
+
472
+ # svi_management is exclusive to svi interfaces
473
+ def svi_management
474
+ return nil unless @name[/^vlan/i]
475
+ not @@node.config_get("interface", "svi_management", @name).nil?
476
+ end
477
+
478
+ def svi_management=(val)
479
+ check_switchport_disabled
480
+ svi_cmd_allowed?('management')
481
+ @@node.config_set("interface", "svi_management", @name, val ? "" : "no")
482
+ end
483
+
484
+ def default_svi_management
485
+ @@node.config_get_default("interface", "svi_management")
486
+ end
487
+
488
+ def default_switchport_vtp
489
+ @@node.config_get_default("interface", "vtp")
490
+ end
491
+
492
+ def switchport_vtp_feature?
493
+ @@node.config_get("vtp", "feature")
494
+ end
495
+
496
+ def check_switchport_disabled
497
+ raise "#{caller[0][/`.*'/][1..-2]} cannot be set unless switchport mode" +
498
+ " is disabled" unless switchport_mode == :disabled
499
+ end
500
+ end # Class
501
+ end # Module