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,113 @@
1
+ # CiscoNodeUtils - Cisco Node Utilities
2
+
3
+ The CiscoNodeUtils gem provides utilities for management of Cisco network
4
+ nodes. It is designed to work with Puppet and Chef as well as other
5
+ open source management tools. This release supports Cisco NX-OS nodes
6
+ running NX-OS 7.0(3)I2(1) and later.
7
+
8
+ ## Installation
9
+
10
+ To install the CiscoNodeUtils, use the following command:
11
+
12
+ $ gem install cisco_node_utils
13
+
14
+ (Add `sudo` if you're installing under a POSIX system as root)
15
+
16
+ Alternatively, if you've checked the source out directly, you can call
17
+ `rake install` from the root project directory.
18
+
19
+ ## Examples
20
+
21
+ These utilities can be used directly on a Cisco device (as used by Puppet
22
+ and Chef) or can run on a workstation and point to a Cisco device (as used
23
+ by the included minitest suite).
24
+
25
+ ### Usage on a Cisco device
26
+
27
+ ```ruby
28
+ require 'cisco_node_utils'
29
+
30
+ # get a connection to the local device
31
+ node = Cisco::Node.instance()
32
+
33
+ version = node.config_get("show_version", "system_image")
34
+
35
+ node.config_set("vtp", "domain", "mycompany.com")
36
+ ```
37
+
38
+ ### Remote usage
39
+
40
+ ```ruby
41
+ require 'cisco_node_utils'
42
+
43
+ Cisco::Node.lazy_connect = true
44
+
45
+ node = Cisco::Node.instance()
46
+ node.connect("n3k.mycompany.com", "username", "password")
47
+
48
+ version = node.config_get("show_version", "system_image")
49
+
50
+ node.config_set("vtp", "domain", "mycompany.com")
51
+ ```
52
+
53
+ ## Documentation
54
+
55
+ ### Node
56
+
57
+ The `Node` class is a singleton which provides for management of a given Cisco
58
+ network node. It provides the base APIs `config_set`, `config_get`, and
59
+ `config_get_default`.
60
+
61
+ ### CommandReference
62
+
63
+ The `CommandReference` module provides for the abstraction of NX-OS CLI,
64
+ especially to handle its variance between hardware platforms.
65
+ A series of YAML files are used to describe the CLI corresponding to a given
66
+ `(feature, attribute)` tuple for any given platform. When a `Node` is
67
+ connected, the platform identification of the Node is used to construct a
68
+ `CmdRef` object that corresponds to this platform. The `Node` APIs
69
+ `config_set`, `config_get`, and `config_get_default` all rely on the `CmdRef`.
70
+
71
+ See also [README_YAML](lib/cisco_node_utils/README_YAML.md).
72
+
73
+ ### Feature Providers
74
+
75
+ Each feature supported by CiscoNodeUtils has its own class. For example,
76
+ `Cisco::RouterOspf` is the class used to manage OSPF router configuration on
77
+ a `Node`. Each feature class has getters and setters which are wrappers around
78
+ the Node APIs `config_set`, `config_get`, and `config_get_default`.
79
+
80
+ ### Puppet and Chef
81
+
82
+ This library is designed as a shared backend between Puppet and Chef for the
83
+ management of Cisco nodes. Puppet providers and Chef providers alike can use
84
+ the feature provider classes from this module to do the majority of work in
85
+ actually managing device configuration and state. This reduces the amount of
86
+ code duplication between the Cisco Puppet modules and the Cisco Chef cookbooks.
87
+
88
+ Generally speaking, Puppet and Chef should only interact with the feature
89
+ provider classes, and not directly call into `CommandReference` or `Node`.
90
+
91
+ ## Changelog
92
+
93
+ See [CHANGELOG](CHANGELOG.md) for a list of changes.
94
+
95
+ ## Contributing
96
+
97
+ See [CONTRIBUTING](CONTRIBUTING.md) for developer and contributor guidelines.
98
+
99
+ ## License
100
+
101
+ Copyright (c) 2013-2015 Cisco and/or its affiliates.
102
+
103
+ Licensed under the Apache License, Version 2.0 (the "License");
104
+ you may not use this file except in compliance with the License.
105
+ You may obtain a copy of the License at
106
+
107
+ http://www.apache.org/licenses/LICENSE-2.0
108
+
109
+ Unless required by applicable law or agreed to in writing, software
110
+ distributed under the License is distributed on an "AS IS" BASIS,
111
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
112
+ See the License for the specific language governing permissions and
113
+ limitations under the License.
@@ -0,0 +1,4 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rubocop/rake_task'
3
+
4
+ RuboCop::RakeTask.new
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'cisco_node_utils/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'cisco_node_utils'
8
+ spec.version = CiscoNodeUtils::VERSION
9
+ spec.authors = ['Alex Hunsberger', 'Glenn Matthews',
10
+ 'Chris Van Heuveln', 'Mike Wiebe', 'Jie Yang']
11
+ spec.email = 'cisco_agent_gem@cisco.com'
12
+ spec.summary = 'Utilities for management of Cisco network nodes'
13
+ spec.description = <<-EOF
14
+ Utilities for management of Cisco network nodes.
15
+ Designed to work with Puppet and Chef.
16
+ Currently supports NX-OS nodes.
17
+ EOF
18
+ spec.license = 'Apache-2.0'
19
+
20
+ spec.files = `git ls-files -z`.split("\x0")
21
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
22
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
23
+ spec.require_paths = ['lib']
24
+
25
+ spec.add_development_dependency 'minitest', '>= 2.5.1', '< 5.0.0'
26
+ spec.add_development_dependency 'bundler', '~> 1.7'
27
+ spec.add_development_dependency 'rake', '~> 10.0'
28
+ spec.add_development_dependency 'rubocop', '>= 0.32'
29
+ spec.add_runtime_dependency 'cisco_nxapi', '>= 0.9'
30
+ end
@@ -0,0 +1,33 @@
1
+ # Copyright (c) 2014-2015 Cisco and/or its affiliates.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require "cisco_node_utils/cisco_cmn_utils"
16
+ require "cisco_node_utils/command_reference"
17
+ require "cisco_node_utils/configparser_lib"
18
+ require "cisco_node_utils/interface"
19
+ require "cisco_node_utils/interface_ospf"
20
+ require "cisco_node_utils/node"
21
+ require "cisco_node_utils/platform"
22
+ require "cisco_node_utils/router_ospf"
23
+ require "cisco_node_utils/router_ospf_vrf"
24
+ require "cisco_node_utils/snmpcommunity"
25
+ require "cisco_node_utils/snmpgroup"
26
+ require "cisco_node_utils/snmpserver"
27
+ require "cisco_node_utils/snmpuser"
28
+ require "cisco_node_utils/tacacs_server"
29
+ require "cisco_node_utils/tacacs_server_host"
30
+ require "cisco_node_utils/version"
31
+ require "cisco_node_utils/vlan"
32
+ require "cisco_node_utils/vtp"
33
+ require "cisco_node_utils/yum"
@@ -0,0 +1,333 @@
1
+ # Command Reference YAML
2
+
3
+ The `command_reference_*.yaml` files in this directory are used with the
4
+ `CommandReference` module as a way to abstract away platform CLI differences.
5
+
6
+ This document describes the structure and semantics of these files.
7
+
8
+ ## Structure
9
+
10
+ ```yaml
11
+ FEATURE_1:
12
+ _template:
13
+ # base parameters for all attributes of this feature go here
14
+
15
+ ATTRIBUTE_1:
16
+ config_get: 'string'
17
+ config_get_token: 'string'
18
+ config_get_token_append: 'string'
19
+ config_set: 'string'
20
+ config_set_append: 'string'
21
+ default_value: string, boolean, integer, or constant
22
+ test_config_get: 'string'
23
+ test_config_get_regexp: '/regexp/'
24
+ test_config_result:
25
+ input_1: output_1
26
+ input_2: output_2
27
+
28
+ ATTRIBUTE_2:
29
+ ...
30
+
31
+ ATTRIBUTE_3:
32
+ ...
33
+
34
+ FEATURE_2:
35
+ ...
36
+ ```
37
+
38
+ All parameters are optional and may be omitted if not needed.
39
+
40
+ ### Wildcard substitution
41
+
42
+ The `config_get_token` and `config_set` (and their associated `_append`
43
+ variants) all support two forms of wildcarding - printf-style and key-value.
44
+
45
+ #### Printf-style wildcards
46
+
47
+ ```yaml
48
+ tacacs_server_host:
49
+ encryption:
50
+ config_set: '%s tacacs-server host %s key %s %s'
51
+ ```
52
+
53
+ This permits parameter values to be passed as a simple sequence:
54
+
55
+ ```ruby
56
+ config_set('tacacs_server_host', 'encryption', 'no', 'user', 'md5', 'password')
57
+
58
+ # this becomes 'no tacacs-server host user key md5 password'
59
+ # ^^ ^^^^ ^^^ ^^^^^^^^
60
+ ```
61
+
62
+ This approach is quick to implement and concise, but less flexible - in
63
+ particular it cannot handle a case where different platforms take parameters
64
+ in a different order - and less readable in the ruby code.
65
+
66
+ #### Key-value wildcards
67
+
68
+ ```yaml
69
+ ospf:
70
+ auto_cost:
71
+ config_set: ['router ospf <name>', 'auto-cost reference-bandwidth <cost> <type>']
72
+ ```
73
+
74
+ This requires parameter values to be passed as a hash:
75
+
76
+ ```ruby
77
+ config_set('ospf', 'auto_cost', {:name => 'red',
78
+ :cost => '40',
79
+ :type => 'Gbps'})
80
+
81
+ # this becomes the config sequence:
82
+ # router ospf red
83
+ # auto-cost reference-bandwidth 40 Gbps
84
+ ```
85
+
86
+ This approach is moderately more complex to implement but is more readable in
87
+ the ruby code and is flexible enough to handle significant platform
88
+ differences in CLI. It is therefore the recommended approach for new
89
+ development.
90
+
91
+ ### `_template`
92
+
93
+ The optional `_template` section can be used to define base parameters for all
94
+ attributes of a given feature. For example, all interface attributes might be
95
+ checked with the `show running-config interface all` command, and all
96
+ attributes might be set by first entering the interface configuration submode
97
+ with the `interface <name>` configuration command. Thus, you might have:
98
+
99
+ ```yaml
100
+ interface:
101
+ _template:
102
+ config_get: 'show running-config interface all'
103
+ config_get_token: '/^interface <name>$/'
104
+ config_set: 'interface <name>'
105
+
106
+ access_vlan:
107
+ config_get_token_append: '/^switchport access vlan (.*)$/'
108
+ config_set_append: 'switchport access vlan <number>'
109
+
110
+ description:
111
+ config_get_token_append: '/^description (.*)$/'
112
+ config_set_append: 'description <desc>'
113
+
114
+ ...
115
+ ```
116
+
117
+ instead of the more repetitive (but equally valid):
118
+
119
+ ```yaml
120
+ interface:
121
+ access_vlan:
122
+ config_get: 'show running interface all'
123
+ config_get_token: ['/^interface %s$/i', '/^switchport access vlan (.*)$/']
124
+ config_set: ['interface %s', 'switchport access vlan %s']
125
+
126
+ description:
127
+ config_get: 'show running-config interface all'
128
+ config_get_token: ['/^interface <name>$/i', '/^description (.*)$/']
129
+ config_set: ['interface <name>', 'description <desc>']
130
+
131
+ ...
132
+ ```
133
+
134
+ ### `config_get`
135
+
136
+ `config_get` must be a single string representing the CLI command (usually a
137
+ `show` command) to be used to display the information needed to get the
138
+ current value of this attribute.
139
+
140
+ ```yaml
141
+ config_get: 'show running-config interface <name> all'
142
+ ```
143
+
144
+ ### `config_get_token`
145
+
146
+ `config_get_token` can be a single string, a single regex, an array of strings,
147
+ or an array of regexs.
148
+
149
+ If this value is a string or array of strings, then the `config_get` command
150
+ will be executed to produce _structured_ output and the string(s) will be
151
+ used as lookup keys.
152
+
153
+ ```yaml
154
+ show_version
155
+ cpu:
156
+ config_get: 'show version'
157
+ config_get_token: 'cpu_name'
158
+ # config_get('show_version', 'cpu') returns structured_output['cpu_name']
159
+ ```
160
+
161
+ ```yaml
162
+ inventory:
163
+ productid:
164
+ config_get: 'show inventory'
165
+ config_get_token: ['TABLE_inv', 'ROW_inv', 0, 'productid']
166
+ # config_get('inventory', 'productid') returns
167
+ # structured_output['TABLE_inv']['ROW_inv'][0]['productid']
168
+ ```
169
+
170
+ If this value is a regex or array or regexs, then the `config_get` command
171
+ will be executed to produce _plaintext_ output.
172
+
173
+ For a single regex, it will be used to match against the plaintext.
174
+
175
+ ```yaml
176
+ memory:
177
+ total:
178
+ config_get: 'show system resources'
179
+ config_get_token: '/Memory.* (\S+) total/'
180
+ # config_get('memory', 'total') returns
181
+ # plaintext_output.scan(/Memory.* (\S+) total/)
182
+ ```
183
+
184
+ For an array of regex, then the plaintext is assumed to be hierarchical in
185
+ nature (like `show running-config`) and the regexs are used to filter down
186
+ through the hierarchy.
187
+
188
+ ```yaml
189
+ interface:
190
+ description:
191
+ config_get: 'show running interface all'
192
+ config_get_token: ['/^interface %s$/i', '/^description (.*)/']
193
+ # config_get('interface', 'description', 'Ethernet1/1') gets the plaintext
194
+ # output, finds the subsection under /^interface Ethernet1/1$/i, then finds
195
+ # the line matching /^description (.*)$/ in that subsection
196
+ ```
197
+
198
+ ### `config_get_token_append`
199
+
200
+ When using a `_template` section, an attribute can use
201
+ `config_get_token_append` to extend the `config_get_token` value provided by
202
+ the template instead of replacing it:
203
+
204
+ ```yaml
205
+ interface:
206
+ _template:
207
+ config_get: 'show running-config interface all'
208
+ config_get_token: '/^interface <name>$/'
209
+
210
+ description:
211
+ config_get_token_append: '/^description (.*)$/'
212
+ # config_get_token value for 'description' is now:
213
+ # ['/^interface %s$/i', '/^description (.*)$/']
214
+ ```
215
+
216
+ This can also be used to specify conditional tokens which may or may not be
217
+ used depending on the set of parameters passed into `config_get()`:
218
+
219
+ ```yaml
220
+ bgp:
221
+ _template:
222
+ config_get: 'show running bgp all'
223
+ config_get_token: '/^router bgp <asnum>$/'
224
+ config_get_token_append:
225
+ - '/^vrf <vrf>$/'
226
+
227
+ router_id:
228
+ config_get_token_append: '/^router-id (\S+)$/'
229
+ ```
230
+
231
+ In this example, both `config_get('bgp', 'router_id', {:asnum => '1'})` and
232
+ `config_get('bgp', 'router_id', {:asnum => '1', :vrf => 'red'})` are valid -
233
+ the former will match 'router bgp 1' followed by 'router-id', while the latter
234
+ will match 'router bgp 1' followed by 'vrf red' followed by 'router-id'.
235
+
236
+ ### `config_set`
237
+
238
+ The `config_set` parameter is a string or array of strings representing the
239
+ configuration CLI command(s) used to set the value of the attribute.
240
+
241
+ ```yaml
242
+ interface:
243
+ create:
244
+ config_set: 'interface <name>'
245
+
246
+ description:
247
+ config_set: ['interface <name>', 'description <desc>']
248
+ ```
249
+
250
+ ### `config_set_append`
251
+
252
+ When using a `_template` section, an attribute can use `config_set_append` to
253
+ extend the `config_set` value provided by the template instead of replacing it:
254
+
255
+ ```yaml
256
+ interface:
257
+ _template:
258
+ config_set: 'interface <name>'
259
+
260
+ access_vlan:
261
+ config_set_append: 'switchport access vlan <number>'
262
+ # config_set value for 'access_vlan' is now:
263
+ # ['interface <name>', 'switchport access vlan <number>']
264
+ ```
265
+
266
+ Much like `config_get_token_append`, this can also be used to specify optional
267
+ commands that can be included or omitted as needed:
268
+
269
+ ```yaml
270
+ bgp:
271
+ _template:
272
+ config_set: 'router bgp <asnum>'
273
+ config_set_append:
274
+ - 'vrf <vrf>'
275
+ ```
276
+
277
+ ### `default_value`
278
+
279
+ If there is a default value for this attribute when not otherwise specified by
280
+ the user, the `default_value` parameter describes it. This can be a string,
281
+ boolean, integer, or array.
282
+
283
+ ```yaml
284
+ interface:
285
+ description:
286
+ default_value: ''
287
+
288
+ interface_ospf:
289
+ hello_interval:
290
+ default_value: 10
291
+
292
+ ospf:
293
+ auto_cost:
294
+ default_value: [40, 'Gbps']
295
+ ```
296
+
297
+ ### `test_config_get` and `test_config_get_regex`
298
+
299
+ Test-only equivalents to `config_get` and `config_get_token` - a show command
300
+ to be executed over telnet by the minitest unit test scripts, and a regex
301
+ (or array thereof) to match in the resulting plaintext output.
302
+ Should only be referenced by test scripts, never by a feature provider itself.
303
+
304
+ ```yaml
305
+ show_version:
306
+ boot_image:
307
+ test_config_get: 'show version | no-more'
308
+ test_config_get_regex: '/NXOS image file is: (.*)$/'
309
+ ```
310
+
311
+ ### `test_config_result`
312
+
313
+ Test-only container for input-result pairs that might differ by platform.
314
+ Should only be referenced by test scripts, never by a feature provider itself.
315
+
316
+ ```yaml
317
+ vtp:
318
+ version:
319
+ test_config_result:
320
+ 3: 'Cisco::CliError'
321
+ ```
322
+
323
+ ## Style Guide
324
+
325
+ Please keep all feature names in alphabetical order, and all options under a
326
+ feature in alphabetical order as well. As YAML permits duplicate entries
327
+ (in which case the last entry overrides any earlier entries), keeping a
328
+ consistent order helps to prevent accidentally introducing such duplication.
329
+
330
+ Note that `~` is the YAML syntax that corresponds to Ruby's `nil`.
331
+
332
+ Use the key-value wildcarding style wherever possible, as it's more flexible
333
+ than the printf-style wildcarding.