hrr_rb_netconf 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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