rbeapi 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. data/.gitignore +35 -0
  2. data/Gemfile +25 -0
  3. data/Guardfile +15 -0
  4. data/LICENSE +28 -0
  5. data/README.md +218 -0
  6. data/Rakefile +12 -0
  7. data/lib/rbeapi.rb +32 -0
  8. data/lib/rbeapi/api.rb +135 -0
  9. data/lib/rbeapi/api/aaa.rb +410 -0
  10. data/lib/rbeapi/api/dns.rb +198 -0
  11. data/lib/rbeapi/api/interfaces.rb +1193 -0
  12. data/lib/rbeapi/api/ipinterfaces.rb +328 -0
  13. data/lib/rbeapi/api/logging.rb +157 -0
  14. data/lib/rbeapi/api/mlag.rb +519 -0
  15. data/lib/rbeapi/api/ntp.rb +201 -0
  16. data/lib/rbeapi/api/ospf.rb +214 -0
  17. data/lib/rbeapi/api/prefixlists.rb +98 -0
  18. data/lib/rbeapi/api/radius.rb +317 -0
  19. data/lib/rbeapi/api/radius.rb.old +399 -0
  20. data/lib/rbeapi/api/routemaps.rb +100 -0
  21. data/lib/rbeapi/api/snmp.rb +427 -0
  22. data/lib/rbeapi/api/staticroutes.rb +88 -0
  23. data/lib/rbeapi/api/stp.rb +381 -0
  24. data/lib/rbeapi/api/switchports.rb +272 -0
  25. data/lib/rbeapi/api/system.rb +87 -0
  26. data/lib/rbeapi/api/tacacs.rb +236 -0
  27. data/lib/rbeapi/api/varp.rb +181 -0
  28. data/lib/rbeapi/api/vlans.rb +338 -0
  29. data/lib/rbeapi/client.rb +454 -0
  30. data/lib/rbeapi/eapilib.rb +334 -0
  31. data/lib/rbeapi/netdev/snmp.rb +370 -0
  32. data/lib/rbeapi/utils.rb +70 -0
  33. data/lib/rbeapi/version.rb +37 -0
  34. data/rbeapi.gemspec +32 -0
  35. data/spec/fixtures/dut.conf +5 -0
  36. data/spec/spec_helper.rb +22 -0
  37. data/spec/support/fixtures.rb +114 -0
  38. data/spec/support/shared_examples_for_api_modules.rb +124 -0
  39. data/spec/system/api_ospf_interfaces_spec.rb +58 -0
  40. data/spec/system/api_ospf_spec.rb +111 -0
  41. data/spec/system/api_varp_interfaces_spec.rb +60 -0
  42. data/spec/system/api_varp_spec.rb +44 -0
  43. data/spec/system/rbeapi/api/dns_spec.rb +77 -0
  44. data/spec/system/rbeapi/api/interfaces_base_spec.rb +94 -0
  45. data/spec/system/rbeapi/api/interfaces_ethernet_spec.rb +135 -0
  46. data/spec/system/rbeapi/api/interfaces_portchannel_spec.rb +188 -0
  47. data/spec/system/rbeapi/api/interfaces_vxlan_spec.rb +115 -0
  48. data/spec/system/rbeapi/api/ipinterfaces_spec.rb +97 -0
  49. data/spec/system/rbeapi/api/logging_spec.rb +65 -0
  50. data/spec/system/rbeapi/api/mlag_interfaces_spec.rb +80 -0
  51. data/spec/system/rbeapi/api/mlag_spec.rb +94 -0
  52. data/spec/system/rbeapi/api/ntp_spec.rb +76 -0
  53. data/spec/system/rbeapi/api/snmp_spec.rb +68 -0
  54. data/spec/system/rbeapi/api/stp_instances_spec.rb +61 -0
  55. data/spec/system/rbeapi/api/stp_interfaces_spec.rb +71 -0
  56. data/spec/system/rbeapi/api/stp_spec.rb +57 -0
  57. data/spec/system/rbeapi/api/switchports_spec.rb +135 -0
  58. data/spec/system/rbeapi/api/system_spec.rb +38 -0
  59. data/spec/system/rbeapi/api/vlans_spec.rb +121 -0
  60. metadata +274 -0
