hrr_rb_netconf 0.1.1 → 0.2.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 (34) hide show
  1. checksums.yaml +4 -4
  2. data/demo/server.rb +2 -3
  3. data/demo/server_over_ssh.rb +4 -6
  4. data/demo/server_with_session-oriented-database.rb +4 -6
  5. data/demo/server_with_sessionless-database.rb +2 -4
  6. data/lib/hrr_rb_netconf/loggable.rb +42 -0
  7. data/lib/hrr_rb_netconf/server/capabilities.rb +8 -4
  8. data/lib/hrr_rb_netconf/server/capability/base_1_0.rb +97 -91
  9. data/lib/hrr_rb_netconf/server/capability/base_1_1.rb +109 -103
  10. data/lib/hrr_rb_netconf/server/capability/candidate_1_0.rb +19 -17
  11. data/lib/hrr_rb_netconf/server/capability/confirmed_commit_1_0.rb +4 -2
  12. data/lib/hrr_rb_netconf/server/capability/confirmed_commit_1_1.rb +10 -8
  13. data/lib/hrr_rb_netconf/server/capability/notification_1_0.rb +62 -62
  14. data/lib/hrr_rb_netconf/server/capability/rollback_on_error_1_0.rb +3 -1
  15. data/lib/hrr_rb_netconf/server/capability/startup_1_0.rb +9 -7
  16. data/lib/hrr_rb_netconf/server/capability/url_1_0.rb +7 -5
  17. data/lib/hrr_rb_netconf/server/capability/validate_1_0.rb +10 -8
  18. data/lib/hrr_rb_netconf/server/capability/validate_1_1.rb +11 -9
  19. data/lib/hrr_rb_netconf/server/capability/writable_running_1_0.rb +4 -2
  20. data/lib/hrr_rb_netconf/server/capability.rb +16 -27
  21. data/lib/hrr_rb_netconf/server/datastore/oper_handler.rb +9 -7
  22. data/lib/hrr_rb_netconf/server/datastore/session.rb +7 -5
  23. data/lib/hrr_rb_netconf/server/datastore.rb +7 -5
  24. data/lib/hrr_rb_netconf/server/error/rpc_errorable.rb +8 -5
  25. data/lib/hrr_rb_netconf/server/model.rb +9 -5
  26. data/lib/hrr_rb_netconf/server/notification_event.rb +0 -1
  27. data/lib/hrr_rb_netconf/server/notification_streams.rb +0 -1
  28. data/lib/hrr_rb_netconf/server/operation.rb +12 -10
  29. data/lib/hrr_rb_netconf/server/session.rb +39 -37
  30. data/lib/hrr_rb_netconf/server.rb +24 -22
  31. data/lib/hrr_rb_netconf/version.rb +1 -1
  32. data/lib/hrr_rb_netconf.rb +0 -1
  33. metadata +3 -3
  34. data/lib/hrr_rb_netconf/logger.rb +0 -56
@@ -7,17 +7,19 @@ require 'thread'
7
7
  require 'monitor'
8
8
  require 'rexml/document'
9
9
  require 'hrr_rb_relaxed_xml'
10
- require 'hrr_rb_netconf/logger'
10
+ require 'hrr_rb_netconf/loggable'
11
11
  require 'hrr_rb_netconf/server/capability'
12
12
  require 'hrr_rb_netconf/server/operation'
13
13
 
14
14
  module HrrRbNetconf
15
15
  class Server
16
16
  class Session
17
+ include Loggable
18
+
17
19
  attr_reader :session_id
18
20
 
19
- def initialize server, capabilities, datastore, session_id, io, strict_capabilities
20
- @logger = Logger.new self.class.name
21
+ def initialize server, capabilities, datastore, session_id, io, strict_capabilities, logger: nil
22
+ self.logger = logger
21
23
  @server = server
22
24
  @local_capabilities = capabilities
23
25
  @remote_capabilities = Array.new
@@ -55,12 +57,12 @@ module HrrRbNetconf
55
57
  end
