rbeapi 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. data/.gitignore +5 -0
  2. data/.rubocop.yml +21 -0
  3. data/CHANGELOG.md +24 -0
  4. data/Gemfile +3 -1
  5. data/Guardfile +3 -3
  6. data/README.md +92 -17
  7. data/Rakefile +99 -4
  8. data/gems/README.rst +4 -0
  9. data/gems/inifile/.gitignore +2 -0
  10. data/gems/inifile/README.rst +5 -0
  11. data/gems/inifile/inifile.spec.tmpl +84 -0
  12. data/gems/net_http_unix/.gitignore +2 -0
  13. data/gems/net_http_unix/README.rst +5 -0
  14. data/gems/net_http_unix/net_http_unix.spec.tmpl +54 -0
  15. data/gems/netaddr/README.rst +5 -0
  16. data/gems/netaddr/netaddr.spec.tmpl +50 -0
  17. data/lib/rbeapi/api/aaa.rb +14 -17
  18. data/lib/rbeapi/api/acl.rb +276 -0
  19. data/lib/rbeapi/api/dns.rb +7 -4
  20. data/lib/rbeapi/api/interfaces.rb +239 -239
  21. data/lib/rbeapi/api/ipinterfaces.rb +5 -3
  22. data/lib/rbeapi/api/logging.rb +8 -5
  23. data/lib/rbeapi/api/mlag.rb +45 -127
  24. data/lib/rbeapi/api/ntp.rb +1 -4
  25. data/lib/rbeapi/api/ospf.rb +16 -13
  26. data/lib/rbeapi/api/prefixlists.rb +4 -4
  27. data/lib/rbeapi/api/radius.rb +34 -25
  28. data/lib/rbeapi/api/routemaps.rb +16 -10
  29. data/lib/rbeapi/api/snmp.rb +26 -13
  30. data/lib/rbeapi/api/staticroutes.rb +6 -5
  31. data/lib/rbeapi/api/stp.rb +77 -18
  32. data/lib/rbeapi/api/switchports.rb +20 -12
  33. data/lib/rbeapi/api/system.rb +6 -6
  34. data/lib/rbeapi/api/tacacs.rb +9 -6
  35. data/lib/rbeapi/api/varp.rb +15 -10
  36. data/lib/rbeapi/api/vlans.rb +5 -6
  37. data/lib/rbeapi/api.rb +56 -16
  38. data/lib/rbeapi/client.rb +85 -50
  39. data/lib/rbeapi/eapilib.rb +95 -56
  40. data/lib/rbeapi/netdev/snmp.rb +7 -16
  41. data/lib/rbeapi/utils.rb +3 -5
  42. data/lib/rbeapi/version.rb +1 -1
  43. data/rbeapi.gemspec +4 -2
  44. data/rbeapi.spec.tmpl +72 -0
  45. data/spec/support/fixtures.rb +6 -4
  46. data/spec/support/shared_examples_for_api_modules.rb +3 -18
  47. data/spec/system/api_acl_spec.rb +128 -0
  48. data/spec/system/api_ospf_interfaces_spec.rb +17 -14
  49. data/spec/system/api_ospf_spec.rb +8 -8
  50. data/spec/system/api_varp_interfaces_spec.rb +22 -13
  51. data/spec/system/api_varp_spec.rb +1 -4
  52. data/spec/system/rbeapi/api/interfaces_base_spec.rb +3 -4
  53. data/spec/system/rbeapi/api/interfaces_ethernet_spec.rb +13 -9
  54. data/spec/system/rbeapi/api/interfaces_portchannel_spec.rb +43 -26
  55. data/spec/system/rbeapi/api/interfaces_vxlan_spec.rb +7 -6
  56. data/spec/system/rbeapi/api/ipinterfaces_spec.rb +34 -21
  57. data/spec/system/rbeapi/api/mlag_interfaces_spec.rb +15 -38
  58. data/spec/system/rbeapi/api/mlag_spec.rb +26 -30
  59. data/spec/system/rbeapi/api/snmp_spec.rb +0 -3
  60. data/spec/system/rbeapi/api/stp_instances_spec.rb +20 -12
  61. data/spec/system/rbeapi/api/stp_interfaces_spec.rb +1 -3
  62. data/spec/system/rbeapi/api/switchports_spec.rb +14 -12
  63. data/spec/system/rbeapi/api/system_spec.rb +0 -3
  64. data/spec/system/rbeapi/api/vlans_spec.rb +19 -9
  65. data/spec/unit/rbeapi/api/acl/default_spec.rb +158 -0
  66. data/spec/unit/rbeapi/api/acl/fixture_acl_standard.text +22 -0
  67. data/spec/unit/rbeapi/api/interfaces/base_spec.rb +123 -0
  68. data/spec/unit/rbeapi/api/interfaces/ethernet_spec.rb +89 -0
  69. data/spec/unit/rbeapi/api/interfaces/fixture_interfaces.text +219 -0
  70. data/spec/unit/rbeapi/api/interfaces/portchannel_spec.rb +149 -0
  71. data/spec/unit/rbeapi/api/interfaces/vxlan_spec.rb +243 -0
  72. data/spec/unit/rbeapi/api/mlag/default_spec.rb +218 -0
  73. data/spec/unit/rbeapi/api/mlag/fixture_mlag.text +238 -0
  74. data/spec/unit/rbeapi/api/vlans/default_spec.rb +135 -0
  75. data/spec/unit/rbeapi/api/vlans/fixture_vlans.text +5 -0
  76. metadata +79 -4
  77. data/lib/rbeapi/api/radius.rb.old +0 -399
