hrr_rb_netconf 0.1.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 (66) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +28 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +32 -0
  5. data/CODE_OF_CONDUCT.md +74 -0
  6. data/Gemfile +6 -0
  7. data/LICENSE +201 -0
  8. data/README.md +220 -0
  9. data/Rakefile +6 -0
  10. data/demo/server.rb +54 -0
  11. data/demo/server_over_ssh.rb +97 -0
  12. data/demo/server_with_session-oriented-database.rb +134 -0
  13. data/demo/server_with_sessionless-database.rb +81 -0
  14. data/hrr_rb_netconf.gemspec +28 -0
  15. data/lib/hrr_rb_netconf.rb +10 -0
  16. data/lib/hrr_rb_netconf/logger.rb +56 -0
  17. data/lib/hrr_rb_netconf/server.rb +109 -0
  18. data/lib/hrr_rb_netconf/server/capabilities.rb +75 -0
  19. data/lib/hrr_rb_netconf/server/capability.rb +206 -0
  20. data/lib/hrr_rb_netconf/server/capability/base_1_0.rb +183 -0
  21. data/lib/hrr_rb_netconf/server/capability/base_1_1.rb +247 -0
  22. data/lib/hrr_rb_netconf/server/capability/candidate_1_0.rb +34 -0
  23. data/lib/hrr_rb_netconf/server/capability/confirmed_commit_1_0.rb +24 -0
  24. data/lib/hrr_rb_netconf/server/capability/confirmed_commit_1_1.rb +24 -0
  25. data/lib/hrr_rb_netconf/server/capability/rollback_on_error_1_0.rb +16 -0
  26. data/lib/hrr_rb_netconf/server/capability/startup_1_0.rb +22 -0
  27. data/lib/hrr_rb_netconf/server/capability/url_1_0.rb +23 -0
  28. data/lib/hrr_rb_netconf/server/capability/validate_1_0.rb +25 -0
  29. data/lib/hrr_rb_netconf/server/capability/validate_1_1.rb +25 -0
  30. data/lib/hrr_rb_netconf/server/capability/writable_running_1_0.rb +17 -0
  31. data/lib/hrr_rb_netconf/server/capability/xpath_1_0.rb +14 -0
  32. data/lib/hrr_rb_netconf/server/datastore.rb +30 -0
  33. data/lib/hrr_rb_netconf/server/datastore/oper_handler.rb +29 -0
  34. data/lib/hrr_rb_netconf/server/datastore/session.rb +52 -0
  35. data/lib/hrr_rb_netconf/server/error.rb +52 -0
  36. data/lib/hrr_rb_netconf/server/error/access_denied.rb +19 -0
  37. data/lib/hrr_rb_netconf/server/error/bad_attribute.rb +20 -0
  38. data/lib/hrr_rb_netconf/server/error/bad_element.rb +20 -0
  39. data/lib/hrr_rb_netconf/server/error/data_exists.rb +19 -0
  40. data/lib/hrr_rb_netconf/server/error/data_missing.rb +19 -0
  41. data/lib/hrr_rb_netconf/server/error/in_use.rb +19 -0
  42. data/lib/hrr_rb_netconf/server/error/invalid_value.rb +19 -0
  43. data/lib/hrr_rb_netconf/server/error/lock_denied.rb +19 -0
  44. data/lib/hrr_rb_netconf/server/error/malformed_message.rb +19 -0
  45. data/lib/hrr_rb_netconf/server/error/missing_attribute.rb +19 -0
  46. data/lib/hrr_rb_netconf/server/error/missing_element.rb +19 -0
  47. data/lib/hrr_rb_netconf/server/error/operation_failed.rb +19 -0
  48. data/lib/hrr_rb_netconf/server/error/operation_not_supported.rb +19 -0
  49. data/lib/hrr_rb_netconf/server/error/partial_operation.rb +19 -0
  50. data/lib/hrr_rb_netconf/server/error/resource_denied.rb +19 -0
  51. data/lib/hrr_rb_netconf/server/error/rollback_failed.rb +19 -0
  52. data/lib/hrr_rb_netconf/server/error/rpc_errorable.rb +138 -0
  53. data/lib/hrr_rb_netconf/server/error/too_big.rb +19 -0
  54. data/lib/hrr_rb_netconf/server/error/unknown_attribute.rb +19 -0
  55. data/lib/hrr_rb_netconf/server/error/unknown_element.rb +19 -0
  56. data/lib/hrr_rb_netconf/server/error/unknown_namespace.rb +19 -0
  57. data/lib/hrr_rb_netconf/server/errors.rb +28 -0
  58. data/lib/hrr_rb_netconf/server/filter.rb +48 -0
  59. data/lib/hrr_rb_netconf/server/filter/subtree.rb +135 -0
  60. data/lib/hrr_rb_netconf/server/filter/xpath.rb +59 -0
  61. data/lib/hrr_rb_netconf/server/model.rb +123 -0
  62. data/lib/hrr_rb_netconf/server/model/node.rb +19 -0
  63. data/lib/hrr_rb_netconf/server/operation.rb +92 -0
  64. data/lib/hrr_rb_netconf/server/session.rb +177 -0
  65. data/lib/hrr_rb_netconf/version.rb +6 -0
  66. 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