56
58
 
57
59
  def close
58
- @logger.info { "Being closed" }
60
+ log_info { "Being closed" }
59
61
  @closed = true
60
62
  @io_r.close_read rescue nil
61
63
  @notification_replay_thread.exit if @notification_replay_thread rescue nil
62
64
  @notification_termination_thread.exit if @notification_termination_thread rescue nil
63
- @logger.info { "Closed" }
65
+ log_info { "Closed" }
64
66
  end
65
67
 
66
68
  def closed?
@@ -73,7 +75,7 @@ module HrrRbNetconf
73
75
  end
74
76
 
75
77
  def send_hello
76
- @logger.info { "Local capabilities: #{@local_capabilities}" }
78
+ log_info { "Local capabilities: #{@local_capabilities}" }
77
79
  xml_doc = REXML::Document.new
78
80
  hello_e = xml_doc.add_element 'hello'
79
81
  hello_e.add_namespace('urn:ietf:params:xml:ns:netconf:base:1.0')
@@ -89,7 +91,7 @@ module HrrRbNetconf
89
91
  formatter = REXML::Formatters::Pretty.new(2)
90
92
  formatter.compact = true
91
93
  formatter.write(xml_doc, buf)
92
- @logger.debug { "Sending hello message: #{buf.inspect}" }
94
+ log_debug { "Sending hello message: #{buf.inspect}" }
93
95
  @io_w.write "#{buf}\n]]>]]>"
94
96
  end
95
97
 
@@ -101,31 +103,31 @@ module HrrRbNetconf
101
103
  break
102
104
  end
103
105
  end
104
- @logger.debug { "Received hello message: #{buf[0..-7].inspect}" }
106
+ log_debug { "Received hello message: #{buf[0..-7].inspect}" }
105
107
  remote_capabilities_xml_doc = REXML::Document.new(buf[0..-7], {:ignore_whitespace_nodes => :all})
106
108
  remote_capabilities_xml_doc.each_element('/hello/capabilities/capability'){ |c| @remote_capabilities.push c.text }
107
- @logger.info { "Remote capabilities: #{@remote_capabilities}" }
109
+ log_info { "Remote capabilities: #{@remote_capabilities}" }
108
110
  end
109
111
 
110
112
  def negotiate_capabilities
111
113
  @capabilities = @local_capabilities.negotiate @remote_capabilities
112
- @logger.info { "Negotiated capabilities: #{@capabilities.list_loadable}" }
114
+ log_info { "Negotiated capabilities: #{@capabilities.list_loadable}" }
113
115
  unless @capabilities.list_loadable.any?{ |c| /^urn:ietf:params:netconf:base:\d+\.\d+$/ =~ c }
114
- @logger.error { "No base NETCONF capability negotiated" }
116
+ log_error { "No base NETCONF capability negotiated" }
115
117
  raise "No base NETCONF capability negotiated"
116
118
  end
117
119
  end
118
120
 
119
121
  def initialize_sender_and_receiver
120
122
  base_capability = @capabilities.list_loadable.select{ |c| /^urn:ietf:params:netconf:base:\d+\.\d+$/ =~ c }.sort.last
121
- @logger.info { "Base NETCONF capability: #{base_capability}" }
122
- @sender = Capability[base_capability]::Sender.new @io_w
123
- @receiver = Capability[base_capability]::Receiver.new @io_r
123
+ log_info { "Base NETCONF capability: #{base_capability}" }
124
+ @sender = Capability[base_capability]::Sender.new @io_w, logger: logger
125
+ @receiver = Capability[base_capability]::Receiver.new @io_r, logger: logger
124
126
  end
125
127
 
126
128
  def operation_loop
127
129
  datastore_session = @datastore.new_session self
128
- operation = Operation.new self, @capabilities, datastore_session, @strict_capabilities
130
+ operation = Operation.new self, @capabilities, datastore_session, @strict_capabilities, logger: logger
129
131
 
130
132
  begin
