hrr_rb_netconf 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +28 -0
- data/.rspec +3 -0
- data/.travis.yml +32 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +6 -0
- data/LICENSE +201 -0
- data/README.md +220 -0
- data/Rakefile +6 -0
- data/demo/server.rb +54 -0
- data/demo/server_over_ssh.rb +97 -0
- data/demo/server_with_session-oriented-database.rb +134 -0
- data/demo/server_with_sessionless-database.rb +81 -0
- data/hrr_rb_netconf.gemspec +28 -0
- data/lib/hrr_rb_netconf.rb +10 -0
- data/lib/hrr_rb_netconf/logger.rb +56 -0
- data/lib/hrr_rb_netconf/server.rb +109 -0
- data/lib/hrr_rb_netconf/server/capabilities.rb +75 -0
- data/lib/hrr_rb_netconf/server/capability.rb +206 -0
- data/lib/hrr_rb_netconf/server/capability/base_1_0.rb +183 -0
- data/lib/hrr_rb_netconf/server/capability/base_1_1.rb +247 -0
- data/lib/hrr_rb_netconf/server/capability/candidate_1_0.rb +34 -0
- data/lib/hrr_rb_netconf/server/capability/confirmed_commit_1_0.rb +24 -0
- data/lib/hrr_rb_netconf/server/capability/confirmed_commit_1_1.rb +24 -0
- data/lib/hrr_rb_netconf/server/capability/rollback_on_error_1_0.rb +16 -0
- data/lib/hrr_rb_netconf/server/capability/startup_1_0.rb +22 -0
- data/lib/hrr_rb_netconf/server/capability/url_1_0.rb +23 -0
- data/lib/hrr_rb_netconf/server/capability/validate_1_0.rb +25 -0
- data/lib/hrr_rb_netconf/server/capability/validate_1_1.rb +25 -0
- data/lib/hrr_rb_netconf/server/capability/writable_running_1_0.rb +17 -0
- data/lib/hrr_rb_netconf/server/capability/xpath_1_0.rb +14 -0
- data/lib/hrr_rb_netconf/server/datastore.rb +30 -0
- data/lib/hrr_rb_netconf/server/datastore/oper_handler.rb +29 -0
- data/lib/hrr_rb_netconf/server/datastore/session.rb +52 -0
- data/lib/hrr_rb_netconf/server/error.rb +52 -0
- data/lib/hrr_rb_netconf/server/error/access_denied.rb +19 -0
- data/lib/hrr_rb_netconf/server/error/bad_attribute.rb +20 -0
- data/lib/hrr_rb_netconf/server/error/bad_element.rb +20 -0
- data/lib/hrr_rb_netconf/server/error/data_exists.rb +19 -0
- data/lib/hrr_rb_netconf/server/error/data_missing.rb +19 -0
- data/lib/hrr_rb_netconf/server/error/in_use.rb +19 -0
- data/lib/hrr_rb_netconf/server/error/invalid_value.rb +19 -0
- data/lib/hrr_rb_netconf/server/error/lock_denied.rb +19 -0
- data/lib/hrr_rb_netconf/server/error/malformed_message.rb +19 -0
- data/lib/hrr_rb_netconf/server/error/missing_attribute.rb +19 -0
- data/lib/hrr_rb_netconf/server/error/missing_element.rb +19 -0
- data/lib/hrr_rb_netconf/server/error/operation_failed.rb +19 -0
- data/lib/hrr_rb_netconf/server/error/operation_not_supported.rb +19 -0
- data/lib/hrr_rb_netconf/server/error/partial_operation.rb +19 -0
- data/lib/hrr_rb_netconf/server/error/resource_denied.rb +19 -0
- data/lib/hrr_rb_netconf/server/error/rollback_failed.rb +19 -0
- data/lib/hrr_rb_netconf/server/error/rpc_errorable.rb +138 -0
- data/lib/hrr_rb_netconf/server/error/too_big.rb +19 -0
- data/lib/hrr_rb_netconf/server/error/unknown_attribute.rb +19 -0
- data/lib/hrr_rb_netconf/server/error/unknown_element.rb +19 -0
- data/lib/hrr_rb_netconf/server/error/unknown_namespace.rb +19 -0
- data/lib/hrr_rb_netconf/server/errors.rb +28 -0
- data/lib/hrr_rb_netconf/server/filter.rb +48 -0
- data/lib/hrr_rb_netconf/server/filter/subtree.rb +135 -0
- data/lib/hrr_rb_netconf/server/filter/xpath.rb +59 -0
- data/lib/hrr_rb_netconf/server/model.rb +123 -0
- data/lib/hrr_rb_netconf/server/model/node.rb +19 -0
- data/lib/hrr_rb_netconf/server/operation.rb +92 -0
- data/lib/hrr_rb_netconf/server/session.rb +177 -0
- data/lib/hrr_rb_netconf/version.rb +6 -0
- metadata +149 -0
@@ -0,0 +1,247 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# vim: et ts=2 sw=2
|
3
|
+
|
4
|
+
require 'rexml/document'
|
5
|
+
require 'hrr_rb_netconf/logger'
|
6
|
+
|
7
|
+
module HrrRbNetconf
|
8
|
+
class Server
|
9
|
+
class Capability
|
10
|
+
class Base_1_1 < Capability
|
11
|
+
ID = 'urn:ietf:params:netconf:base:1.1'
|
12
|
+
DEPENDENCIES = []
|
13
|
+
IF_FEATURES = []
|
14
|
+
|
15
|
+
oper_proc('get'){ |session, datastore, input_e|
|
16
|
+
datastore.run 'get', input_e
|
17
|
+
}
|
18
|
+
|
19
|
+
oper_proc('get-config'){ |session, datastore, input_e|
|
20
|
+
datastore.run 'get-config', input_e
|
21
|
+
}
|
22
|
+
|
23
|
+
oper_proc('edit-config'){ |session, datastore, input_e|
|
24
|
+
datastore.run 'edit-config', input_e
|
25
|
+
'<ok />'
|
26
|
+
}
|
27
|
+
|
28
|
+
oper_proc('copy-config'){ |session, datastore, input_e|
|
29
|
+
datastore.run 'copy-config', input_e
|
30
|
+
'<ok />'
|
31
|
+
}
|
32
|
+
|
33
|
+
oper_proc('delete-config'){ |session, datastore, input_e|
|
34
|
+
datastore.run 'delete-config', input_e
|
35
|
+
'<ok />'
|
36
|
+
}
|
37
|
+
|
38
|
+
oper_proc('lock'){ |session, datastore, input_e|
|
39
|
+
target = input_e.elements['target'].elements[1].name
|
40
|
+
session.lock target
|
41
|
+
begin
|
42
|
+
datastore.run 'lock', input_e
|
43
|
+
'<ok />'
|
44
|
+
rescue
|
45
|
+
session.unlock target
|
46
|
+
raise
|
47
|
+
end
|
48
|
+
}
|
49
|
+
|
50
|
+
oper_proc('unlock'){ |session, datastore, input_e|
|
51
|
+
datastore.run 'unlock', input_e
|
52
|
+
target = input_e.elements['target'].elements[1].name
|
53
|
+
session.unlock target
|
54
|
+
'<ok />'
|
55
|
+
}
|
56
|
+
|
57
|
+
oper_proc('close-session'){ |session, datastore, input_e|
|
58
|
+
datastore.run 'close-session', input_e
|
59
|
+
session.close
|
60
|
+
'<ok />'
|
61
|
+
}
|
62
|
+
|
63
|
+
oper_proc('kill-session'){ |session, datastore, input_e|
|
64
|
+
session.close_other Integer(input_e.elements['session-id'].text)
|
65
|
+
'<ok />'
|
66
|
+
}
|
67
|
+
|
68
|
+
model 'get', ['filter'], 'leaf', 'type' => 'anyxml'
|
69
|
+
model 'get-config', ['source'], 'container'
|
70
|
+
model 'get-config', ['source', 'config-source'], 'choice', 'mandatory' => true
|
71
|
+
model 'get-config', ['source', 'config-source', 'running'], 'leaf', 'type' => 'empty'
|
72
|
+
model 'get-config', ['filter'], 'leaf', 'type' => 'anyxml'
|
73
|
+
model 'edit-config', ['target'], 'container'
|
74
|
+
model 'edit-config', ['target', 'config-target'], 'choice', 'mandatory' => true
|
75
|
+
model 'edit-config', ['default-operation'], 'leaf', 'type' => 'enumeration', 'enum' => ['merge', 'replace', 'none'], 'default' => 'merge'
|
76
|
+
model 'edit-config', ['error-option'], 'leaf', 'type' => 'enumeration', 'enum' => ['stop-on-error', 'continue-on-error', 'rollback-on-error'], 'default' => 'stop-on-error'
|
77
|
+
model 'edit-config', ['edit-content'], 'choice', 'mandatory' => true
|
78
|
+
model 'edit-config', ['edit-content', 'config'], 'leaf', 'type' => 'anyxml'
|
79
|
+
model 'copy-config', ['target'], 'container'
|
80
|
+
model 'copy-config', ['target', 'config-target'], 'choice', 'mandatory' => true
|
81
|
+
model 'copy-config', ['source'], 'container'
|
82
|
+
model 'copy-config', ['source', 'config-source'], 'choice', 'mandatory' => true
|
83
|
+
model 'copy-config', ['source', 'config-source', 'running'], 'leaf', 'type' => 'empty'
|
84
|
+
model 'copy-config', ['source', 'config-source', 'config'], 'leaf', 'type' => 'anyxml'
|
85
|
+
model 'delete-config', ['target'], 'container'
|
86
|
+
model 'delete-config', ['target', 'config-target'], 'choice', 'mandatory' => true
|
87
|
+
model 'lock', ['target'], 'container'
|
88
|
+
model 'lock', ['target', 'config-target'], 'choice', 'mandatory' => true
|
89
|
+
model 'lock', ['target', 'config-target', 'running'], 'leaf', 'type' => 'empty'
|
90
|
+
model 'unlock', ['target'], 'container'
|
91
|
+
model 'unlock', ['target', 'config-target'], 'choice', 'mandatory' => true
|
92
|
+
model 'unlock', ['target', 'config-target', 'running'], 'leaf', 'type' => 'empty'
|
93
|
+
model 'close-session', []
|
94
|
+
model 'kill-session', ['session-id'], 'leaf', 'type' => 'integer', 'range' => [1, 2**32-1]
|
95
|
+
|
96
|
+
class Sender
|
97
|
+
MAX_CHUNK_SIZE = 2**32 - 1
|
98
|
+
|
99
|
+
def initialize io_w
|
100
|
+
@logger = Logger.new self.class.name
|
101
|
+
@io_w = io_w
|
102
|
+
@formatter = REXML::Formatters::Pretty.new(2)
|
103
|
+
@formatter.compact = true
|
104
|
+
end
|
105
|
+
|
106
|
+
def send_message msg
|
107
|
+
raw_msg = StringIO.new
|
108
|
+
case msg
|
109
|
+
when String
|
110
|
+
begin
|
111
|
+
@formatter.write(REXML::Document.new(msg, {:ignore_whitespace_nodes => :all}).root, raw_msg)
|
112
|
+
rescue => e
|
113
|
+
@logger.error { "Invalid sending message: #{msg.inspect}: #{e.message}" }
|
114
|
+
raise "Invalid sending message: #{msg.inspect}: #{e.message}"
|
115
|
+
end
|
116
|
+
when REXML::Document
|
117
|
+
@formatter.write(msg.root, raw_msg)
|
118
|
+
when REXML::Element
|
119
|
+
@formatter.write(msg, raw_msg)
|
120
|
+
else
|
121
|
+
@logger.error { "Unexpected sending message: #{msg.inspect}" }
|
122
|
+
raise ArgumentError, "Unexpected sending message: #{msg.inspect}"
|
123
|
+
end
|
124
|
+
@logger.debug { "Sending message: #{raw_msg.string.inspect}" }
|
125
|
+
raw_msg.rewind
|
126
|
+
encoded_msg = StringIO.new
|
127
|
+
until raw_msg.eof?
|
128
|
+
chunk_size = rand(1..MAX_CHUNK_SIZE)
|
129
|
+
chunk_data = raw_msg.read(chunk_size)
|
130
|
+
encoded_msg.write "\n##{chunk_data.size}\n#{chunk_data}"
|
131
|
+
end
|
132
|
+
encoded_msg.write "\n##\n"
|
133
|
+
@logger.debug { "Sending encoded message: #{encoded_msg.string.inspect}" }
|
134
|
+
begin
|
135
|
+
@io_w.write encoded_msg.string
|
136
|
+
rescue => e
|
137
|
+
@logger.info { "Sender IO closed: #{e.class}: #{e.message}" }
|
138
|
+
raise IOError, "Sender IO closed: #{e.class}: #{e.message}"
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
class Receiver
|
144
|
+
def initialize io_r
|
145
|
+
@logger = Logger.new self.class.name
|
146
|
+
@io_r = io_r
|
147
|
+
end
|
148
|
+
|
149
|
+
def receive_message
|
150
|
+
chunk_size = StringIO.new
|
151
|
+
chunked_msg = StringIO.new
|
152
|
+
decoded_msg = StringIO.new
|
153
|
+
read_len = 1
|
154
|
+
state = :beginning_of_msg
|
155
|
+
until state == :end_of_msg
|
156
|
+
begin
|
157
|
+
buf = @io_r.read(read_len)
|
158
|
+
rescue => e
|
159
|
+
@logger.info { "Receiver IO closed: #{e.class}: #{e.message}" }
|
160
|
+
return nil
|
161
|
+
end
|
162
|
+
if buf.nil?
|
163
|
+
@logger.info { "Receiver IO closed" }
|
164
|
+
return nil
|
165
|
+
end
|
166
|
+
chunked_msg.write buf
|
167
|
+
case state
|
168
|
+
when :beginning_of_msg
|
169
|
+
if buf == "\n"
|
170
|
+
state = :before_chunk_size
|
171
|
+
else
|
172
|
+
info = "In beginning_of_msg: expected #{"\n".inspect}, but got #{buf.inspect}: #{chunked_msg.string.inspect}"
|
173
|
+
@logger.info { info }
|
174
|
+
raise Error['malformed-message'].new("rpc", "error")
|
175
|
+
end
|
176
|
+
when :before_chunk_size
|
177
|
+
if buf == "#"
|
178
|
+
state = :in_chunk_size
|
179
|
+
else
|
180
|
+
info = "In before_chunk_size: expected #{"#".inspect}, but got #{buf.inspect}: #{chunked_msg.string.inspect}"
|
181
|
+
@logger.info { info }
|
182
|
+
raise Error['malformed-message'].new("rpc", "error")
|
183
|
+
end
|
184
|
+
when :in_chunk_size
|
185
|
+
if buf =~ /[0-9]/
|
186
|
+
chunk_size.write buf
|
187
|
+
elsif buf == "\n"
|
188
|
+
read_len = chunk_size.string.to_i
|
189
|
+
state = :in_chunk_data
|
190
|
+
elsif buf == "#"
|
191
|
+
state = :ending_msg
|
192
|
+
else
|
193
|
+
info = "In in_chunk_size: expected #{"/[0-9]/".inspect}, #{"\n".inspect}, or #{"#".inspect}, but got #{buf.inspect}: #{chunked_msg.string.inspect}"
|
194
|
+
@logger.info { info }
|
195
|
+
raise Error['malformed-message'].new("rpc", "error")
|
196
|
+
end
|
197
|
+
when :in_chunk_data
|
198
|
+
chunk_size = StringIO.new
|
199
|
+
decoded_msg.write buf
|
200
|
+
read_len = 1
|
201
|
+
state = :after_chunk_data
|
202
|
+
when :after_chunk_data
|
203
|
+
if buf == "\n"
|
204
|
+
state = :before_chunk_size
|
205
|
+
else
|
206
|
+
info = "In after_chunk_data: expected #{"\n".inspect}, but got #{buf.inspect}: #{chunked_msg.string.inspect}"
|
207
|
+
@logger.info { info }
|
208
|
+
raise Error['malformed-message'].new("rpc", "error")
|
209
|
+
end
|
210
|
+
when :ending_msg
|
211
|
+
if buf == "\n"
|
212
|
+
state = :end_of_msg
|
213
|
+
else
|
214
|
+
info = "In ending_msg: expected #{"\n".inspect}, but got #{buf.inspect}: #{chunked_msg.string.inspect}"
|
215
|
+
@logger.info { info }
|
216
|
+
raise Error['malformed-message'].new("rpc", "error")
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
220
|
+
@logger.debug { "Received message: #{decoded_msg.string.inspect}" }
|
221
|
+
begin
|
222
|
+
received_msg = REXML::Document.new(decoded_msg.string, {:ignore_whitespace_nodes => :all}).root
|
223
|
+
validate_received_msg received_msg
|
224
|
+
received_msg
|
225
|
+
rescue => e
|
226
|
+
info = "Invalid received message: #{e.message.split("\n").first}: #{decoded_msg.string.inspect}"
|
227
|
+
@logger.info { info }
|
228
|
+
raise Error['malformed-message'].new("rpc", "error")
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
def validate_received_msg received_msg
|
233
|
+
unless received_msg
|
234
|
+
raise "No valid root tag interpreted"
|
235
|
+
end
|
236
|
+
unless "rpc" == received_msg.name
|
237
|
+
raise "Invalid message: expected #{"rpc".inspect}, but got #{received_msg.name.inspect}"
|
238
|
+
end
|
239
|
+
unless "urn:ietf:params:xml:ns:netconf:base:1.0" == received_msg.namespace
|
240
|
+
raise "Invalid namespace: expected #{"urn:ietf:params:xml:ns:netconf:base:1.0".inspect}, but got #{received_msg.namespace.inspect}"
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|
247
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# vim: et ts=2 sw=2
|
3
|
+
|
4
|
+
module HrrRbNetconf
|
5
|
+
class Server
|
6
|
+
class Capability
|
7
|
+
class Candidate_1_0 < Capability
|
8
|
+
ID = 'urn:ietf:params:netconf:capability:candidate:1.0'
|
9
|
+
DEPENDENCIES = []
|
10
|
+
IF_FEATURES = ['candidate']
|
11
|
+
|
12
|
+
oper_proc('commit'){ |session, datastore, input_e|
|
13
|
+
datastore.run 'commit', input_e
|
14
|
+
'<ok />'
|
15
|
+
}
|
16
|
+
|
17
|
+
oper_proc('discard-changes'){ |session, datastore, input_e|
|
18
|
+
datastore.run 'discard-changes', input_e
|
19
|
+
'<ok />'
|
20
|
+
}
|
21
|
+
|
22
|
+
model 'get-config', ['source', 'config-source', 'candidate'], 'leaf', 'type' => 'empty'
|
23
|
+
model 'edit-config', ['target', 'config-target', 'candidate'], 'leaf', 'type' => 'empty'
|
24
|
+
model 'copy-config', ['source', 'config-source', 'candidate'], 'leaf', 'type' => 'empty'
|
25
|
+
model 'copy-config', ['target', 'config-target', 'candidate'], 'leaf', 'type' => 'empty'
|
26
|
+
model 'validate', ['source', 'config-source', 'candidate'], 'leaf', 'type' => 'empty'
|
27
|
+
model 'lock', ['target', 'config-target', 'candidate'], 'leaf', 'type' => 'empty'
|
28
|
+
model 'unlock', ['target', 'config-target', 'candidate'], 'leaf', 'type' => 'empty'
|
29
|
+
model 'commit', []
|
30
|
+
model 'discard-changes', []
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# vim: et ts=2 sw=2
|
3
|
+
|
4
|
+
module HrrRbNetconf
|
5
|
+
class Server
|
6
|
+
class Capability
|
7
|
+
class ConfirmedCommit_1_0 < Capability
|
8
|
+
ID = 'urn:ietf:params:netconf:capability:confirmed-commit:1.0'
|
9
|
+
DEPENDENCIES = ['urn:ietf:params:netconf:capability:candidate:1.0']
|
10
|
+
IF_FEATURES = ['candidate', 'confirmed-commit']
|
11
|
+
|
12
|
+
oper_proc('cancel-commit'){ |session, datastore, input_e|
|
13
|
+
datastore.run 'cancel-commit', input_e
|
14
|
+
'<ok />'
|
15
|
+
}
|
16
|
+
|
17
|
+
model 'commit', ['confirmed'], 'leaf', 'type' => 'empty'
|
18
|
+
model 'commit', ['confirm-timeout'], 'leaf', 'type' => 'integer', 'range' => [1, 2**32-1], 'default' => '600'
|
19
|
+
model 'commit', ['persist'], 'leaf', 'type' => 'string'
|
20
|
+
model 'commit', ['persist-id'], 'leaf', 'type' => 'string'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# vim: et ts=2 sw=2
|
3
|
+
|
4
|
+
module HrrRbNetconf
|
5
|
+
class Server
|
6
|
+
class Capability
|
7
|
+
class ConfirmedCommit_1_1 < Capability
|
8
|
+
ID = 'urn:ietf:params:netconf:capability:confirmed-commit:1.1'
|
9
|
+
DEPENDENCIES = ['urn:ietf:params:netconf:capability:candidate:1.0']
|
10
|
+
IF_FEATURES = ['candidate', 'confirmed-commit']
|
11
|
+
|
12
|
+
oper_proc('cancel-commit'){ |session, datastore, input_e|
|
13
|
+
datastore.run 'cancel-commit', input_e
|
14
|
+
'<ok />'
|
15
|
+
}
|
16
|
+
|
17
|
+
model 'commit', ['confirmed'], 'leaf', 'type' => 'empty'
|
18
|
+
model 'commit', ['confirm-timeout'], 'leaf', 'type' => 'integer', 'range' => [1, 2**32-1], 'default' => '600'
|
19
|
+
model 'commit', ['persist'], 'leaf', 'type' => 'string'
|
20
|
+
model 'commit', ['persist-id'], 'leaf', 'type' => 'string'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# vim: et ts=2 sw=2
|
3
|
+
|
4
|
+
module HrrRbNetconf
|
5
|
+
class Server
|
6
|
+
class Capability
|
7
|
+
class RollbackOnError_1_0 < Capability
|
8
|
+
ID = 'urn:ietf:params:netconf:capability:rollback-on-error:1.0'
|
9
|
+
DEPENDENCIES = []
|
10
|
+
IF_FEATURES = ['rollback-on-error']
|
11
|
+
|
12
|
+
model 'edit-config', ['error-option'], 'leaf', 'type' => 'enumeration', 'enum' => ['stop-on-error', 'continue-on-error', 'rollback-on-error'], 'default' => 'stop-on-error'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# vim: et ts=2 sw=2
|
3
|
+
|
4
|
+
module HrrRbNetconf
|
5
|
+
class Server
|
6
|
+
class Capability
|
7
|
+
class Startup_1_0 < Capability
|
8
|
+
ID = 'urn:ietf:params:netconf:capability:startup:1.0'
|
9
|
+
DEPENDENCIES = []
|
10
|
+
IF_FEATURES = ['startup']
|
11
|
+
|
12
|
+
model 'get-config', ['source', 'config-source', 'startup'], 'leaf', 'type' => 'empty'
|
13
|
+
model 'copy-config', ['source', 'config-source', 'startup'], 'leaf', 'type' => 'empty'
|
14
|
+
model 'copy-config', ['target', 'config-target', 'startup'], 'leaf', 'type' => 'empty'
|
15
|
+
model 'lock', ['target', 'config-target', 'startup'], 'leaf', 'type' => 'empty'
|
16
|
+
model 'unlock', ['target', 'config-target', 'startup'], 'leaf', 'type' => 'empty'
|
17
|
+
model 'validate', ['source', 'config-source', 'startup'], 'leaf', 'type' => 'empty'
|
18
|
+
model 'delete-config', ['target', 'config-target', 'startup'], 'leaf', 'type' => 'empty'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# vim: et ts=2 sw=2
|
3
|
+
|
4
|
+
require 'uri'
|
5
|
+
|
6
|
+
module HrrRbNetconf
|
7
|
+
class Server
|
8
|
+
class Capability
|
9
|
+
class Url_1_0 < Capability
|
10
|
+
ID = 'urn:ietf:params:netconf:capability:url:1.0'
|
11
|
+
QUERIES = {'scheme' => ['http', 'ftp', 'file']}
|
12
|
+
DEPENDENCIES = []
|
13
|
+
IF_FEATURES = []
|
14
|
+
|
15
|
+
model 'edit-config', ['edit-content', 'url'], 'leaf', 'type' => 'string', 'validation' => proc { |cap, node| cap.queries['scheme'].any?{|s| s == URI.parse(node.text).scheme} }
|
16
|
+
model 'copy-config', ['target', 'config-target', 'url'], 'leaf', 'type' => 'string'
|
17
|
+
model 'copy-config', ['source', 'config-source', 'url'], 'leaf', 'type' => 'string'
|
18
|
+
model 'delete-config', ['target', 'config-target', 'url'], 'leaf', 'type' => 'string'
|
19
|
+
model 'validate', ['source', 'config-source', 'url'], 'leaf', 'type' => 'string'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# vim: et ts=2 sw=2
|
3
|
+
|
4
|
+
module HrrRbNetconf
|
5
|
+
class Server
|
6
|
+
class Capability
|
7
|
+
class Validate_1_0 < Capability
|
8
|
+
ID = 'urn:ietf:params:netconf:capability:validate:1.0'
|
9
|
+
DEPENDENCIES = []
|
10
|
+
IF_FEATURES = ['validate']
|
11
|
+
|
12
|
+
oper_proc('validate'){ |session, datastore, input_e|
|
13
|
+
datastore.run 'validate', input_e
|
14
|
+
'<ok />'
|
15
|
+
}
|
16
|
+
|
17
|
+
model 'edit-config', ['test-option'], 'leaf', 'type' => 'enumeration', 'enum' => ['test-then-set', 'set', 'test-only'], 'default' => 'test-then-set'
|
18
|
+
model 'validate', ['source'], 'container'
|
19
|
+
model 'validate', ['source', 'config-source'], 'choice', 'mandatory' => true
|
20
|
+
model 'validate', ['source', 'config-source', 'running'], 'leaf', 'type' => 'empty'
|
21
|
+
model 'validate', ['source', 'config-source', 'config'], 'leaf', 'type' => 'anyxml'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# vim: et ts=2 sw=2
|
3
|
+
|
4
|
+
module HrrRbNetconf
|
5
|
+
class Server
|
6
|
+
class Capability
|
7
|
+
class Validate_1_1 < Capability
|
8
|
+
ID = 'urn:ietf:params:netconf:capability:validate:1.1'
|
9
|
+
DEPENDENCIES = []
|
10
|
+
IF_FEATURES = ['validate']
|
11
|
+
|
12
|
+
oper_proc('validate'){ |session, datastore, input_e|
|
13
|
+
datastore.run 'validate', input_e
|
14
|
+
'<ok />'
|
15
|
+
}
|
16
|
+
|
17
|
+
model 'edit-config', ['test-option'], 'leaf', 'type' => 'enumeration', 'enum' => ['test-then-set', 'set', 'test-only'], 'default' => 'test-then-set'
|
18
|
+
model 'validate', ['source'], 'container'
|
19
|
+
model 'validate', ['source', 'config-source'], 'choice', 'mandatory' => true
|
20
|
+
model 'validate', ['source', 'config-source', 'running'], 'leaf', 'type' => 'empty'
|
21
|
+
model 'validate', ['source', 'config-source', 'config'], 'leaf', 'type' => 'anyxml'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|