hrr_rb_netconf 0.1.0

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