131
133
  loop do
@@ -138,7 +140,7 @@ module HrrRbNetconf
138
140
  rpc_reply_e.add_namespace("urn:ietf:params:xml:ns:netconf:base:1.0")
139
141
  rpc_reply_e.add e.to_rpc_error
140
142
  rescue => e
141
- @logger.error { e.message }
143
+ log_error { e.message }
142
144
  raise
143
145
  end
144
146
  @monitor.synchronize do
@@ -149,7 +151,7 @@ module HrrRbNetconf
149
151
  rpc_reply_e.name = "rpc-reply"
150
152
  rpc_reply_e.add e.to_rpc_error
151
153
  rescue => e
152
- @logger.error { e.message }
154
+ log_error { e.message }
153
155
  raise
154
156
  ensure
155
157
  begin
@@ -164,7 +166,7 @@ module HrrRbNetconf
164
166
  datastore_session.close rescue nil
165
167
  @io_w.close_write rescue nil
166
168
  end
167
- @logger.info { "Exit operation_loop" }
169
+ log_info { "Exit operation_loop" }
168
170
  end
169
171
 
170
172
  def close_other session_id
@@ -180,38 +182,38 @@ module HrrRbNetconf
180
182
  end
181
183
 
182
184
  def subscription_creatable? stream
183
- @logger.info { "Check subscription for stream: #{stream}" }
185
+ log_info { "Check subscription for stream: #{stream}" }
184
186
  if ! @server.has_notification_stream? stream
185
- @logger.error { "Server doesn't have notification stream: #{stream}" }
187
+ log_error { "Server doesn't have notification stream: #{stream}" }
186
188
  false
187
189
  elsif @subscribed_streams.has_key? stream
188
- @logger.error { "Session already has subscription for stream: #{stream}" }
190
+ log_error { "Session already has subscription for stream: #{stream}" }
189
191
  false
190
192
  else
191
- @logger.info { "Subscription creatable for stream: #{stream}" }
193
+ log_info { "Subscription creatable for stream: #{stream}" }
192
194
  true
193
195
  end
194
196
  end
195
197
 
196
198
  def create_subscription stream, start_time, stop_time
197
- @logger.info { "Create subscription for stream: #{stream}" }
199
+ log_info { "Create subscription for stream: #{stream}" }
198
200
  @subscribed_streams[stream] = true
199
201
  start_notification_termination_thread stream, start_time, stop_time if stop_time
200
- @logger.info { "Create subscription done for stream: #{stream}" }
202
+ log_info { "Create subscription done for stream: #{stream}" }
201
203
  end
202
204
 
203
205
  def terminate_subscription stream
204
- @logger.info { "Terminate subscription for stream: #{stream}" }
206
+ log_info { "Terminate subscription for stream: #{stream}" }
205
207
  @subscribed_streams.delete stream
206
- @logger.info { "Terminate subscription done for stream: #{stream}" }
208
+ log_info { "Terminate subscription done for stream: #{stream}" }
207
209
  end
208
210
 
209
211
  def notification_replay stream, start_time, stop_time, events
210
212
  if @server.notification_stream_support_replay? stream
211
213
  start_notification_replay_thread stream, start_time, stop_time, events
212
214
  else
213
- @logger.error { "Notification replay is not supported by stream: #{stream}" }
214
- raise Error['operation-failed'].new('protocol', 'error')
215
+ log_error { "Notification replay is not supported by stream: #{stream}" }
216
+ raise Error['operation-failed'].new('protocol', 'error', logger: logger)
215
217
  end
216
218
  end
217
219
 
@@ -221,11 +223,11 @@ module HrrRbNetconf
221
223
 
222
224
  def start_notification_replay_thread stream, start_time, stop_time, events
223
225
  @notification_replay_thread = Thread.new do
224
- @logger.info { "Notification replay start for stream: #{stream}" }
226
+ log_info { "Notification replay start for stream: #{stream}" }
225
227
  begin
226
228
  @monitor.synchronize do
