rubybvc 0.3.1
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.
- checksums.yaml +7 -0
- data/lib/controller/controller.rb +445 -0
- data/lib/controller/netconf_node.rb +55 -0
- data/lib/controller/node.rb +41 -0
- data/lib/controller/openflow_node.rb +33 -0
- data/lib/netconfdev/vrouter/dataplane_firewall.rb +53 -0
- data/lib/netconfdev/vrouter/firewall.rb +44 -0
- data/lib/netconfdev/vrouter/rule.rb +53 -0
- data/lib/netconfdev/vrouter/rules.rb +53 -0
- data/lib/netconfdev/vrouter/vrouter5600.rb +242 -0
- data/lib/openflowdev/action_output.rb +71 -0
- data/lib/openflowdev/actions/action.rb +39 -0
- data/lib/openflowdev/actions/actions.rb +63 -0
- data/lib/openflowdev/actions/copy_ttl_inwards_action.rb +39 -0
- data/lib/openflowdev/actions/copy_ttl_outwards_action.rb +39 -0
- data/lib/openflowdev/actions/dec_mpls_ttl_action.rb +39 -0
- data/lib/openflowdev/actions/dec_nw_ttl_action.rb +39 -0
- data/lib/openflowdev/actions/drop_action.rb +37 -0
- data/lib/openflowdev/actions/flood_action.rb +39 -0
- data/lib/openflowdev/actions/flood_all_action.rb +39 -0
- data/lib/openflowdev/actions/group_action.rb +44 -0
- data/lib/openflowdev/actions/hw_path_action.rb +39 -0
- data/lib/openflowdev/actions/loopback_action.rb +39 -0
- data/lib/openflowdev/actions/output_action.rb +43 -0
- data/lib/openflowdev/actions/pop_mpls_header_action.rb +41 -0
- data/lib/openflowdev/actions/pop_pbb_header_action.rb +39 -0
- data/lib/openflowdev/actions/pop_vlan_header_action.rb +39 -0
- data/lib/openflowdev/actions/push_mpls_header_action.rb +41 -0
- data/lib/openflowdev/actions/push_pbb_header_action.rb +40 -0
- data/lib/openflowdev/actions/push_vlan_header_action.rb +46 -0
- data/lib/openflowdev/actions/set_dl_dst_action.rb +41 -0
- data/lib/openflowdev/actions/set_dl_src_action.rb +41 -0
- data/lib/openflowdev/actions/set_field_action.rb +43 -0
- data/lib/openflowdev/actions/set_mpls_ttl_action.rb +41 -0
- data/lib/openflowdev/actions/set_nw_dst_action.rb +41 -0
- data/lib/openflowdev/actions/set_nw_src_action.rb +41 -0
- data/lib/openflowdev/actions/set_nw_ttl_action.rb +41 -0
- data/lib/openflowdev/actions/set_queue_action.rb +44 -0
- data/lib/openflowdev/actions/set_tp_dst_action.rb +41 -0
- data/lib/openflowdev/actions/set_tp_src_action.rb +41 -0
- data/lib/openflowdev/actions/set_vlan_cfi_action.rb +41 -0
- data/lib/openflowdev/actions/set_vlan_id_action.rb +41 -0
- data/lib/openflowdev/actions/set_vlan_pcp_action.rb +41 -0
- data/lib/openflowdev/actions/strip_vlan_action.rb +35 -0
- data/lib/openflowdev/actions/sw_path_action.rb +39 -0
- data/lib/openflowdev/flow_entry.rb +91 -0
- data/lib/openflowdev/instruction.rb +53 -0
- data/lib/openflowdev/match.rb +121 -0
- data/lib/openflowdev/of_switch.rb +374 -0
- data/lib/rubybvc.rb +52 -0
- data/lib/utils/hash_with_compact.rb +46 -0
- data/lib/utils/netconf_response.rb +67 -0
- data/lib/utils/netconf_response_status.rb +41 -0
- data/lib/utils/rest_agent.rb +103 -0
- data/lib/utils/utilities.rb +51 -0
- metadata +111 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 0b3c2cc02ad9c527fce130fcc17d73725e11eee9
|
4
|
+
data.tar.gz: 8634ee93a57d512ce5761216cf785a1f1ce91fe0
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 07f09c082d23fadc7b94e7611f65fd69edd02a93de43da0de34cab13454e56063c2f682d088a3ebc938f6ef039fcf3591ced849d38ca7fccd35aae79217b6ba5
|
7
|
+
data.tar.gz: dec8ff130b3e240d12bd45b4ce8f72517c34964efbdf7fdf40cb522cc6bfb7a3d662bcde8a65ac8f5740101ad6d5e4f6d0034b192da4f7daff3e52f7175cda40
|
@@ -0,0 +1,445 @@
|
|
1
|
+
# Copyright (c) 2015, BROCADE COMMUNICATIONS SYSTEMS, INC
|
2
|
+
#
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without modification,
|
6
|
+
# are permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# 1. Redistributions of source code must retain the above copyright notice, this
|
9
|
+
# list of conditions and the following disclaimer.
|
10
|
+
#
|
11
|
+
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
12
|
+
# this list of conditions and the following disclaimer in the documentation
|
13
|
+
# and/or other materials provided with the distribution.
|
14
|
+
#
|
15
|
+
# 3. Neither the name of the copyright holder nor the names of its contributors
|
16
|
+
# may be used to endorse or promote products derived from this software without
|
17
|
+
# specific prior written permission.
|
18
|
+
#
|
19
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
20
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
21
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
22
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
23
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
24
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
25
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
26
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
27
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
28
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
29
|
+
# THE POSSIBILITY OF SUCH DAMAGE.
|
30
|
+
|
31
|
+
class Controller
|
32
|
+
require 'json'
|
33
|
+
require 'utils/rest_agent'
|
34
|
+
require 'utils/netconf_response'
|
35
|
+
require 'utils/utilities'
|
36
|
+
require 'controller/netconf_node'
|
37
|
+
require 'nokogiri'
|
38
|
+
|
39
|
+
attr_reader :ip
|
40
|
+
attr_reader :port
|
41
|
+
attr_reader :username
|
42
|
+
attr_reader :password
|
43
|
+
attr_reader :timeout
|
44
|
+
attr_reader :rest_agent
|
45
|
+
|
46
|
+
def initialize(ip_addr: nil, port_number: 8181, admin_name: nil,
|
47
|
+
admin_password: nil, timeout_in_s: 5)
|
48
|
+
raise ArgumentError, "IP Address (ip_addr) required" unless ip_addr
|
49
|
+
raise ArgumentError, "Admin Username (admin_name) required" unless admin_name
|
50
|
+
raise ArgumentError, "Admin Password (admin_password) required" unless admin_password
|
51
|
+
@ip = ip_addr
|
52
|
+
@port = port_number
|
53
|
+
@username = admin_name
|
54
|
+
@password = admin_password
|
55
|
+
@timeout = timeout_in_s
|
56
|
+
|
57
|
+
@rest_agent = RestAgent.new("http://#{@ip}:#{@port}", username: @username,
|
58
|
+
password: @password, open_timeout: @timeout)
|
59
|
+
end
|
60
|
+
|
61
|
+
def get_schemas(node_name)
|
62
|
+
get_uri = "/restconf/operational/opendaylight-inventory:nodes/node/"\
|
63
|
+
"#{node_name}/yang-ext:mount/ietf-netconf-monitoring:netconf-state/schemas"
|
64
|
+
response = @rest_agent.get_request(get_uri)
|
65
|
+
check_response_for_success(response) do |body|
|
66
|
+
if body.has_key?('schemas') && body['schemas'].has_key?('schema')
|
67
|
+
NetconfResponse.new(NetconfResponseStatus::OK, body['schemas']['schema'])
|
68
|
+
else
|
69
|
+
NetconfResponse.new(NetconfResponseStatus::DATA_NOT_FOUND)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def get_schema(node_name, id: nil, version: nil)
|
75
|
+
raise ArgumentError, "Identifier (id) required" unless id
|
76
|
+
raise ArgumentError, "Version (version) required" unless version
|
77
|
+
post_uri = "/restconf/operations/opendaylight-inventory:nodes/node/"\
|
78
|
+
"#{node_name}/yang-ext:mount/ietf-netconf-monitoring:get-schema"
|
79
|
+
post_body = {:input => {:identifier => id, :version => version,
|
80
|
+
:format => 'yang'}}
|
81
|
+
response = @rest_agent.post_request(post_uri, post_body)
|
82
|
+
check_response_for_success(response) do |body|
|
83
|
+
if body.has_key?('get-schema') && body['get-schema'].has_key?('output') &&
|
84
|
+
body['get-schema']['output'].has_key?('data')
|
85
|
+
NetconfResponse.new(NetconfResponseStatus::OK,
|
86
|
+
body['get-schema']['output']['data'])
|
87
|
+
else
|
88
|
+
NetconfResponse.new(NetconfResponseStatus::DATA_NOT_FOUND)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def get_service_providers_info
|
94
|
+
get_uri = "/restconf/config/opendaylight-inventory:nodes/node/"\
|
95
|
+
"controller-config/yang-ext:mount/config:services"
|
96
|
+
response = @rest_agent.get_request(get_uri)
|
97
|
+
check_response_for_success(response) do |body|
|
98
|
+
if body.has_key?('services') && body['services'].has_key?('service')
|
99
|
+
NetconfResponse.new(NetconfResponseStatus::OK, body['services']['service'])
|
100
|
+
else
|
101
|
+
NetconfResponse.new(NetconfResponseStatus::DATA_NOT_FOUND)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def get_service_provider_info(provider_name)
|
107
|
+
get_uri = "/restconf/config/opendaylight-inventory:nodes/node/"\
|
108
|
+
"controller-config/yang-ext:mount/config:services/service/#{provider_name}"
|
109
|
+
response = @rest_agent.get_request(get_uri)
|
110
|
+
check_response_for_success(response) do |body|
|
111
|
+
if body.has_key?('service')
|
112
|
+
NetconfResponse.new(NetconfResponseStatus::OK, body['service'])
|
113
|
+
else
|
114
|
+
NetconfResponse.new(NetconfResponseStatus::DATA_NOT_FOUND)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def get_netconf_operations(node_name)
|
120
|
+
get_uri = "/restconf/operations/opendaylight-inventory:nodes/node/"\
|
121
|
+
"#{node_name}/yang-ext:mount"
|
122
|
+
response = @rest_agent.get_request(get_uri)
|
123
|
+
check_response_for_success(response) do |body|
|
124
|
+
if body.has_key?('operations')
|
125
|
+
NetconfResponse.new(NetconfResponseStatus::OK, body['operations'])
|
126
|
+
else
|
127
|
+
NetconfResponse.new(NetconfResponseStatus::DATA_NOT_FOUND)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def get_all_modules_operational_state
|
133
|
+
get_uri = "/restconf/operational/opendaylight-inventory:nodes/node/"\
|
134
|
+
"controller-config/yang-ext:mount/config:modules"
|
135
|
+
response = @rest_agent.get_request(get_uri)
|
136
|
+
response.body.gsub!("\\\n", "")
|
137
|
+
check_response_for_success(response) do |body|
|
138
|
+
if body.has_key?('modules') && body['modules'].has_key?('module')
|
139
|
+
NetconfResponse.new(NetconfResponseStatus::OK, body['modules']['module'])
|
140
|
+
else
|
141
|
+
NetconfResponse.new(NetconfResponseStatus::DATA_NOT_FOUND)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def get_module_operational_state(type: nil, name: nil)
|
147
|
+
raise ArgumentError, "Type (type) required" unless type
|
148
|
+
raise ArgumentError, "Name (name) required" unless name
|
149
|
+
get_uri = "/restconf/operational/opendaylight-inventory:nodes/node/"\
|
150
|
+
"controller-config/yang-ext:mount/config:modules/module/"\
|
151
|
+
"#{type}/#{name}"
|
152
|
+
response = @rest_agent.get_request(get_uri)
|
153
|
+
check_response_for_success(response) do |body|
|
154
|
+
if body.has_key?('module')
|
155
|
+
NetconfResponse.new(NetconfResponseStatus::OK, body["module"])
|
156
|
+
else
|
157
|
+
NetconfResponse.new(NetconfResponseStatus::DATA_NOT_FOUND)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def get_sessions_info(node_name)
|
163
|
+
get_uri = "/restconf/operational/opendaylight-inventory:nodes/node/"\
|
164
|
+
"#{node_name}/yang-ext:mount/ietf-netconf-monitoring:netconf-state/"\
|
165
|
+
"sessions"
|
166
|
+
response = @rest_agent.get_request(get_uri)
|
167
|
+
check_response_for_success(response) do |body|
|
168
|
+
if body.has_key?('sessions')
|
169
|
+
NetconfResponse.new(NetconfResponseStatus::OK, body["sessions"])
|
170
|
+
else
|
171
|
+
NetconfResponse.new(NetconfResponseStatus::DATA_NOT_FOUND)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
def get_streams_info
|
177
|
+
get_uri = "restconf/streams"
|
178
|
+
response = @rest_agent.get_request(get_uri)
|
179
|
+
check_response_for_success(response) do |body|
|
180
|
+
if body.has_key?('streams')
|
181
|
+
NetconfResponse.new(NetconfResponseStatus::OK, body['streams'])
|
182
|
+
else
|
183
|
+
NetconfResponse.new(NetconfResponseStatus::DATA_NOT_FOUND)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
def get_all_nodes_in_config
|
189
|
+
get_uri = "/restconf/config/opendaylight-inventory:nodes"
|
190
|
+
response = @rest_agent.get_request(get_uri)
|
191
|
+
check_response_for_success(response) do |body|
|
192
|
+
if body.has_key?('nodes') && body['nodes'].has_key?('node')
|
193
|
+
devices = []
|
194
|
+
body['nodes']['node'].each do |node|
|
195
|
+
devices << node['id']
|
196
|
+
end
|
197
|
+
NetconfResponse.new(NetconfResponseStatus::OK, devices)
|
198
|
+
else
|
199
|
+
NetconfResponse.new(NetconfResponseStatus::DATA_NOT_FOUND)
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
def get_netconf_nodes_in_config
|
205
|
+
get_uri = "/restconf/config/opendaylight-inventory:nodes"
|
206
|
+
response = @rest_agent.get_request(get_uri)
|
207
|
+
check_response_for_success(response) do |body|
|
208
|
+
if body.has_key?('nodes') && body['nodes'].has_key?('node')
|
209
|
+
devices = []
|
210
|
+
body['nodes']['node'].each do |node|
|
211
|
+
devices << node['id'] unless node['id'].include?('openflow')
|
212
|
+
end
|
213
|
+
NetconfResponse.new(NetconfResponseStatus::OK, devices)
|
214
|
+
else
|
215
|
+
NetconfResponse.new(NetconfResponseStatus::DATA_NOT_FOUND)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
def get_netconf_nodes_conn_status
|
221
|
+
get_uri = "/restconf/operational/opendaylight-inventory:nodes"
|
222
|
+
response = @rest_agent.get_request(get_uri)
|
223
|
+
check_response_for_success(response) do |body|
|
224
|
+
if body.has_key?('nodes') && body['nodes'].has_key?('node')
|
225
|
+
conn_list = []
|
226
|
+
body['nodes']['node'].each do |node|
|
227
|
+
unless node['id'].include?('openflow')
|
228
|
+
conn_status = {:node => node['id'],
|
229
|
+
:connected => node['netconf-node-inventory:connected']}
|
230
|
+
conn_list << conn_status
|
231
|
+
end
|
232
|
+
end
|
233
|
+
NetconfResponse.new(NetconfResponseStatus::OK, conn_list)
|
234
|
+
else
|
235
|
+
NetconfResponse.new(NetconfResponseStatus::DATA_NOT_FOUND)
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
def get_nodes_operational_list
|
241
|
+
get_uri = "/restconf/operational/opendaylight-inventory:nodes"
|
242
|
+
response = @rest_agent.get_request(get_uri)
|
243
|
+
check_response_for_success(response) do |body|
|
244
|
+
if body.has_key?('nodes') && body['nodes'].has_key?('node')
|
245
|
+
list = []
|
246
|
+
body['nodes']['node'].each do |node|
|
247
|
+
list << node['id'] if node['id']
|
248
|
+
end
|
249
|
+
NetconfResponse.new(NetconfResponseStatus::OK, list)
|
250
|
+
else
|
251
|
+
NetconfResponse.new(NetconfResponseStatus::DATA_NOT_FOUND)
|
252
|
+
end
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
def get_openflow_nodes_operational_list
|
257
|
+
get_uri = "/restconf/operational/opendaylight-inventory:nodes"
|
258
|
+
response = @rest_agent.get_request(get_uri)
|
259
|
+
check_response_for_success(response) do |body|
|
260
|
+
if body.has_key?('nodes') && body['nodes'].has_key?('node')
|
261
|
+
filtered_list = []
|
262
|
+
body['nodes']['node'].each do |node|
|
263
|
+
filtered_list << node['id'] if node['id'].start_with?('openflow')
|
264
|
+
end
|
265
|
+
NetconfResponse.new(NetconfResponseStatus::OK, filtered_list)
|
266
|
+
else
|
267
|
+
NetconfResponse.new(NetconfResponseStatus::DATA_NOT_FOUND)
|
268
|
+
end
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
def get_node_info(node_name)
|
273
|
+
get_uri = "/restconf/operational/opendaylight-inventory:nodes/node/"\
|
274
|
+
"#{node_name}"
|
275
|
+
response = @rest_agent.get_request(get_uri)
|
276
|
+
check_response_for_success(response) do |body|
|
277
|
+
if body.has_key?('node')
|
278
|
+
NetconfResponse.new(NetconfResponseStatus::OK, body['node'])
|
279
|
+
else
|
280
|
+
NetconfResponse.new(NetconfResponseStatus::DATA_NOT_FOUND)
|
281
|
+
end
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
def check_node_config_status(node_name)
|
286
|
+
get_uri = "/restconf/config/opendaylight-inventory:nodes/node/#{node_name}"
|
287
|
+
response = @rest_agent.get_request(get_uri)
|
288
|
+
check_response_for_success(response) do
|
289
|
+
NetconfResponse.new(NetconfResponseStatus::NODE_CONFIGURED,
|
290
|
+
JSON.parse(response.body))
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
def check_node_conn_status(node_name)
|
295
|
+
get_uri = "/restconf/operational/opendaylight-inventory:nodes/node/"\
|
296
|
+
"#{node_name}"
|
297
|
+
response = @rest_agent.get_request(get_uri)
|
298
|
+
if response.code.to_i == 404
|
299
|
+
NetconfResponse.new(NetconfResponseStatus::NODE_NOT_FOUND)
|
300
|
+
else
|
301
|
+
check_response_for_success(response) do |body|
|
302
|
+
connected = false
|
303
|
+
if body.has_key?('node') && body['node'][0] && body['node'][0].has_key?('id')
|
304
|
+
if body['node'][0].has_key?('netconf-node-inventory:connected')
|
305
|
+
if body['node'][0]['netconf-node-inventory:connected']
|
306
|
+
connected = true
|
307
|
+
end
|
308
|
+
end
|
309
|
+
end
|
310
|
+
if connected
|
311
|
+
NetconfResponse.new(NetconfResponseStatus::NODE_CONNECTED)
|
312
|
+
else
|
313
|
+
NetconfResponse.new(NetconfResponseStatus::NODE_DISCONNECTED)
|
314
|
+
end
|
315
|
+
end
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
def get_all_nodes_conn_status
|
320
|
+
get_uri = "/restconf/operational/opendaylight-inventory:nodes"
|
321
|
+
response = @rest_agent.get_request(get_uri)
|
322
|
+
check_response_for_success(response) do |body|
|
323
|
+
if body.has_key?('nodes') && body['nodes'].has_key?('node')
|
324
|
+
conn_list = []
|
325
|
+
body['nodes']['node'].each do |node|
|
326
|
+
is_connected = false
|
327
|
+
if node['id'].include?('openflow')
|
328
|
+
# OpenFlow devices connect to controller (unlike NETCONF nodes),
|
329
|
+
# so if we see one, then it is 'connected'
|
330
|
+
is_connected = true
|
331
|
+
elsif node.has_key?('netconf-node-inventory:connected')
|
332
|
+
is_connected = node['netconf-node-inventory:connected']
|
333
|
+
end
|
334
|
+
conn_status = {:node => node['id'],
|
335
|
+
:connected => is_connected}
|
336
|
+
conn_list << conn_status
|
337
|
+
end
|
338
|
+
NetconfResponse.new(NetconfResponseStatus::OK, conn_list)
|
339
|
+
else
|
340
|
+
NetconfResponse.new(NetconfResponseStatus::DATA_NOT_FOUND)
|
341
|
+
end
|
342
|
+
end
|
343
|
+
end
|
344
|
+
|
345
|
+
def add_netconf_node(node)
|
346
|
+
post_uri = "/restconf/config/opendaylight-inventory:nodes/node/"\
|
347
|
+
"controller-config/yang-ext:mount/config:modules"
|
348
|
+
post_body = generate_node_xml(node)
|
349
|
+
response = @rest_agent.post_request(post_uri, post_body,
|
350
|
+
headers: {'Content-Type' => "application/xml",
|
351
|
+
'Accept' => "application/xml"})
|
352
|
+
check_response_for_success(response) do
|
353
|
+
NetconfResponse.new(NetconfResponseStatus::OK)
|
354
|
+
end
|
355
|
+
end
|
356
|
+
|
357
|
+
def delete_netconf_node(node)
|
358
|
+
delete_uri = "/restconf/config/opendaylight-inventory:nodes/node/"\
|
359
|
+
"controller-config/yang-ext:mount/config:modules/module/"\
|
360
|
+
"odl-sal-netconf-connector-cfg:sal-netconf-connector/#{node.name}"
|
361
|
+
response = @rest_agent.delete_request(delete_uri)
|
362
|
+
# need to do the check here because there is no response body and the code
|
363
|
+
# is a 200 instead of 204
|
364
|
+
if response.code.to_i == 200
|
365
|
+
NetconfResponse.new(NetconfResponseStatus::OK)
|
366
|
+
else
|
367
|
+
handle_error_response(response)
|
368
|
+
end
|
369
|
+
end
|
370
|
+
|
371
|
+
def get_node_operational_uri(node)
|
372
|
+
raise ArgumentError, "Node (node) must be a 'Node' object or a 'Node' "\
|
373
|
+
"subclass object" unless node.is_a?(Node) ||
|
374
|
+
(node.methods.include?(:ancestors) && node.ancestors.include?(Node))
|
375
|
+
"/restconf/operational/opendaylight-inventory:nodes/node/#{node.name}"
|
376
|
+
end
|
377
|
+
|
378
|
+
def get_node_config_uri(node)
|
379
|
+
raise ArgumentError, "Node (node) must be a 'Node' object or a 'Node' "\
|
380
|
+
"subclass object" unless node.is_a?(Node) ||
|
381
|
+
(node.methods.include?(:ancestors) && node.ancestors.include?(Node))
|
382
|
+
"/restconf/config/opendaylight-inventory:nodes/node/#{node.name}"
|
383
|
+
end
|
384
|
+
|
385
|
+
def get_ext_mount_config_uri(node)
|
386
|
+
raise ArgumentError, "Node (node) must be a 'Node' object or a 'Node' "\
|
387
|
+
"subclass object" unless node.is_a?(Node)
|
388
|
+
"/restconf/config/opendaylight-inventory:nodes/node/#{node.name}/yang-ext:mount"
|
389
|
+
end
|
390
|
+
|
391
|
+
def to_hash
|
392
|
+
{:ip_addr => @ip, :port_num => @port, :admin_name => @username,
|
393
|
+
:admin_password => @password}
|
394
|
+
end
|
395
|
+
|
396
|
+
private
|
397
|
+
|
398
|
+
def node_namespace_prefix
|
399
|
+
"urn:opendaylight:params:xml:ns:yang:controller"
|
400
|
+
end
|
401
|
+
|
402
|
+
def node_namespace
|
403
|
+
"#{node_namespace_prefix}:md:sal:connector:netconf"
|
404
|
+
end
|
405
|
+
|
406
|
+
def generate_node_xml(node)
|
407
|
+
builder = Nokogiri::XML::Builder.new { |xml|
|
408
|
+
xml.module(:xmlns => "#{node_namespace_prefix}:config") {
|
409
|
+
xml.type "prefix:sal-netconf-connector", 'xmlns:prefix' => node_namespace
|
410
|
+
xml.name node.name
|
411
|
+
xml.address node.ip, :xmlns => node_namespace
|
412
|
+
xml.port node.port, :xmlns => node_namespace
|
413
|
+
xml.username node.username, :xmlns => node_namespace
|
414
|
+
xml.password node.password, :xmlns => node_namespace
|
415
|
+
xml.send(:'tcp-only', node.tcp_only, :xmlns => node_namespace)
|
416
|
+
xml.send(:'event-executor', :xmlns => node_namespace) {
|
417
|
+
xml.type "prefix:netty-event-executor",
|
418
|
+
'xmlns:prefix' => "#{node_namespace_prefix}:netty"
|
419
|
+
xml.name "global-event-executor"
|
420
|
+
}
|
421
|
+
xml.send(:'binding-registry', :xmlns => node_namespace) {
|
422
|
+
xml.type "prefix:binding-broker-osgi-registry",
|
423
|
+
'xmlns:prefix' => "#{node_namespace_prefix}:md:sal:binding"
|
424
|
+
xml.name "binding-osgi-broker"
|
425
|
+
}
|
426
|
+
xml.send(:'dom-registry', :xmlns => node_namespace) {
|
427
|
+
xml.type "prefix:dom-broker-osgi-registry",
|
428
|
+
'xmlns:prefix' => "#{node_namespace_prefix}:md:sal:dom"
|
429
|
+
xml.name "dom-broker"
|
430
|
+
}
|
431
|
+
xml.send(:'client-dispatcher', :xmlns => node_namespace) {
|
432
|
+
xml.type "prefix:netconf-client-dispatcher",
|
433
|
+
'xmlns:prefix' => "#{node_namespace_prefix}:config:netconf"
|
434
|
+
xml.name "global-netconf-dispatcher"
|
435
|
+
}
|
436
|
+
xml.send(:'processing-executor', :xmlns => node_namespace) {
|
437
|
+
xml.type "prefix:threadpool",
|
438
|
+
'xmlns:prefix' => "#{node_namespace_prefix}:threadpool"
|
439
|
+
xml.name "global-netconf-processing-executor"
|
440
|
+
}
|
441
|
+
}
|
442
|
+
}
|
443
|
+
builder.to_xml
|
444
|
+
end
|
445
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# Copyright (c) 2015, BROCADE COMMUNICATIONS SYSTEMS, INC
|
2
|
+
#
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without modification,
|
6
|
+
# are permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# 1. Redistributions of source code must retain the above copyright notice, this
|
9
|
+
# list of conditions and the following disclaimer.
|
10
|
+
#
|
11
|
+
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
12
|
+
# this list of conditions and the following disclaimer in the documentation
|
13
|
+
# and/or other materials provided with the distribution.
|
14
|
+
#
|
15
|
+
# 3. Neither the name of the copyright holder nor the names of its contributors
|
16
|
+
# may be used to endorse or promote products derived from this software without
|
17
|
+
# specific prior written permission.
|
18
|
+
#
|
19
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
20
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
21
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
22
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
23
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
24
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
25
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
26
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
27
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
28
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
29
|
+
# THE POSSIBILITY OF SUCH DAMAGE.
|
30
|
+
|
31
|
+
require 'controller/node'
|
32
|
+
class NetconfNode < Node
|
33
|
+
attr_reader :ip, :port, :username, :password, :tcp_only
|
34
|
+
|
35
|
+
def initialize(controller: nil, name: nil, ip_addr: nil,
|
36
|
+
port_number: nil, admin_name: nil, admin_password: nil,
|
37
|
+
tcp_only: false)
|
38
|
+
super(controller: controller, name: name)
|
39
|
+
raise ArgumentError, "IP Address (ip_addr) required" unless ip_addr
|
40
|
+
raise ArgumentError, "Port Number (port_number) required" unless port_number
|
41
|
+
raise ArgumentError, "Admin Username (admin_name) required" unless admin_name
|
42
|
+
raise ArgumentError, "Admin Password (admin_password) required" unless admin_password
|
43
|
+
|
44
|
+
@ip = ip_addr
|
45
|
+
@port = port_number
|
46
|
+
@username = admin_name
|
47
|
+
@password = admin_password
|
48
|
+
@tcp_only = tcp_only
|
49
|
+
end
|
50
|
+
|
51
|
+
def to_hash
|
52
|
+
{:controller => @controller.to_hash, :name => @name, :ip_addr => @ip,
|
53
|
+
:port_num => @port, :admin_name => @username, :admin_password => @password}
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# Copyright (c) 2015, BROCADE COMMUNICATIONS SYSTEMS, INC
|
2
|
+
#
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without modification,
|
6
|
+
# are permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# 1. Redistributions of source code must retain the above copyright notice, this
|
9
|
+
# list of conditions and the following disclaimer.
|
10
|
+
#
|
11
|
+
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
12
|
+
# this list of conditions and the following disclaimer in the documentation
|
13
|
+
# and/or other materials provided with the distribution.
|
14
|
+
#
|
15
|
+
# 3. Neither the name of the copyright holder nor the names of its contributors
|
16
|
+
# may be used to endorse or promote products derived from this software without
|
17
|
+
# specific prior written permission.
|
18
|
+
#
|
19
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
20
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
21
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
22
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
23
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
24
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
25
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
26
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
27
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
28
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
29
|
+
# THE POSSIBILITY OF SUCH DAMAGE.
|
30
|
+
|
31
|
+
class Node
|
32
|
+
attr_reader :name
|
33
|
+
|
34
|
+
def initialize(controller: nil, name: nil)
|
35
|
+
raise ArgumentError, "Controller (controller) required" unless controller
|
36
|
+
raise ArgumentError, "Name (name) required" unless name
|
37
|
+
raise ArgumentError, "Controller (controller) must be instance of 'Controller'" unless controller.is_a?(Controller)
|
38
|
+
@controller = controller
|
39
|
+
@name = name
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# Copyright (c) 2015, BROCADE COMMUNICATIONS SYSTEMS, INC
|
2
|
+
#
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without modification,
|
6
|
+
# are permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# 1. Redistributions of source code must retain the above copyright notice, this
|
9
|
+
# list of conditions and the following disclaimer.
|
10
|
+
#
|
11
|
+
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
12
|
+
# this list of conditions and the following disclaimer in the documentation
|
13
|
+
# and/or other materials provided with the distribution.
|
14
|
+
#
|
15
|
+
# 3. Neither the name of the copyright holder nor the names of its contributors
|
16
|
+
# may be used to endorse or promote products derived from this software without
|
17
|
+
# specific prior written permission.
|
18
|
+
#
|
19
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
20
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
21
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
22
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
23
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
24
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
25
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
26
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
27
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
28
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
29
|
+
# THE POSSIBILITY OF SUCH DAMAGE.
|
30
|
+
|
31
|
+
class OpenflowNode < Node
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# Copyright (c) 2015, BROCADE COMMUNICATIONS SYSTEMS, INC
|
2
|
+
#
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without modification,
|
6
|
+
# are permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# 1. Redistributions of source code must retain the above copyright notice, this
|
9
|
+
# list of conditions and the following disclaimer.
|
10
|
+
#
|
11
|
+
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
12
|
+
# this list of conditions and the following disclaimer in the documentation
|
13
|
+
# and/or other materials provided with the distribution.
|
14
|
+
#
|
15
|
+
# 3. Neither the name of the copyright holder nor the names of its contributors
|
16
|
+
# may be used to endorse or promote products derived from this software without
|
17
|
+
# specific prior written permission.
|
18
|
+
#
|
19
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
20
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
21
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
22
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
23
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
24
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
25
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
26
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
27
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
28
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
29
|
+
# THE POSSIBILITY OF SUCH DAMAGE.
|
30
|
+
|
31
|
+
class DataplaneFirewall
|
32
|
+
def initialize(interface_name: nil, in_firewall_name: nil,
|
33
|
+
out_firewall_name: nil)
|
34
|
+
raise ArgumentError, "Interface Name (interface_name) required" unless interface_name
|
35
|
+
raise ArgumentError, "At least one firewall name (in_firewall_name, "\
|
36
|
+
"out_firewall_name) required" unless in_firewall_name || out_firewall_name
|
37
|
+
|
38
|
+
@name = interface_name
|
39
|
+
@in_firewall = in_firewall_name
|
40
|
+
@out_firewall = out_firewall_name
|
41
|
+
end
|
42
|
+
|
43
|
+
def get_uri
|
44
|
+
"/vyatta-interfaces:interfaces/vyatta-interfaces-dataplane:dataplane/"\
|
45
|
+
"#{@name}"
|
46
|
+
end
|
47
|
+
|
48
|
+
def to_hash
|
49
|
+
{'vyatta-interfaces-dataplane:dataplane' => {:tagnode => @name,
|
50
|
+
'vyatta-security-firewall:firewall' => {:in => [@in_firewall],
|
51
|
+
:out => [@out_firewall]}}}
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# Copyright (c) 2015, BROCADE COMMUNICATIONS SYSTEMS, INC
|
2
|
+
#
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without modification,
|
6
|
+
# are permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# 1. Redistributions of source code must retain the above copyright notice, this
|
9
|
+
# list of conditions and the following disclaimer.
|
10
|
+
#
|
11
|
+
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
12
|
+
# this list of conditions and the following disclaimer in the documentation
|
13
|
+
# and/or other materials provided with the distribution.
|
14
|
+
#
|
15
|
+
# 3. Neither the name of the copyright holder nor the names of its contributors
|
16
|
+
# may be used to endorse or promote products derived from this software without
|
17
|
+
# specific prior written permission.
|
18
|
+
#
|
19
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
20
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
21
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
22
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
23
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
24
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
25
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
26
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
27
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
28
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
29
|
+
# THE POSSIBILITY OF SUCH DAMAGE.
|
30
|
+
|
31
|
+
class Firewall
|
32
|
+
attr_reader :rules
|
33
|
+
|
34
|
+
def initialize(rules: nil)
|
35
|
+
raise ArgumentError, "Rules (rules) required" unless rules
|
36
|
+
raise ArgumentError, "Rules (rules) must be instance of 'Rules'" unless rules.is_a?(Rules)
|
37
|
+
@rules = rules
|
38
|
+
end
|
39
|
+
|
40
|
+
def to_hash
|
41
|
+
{'vyatta-security:security' => {'vyatta-security-firewall:firewall' =>
|
42
|
+
{:name => [@rules.to_hash]}}}
|
43
|
+
end
|
44
|
+
end
|