@@ -32,14 +32,16 @@
32
32
  require 'rbeapi/api'
33
33
  require 'rbeapi/utils'
34
34
 
35
+ ##
36
+ # Rbeapi toplevel namespace
35
37
  module Rbeapi
36
-
38
+ ##
39
+ # Api module namespace
37
40
  module Api
38
-
41
+ ##
42
+ # The Interfaces class manages all physical and logical interfaces on an
43
+ # EOS node.
39
44
  class Interfaces < Entity
40
-
41
- METHODS = [:create, :delete, :default]
42
-
43
45
  def initialize(node)
44
46
  super(node)
45
47
  @instances = {}
@@ -59,7 +61,7 @@ module Rbeapi
59
61
  end
60
62
 
61
63
  def get_instance(name)
62
- name = name[0,2].upcase
64
+ name = name[0, 2].upcase
63
65
  case name
64
66
  when 'ET'
65
67
  cls = 'Rbeapi::Api::EthernetInterface'
@@ -78,10 +80,8 @@ module Rbeapi
78
80
  end
79
81
 
80
82
  def method_missing(method_name, *args, &block)
81
- if method_name.to_s =~ /set_(.*)/ || METHODS.include?(method_name)
82
- instance = get_instance(args[0])
83
- instance.send(method_name.to_sym, *args, &block)
84
- end
83
+ instance = get_instance(args[0])
84
+ instance.send(method_name.to_sym, *args, &block)
85
85
  end
86
86
 
87
87
  def respond_to?(method_name, name = nil)
@@ -89,14 +89,12 @@ module Rbeapi
89
89
  instance = get_instance(name)
90
90
  instance.respond_to?(method_name) || super
91
91
  end
92
-
93
92
  end
94
93
 
95
94
  ##
96
95
  # The BaseInterface class extends Entity and provides an implementation
97
96
  # that is common to all interfaces configured in EOS.
98
97
  class BaseInterface < Entity
99
-
100
98
  DEFAULT_INTF_DESCRIPTION = ''
101
99
 
102
100
  ##
@@ -169,9 +167,6 @@ module Rbeapi
169
167
  #
170
168
  # @eos_version 4.13.7M
171
169
  #
172
- # @commands
173
- # interface <value>
174
- #
175
170
  # @param [String] :value The interface name to create on the node. The
176
171
  # interface name must be the full interface identifier (ie Loopback,
177
172
  # not Lo)
@@ -189,9 +184,6 @@ module Rbeapi
189
184
  #
190
185
  # @eos_version 4.13.7M
191
186
  #
192
- # @commands
193
- # no interface <value>
194
- #
195
187
  # @param [String] :value The interface name to delete from the node.
196
188
  # The interface name must be the full interface identifier
197
189
  # (ie Loopback, no Lo)
@@ -209,9 +201,6 @@ module Rbeapi
209
201
  #
210
202
  # @eos_version 4.13.7M
211
203
  #
212
- # @commands
213
- # default interface <value>
214
- #
215
204
  # @param [String] :value The interface name to default in the node. The
216
205
  # interface name must be the full interface identifier (ie Loopback,
217
206
  # not Lo)
@@ -232,12 +221,6 @@ module Rbeapi
232
221
  #
233
222
  # @eos_version 4.13.7M
234
223
  #
235
- # @commands
236
- # interface <name>
237
- # description <value>
238
- # no description
239
- # default description
240
- #
241
224
  # @param [String] :name The interface name to apply the configuration
242
225
  # to. The name value must be the full interface identifier
243
226
  #
@@ -251,18 +234,8 @@ module Rbeapi
251
234
  #
252
235
  # @return [Boolean] returns true if the command completed successfully
253
236
  def set_description(name, opts = {})
254
- value = opts[:value]
255
- value = nil if value.empty?
256
- default = opts.fetch(:default, false)
257
-
258
- cmds = ["interface #{name}"]
259
- case default
260
- when true
261
- cmds << 'default description'
262
- when false
263
- cmds << (value.nil? ? 'no description' : "description #{value}")
264
- end
265
- configure(cmds)
237
+ commands = command_builder('description', opts)
238
+ configure_interface(name, commands)
266
239
  end
267
240
 
268
241
  ##
@@ -277,12 +250,6 @@ module Rbeapi
277
250
  #
278
251
  # @eos_version 4.13.7M
279
252
  #