227
229
  unless events.respond_to? :each
228
- @logger.error { "Argument `events' doesn't respond to :each method: #{events}" }
230
+ log_error { "Argument `events' doesn't respond to :each method: #{events}" }
229
231
  else
230
232
  begin
231
233
  events.each{ |arg1, arg2|
@@ -242,29 +244,29 @@ module HrrRbNetconf
242
244
  end
243
245
  }
244
246
  rescue => e
245
- @logger.error { "Got an exception during processing replay: #{e.message}" }
247
+ log_error { "Got an exception during processing replay: #{e.message}" }
246
248
  end
247
249
  end
248
250
  send_replay_complete stream
249
251
  end
250
252
  ensure
251
- @logger.info { "Notification replay completed for stream: #{stream}" }
253
+ log_info { "Notification replay completed for stream: #{stream}" }
252
254
  end
253
255
  end
254
256
  end
255
257
 
256
258
  def start_notification_termination_thread stream, start_time, stop_time
257
259
  @notification_termination_thread = Thread.new do
258
- @logger.info { "Notification termination thread start for stream: #{stream}" }
260
+ log_info { "Notification termination thread start for stream: #{stream}" }
259
261
  begin
260
262
  loop do
261
263
  now = DateTime.now
262
264
  if now.to_time < stop_time.to_time
263
265
  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}" }
266
+ log_debug { "Notification termination thread for stream: #{stream}: sleep [sec]: #{sleep_time}" }
265
267
  sleep sleep_time
266
268
  else
267
- @logger.info { "Notification termination thread terminates subscription for stream: #{stream}" }
269
+ log_info { "Notification termination thread terminates subscription for stream: #{stream}" }
268
270
  @monitor.synchronize do
269
271
  terminate_subscription stream
270
272
  send_notification_complete stream
@@ -273,7 +275,7 @@ module HrrRbNetconf
273
275
  end
274
276
  end
275
277
  ensure
276
- @logger.info { "Notification termination completed for stream: #{stream}" }
278
+ log_info { "Notification termination completed for stream: #{stream}" }
277
279
  end
278
280
  end
279
281
  end
@@ -288,7 +290,7 @@ module HrrRbNetconf
288
290
  begin
289
291
  @sender.send_message notif_e
290
292
  rescue IOError => e
291
- @logger.warn { "Failed sending notification: #{e.message}" }
293
+ log_warn { "Failed sending notification: #{e.message}" }
292
294
  end
293
295
  end
294
296
  end
@@ -4,7 +4,7 @@
4
4
  require 'date'
5
5
  require 'thread'
6
6
  require 'hrr_rb_relaxed_xml'
7
- require 'hrr_rb_netconf/logger'
7
+ require 'hrr_rb_netconf/loggable'
8
8
  require 'hrr_rb_netconf/server/error'
9
9
  require 'hrr_rb_netconf/server/errors'
10
10
  require 'hrr_rb_netconf/server/datastore'
@@ -15,15 +15,17 @@ require 'hrr_rb_netconf/server/notification_streams'
15
15
 
16
16
  module HrrRbNetconf
17
17
  class Server
18
+ include Loggable
19
+
18
20
  SESSION_ID_UNALLOCATED = "UNALLOCATED"
19
21
  SESSION_ID_MIN = 1
20
22
  SESSION_ID_MAX = 2**32 - 1
21
23
  SESSION_ID_MODULO = SESSION_ID_MAX - SESSION_ID_MIN + 1
22
24
 
23
- def initialize datastore, capabilities: nil, strict_capabilities: false
24
- @logger = Logger.new self.class.name
25
+ def initialize datastore, capabilities: nil, strict_capabilities: false, logger: nil
26
+ self.logger = logger
25
27
  @datastore = datastore
26
- @capabilities = capabilities || Capabilities.new
28
+ @capabilities = capabilities || Capabilities.new(logger: logger)
27
29
  @strict_capabilities = strict_capabilities
28
30
  @mutex = Mutex.new
