hrr_rb_netconf 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 80d570618616c7c6db898307a743eb31cba40b7811d0b9c5dd18e6691b679a21
4
- data.tar.gz: 2eb821c7bafcf5afdfbe3d866494bbd308954b59e11554f6cfe0a1cd12d27e47
3
+ metadata.gz: 0feb4042406ce9043aa1f3f535da2ffbe4136197a28800f805e43860e43755a4
4
+ data.tar.gz: 8ec823251fe7a8c26223a7bc856b83263437833bf90938e6ff065ede68be97dd
5
5
  SHA512:
6
- metadata.gz: fd4001d68726903b2d708bc494dec4e582c7383ff699e3f092d43c5284a7c5336e47e9288299b5a121ec93ba8ba1615f6766f99acaffbbd4042c8fcaad2d187b
7
- data.tar.gz: '088857bc573595df3813b9eca6baaff492f5307053d18d56b1263e0da3303fca30a9cc5e9d29451936fd2f07d92816031781842a9082755a7798c9ec7e24ff35'
6
+ metadata.gz: 5755adcd86b0cb11c12e192542a10731dbfe3a00414bc901a652bd08a23b28bb1ba39a392f95a52b8c830c9132bc87b610e2381d1e01c9ceffd6c5009f136ce5
7
+ data.tar.gz: 7d72b95b3153cb54c28cfe808e24de5351a0c9327076b1b6dd1b1a8237a4ef29a9d1e456c0c9d9f5128d6fc1aae354b6956167516015d759855baa35d774a1ca
data/.travis.yml CHANGED
@@ -11,6 +11,7 @@ rvm:
11
11
  - 2.4
12
12
  - 2.5
13
13
  - 2.6
14
+ - 2.7
14
15
  - ruby-head
15
16
  os:
16
17
  - linux
data/README.md CHANGED
@@ -207,9 +207,16 @@ The following capabilities are currently supported.
207
207
 
208
208
  Required feature: xpath
209
209
 
210
+ - urn:ietf:params:netconf:capability:notification:1.0
211
+
212
+ Required feature: notification
213
+
214
+ Required datastore operations:
215
+ - create-subscription
216
+
210
217
  ## Contributing
211
218
 
212
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/hrr_rb_netconf. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
219
+ Bug reports and pull requests are welcome on GitHub at https://github.com/hirura/hrr_rb_netconf. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
213
220
 
214
221
  ## Code of Conduct
215
222
 
@@ -22,7 +22,9 @@ Gem::Specification.new do |spec|
22
22
 
23
23
  spec.required_ruby_version = '>= 2.0.0'
24
24
 
25
- spec.add_development_dependency "rake", "~> 10.0"
25
+ spec.add_dependency "hrr_rb_relaxed_xml"
26
+
27
+ spec.add_development_dependency "rake", "~> 12.0"
26
28
  spec.add_development_dependency "rspec", "~> 3.0"
27
29
  spec.add_development_dependency "simplecov", "~> 0.16"
28
30
  end
@@ -121,7 +121,7 @@ module HrrRbNetconf
121
121
  end
122
122
  @logger.debug { "Sending message: #{buf.inspect}" }
123
123
  begin
124
- @io_w.write "#{buf}\n]]>]]>\n"
124
+ @io_w.write "#{buf}\n]]>]]>"
125
125
  rescue => e
126
126
  @logger.info { "Sender IO closed: #{e.class}: #{e.message}" }
127
127
  raise IOError, "Sender IO closed: #{e.class}: #{e.message}"
@@ -9,15 +9,8 @@ module HrrRbNetconf
9
9
  DEPENDENCIES = ['urn:ietf:params:netconf:capability:candidate:1.0']
10
10
  IF_FEATURES = ['candidate', 'confirmed-commit']
11
11
 
12
- oper_proc('cancel-commit'){ |session, datastore, input_e|
13
- datastore.run 'cancel-commit', input_e
14
- '<ok />'
15
- }
16
-
17
12
  model 'commit', ['confirmed'], 'leaf', 'type' => 'empty'
