rbeapi 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +35 -0
- data/Gemfile +25 -0
- data/Guardfile +15 -0
- data/LICENSE +28 -0
- data/README.md +218 -0
- data/Rakefile +12 -0
- data/lib/rbeapi.rb +32 -0
- data/lib/rbeapi/api.rb +135 -0
- data/lib/rbeapi/api/aaa.rb +410 -0
- data/lib/rbeapi/api/dns.rb +198 -0
- data/lib/rbeapi/api/interfaces.rb +1193 -0
- data/lib/rbeapi/api/ipinterfaces.rb +328 -0
- data/lib/rbeapi/api/logging.rb +157 -0
- data/lib/rbeapi/api/mlag.rb +519 -0
- data/lib/rbeapi/api/ntp.rb +201 -0
- data/lib/rbeapi/api/ospf.rb +214 -0
- data/lib/rbeapi/api/prefixlists.rb +98 -0
- data/lib/rbeapi/api/radius.rb +317 -0
- data/lib/rbeapi/api/radius.rb.old +399 -0
- data/lib/rbeapi/api/routemaps.rb +100 -0
- data/lib/rbeapi/api/snmp.rb +427 -0
- data/lib/rbeapi/api/staticroutes.rb +88 -0
- data/lib/rbeapi/api/stp.rb +381 -0
- data/lib/rbeapi/api/switchports.rb +272 -0
- data/lib/rbeapi/api/system.rb +87 -0
- data/lib/rbeapi/api/tacacs.rb +236 -0
- data/lib/rbeapi/api/varp.rb +181 -0
- data/lib/rbeapi/api/vlans.rb +338 -0
- data/lib/rbeapi/client.rb +454 -0
- data/lib/rbeapi/eapilib.rb +334 -0
- data/lib/rbeapi/netdev/snmp.rb +370 -0
- data/lib/rbeapi/utils.rb +70 -0
- data/lib/rbeapi/version.rb +37 -0
- data/rbeapi.gemspec +32 -0
- data/spec/fixtures/dut.conf +5 -0
- data/spec/spec_helper.rb +22 -0
- data/spec/support/fixtures.rb +114 -0
- data/spec/support/shared_examples_for_api_modules.rb +124 -0
- data/spec/system/api_ospf_interfaces_spec.rb +58 -0
- data/spec/system/api_ospf_spec.rb +111 -0
- data/spec/system/api_varp_interfaces_spec.rb +60 -0
- data/spec/system/api_varp_spec.rb +44 -0
- data/spec/system/rbeapi/api/dns_spec.rb +77 -0
- data/spec/system/rbeapi/api/interfaces_base_spec.rb +94 -0
- data/spec/system/rbeapi/api/interfaces_ethernet_spec.rb +135 -0
- data/spec/system/rbeapi/api/interfaces_portchannel_spec.rb +188 -0
- data/spec/system/rbeapi/api/interfaces_vxlan_spec.rb +115 -0
- data/spec/system/rbeapi/api/ipinterfaces_spec.rb +97 -0
- data/spec/system/rbeapi/api/logging_spec.rb +65 -0
- data/spec/system/rbeapi/api/mlag_interfaces_spec.rb +80 -0
- data/spec/system/rbeapi/api/mlag_spec.rb +94 -0
- data/spec/system/rbeapi/api/ntp_spec.rb +76 -0
- data/spec/system/rbeapi/api/snmp_spec.rb +68 -0
- data/spec/system/rbeapi/api/stp_instances_spec.rb +61 -0
- data/spec/system/rbeapi/api/stp_interfaces_spec.rb +71 -0
- data/spec/system/rbeapi/api/stp_spec.rb +57 -0
- data/spec/system/rbeapi/api/switchports_spec.rb +135 -0
- data/spec/system/rbeapi/api/system_spec.rb +38 -0
- data/spec/system/rbeapi/api/vlans_spec.rb +121 -0
- metadata +274 -0
@@ -0,0 +1,272 @@
|
|
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
|
+
module Rbeapi
|
35
|
+
##
|
36
|
+
# Eos is module namesapce for working with the EOS command API
|
37
|
+
module Api
|
38
|
+
##
|
39
|
+
# The Switchport class provides a base class instance for working with
|
40
|
+
# logical layer-2 interfaces.
|
41
|
+
#
|
42
|
+
class Switchports < Entity
|
43
|
+
|
44
|
+
##
|
45
|
+
# Retrieves the properies for a logical switchport from the
|
46
|
+
# running-config using eAPI
|
47
|
+
#
|
48
|
+
# Example
|
49
|
+
# {
|
50
|
+
# "name": <String>,
|
51
|
+
# "mode": [access, trunk],
|
52
|
+
# "trunk_allowed_vlans": array<strings>
|
53
|
+
# "trunk_native_vlan": <Integer>,
|
54
|
+
# "access_vlan": <Integer>
|
55
|
+
# }
|
56
|
+
#
|
57
|
+
# @param [String] name The full name of the interface to get. The
|
58
|
+
# interface name must be the full interface (ie Ethernet, not Et)
|
59
|
+
#
|
60
|
+
# @return [Hash] a hash that includes the switchport properties
|
61
|
+
def get(name)
|
62
|
+
config = get_block("interface #{name}")
|
63
|
+
return nil unless config
|
64
|
+
return nil if /no\sswitchport$/ =~ config
|
65
|
+
|
66
|
+
response = {}
|
67
|
+
response.merge!(parse_mode(config))
|
68
|
+
response.merge!(parse_access_vlan(config))
|
69
|
+
response.merge!(parse_trunk_native_vlan(config))
|
70
|
+
response.merge!(parse_trunk_allowed_vlans(config))
|
71
|
+
response
|
72
|
+
end
|
73
|
+
|
74
|
+
def parse_mode(config)
|
75
|
+
mdata = /(?<=\s{3}switchport\smode\s)(.+)$/.match(config)
|
76
|
+
{ mode: mdata[1] }
|
77
|
+
end
|
78
|
+
|
79
|
+
def parse_access_vlan(config)
|
80
|
+
mdata = /(?<=access\svlan\s)(.+)$/.match(config)
|
81
|
+
{ access_vlan: mdata[1] }
|
82
|
+
end
|
83
|
+
|
84
|
+
def parse_trunk_native_vlan(config)
|
85
|
+
mdata = /(?<=trunk\snative\svlan\s)(.+)$/.match(config)
|
86
|
+
{ trunk_native_vlan: mdata[1] }
|
87
|
+
end
|
88
|
+
|
89
|
+
def parse_trunk_allowed_vlans(config)
|
90
|
+
mdata = /(?<=trunk\sallowed\svlan\s)(.+)$/.match(config)
|
91
|
+
return { trunk_allowed_vlans: [] } unless mdata[1] != 'none'
|
92
|
+
vlans = mdata[1].split(',')
|
93
|
+
values = vlans.each_with_object([]) do |vlan, arry|
|
94
|
+
if /-/ !~ vlan
|
95
|
+
arry << vlan.to_i
|
96
|
+
else
|
97
|
+
range_start, range_end = vlan.split('-')
|
98
|
+
arry.push(*Array(range_start.to_i..range_end.to_i))
|
99
|
+
end
|
100
|
+
end
|
101
|
+
{ trunk_allowed_vlans: values }
|
102
|
+
end
|
103
|
+
|
104
|
+
##
|
105
|
+
# Retrieves all switchport interfaces from the running-config
|
106
|
+
#
|
107
|
+
# @return [Array] an array of switchport hashes
|
108
|
+
def getall
|
109
|
+
interfaces = config.scan(/(?<=^interface\s)([Et|Po].+)$/)
|
110
|
+
interfaces.each_with_object({}) do |port, hsh|
|
111
|
+
cfg = get port.first
|
112
|
+
hsh[port.first] = cfg if cfg
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
##
|
117
|
+
# Creates a new logical switchport interface in EOS
|
118
|
+
#
|
119
|
+
# @param [String] name The name of the logical interface
|
120
|
+
#
|
121
|
+
# @return [Boolean] True if it succeeds otherwise False
|
122
|
+
def create(name)
|
123
|
+
configure ["interface #{name}", 'no ip address', 'switchport']
|
124
|
+
end
|
125
|
+
|
126
|
+
##
|
127
|
+
# Deletes a logical switchport interface from the running-config
|
128
|
+
#
|
129
|
+
# @param [String] name The name of the logical interface
|
130
|
+
#
|
131
|
+
# @return [Boolean] True if it succeeds otherwise False
|
132
|
+
def delete(name)
|
133
|
+
configure ["interface #{name}", 'no switchport']
|
134
|
+
end
|
135
|
+
|
136
|
+
##
|
137
|
+
# Defaults a logical switchport interface in the running-config
|
138
|
+
#
|
139
|
+
# @param [String] name The name of the logical interface
|
140
|
+
#
|
141
|
+
# @return [Boolean] True if it succeeds otherwise False
|
142
|
+
def default(name)
|
143
|
+
configure ["interface #{name}", 'default switchport']
|
144
|
+
end
|
145
|
+
|
146
|
+
##
|
147
|
+
# Configures the switchport mode for the specified interafce. Valid
|
148
|
+
# modes are access (default) or trunk
|
149
|
+
#
|
150
|
+
# @param [String] name The name of the interface to configure
|
151
|
+
# @param [Hash] opts The configuration parameters for the interface
|
152
|
+
# @option opts [string] :value The value to set the mode to
|
153
|
+
# @option opts [Boolean] :default The value should be set to default
|
154
|
+
#
|
155
|
+
# @return [Boolean] True if the commands succeed otherwise False
|
156
|
+
def set_mode(name, opts = {})
|
157
|
+
value = opts[:value]
|
158
|
+
default = opts[:default] || false
|
159
|
+
|
160
|
+
cmds = ["interface #{name}"]
|
161
|
+
case default
|
162
|
+
when true
|
163
|
+
cmds << 'default switchport mode'
|
164
|
+
when false
|
165
|
+
cmds << (value.nil? ? 'no switchport mode' : \
|
166
|
+
"switchport mode #{value}")
|
167
|
+
end
|
168
|
+
configure(cmds)
|
169
|
+
end
|
170
|
+
|
171
|
+
##
|
172
|
+
# set_trunk_allowed_vlans configures the list of vlan ids that are
|
173
|
+
# allowed on the specified trunk port. If the value option is not
|
174
|
+
# provided, then the allowed trunks is configured using the no keyword.
|
175
|
+
# If the default keyword is provied then the allowed trunks is configured
|
176
|
+
# using the default keywork The default optio takes precedence over the
|
177
|
+
# value option if both are specified
|
178
|
+
#
|
179
|
+
# @eos_version 4.13.7M
|
180
|
+
#
|
181
|
+
# @commands
|
182
|
+
# switchport trunk allowed vlan add <value>
|
183
|
+
# no switchport trunk allowed vlan
|
184
|
+
# default switchport trunk allowed vlan
|
185
|
+
#
|
186
|
+
# @option [Array] :value The list of vlan ids to configure on the
|
187
|
+
# switchport to be allowed. This value must be an array of valid vlan
|
188
|
+
# ids
|
189
|
+
#
|
190
|
+
# @option [Boolean] :default Configures the switchport trunk allowed
|
191
|
+
# vlans command using the default keyword
|
192
|
+
#
|
193
|
+
# @return [Boolean] returns true if the commands complete successfully
|
194
|
+
def set_trunk_allowed_vlans(name, opts = {})
|
195
|
+
value = opts[:value]
|
196
|
+
default = opts[:default] || false
|
197
|
+
|
198
|
+
unless value.is_a?(Array)
|
199
|
+
raise ArgumentError, 'value must be an Array'
|
200
|
+
end
|
201
|
+
|
202
|
+
value = value.map(&:inspect).join(',') if value
|
203
|
+
|
204
|
+
cmds = ["interface #{name}"]
|
205
|
+
case default
|
206
|
+
when true
|
207
|
+
cmds << 'default switchport trunk allowed vlan'
|
208
|
+
when false
|
209
|
+
if value.nil?
|
210
|
+
cmds << 'no switchport trunk allowed vlan'
|
211
|
+
else
|
212
|
+
cmds << 'switchport trunk allowed vlan none'
|
213
|
+
cmds << "switchport trunk allowed vlan add #{value}"
|
214
|
+
end
|
215
|
+
end
|
216
|
+
configure(cmds)
|
217
|
+
end
|
218
|
+
|
219
|
+
##
|
220
|
+
# Configures the trunk port native vlan for the specified interface.
|
221
|
+
# This value is only valid if the switchport mode is configure as
|
222
|
+
# trunk.
|
223
|
+
#
|
224
|
+
# @param [String] name The name of the interface to configure
|
225
|
+
# @param [Hash] opts The configuration parameters for the interface
|
226
|
+
# @option opts [string] :value The value of the trunk native vlan
|
227
|
+
# @option opts [Boolean] :default The value should be set to default
|
228
|
+
#
|
229
|
+
# @return [Boolean] True if the commands succeed otherwise False
|
230
|
+
def set_trunk_native_vlan(name, opts = {})
|
231
|
+
value = opts[:value]
|
232
|
+
default = opts[:default] || false
|
233
|
+
|
234
|
+
cmds = ["interface #{name}"]
|
235
|
+
case default
|
236
|
+
when true
|
237
|
+
cmds << 'default switchport trunk native vlan'
|
238
|
+
when false
|
239
|
+
cmds << (value.nil? ? 'no switchport trunk native vlan' : \
|
240
|
+
"switchport trunk native vlan #{value}")
|
241
|
+
end
|
242
|
+
configure(cmds)
|
243
|
+
end
|
244
|
+
|
245
|
+
##
|
246
|
+
# Configures the access port vlan for the specified interface.
|
247
|
+
# This value is only valid if the switchport mode is configure
|
248
|
+
# in access mode.
|
249
|
+
#
|
250
|
+
# @param [String] name The name of the interface to configure
|
251
|
+
# @param [Hash] opts The configuration parameters for the interface
|
252
|
+
# @option opts [string] :value The value of the access vlan
|
253
|
+
# @option opts [Boolean] :default The value should be set to default
|
254
|
+
#
|
255
|
+
# @return [Boolean] True if the commands succeed otherwise False
|
256
|
+
def set_access_vlan(name, opts = {})
|
257
|
+
value = opts[:value]
|
258
|
+
default = opts[:default] || false
|
259
|
+
|
260
|
+
cmds = ["interface #{name}"]
|
261
|
+
case default
|
262
|
+
when true
|
263
|
+
cmds << 'default switchport access vlan'
|
264
|
+
when false
|
265
|
+
cmds << (value.nil? ? 'no switchport access vlan' : \
|
266
|
+
"switchport access vlan #{value}")
|
267
|
+
end
|
268
|
+
configure(cmds)
|
269
|
+
end
|
270
|
+
end
|
271
|
+
end
|
272
|
+
end
|
@@ -0,0 +1,87 @@
|
|
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
|
+
module Rbeapi
|
35
|
+
|
36
|
+
module Api
|
37
|
+
|
38
|
+
##
|
39
|
+
# The System class configures the node system services such as
|
40
|
+
# hostname and domain name
|
41
|
+
class System < Entity
|
42
|
+
|
43
|
+
##
|
44
|
+
# Returns the system settings
|
45
|
+
#
|
46
|
+
# @example
|
47
|
+
# {
|
48
|
+
# hostname: <string>
|
49
|
+
# }
|
50
|
+
#
|
51
|
+
# @return [Hash] A Ruby hash objec that provides the system settings as
|
52
|
+
# key/value pairs.
|
53
|
+
def get()
|
54
|
+
response = {}
|
55
|
+
response.merge!(parse_hostname(config))
|
56
|
+
response
|
57
|
+
end
|
58
|
+
|
59
|
+
def parse_hostname(config)
|
60
|
+
mdata = /(?<=^hostname\s)(.+)$/.match(config)
|
61
|
+
{ hostname: mdata.nil? ? '' : mdata[1] }
|
62
|
+
end
|
63
|
+
|
64
|
+
##
|
65
|
+
# Configures the system hostname value in the running-config
|
66
|
+
#
|
67
|
+
# @param [Hash] opts The configuration parameters
|
68
|
+
# @option opts [string] :value The value to set the hostname to
|
69
|
+
# @option opts [Boolean] :default The value should be set to default
|
70
|
+
#
|
71
|
+
# @return [Boolean] returns true if the command completed successfully
|
72
|
+
def set_hostname(opts = {})
|
73
|
+
value = opts[:value]
|
74
|
+
default = opts[:default] || false
|
75
|
+
|
76
|
+
case default
|
77
|
+
when true
|
78
|
+
cmds = ['default hostname']
|
79
|
+
when false
|
80
|
+
cmds = (value.nil? ? 'no hostname' : \
|
81
|
+
"hostname #{value}")
|
82
|
+
end
|
83
|
+
configure(cmds)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,236 @@
|
|
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
|
+
module Rbeapi
|
35
|
+
##
|
36
|
+
# Eos is module namesapce for working with the EOS command API
|
37
|
+
module Api
|
38
|
+
|
39
|
+
##
|
40
|
+
# Tacacs provides instance methods to retrieve and set tacacs configuration
|
41
|
+
# values.
|
42
|
+
class Tacacs < Entity
|
43
|
+
|
44
|
+
DEFAULT_KEY_FORMAT = 0
|
45
|
+
DEFAULT_KEY = nil
|
46
|
+
|
47
|
+
# Regular expression to extract a tacacs 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 = /tacacs-server[ ]host[ ]([^\s]+)
|
51
|
+
(?:[ ](single-connection))?
|
52
|
+
(?:[ ]vrf[ ]([^\s]+))?
|
53
|
+
(?:[ ]port[ ](\d+))?
|
54
|
+
(?:[ ]timeout[ ](\d+))?
|
55
|
+
(?:[ ]key[ ](\d+)[ ](\w+))?\s/x
|
56
|
+
|
57
|
+
# Default Tacacs TCP port
|
58
|
+
DEFAULT_PORT = 49
|
59
|
+
|
60
|
+
##
|
61
|
+
# getall Returns an Array with a single resource Hash describing the
|
62
|
+
# current state of the global tacacs configuration on the target device.
|
63
|
+
# This method is intended to be used by a provider's instances class
|
64
|
+
# method.
|
65
|
+
#
|
66
|
+
# The resource hash returned contains the following information:
|
67
|
+
# * name: ('settings')
|
68
|
+
# * enable: (true | false) if tacacs functionality is enabled. This is
|
69
|
+
# always true for EOS.
|
70
|
+
# * key: (String) the key either in plaintext or hashed format
|
71
|
+
# * key_format: (Integer) e.g. 0 or 7
|
72
|
+
# * timeout: (Integer) seconds before the timeout period ends
|
73
|
+
#
|
74
|
+
# @api public
|
75
|
+
#
|
76
|
+
# @return [Array<Hash>] Single element Array of resource hashes
|
77
|
+
def get
|
78
|
+
global = {}
|
79
|
+
global.merge!(parse_global_timeout)
|
80
|
+
global.merge!(parse_global_key)
|
81
|
+
resource = { global: global, servers: servers }
|
82
|
+
resource
|
83
|
+
end
|
84
|
+
|
85
|
+
##
|
86
|
+
# parse_global_key takes a running configuration as a string and
|
87
|
+
# parses out the radius global key and global key format if it exists in
|
88
|
+
# the configuration. An empty Hash is returned if there is no global key
|
89
|
+
# configured. The intent of the Hash is to be merged into a property
|
90
|
+
# hash.
|
91
|
+
#
|
92
|
+
# @param [String] config The running configuration as a single string.
|
93
|
+
#
|
94
|
+
# @api private
|
95
|
+
#
|
96
|
+
# @return [Hash<Symbol,Object>] resource hash attributes
|
97
|
+
def parse_global_key
|
98
|
+
rsrc_hsh = {}
|
99
|
+
(key_format, key) = config.scan(/tacacs-server key (\d+) (\w+)/).first
|
100
|
+
rsrc_hsh[:key_format] = key_format.to_i || DEFAULT_KEY_FORMAT
|
101
|
+
rsrc_hsh[:key] = key || DEFAULT_KEY
|
102
|
+
{ key: key, key_format: key_format }
|
103
|
+
end
|
104
|
+
private :parse_global_key
|
105
|
+
|
106
|
+
##
|
107
|
+
# parse_global_timeout takes a running configuration as a string
|
108
|
+
# and parses out the tacacs global timeout if it exists in the
|
109
|
+
# configuration. An empty Hash is returned if there is no global timeout
|
110
|
+
# value configured. The intent of the Hash is to be merged into a
|
111
|
+
# property hash.
|
112
|
+
#
|
113
|
+
# @param [String] config The running configuration as a single string.
|
114
|
+
#
|
115
|
+
# @api private
|
116
|
+
#
|
117
|
+
# @return [Hash<Symbol,Object>] resource hash attributes
|
118
|
+
def parse_global_timeout
|
119
|
+
timeout = config.scan(/tacacs-server timeout (\d+)/).first
|
120
|
+
{ timeout: timeout.first.to_i }
|
121
|
+
end
|
122
|
+
private :parse_global_timeout
|
123
|
+
|
124
|
+
##
|
125
|
+
# servers returns an Array of tacacs server resource hashes. Each hash
|
126
|
+
# describes the current state of the tacacs server and is suitable for
|
127
|
+
# use in initializing a tacacs_server provider.
|
128
|
+
#
|
129
|
+
# The resource hash returned contains the following information:
|
130
|
+
#
|
131
|
+
# * hostname: hostname or ip address, part of the identifier
|
132
|
+
# * port: (Fixnum) TCP port of the server, part of the identifier
|
133
|
+
# * key: (String) the key either in plaintext or hashed format
|
134
|
+
# * key_format: (Fixnum) e.g. 0 or 7
|
135
|
+
# * timeout: (Fixnum) seconds before the timeout period ends
|
136
|
+
# * multiplex: (Boolean) true when configured to make requests through a
|
137
|
+
# single connection
|
138
|
+
#
|
139
|
+
# @api public
|
140
|
+
#
|
141
|
+
# @return [Array<Hash<Symbol,Object>>] Array of resource hashes
|
142
|
+
def servers
|
143
|
+
tuples = config.scan(SERVER_REGEXP)
|
144
|
+
tuples.map do |(host, mplex, vrf, port, tout, keyfm, key)|
|
145
|
+
hsh = {}
|
146
|
+
hsh[:hostname] = host
|
147
|
+
hsh[:vrf] = vrf
|
148
|
+
hsh[:port] = port.to_i
|
149
|
+
hsh[:timeout] = tout.to_i
|
150
|
+
hsh[:key_format] = keyfm.to_i
|
151
|
+
hsh[:key] = key
|
152
|
+
hsh[:multiplex] = mplex ? true : false
|
153
|
+
hsh
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
##
|
158
|
+
# set_global_key configures the tacacs default key. This method maps to
|
159
|
+
# the `tacacs-server key` EOS configuration command, e.g. `tacacs-server
|
160
|
+
# key 7 070E234F1F5B4A`.
|
161
|
+
#
|
162
|
+
# @option opts [String] :key ('070E234F1F5B4A') The key value
|
163
|
+
#
|
164
|
+
# @option opts [Fixnum] :key_format (7) The key format, 0 for plaintext
|
165
|
+
# and 7 for a hashed value. 7 will be assumed if this option is not
|
166
|
+
# provided.
|
167
|
+
#
|
168
|
+
# @api public
|
169
|
+
#
|
170
|
+
# @return [Boolean] true if no errors
|
171
|
+
def set_global_key(opts = {})
|
172
|
+
format = opts[:key_format]
|
173
|
+
key = opts[:key]
|
174
|
+
fail ArgumentError, 'key option is required' unless key
|
175
|
+
result = api.config("tacacs-server key #{format} #{key}")
|
176
|
+
result == [{}]
|
177
|
+
end
|
178
|
+
|
179
|
+
##
|
180
|
+
# set_timeout configures the tacacs default timeout. This method maps to
|
181
|
+
# the `tacacs-server timeout` setting.
|
182
|
+
#
|
183
|
+
# @option opts [Fixnum] :timeout (50) The timeout in seconds to
|
184
|
+
# configure.
|
185
|
+
#
|
186
|
+
# @api public
|
187
|
+
#
|
188
|
+
# @return [Boolean] true if no errors
|
189
|
+
def set_global_timeout(opts = {})
|
190
|
+
value = opts[:value]
|
191
|
+
default = opts[:default] || false
|
192
|
+
|
193
|
+
case default
|
194
|
+
when true
|
195
|
+
cmds = 'default tacacs-server timeout'
|
196
|
+
when false
|
197
|
+
cmds = value ? "tacacs-server timeout #{value}" :
|
198
|
+
'no tacacs-server timeout'
|
199
|
+
end
|
200
|
+
configure cmds
|
201
|
+
end
|
202
|
+
|
203
|
+
##
|
204
|
+
# update_server configures a tacacs server resource on the target device.
|
205
|
+
# This API method maps to the `tacacs server host` command, e.g.
|
206
|
+
# `tacacs-server host 1.2.3.4 single-connection port 4949 timeout 6 key 7
|
207
|
+
# 06070D221D1C5A`
|
208
|
+
#
|
209
|
+
# @api public
|
210
|
+
#
|
211
|
+
# @return [Boolean] true if there are no errors
|
212
|
+
def update_server(opts = {})
|
213
|
+
key_format = opts[:key_format] || 7
|
214
|
+
cmd = "tacacs-server host #{opts[:hostname]}"
|
215
|
+
cmd << ' single-connection' if opts[:multiplex]
|
216
|
+
cmd << " port #{opts[:port]}" if opts[:port]
|
217
|
+
cmd << " timeout #{opts[:timeout]}" if opts[:timeout]
|
218
|
+
cmd << " key #{key_format} #{opts[:key]}" if opts[:key]
|
219
|
+
configure cmd
|
220
|
+
end
|
221
|
+
|
222
|
+
##
|
223
|
+
# remove_server removes the tacacs server identified by the hostname,
|
224
|
+
# and port attributes.
|
225
|
+
#
|
226
|
+
# @api public
|
227
|
+
#
|
228
|
+
# @return [Boolean] true if no errors
|
229
|
+
def remove_server(opts = {})
|
230
|
+
cmd = "no tacacs-server host #{opts[:hostname]}"
|
231
|
+
cmd << " port #{opts[:port]}" if opts[:port]
|
232
|
+
configure cmd
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|