@@ -0,0 +1,317 @@
1
+ #
2
+ # Copyright (c) 2014, Arista Networks, Inc.
3
+ # All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are
7
+ # met:
8
+ #
9
+ # Redistributions of source code must retain the above copyright notice,
10
+ # this list of conditions and the following disclaimer.
11
+ #
12
+ # Redistributions in binary form must reproduce the above copyright
13
+ # notice, this list of conditions and the following disclaimer in the
14
+ # documentation and/or other materials provided with the distribution.
15
+ #
16
+ # Neither the name of Arista Networks nor the names of its
17
+ # contributors may be used to endorse or promote products derived from
18
+ # this software without specific prior written permission.
19
+ #
20
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21
+ # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22
+ # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23
+ # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS
24
+ # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
27
+ # BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28
+ # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29
+ # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
30
+ # IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
+ #
32
+ require 'rbeapi/api'
33
+
34
+
35
+ module Rbeapi
36
+ ##
37
+ # Eos is module namesapce for working with the EOS command API
38
+ module Api
39
+ ##
40
+ # Radius provides instance methods to retrieve and set radius configuration
41
+ # values.
42
+ class Radius < Entity
43
+
44
+ DEFAULT_KEY_FORMAT = 0
45
+ DEFAULT_KEY = nil
46
+
47
+ # Regular expression to extract a radius server's attributes from the
48
+ # running-configuration text. The explicit [ ] spaces enable line
49
+ # wrappping and indentation with the /x flag.
50
+ SERVER_REGEXP = /radius-server[ ]host[ ](.*?)
51
+ (?:[ ]vrf[ ]([^\s]+))?
52
+ (?:[ ]auth-port[ ](\d+))?
53
+ (?:[ ]acct-port[ ](\d+))?
54
+ (?:[ ]timeout[ ](\d+))?
55
+ (?:[ ]retransmit[ ](\d+))?
56
+ (?:[ ]key[ ](\d+)[ ](\w+))?\s/x
57
+
58
+ ##
59
+ # get Returns an Array with a single resource Hash describing the
60
+ # current state of the global radius configuration on the target device.
61
+ # This method is intended to be used by a provider's instances class
62
+ # method.
63
+ #
64
+ # The resource hash returned contains the following information:
65
+ # * key: (String) the key either in plaintext or hashed format
66
+ # * key_format: (Fixnum) e.g. 0 or 7
67
+ # * timeout: (Fixnum) seconds before the timeout period ends
68
+ # * retransmit: (Fixnum), e.g. 3, attempts after first timeout expiry.
69
+ # * servers: (Array),
70
+ #
71
+ # @api public
72
+ #
73
+ # @return [Array<Hash>] Single element Array of resource hashes
74
+ def get
75
+ global = {}
76
+ global.merge!(parse_global_timeout)
77
+ global.merge!(parse_global_retransmit)
78
+ global.merge!(parse_global_key)
79
+ resource = { global: global, servers: parse_servers }
80
+ resource
81
+ end
82
+
83
+ ##
84
+ # parse_time scans the nodes current configuraiton and parse the
85
+ # radius-server timeout value. The timeout value is expected to always
86
+ # be present in the config
87
+ #
88
+ # @api private
89
+ #
90
+ # @return [Hash<Symbol, Object>] resource hash attribute
91
+ def parse_global_timeout
92
+ value = config.scan(/radius-server timeout (\d+)/).first
93
+ { timeout: value.first.to_i }
94
+ end
95
+ private :parse_global_timeout
96
+
97
+ ##
98
+ # parse_retransmit scans the cnodes current configuration and parses the
99
+ # radius-server retransmit value. the retransmist value is expected to
100
+ # always be present in the config
101
+ #
102
+ # @api private
103
+ #
104
+ # @return [Hash<Symbol, Object>] resource hash attribute
105
+ def parse_global_retransmit
106
+ value = config.scan(/radius-server retransmit (\d+)/).first
107
+ { retransmit: value.first.to_i }
108
+ end
109
+ private :parse_global_retransmit
110
+
111
+ ##
112
+ # parse_key scans the current nodes running configuration and parse the
113
+ # global radius-server key and format value. If the key is not
114
+ # configured this method will return DEFAULT_KEY and DEFAULT_KEY_FORMAT
115
+ # for the resource hash values.
116
+ #
117
+ # @api private
118
+ #
119
+ # @return [Hash<Symbol, Object>] resource hash attribute
120
+ def parse_global_key
121
+ rsrc_hsh = {}
122
+ (key_format, key) = config.scan(/radius-server key (\d+) (\w+)/).first
123
+ rsrc_hsh[:key_format] = key_format.to_i || DEFAULT_KEY_FORMAT
124
+ rsrc_hsh[:key] = key || DEFAULT_KEY
125
+ rsrc_hsh
126
+ end
127
+ private :parse_global_key
128
+
129
+ ##
130
+ # parse_servers returns an Array of radius server resource hashes. Each
131
+ # hash describes the current state of the radius server and is intended
132
+ # to be merged into the radius resource hash
133
+ #
134
+ # The resource hash returned contains the following information:
135
+ # * hostname: hostname or ip address
136
+ # * vrf: (String) vrf name
137
+ # * key: (String) the key either in plaintext or hashed format
138
+ # * key_format: (Fixnum) e.g. 0 or 7
139
+ # * timeout: (Fixnum) seconds before the timeout period ends
140
+ # * retransmit: (Integer), e.g. 3, attempts after first timeout expiry.
141
+ # * group: (String) Server group associated with this server.
142
+ # * acct_port: (Fixnum) Port number to use for accounting.
143
+ # * accounting_only: (Boolean) Enable this server for accounting only.
144
+ # * auth_port: (Fixnum) Port number to use for authentication
145
+ #
146
+ # @api private
147
+ #
148
+ # @return [Array<Hash<Symbol,Object>>] Array of resource hashes
149
+ def parse_servers
150
+ tuples = config.scan(SERVER_REGEXP)
151
+ tuples.map do |(host, vrf, authp, acctp, tout, tries, keyfm, key)|
152
+ hsh = {}
153
+ hsh[:hostname] = host
154
+ hsh[:vrf] = vrf
155
+ hsh[:auth_port] = authp.to_i
156
+ hsh[:acct_port] = acctp.to_i
157
+ hsh[:timeout] = tout.to_i
158
+ hsh[:retransmit] = tries.to_i
159
+ hsh[:key_format] = keyfm.to_i
160
+ hsh[:key] = key
161
+ hsh
162
+ end
163
+ end
164
+ private :parse_servers
165
+
166
+ ##
167
+ # set_global_key configures the global radius-server key. If the value option
168
+ # is not specified, radius-server key is configured using the no keyword.
169
+ # If the default option is specified, radius-server key is configured
170
+ # using the default keyword. If both options are specified, the default
171
+ # keyword option takes precedence.
172
+ #
173
+ # @eos_version 4.13.7M
174
+ #
175
+ # @commands
176
+ # radius-server key <format> <value>
177
+ # no radius-server key
178
+ # default radius-server key
179
+ #
180
+ # @option [String] :value The value to configure the radius-server key to
181
+ # in the nodes running configuration
182
+ #
183
+ # @option [Fixnum] :key_format The format of the key to be passed to the
184
+ # nodes running configuration. Valid values are 0 (cleartext) or 7
185
+ # (encrypted). The default value is 0 if format is not provided.
186
+ #
187
+ # @option [Boolean] :default Configures the radius-server key using the
188
+ # default keyword argument
189
+ #
190
+ # @return [Boolean] returns true if the commands complete successfully
191
+ def set_global_key(opts = {})
192
+ value = opts[:value]
193
+ key_format = opts[:key_format] || 0
194
+ default = opts[:default] || false
195
+
196
+ case default
197
+ when true
198
+ cmds = 'default radius-server key'
199
+ when false
200
+ cmds = value ? "radius-server key #{key_format} #{value}" :
201
+ 'no radius-server key'
202
+ end
203
+ configure cmds
204
+ end
205
+
206
+ ##
207
+ # set_global_timeout configures the radius-server timeout value. If the value
208
+ # options is not specified, radius-server timeout is configured using the
209
+ # no keyword. If the default option is specified, radius-server timeout
210
+ # is configured using the default keyword. If both options are specified
211
+ # then the default keyword takes precedence.
212
+ #
213
+ # @eos_version 4.13.7M
214
+ #
215
+ # @commands
216
+ # radius-server timeout <value>
217
+ # no radius-server timeout
218
+ # default radius-server timeout
219
+ #
220
+ # @option [String, Fixnum] :value The value to set the global
221
+ # radius-server timeout value to. This value should be in the range of
222
+ # 1 to 1000
223
+ #
224
+ # @option [Boolean] :default Configures the radius-server timeout value
225
+ # using the default keyword.
226
+ #
227
+ # @return [Boolean] returns true if the commands complete successfully
228
+ def set_global_timeout(opts = {})
229
+ value = opts[:value]
230
+ default = opts[:default] || false
231
+
232
+ case default
233
+ when true
234
+ cmds = 'default radius-server timeout'
235
+ when false
236
+ cmds = value ? "radius-server timeout #{value}" :
237
+ 'no radius-server timeout'
238
+ end
239
+ configure cmds
240
+ end
241
+
242
+ ##
243
+ # set_global_retransmit configures the global radius-server restransmit value.
244
+ # If the value is not specified, the radius-server retransmist value is
245
+ # configured using the no keyword. If the default option is specified,
246
+ # the radius-server retransmit value is configured using the default
247
+ # keyword. If both options are specified then the default keyword taks
248
+ # precedence
249
+ #
250
+ # @eos_version 4.13.7M
251
+ #
252
+ # @commands
253
+ # radius-server retransmit <value>
254
+ # no radius-server retransmit
255
+ # default radius-server retrasmit
256
+ #
257
+ # @option [String, Fixnum] :value The valu to set the global
258
+ # radius-server retransmit value to. This value should be in the range
259
+ # of 1 to 100
260
+ #
261
+ # @option [Boolean] :default Configures the radius-server retransmit
262
+ # value using the default keyword
263
+ #
264
+ # @return [Boolean] returns true if the commands complete successfully
265
+ def set_global_retransmit(opts = {})
266
+ value = opts[:value]
267
+ default = opts[:default] || false
268
+
269
+ case default
270
+ when true
271
+ cmds = 'default radius-server retransmit'
272
+ when false
273
+ cmds = value ? "radius-server retransmit #{value}" :
274
+ 'no radius-server retransmit'
275
+ end
276
+ configure cmds
277
+ end
278
+
279
+ ##
280
+ # update_server configures a radius server resource on the target device.
281
+ # This API method maps to the `radius server host` command, e.g.
282
+ # `radius-server host 10.11.12.13 auth-port 1024 acct-port 2048 timeout
283
+ # 30 retransmit 5 key 7 011204070A5955`
284
+ #
285
+ # @api public
286
+ #
287
+ # @return [Boolean] true if there are no errors
288
+ def update_server(opts = {})
289
+ # beware: order of cli keyword options counts
290
+ key_format = opts[:key_format] || 7
291
+ cmd = "radius-server host #{opts[:hostname]}"
292
+ cmd << " vrf #{opts[:vrf]}" if opts[:vrf]
293
+ cmd << " auth-port #{opts[:auth_port]}" if opts[:auth_port]
294
+ cmd << " acct-port #{opts[:acct_port]}" if opts[:acct_port]
295
+ cmd << " timeout #{opts[:timeout]}" if opts[:timeout]
296
+ cmd << " retransmit #{opts[:retransmit]}" if opts[:retransmit]
297
+ cmd << " key #{key_format} #{opts[:key]}" if opts[:key]
298
+ configure cmd
299
+ end
300
+
301
+ ##
302
+ # remove_server removes the SNMP server identified by the hostname,
303
+ # auth_port, and acct_port attributes.
304
+ #
305
+ # @api public
306
+ #
307
+ # @return [Boolean] true if no errors
308
+ def remove_server(opts = {})
309
+ cmd = "no radius-server host #{opts[:hostname]}"
310
+ cmd << " vrf #{opts[:vrf]}" if opts[:vrf]
311
+ cmd << " auth-port #{opts[:auth_port]}" if opts[:auth_port]
312
+ cmd << " acct-port #{opts[:acct_port]}" if opts[:acct_port]
313
+ configure cmd
314
+ end
315
+ end
316
+ end
317
+ end
@@ -0,0 +1,399 @@
1
+ #
2
+ # Copyright (c) 2014, Arista Networks, Inc.
3
+ # All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are
7
+ # met:
8
+ #
9
+ # Redistributions of source code must retain the above copyright notice,
10
+ # this list of conditions and the following disclaimer.
11
+ #
12
+ # Redistributions in binary form must reproduce the above copyright
13
+ # notice, this list of conditions and the following disclaimer in the
14
+ # documentation and/or other materials provided with the distribution.
15
+ #
16
+ # Neither the name of Arista Networks nor the names of its
17
+ # contributors may be used to endorse or promote products derived from
18
+ # this software without specific prior written permission.
19
+ #
20
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21
+ # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22
+ # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23
+ # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS
24
+ # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
27
+ # BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28
+ # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29
+ # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
30
+ # IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
+ #
32
+ require 'rbeapi/api'
33
+
34
+
35
+ module Rbeapi
36
+ ##
37
+ # Eos is module namesapce for working with the EOS command API
38
+ module Api
39
+ ##
40
+ # Radius provides instance methods to retrieve and set radius configuration
41
+ # values.
42
+ class Radius < Entity
43
+
44
+ DEFAULT_AUTH_PORT = 1812
45
+ DEFAULT_ACCT_PORT = 1813
46
+
47
+ # Regular expression to extract a radius server's attributes from the
48
+ # running-configuration text. The explicit [ ] spaces enable line
49
+ # wrappping and indentation with the /x flag.
50
+ SERVER_REGEXP = /radius-server[ ]host[ ](.*?)
51
+ (?:[ ]auth-port[ ](\d+))?
52
+ (?:[ ]acct-port[ ](\d+))?
53
+ (?:[ ]timeout[ ](\d+))?
54
+ (?:[ ]deadtime[ ](\d+))?
55
+ (?:[ ]retransmit[ ](\d+))?
56
+ (?:[ ]key[ ](\d+)[ ](\w+))?\s/x
57
+
58
+ GROUP_MEMBER_REGEXP = /server[ ](.*?)
59
+ (?:[ ]auth-port[ ](\d+))?
60
+ (?:[ ]acct-port[ ](\d+))?\s/x
61
+
62
+ # Regular expression to extract a radius server's attributes from the
63
+ # running-configuration text. The explicit [ ] spaces enable line
64
+ # wrappping and indentation with the /x flag.
65
+ SERVER_GROUP_REGEXP = /aaa group server radius (.*)/
66
+
67
+ ##
68
+ # getall Returns an Array with a single resource Hash describing the
69
+ # current state of the global radius configuration on the target device.
70
+ # This method is intended to be used by a provider's instances class
71
+ # method.
72
+ #
73
+ # The resource hash returned contains the following information:
74
+ # * name: ('settings')
75
+ # * enable: (true | false) if radius functionality is enabled. This is
76
+ # always true for EOS.
77
+ # * key: (String) the key either in plaintext or hashed format
78
+ # * key_format: (Integer) e.g. 0 or 7
79
+ # * timeout: (Integer) seconds before the timeout period ends
80
+ # * retransmit_count: (Integer), e.g. 3, attempts after first timeout
81
+ # expiry.
82
+ #
83
+ # @api public
84
+ #
85
+ # @return [Array<Hash>] Single element Array of resource hashes
86
+ def getall
87
+ rsrc_hsh = radius_global_defaults
88
+ rsrc_hsh.merge!(parse_global_key(config))
89
+ rsrc_hsh.merge!(parse_global_timeout(config))
90
+ rsrc_hsh.merge!(parse_global_retransmit(config))
91
+ [rsrc_hsh]
92
+ end
93
+
94
+ ##
95
+ # servers returns an Array of radius server resource hashes. Each hash
96
+ # describes the current state of the radius server and is suitable for
97
+ # use in initializing a radius_server provider.
98
+ #
99
+ # The resource hash returned contains the following information:
100
+ # * hostname: hostname or ip address
101
+ # * key: (String) the key either in plaintext or hashed format
102
+ # * key_format: (Fixnum) e.g. 0 or 7
103
+ # * timeout: (Fixnum) seconds before the timeout period ends
104
+ # * retransmit_count: (Integer), e.g. 3, attempts after first timeout
105
+ # expiry.
106
+ # * group: (String) Server group associated with this server.
107
+ # * deadtime: (Fixnum) number of minutes to ignore an unresponsive
108
+ # server.
109
+ # * acct_port: (Fixnum) Port number to use for accounting.
110
+ # * accounting_only: (Boolean) Enable this server for accounting only.
111
+ # * auth_port: (Fixnum) Port number to use for authentication
112
+ #
113
+ # @api public
114
+ #
115
+ # @return [Array<Hash<Symbol,Object>>] Array of resource hashes
116
+ def servers
117
+ config = running_configuration
118
+ tuples = config.scan(SERVER_REGEXP)
119
+ tuples.map do |(host, authp, acctp, tout, dead, tries, keyfm, key)|
120
+ hsh = { auth_port: DEFAULT_AUTH_PORT, acct_port: DEFAULT_ACCT_PORT }
121
+ hsh[:hostname] = host if host
122
+ hsh[:auth_port] = authp.to_i if authp
123
+ hsh[:acct_port] = acctp.to_i if acctp
124
+ hsh[:timeout] = tout.to_i if tout
125
+ hsh[:retransmit_count] = tries.to_i if tries
126
+ hsh[:deadtime] = dead.to_i if dead
127
+ hsh[:key_format] = keyfm.to_i if keyfm
128
+ hsh[:key] = key if key
129
+ hsh
130
+ end
131
+ end
132
+
133
+ ##
134
+ # server_groups retrieves a list of radius server groups from the target
135
+ # device.
136
+ #
137
+ # @api public
138
+ #
139
+ # @return [Array<Hash<Symbol,Object>>] Array of resource hashes
140
+ def server_groups
141
+ config = running_configuration
142
+ tuples = config.scan(SERVER_GROUP_REGEXP)
143
+ tuples.map do |(name)|
144
+ { name: name, servers: parse_group_servers(config, name) }
145
+ end
146
+ end
147
+
148
+ ##
149
+ # parse_group_servers parses the list of servers associated with a radius
150
+ # server group given a group name and a running configuration text.
151
+ #
152
+ # @param [String] config The running configuration text.
153
+ #
154
+ # @param [String] name The name of the server group to parse.
155
+ #
156
+ # @api private
157
+ #
158
+ # @return [Array<Hash<Symbol,Object>] Array of server attributes
159
+ def parse_group_servers(config, name)
160
+ regexp = /aaa group server radius #{name}(.*?)!/m
161
+ mdata = regexp.match(config)
162
+ if mdata
163
+ tuples = mdata[1].scan(GROUP_MEMBER_REGEXP)
164
+ tuples.collect do |(hostname, auth_port, acct_port)|
165
+ {
166
+ hostname: hostname,
167
+ auth_port: auth_port ? auth_port.to_i : DEFAULT_AUTH_PORT,
168
+ acct_port: acct_port ? acct_port.to_i : DEFAULT_ACCT_PORT
169
+ }
170
+ end
171
+ else
172
+ Array.new
173
+ end
174
+ end
175
+
176
+ ##
177
+ # update_server_group updates a radius server group given an Array of
178
+ # server attributes and the name of the server group. The update happens
179
+ # by first deleting the existing group if it exists then creating it
180
+ # again with all of the specified servers.
181
+ #
182
+ # @param [String] name The name of the server group to update
183
+ #
184
+ # @param [Array<Hash<Symbol,Object>>] servers The array of servers to
185
+ # associate with the server group. This hash should have at least the
186
+ # :hostname key.
187
+ #
188
+ # @api public
189
+ #
190
+ # @return [Boolean] true if no errors
191
+ def update_server_group(opts = {})
192
+ cmd = "aaa group server radius #{opts[:name]}"
193
+ api.config("no #{cmd}")
194
+ cmds = [cmd]
195
+ opts[:servers].each do |hsh|
196
+ server = "server #{hsh[:hostname]}"
197
+ server << " auth-port #{hsh[:auth_port] || DEFAULT_AUTH_PORT}"
198
+ server << " acct-port #{hsh[:acct_port] || DEFAULT_ACCT_PORT}"
199
+ cmds << server
200
+ end
201
+ result = api.config(cmds)
202
+ !result.find { |r| r != {} }
203
+ end
204
+
205
+ ##
206
+ # remove_server_group removes a radius server group by name. This API
207
+ # call maps to the `no aaa group server radius <name>` command.
208
+ #
209
+ # @option opts [String] :name ('RAD-SV2') The name of the radius server
210
+ # group to remove.
211
+ #
212
+ # @api public
213
+ #
214
+ # @return [Boolean] true if no errors
215
+ def remove_server_group(opts = {})
216
+ result = api.config("no aaa group server radius #{opts[:name]}")
217
+ result == [{}]
218
+ end
219
+
220
+ ##
221
+ # update_server configures a radius server resource on the target device.
222
+ # This API method maps to the `radius server host` command, e.g.
223
+ # `radius-server host 10.11.12.13 auth-port 1024 acct-port 2048 timeout
224
+ # 30 retransmit 5 key 7 011204070A5955`
225
+ #
226
+ # @api public
227
+ #
228
+ # @return [Boolean] true if there are no errors
229
+ def update_server(opts = {})
230
+ retransmit = opts[:retransmit_count]
231
+ key_format = opts[:key_format] || 7
232
+ cmd = "radius-server host #{opts[:hostname]}"
233
+ cmd << " auth-port #{opts[:auth_port]}" if opts[:auth_port]
234
+ cmd << " acct-port #{opts[:acct_port]}" if opts[:acct_port]
235
+ cmd << " timeout #{opts[:timeout]}" if opts[:timeout]
236
+ cmd << " deadtime #{opts[:deadtime]}" if opts[:deadtime]
237
+ cmd << " retransmit #{retransmit}" if retransmit
238
+ cmd << " key #{key_format} #{opts[:key]}" if opts[:key]
239
+ result = api.config(cmd)
240
+ result == [{}]
241
+ end
242
+
243
+ ##
244
+ # remove_server removes the SNMP server identified by the hostname,
245
+ # auth_port, and acct_port attributes.
246
+ #
247
+ # @api public
248
+ #
249
+ # @return [Boolean] true if no errors
250
+ def remove_server(opts = {})
251
+ cmd = "no radius-server host #{opts[:hostname]}"
252
+ cmd << " auth-port #{opts[:auth_port]}" if opts[:auth_port]
253
+ cmd << " acct-port #{opts[:acct_port]}" if opts[:acct_port]
254
+ result = api.config(cmd)
255
+ result == [{}]
256
+ end
257
+
258
+ ##
259
+ # radius_global_defaults returns the default values for the radius_global
260
+ # resource. This is in a single method to keep the information in one
261
+ # place. If a value is explicitly configured to be the same as a default
262
+ # value it will not show up in the running configuration and as a result
263
+ # will not be parsed out by the parse instance methods. This method
264
+ # exposes the default values.
265
+ #
266
+ # @return [Array<Hash>] Single element Array of resource hashes
267
+ def radius_global_defaults
268
+ {
269
+ name: 'settings',
270
+ enable: true,
271
+ timeout: 5,
272
+ retransmit_count: 3
273
+ }
274
+ end
275
+ private :radius_global_defaults
276
+
277
+ ##
278
+ # parse_global_key takes a running configuration as a string and
279
+ # parses out the radius global key and global key format if it exists in
280
+ # the configuration. An empty Hash is returned if there is no global key
281
+ # configured. The intent of the Hash is to be merged into a property
282
+ # hash.
283
+ #
284
+ # @param [String] config The running configuration as a single string.
285
+ #
286
+ # @api private
287
+ #
288
+ # @return [Hash<Symbol,Object>] resource hash attributes
289
+ def parse_global_key(config)
290
+ rsrc_hsh = {}
291
+ (key_format, key) = config.scan(/radius-server key (\d+) (\w+)/).first
292
+ rsrc_hsh[:key_format] = key_format.to_i if key_format
293
+ rsrc_hsh[:key] = key if key
294
+ rsrc_hsh
295
+ end
296
+ private :parse_global_key
297
+
298
+ ##
299
+ # parse_global_timeout takes a running configuration as a string
300
+ # and parses out the radius global timeout if it exists in the
301
+ # configuration. An empty Hash is returned if there is no global timeout
302
+ # value configured. The intent of the Hash is to be merged into a
303
+ # property hash.
304
+ #
305
+ # @param [String] config The running configuration as a single string.
306
+ #
307
+ # @api private
308
+ #
309
+ # @return [Hash<Symbol,Object>] resource hash attributes
310
+ def parse_global_timeout(config)
311
+ rsrc_hsh = {}
312
+ timeout = config.scan(/radius-server timeout (\d+)/).first
313
+ # EOS default is 5 (does not show up in the running config)
314
+ rsrc_hsh[:timeout] = timeout.first.to_i if timeout
315
+ rsrc_hsh
316
+ end
317
+ private :parse_global_timeout
318
+
319
+ ##
320
+ # parse_global_retransmit takes a running configuration as a string and
321
+ # parses out the radius global retransmit count value if it exists in the
322
+ # configuration. An empty Hash is returned if there is no global timeout
323
+ # value configured. The intent of the Hash is to be merged into a
324
+ # property hash.
325
+ #
326
+ # @param [String] config The running configuration as a single string.
327
+ #
328
+ # @api private
329
+ #
330
+ # @return [Hash<Symbol,Object>] resource hash attributes
331
+ def parse_global_retransmit(config)
332
+ rsrc_hsh = {}
333
+ count = config.scan(/radius-server retransmit (\d+)/).first
334
+ # EOS default is 3 (does not show up in the running config)
335
+ rsrc_hsh[:retransmit_count] = count.first.to_i if count
336
+ rsrc_hsh
337
+ end
338
+ private :parse_global_retransmit
339
+
340
+ ##
341
+ # set_global_key configures the radius default key. This method maps to
342
+ # the `radius-server key` EOS configuration command, e.g. `radius-server
343
+ # key 7 070E234F1F5B4A`.
344
+ #
345
+ # @option opts [String] :key ('070E234F1F5B4A') The key value
346
+ #
347
+ # @option opts [Fixnum] :key_format (7) The key format, 0 for plaintext
348
+ # and 7 for a hashed value. 7 will be assumed if this option is not
349
+ # provided.
350
+ #
351
+ # @api public
352
+ #
353
+ # @return [Boolean] true if no errors
354
+ def set_global_key(opts = {})
355
+ format = opts[:key_format] || 7
356
+ key = opts[:key]
357
+ fail ArgumentError, 'key option is required' unless key
358
+ result = api.config("radius-server key #{format} #{key}")
359
+ result == [{}]
360
+ end
361
+
362
+ ##
363
+ # set_timeout configures the radius default timeout. This method maps to
364
+ # the `radius-server timeout` setting.
365
+ #
366
+ # @option opts [Fixnum] :timeout (50) The timeout in seconds to
367
+ # configure.
368
+ #
369
+ # @api public
370
+ #
371
+ # @return [Boolean] true if no errors
372
+ def set_timeout(opts = {})
373
+ timeout = opts[:timeout]
374
+ fail ArgumentError, 'timeout option is required' unless timeout
375
+ result = api.config("radius-server timeout #{timeout}")
376
+ result == [{}]
377
+ end
378
+
379
+ ##
380
+ # set_retransmit_count configures the radius default retransmit count.
381
+ # This method maps to the `radius-server retransmit` configuration
382
+ # command.
383
+ #
384
+ # @option opts [Fixnum] :retransmit_count (4) The number of times to
385
+ # retry an unresponsive server after the first timeout period.
386
+ #
387
+ # @api public
388
+ #
389
+ # @return [Boolean] true if no errors
390
+ def set_retransmit_count(opts = {})
391
+ retransmit_count = opts[:retransmit_count]
392
+ fail ArgumentError,
393
+ 'retransmit_count option is required' unless retransmit_count
394
+ result = api.config("radius-server retransmit #{retransmit_count}")
395
+ result == [{}]
396
+ end
397
+ end
398
+ end
399
+ end