18
13
  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
14
  end
22
15
  end
23
16
  end
@@ -0,0 +1,81 @@
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 Notification_1_0 < Capability
11
+ ID = 'urn:ietf:params:netconf:capability:notification:1.0'
12
+ DEPENDENCIES = []
13
+ IF_FEATURES = ['notification']
14
+
15
+ oper_proc('create-subscription'){ |session, datastore, input_e|
16
+ logger = Logger.new HrrRbNetconf::Server::Capability::Notification_1_0
17
+ stream_e = input_e.elements['stream']
18
+ unless stream_e
19
+ logger.debug { "create-subscription doesn't have stream, so use NETCONF stream" }
20
+ stream_e = input_e.add_element('stream')
21
+ stream_e.text = 'NETCONF'
22
+ end
23
+ stream = stream_e.text
24
+ start_time_e = input_e.elements['startTime']
25
+ start_time = unless start_time_e
26
+ nil
27
+ else
28
+ DateTime.rfc3339(start_time_e.text)
29
+ end
30
+ stop_time_e = input_e.elements['stopTime']
31
+ stop_time = unless stop_time_e
32
+ nil
33
+ else
34
+ DateTime.rfc3339(stop_time_e.text)
35
+ end
36
+ if ! session.subscription_creatable? stream
37
+ logger.error { "Not available stream: #{stream}" }
38
+ raise Error['bad-element'].new('protocol', 'error', info: {'bad-element' => 'stream'})
39
+ end
40
+ if start_time.nil? && stop_time
41
+ logger.error { "startTime element doesn't exist, but stopTime does" }
42
+ raise Error['missing-element'].new('protocol', 'error', info: {'bad-element' => 'startTime'})
43
+ end
44
+ if start_time && stop_time && (start_time > stop_time)
45
+ logger.error { "stopTime is earlier than startTime" }
46
+ raise Error['bad-element'].new('protocol', 'error', info: {'bad-element' => 'stopTime'})
47
+ end
48
+ if start_time && (start_time > DateTime.now)
49
+ logger.error { "startTime is later than current time" }
50
+ raise Error['bad-element'].new('protocol', 'error', info: {'bad-element' => 'startTime'})
51
+ end
52
+ begin
53
+ events = datastore.run('create-subscription', input_e)
54
+ rescue Error
55
+ raise
56
+ rescue => e
57
+ logger.error { "Exception in datastore.run('create-subscription', input_e): #{e.message}" }
58
+ raise Error['operation-failed'].new('application', 'error')
59
+ end
60
+ begin
61
+ if start_time
62
+ session.notification_replay stream, start_time, stop_time, events
63
+ end
64
+ rescue Error
65
+ raise
66
+ rescue => e
67
+ logger.error { "Exception in session.notification_replay: #{e.message}" }
68
+ raise Error['operation-failed'].new('protocol', 'error')
69
+ end
70
+ session.create_subscription stream, start_time, stop_time
71
+ '<ok />'
72
+ }
73
+
74
+ model 'create-subscription', ['stream'], 'leaf', 'type' => 'string'
75
+ model 'create-subscription', ['filter'], 'leaf', 'type' => 'anyxml'
76
+ model 'create-subscription', ['startTime'], 'leaf', 'type' => 'string'
77
+ model 'create-subscription', ['stopTime'], 'leaf', 'type' => 'string'
78
+ end
79
+ end
80
+ end
81
+ end
@@ -14,7 +14,6 @@ module HrrRbNetconf
14
14
  '<ok />'
15
15
  }
16
16
 
17
- model 'edit-config', ['test-option'], 'leaf', 'type' => 'enumeration', 'enum' => ['test-then-set', 'set', 'test-only'], 'default' => 'test-then-set'
18
17
  model 'validate', ['source'], 'container'
19
18
  model 'validate', ['source', 'config-source'], 'choice', 'mandatory' => true
20
19
  model 'validate', ['source', 'config-source', 'running'], 'leaf', 'type' => 'empty'
