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,201 @@
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
+ # Eos is the toplevel namespace for working with Arista EOS nodes
36
+ module Rbeapi
37
+ ##
38
+ # Api is module namesapce for working with the EOS command API
39
+ module Api
40
+
41
+ ##
42
+ # The Ntp class provides an intstance for working with the nodes
43
+ # NTP configuraiton.
44
+ class Ntp < Entity
45
+
46
+ DEFAULT_SRC_INTF = ''
47
+
48
+ ##
49
+ # get returns the nodes current ntp configure as a resource hash
50
+ #
51
+ # @example
52
+ # {
53
+ # source_interface: <string>
54
+ # servers: {
55
+ # prefer: [true, false]
56
+ # }
57
+ # }
58
+ #
59
+ # @return [nil, Hash<Symbol, Object>] Returns the ntp resource as a
60
+ # Hash.
61
+ def get
62
+ response = {}
63
+ response.merge!(parse_source_interface)
64
+ response.merge!(parse_servers)
65
+ response
66
+ end
67
+
68
+ ##
69
+ # parse_source_interface scans the nodes configurations and parses
70
+ # the ntp source interface if configured. If the source interface
71
+ # is not configured, this method will return DEFAULT_SRC_INTF as the
72
+ # value. The return hash is intended to be merged into the resource hash
73
+ #
74
+ # @api private
75
+ #
76
+ # @return [Hash<Symbol, Object>] resource hash attribute
77
+ def parse_source_interface
78
+ mdata = /(?<=^ntp\ssource\s)(.+)$/.match(config)
79
+ { source_interface: mdata.nil? ? DEFAULT_SRC_INTF : mdata[1] }
80
+ end
81
+ private :parse_source_interface
82
+
83
+ ##
84
+ # parse_servers scans the nodes configuration and parses the configured
85
+ # ntp server host names and/or addresses. This method will also return
86
+ # the value of prefer. If no servers are configured, the value will be
87
+ # set to an empty array. The return hash is inteded to be merged into
88
+ # the resource hash
89
+ #
90
+ # @api private
91
+ #
92
+ # @return [Hash<Symbol, Object>] resource hash attribute
93
+ def parse_servers
94
+ servers = config.scan(/(?:ntp server\s)([^\s]+)\s(prefer)?/)
95
+ values = servers.each_with_object({}) do |(srv, prefer), hsh|
96
+ hsh[srv] = { prefer: !prefer.nil? }
97
+ end
98
+ { servers: values }
99
+ end
100
+
101
+ ##
102
+ # set_source_interface configures the ntp source value in the nodes
103
+ # running configuration. If no value is provided in the options, then
104
+ # the ntp source is configured with the no keyword argument. If the
105
+ # default keyword argument is provided and set to true, the value is
106
+ # configured used the default keyword. The default keyword takes
107
+ # precedence over the value keyword if both optiosn are specified.
108
+ #
109
+ # @eos_version 4.13.7M
110
+ #
111
+ # @commands
112
+ # ntp source <value>
113
+ # no ntp source
114
+ # deafult ntp source
115
+ #
116
+ # @param [Hash] :opts Optional keyword arguments
117
+ #
118
+ # @option :opts [String] :value The value to configure the ntp source
119
+ # in the nodes configuration
120
+ #
121
+ # @option :opts [Boolean] :default Configure the ntp source value using
122
+ # the default keyword
123
+ #
124
+ # @return [Boolean] returns true if the command completed successfully
125
+ def set_source_interface(opts = {})
126
+ value = opts[:value]
127
+ default = opts[:default] || false
128
+
129
+ case default
130
+ when true
131
+ cmds = 'default ntp source'
132
+ when false
133
+ cmds = (value ? "ntp source #{value}" : \
134
+ 'no ntp source')
135
+ end
136
+ configure(cmds)
137
+ end
138
+
139
+ ##
140
+ # add_server configures a new ntp server destination hostname or ip
141
+ # address to the list of ntp destinations. The optional prefer argument
142
+ # configures the server as a preferred (true) or not (false) ntp
143
+ # destination.
144
+ #
145
+ # @param [String] :server The IP address or FQDN of the NTP server to
146
+ # be removed from the configuration
147
+ #
148
+ # @param [Boolean] :prefer Appends the prefer keyword argument to the
149
+ # command if this value is true
150
+ #
151
+ # @return [Boolean] returns true if the command completed successfully
152
+ def add_server(server, prefer = false)
153
+ cmd = "ntp server #{server}"
154
+ cmd << ' prefer' if prefer
155
+ configure cmd
156
+ end
157
+
158
+ ##
159
+ # remove_server deletes the provided server destination from the list of
160
+ # ntp server destinations. If the ntp server does not exist in the list
161
+ # of servers, this method will return successful
162
+ #
163
+ # @param [String] :server The IP address or FQDN of the NTP server to
164
+ # be removed from the configuration
165
+ #
166
+ # @return [Boolean] returns true if the command completed successfully
167
+ def remove_server(server)
168
+ configure("no ntp server #{server}")
169
+ end
170
+
171
+ ##
172
+ # set_prefer will set the prefer keyword for the specified ntp server.
173
+ # If the server does not already exist in the configuration, it will be
174
+ # added and the prefer keyword will be set.
175
+ #
176
+ # @eos_version 4.13.7M
177
+ #
178
+ # @commands
179
+ # ntp server <srv> prefer
180
+ # no ntp server <srv> prefer
181
+ #
182
+ # @param [String] :srv The IP address or hostname of the ntp server to
183
+ # configure with the prefer value
184
+ #
185
+ # @param [Boolean] :value The value to configure for prefer. If true
186
+ # the prefer value is configured for the server. If false, then the
187
+ # prefer value is removed.
188
+ #
189
+ # @return [Boolean] returns true if the commands completed successfully
190
+ def set_prefer(srv, value)
191
+ case value
192
+ when true
193
+ cmds = "ntp server #{srv} prefer"
194
+ when false
195
+ cmds = ["no ntp server #{srv} prefer", "ntp server #{srv}"]
196
+ end
197
+ configure cmds
198
+ end
199
+ end
200
+ end
201
+ end
@@ -0,0 +1,214 @@
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 Ospf class is a global class that provides an instance for working
40
+ # with the node's OSPF configuration
41
+ class Ospf < Entity
42
+
43
+ ##
44
+ # Returns the global OSPF configuration from the node
45
+ #
46
+ # @example
47
+ # {
48
+ # "router_id": <string>
49
+ # "areas": {
50
+ # <string>: array<string>
51
+ # },
52
+ # "resdistribute"
53
+ # }
54
+ #
55
+ # @return [Hash] A Ruby hash object that provides the OSPF settings as
56
+ # key / value pairs.
57
+ def get(inst)
58
+ config = get_block("router ospf #{inst}")
59
+ return nil unless config
60
+
61
+ resp = {}
62
+ mdata = /(?<=^\s{3}router-id\s)(.+)$/.match(config)
63
+ resp['router_id'] = mdata.nil? ? '' : mdata[0]
64
+
65
+ mdata = /^\s{3}network\s(.+)\sarea\s(.+)$/.match(config)
66
+ networks = config.scan(/^\s{3}network\s(.+)\sarea\s(.+)$/)
67
+ areas = networks.each_with_object({}) do |cfg, hsh|
68
+ net, area = cfg
69
+ if hsh.include?(area)
70
+ hsh[area] << net
71
+ else
72
+ hsh[area] = [net]
73
+ end
74
+ end
75
+ resp['areas'] = areas
76
+
77
+ values = config.scan(/(?<=^\s{3}redistribute\s)(\w+)[\s|$]*(route-map\s(.+))?/)
78
+
79
+ resp['redistribute'] = values.each_with_object({}) do |value, hsh|
80
+ hsh[value[0]] = { 'route_map' => value[2] }
81
+ end
82
+ resp
83
+ end
84
+
85
+ ##
86
+ # Returns the OSPF configuration from the node as a Ruby hash
87
+ #
88
+ # @example
89
+ # {
90
+ # <pid>: {...}
91
+ # "interfaces": {...}
92
+ # }
93
+ def getall
94
+ response = {}
95
+
96
+ instances = config.scan(/(?<=^router\sospf\s)\d+$/)
97
+ response = instances.each_with_object({}) do |inst, hsh|
98
+ hsh[inst] = get inst
99
+ end
100
+ response['interfaces'] = interfaces.getall
101
+ response
102
+ end
103
+
104
+ def interfaces
105
+ @interfaces if @interfaces
106
+ @interfaces = OspfInterfaces.new(node)
107
+ @interfaces
108
+ end
109
+
110
+ def create(pid)
111
+ configure "router ospf #{pid}"
112
+ end
113
+
114
+ def delete(pid)
115
+ configure "no router ospf #{pid}"
116
+ end
117
+
118
+ def set_router_id(pid, opts = {})
119
+ value = opts[:value]
120
+ default = opts[:default] || false
121
+
122
+ cmds = ["router ospf #{pid}"]
123
+ case default
124
+ when true
125
+ cmds << 'default router-id'
126
+ when false
127
+ cmds << (value ? "router-id #{value}" : 'no router-id')
128
+ end
129
+ configure cmds
130
+ end
131
+
132
+ def add_network(pid, net, area)
133
+ configure ["router ospf #{pid}", "network #{net} area #{area}"]
134
+ end
135
+
136
+ def remove_network(pid, net, area)
137
+ configure ["router ospf #{pid}", "no network #{net} area #{area}"]
138
+ end
139
+
140
+ def set_redistribute(pid, proto, opts = {})
141
+ routemap = opts[:routemap]
142
+ cmds = ["router ospf #{pid}", "redistribute #{proto}"]
143
+ cmds[1] << " route-map #{routemap}" if routemap
144
+ configure cmds
145
+ end
146
+ end
147
+
148
+ class OspfInterfaces < Entity
149
+
150
+ ##
151
+ # Returns a single MLAG interface configuration
152
+ #
153
+ # Example
154
+ # {
155
+ # "name": <string>,
156
+ # "network_type": <string>
157
+ # }
158
+ #
159
+ # @param [String] :name The interface name to return the configuration
160
+ # values for. This must be the full interface identifier.
161
+ #
162
+ # @return [nil, Hash<String, String>] A Ruby hash that represents the
163
+ # MLAG interface confguration. A nil object is returned if the
164
+ # specified interface is not configured
165
+ def get(name)
166
+ config = get_block("interface #{name}")
167
+ return nil unless config
168
+ return nil unless /no switchport$/ =~ config
169
+
170
+ response = {}
171
+ nettype = /ip ospf network point-to-point/ =~ config
172
+ response['network_type'] = nettype.nil? ? 'broadcast' : 'point-to-point'
173
+ response
174
+ end
175
+
176
+ ##
177
+ # Returns the collection of MLAG interfaces as a hash index by the
178
+ # interface name
179
+ #
180
+ # Example
181
+ # {
182
+ # <name>: {...},
183
+ # <name>: {...}
184
+ # }
185
+ #
186
+ # @return [nil, Hash<String, String>] A Ruby hash that represents the
187
+ # MLAG interface confguration. A nil object is returned if no
188
+ # interfaces are configured.
189
+ def getall
190
+ interfaces = config.scan(/(?<=interface\s)[Et|Po|Lo|Vl].+/)
191
+ interfaces.each_with_object({}) do |intf, hsh|
192
+ values = get(intf)
193
+ hsh[intf] = values if values
194
+ end
195
+ end
196
+
197
+ def set_network_type(name, opts = {})
198
+ value = opts[:value]
199
+ default = opts[:default] || false
200
+
201
+ return false unless %w(nil point-to-point).include?(value)
202
+
203
+ cmds = ["interface #{name}"]
204
+ case default
205
+ when true
206
+ cmds << 'default ip ospf network'
207
+ when false
208
+ cmds << (value ? "ip ospf network #{value}" : 'no ip ospf netework')
209
+ end
210
+ configure(cmds)
211
+ end
212
+ end
213
+ end
214
+ end
@@ -0,0 +1,98 @@
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 Prefixlists class provides a configuration instance for working
40
+ # with static routes in EOS.
41
+ #
42
+ class Prefixlists < Entity
43
+
44
+ ##
45
+ # Returns the static routes configured on the node
46
+ #
47
+ # @example
48
+ # {
49
+ # <route>: {
50
+ # "next_hop": <string>,
51
+ # "name": <string, nil>
52
+ # }
53
+ # }
54
+ #
55
+ # @returns [Hash<String, String> The method will return all of the
56
+ # configured static routes on the node as a Ruby hash object. If
57
+ # there are no static routes configured, this method will return
58
+ # an empty hash
59
+
60
+ def get(name)
61
+ config = get_block("ip prefix-list #{name}")
62
+ return nil unless config
63
+
64
+ entries = config.scan(/^\s{3}(?:seq\s)(\d+)\s(permit|deny)\s(.+)$/)
65
+ entries.each_with_object([]) do |entry, arry|
66
+ arry << { 'seq' => entry[0], 'action' => entry[1],
67
+ 'prefex' => entry[2] }
68
+ end
69
+ end
70
+
71
+ def getall
72
+ lists = config.scan(/(?<=^ip\sprefix-list\s).+/)
73
+ lists.each_with_object({}) do |name, hsh|
74
+ values = get name
75
+ hsh[name] = values if values
76
+ end
77
+ end
78
+
79
+ def create(name)
80
+ configure "ip prefix-list #{name}"
81
+ end
82
+
83
+ def add_rule(name, action, prefix, seq = nil)
84
+ cmd = "ip prefix-list #{name}"
85
+ cmd << " seq #{seq}" if seq
86
+ cmd << " #{action} #{prefix}"
87
+ configure cmd
88
+ end
89
+
90
+ def delete(name, seq = nil)
91
+ cmd = "no ip prefix-list #{name}"
92
+ cmd << " seq #{seq}" if seq
93
+ configure cmd
94
+ end
95
+
96
+ end
97
+ end
98
+ end