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
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/demo/server.rb ADDED
@@ -0,0 +1,54 @@
1
+ # coding: utf-8
2
+ # vim: et ts=2 sw=2
3
+
4
+ require 'socket'
5
+ require 'logger'
6
+
7
+ begin
8
+ require 'hrr_rb_netconf'
9
+ rescue LoadError
10
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
11
+ require 'hrr_rb_netconf'
12
+ end
13
+
14
+
15
+ logger = Logger.new STDOUT
16
+ logger.level = Logger::DEBUG
17
+ HrrRbNetconf::Logger.initialize logger
18
+
19
+ datastore = HrrRbNetconf::Server::Datastore.new('dummy'){ |db, session, oper_handler|
20
+ begin
21
+ logger.debug { "begin DB session" }
22
+ oper_handler.start db
23
+ ensure
24
+ logger.debug { "close DB in ensure" }
25
+ end
26
+ }
27
+ datastore.oper_proc('get'){ |datastore, input_e|
28
+ '<a xmlns="dummy"><b/></a>'
29
+ }
30
+ datastore.oper_proc('close-session'){ |datastore, input_e|
31
+ '<ok/>'
32
+ }
33
+ datastore.oper_proc('kill-session'){ |datastore, input_e|
34
+ '<ok/>'
35
+ }
36
+
37
+ netconf_server = HrrRbNetconf::Server.new datastore
38
+
39
+ server = TCPServer.new 10830
40
+ loop do
41
+ Thread.new(server.accept) do |io|
42
+ begin
43
+ netconf_server.start_session io
44
+ rescue => e
45
+ logger.error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
46
+ ensure
47
+ begin
48
+ io.close
49
+ rescue => e
50
+ logger.error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,97 @@
1
+ # coding: utf-8
2
+ # vim: et ts=2 sw=2
3
+
4
+ require 'socket'
5
+ require 'logger'
6
+ require 'rexml/document'
7
+
8
+ begin
9
+ require 'hrr_rb_ssh'
10
+ rescue LoadError
11
+ STDERR.puts "Faild require 'hrr_rb_ssh' gem. Please install it with 'gem install hrr_rb_ssh'."
12
+ exit(1)
13
+ end
14
+
15
+ begin
16
+ require 'hrr_rb_netconf'
17
+ rescue LoadError
18
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
19
+ require 'hrr_rb_netconf'
20
+ end
21
+
22
+
23
+ logger = Logger.new STDOUT
24
+ logger.level = Logger::INFO
25
+ logger.level = Logger::DEBUG
26
+ HrrRbNetconf::Logger.initialize logger
27
+
28
+
29
+ db = '<root />'
30
+
31
+ datastore = HrrRbNetconf::Server::Datastore.new(db)
32
+ datastore.oper_proc('get'){ |db, input_e|
33
+ db
34
+ }
35
+ datastore.oper_proc('get-config'){ |db, input_e|
36
+ db
37
+ }
38
+ datastore.oper_proc('edit-config'){ |db, input_e|
39
+ config_e = input_e.elements['config'].elements[1].to_s
40
+ db = config_e
41
+ }
42
+ datastore.oper_proc('close-session'){ |db, input_e|
43
+ # pass
44
+ }
45
+ datastore.oper_proc('lock'){ |db, input_e|
46
+ # pass
47
+ }
48
+ datastore.oper_proc('unlock'){ |db, input_e|
49
+ # pass
50
+ }
51
+
52
+ netconf_server = HrrRbNetconf::Server.new datastore
53
+
54
+
55
+ auth_password = HrrRbSsh::Authentication::Authenticator.new { |context|
56
+ true # accept any user and password
57
+ }
58
+ conn_subsys = HrrRbSsh::Connection::RequestHandler.new { |context|
59
+ context.chain_proc { |chain|
60
+ case context.subsystem_name
61
+ when 'netconf'
62
+ begin
63
+ netconf_server.start_session context.io
64
+ exitstatus = 0
65
+ rescue => e
66
+ logger.error([e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join)
67
+ exitstatus = 1
68
+ end
69
+ else
70
+ exitstatus = 0
71
+ end
72
+ exitstatus
73
+ }
74
+ }
75
+
76
+ options = {}
77
+ options['authentication_password_authenticator'] = auth_password
78
+ options['connection_channel_request_subsystem'] = conn_subsys
79
+
80
+
81
+
82
+ server = TCPServer.new 10830
83
+ loop do
84
+ Thread.new(server.accept) do |io|
85
+ begin
86
+ ssh_server = HrrRbSsh::Server.new io, options
87
+ ssh_server.start
88
+ rescue => e
89
+ logger.error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
90
+ ensure
91
+ begin
92
+ io.close
93
+ rescue
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,134 @@
1
+ # coding: utf-8
2
+ # vim: et ts=2 sw=2
3
+
4
+ require 'socket'
5
+ require 'logger'
6
+ require 'rexml/document'
7
+
8
+ begin
9
+ require 'hrr_rb_netconf'
10
+ rescue LoadError
11
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
12
+ require 'hrr_rb_netconf'
13
+ end
14
+
15
+ class SessionOrientedDatabase
16
+ class DatabaseSession
17
+ def initialize db, session_id
18
+ @db = db
19
+ @session_id = session_id
20
+ end
21
+
22
+ def lock
23
+ # Dummy method
24
+ end
25
+
26
+ def unlock
27
+ # Dummy method
28
+ end
29
+
30
+ def close
31
+ # Dummy method
32
+ end
33
+
34
+ def get
35
+ @db.get
36
+ end
37
+
38
+ def get_config
39
+ @db.get_config
40
+ end
41
+
42
+ def edit input_e
43
+ @db.edit input_e
44
+ end
45
+ end
46
+
47
+ def initialize
48
+ @xml_doc = REXML::Document.new('<original />')
49
+ @content = ''
50
+ end
51
+
52
+ def new_session session_id
53
+ DatabaseSession.new self, session_id
54
+ end
55
+
56
+ def get
57
+ @xml_doc.root.deep_clone
58
+ end
59
+
60
+ def get_config
61
+ @xml_doc.root.deep_clone
62
+ end
63
+
64
+ def edit input_e
65
+ @xml_doc = REXML::Document.new
66
+ @xml_doc.add input_e
67
+ end
68
+ end
69
+
70
+
71
+ logger = Logger.new STDOUT
72
+ logger.level = Logger::INFO
73
+ logger.level = Logger::DEBUG
74
+ HrrRbNetconf::Logger.initialize logger
75
+
76
+
77
+ db = SessionOrientedDatabase.new
78
+
79
+ datastore = HrrRbNetconf::Server::Datastore.new(db){ |db, session, oper_handler|
80
+ begin
81
+ logger.debug { "begin DB session" }
82
+ db_session = db.new_session session.session_id
83
+ dummy_arg = 'dummy_arg'
84
+ oper_handler.start db_session, dummy_arg
85
+ ensure
86
+ logger.debug { "close DB in ensure" }
87
+ db_session.close rescue nil
88
+ end
89
+ }
90
+ datastore.oper_proc('get'){ |db_session, dummy_arg, input_e|
91
+ db_session.get
92
+ }
93
+ datastore.oper_proc('get-config'){ |db_session, dummy_arg, input_e|
94
+ db_session.get_config
95
+ }
96
+ datastore.oper_proc('edit-config'){ |db_session, dummy_arg, input_e|
97
+ config_e = input_e.elements['config'].elements[1]
98
+ db_session.edit config_e
99
+ }
100
+ datastore.oper_proc('close-session'){ |db_session, dummy_arg, input_e|
101
+ begin
102
+ db_session.close
103
+ rescue => e
104
+ raise HrrRbNetconf::Server::Error['operation-failed'].new('application', 'error', message: e.message)
105
+ end
106
+ }
107
+ datastore.oper_proc('lock'){ |db_session, dummy_arg, input_e|
108
+ begin
109
+ db_session.lock
110
+ rescue => e
111
+ raise HrrRbNetconf::Server::Error['resource-denied'].new('application', 'error', message: e.message)
112
+ end
113
+ }
114
+ datastore.oper_proc('unlock'){ |db_session, dummy_arg, input_e|
115
+ db_session.unlock rescue nil
116
+ }
117
+
118
+
119
+ server = TCPServer.new 10830
120
+ netconf_server = HrrRbNetconf::Server.new datastore
121
+ loop do
122
+ Thread.new(server.accept) do |io|
123
+ begin
124
+ netconf_server.start_session io
125
+ rescue => e
126
+ logger.error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
127
+ ensure
128
+ begin
129
+ io.close
130
+ rescue
131
+ end
132
+ end
133
+ end
134
+ end
@@ -0,0 +1,81 @@
1
+ # coding: utf-8
2
+ # vim: et ts=2 sw=2
3
+
4
+ require 'socket'
5
+ require 'logger'
6
+ require 'rexml/document'
7
+
8
+ begin
9
+ require 'hrr_rb_netconf'
10
+ rescue LoadError
11
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
12
+ require 'hrr_rb_netconf'
13
+ end
14
+
15
+ class SessionlessDatabase
16
+ def initialize
17
+ @xml_doc = REXML::Document.new('<original />')
18
+ @content = ''
19
+ end
20
+
21
+ def get
22
+ @xml_doc.root.deep_clone
23
+ end
24
+
25
+ def get_config
26
+ @xml_doc.root.deep_clone
27
+ end
28
+
29
+ def edit input_e
30
+ @xml_doc = REXML::Document.new
31
+ @xml_doc.add input_e
32
+ end
33
+ end
34
+
35
+
36
+ logger = Logger.new STDOUT
37
+ logger.level = Logger::INFO
38
+ logger.level = Logger::DEBUG
39
+ HrrRbNetconf::Logger.initialize logger
40
+
41
+
42
+ db = SessionlessDatabase.new
43
+
44
+ datastore = HrrRbNetconf::Server::Datastore.new(db)
45
+ datastore.oper_proc('get'){ |db, input_e|
46
+ db.get
47
+ }
48
+ datastore.oper_proc('get-config'){ |db, input_e|
49
+ db.get_config
50
+ }
51
+ datastore.oper_proc('edit-config'){ |db, input_e|
52
+ config_e = input_e.elements['config'].elements[1]
53
+ db.edit config_e
54
+ }
55
+ datastore.oper_proc('close-session'){ |db, input_e|
56
+ # pass
57
+ }
58
+ datastore.oper_proc('lock'){ |db, input_e|
59
+ # pass
60
+ }
61
+ datastore.oper_proc('unlock'){ |db, input_e|
62
+ # pass
63
+ }
64
+
65
+
66
+ server = TCPServer.new 10830
67
+ netconf_server = HrrRbNetconf::Server.new datastore
68
+ loop do
69
+ Thread.new(server.accept) do |io|
70
+ begin
71
+ netconf_server.start_session io
72
+ rescue => e
73
+ logger.error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
74
+ ensure
75
+ begin
76
+ io.close
77
+ rescue
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ # vim: et ts=2 sw=2
3
+
4
+ lib = File.expand_path("../lib", __FILE__)
5
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
6
+ require "hrr_rb_netconf/version"
7
+
8
+ Gem::Specification.new do |spec|
9
+ spec.name = "hrr_rb_netconf"
10
+ spec.version = HrrRbNetconf::VERSION
11
+ spec.license = 'Apache-2.0'
12
+ spec.summary = %q{Pure Ruby NETCONF server implementation}
13
+ spec.description = %q{Pure Ruby NETCONF server implementation}
14
+ spec.authors = ["hirura"]
15
+ spec.email = ["hirura@gmail.com"]
16
+ spec.homepage = "https://github.com/hirura/hrr_rb_netconf"
17
+
18
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
19
+ f.match(%r{^(test|spec|features)/})
20
+ end
21
+ spec.require_paths = ["lib"]
22
+
23
+ spec.required_ruby_version = '>= 2.0.0'
24
+
25
+ spec.add_development_dependency "rake", "~> 10.0"
26
+ spec.add_development_dependency "rspec", "~> 3.0"
27
+ spec.add_development_dependency "simplecov", "~> 0.16"
28
+ end
@@ -0,0 +1,10 @@
1
+ # coding: utf-8
2
+ # vim: et ts=2 sw=2
3
+
4
+ require "hrr_rb_netconf/version"
5
+ require "hrr_rb_netconf/logger"
6
+ require "hrr_rb_netconf/server"
7
+
8
+ module HrrRbNetconf
9
+ # Your code goes here...
10
+ end
@@ -0,0 +1,56 @@
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