@@ -204,3 +204,4 @@ require 'hrr_rb_netconf/server/capability/validate_1_0'
204
204
  require 'hrr_rb_netconf/server/capability/validate_1_1'
205
205
  require 'hrr_rb_netconf/server/capability/url_1_0'
206
206
  require 'hrr_rb_netconf/server/capability/xpath_1_0'
207
+ require 'hrr_rb_netconf/server/capability/notification_1_0'
@@ -0,0 +1,47 @@
1
+ # coding: utf-8
2
+ # vim: et ts=2 sw=2
3
+
4
+ require 'hrr_rb_relaxed_xml'
5
+ require 'hrr_rb_netconf/logger'
6
+
7
+ module HrrRbNetconf
8
+ class Server
9
+ class NotificationEvent
10
+ def initialize arg1, arg2=nil
11
+ unless arg2
12
+ @event_xml = case arg1
13
+ when HrrRbRelaxedXML::Document
14
+ arg1
15
+ else
16
+ HrrRbRelaxedXML::Document.new(arg2, {:ignore_whitespace_nodes => :all})
17
+ end
18
+ event_time = @event_xml.elements['eventTime'].text
19
+ @event_xml.elements['eventTime'].text = DateTime.parse(event_time).rfc3339
20
+ else
21
+ event_time_e = REXML::Element.new('eventTime')
22
+ event_time_e.text = case arg1
23
+ when REXML::Element
24
+ DateTime.parse(arg1.text).rfc3339
25
+ else
26
+ DateTime.parse(arg1.to_s).rfc3339
27
+ end
28
+ event_e = case arg2
29
+ when REXML::Document
30
+ arg2.root.deep_clone
31
+ when REXML::Element
32
+ arg2.deep_clone
33
+ else
34
+ REXML::Document.new(arg2, {:ignore_whitespace_nodes => :all}).root
35
+ end
36
+ @event_xml = HrrRbRelaxedXML::Document.new
37
+ @event_xml.add event_time_e
38
+ @event_xml.add event_e
39
+ end
40
+ end
41
+
42
+ def to_xml
43
+ @event_xml
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ # vim: et ts=2 sw=2
3
+
4
+ module HrrRbNetconf
5
+ class Server
6
+ class NotificationStream
7
+ attr_reader :blk
8
+
9
+ def initialize blk, replay_support
10
+ @blk = blk
11
+ @replay_support = replay_support
12
+ end
13
+
14
+ def match? event_xml
15
+ if @blk.call(event_xml)
16
+ true
17
+ else
18
+ false
19
+ end
20
+ end
21
+
22
+ def support_replay?
23
+ @replay_support
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,40 @@
1
+ # coding: utf-8
2
+ # vim: et ts=2 sw=2
3
+
4
+ require 'hrr_rb_netconf/logger'
5
+ require 'hrr_rb_netconf/server/notification_stream'
6
+
7
+ module HrrRbNetconf
8
+ class Server
9
+ class NotificationStreams
10
+ def initialize
11
+ @streams = Hash.new
12
+ @streams['NETCONF'] = NotificationStream.new(Proc.new { true }, false)
13
+ end
14
+
15
+ def has_stream? stream
16
+ @streams.has_key? stream
17
+ end
18
+
19
+ def stream_support_replay? stream
20
+ @streams[stream].support_replay?
21
+ end
22
+
23
+ def update stream, blk, replay_support
24
+ if blk.nil? && (! @streams.has_key?( stream ))
25
+ raise ArgumentError, "Requires block for new stream: #{stream}"
26
+ end
27
+ blk ||= @streams[stream].blk
28
+ @streams[stream] = NotificationStream.new(blk, replay_support)
29
+ end
30
+
31
+ def matched_streams event_xml
32
+ @streams.select{ |k, v| v.match? event_xml }.keys
33
+ end
34
+
35
+ def event_match_stream? event_xml, stream
36
+ @streams[stream].match? event_xml
37
+ end
38
+ end
39
+ end
40
+ end
@@ -1,7 +1,12 @@
1
1
  # coding: utf-8