280
- # @commands
281
- # interface <name<
282
- # shutdown
283
- # no shutdown
284
- # default shutdown
285
- #
286
253
  # @param [String] :name The interface name to apply the configuration
287
254
  # to. The name value must be the full interface identifier
288
255
  #
@@ -297,22 +264,15 @@ module Rbeapi
297
264
  #
298
265
  # @return [Boolean] returns true if the command completed successfully
299
266
  def set_shutdown(name, opts = {})
300
- value = opts[:value]
301
- default = opts.fetch(:default, false)
302
-
303
- cmds = ["interface #{name}"]
304
- case default
305
- when true
306
- cmds << 'default shutdown'
307
- when false
308
- cmds << (value ? 'shutdown' : 'no shutdown')
309
- end
310
- configure(cmds)
267
+ commands = command_builder('shutdown', opts)
268
+ configure_interface(name, commands)
311
269
  end
312
270
  end
313
271
 
272
+ ##
273
+ # The EthernetInterface class manages all Ethernet interfaces on an
274
+ # EOS node.
314
275
  class EthernetInterface < BaseInterface
315
-
316
276
  DEFAULT_ETH_FLOWC_TX = 'off'
317
277
  DEFAULT_ETH_FLOWC_RX = 'off'
318
278
  DEFAULT_SPEED = 'auto'
@@ -324,18 +284,18 @@ module Rbeapi
324
284
  #
325
285
  # The resource hash returned contains the following information:
326
286
  #
327
- # * name (string): the interface name (eg Ethernet1)
328
- # * type (string): will always be 'ethernet'
329
- # * description (string): the interface description value
330
- # * speed (string): the current speed setting for the interface speed
331
- # * forced (boolean): true if autonegotiation is disabled otherwise
332
- # false
333
- # * sflow (boolean): true if sflow is enabled on the interface
334
- # otherwise false
335
- # * flowcontrol_send (string): the inteface flowcontrol send value.
336
- # Valid values are 'on' or 'off'
337
- # * flowconrol_receive (string): the interface flowcontrol receive
338
- # value. Valid values are 'on' or 'off'
287
+ # * name (string): the interface name (eg Ethernet1)
288
+ # * type (string): will always be 'ethernet'
289
+ # * description (string): the interface description value
290
+ # * speed (string): the current speed setting for the interface speed
291
+ # * forced (boolean): true if autonegotiation is disabled otherwise
292
+ # false
293
+ # * sflow (boolean): true if sflow is enabled on the interface
294
+ # otherwise false
295
+ # * flowcontrol_send (string): the inteface flowcontrol send value.
296
+ # Valid values are 'on' or 'off'
297
+ # * flowconrol_receive (string): the interface flowcontrol receive
298
+ # value. Valid values are 'on' or 'off'
339
299
  #
340
300
  # @param [String] :name The interface name to return a resource hash
341
301
  # for from the node's running configuration
@@ -371,7 +331,7 @@ module Rbeapi
371
331
  value = config.scan(/speed (forced)?[ ]?(\w+)/).first
372
332
  return { speed: DEFAULT_SPEED, forced: DEFAULT_FORCED } unless value
373
333
  (forced, value) = value.first
374
- { speed: value, forced: forced != nil }
334
+ { speed: value, forced: !forced.nil? }
375
335
  end
376
336
  private :parse_speed
377
337
 
@@ -430,8 +390,8 @@ module Rbeapi
430
390
  #
431
391
  # @raise [NotImplementedError] Creation of physical Ethernet interfaces
432
392
  # is not supported
433
- def create(name)
434
- raise NotImplementedError, 'creating Ethernet interfaces is '\
393
+ def create(_name)
394
+ fail NotImplementedError, 'creating Ethernet interfaces is '\
435
395
  'not supported'
436
396
  end
437
397
 
@@ -444,8 +404,8 @@ module Rbeapi
444
404
  #
445
405
  # @raise [NotImplementedError] Deletion of physical Ethernet interfaces
446
406
  # is not supported
447
- def delete(name)
448
- raise NotImplementedError, 'deleting Ethernet interfaces is '\
407
+ def delete(_name)
408
+ fail NotImplementedError, 'deleting Ethernet interfaces is '\
449
409
  'not supported'
450
410
  end
451
411
 
@@ -459,12 +419,6 @@ module Rbeapi
459
419
  #
460
420
  # @eos_version 4.13.7M
461
421
  #
462
- # @commands
463
- # interface <name>
464
- # speed [forced] <value>
465
- # no speed
466
- # default speed
467
- #
468
422
  # @param [String] :name The interface name to apply the configuration
469
423
  # values to. The name must be the full interface identifier.
470
424
  #
@@ -509,12 +463,6 @@ module Rbeapi
509
463
  #
510
464
  # @eos_version 4.13.7M
511
465
  #
512
- # @commands
513
- # interface <name>
514
- # sflow enable
515
- # no sflow enable
516
- # default sflow
517
- #
518
466
  # @param [String] :name The interface name to apply the configuration