29
31
  @sessions = Hash.new
@@ -36,7 +38,7 @@ module HrrRbNetconf
36
38
  def allocate_session_id
37
39
  session_id = (SESSION_ID_MODULO).times.lazy.map{ |idx| (@last_session_id + 1 + idx - SESSION_ID_MIN) % SESSION_ID_MODULO + SESSION_ID_MIN }.reject{ |sid| @sessions.has_key? sid }.first
38
40
  unless session_id
39
- @logger.error { "Failed allocating Session ID" }
41
+ log_error { "Failed allocating Session ID" }
40
42
  raise "Failed allocating Session ID"
41
43
  end
42
44
  @last_session_id = session_id
@@ -49,20 +51,20 @@ module HrrRbNetconf
49
51
  end
50
52
 
51
53
  def start_session io
52
- @logger.info { "Start session" }
54
+ log_info { "Start session" }
53
55
  session_id = SESSION_ID_UNALLOCATED
54
56
  begin
55
57
  @mutex.synchronize do
56
58
  session_id = allocate_session_id
57
- @logger.info { "Session ID: #{session_id}" }
58
- @sessions[session_id] = Session.new self, @capabilities, @datastore, session_id, io, @strict_capabilities
59
+ log_info { "Session ID: #{session_id}" }
60
+ @sessions[session_id] = Session.new self, @capabilities, @datastore, session_id, io, @strict_capabilities, logger: logger
59
61
  end
60
62
  @sessions[session_id].start
61
63
  rescue => e
62
- @logger.error { "Session terminated: Session ID: #{session_id}" }
64
+ log_error { "Session terminated: Session ID: #{session_id}" }
63
65
  raise
64
66
  else
65
- @logger.info { "Session closed: Session ID: #{session_id}" }
67
+ log_info { "Session closed: Session ID: #{session_id}" }
66
68
  ensure
67
69
  @lock_mutex.synchronize do
68
70
  @locks.delete_if{ |tgt, sid| sid == session_id }
@@ -74,16 +76,16 @@ module HrrRbNetconf
74
76
  end
75
77
 
76
78
  def close_session session_id
77
- @logger.info { "Close session: Session ID: #{session_id}" }
79
+ log_info { "Close session: Session ID: #{session_id}" }
78
80
  @sessions[session_id].close
79
81
  end
80
82
 
81
83
  def lock target, session_id
82
- @logger.info { "Lock: Target: #{target}, Session ID: #{session_id}" }
84
+ log_info { "Lock: Target: #{target}, Session ID: #{session_id}" }
83
85
  @lock_mutex.synchronize do
84
86
  if @locks.has_key? target
85
- @logger.info { "Lock failed, lock is already held by session-id: #{@locks[target]}" }
86
- raise Error['lock-denied'].new('protocol', 'error', info: {'session-id' => @locks[target].to_s}, message: 'Lock failed, lock is already held')
87
+ log_info { "Lock failed, lock is already held by session-id: #{@locks[target]}" }
88
+ raise Error['lock-denied'].new('protocol', 'error', info: {'session-id' => @locks[target].to_s}, message: 'Lock failed, lock is already held', logger: logger)
87
89
  else
88
90
  @locks[target] = session_id
89
91
  end
@@ -91,18 +93,18 @@ module HrrRbNetconf
91
93
  end
92
94
 
93
95
  def unlock target, session_id
94
- @logger.info { "Unlock: Target: #{target}, Session ID: #{session_id}" }
96
+ log_info { "Unlock: Target: #{target}, Session ID: #{session_id}" }
95
97
  @lock_mutex.synchronize do
96
98
  if @locks.has_key? target
97
99
  if @locks[target] == session_id
98
100
  @locks.delete target
99
101
  else
100
- @logger.info { "Unlock failed, lock is held by session-id: #{@locks[target]}" }
101
- raise Error['operation-failed'].new('protocol', 'error')
102
+ log_info { "Unlock failed, lock is held by session-id: #{@locks[target]}" }
103
+ raise Error['operation-failed'].new('protocol', 'error', logger: logger)
102
104
  end