2
2
  # vim: et ts=2 sw=2
3
3
 
4
+ require 'time'
5
+ require 'date'
6
+ require 'thread'
7
+ require 'monitor'
4
8
  require 'rexml/document'
9
+ require 'hrr_rb_relaxed_xml'
5
10
  require 'hrr_rb_netconf/logger'
6
11
  require 'hrr_rb_netconf/server/capability'
7
12
  require 'hrr_rb_netconf/server/operation'
@@ -28,6 +33,12 @@ module HrrRbNetconf
28
33
  end
29
34
  @strict_capabilities = strict_capabilities
30
35
  @closed = false
36
+ @notification_enabled = false
37
+ @monitor = Monitor.new
38
+ @subscribed_streams = Hash.new
39
+ @subscribed_streams_stop_time = Hash.new
40
+ @notification_replay_thread = nil
41
+ @subscription_termination_thread = nil
31
42
  end
32
43
 
33
44
  def start
@@ -46,10 +57,10 @@ module HrrRbNetconf
46
57
  def close
47
58
  @logger.info { "Being closed" }
48
59
  @closed = true
49
- begin
50
- @io_r.close_read
51
- rescue
52
- end
60
+ @io_r.close_read rescue nil
61
+ @notification_replay_thread.exit if @notification_replay_thread rescue nil
62
+ @notification_termination_thread.exit if @notification_termination_thread rescue nil
63
+ @logger.info { "Closed" }
53
64
  end
54
65
 
55
66
  def closed?
@@ -79,7 +90,7 @@ module HrrRbNetconf
79
90
  formatter.compact = true
80
91
  formatter.write(xml_doc, buf)
81
92
  @logger.debug { "Sending hello message: #{buf.inspect}" }
82
- @io_w.write "#{buf}\n]]>]]>\n"
93
+ @io_w.write "#{buf}\n]]>]]>"
83
94
  end
84
95
 
85
96
  def receive_hello
@@ -118,45 +129,40 @@ module HrrRbNetconf
118
129
 
119
130
  begin
120
131
  loop do
121
- if closed?
122
- break
123
- end
124
-
132
+ break if closed?
125
133
  begin
134
+ received_message = @receiver.receive_message
135
+ break unless received_message
136
+ rescue Error => e
137
+ rpc_reply_e = REXML::Element.new("rpc-reply")
138
+ rpc_reply_e.add_namespace("urn:ietf:params:xml:ns:netconf:base:1.0")
139
+ rpc_reply_e.add e.to_rpc_error
140
+ rescue => e
141
+ @logger.error { e.message }
142
+ raise
143
+ end
144
+ @monitor.synchronize do
126
145
  begin
127
- received_message = @receiver.receive_message
128
- break unless received_message
129
146
  rpc_reply_e = operation.run received_message
130
147
  rescue Error => e
131
- if received_message
132
- rpc_reply_e = received_message.clone
133
- rpc_reply_e.name = "rpc-reply"
134
- else
135
- rpc_reply_e = REXML::Element.new("rpc-reply")
136
- rpc_reply_e.add_namespace("urn:ietf:params:xml:ns:netconf:base:1.0")
137
- end
148
+ rpc_reply_e = received_message.clone
149
+ rpc_reply_e.name = "rpc-reply"
138
150
  rpc_reply_e.add e.to_rpc_error
151
+ rescue => e
152
+ @logger.error { e.message }
153
+ raise
154
+ ensure
155
+ begin
156
+ @sender.send_message rpc_reply_e if rpc_reply_e
157
+ rescue IOError
158
+ break
159
+ end
139
160
  end
140
-
141
- begin
142
- @sender.send_message rpc_reply_e
143
- rescue IOError
144
- break
145
- end
146
- rescue => e
147
- @logger.error { e.message }
148
- raise
149
161
  end
150
162
  end
151
163
  ensure
