cisco_node_utils 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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