519
467
  # values to. The name must be the full interface identifier.
520
468
  #
@@ -531,14 +479,18 @@ module Rbeapi
531
479
  value = opts[:value]
532
480
  default = opts.fetch(:default, false)
533
481
 
534
- cmds = ["interface #{name}"]
535
482
  case default
536
483
  when true
537
- cmds << 'default sflow'
484
+ command = 'default sflow enable'
538
485
  when false
539
- cmds << (value ? 'sflow enable' : 'no sflow enable')
486
+ case value
487
+ when true
488
+ command = 'sflow enable'
489
+ when false
490
+ command = 'no sflow enable'
491
+ end
540
492
  end
541
- configure(cmds)
493
+ configure_interface(name, command)
542
494
  end
543
495
 
544
496
  ##
@@ -551,12 +503,6 @@ module Rbeapi
551
503
  #
552
504
  # @eos_version 4.13.7M
553
505
  #
554
- # @commands
555
- # interface <name>
556
- # flowcontrol [send | receive] [on, off]
557
- # no flowcontrol [send | receive]
558
- # default flowcontrol [send | receive]
559
- #
560
506
  # @param [String] :name The interface name to apply the configuration
561
507
  # values to. The name must be the full interface identifier.
562
508
  #
@@ -573,18 +519,8 @@ module Rbeapi
573
519
  #
574
520
  # @return [Boolean] returns true if the command completed successfully
575
521
  def set_flowcontrol(name, direction, opts = {})
576
- value = opts[:value]
577
- default = opts.fetch(:default, false)
578
-
579
- commands = ["interface #{name}"]
580
- case default
581
- when true
582
- commands << "default flowcontrol #{direction}"
583
- when false
584
- commands << (value.nil? ? "no flowcontrol #{direction}" :
585
- "flowcontrol #{direction} #{value}")
586
- end
587
- configure(commands)
522
+ commands = command_builder("flowcontrol #{direction}", opts)
523
+ configure_interface(name, commands)
588
524
  end
589
525
 
590
526
  ##
@@ -595,12 +531,6 @@ module Rbeapi
595
531
  #
596
532
  # @eos_version 4.13.7M
597
533
  #
598
- # @commands
599
- # interface <name>
600
- # flowcontrol [send | receive] [on, off]
601
- # no flowcontrol [send | receive]
602
- # default flowcontrol [send | receive]
603
- #
604
534
  # @param [String] :name The interface name to apply the configuration
605
535
  # values to. The name must be the full interface identifier.
606
536
  #
@@ -625,12 +555,6 @@ module Rbeapi
625
555
  #
626
556
  # @eos_version 4.13.7M
627
557
  #
628
- # @commands
629
- # interface <name>
630
- # flowcontrol [send | receive] [on, off]
631
- # no flowcontrol [send | receive]
632
- # default flowcontrol [send | receive]
633
- #
634
558
  # @param [String] :name The interface name to apply the configuration
635
559
  # values to. The name must be the full interface identifier.
636
560
  #
@@ -648,8 +572,10 @@ module Rbeapi
648
572
  end
649
573
  end
650
574
 
575
+ ##
576
+ # The PortchannelInterface class manages all port channel interfaces on an
577
+ # EOS node.
651
578
  class PortchannelInterface < BaseInterface
652
-
653
579
  DEFAULT_LACP_FALLBACK = 'disabled'
654
580
  DEFAULT_LACP_MODE = 'on'
655
581
  DEFAULT_MIN_LINKS = '0'
@@ -711,7 +637,7 @@ module Rbeapi
711
637
  grpid = name.scan(/(?<=Port-Channel)\d+/)[0]
712
638
  command = "show port-channel #{grpid} all-ports"
713
639
  config = node.enable(command, format: 'text')
714
- values = config.first[:result]['output'].scan(/Ethernet[\d\/]*/)
640
+ values = config.first[:result]['output'].scan(%r{\bEthernet[\d\/]*})
715
641
  { members: values }
716
642
  end
717
643
  private :parse_members
@@ -734,7 +660,7 @@ module Rbeapi
734
660
  return { lacp_mode: DEFAULT_LACP_MODE } unless members
735
661
  config = get_block("interface #{members.first}")
736
662
  mdata = /channel-group \d+ mode (\w+)/.match(config)
737
- { lacp_mode: mdata.nil? ? DEFAULT_LACP_MODE : mdata[1] }
663
+ { lacp_mode: mdata ? mdata[1] : DEFAULT_LACP_MODE }
738
664
  end
739
665
  private :parse_lacp_mode
740
666
 
@@ -753,7 +679,7 @@ module Rbeapi
753
679
  # @return [Hash<Symbol, Object>] resource hash attribute
754
680
  def parse_minimum_links(config)
755
681
  mdata = /port-channel min-links (\d+)$/.match(config)
756
- { minimum_links: mdata.nil? ? DEFAULT_MIN_LINKS : mdata[1] }
682
+ { minimum_links: mdata ? mdata[1] : DEFAULT_MIN_LINKS }
757
683
  end