152
- begin
153
- datastore_session.close
154
- rescue
155
- end
156
- begin
157
- @io_w.close_write
158
- rescue
159
- end
164
+ datastore_session.close rescue nil
165
+ @io_w.close_write rescue nil
160
166
  end
161
167
  @logger.info { "Exit operation_loop" }
162
168
  end
@@ -172,6 +178,144 @@ module HrrRbNetconf
172
178
  def unlock target
173
179
  @server.unlock target, @session_id
174
180
  end
181
+
182
+ def subscription_creatable? stream
183
+ @logger.info { "Check subscription for stream: #{stream}" }
184
+ if ! @server.has_notification_stream? stream
185
+ @logger.error { "Server doesn't have notification stream: #{stream}" }
186
+ false
187
+ elsif @subscribed_streams.has_key? stream
188
+ @logger.error { "Session already has subscription for stream: #{stream}" }
189
+ false
190
+ else
191
+ @logger.info { "Subscription creatable for stream: #{stream}" }
192
+ true
193
+ end
194
+ end
195
+
196
+ def create_subscription stream, start_time, stop_time
197
+ @logger.info { "Create subscription for stream: #{stream}" }
198
+ @subscribed_streams[stream] = true
199
+ start_notification_termination_thread stream, start_time, stop_time if stop_time
200
+ @logger.info { "Create subscription done for stream: #{stream}" }
201
+ end
202
+
203
+ def terminate_subscription stream
204
+ @logger.info { "Terminate subscription for stream: #{stream}" }
205
+ @subscribed_streams.delete stream
206
+ @logger.info { "Terminate subscription done for stream: #{stream}" }
207
+ end
208
+
209
+ def notification_replay stream, start_time, stop_time, events
210
+ if @server.notification_stream_support_replay? stream
211
+ start_notification_replay_thread stream, start_time, stop_time, events
212
+ else
213
+ @logger.error { "Notification replay is not supported by stream: #{stream}" }
214
+ raise Error['operation-failed'].new('protocol', 'error')
215
+ end
216
+ end
217
+
218
+ def stream_subscribed? stream
219
+ @subscribed_streams.has_key? stream
220
+ end
221
+
222
+ def start_notification_replay_thread stream, start_time, stop_time, events
223
+ @notification_replay_thread = Thread.new do
224
+ @logger.info { "Notification replay start for stream: #{stream}" }
225
+ begin
226
+ @monitor.synchronize do
227
+ unless events.respond_to? :each
228
+ @logger.error { "Argument `events' doesn't respond to :each method: #{events}" }
229
+ else
230
+ begin
231
+ events.each{ |arg1, arg2|
232
+ event_xml = NotificationEvent.new(arg1, arg2).to_xml
233
+ if @server.event_match_stream? event_xml, stream
234
+ if start_time
235
+ event_time = DateTime.rfc3339(event_xml.elements['eventTime'].text)
236
+ if start_time < event_time
237
+ if stop_time.nil? || event_time < stop_time
238
+ send_notification event_xml
239
+ end
240
+ end
241
+ end
242
+ end
243
+ }
244
+ rescue => e
245
+ @logger.error { "Got an exception during processing replay: #{e.message}" }
246
+ end
247
+ end
248
+ send_replay_complete stream
249
+ end
250
+ ensure
251
+ @logger.info { "Notification replay completed for stream: #{stream}" }
252
+ end
253
+ end
254
+ end
255
+
256
+ def start_notification_termination_thread stream, start_time, stop_time
257
+ @notification_termination_thread = Thread.new do
258
+ @logger.info { "Notification termination thread start for stream: #{stream}" }
259
+ begin
260
+ loop do
261
+ now = DateTime.now
262
+ if now.to_time < stop_time.to_time
263
+ sleep_time = ((stop_time.to_time - now.to_time) / 2.0).ceil
264
+ @logger.debug { "Notification termination thread for stream: #{stream}: sleep [sec]: #{sleep_time}" }
265
+ sleep sleep_time
266
+ else
267
+ @logger.info { "Notification termination thread terminates subscription for stream: #{stream}" }
268
+ @monitor.synchronize do
269
+ terminate_subscription stream
270
+ send_notification_complete stream
271
+ end
272
+ break
273
+ end
274
+ end
275
+ ensure
276
+ @logger.info { "Notification termination completed for stream: #{stream}" }
277
+ end
278
+ end
279
+ end
280
+
281
+ def send_notification event_e
282
+ @monitor.synchronize do
283
+ notif_e = REXML::Element.new("notification")
284
+ notif_e.add_namespace("urn:ietf:params:xml:ns:netconf:notification:1.0")
285
+ event_e.elements.each{ |e|
286
+ notif_e.add e.deep_clone
287
+ }
288
+ begin
289
+ @sender.send_message notif_e
290
+ rescue IOError => e
291
+ @logger.warn { "Failed sending notification: #{e.message}" }
292
+ end
293
+ end
294
+ end
295
+
296
+ def filter_and_send_notification matched_streams, event_xml
297
+ unless (matched_streams & @subscribed_streams.keys).empty?
298
+ #event_e = filter(event_xml)
299
+ event_e = event_xml
300
+ send_notification event_e
301
+ end
302
+ end
303
+
304
+ def send_replay_complete stream
305
+ event_xml = HrrRbRelaxedXML::Document.new
306
+ event_time_e = event_xml.add_element('eventTime')
307
+ event_time_e.text = DateTime.now.rfc3339
308
+ event_e = event_xml.add_element("replayComplete")
309
+ send_notification event_xml
310
+ end
311
+
312
+ def send_notification_complete stream
313
+ event_xml = HrrRbRelaxedXML::Document.new
314
+ event_time_e = event_xml.add_element('eventTime')
315
+ event_time_e.text = DateTime.now.rfc3339
316
+ event_e = event_xml.add_element("notificationComplete")
317
+ send_notification event_xml
318
+ end
175
319
  end