103
105
  else
104
- @logger.info { "Unlock failed, lock is not held" }
105
- raise Error['operation-failed'].new('protocol', 'error')
106
+ log_info { "Unlock failed, lock is not held" }
107
+ raise Error['operation-failed'].new('protocol', 'error', logger: logger)
106
108
  end
107
109
  end
108
110
  end
@@ -126,12 +128,12 @@ module HrrRbNetconf
126
128
  def send_notification arg1, arg2=nil
127
129
  event_xml = NotificationEvent.new(arg1, arg2).to_xml
128
130
  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
+ log_info { "Send notification" }
132
+ log_debug { "Event time: #{event_xml.elements['eventTime'].text}, Event: #{event_xml.elements.to_a}" }
131
133
  @sessions.each{ |session_id, session|
132
134
  session.filter_and_send_notification matched_streams, event_xml
133
135
  }
134
- @logger.info { "Send notification done" }
136
+ log_info { "Send notification done" }
135
137
  end
136
138
  end
137
139
  end
@@ -2,5 +2,5 @@
2
2
  # vim: et ts=2 sw=2
3
3
 
4
4
  module HrrRbNetconf
5
- VERSION = "0.1.1"
5
+ VERSION = "0.2.0"
6
6
  end
@@ -2,7 +2,6 @@
2
2
  # vim: et ts=2 sw=2
3
3
 
4
4
  require "hrr_rb_netconf/version"
5
- require "hrr_rb_netconf/logger"
6
5
  require "hrr_rb_netconf/server"
7
6
 
8
7
  module HrrRbNetconf
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hrr_rb_netconf
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - hirura
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-01-09 00:00:00.000000000 Z
11
+ date: 2020-01-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: hrr_rb_relaxed_xml
@@ -87,7 +87,7 @@ files:
87
87
  - demo/server_with_sessionless-database.rb
88
88
  - hrr_rb_netconf.gemspec
89
89
  - lib/hrr_rb_netconf.rb
90
- - lib/hrr_rb_netconf/logger.rb
90
+ - lib/hrr_rb_netconf/loggable.rb
91
91
  - lib/hrr_rb_netconf/server.rb
92
92
  - lib/hrr_rb_netconf/server/capabilities.rb
93
93
  - lib/hrr_rb_netconf/server/capability.rb
@@ -1,56 +0,0 @@
1
- # coding: utf-8
2
- # vim: et ts=2 sw=2
3
-
4
- module HrrRbNetconf
5
- class Logger
6
- @@logger = nil
7
-
8
- class << self
9
- def initialize logger
10
- @@logger = logger
11
- end
12
-
13
- def uninitialize
14
- @@logger = nil
15
- end
16
-
17
- def initialized?
18
- @@logger != nil
19
- end
20
- end
21
-
22
- def initialize name
23
- @name = name
24
- end
25
-
26
- def fatal
27
- if @@logger
28
- @@logger.fatal { "p#{Process.pid}.t#{Thread.current.object_id}: #{@name}: #{yield}" }
29
- end
30
- end
31
-
32
- def error
33
- if @@logger
34
- @@logger.error { "p#{Process.pid}.t#{Thread.current.object_id}: #{@name}: #{yield}" }
35
- end
36
- end
37
-
38
- def warn
39
- if @@logger
40
- @@logger.warn { "p#{Process.pid}.t#{Thread.current.object_id}: #{@name}: #{yield}" }
41
- end
42
- end
43
-
44
- def info
45
- if @@logger
46
- @@logger.info { "p#{Process.pid}.t#{Thread.current.object_id}: #{@name}: #{yield}" }
47
- end
48
- end
49
-
50
- def debug
51
- if @@logger
52
- @@logger.debug { "p#{Process.pid}.t#{Thread.current.object_id}: #{@name}: #{yield}" }
53
- end
54
- end
55
- end
56
- end