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.
- checksums.yaml +7 -0
- data/.gitignore +28 -0
- data/.rspec +3 -0
- data/.travis.yml +32 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +6 -0
- data/LICENSE +201 -0
- data/README.md +220 -0
- data/Rakefile +6 -0
- data/demo/server.rb +54 -0
- data/demo/server_over_ssh.rb +97 -0
- data/demo/server_with_session-oriented-database.rb +134 -0
- data/demo/server_with_sessionless-database.rb +81 -0
- data/hrr_rb_netconf.gemspec +28 -0
- data/lib/hrr_rb_netconf.rb +10 -0
- data/lib/hrr_rb_netconf/logger.rb +56 -0
- data/lib/hrr_rb_netconf/server.rb +109 -0
- data/lib/hrr_rb_netconf/server/capabilities.rb +75 -0
- data/lib/hrr_rb_netconf/server/capability.rb +206 -0
- data/lib/hrr_rb_netconf/server/capability/base_1_0.rb +183 -0
- data/lib/hrr_rb_netconf/server/capability/base_1_1.rb +247 -0
- data/lib/hrr_rb_netconf/server/capability/candidate_1_0.rb +34 -0
- data/lib/hrr_rb_netconf/server/capability/confirmed_commit_1_0.rb +24 -0
- data/lib/hrr_rb_netconf/server/capability/confirmed_commit_1_1.rb +24 -0
- data/lib/hrr_rb_netconf/server/capability/rollback_on_error_1_0.rb +16 -0
- data/lib/hrr_rb_netconf/server/capability/startup_1_0.rb +22 -0
- data/lib/hrr_rb_netconf/server/capability/url_1_0.rb +23 -0
- data/lib/hrr_rb_netconf/server/capability/validate_1_0.rb +25 -0
- data/lib/hrr_rb_netconf/server/capability/validate_1_1.rb +25 -0
- data/lib/hrr_rb_netconf/server/capability/writable_running_1_0.rb +17 -0
- data/lib/hrr_rb_netconf/server/capability/xpath_1_0.rb +14 -0
- data/lib/hrr_rb_netconf/server/datastore.rb +30 -0
- data/lib/hrr_rb_netconf/server/datastore/oper_handler.rb +29 -0
- data/lib/hrr_rb_netconf/server/datastore/session.rb +52 -0
- data/lib/hrr_rb_netconf/server/error.rb +52 -0
- data/lib/hrr_rb_netconf/server/error/access_denied.rb +19 -0
- data/lib/hrr_rb_netconf/server/error/bad_attribute.rb +20 -0
- data/lib/hrr_rb_netconf/server/error/bad_element.rb +20 -0
- data/lib/hrr_rb_netconf/server/error/data_exists.rb +19 -0
- data/lib/hrr_rb_netconf/server/error/data_missing.rb +19 -0
- data/lib/hrr_rb_netconf/server/error/in_use.rb +19 -0
- data/lib/hrr_rb_netconf/server/error/invalid_value.rb +19 -0
- data/lib/hrr_rb_netconf/server/error/lock_denied.rb +19 -0
- data/lib/hrr_rb_netconf/server/error/malformed_message.rb +19 -0
- data/lib/hrr_rb_netconf/server/error/missing_attribute.rb +19 -0
- data/lib/hrr_rb_netconf/server/error/missing_element.rb +19 -0
- data/lib/hrr_rb_netconf/server/error/operation_failed.rb +19 -0
- data/lib/hrr_rb_netconf/server/error/operation_not_supported.rb +19 -0
- data/lib/hrr_rb_netconf/server/error/partial_operation.rb +19 -0
- data/lib/hrr_rb_netconf/server/error/resource_denied.rb +19 -0
- data/lib/hrr_rb_netconf/server/error/rollback_failed.rb +19 -0
- data/lib/hrr_rb_netconf/server/error/rpc_errorable.rb +138 -0
- data/lib/hrr_rb_netconf/server/error/too_big.rb +19 -0
- data/lib/hrr_rb_netconf/server/error/unknown_attribute.rb +19 -0
- data/lib/hrr_rb_netconf/server/error/unknown_element.rb +19 -0
- data/lib/hrr_rb_netconf/server/error/unknown_namespace.rb +19 -0
- data/lib/hrr_rb_netconf/server/errors.rb +28 -0
- data/lib/hrr_rb_netconf/server/filter.rb +48 -0
- data/lib/hrr_rb_netconf/server/filter/subtree.rb +135 -0
- data/lib/hrr_rb_netconf/server/filter/xpath.rb +59 -0
- data/lib/hrr_rb_netconf/server/model.rb +123 -0
- data/lib/hrr_rb_netconf/server/model/node.rb +19 -0
- data/lib/hrr_rb_netconf/server/operation.rb +92 -0
- data/lib/hrr_rb_netconf/server/session.rb +177 -0
- data/lib/hrr_rb_netconf/version.rb +6 -0
- metadata +149 -0
data/Rakefile
ADDED
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,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
|