net-netconf 0.4.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/examples/confd/get-running.rb +27 -0
- data/examples/jnpr/edit-config-jnpr-set.rb +55 -0
- data/examples/jnpr/edit-config-jnpr-text.rb +64 -0
- data/examples/jnpr/edit-config-jnpr.rb +73 -0
- data/examples/jnpr/edit-config-std.rb +64 -0
- data/examples/jnpr/edit-config-text-std.rb +68 -0
- data/examples/jnpr/get-config-jnpr.rb +62 -0
- data/examples/jnpr/get-config-matching.rb +20 -0
- data/examples/jnpr/get-config-std.rb +49 -0
- data/examples/jnpr/get-inventory-serial-explicit.rb +27 -0
- data/examples/jnpr/get-inventory-serial.rb +25 -0
- data/examples/jnpr/get-inventory-telnet.rb +14 -0
- data/examples/jnpr/get-inventory.rb +16 -0
- data/examples/jnpr/scp.rb +22 -0
- data/lib/net/netconf.rb +24 -0
- data/lib/net/netconf/exception.rb +38 -0
- data/lib/net/netconf/ioproc.rb +88 -0
- data/lib/net/netconf/jnpr.rb +9 -0
- data/lib/net/netconf/jnpr/ioproc.rb +14 -0
- data/lib/net/netconf/jnpr/junos_config.rb +104 -0
- data/lib/net/netconf/jnpr/rpc.rb +162 -0
- data/lib/net/netconf/jnpr/serial.rb +15 -0
- data/lib/net/netconf/jnpr/ssh.rb +27 -0
- data/lib/net/netconf/jnpr/telnet.rb +23 -0
- data/lib/net/netconf/rpc.rb +71 -0
- data/lib/net/netconf/rpc_std.rb +133 -0
- data/lib/net/netconf/serial.rb +135 -0
- data/lib/net/netconf/ssh.rb +94 -0
- data/lib/net/netconf/telnet.rb +52 -0
- data/lib/net/netconf/transport.rb +156 -0
- data/lib/net/netconf/version.rb +3 -0
- metadata +116 -0
@@ -0,0 +1,162 @@
|
|
1
|
+
## -----------------------------------------------------------------------
|
2
|
+
## This file contains the Junos specific RPC methods that are generated
|
3
|
+
## specifically and different as generated by the Netconf::RPC::Builder
|
4
|
+
## module. These are specifically the following:
|
5
|
+
##
|
6
|
+
## get_configuration - alternative NETCONF: 'get-config'
|
7
|
+
## load_configuration - alternative NETCONF: 'edit-config'
|
8
|
+
## lock_configuration - alternative NETCONF: 'lock'
|
9
|
+
## commit_configuration - alternative NETCONF: 'commit'
|
10
|
+
##
|
11
|
+
## note: unlock_configuration is not included in this file since
|
12
|
+
## the Netconf::RPC::Builder works "as-is" in this case
|
13
|
+
## -----------------------------------------------------------------------
|
14
|
+
|
15
|
+
module Netconf
|
16
|
+
module RPC
|
17
|
+
module Junos
|
18
|
+
|
19
|
+
def lock_configuration
|
20
|
+
lock( 'candidate' )
|
21
|
+
end
|
22
|
+
|
23
|
+
def check_configuration
|
24
|
+
validate( 'candidate' )
|
25
|
+
end
|
26
|
+
|
27
|
+
def commit_configuration( params = nil, attrs = nil )
|
28
|
+
rpc = Netconf::RPC::Builder.commit_configuration( params, attrs )
|
29
|
+
Netconf::RPC.set_exception( rpc, Netconf::CommitError )
|
30
|
+
@trans.rpc_exec( rpc )
|
31
|
+
end
|
32
|
+
|
33
|
+
def get_configuration( *args )
|
34
|
+
|
35
|
+
filter = nil
|
36
|
+
|
37
|
+
while arg = args.shift
|
38
|
+
case arg.class.to_s
|
39
|
+
when /^Nokogiri/
|
40
|
+
filter = case arg
|
41
|
+
when Nokogiri::XML::Builder then arg.doc.root
|
42
|
+
when Nokogiri::XML::Document then arg.root
|
43
|
+
else arg
|
44
|
+
end
|
45
|
+
when 'Hash' then attrs = arg
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
rpc = Nokogiri::XML('<rpc><get-configuration/></rpc>').root
|
50
|
+
Netconf::RPC.add_attributes( rpc.first_element_child, attrs ) if attrs
|
51
|
+
|
52
|
+
if block_given?
|
53
|
+
Nokogiri::XML::Builder.with(rpc.at( 'get-configuration' )){ |xml|
|
54
|
+
xml.configuration {
|
55
|
+
yield( xml )
|
56
|
+
}}
|
57
|
+
elsif filter
|
58
|
+
# filter must have toplevel = <configuration>
|
59
|
+
rpc.first_element_child << filter.dup # *MUST* use the .dup so we don't disrupt the original filter
|
60
|
+
end
|
61
|
+
|
62
|
+
@trans.rpc_exec( rpc )
|
63
|
+
end
|
64
|
+
|
65
|
+
def load_configuration( *args )
|
66
|
+
|
67
|
+
config = nil
|
68
|
+
|
69
|
+
# default format is XML
|
70
|
+
attrs = { :format => 'xml' }
|
71
|
+
|
72
|
+
while arg = args.shift
|
73
|
+
case arg.class.to_s
|
74
|
+
when /^Nokogiri/
|
75
|
+
config = case arg
|
76
|
+
when Nokogiri::XML::Builder then arg.doc.root
|
77
|
+
when Nokogiri::XML::Document then arg.root
|
78
|
+
else arg
|
79
|
+
end
|
80
|
+
when 'Hash' then attrs.merge! arg
|
81
|
+
when 'Array' then config = arg.join("\n")
|
82
|
+
when 'String' then config = arg
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
case attrs[:format]
|
87
|
+
when 'set'
|
88
|
+
toplevel = 'configuration-set'
|
89
|
+
attrs[:format] = 'text'
|
90
|
+
attrs[:action] = 'set'
|
91
|
+
when 'text'
|
92
|
+
toplevel = 'configuration-text'
|
93
|
+
when 'xml'
|
94
|
+
toplevel = 'configuration'
|
95
|
+
end
|
96
|
+
|
97
|
+
rpc = Nokogiri::XML('<rpc><load-configuration/></rpc>').root
|
98
|
+
ld_cfg = rpc.first_element_child
|
99
|
+
Netconf::RPC.add_attributes( ld_cfg, attrs ) if attrs
|
100
|
+
|
101
|
+
if block_given?
|
102
|
+
if attrs[:format] == 'xml'
|
103
|
+
Nokogiri::XML::Builder.with( ld_cfg ){ |xml|
|
104
|
+
xml.send( toplevel ) {
|
105
|
+
yield( xml )
|
106
|
+
}}
|
107
|
+
else
|
108
|
+
config = yield # returns String | Array(of stringable)
|
109
|
+
config = config.join("\n") if config.class == Array
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
if config
|
114
|
+
if attrs[:format] == 'xml'
|
115
|
+
# config assumes toplevel = <configuration> given
|
116
|
+
ld_cfg << config.dup # duplicate the config so as to not distrupt it
|
117
|
+
else
|
118
|
+
# config is stringy, so just add it as the text node
|
119
|
+
c_node = Nokogiri::XML::Node.new( toplevel, rpc )
|
120
|
+
c_node.content = config
|
121
|
+
ld_cfg << c_node
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
# set a specific exception class on this RPC so it can be
|
126
|
+
# properlly handled by the calling enviornment
|
127
|
+
|
128
|
+
Netconf::RPC::set_exception( rpc, Netconf::EditError )
|
129
|
+
@trans.rpc_exec( rpc )
|
130
|
+
end # load_configuration
|
131
|
+
|
132
|
+
def command( cmd_str, attrs = nil )
|
133
|
+
rpc = Nokogiri::XML("<rpc><command>#{cmd_str}</command></rpc>").root
|
134
|
+
Netconf::RPC.add_attributes( rpc.at('command'), attrs ) if attrs
|
135
|
+
@trans.rpc_exec( rpc )
|
136
|
+
end
|
137
|
+
|
138
|
+
## contributed by 'dgjnpr'
|
139
|
+
def request_pfe_execute( params = nil )
|
140
|
+
raise ArgumentError, 'Manditorary argument :target missing' unless params[:target]
|
141
|
+
raise ArgumentError, 'Manditorary argument :command missing' unless params[:command]
|
142
|
+
|
143
|
+
rpc_nx = Nokogiri::XML::Builder.new { |xml|
|
144
|
+
xml.rpc {
|
145
|
+
xml.send( 'request-pfe-execute' ) {
|
146
|
+
xml.send( 'target', params[:target] )
|
147
|
+
if params[:command].class.to_s =~ /^Array/
|
148
|
+
params[:command].each { |cmd|
|
149
|
+
xml.send( 'command', cmd )
|
150
|
+
}
|
151
|
+
elsif params[:command].class.to_s =~ /^String/
|
152
|
+
xml.send( 'command', params[:command] )
|
153
|
+
end
|
154
|
+
}
|
155
|
+
}
|
156
|
+
}
|
157
|
+
@trans.rpc_exec( rpc_nx )
|
158
|
+
end
|
159
|
+
|
160
|
+
end # module: JUNOS
|
161
|
+
end # module: RPC
|
162
|
+
end # module: Netconf
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'net/netconf'
|
2
|
+
require 'net/netconf/serial'
|
3
|
+
require 'net/netconf/jnpr'
|
4
|
+
|
5
|
+
module Netconf
|
6
|
+
module Junos
|
7
|
+
module TransSerial
|
8
|
+
def trans_start_netconf( last_console )
|
9
|
+
last_console.match(/[^%]\s+$/)
|
10
|
+
netconf_cmd = ($1 == '%') ? Netconf::Junos::NETCONF_SHELL : Netconf::Junos::NETCONF_CLI
|
11
|
+
puts netconf_cmd
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'net/netconf'
|
2
|
+
require 'net/netconf/jnpr'
|
3
|
+
|
4
|
+
module Netconf
|
5
|
+
module Junos
|
6
|
+
module TransSSH
|
7
|
+
|
8
|
+
##
|
9
|
+
## this is used to handle the case where NETCONF (port 830) is disabled. We can still access
|
10
|
+
## the NETCONF subsystem from the CLI using a hidden command 'netconf'
|
11
|
+
##
|
12
|
+
|
13
|
+
def trans_on_connect_refused( start_args )
|
14
|
+
start_args[:port] = 22
|
15
|
+
@trans[:conn] = Net::SSH.start( @args[:target], @args[:username], start_args )
|
16
|
+
do_once = true
|
17
|
+
@trans[:conn].exec( NETCONF_CLI ) do |chan, success|
|
18
|
+
@trans[:chan] = chan
|
19
|
+
do_once = false
|
20
|
+
end
|
21
|
+
@trans[:conn].loop { do_once }
|
22
|
+
@trans[:chan]
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'net/netconf'
|
2
|
+
require 'net/netconf/telnet'
|
3
|
+
require 'net/netconf/jnpr'
|
4
|
+
|
5
|
+
module Netconf
|
6
|
+
module Junos
|
7
|
+
module TransTelnet
|
8
|
+
|
9
|
+
def trans_login
|
10
|
+
l_rsp = @trans.login( @args[:username], @args[:password] )
|
11
|
+
# @@@/JLS: need to rescue the timeout ... ???
|
12
|
+
l_rsp.match("([>%])\s+$")
|
13
|
+
@exec_netconf = ($1 == '%') ? Netconf::Junos::NETCONF_SHELL : Netconf::Junos::NETCONF_CLI
|
14
|
+
end
|
15
|
+
|
16
|
+
def trans_start_netconf
|
17
|
+
@trans.puts @exec_netconf
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'net/netconf/rpc_std'
|
2
|
+
|
3
|
+
module Netconf
|
4
|
+
module RPC
|
5
|
+
|
6
|
+
def RPC.add_attributes( ele_nx, attr_h )
|
7
|
+
attr_h.each{ |k,v| ele_nx[k] = v }
|
8
|
+
end
|
9
|
+
|
10
|
+
def RPC.set_exception( rpc_nx, exception )
|
11
|
+
rpc_nx.instance_variable_set(:@netconf_exception, exception )
|
12
|
+
end
|
13
|
+
|
14
|
+
def RPC.get_exception( rpc_nx )
|
15
|
+
rpc_nx.instance_variable_get(:@netconf_exception) || Netconf::RpcError
|
16
|
+
end
|
17
|
+
|
18
|
+
module Builder
|
19
|
+
# autogenerate an <rpc>, converting underscores (_)
|
20
|
+
# to hyphens (-) along the way ...
|
21
|
+
|
22
|
+
def Builder.method_missing( method, params = nil, attrs = nil )
|
23
|
+
|
24
|
+
rpc_name = method.to_s.tr('_','-').to_sym
|
25
|
+
|
26
|
+
if params
|
27
|
+
# build the XML starting at <rpc>, envelope the <method> toplevel element,
|
28
|
+
# and then create name/value elements for each of the additional params. An element
|
29
|
+
# without a value should simply be set to true
|
30
|
+
rpc_nx = Nokogiri::XML::Builder.new { |xml|
|
31
|
+
xml.rpc { xml.send( rpc_name ) {
|
32
|
+
params.each{ |k,v|
|
33
|
+
sym = k.to_s.tr('_','-').to_sym
|
34
|
+
xml.send(sym, (v==true) ? nil : v )
|
35
|
+
}
|
36
|
+
}}
|
37
|
+
}.doc.root
|
38
|
+
else
|
39
|
+
# -- no params
|
40
|
+
rpc_nx = Nokogiri::XML("<rpc><#{rpc_name}/></rpc>").root
|
41
|
+
end
|
42
|
+
|
43
|
+
# if a block is given it is used to set the attributes of the toplevel element
|
44
|
+
RPC.add_attributes( rpc_nx.at( rpc_name ), attrs ) if attrs
|
45
|
+
|
46
|
+
# return the rpc command
|
47
|
+
rpc_nx
|
48
|
+
end # def: method-missing?
|
49
|
+
|
50
|
+
end # module: Builder
|
51
|
+
|
52
|
+
class Executor
|
53
|
+
include Netconf::RPC::Standard
|
54
|
+
|
55
|
+
def initialize( trans, os_type )
|
56
|
+
@trans = trans
|
57
|
+
begin
|
58
|
+
extend Netconf::RPC::const_get( os_type )
|
59
|
+
rescue NameError
|
60
|
+
# no extensions available ...
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def method_missing( method, params = nil, attrs = nil )
|
65
|
+
@trans.rpc_exec( Netconf::RPC::Builder.send( method, params, attrs ))
|
66
|
+
end
|
67
|
+
end # class: Executor
|
68
|
+
|
69
|
+
end # module: RPC
|
70
|
+
end # module: Netconf
|
71
|
+
|
@@ -0,0 +1,133 @@
|
|
1
|
+
module Netconf
|
2
|
+
module RPC
|
3
|
+
|
4
|
+
MSG_END = "]]>]]>"
|
5
|
+
MSG_END_RE = /\]\]>\]\]>[\r\n]*$/
|
6
|
+
MSG_CLOSE_SESSION = '<rpc><close-session/></rpc>'
|
7
|
+
MSG_HELLO = <<-EOM
|
8
|
+
<hello xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
|
9
|
+
<capabilities>
|
10
|
+
<capability>urn:ietf:params:netconf:base:1.0</capability>
|
11
|
+
</capabilities>
|
12
|
+
</hello>
|
13
|
+
EOM
|
14
|
+
|
15
|
+
module Standard
|
16
|
+
|
17
|
+
def lock( target )
|
18
|
+
rpc = Nokogiri::XML( "<rpc><lock><target><#{target}/></target></lock></rpc>" ).root
|
19
|
+
Netconf::RPC.set_exception( rpc, Netconf::LockError )
|
20
|
+
@trans.rpc_exec( rpc )
|
21
|
+
end
|
22
|
+
|
23
|
+
def unlock( target )
|
24
|
+
rpc = Nokogiri::XML( "<rpc><unlock><target><#{target}/></target></unlock></rpc>" ).root
|
25
|
+
@trans.rpc_exec( rpc )
|
26
|
+
end
|
27
|
+
|
28
|
+
def validate( source )
|
29
|
+
rpc = Nokogiri::XML( "<rpc><validate><source><#{source}/></source></validate></rpc>" ).root
|
30
|
+
Netconf::RPC.set_exception( rpc, Netconf::ValidateError )
|
31
|
+
@trans.rpc_exec( rpc )
|
32
|
+
end
|
33
|
+
|
34
|
+
def commit
|
35
|
+
rpc = Nokogiri::XML( "<rpc><commit/></rpc>" ).root
|
36
|
+
Netconf::RPC.set_exception( rpc, Netconf::CommitError )
|
37
|
+
@trans.rpc_exec( rpc )
|
38
|
+
end
|
39
|
+
|
40
|
+
def delete_config( target )
|
41
|
+
rpc = Nokogiri::XML( "<rpc><delete-config><target><#{target}/></target></delete-config></rpc>" ).root
|
42
|
+
@trans.rpc_exec( rpc )
|
43
|
+
end
|
44
|
+
|
45
|
+
def get_config( *args ) # :yeield: filter_builder
|
46
|
+
|
47
|
+
source = 'running' # default source is 'running'
|
48
|
+
filter = nil # no filter by default
|
49
|
+
|
50
|
+
while arg = args.shift
|
51
|
+
case arg.class.to_s
|
52
|
+
when /^Nokogiri/
|
53
|
+
filter = case arg
|
54
|
+
when Nokogiri::XML::Builder then arg.doc.root
|
55
|
+
when Nokogiri::XML::Document then arg.root
|
56
|
+
else arg
|
57
|
+
end
|
58
|
+
when 'Hash' then attrs = arg
|
59
|
+
when 'String' then source = arg
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
rpc = Nokogiri::XML("<rpc><get-config><source><#{source}/></source></get-config></rpc>").root
|
64
|
+
|
65
|
+
if block_given?
|
66
|
+
Nokogiri::XML::Builder.with( rpc.at( 'get-config' )){ |xml|
|
67
|
+
xml.filter( :type => 'subtree' ) {
|
68
|
+
yield( xml )
|
69
|
+
}
|
70
|
+
}
|
71
|
+
end
|
72
|
+
|
73
|
+
if filter
|
74
|
+
f_node = Nokogiri::XML::Node.new( 'filter', rpc )
|
75
|
+
f_node['type'] = 'subtree'
|
76
|
+
f_node << filter.dup # copy filter, don't mess with the original since it may be re-used
|
77
|
+
rpc.at('get-config') << f_node
|
78
|
+
end
|
79
|
+
|
80
|
+
@trans.rpc_exec( rpc )
|
81
|
+
end
|
82
|
+
|
83
|
+
def edit_config( *args ) # :yeield: config_builder
|
84
|
+
|
85
|
+
toplevel = 'config' # default toplevel config element
|
86
|
+
target = 'candidate' # default source is 'candidate' @@@/JLS hack; need to fix this
|
87
|
+
config = nil
|
88
|
+
options = {}
|
89
|
+
|
90
|
+
while arg = args.shift
|
91
|
+
case arg.class.to_s
|
92
|
+
when /^Nokogiri/
|
93
|
+
config = case arg
|
94
|
+
when Nokogiri::XML::Builder then arg.doc.root
|
95
|
+
when Nokogiri::XML::Document then arg.root
|
96
|
+
else arg
|
97
|
+
end
|
98
|
+
when 'Hash' then options = arg
|
99
|
+
when 'String' then target = arg
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
toplevel = options[:toplevel] if options[:toplevel]
|
104
|
+
|
105
|
+
rpc_str = <<-EO_RPC
|
106
|
+
<rpc>
|
107
|
+
<edit-config>
|
108
|
+
<target><#{target}/></target>
|
109
|
+
<#{toplevel}/>
|
110
|
+
</edit-config>
|
111
|
+
</rpc>
|
112
|
+
EO_RPC
|
113
|
+
|
114
|
+
rpc = Nokogiri::XML( rpc_str ).root
|
115
|
+
|
116
|
+
if block_given?
|
117
|
+
Nokogiri::XML::Builder.with(rpc.at( toplevel )){ |xml|
|
118
|
+
yield( xml )
|
119
|
+
}
|
120
|
+
elsif config
|
121
|
+
rpc.at( toplevel ) << config.dup
|
122
|
+
else
|
123
|
+
raise ArgumentError, "You must specify edit-config data!"
|
124
|
+
end
|
125
|
+
|
126
|
+
Netconf::RPC.set_exception( rpc, Netconf::EditError )
|
127
|
+
@trans.rpc_exec( rpc )
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
|
132
|
+
end # module: RPC
|
133
|
+
end # module: Netconf
|
@@ -0,0 +1,135 @@
|
|
1
|
+
require 'serialport'
|
2
|
+
|
3
|
+
module Netconf
|
4
|
+
|
5
|
+
class Serial < Netconf::Transport
|
6
|
+
|
7
|
+
DEFAULT_BAUD = 9600
|
8
|
+
DEFAULT_DATABITS = 8
|
9
|
+
DEFAULT_STOPBITS = 1
|
10
|
+
DEFAULT_PARITY = SerialPort::NONE
|
11
|
+
DEFAULT_RDBLKSZ = (1024*1024)
|
12
|
+
|
13
|
+
attr_reader :args
|
14
|
+
|
15
|
+
def initialize( args_h, &block )
|
16
|
+
os_type = args_h[:os_type] || Netconf::DEFAULT_OS_TYPE
|
17
|
+
|
18
|
+
raise Netconf::InitError, "Missing 'port' param" unless args_h[:port]
|
19
|
+
raise Netconf::InitError, "Missing 'username' param" unless args_h[:username]
|
20
|
+
|
21
|
+
@args = args_h.clone
|
22
|
+
@args[:prompt] ||= /([%>])\s+$/
|
23
|
+
|
24
|
+
# extend this instance with the capabilities of the specific console
|
25
|
+
# type; it needs to define #trans_start_netconf session
|
26
|
+
# this must be provided! if the caller does not, this will
|
27
|
+
# throw a NameError exception.
|
28
|
+
|
29
|
+
extend Netconf::const_get( os_type )::TransSerial
|
30
|
+
|
31
|
+
@trans_timeout = @args[:timeout] || Netconf::DEFAULT_TIMEOUT
|
32
|
+
@trans_waitio = @args[:waitio] || Netconf::DEFAULT_WAITIO
|
33
|
+
|
34
|
+
super( &block )
|
35
|
+
end
|
36
|
+
|
37
|
+
def login
|
38
|
+
|
39
|
+
begin
|
40
|
+
puts
|
41
|
+
waitfor(/ogin:/)
|
42
|
+
rescue Timeout::Error
|
43
|
+
puts
|
44
|
+
waitfor(/ogin:/)
|
45
|
+
end
|
46
|
+
|
47
|
+
puts @args[:username]
|
48
|
+
|
49
|
+
waitfor(/assword:/)
|
50
|
+
puts @args[:password]
|
51
|
+
|
52
|
+
waitfor( @args[:prompt] )
|
53
|
+
end
|
54
|
+
|
55
|
+
def trans_open # :yield: self
|
56
|
+
|
57
|
+
baud = @args[:speed] || DEFAULT_BAUD
|
58
|
+
data_bits = @args[:bits] || DEFAULT_DATABITS
|
59
|
+
stop_bits = @args[:stop] || DEFAULT_STOPBITS
|
60
|
+
parity = @args[:parity] || DEFAULT_PARITY
|
61
|
+
|
62
|
+
@trans = SerialPort.new( @args[:port], baud, data_bits, stop_bits, parity )
|
63
|
+
|
64
|
+
got = login()
|
65
|
+
yield self if block_given?
|
66
|
+
trans_start_netconf( got )
|
67
|
+
|
68
|
+
self
|
69
|
+
end
|
70
|
+
|
71
|
+
def trans_receive_hello
|
72
|
+
hello_str = trans_receive()
|
73
|
+
so_xml = hello_str.index("\n") + 1
|
74
|
+
hello_str.slice!(0, so_xml)
|
75
|
+
hello_str
|
76
|
+
end
|
77
|
+
|
78
|
+
def trans_send_hello
|
79
|
+
nil
|
80
|
+
end
|
81
|
+
|
82
|
+
def trans_close
|
83
|
+
@trans.write Netconf::RPC::MSG_CLOSE_SESSION
|
84
|
+
@trans.close
|
85
|
+
end
|
86
|
+
|
87
|
+
def trans_send( cmd_str )
|
88
|
+
@trans.write( cmd_str )
|
89
|
+
end
|
90
|
+
|
91
|
+
def trans_receive
|
92
|
+
got = waitfor( Netconf::RPC::MSG_END_RE )
|
93
|
+
msg_end = got.rindex( Netconf::RPC::MSG_END )
|
94
|
+
got[msg_end .. -1] = ''
|
95
|
+
got
|
96
|
+
end
|
97
|
+
|
98
|
+
def puts( str = nil )
|
99
|
+
@trans.puts str
|
100
|
+
end
|
101
|
+
|
102
|
+
def waitfor( this_re = nil )
|
103
|
+
on_re = this_re || @args[:prompt]
|
104
|
+
|
105
|
+
time_out = @trans_timeout
|
106
|
+
wait_io = @trans_waitio
|
107
|
+
|
108
|
+
time_out = nil if time_out == false
|
109
|
+
done = false
|
110
|
+
rx_buf = ''
|
111
|
+
|
112
|
+
until( rx_buf.match( on_re ) and not IO::select( [@trans], nil, nil, wait_io ) )
|
113
|
+
|
114
|
+
unless IO::select( [@trans], nil, nil, time_out )
|
115
|
+
raise TimeoutError, "Netconf IO timed out while waiting for more data"
|
116
|
+
end
|
117
|
+
|
118
|
+
begin
|
119
|
+
|
120
|
+
rx_some = @trans.readpartial( DEFAULT_RDBLKSZ )
|
121
|
+
|
122
|
+
rx_buf += rx_some
|
123
|
+
break if rx_buf.match( on_re )
|
124
|
+
|
125
|
+
rescue EOFError # End of file reached
|
126
|
+
rx_buf = nil if rx_buf == ''
|
127
|
+
break # out of outer 'until' loop
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
rx_buf
|
132
|
+
end
|
133
|
+
|
134
|
+
end # class: Serial
|
135
|
+
end # module: Netconf
|