net-netconf 0.4.1 → 0.4.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/net/netconf.rb +37 -0
- data/lib/net/netconf/exception.rb +11 -11
- data/lib/net/netconf/ioproc.rb +24 -54
- data/lib/net/netconf/jnpr.rb +1 -1
- data/lib/net/netconf/jnpr/ioproc.rb +2 -2
- data/lib/net/netconf/jnpr/junos_config.rb +1 -1
- data/lib/net/netconf/jnpr/rpc.rb +87 -88
- data/lib/net/netconf/jnpr/serial.rb +4 -4
- data/lib/net/netconf/jnpr/ssh.rb +10 -10
- data/lib/net/netconf/jnpr/telnet.rb +7 -7
- data/lib/net/netconf/rpc.rb +31 -31
- data/lib/net/netconf/rpc_std.rb +19 -23
- data/lib/net/netconf/serial.rb +40 -71
- data/lib/net/netconf/ssh.rb +45 -44
- data/lib/net/netconf/telnet.rb +27 -30
- data/lib/net/netconf/transport.rb +23 -30
- data/lib/net/netconf/version.rb +1 -1
- metadata +3 -2
@@ -3,13 +3,13 @@ require 'net/netconf/serial'
|
|
3
3
|
require 'net/netconf/jnpr'
|
4
4
|
|
5
5
|
module Netconf
|
6
|
-
module Junos
|
7
|
-
module TransSerial
|
6
|
+
module Junos
|
7
|
+
module TransSerial
|
8
8
|
def trans_start_netconf( last_console )
|
9
9
|
last_console.match(/[^%]\s+$/)
|
10
10
|
netconf_cmd = ($1 == '%') ? Netconf::Junos::NETCONF_SHELL : Netconf::Junos::NETCONF_CLI
|
11
11
|
puts netconf_cmd
|
12
|
-
end
|
13
|
-
end
|
12
|
+
end
|
13
|
+
end
|
14
14
|
end
|
15
15
|
end
|
data/lib/net/netconf/jnpr/ssh.rb
CHANGED
@@ -2,26 +2,26 @@ require 'net/netconf'
|
|
2
2
|
require 'net/netconf/jnpr'
|
3
3
|
|
4
4
|
module Netconf
|
5
|
-
module Junos
|
5
|
+
module Junos
|
6
6
|
module TransSSH
|
7
|
-
|
7
|
+
|
8
8
|
##
|
9
9
|
## this is used to handle the case where NETCONF (port 830) is disabled. We can still access
|
10
10
|
## the NETCONF subsystem from the CLI using a hidden command 'netconf'
|
11
11
|
##
|
12
|
-
|
13
|
-
def trans_on_connect_refused( start_args )
|
14
|
-
start_args[:port] = 22
|
12
|
+
|
13
|
+
def trans_on_connect_refused( start_args )
|
14
|
+
start_args[:port] = 22
|
15
15
|
@trans[:conn] = Net::SSH.start( @args[:target], @args[:username], start_args )
|
16
16
|
do_once = true
|
17
|
-
@trans[:conn].exec( NETCONF_CLI ) do |chan, success|
|
17
|
+
@trans[:conn].exec( NETCONF_CLI ) do |chan, success|
|
18
18
|
@trans[:chan] = chan
|
19
19
|
do_once = false
|
20
20
|
end
|
21
|
-
@trans[:conn].loop { do_once }
|
21
|
+
@trans[:conn].loop { do_once }
|
22
22
|
@trans[:chan]
|
23
23
|
end
|
24
|
-
|
24
|
+
|
25
25
|
end
|
26
|
-
end
|
27
|
-
end
|
26
|
+
end
|
27
|
+
end
|
@@ -3,21 +3,21 @@ require 'net/netconf/telnet'
|
|
3
3
|
require 'net/netconf/jnpr'
|
4
4
|
|
5
5
|
module Netconf
|
6
|
-
module Junos
|
6
|
+
module Junos
|
7
7
|
module TransTelnet
|
8
|
-
|
8
|
+
|
9
9
|
def trans_login
|
10
10
|
l_rsp = @trans.login( @args[:username], @args[:password] )
|
11
|
-
# @@@/JLS: need to rescue the timeout ... ???
|
11
|
+
# @@@/JLS: need to rescue the timeout ... ???
|
12
12
|
l_rsp.match("([>%])\s+$")
|
13
13
|
@exec_netconf = ($1 == '%') ? Netconf::Junos::NETCONF_SHELL : Netconf::Junos::NETCONF_CLI
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
16
|
def trans_start_netconf
|
17
17
|
@trans.puts @exec_netconf
|
18
18
|
end
|
19
|
-
|
19
|
+
|
20
20
|
end
|
21
|
-
end
|
22
|
-
end
|
21
|
+
end
|
22
|
+
end
|
23
23
|
|
data/lib/net/netconf/rpc.rb
CHANGED
@@ -1,32 +1,32 @@
|
|
1
1
|
require 'net/netconf/rpc_std'
|
2
2
|
|
3
|
-
module Netconf
|
4
|
-
module RPC
|
5
|
-
|
3
|
+
module Netconf
|
4
|
+
module RPC
|
5
|
+
|
6
6
|
def RPC.add_attributes( ele_nx, attr_h )
|
7
|
-
attr_h.each{ |k,v| ele_nx[k] = v }
|
7
|
+
attr_h.each{ |k,v| ele_nx[k] = v }
|
8
8
|
end
|
9
|
-
|
9
|
+
|
10
10
|
def RPC.set_exception( rpc_nx, exception )
|
11
11
|
rpc_nx.instance_variable_set(:@netconf_exception, exception )
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
14
|
def RPC.get_exception( rpc_nx )
|
15
15
|
rpc_nx.instance_variable_get(:@netconf_exception) || Netconf::RpcError
|
16
16
|
end
|
17
|
-
|
18
|
-
module Builder
|
17
|
+
|
18
|
+
module Builder
|
19
19
|
# autogenerate an <rpc>, converting underscores (_)
|
20
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
|
21
|
+
|
22
|
+
def Builder.method_missing( method, params = nil, attrs = nil )
|
23
|
+
|
24
|
+
rpc_name = method.to_s.tr('_','-').to_sym
|
25
25
|
|
26
26
|
if params
|
27
27
|
# build the XML starting at <rpc>, envelope the <method> toplevel element,
|
28
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
|
29
|
+
# without a value should simply be set to true
|
30
30
|
rpc_nx = Nokogiri::XML::Builder.new { |xml|
|
31
31
|
xml.rpc { xml.send( rpc_name ) {
|
32
32
|
params.each{ |k,v|
|
@@ -36,36 +36,36 @@ module Netconf
|
|
36
36
|
}}
|
37
37
|
}.doc.root
|
38
38
|
else
|
39
|
-
# -- no params
|
39
|
+
# -- no params
|
40
40
|
rpc_nx = Nokogiri::XML("<rpc><#{rpc_name}/></rpc>").root
|
41
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
|
-
|
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
46
|
# return the rpc command
|
47
|
-
rpc_nx
|
48
|
-
end # def: method-missing?
|
49
|
-
|
50
|
-
end # module: Builder
|
51
|
-
|
47
|
+
rpc_nx
|
48
|
+
end # def: method-missing?
|
49
|
+
|
50
|
+
end # module: Builder
|
51
|
+
|
52
52
|
class Executor
|
53
53
|
include Netconf::RPC::Standard
|
54
|
-
|
54
|
+
|
55
55
|
def initialize( trans, os_type )
|
56
56
|
@trans = trans
|
57
|
-
begin
|
58
|
-
extend Netconf::RPC::const_get( os_type )
|
57
|
+
begin
|
58
|
+
extend Netconf::RPC::const_get( os_type )
|
59
59
|
rescue NameError
|
60
60
|
# no extensions available ...
|
61
|
-
end
|
61
|
+
end
|
62
62
|
end
|
63
|
-
|
63
|
+
|
64
64
|
def method_missing( method, params = nil, attrs = nil )
|
65
65
|
@trans.rpc_exec( Netconf::RPC::Builder.send( method, params, attrs ))
|
66
|
-
end
|
66
|
+
end
|
67
67
|
end # class: Executor
|
68
|
-
|
68
|
+
|
69
69
|
end # module: RPC
|
70
70
|
end # module: Netconf
|
71
|
-
|
71
|
+
|
data/lib/net/netconf/rpc_std.rb
CHANGED
@@ -13,11 +13,9 @@ module Netconf
|
|
13
13
|
EOM
|
14
14
|
|
15
15
|
module Standard
|
16
|
-
|
17
16
|
def lock( target )
|
18
|
-
|
19
|
-
|
20
|
-
@trans.rpc_exec( rpc )
|
17
|
+
run_valid_or_lock_rpc "<rpc><lock><target><#{target}/></target></lock></rpc>",
|
18
|
+
Netconf::LockError
|
21
19
|
end
|
22
20
|
|
23
21
|
def unlock( target )
|
@@ -26,8 +24,13 @@ EOM
|
|
26
24
|
end
|
27
25
|
|
28
26
|
def validate( source )
|
29
|
-
|
30
|
-
|
27
|
+
run_valid_or_lock_rpc "<rpc><validate><source><#{source}/></source></validate></rpc>",
|
28
|
+
Netconf::ValidateError
|
29
|
+
end
|
30
|
+
|
31
|
+
def run_valid_or_lock_rpc(rpc_string, error_type)
|
32
|
+
rpc = Nokogiri::XML(rpc_string).root
|
33
|
+
Netconf::RPC.set_exception( rpc, error_type )
|
31
34
|
@trans.rpc_exec( rpc )
|
32
35
|
end
|
33
36
|
|
@@ -42,11 +45,7 @@ EOM
|
|
42
45
|
@trans.rpc_exec( rpc )
|
43
46
|
end
|
44
47
|
|
45
|
-
def
|
46
|
-
|
47
|
-
source = 'running' # default source is 'running'
|
48
|
-
filter = nil # no filter by default
|
49
|
-
|
48
|
+
def process_args(args)
|
50
49
|
while arg = args.shift
|
51
50
|
case arg.class.to_s
|
52
51
|
when /^Nokogiri/
|
@@ -59,6 +58,14 @@ EOM
|
|
59
58
|
when 'String' then source = arg
|
60
59
|
end
|
61
60
|
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def get_config( *args ) # :yeield: filter_builder
|
64
|
+
|
65
|
+
source = 'running' # default source is 'running'
|
66
|
+
filter = nil # no filter by default
|
67
|
+
|
68
|
+
arg = process_args(args)
|
62
69
|
|
63
70
|
rpc = Nokogiri::XML("<rpc><get-config><source><#{source}/></source></get-config></rpc>").root
|
64
71
|
|
@@ -87,18 +94,7 @@ EOM
|
|
87
94
|
config = nil
|
88
95
|
options = {}
|
89
96
|
|
90
|
-
|
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
|
97
|
+
arg = process_args(args)
|
102
98
|
|
103
99
|
toplevel = options[:toplevel] if options[:toplevel]
|
104
100
|
|
data/lib/net/netconf/serial.rb
CHANGED
@@ -1,41 +1,41 @@
|
|
1
1
|
require 'serialport'
|
2
2
|
|
3
3
|
module Netconf
|
4
|
-
|
4
|
+
|
5
5
|
class Serial < Netconf::Transport
|
6
|
-
|
6
|
+
|
7
7
|
DEFAULT_BAUD = 9600
|
8
8
|
DEFAULT_DATABITS = 8
|
9
9
|
DEFAULT_STOPBITS = 1
|
10
10
|
DEFAULT_PARITY = SerialPort::NONE
|
11
11
|
DEFAULT_RDBLKSZ = (1024*1024)
|
12
|
-
|
12
|
+
|
13
13
|
attr_reader :args
|
14
|
-
|
14
|
+
|
15
15
|
def initialize( args_h, &block )
|
16
16
|
os_type = args_h[:os_type] || Netconf::DEFAULT_OS_TYPE
|
17
|
-
|
17
|
+
|
18
18
|
raise Netconf::InitError, "Missing 'port' param" unless args_h[:port]
|
19
19
|
raise Netconf::InitError, "Missing 'username' param" unless args_h[:username]
|
20
|
-
|
20
|
+
|
21
21
|
@args = args_h.clone
|
22
22
|
@args[:prompt] ||= /([%>])\s+$/
|
23
|
-
|
23
|
+
|
24
24
|
# extend this instance with the capabilities of the specific console
|
25
25
|
# type; it needs to define #trans_start_netconf session
|
26
|
-
# this must be provided! if the caller does not, this will
|
26
|
+
# this must be provided! if the caller does not, this will
|
27
27
|
# throw a NameError exception.
|
28
|
-
|
29
|
-
extend Netconf::const_get( os_type )::TransSerial
|
30
|
-
|
28
|
+
|
29
|
+
extend Netconf::const_get( os_type )::TransSerial
|
30
|
+
|
31
31
|
@trans_timeout = @args[:timeout] || Netconf::DEFAULT_TIMEOUT
|
32
32
|
@trans_waitio = @args[:waitio] || Netconf::DEFAULT_WAITIO
|
33
33
|
|
34
|
-
super( &block )
|
35
|
-
end
|
36
|
-
|
34
|
+
super( &block )
|
35
|
+
end
|
36
|
+
|
37
37
|
def login
|
38
|
-
|
38
|
+
|
39
39
|
begin
|
40
40
|
puts
|
41
41
|
waitfor(/ogin:/)
|
@@ -43,93 +43,62 @@ module Netconf
|
|
43
43
|
puts
|
44
44
|
waitfor(/ogin:/)
|
45
45
|
end
|
46
|
-
|
46
|
+
|
47
47
|
puts @args[:username]
|
48
|
-
|
48
|
+
|
49
49
|
waitfor(/assword:/)
|
50
50
|
puts @args[:password]
|
51
|
-
|
51
|
+
|
52
52
|
waitfor( @args[:prompt] )
|
53
53
|
end
|
54
|
-
|
54
|
+
|
55
55
|
def trans_open # :yield: self
|
56
|
-
|
56
|
+
|
57
57
|
baud = @args[:speed] || DEFAULT_BAUD
|
58
58
|
data_bits = @args[:bits] || DEFAULT_DATABITS
|
59
59
|
stop_bits = @args[:stop] || DEFAULT_STOPBITS
|
60
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
|
-
|
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
68
|
self
|
69
69
|
end
|
70
|
-
|
70
|
+
|
71
71
|
def trans_receive_hello
|
72
72
|
hello_str = trans_receive()
|
73
73
|
so_xml = hello_str.index("\n") + 1
|
74
74
|
hello_str.slice!(0, so_xml)
|
75
75
|
hello_str
|
76
76
|
end
|
77
|
-
|
77
|
+
|
78
78
|
def trans_send_hello
|
79
79
|
nil
|
80
80
|
end
|
81
|
-
|
81
|
+
|
82
82
|
def trans_close
|
83
83
|
@trans.write Netconf::RPC::MSG_CLOSE_SESSION
|
84
84
|
@trans.close
|
85
85
|
end
|
86
|
-
|
86
|
+
|
87
87
|
def trans_send( cmd_str )
|
88
88
|
@trans.write( cmd_str )
|
89
89
|
end
|
90
|
-
|
90
|
+
|
91
91
|
def trans_receive
|
92
|
-
|
93
|
-
msg_end = got.rindex( Netconf::RPC::MSG_END )
|
94
|
-
got[msg_end .. -1] = ''
|
95
|
-
got
|
92
|
+
Netconf.trans_receive
|
96
93
|
end
|
97
|
-
|
94
|
+
|
98
95
|
def puts( str = nil )
|
99
|
-
@trans.puts str
|
96
|
+
@trans.puts str
|
100
97
|
end
|
101
|
-
|
102
|
-
def waitfor( this_re = nil )
|
103
|
-
on_re
|
104
|
-
|
105
|
-
|
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
|
-
|
98
|
+
|
99
|
+
def waitfor( this_re = nil )
|
100
|
+
Netconf.waitfor(on_re)
|
101
|
+
end
|
102
|
+
|
134
103
|
end # class: Serial
|
135
104
|
end # module: Netconf
|
data/lib/net/netconf/ssh.rb
CHANGED
@@ -1,94 +1,95 @@
|
|
1
1
|
require 'net/ssh'
|
2
|
+
require 'net/netconf/ssh'
|
2
3
|
|
3
|
-
module Netconf
|
4
|
+
module Netconf
|
4
5
|
class SSH < Netconf::Transport
|
5
|
-
|
6
6
|
NETCONF_PORT = 830
|
7
|
-
NETCONF_SUBSYSTEM = 'netconf'
|
8
|
-
|
9
|
-
def initialize(
|
7
|
+
NETCONF_SUBSYSTEM = 'netconf'
|
8
|
+
|
9
|
+
def initialize(args_h, &block)
|
10
10
|
@args = args_h.clone
|
11
11
|
@args[:os_type] = args_h[:os_type] || Netconf::DEFAULT_OS_TYPE
|
12
|
-
|
12
|
+
|
13
13
|
# extend this instance with the capabilities of the specific os_type
|
14
14
|
begin
|
15
|
-
extend Netconf
|
15
|
+
extend Netconf.const_get(@args[:os_type]).TransSSH
|
16
16
|
rescue NameError
|
17
17
|
# no extensions available ...
|
18
|
-
end
|
19
|
-
|
20
|
-
@trans =
|
21
|
-
super(
|
18
|
+
end
|
19
|
+
|
20
|
+
@trans = {}
|
21
|
+
super(&block)
|
22
22
|
end
|
23
|
-
|
24
|
-
def trans_open(
|
25
|
-
# open a connection to the NETCONF subsystem
|
26
|
-
start_args =
|
23
|
+
|
24
|
+
def trans_open(&block)
|
25
|
+
# open a connection to the NETCONF subsystem
|
26
|
+
start_args = {}
|
27
27
|
start_args[:password] ||= @args[:password]
|
28
28
|
start_args[:passphrase] = @args[:passphrase] || nil
|
29
29
|
start_args[:port] = @args[:port] || NETCONF_PORT
|
30
30
|
start_args.merge!(@args[:ssh_args]) if @args[:ssh_args]
|
31
|
-
|
31
|
+
|
32
32
|
begin
|
33
|
-
@trans[:conn] = Net::SSH.start(
|
34
|
-
@trans[:chan] = @trans[:conn].open_channel
|
33
|
+
@trans[:conn] = Net::SSH.start(@args[:target], @args[:username], start_args)
|
34
|
+
@trans[:chan] = @trans[:conn].open_channel do |ch|
|
35
|
+
ch.subsystem(NETCONF_SUBSYSTEM)
|
36
|
+
end
|
35
37
|
rescue Errno::ECONNREFUSED => e
|
36
38
|
if self.respond_to? 'trans_on_connect_refused'
|
37
|
-
return trans_on_connect_refused(
|
39
|
+
return trans_on_connect_refused(start_args)
|
38
40
|
end
|
39
41
|
return nil
|
40
42
|
end
|
41
43
|
@trans[:chan]
|
42
44
|
end
|
43
|
-
|
44
|
-
def trans_close
|
45
|
+
|
46
|
+
def trans_close
|
45
47
|
@trans[:chan].close if @trans[:chan]
|
46
48
|
@trans[:conn].close if @trans[:conn]
|
47
49
|
end
|
48
|
-
|
50
|
+
|
49
51
|
def trans_receive
|
50
52
|
@trans[:rx_buf] = ''
|
51
53
|
@trans[:more] = true
|
52
|
-
|
54
|
+
|
53
55
|
# collect the response data as it comes back ...
|
54
56
|
# the "on" functions must be set before calling
|
55
57
|
# the #loop method
|
56
|
-
|
57
|
-
@trans[:chan].on_data do |
|
58
|
-
if data.include?(
|
59
|
-
data.slice!(
|
58
|
+
|
59
|
+
@trans[:chan].on_data do |_ch, data|
|
60
|
+
if data.include?(RPC::MSG_END)
|
61
|
+
data.slice!(RPC::MSG_END)
|
60
62
|
@trans[:rx_buf] << data unless data.empty?
|
61
63
|
@trans[:more] = false
|
62
64
|
else
|
63
65
|
@trans[:rx_buf] << data
|
64
66
|
end
|
65
67
|
end
|
66
|
-
|
67
|
-
# ... if there are errors ...
|
68
|
-
@trans[:chan].on_extended_data do |
|
68
|
+
|
69
|
+
# ... if there are errors ...
|
70
|
+
@trans[:chan].on_extended_data do |_ch, _type, data|
|
69
71
|
@trans[:rx_err] = data
|
70
72
|
@trans[:more] = false
|
71
73
|
end
|
72
|
-
|
74
|
+
|
73
75
|
# the #loop method is what actually performs
|
74
76
|
# ssh event processing ...
|
75
|
-
|
76
|
-
@trans[:conn].loop { @trans[:more] }
|
77
|
-
|
78
|
-
|
77
|
+
|
78
|
+
@trans[:conn].loop { @trans[:more] }
|
79
|
+
|
80
|
+
@trans[:rx_buf]
|
79
81
|
end
|
80
|
-
|
81
|
-
def trans_send(
|
82
|
-
@trans[:chan].send_data(
|
82
|
+
|
83
|
+
def trans_send(cmd_str)
|
84
|
+
@trans[:chan].send_data(cmd_str)
|
83
85
|
end
|
84
|
-
|
86
|
+
|
85
87
|
# accessor to create an Net::SCP object so the caller can perform
|
86
88
|
# secure-copy operations (see Net::SCP) for details
|
87
89
|
def scp
|
88
|
-
@scp ||= Net::SCP.start(
|
90
|
+
@scp ||= Net::SCP.start(@args[:target],
|
91
|
+
@args[:username],
|
92
|
+
password: @args[:password])
|
89
93
|
end
|
90
|
-
|
91
94
|
end # class: SSH
|
92
|
-
end #module: Netconf
|
93
|
-
|
94
|
-
require 'net/netconf/ssh'
|
95
|
+
end # module: Netconf
|