rbeapi 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -0
- data/.rubocop.yml +21 -0
- data/CHANGELOG.md +24 -0
- data/Gemfile +3 -1
- data/Guardfile +3 -3
- data/README.md +92 -17
- data/Rakefile +99 -4
- data/gems/README.rst +4 -0
- data/gems/inifile/.gitignore +2 -0
- data/gems/inifile/README.rst +5 -0
- data/gems/inifile/inifile.spec.tmpl +84 -0
- data/gems/net_http_unix/.gitignore +2 -0
- data/gems/net_http_unix/README.rst +5 -0
- data/gems/net_http_unix/net_http_unix.spec.tmpl +54 -0
- data/gems/netaddr/README.rst +5 -0
- data/gems/netaddr/netaddr.spec.tmpl +50 -0
- data/lib/rbeapi/api/aaa.rb +14 -17
- data/lib/rbeapi/api/acl.rb +276 -0
- data/lib/rbeapi/api/dns.rb +7 -4
- data/lib/rbeapi/api/interfaces.rb +239 -239
- data/lib/rbeapi/api/ipinterfaces.rb +5 -3
- data/lib/rbeapi/api/logging.rb +8 -5
- data/lib/rbeapi/api/mlag.rb +45 -127
- data/lib/rbeapi/api/ntp.rb +1 -4
- data/lib/rbeapi/api/ospf.rb +16 -13
- data/lib/rbeapi/api/prefixlists.rb +4 -4
- data/lib/rbeapi/api/radius.rb +34 -25
- data/lib/rbeapi/api/routemaps.rb +16 -10
- data/lib/rbeapi/api/snmp.rb +26 -13
- data/lib/rbeapi/api/staticroutes.rb +6 -5
- data/lib/rbeapi/api/stp.rb +77 -18
- data/lib/rbeapi/api/switchports.rb +20 -12
- data/lib/rbeapi/api/system.rb +6 -6
- data/lib/rbeapi/api/tacacs.rb +9 -6
- data/lib/rbeapi/api/varp.rb +15 -10
- data/lib/rbeapi/api/vlans.rb +5 -6
- data/lib/rbeapi/api.rb +56 -16
- data/lib/rbeapi/client.rb +85 -50
- data/lib/rbeapi/eapilib.rb +95 -56
- data/lib/rbeapi/netdev/snmp.rb +7 -16
- data/lib/rbeapi/utils.rb +3 -5
- data/lib/rbeapi/version.rb +1 -1
- data/rbeapi.gemspec +4 -2
- data/rbeapi.spec.tmpl +72 -0
- data/spec/support/fixtures.rb +6 -4
- data/spec/support/shared_examples_for_api_modules.rb +3 -18
- data/spec/system/api_acl_spec.rb +128 -0
- data/spec/system/api_ospf_interfaces_spec.rb +17 -14
- data/spec/system/api_ospf_spec.rb +8 -8
- data/spec/system/api_varp_interfaces_spec.rb +22 -13
- data/spec/system/api_varp_spec.rb +1 -4
- data/spec/system/rbeapi/api/interfaces_base_spec.rb +3 -4
- data/spec/system/rbeapi/api/interfaces_ethernet_spec.rb +13 -9
- data/spec/system/rbeapi/api/interfaces_portchannel_spec.rb +43 -26
- data/spec/system/rbeapi/api/interfaces_vxlan_spec.rb +7 -6
- data/spec/system/rbeapi/api/ipinterfaces_spec.rb +34 -21
- data/spec/system/rbeapi/api/mlag_interfaces_spec.rb +15 -38
- data/spec/system/rbeapi/api/mlag_spec.rb +26 -30
- data/spec/system/rbeapi/api/snmp_spec.rb +0 -3
- data/spec/system/rbeapi/api/stp_instances_spec.rb +20 -12
- data/spec/system/rbeapi/api/stp_interfaces_spec.rb +1 -3
- data/spec/system/rbeapi/api/switchports_spec.rb +14 -12
- data/spec/system/rbeapi/api/system_spec.rb +0 -3
- data/spec/system/rbeapi/api/vlans_spec.rb +19 -9
- data/spec/unit/rbeapi/api/acl/default_spec.rb +158 -0
- data/spec/unit/rbeapi/api/acl/fixture_acl_standard.text +22 -0
- data/spec/unit/rbeapi/api/interfaces/base_spec.rb +123 -0
- data/spec/unit/rbeapi/api/interfaces/ethernet_spec.rb +89 -0
- data/spec/unit/rbeapi/api/interfaces/fixture_interfaces.text +219 -0
- data/spec/unit/rbeapi/api/interfaces/portchannel_spec.rb +149 -0
- data/spec/unit/rbeapi/api/interfaces/vxlan_spec.rb +243 -0
- data/spec/unit/rbeapi/api/mlag/default_spec.rb +218 -0
- data/spec/unit/rbeapi/api/mlag/fixture_mlag.text +238 -0
- data/spec/unit/rbeapi/api/vlans/default_spec.rb +135 -0
- data/spec/unit/rbeapi/api/vlans/fixture_vlans.text +5 -0
- metadata +79 -4
- data/lib/rbeapi/api/radius.rb.old +0 -399
data/lib/rbeapi/client.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#
|
2
|
-
# Copyright (c) 2014, Arista Networks, Inc.
|
2
|
+
# Copyright (c) 2014, 2015 Arista Networks, Inc.
|
3
3
|
# All rights reserved.
|
4
4
|
#
|
5
5
|
# Redistribution and use in source and binary forms, with or without
|
@@ -41,10 +41,8 @@ module Rbeapi
|
|
41
41
|
##
|
42
42
|
# Rbeapi::Client
|
43
43
|
module Client
|
44
|
-
|
45
44
|
class << self
|
46
|
-
|
47
|
-
DEFAULT_TRANSPORT = 'http'
|
45
|
+
DEFAULT_TRANSPORT = 'https'
|
48
46
|
|
49
47
|
TRANSPORTS = { 'http' => 'Rbeapi::Eapilib::HttpEapiConnection',
|
50
48
|
'https' => 'Rbeapi::Eapilib::HttpsEapiConnection',
|
@@ -60,15 +58,15 @@ module Rbeapi
|
|
60
58
|
# with the eapi.conf file
|
61
59
|
def config
|
62
60
|
return @config if @config
|
63
|
-
@config = Config.new
|
64
|
-
|
61
|
+
@config = Config.new
|
62
|
+
@config
|
65
63
|
end
|
66
64
|
|
67
65
|
##
|
68
66
|
# load_config overrides the default conf file loaded in the config
|
69
67
|
# instances using the supplied conf argument as the conf file. This
|
70
68
|
# method will clear out an previously loaded configuration and replace
|
71
|
-
# all entries with the
|
69
|
+
# all entries with the contents of the supplied file.
|
72
70
|
#
|
73
71
|
# @param [String] :conf The full path to the conf file to load into
|
74
72
|
# the config instance.
|
@@ -77,8 +75,8 @@ module Rbeapi
|
|
77
75
|
end
|
78
76
|
|
79
77
|
##
|
80
|
-
# Returns the configuration options for the named connection from
|
81
|
-
# the loaded
|
78
|
+
# Returns the configuration options for the named connection from
|
79
|
+
# the loaded configuration. The configuration name is specified as
|
82
80
|
# the string right of the colon in the section name.
|
83
81
|
#
|
84
82
|
# @param [String] :name The connection name to return from the loaded
|
@@ -88,7 +86,7 @@ module Rbeapi
|
|
88
86
|
# the named configuration if found. If the name is not found, then
|
89
87
|
# nil is returned
|
90
88
|
def config_for(name)
|
91
|
-
|
89
|
+
config.get_connection(name)
|
92
90
|
end
|
93
91
|
|
94
92
|
##
|
@@ -103,6 +101,7 @@ module Rbeapi
|
|
103
101
|
def connect_to(name)
|
104
102
|
config = config_for(name)
|
105
103
|
return nil unless config
|
104
|
+
config['host'] = name if config['host'] == '*'
|
106
105
|
config = Rbeapi::Utils.transform_keys_to_symbols(config)
|
107
106
|
connection = connect config
|
108
107
|
Node.new(connection)
|
@@ -118,13 +117,13 @@ module Rbeapi
|
|
118
117
|
#
|
119
118
|
# @param [Hash] :opts the options to create a message with
|
120
119
|
# @option :opts [String] :host The IP address or hostname of the remote
|
121
|
-
# eAPI
|
120
|
+
# eAPI endpoint
|
122
121
|
# @option :opts [String] :username The username to use to authenticate
|
123
122
|
# the eAPI connection with
|
124
123
|
# @option :opts [String] :password The password to use to authenticate
|
125
124
|
# the eAPI connection with
|
126
125
|
# @option :opts [String] :enable_pwd The enable password (if defined) to
|
127
|
-
# pass to the remote node to enter
|
126
|
+
# pass to the remote node to enter privilege mode
|
128
127
|
# @option :opts [String] :use_ssl Specifies whether or not to use the
|
129
128
|
# HTTP or HTTPS protocol
|
130
129
|
# @option :opts [String] :port The port to connect to. If not specified
|
@@ -153,15 +152,15 @@ module Rbeapi
|
|
153
152
|
end
|
154
153
|
end
|
155
154
|
|
155
|
+
##
|
156
|
+
# The Config class holds the loaded configuration file data. It is a
|
157
|
+
# subclass of IniFile.
|
156
158
|
class Config < IniFile
|
157
|
-
|
158
159
|
CONFIG_SEARCH_PATH = ['~/.eapi.conf', '/mnt/flash/eapi.conf']
|
159
160
|
|
160
161
|
##
|
161
|
-
# The Config class
|
162
|
-
#
|
163
|
-
# a filename to load (if none provided) and load the data when the
|
164
|
-
# object is instantiated.
|
162
|
+
# The Config class will automatically search for a filename to load
|
163
|
+
# (if none provided) and load the data when the object is instantiated.
|
165
164
|
#
|
166
165
|
# @param [String] :filename The full path to the filename to load. If
|
167
166
|
# the filename is not provided, then this class will attempt to find
|
@@ -173,7 +172,7 @@ module Rbeapi
|
|
173
172
|
end
|
174
173
|
|
175
174
|
##
|
176
|
-
# This private method
|
175
|
+
# This private method automatically finds and loads the conf file
|
177
176
|
# into the instance using the class variable CONFIG_SEARCH_PATH. The
|
178
177
|
# connections should be retrieved using the get_connection method
|
179
178
|
#
|
@@ -189,8 +188,11 @@ module Rbeapi
|
|
189
188
|
|
190
189
|
path.each do |fn|
|
191
190
|
fn = File.expand_path(fn)
|
192
|
-
return read(fn) if File.
|
191
|
+
return read(fn) if File.exist?(fn)
|
193
192
|
end
|
193
|
+
|
194
|
+
return if get_connection 'localhost'
|
195
|
+
add_connection('localhost', transport: 'socket')
|
194
196
|
end
|
195
197
|
private :autoload
|
196
198
|
|
@@ -202,15 +204,24 @@ module Rbeapi
|
|
202
204
|
# @param [String] :filename The full path to the filename to load
|
203
205
|
def read(filename)
|
204
206
|
super(filename: filename)
|
205
|
-
|
206
|
-
|
207
|
+
|
208
|
+
# For each section, if the host parameter is omitted then the
|
209
|
+
# connection name is used
|
210
|
+
sections.each do |name|
|
211
|
+
if name.start_with?('connection:')
|
212
|
+
conn = self["#{name}"]
|
213
|
+
conn['host'] = name.split(':')[1] unless conn['host']
|
214
|
+
end
|
207
215
|
end
|
216
|
+
|
217
|
+
return if get_connection 'localhost'
|
218
|
+
add_connection('localhost', transport: 'socket')
|
208
219
|
end
|
209
220
|
|
210
221
|
##
|
211
222
|
# This method will cause the config to be loaded. The process of
|
212
223
|
# finding the configuration will be repeated so it is possible a
|
213
|
-
# different conf file could be
|
224
|
+
# different conf file could be chosen if the original file was
|
214
225
|
# removed or a new file added higher on the search priority list
|
215
226
|
#
|
216
227
|
# @param [Hash] :opts The options for specifying the message
|
@@ -220,18 +231,22 @@ module Rbeapi
|
|
220
231
|
end
|
221
232
|
|
222
233
|
##
|
223
|
-
# Returns the configuration for the connection specified
|
234
|
+
# Returns the configuration for the connection specified. If a
|
235
|
+
# connection is not found matching the name and if a default
|
236
|
+
# connection has been specified then return the default connection.
|
224
237
|
#
|
225
238
|
# @param [String] :name The name of the connection to return from
|
226
239
|
# the configuration. This should be the string right of the :
|
227
240
|
# in the config section header
|
228
241
|
#
|
229
242
|
# @return [nil, Hash<String, String> Returns a hash of the connection
|
230
|
-
#
|
243
|
+
# properties from the loaded config. This method will return nil
|
231
244
|
# if the connection name is not found.
|
232
245
|
def get_connection(name)
|
233
|
-
return
|
234
|
-
|
246
|
+
return self["connection:#{name}"] \
|
247
|
+
if sections.include? "connection:#{name}"
|
248
|
+
return self['connection:*'] if sections.include? 'connection:*'
|
249
|
+
nil
|
235
250
|
end
|
236
251
|
|
237
252
|
##
|
@@ -245,14 +260,15 @@ module Rbeapi
|
|
245
260
|
end
|
246
261
|
end
|
247
262
|
|
263
|
+
##
|
264
|
+
# The Node object provides an instance for sending and receiving messages
|
265
|
+
# with a specific EOS device. The methods provided in this class allow
|
266
|
+
# for handling both enable mode and config mode commands
|
248
267
|
class Node
|
249
|
-
|
250
268
|
attr_reader :connection
|
251
269
|
|
252
270
|
##
|
253
|
-
#
|
254
|
-
# with a specific EOS device. The methods provided in this calss allow
|
255
|
-
# for handling both enable mode and config mode commands
|
271
|
+
# Save the connection and set autorefresh to true.
|
256
272
|
#
|
257
273
|
# @param [Rbeapi::Eapilib::EapiConnection] :connection An instance of
|
258
274
|
# EapiConnection used to send and receive eAPI formatted messages
|
@@ -269,18 +285,16 @@ module Rbeapi
|
|
269
285
|
def running_config
|
270
286
|
return @running_config if @running_config
|
271
287
|
@running_config = get_config(params: 'all', as_string: true)
|
272
|
-
return @running_config
|
273
288
|
end
|
274
289
|
|
275
290
|
##
|
276
291
|
# Provides access to the nodes startup-configuration. This is a lazily
|
277
|
-
# loaded memoized
|
292
|
+
# loaded memoized property for working with the nodes startup config
|
278
293
|
#
|
279
294
|
# @return [String] The node's startup-config as a string
|
280
295
|
def startup_config
|
281
296
|
return @startup_config if @startup_config
|
282
297
|
@startup_config = get_config(config: 'startup-config', as_string: true)
|
283
|
-
return @startup_config
|
284
298
|
end
|
285
299
|
|
286
300
|
##
|
@@ -302,13 +316,20 @@ module Rbeapi
|
|
302
316
|
# to the caller
|
303
317
|
#
|
304
318
|
# @param [Array<String>] commands An ordered list of commands to execute
|
319
|
+
# @option :opts [String] :encoding The encoding scheme to use for sending
|
320
|
+
# and receive eAPI messages. Valid values are json and text. The
|
321
|
+
# default value is json
|
322
|
+
# @option :opts [Float] :open_timeout Number of seconds to wait for the
|
323
|
+
# eAPI connection to open.
|
324
|
+
# @option :opts [Float] :read_timeout Number of seconds to wait for one
|
325
|
+
# block of eAPI results to be read (via one read(2) call).
|
305
326
|
#
|
306
327
|
# @return [Array<Hash>] ordered list of output from commands
|
307
|
-
def config(commands)
|
328
|
+
def config(commands, opts = {})
|
308
329
|
commands = [*commands] unless commands.respond_to?('each')
|
309
330
|
|
310
331
|
commands.insert(0, 'configure')
|
311
|
-
response = run_commands
|
332
|
+
response = run_commands(commands, opts)
|
312
333
|
|
313
334
|
refresh if @autorefresh
|
314
335
|
|
@@ -318,34 +339,42 @@ module Rbeapi
|
|
318
339
|
|
319
340
|
##
|
320
341
|
# The enable method is a convenience method that will handling putting
|
321
|
-
# the switch into
|
342
|
+
# the switch into privilege mode prior to executing commands.
|
343
|
+
#
|
344
|
+
# rubocop:disable Metrics/MethodLength
|
322
345
|
#
|
323
346
|
# @param [Array<String>] commands An ordered list of commands to execute
|
324
|
-
# @
|
325
|
-
# receive eAPI messages. Valid values are json and text. The
|
326
|
-
# value is json
|
347
|
+
# @option :opts [String] :encoding The encoding scheme to use for sending
|
348
|
+
# and receive eAPI messages. Valid values are json and text. The
|
349
|
+
# default value is json
|
350
|
+
# @option :opts [Float] :open_timeout Number of seconds to wait for the
|
351
|
+
# eAPI connection to open.
|
352
|
+
# @option :opts [Float] :read_timeout Number of seconds to wait for one
|
353
|
+
# block of eAPI results to be read (via one read(2) call).
|
327
354
|
#
|
328
355
|
# @return [Array<Hash>] ordered list of output from commands
|
329
356
|
def enable(commands, opts = {})
|
330
357
|
commands = [*commands] unless commands.respond_to?('each')
|
331
358
|
|
332
359
|
encoding = opts.fetch(:encoding, 'json')
|
360
|
+
opts[:encoding] = encoding
|
333
361
|
strict = opts.fetch(:strict, false)
|
334
362
|
|
335
363
|
results = []
|
336
364
|
if strict
|
337
|
-
responses = run_commands(commands,
|
365
|
+
responses = run_commands(commands, opts)
|
338
366
|
responses.each_with_index do |resp, idx|
|
339
367
|
results << make_response(commands[idx], resp, encoding)
|
340
368
|
end
|
341
369
|
else
|
342
370
|
commands.each do |cmd|
|
343
371
|
begin
|
344
|
-
response = run_commands(cmd,
|
372
|
+
response = run_commands(cmd, opts)
|
345
373
|
results << make_response(cmd, response.first, encoding)
|
346
374
|
rescue Rbeapi::Eapilib::CommandError => exc
|
347
375
|
raise unless exc.error_code == 1003
|
348
|
-
|
376
|
+
opts[:encoding] = 'text'
|
377
|
+
response = run_commands(cmd, opts)
|
349
378
|
results << make_response(cmd, response.first, encoding)
|
350
379
|
end
|
351
380
|
end
|
@@ -376,20 +405,26 @@ module Rbeapi
|
|
376
405
|
#
|
377
406
|
# @param [Array] :commands The ordered list of commands to send to the
|
378
407
|
# destination node.
|
379
|
-
# @
|
380
|
-
# receive eAPI requests. This argument is optional.
|
381
|
-
# include json or text. The default is json
|
382
|
-
|
408
|
+
# @option :opts [String] :encoding The encoding scheme to use for
|
409
|
+
# sending and receive eAPI requests. This argument is optional.
|
410
|
+
# Valid values include json or text. The default is json
|
411
|
+
# @option :opts [Float] :open_timeout Number of seconds to wait for the
|
412
|
+
# eAPI connection to open.
|
413
|
+
# @option :opts [Float] :read_timeout Number of seconds to wait for one
|
414
|
+
# block of eAPI results to be read (via one read(2) call).
|
415
|
+
def run_commands(commands, opts = {})
|
416
|
+
encoding = opts.fetch(:encoding, 'json')
|
383
417
|
commands = [*commands] unless commands.respond_to?('each')
|
384
418
|
commands = commands.dup
|
385
419
|
|
386
420
|
if @enablepwd
|
387
|
-
commands.insert(0,
|
421
|
+
commands.insert(0, 'cmd' => 'enable', 'input' => @enablepwd)
|
388
422
|
else
|
389
423
|
commands.insert(0, 'enable')
|
390
424
|
end
|
391
425
|
|
392
|
-
|
426
|
+
opts[:format] = encoding
|
427
|
+
response = @connection.execute(commands, opts)
|
393
428
|
response.shift
|
394
429
|
response
|
395
430
|
end
|
@@ -424,13 +459,13 @@ module Rbeapi
|
|
424
459
|
config = opts.fetch(:config, 'running-config')
|
425
460
|
params = opts.fetch(:params, '')
|
426
461
|
as_string = opts.fetch(:as_string, false)
|
427
|
-
result = run_commands("show #{config} #{params}", 'text')
|
462
|
+
result = run_commands("show #{config} #{params}", encoding: 'text')
|
428
463
|
return result.first['output'].strip.split("\n") unless as_string
|
429
464
|
result.first['output'].strip
|
430
465
|
end
|
431
466
|
|
432
467
|
##
|
433
|
-
# Returns an API module for working with the active
|
468
|
+
# Returns an API module for working with the active configuration
|
434
469
|
# of the node
|
435
470
|
def api(name, opts = {})
|
436
471
|
path = opts.fetch(:path, 'rbeapi/api')
|
data/lib/rbeapi/eapilib.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#
|
2
|
-
# Copyright (c) 2014, Arista Networks, Inc.
|
2
|
+
# Copyright (c) 2014, 2015, Arista Networks, Inc.
|
3
3
|
# All rights reserved.
|
4
4
|
#
|
5
5
|
# Redistribution and use in source and binary forms, with or without
|
@@ -31,28 +31,32 @@
|
|
31
31
|
#
|
32
32
|
require 'net/http'
|
33
33
|
require 'json'
|
34
|
+
require 'openssl'
|
34
35
|
|
35
36
|
require 'net_http_unix'
|
36
37
|
|
38
|
+
##
|
39
|
+
# Rbeapi toplevel namespace
|
37
40
|
module Rbeapi
|
38
|
-
|
41
|
+
##
|
42
|
+
# Rbeapi::Eapilib
|
39
43
|
module Eapilib
|
40
|
-
|
41
44
|
DEFAULT_HTTP_PORT = 80
|
42
45
|
DEFAULT_HTTPS_PORT = 443
|
43
46
|
DEFAULT_HTTP_LOCAL_PORT = 8080
|
44
|
-
|
47
|
+
DEFAULT_HTTP_OPEN_TIMEOUT = 10
|
48
|
+
DEFAULT_HTTP_READ_TIMEOUT = 10
|
45
49
|
DEFAULT_HTTP_PATH = '/command-api'
|
46
50
|
DEFAULT_UNIX_SOCKET = '/var/run/command-api.sock'
|
47
51
|
|
52
|
+
##
|
53
|
+
# Base error class for generating exceptions. The EapiError class
|
48
54
|
class EapiError < StandardError
|
49
|
-
|
50
55
|
attr_accessor :commands
|
51
56
|
|
52
57
|
##
|
53
|
-
#
|
54
|
-
#
|
55
|
-
# when the error was generated
|
58
|
+
# The EapiError class provides one property for holding the set of
|
59
|
+
# commands issued when the error was generated.
|
56
60
|
#
|
57
61
|
# @param [String] :message The error message to return from raising
|
58
62
|
# the exception
|
@@ -63,20 +67,20 @@ module Rbeapi
|
|
63
67
|
end
|
64
68
|
end
|
65
69
|
|
70
|
+
##
|
71
|
+
# A CommandError exception is raised in response to an eAPI call that
|
72
|
+
# returns a failure message.
|
66
73
|
class CommandError < EapiError
|
67
|
-
|
68
74
|
attr_reader :error_code
|
69
75
|
attr_reader :error_text
|
70
76
|
|
71
77
|
##
|
72
|
-
#
|
73
|
-
# returns a failure message. The exception contains the eAPI error
|
74
|
-
# code and error text.
|
78
|
+
# The exception contains the eAPI error code and error text.
|
75
79
|
#
|
76
80
|
# @param [String] :message The error message to return from raising
|
77
81
|
# this exception
|
78
82
|
# @param [Integer] :code The error code associated with the error
|
79
|
-
#
|
83
|
+
# message to be raised
|
80
84
|
# @param [Array] :commands The list of commands that were used in the
|
81
85
|
# eAPI request message
|
82
86
|
def initialize(message, code, commands = nil)
|
@@ -88,13 +92,14 @@ module Rbeapi
|
|
88
92
|
end
|
89
93
|
end
|
90
94
|
|
95
|
+
##
|
96
|
+
# A ConnectionError exception is raised when the connection object
|
97
|
+
# is unable to establish a connection with eAPI.
|
91
98
|
class ConnectionError < EapiError
|
92
|
-
|
93
99
|
attr_accessor :connection_type
|
94
100
|
|
95
101
|
##
|
96
|
-
#
|
97
|
-
# is unable to establish a connection with eAPI.
|
102
|
+
# The exception contains the eAPI error code and error text.
|
98
103
|
#
|
99
104
|
# @param [String] :message The error message to return from raising
|
100
105
|
# this exception
|
@@ -109,16 +114,16 @@ module Rbeapi
|
|
109
114
|
end
|
110
115
|
end
|
111
116
|
|
117
|
+
##
|
118
|
+
# The EapiConnection provides a base class for building eAPI connection
|
119
|
+
# instances with a specific transport for connecting to Arista EOS
|
120
|
+
# devices. This class handles sending and receiving eAPI calls using
|
121
|
+
# JSON-RPC. This class should not need to be directly instantiated.
|
112
122
|
class EapiConnection
|
113
|
-
|
114
123
|
attr_reader :error
|
115
124
|
|
116
125
|
##
|
117
|
-
# The
|
118
|
-
# instances with a specific transport for connecting to Arista EOS
|
119
|
-
# devices. This class handles sending and receiving eAPI calls using
|
120
|
-
# JSON-RPC over HTTP. This class should not need to be directly
|
121
|
-
# instantiated.
|
126
|
+
# The connection contains the transport.
|
122
127
|
#
|
123
128
|
# @param [Net::HTTP] :transport The HTTP transport to use for sending
|
124
129
|
# and receive eAPI request and response messages
|
@@ -129,17 +134,32 @@ module Rbeapi
|
|
129
134
|
|
130
135
|
##
|
131
136
|
# Configures the connection authentication values (username and
|
132
|
-
#
|
137
|
+
# password). The authentication values are used to authenticate
|
133
138
|
# the eAPI connection. Using authentication is only required for
|
134
139
|
# connections that use Http or Https transports
|
135
140
|
#
|
136
|
-
# @
|
137
|
-
# eAPI
|
138
|
-
# @
|
139
|
-
# eAPI
|
140
|
-
def authentication(
|
141
|
-
@username = username
|
142
|
-
@password = password
|
141
|
+
# @options :opts [String] :username The username to use to
|
142
|
+
# authenticate with eAPI. Default is 'admin'.
|
143
|
+
# @options :opts [String] :password The password to use to
|
144
|
+
# authenticate with eAPI. Default is ''.
|
145
|
+
def authentication(opts = {})
|
146
|
+
@username = opts.fetch(:username, 'admin')
|
147
|
+
@password = opts.fetch(:password, '')
|
148
|
+
end
|
149
|
+
|
150
|
+
##
|
151
|
+
# Configures the connection timeout values (open_timeout and
|
152
|
+
# read_timeout). The timeout values are used for the eAPI
|
153
|
+
# connection.
|
154
|
+
#
|
155
|
+
# @option :opts [Float] :open_timeout Number of seconds to wait for the
|
156
|
+
# eAPI connection to open. Default is DEFAULT_HTTP_OPEN_TIMEOUT.
|
157
|
+
# @option :opts [Float] :read_timeout Number of seconds to wait for one
|
158
|
+
# block of eAPI results to be read (via one read(2) call). Default
|
159
|
+
# is DEFAULT_HTTP_READ_TIMEOUT.
|
160
|
+
def timeouts(opts = {})
|
161
|
+
@open_timeout = opts.fetch(:open_timeout, DEFAULT_HTTP_OPEN_TIMEOUT)
|
162
|
+
@read_timeout = opts.fetch(:read_timeout, DEFAULT_HTTP_READ_TIMEOUT)
|
143
163
|
end
|
144
164
|
|
145
165
|
##
|
@@ -170,9 +190,9 @@ module Rbeapi
|
|
170
190
|
# value is json
|
171
191
|
#
|
172
192
|
# @return [Hash] Returns a Ruby hash of the request message that is
|
173
|
-
# suitable to be JSON encoded and sent to the
|
193
|
+
# suitable to be JSON encoded and sent to the destination node
|
174
194
|
def request(commands, opts = {})
|
175
|
-
id = opts.fetch(:reqid,
|
195
|
+
id = opts.fetch(:reqid, object_id)
|
176
196
|
format = opts.fetch(:format, 'json')
|
177
197
|
cmds = [*commands]
|
178
198
|
params = { 'version' => 1, 'cmds' => cmds, 'format' => format }
|
@@ -222,18 +242,26 @@ module Rbeapi
|
|
222
242
|
#
|
223
243
|
# @param [Hash] :data A hash containing the body of the request
|
224
244
|
# message. This should be a valid eAPI request message.
|
245
|
+
# @option :opts [Float] :open_timeout Number of seconds to wait for the
|
246
|
+
# eAPI connection to open.
|
247
|
+
# @option :opts [Float] :read_timeout Number of seconds to wait for one
|
248
|
+
# block of eAPI results to be read (via one read(2) call).
|
225
249
|
#
|
226
250
|
# @return [Hash] returns the response message as a Ruby hash object
|
227
251
|
#
|
228
252
|
# @raises [CommandError] Raised if an eAPI failure response is return
|
229
253
|
# from the destination node.
|
230
|
-
def send(data)
|
254
|
+
def send(data, opts)
|
231
255
|
request = Net::HTTP::Post.new('/command-api')
|
232
256
|
request.body = JSON.dump(data)
|
233
257
|
request.basic_auth @username, @password
|
234
258
|
|
259
|
+
open_timeout = opts.fetch(:open_timeout, @open_timeout)
|
260
|
+
read_timeout = opts.fetch(:read_timeout, @read_timeout)
|
261
|
+
|
235
262
|
begin
|
236
|
-
@transport.open_timeout =
|
263
|
+
@transport.open_timeout = open_timeout
|
264
|
+
@transport.read_timeout = read_timeout
|
237
265
|
response = @transport.request(request)
|
238
266
|
decoded = JSON(response.body)
|
239
267
|
|
@@ -246,18 +274,22 @@ module Rbeapi
|
|
246
274
|
raise ConnectionError, 'unable to connect to eAPI'
|
247
275
|
end
|
248
276
|
|
249
|
-
|
277
|
+
decoded
|
250
278
|
end
|
251
279
|
|
252
280
|
##
|
253
281
|
# Executes the commands on the destination node and returns the
|
254
282
|
# response from the node.
|
255
283
|
#
|
256
|
-
# @param [Array] :commands The ordered list of
|
284
|
+
# @param [Array] :commands The ordered list of commands to execute
|
257
285
|
# on the destination node.
|
258
286
|
# @param [Hash] :opts Optional keyword arguments
|
259
287
|
# @option :opts [String] :encoding Used to specify the encoding to be
|
260
288
|
# used for the response. Valid encoding values are json or text
|
289
|
+
# @option :opts [Float] :open_timeout Number of seconds to wait for the
|
290
|
+
# eAPI connection to open.
|
291
|
+
# @option :opts [Float] :read_timeout Number of seconds to wait for one
|
292
|
+
# block of eAPI results to be read (via one read(2) call).
|
261
293
|
#
|
262
294
|
# @returns [Array<Hash>] This method will return the array of responses
|
263
295
|
# for each command executed on the node.
|
@@ -265,22 +297,23 @@ module Rbeapi
|
|
265
297
|
# @raises [CommandError] Raises a CommandError if rescued from the
|
266
298
|
# send method and adds the list of commands to the exception message
|
267
299
|
#
|
268
|
-
# @raises [ConnectionError] Raises a ConnectionError if
|
300
|
+
# @raises [ConnectionError] Raises a ConnectionError if rescued and
|
269
301
|
# adds the list of commands to the exception message
|
270
302
|
def execute(commands, opts = {})
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
raise
|
280
|
-
end
|
303
|
+
@error = nil
|
304
|
+
request = request(commands, opts)
|
305
|
+
response = send(request, opts)
|
306
|
+
return response['result']
|
307
|
+
rescue ConnectionError, CommandError => exc
|
308
|
+
exc.commands = commands
|
309
|
+
@error = exc
|
310
|
+
raise
|
281
311
|
end
|
282
312
|
end
|
283
313
|
|
314
|
+
##
|
315
|
+
# The SocketEapiConnection provides a class for building a domain
|
316
|
+
# socket eAPI connection to Arista EOS devices.
|
284
317
|
class SocketEapiConnection < EapiConnection
|
285
318
|
def initialize(opts = {})
|
286
319
|
path = opts.fetch(:path, DEFAULT_UNIX_SOCKET)
|
@@ -289,6 +322,9 @@ module Rbeapi
|
|
289
322
|
end
|
290
323
|
end
|
291
324
|
|
325
|
+
##
|
326
|
+
# The HttpEapiConnection provides a class for building an HTTP
|
327
|
+
# eAPI connection to a Arista EOS devices.
|
292
328
|
class HttpEapiConnection < EapiConnection
|
293
329
|
def initialize(opts = {})
|
294
330
|
port = opts.fetch(:port, DEFAULT_HTTP_PORT)
|
@@ -297,24 +333,28 @@ module Rbeapi
|
|
297
333
|
transport = Net::HTTP.new(host, port.to_i)
|
298
334
|
super(transport)
|
299
335
|
|
300
|
-
|
301
|
-
|
302
|
-
authentication(user, pass)
|
336
|
+
authentication(opts)
|
337
|
+
timeouts(opts)
|
303
338
|
end
|
304
339
|
end
|
305
340
|
|
341
|
+
##
|
342
|
+
# The HttpLocalEapiConnection provides a class for building an HTTP
|
343
|
+
# eAPI connection to a local Arista EOS devices.
|
306
344
|
class HttpLocalEapiConnection < EapiConnection
|
307
345
|
def initialize(opts = {})
|
308
346
|
port = opts.fetch(:port, DEFAULT_HTTP_LOCAL_PORT)
|
309
347
|
transport = Net::HTTP.new('localhost', port)
|
310
348
|
super(transport)
|
311
349
|
|
312
|
-
|
313
|
-
|
314
|
-
authentication(user, pass)
|
350
|
+
authentication(opts)
|
351
|
+
timeouts(opts)
|
315
352
|
end
|
316
353
|
end
|
317
354
|
|
355
|
+
##
|
356
|
+
# The HttpEapiConnection provides a class for building an HTTPS
|
357
|
+
# eAPI connection to a Arista EOS devices.
|
318
358
|
class HttpsEapiConnection < EapiConnection
|
319
359
|
def initialize(opts = {})
|
320
360
|
host = opts.fetch(:host, 'localhost')
|
@@ -325,9 +365,8 @@ module Rbeapi
|
|
325
365
|
transport.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
326
366
|
super(transport)
|
327
367
|
|
328
|
-
|
329
|
-
|
330
|
-
authentication(user, pass)
|
368
|
+
authentication(opts)
|
369
|
+
timeouts(opts)
|
331
370
|
end
|
332
371
|
end
|
333
372
|
end
|