758
684
  private :parse_minimum_links
759
685
 
@@ -772,7 +698,7 @@ module Rbeapi
772
698
  # @return [Hash<Symbol, Object>] resource hash attribute
773
699
  def parse_lacp_fallback(config)
774
700
  mdata = /lacp fallback (static|individual)/.match(config)
775
- { lacp_fallback: mdata.nil? ? DEFAULT_LACP_FALLBACK : mdata[1] }
701
+ { lacp_fallback: mdata ? mdata[1] : DEFAULT_LACP_FALLBACK }
776
702
  end
777
703
  private :parse_lacp_fallback
778
704
 
@@ -805,12 +731,6 @@ module Rbeapi
805
731
  #
806
732
  # @eos_version 4.13.7M
807
733
  #
808
- # @commands
809
- # interface <name>
810
- # port-channel min-links <value>
811
- # no port-channel min-links
812
- # default port-channel min-links
813
- #
814
734
  # @param [String] :name The interface name to apply the configuration
815
735
  # values to. The name must be the full interface identifier.
816
736
  #
@@ -825,18 +745,8 @@ module Rbeapi
825
745
  #
826
746
  # @return [Boolean] returns true if the command completed successfully
827
747
  def set_minimum_links(name, opts = {})
828
- value = opts[:value]
829
- default = opts.fetch(:default, false)
830
-
831
- cmds = ["interface #{name}"]
832
- case default
833
- when true
834
- cmds << 'default port-channel min-links'
835
- when false
836
- cmds << (value ? "port-channel min-links #{value}" : \
837
- 'no port-channel min-links')
838
- end
839
- configure(cmds)
748
+ commands = command_builder('port-channel min-links', opts)
749
+ configure_interface(name, commands)
840
750
  end
841
751
 
842
752
  ##
@@ -873,7 +783,7 @@ module Rbeapi
873
783
  return false unless result
874
784
  end
875
785
 
876
- return true
786
+ true
877
787
  end
878
788
 
879
789
  ##
@@ -883,10 +793,6 @@ module Rbeapi
883
793
  #
884
794
  # @eos_version 4.13.7M
885
795
  #
886
- # @commands
887
- # interface <name>
888
- # channel-group <grpid> mode <lacp_mode>
889
- #
890
796
  # @param [String] :name The name of the port-channel interface to apply
891
797
  # the configuration to.
892
798
  #
@@ -897,7 +803,7 @@ module Rbeapi
897
803
  def add_member(name, member)
898
804
  lacp = parse_lacp_mode(name)[:lacp_mode]
899
805
  grpid = /(\d+)/.match(name)[0]
900
- configure ["interface #{member}", "channel-group #{grpid} mode #{lacp}"]
806
+ configure_interface(member, "channel-group #{grpid} mode #{lacp}")
901
807
  end
902
808
 
903
809
  ##
@@ -907,10 +813,6 @@ module Rbeapi
907
813
  #
908
814
  # @eos_version 4.13.7M
909
815
  #
910
- # @commands
911
- # interface <name>
912
- # no channel-group <grpid>
913
- #
914
816
  # @param [String] :name The name of the port-channel interface to apply
915
817
  # the configuration to.
916
818
  #
@@ -920,7 +822,7 @@ module Rbeapi
920
822
  # @return [Boolean] returns true if the command completed successfully
921
823
  def remove_member(name, member)
922
824
  grpid = /(\d+)/.match(name)[0]
923
- configure ["interface #{member}", "no channel-group #{grpid}"]
825
+ configure_interface(member, "no channel-group #{grpid}")
924
826
  end
925
827
 
926
828
  ##
@@ -931,11 +833,6 @@ module Rbeapi
931
833
  #
932
834
  # @eos_version 4.13.7M
933
835
  #
934
- # @commands
935
- # interface <name>
936
- # no channel-group <grpid>
937
- # channge-group <grpid> mode <lacp_mode>
938
- #
939
836
  # @param [String] :name The interface name to apply the configuration
940
837
  # values to. The name must be the full interface identifier.
941
838
  #
@@ -970,12 +867,6 @@ module Rbeapi
970
867
  #
971
868
  # @eos_version 4.13.7M
972
869
  #
973
- # @commands
974
- # interface <name>
975
- # port-channel lacp fallback <value>
976
- # no port-channel lacp fallback
977
- # default port-channel lacp fallback
978
- #
979
870
  # @param [String] :name The interface name to apply the configuration
980
871
  # values to. The name must be the full interface identifier.
981
872
  #
@@ -990,21 +881,9 @@ module Rbeapi
990
881
  #
991
882
  # @return [Boolean] returns true if the command completed successfully
992
883
  def set_lacp_fallback(name, opts = {})