176
320
  end
177
321
  end
@@ -1,13 +1,17 @@
1
1
  # coding: utf-8
2
2
  # vim: et ts=2 sw=2
3
3
 
4
+ require 'date'
4
5
  require 'thread'
6
+ require 'hrr_rb_relaxed_xml'
5
7
  require 'hrr_rb_netconf/logger'
6
8
  require 'hrr_rb_netconf/server/error'
7
9
  require 'hrr_rb_netconf/server/errors'
8
10
  require 'hrr_rb_netconf/server/datastore'
9
11
  require 'hrr_rb_netconf/server/capabilities'
10
12
  require 'hrr_rb_netconf/server/session'
13
+ require 'hrr_rb_netconf/server/notification_event'
14
+ require 'hrr_rb_netconf/server/notification_streams'
11
15
 
12
16
  module HrrRbNetconf
13
17
  class Server
@@ -26,6 +30,7 @@ module HrrRbNetconf
26
30
  @locks = Hash.new
27
31
  @lock_mutex = Mutex.new
28
32
  @last_session_id = SESSION_ID_MIN - 1
33
+ @notification_streams = NotificationStreams.new
29
34
  end
30
35
 
31
36
  def allocate_session_id
@@ -44,7 +49,7 @@ module HrrRbNetconf
44
49
  end
45
50
 
46
51
  def start_session io
47
- @logger.info { "Starting session" }
52
+ @logger.info { "Start session" }
48
53
  session_id = SESSION_ID_UNALLOCATED
49
54
  begin
50
55
  @mutex.synchronize do
@@ -52,11 +57,7 @@ module HrrRbNetconf
52
57
  @logger.info { "Session ID: #{session_id}" }
53
58
  @sessions[session_id] = Session.new self, @capabilities, @datastore, session_id, io, @strict_capabilities
54
59
  end
55
- t = Thread.new {
56
- @sessions[session_id].start
57
- }
58
- @logger.info { "Session started: Session ID: #{session_id}" }
59
- t.join
60
+ @sessions[session_id].start
60
61
  rescue => e
61
62
  @logger.error { "Session terminated: Session ID: #{session_id}" }
62
63
  raise