993
- value = opts[:value]
994
- default = opts.fetch(:default, false)
995
-
996
- cmds = ["interface #{name}"]
997
- case default
998
- when true
999
- cmds << 'default port-channel lacp fallback'
1000
- when false
1001
- if [nil, 'disabled'].include?(value)
1002
- cmds << 'no port-channel lacp fallback'
1003
- else
1004
- cmds << "port-channel lacp fallback #{value}"
1005
- end
1006
- end
1007
- configure(cmds)
884
+ opts[:value] = nil if opts[:value] == 'disabled'
885
+ commands = command_builder('port-channel lacp fallback', opts)
886
+ configure_interface(name, commands)
1008
887
  end
1009
888
 
1010
889
  ##
@@ -1017,12 +896,6 @@ module Rbeapi
1017
896
  #
1018
897
  # @eos_version 4.13.7M
1019
898
  #
1020
- # @commands
1021
- # interface <name>
1022
- # port-channel lacp fallback timeout <value>
1023
- # no port-channel lacp fallback timeout
1024
- # default port-channel lacp fallback timeout
1025
- #
1026
899
  # @param [String] :name The interface name to apply the configuration
1027
900
  # values to. The name must be the full interface identifier.
1028
901
  #
@@ -1037,23 +910,14 @@ module Rbeapi
1037
910
  #
1038
911
  # @return [Boolean] returns true if the command completed successfully
1039
912
  def set_lacp_timeout(name, opts = {})
1040
- value = opts[:value]
1041
- default = opts.fetch(:default, false)
1042
-
1043
- cmds = ["interface #{name}"]
1044
- case default
1045
- when true
1046
- cmds << 'default port-channel lacp fallback timeout'
1047
- when false
1048
- cmds << (value ? "port-channel lacp fallback timeout #{value}" : \
1049
- 'no port-channel lacp fallback timeout')
1050
- end
1051
- configure(cmds)
913
+ commands = command_builder('port-channel lacp fallback timeout', opts)
914
+ configure_interface(name, commands)
1052
915
  end
1053
916
  end
1054
917
 
918
+ ##
919
+ # The VxlanInterface class manages all Vxlan interfaces on an EOS node.
1055
920
  class VxlanInterface < BaseInterface
1056
-
1057
921
  DEFAULT_SRC_INTF = ''
1058
922
  DEFAULT_MCAST_GRP = ''
1059
923
 
@@ -1063,15 +927,16 @@ module Rbeapi
1063
927
  # BaseInterface get method and adds the Vxlan specific attributes to
1064
928
  # the hash
1065
929
  #
1066
- # @example
1067
- # {
1068
- # "name": <string>,
1069
- # "type": 'vxlan',
1070
- # "description": <string>,
1071
- # "shutdown": [true, false],
1072
- # "source_interface": <string>,
1073
- # "multicast_group": <string>
1074
- # }
930
+ # The returned resource hash contains the following
931
+ #
932
+ # * name: (String) The full interface name identifier
933
+ # * type: (String) 'vxlan'
934
+ # * descripition: (String) The configured interface description
935
+ # * shutdown: (Boolean) The admin state of the interface
936
+ # * source_interface: (String) The vxlan source-interface value
937
+ # * multicast_group: (String) The vxlan multicast-group value
938
+ # * udp_port: (Fixnum) The vxlan udp-port value
939
+ # * flood_list: (Array) The list of VTEPs to flood traffic towards
1075
940
  #
1076
941
  # @param [String] :name The interface name to return from the nodes
1077
942
  # configuration. This optional parameter defaults to Vxlan1
@@ -1087,6 +952,9 @@ module Rbeapi
1087
952
  response[:type] = 'vxlan'
1088
953
  response.merge!(parse_source_interface(config))
1089
954
  response.merge!(parse_multicast_group(config))
955
+ response.merge!(parse_udp_port(config))
956
+ response.merge!(parse_flood_list(config))
957
+ response.merge!(parse_vlans(config))
1090
958
  response
1091
959
  end
1092
960
 
@@ -1101,10 +969,10 @@ module Rbeapi
1101
969
  # @param [String] :config The interface configuration block to extract
1102
970
  # the vxlan source-interface value from
1103
971
  #
1104
- # @return [Hash<Symbol, Object>] resource hash attribute
972
+ # @return [Hash<Symbol, Object>]
1105
973
  def parse_source_interface(config)
1106
974
  mdata = /source-interface ([^\s]+)$/.match(config)
1107
- { source_interface: mdata.nil? ? DEFAULT_SRC_INTF : mdata[1] }
975
+ { source_interface: mdata ? mdata[1] : DEFAULT_SRC_INTF }
1108
976
  end
1109
977
  private :parse_source_interface
1110
978
 
@@ -1119,13 +987,71 @@ module Rbeapi
1119
987
  # @param [String] :config The interface configuration block to extract
1120
988
  # the vxlan multicast-group value from
1121
989
  #
1122
- # @return [Hash<Symbol, Object>] resource hash attribute
990
+ # @return [Hash<Symbol, Object>]
1123
991
  def parse_multicast_group(config)
1124
992
  mdata = /multicast-group ([^\s]+)$/.match(config)
1125
- { multicast_group: mdata.nil? ? DEFAULT_MCAST_GRP : mdata[1] }
993
+ { multicast_group: mdata ? mdata[1] : DEFAULT_MCAST_GRP }
1126
994
  end
1127
995
  private :parse_multicast_group
1128
996
 
997
+ ##
998
+ # parse_udp_port scans the interface config block and returns the value
999
+ # of the vxlan udp-port setting. The vxlan udp-port value is expected to
1000
+ # always be present in the configuration. The returned value is intended
1001
+ # to be merged into the interface resource Hash
1002
+ #
1003
+ # @api private
1004
+ #
1005
+ # @param [String] :config The interface configuration block to parse the
1006
+ # vxlan udp-port value from
1007
+ #
1008
+ # @return [Hash<Symbol, Object>]
1009
+ def parse_udp_port(config)
1010
+ value = config.scan(/(?<=vxlan udp-port )\d+/)
1011
+ { udp_port: value.first.to_i }
1012
+ end
1013
+ private :parse_udp_port
1014
+
1015
+ ##
1016
+ # parse_flood_list scans the interface config block and returns the list
1017
+ # of configured VTEPs that comprise the flood list. If there are no
1018
+ # flood list values configured, the value will return DEFAULT_FLOOD_LIST.
1019
+ # The returned value is intended to be merged into the inteface resource
1020
+ # Hash.
1021
+ #
1022
+ # @api private
1023
+ #
1024
+ # @param [String] :config The interface configuration block to parse the
1025
+ # vxlan flood list values from
1026
+ #
1027
+ # @return [Hash<Symbol, Object>]
1028
+ def parse_flood_list(config)
1029
+ values = config.scan(/(?<=\s{3}vxlan flood vtep ).+$/)
1030
+ values = values.first.split(' ') unless values.empty?
1031
+ { flood_list: values }
1032
+ end
1033
+ private :parse_flood_list
1034
+
1035
+ ##
1036
+ # parse_vlans scans the interface config block and returns the set of
1037
+ # configured vlan to vni mappings. if there are no vlans configured, the
1038
+ # value will return an empty Hash
1039
+ #
1040
+ # @api private
1041
+ #
1042
+ # @param [String] :config The interface configuration block to parse the
1043
+ # vxlan flood list values from
1044
+ #
1045
+ # @return [Hash<Symbol, Object>]
1046
+ def parse_vlans(config)
1047
+ values = config.scan(/vxlan vlan (\d+) vni (\d+)/)
1048
+ values = values.each_with_object({}) do |v, hsh|
1049
+ hsh[v.first] = { vni: v.last }
1050
+ end
1051
+ { vlans: values }
1052
+ end
1053
+ private :parse_vlans
1054
+
1129
1055
  ##
1130
1056
  # Configures the vxlan source-interface to the specified value. This
1131
1057
  # parameter should be a the interface identifier of the interface to act
@@ -1133,29 +1059,21 @@ module Rbeapi
1133
1059
  #
1134
1060
  # @param [String] :name The name of the interface to apply the
1135
1061
  # configuration values to
1062
+ #
1136
1063
  # @param [Hash] :opt Optional keyword arguments
1064
+ #
1137
1065
  # @option :opts [String] :value Configures the vxlan source-interface to
1138
1066
  # the spcified value. If no value is provided and the
1139
1067
  # default keyword is not specified then the value is negated
1068
+ #
1140
1069
  # @option :opts [Boolean] :default Specifies whether or not the
1141
1070
  # multicast-group command is configured as default. The value of this
1142
1071
  # option has a higher precedence than :value
1143
1072
  #
1144
- # @return [Boolean] This method returns true if the commands were
1145
- # successful otherwise it returns false
1073
+ # @return [Boolean] Returns true if the commands complete successfully
1146
1074
  def set_source_interface(name = 'Vxlan1', opts = {})
1147
- value = opts[:value]
1148
- default = opts.fetch(:default, false)
1149
-
1150
- cmds = ["interface #{name}"]
1151
- case default
1152
- when true
1153
- cmds << 'default vxlan source-interface'
1154
- when false
1155
- cmds << (value ? "vxlan source-interface #{value}" : \
1156
- 'no vxlan source-interface')
1157
- end
1158
- configure(cmds)
1075
+ commands = command_builder('vxlan source-interface', opts)
1076
+ configure_interface(name, commands)
1159
1077
  end
1160
1078
 
1161
1079
  ##
@@ -1164,29 +1082,111 @@ module Rbeapi
1164
1082
  #
1165
1083
  # @param [String] :name The name of the interface to apply the
1166
1084
  # configuration values to
1085
+ #
1167
1086
  # @param [Hash] :opt Optional keyword arguments
1087
+ #
1168
1088
  # @option :opts [String] :value Configures the mutlicast-group flood
1169
1089
  # address to the specified value. If no value is provided and the
1170
1090
  # default keyword is not specified then the value is negated
1091
+ #
1171
1092
  # @option :opts [Boolean] :default Specifies whether or not the