@@ -105,5 +106,32 @@ module HrrRbNetconf
105
106
  end
106
107
  end
107
108
  end
109
+
110
+ def notification_stream stream, replay_support: false, &blk
111
+ @notification_streams.update stream, blk, replay_support
112
+ end
113
+
114
+ def has_notification_stream? stream
115
+ @notification_streams.has_stream? stream
116
+ end
117
+
118
+ def notification_stream_support_replay? stream
119
+ @notification_streams.stream_support_replay? stream
120
+ end
121
+
122
+ def event_match_stream? event_xml, stream
123
+ @notification_streams.event_match_stream? event_xml, stream
124
+ end
125
+
126
+ def send_notification arg1, arg2=nil
127
+ event_xml = NotificationEvent.new(arg1, arg2).to_xml
128
+ matched_streams = @notification_streams.matched_streams event_xml
129
+ @logger.info { "Send notification" }
130
+ @logger.debug { "Event time: #{event_xml.elements['eventTime'].text}, Event: #{event_xml.elements.to_a}" }
131
+ @sessions.each{ |session_id, session|
132
+ session.filter_and_send_notification matched_streams, event_xml
133
+ }
134
+ @logger.info { "Send notification done" }
135
+ end
108
136
  end
109
137
  end
@@ -2,5 +2,5 @@
2
2
  # vim: et ts=2 sw=2
3
3
 
4
4
  module HrrRbNetconf
5
- VERSION = "0.1.0"
5
+ VERSION = "0.1.1"
6
6
  end
metadata CHANGED
@@ -1,29 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hrr_rb_netconf
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - hirura
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-06-01 00:00:00.000000000 Z
11
+ date: 2020-01-09 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: hrr_rb_relaxed_xml
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: rake
15
29
  requirement: !ruby/object:Gem::Requirement
16
30
  requirements:
17
31
  - - "~>"
18
32
  - !ruby/object:Gem::Version
19
- version: '10.0'
33
+ version: '12.0'
20
34
  type: :development
21
35
  prerelease: false
22
36
  version_requirements: !ruby/object:Gem::Requirement
23
37
  requirements:
24
38
  - - "~>"
25
39
  - !ruby/object:Gem::Version
26
- version: '10.0'
40
+ version: '12.0'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: rspec
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -82,6 +96,7 @@ files:
82
96
  - lib/hrr_rb_netconf/server/capability/candidate_1_0.rb
83
97
  - lib/hrr_rb_netconf/server/capability/confirmed_commit_1_0.rb
84
98
  - lib/hrr_rb_netconf/server/capability/confirmed_commit_1_1.rb
99
+ - lib/hrr_rb_netconf/server/capability/notification_1_0.rb
85
100
  - lib/hrr_rb_netconf/server/capability/rollback_on_error_1_0.rb
86
101
  - lib/hrr_rb_netconf/server/capability/startup_1_0.rb
87
102
  - lib/hrr_rb_netconf/server/capability/url_1_0.rb
@@ -120,6 +135,9 @@ files:
120
135
  - lib/hrr_rb_netconf/server/filter/xpath.rb
121
136
  - lib/hrr_rb_netconf/server/model.rb
122
137
  - lib/hrr_rb_netconf/server/model/node.rb
138
+ - lib/hrr_rb_netconf/server/notification_event.rb
139
+ - lib/hrr_rb_netconf/server/notification_stream.rb
140
+ - lib/hrr_rb_netconf/server/notification_streams.rb
123
141
  - lib/hrr_rb_netconf/server/operation.rb
124
142
  - lib/hrr_rb_netconf/server/session.rb
125
143
  - lib/hrr_rb_netconf/version.rb
@@ -142,7 +160,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
142
160
  - !ruby/object:Gem::Version
143
161
  version: '0'
144
162
  requirements: []
145
- rubygems_version: 3.0.3
163
+ rubygems_version: 3.1.2
146
164
  signing_key:
147
165
  specification_version: 4
148
166
  summary: Pure Ruby NETCONF server implementation