1172
1093
  # multicast-group command is configured as default. The value of this
1173
1094
  # option has a higher precedence than :value
1174
1095
  #
1175
- # @return [Boolean] This method returns true if the commands were
1176
- # successful otherwise it returns false
1096
+ # @return [Boolean] Returns true if the commands complete successfully
1177
1097
  def set_multicast_group(name = 'Vxlan1', opts = {})
1178
- value = opts[:value]
1179
- default = opts.fetch(:default, false)
1098
+ commands = command_builder('vxlan multicast-group', opts)
1099
+ configure_interface(name, commands)
1100
+ end
1180
1101
 
1181
- cmds = ["interface #{name}"]
1182
- case default
1183
- when true
1184
- cmds << 'default vxlan multicast-group'
1185
- when false
1186
- cmds << (value ? "vxlan multicast-group #{value}" : \
1187
- 'no vxlan multtcast-group')
1188
- end
1189
- configure(cmds)
1102
+ ##
1103
+ # set_udp_port configures the Vxlan udp-port value in EOS for the
1104
+ # specified interface name. If the value option is not provided then the
1105
+ # no keyword is used to configure the value. If the default option is
1106
+ # provided and set to true, then the default keyword is used. If both
1107
+ # options are provided, the default keyword will take precedence.
1108
+ #
1109
+ # @eos_version 4.13.7M
1110
+ #
1111
+ # @param [String] :name The name of the vxlan interface to configure
1112
+ #
1113
+ # @param [Hash] :opts optional keyword arguments
1114
+ #
1115
+ # @option :opts [String] :value Specifies the value to configure the
1116
+ # udp-port setting to. Valid values are in the range of 1024 to
1117
+ # 65535
1118
+ #
1119
+ # @option :opts [Boolean] :default Configures the udp-port value on
1120
+ # the interface using the default keyword
1121
+ #
1122
+ # @return [Boolean] returns true if the command completed successfully
1123
+ def set_udp_port(name, opts = {})
1124
+ commands = command_builder('vxlan udp-port', opts)
1125
+ configure_interface(name, commands)
1126
+ end
1127
+
1128
+ ##
1129
+ # add_vtep adds a new VTEP endpoint to the global flood list for the
1130
+ # specified interface. If the VTEP endpoint is already configured, this
1131
+ # method will still return successfully.
1132
+ #
1133
+ # @eos_version 4.13.7M
1134
+ #
1135
+ # @param [String] :name The name of the interface to configure
1136
+ # @param [String] :vtep The IP address of the remote VTEP endpoint
1137
+ #
1138
+ # @return [Boolean] Returns true if the commands completed successfully
1139
+ def add_vtep(name, vtep)
1140
+ configure_interface(name, "vxlan flood vtep add #{vtep}")
1141
+ end
1142
+
1143
+ ##
1144
+ # remove_vtep deletes a VTEP endpoint from the global flood list for the
1145
+ # specified interface. If the VTEP endpoint specified is not configured,
1146
+ # this method will still return successfully.
1147
+ #
1148
+ # @eos_version 4.13.7M
1149
+ #
1150
+ # @param [String] :name The name of the interface to configure
1151
+ # @param [String] :vtep The IP address of the remote VTEP endpoint
1152
+ #
1153
+ # @return [Boolean] Returns true if the commands completed successfully
1154
+ def remove_vtep(name, vtep)
1155
+ configure_interface(name, "vxlan flood vtep remove #{vtep}")
1156
+ end
1157
+
1158
+ ##
1159
+ # update_vlan creates a new vlan to vni mapping for the specified
1160
+ # interface in the nodes current configuration
1161
+ #
1162
+ # @eos_verson 4.13.7M
1163
+ #
1164
+ # @param [String] :name The name of the interface to configure
1165
+ #
1166
+ # @param [Fixnum] :vlan The VLAN ID to configure.
1167
+ #
1168
+ # @param [Fixnum] :vni The VNI value to map the VLAN into
1169
+ #
1170
+ # @return [Boolean] returns true if the command completed successfully
1171
+ def update_vlan(name, vlan, vni)
1172
+ configure_interface(name, "vxlan vlan #{vlan} vni #{vni}")
1173
+ end
1174
+
1175
+ ##
1176
+ # remove_vlan deletes a previously configured VLAN to VNI mapping on the
1177
+ # specified interface.
1178
+ #
1179
+ # @eos_version 4.13.7M
1180
+ #
1181
+ # @param [String] :name the name of the interface to configure
1182
+ #
1183
+ # @param [Fixnum] :vlan The VLAN ID to remove from the configuration. If
1184
+ # the VLAN ID does not exist, this method will still return
1185
+ # successfully
1186
+ #
1187
+ # @return [Boolean] returns true if the command completed successfully
1188
+ def remove_vlan(name, vlan)
1189
+ configure_interface(name, "no vxlan vlan #{vlan} vni")
1190
1190
  end
1191
1191
  end
1192
1192
  end