netconf 0.2.4 → 0.2.5
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.
- data/examples/jnpr/edit-config-jnpr.rb +24 -12
- data/examples/jnpr/get-config-jnpr.rb +6 -3
- data/lib/net/netconf.rb +3 -5
- data/lib/net/netconf/ioproc.rb +88 -0
- data/lib/net/netconf/jnpr.rb +2 -1
- 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 +12 -12
- data/lib/net/netconf/jnpr/serial.rb +4 -6
- data/lib/net/netconf/jnpr/telnet.rb +3 -3
- data/lib/net/netconf/serial.rb +1 -5
- data/lib/net/netconf/telnet.rb +1 -1
- metadata +5 -3
- data/lib/net/netconf/localhost.rb +0 -9
@@ -2,21 +2,32 @@ require 'net/netconf/jnpr'
|
|
2
2
|
|
3
3
|
puts "NETCONF v#{Netconf::VERSION}"
|
4
4
|
|
5
|
-
login = { :target => '
|
5
|
+
login = { :target => 'ex4', :username => "jeremy", :password => "jeremy1" }
|
6
6
|
|
7
|
-
new_host_name = "
|
7
|
+
new_host_name = "ex4-abc"
|
8
8
|
|
9
9
|
puts "Connecting to device: #{login[:target]}"
|
10
10
|
|
11
11
|
Netconf::SSH.new( login ){ |dev|
|
12
12
|
puts "Connected!"
|
13
13
|
|
14
|
+
# when providing a collection of configuration,
|
15
|
+
# you need to include the <configuration> as the
|
16
|
+
# toplevel element
|
17
|
+
|
14
18
|
location = Nokogiri::XML::Builder.new{ |x|
|
15
|
-
x.
|
16
|
-
x.
|
17
|
-
x.
|
18
|
-
|
19
|
-
|
19
|
+
x.configuration {
|
20
|
+
x.system {
|
21
|
+
x.location {
|
22
|
+
x.building "Main Campus, D"
|
23
|
+
x.floor 22
|
24
|
+
x.rack 38
|
25
|
+
}
|
26
|
+
}
|
27
|
+
x.system {
|
28
|
+
x.services {
|
29
|
+
x.ftp;
|
30
|
+
}
|
20
31
|
}
|
21
32
|
}
|
22
33
|
}
|
@@ -24,7 +35,12 @@ Netconf::SSH.new( login ){ |dev|
|
|
24
35
|
begin
|
25
36
|
|
26
37
|
rsp = dev.rpc.lock_configuration
|
27
|
-
|
38
|
+
|
39
|
+
# --------------------------------------------------------------------
|
40
|
+
# configuration as PARAM
|
41
|
+
|
42
|
+
rsp = dev.rpc.load_configuration( location, :action => 'replace' )
|
43
|
+
|
28
44
|
# --------------------------------------------------------------------
|
29
45
|
# configuration as BLOCK
|
30
46
|
|
@@ -34,10 +50,6 @@ Netconf::SSH.new( login ){ |dev|
|
|
34
50
|
}
|
35
51
|
}
|
36
52
|
|
37
|
-
# --------------------------------------------------------------------
|
38
|
-
# configuration as PARAM
|
39
|
-
|
40
|
-
rsp = dev.rpc.load_configuration( location )
|
41
53
|
rpc = dev.rpc.check_configuration
|
42
54
|
rpc = dev.rpc.commit_configuration
|
43
55
|
rpc = dev.rpc.unlock_configuration
|
@@ -2,7 +2,7 @@ require 'net/netconf/jnpr' # note: including Juniper specific extension
|
|
2
2
|
|
3
3
|
puts "NETCONF v.#{Netconf::VERSION}"
|
4
4
|
|
5
|
-
login = { :target => '
|
5
|
+
login = { :target => 'ex4', :username => "jeremy", :password => "jeremy1" }
|
6
6
|
|
7
7
|
puts "Connecting to device: #{login[:target]}"
|
8
8
|
|
@@ -22,6 +22,7 @@ Netconf::SSH.new( login ){ |dev|
|
|
22
22
|
|
23
23
|
cfgsvc1_1 = dev.rpc.get_configuration{ |x|
|
24
24
|
x.system { x.services }
|
25
|
+
x.system { x.login }
|
25
26
|
}
|
26
27
|
|
27
28
|
cfgsvc1_1.xpath('system/services/*').each{|s| puts s.name }
|
@@ -36,10 +37,12 @@ Netconf::SSH.new( login ){ |dev|
|
|
36
37
|
|
37
38
|
# ----------------------------------------------------------------------
|
38
39
|
# specifying a filter as a parameter to get_configuration
|
40
|
+
# you must wrap the config in a toplevel <configuration> element
|
39
41
|
|
40
|
-
filter = Nokogiri::XML::Builder.new{ |x|
|
42
|
+
filter = Nokogiri::XML::Builder.new{ |x| x.configuration {
|
41
43
|
x.system { x.services }
|
42
|
-
|
44
|
+
x.system { x.login }
|
45
|
+
}}
|
43
46
|
|
44
47
|
puts "Retrieved services by PARAM, as XML"
|
45
48
|
|
data/lib/net/netconf.rb
CHANGED
@@ -7,11 +7,9 @@ require 'net/netconf/transport'
|
|
7
7
|
require 'net/netconf/ssh'
|
8
8
|
|
9
9
|
module Netconf
|
10
|
-
VERSION = "0.2.
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
DEFAULT_OS_TYPE = :JUNOS
|
10
|
+
VERSION = "0.2.5"
|
11
|
+
NAMESPACE = "urn:ietf:params:xml:ns:netconf:base:1.0"
|
12
|
+
DEFAULT_OS_TYPE = :Junos
|
15
13
|
DEFAULT_TIMEOUT = 10
|
16
14
|
DEFAULT_WAITIO = 0
|
17
15
|
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
module Netconf
|
2
|
+
|
3
|
+
class IOProc < Netconf::Transport
|
4
|
+
|
5
|
+
DEFAULT_RDBLKSZ = (1024*1024)
|
6
|
+
|
7
|
+
attr_reader :args
|
8
|
+
|
9
|
+
def initialize( args_h = {}, &block )
|
10
|
+
os_type = args_h[:os_type] || Netconf::DEFAULT_OS_TYPE
|
11
|
+
|
12
|
+
@args = args_h.clone
|
13
|
+
|
14
|
+
# an OS specific implementation must exist to support this transport type
|
15
|
+
extend Netconf::const_get( os_type )::IOProc
|
16
|
+
|
17
|
+
@trans_timeout = @args[:timeout] || Netconf::DEFAULT_TIMEOUT
|
18
|
+
@trans_waitio = @args[:waitio] || Netconf::DEFAULT_WAITIO
|
19
|
+
|
20
|
+
super( &block )
|
21
|
+
end
|
22
|
+
|
23
|
+
# the OS specific transport must implement this method
|
24
|
+
def trans_open # :yield: self
|
25
|
+
raise "Unsupported IOProc"
|
26
|
+
end
|
27
|
+
|
28
|
+
def trans_receive_hello
|
29
|
+
trans_receive()
|
30
|
+
end
|
31
|
+
|
32
|
+
def trans_send_hello
|
33
|
+
nil
|
34
|
+
end
|
35
|
+
|
36
|
+
def trans_close
|
37
|
+
@trans.write Netconf::RPC::MSG_CLOSE_SESSION
|
38
|
+
@trans.close
|
39
|
+
end
|
40
|
+
|
41
|
+
def trans_send( cmd_str )
|
42
|
+
@trans.write( cmd_str )
|
43
|
+
end
|
44
|
+
|
45
|
+
def trans_receive
|
46
|
+
got = waitfor( Netconf::RPC::MSG_END_RE )
|
47
|
+
msg_end = got.rindex( Netconf::RPC::MSG_END )
|
48
|
+
got[msg_end .. -1] = ''
|
49
|
+
got
|
50
|
+
end
|
51
|
+
|
52
|
+
def puts( str = nil )
|
53
|
+
@trans.puts( str )
|
54
|
+
end
|
55
|
+
|
56
|
+
def waitfor( on_re )
|
57
|
+
|
58
|
+
time_out = @trans_timeout
|
59
|
+
wait_io = @trans_waitio
|
60
|
+
|
61
|
+
time_out = nil if time_out == false
|
62
|
+
done = false
|
63
|
+
rx_buf = ''
|
64
|
+
|
65
|
+
until( rx_buf.match( on_re ) and not IO::select( [@trans], nil, nil, wait_io ) )
|
66
|
+
|
67
|
+
unless IO::select( [@trans], nil, nil, time_out )
|
68
|
+
raise TimeoutError, "Netconf IO timed out while waiting for more data"
|
69
|
+
end
|
70
|
+
|
71
|
+
begin
|
72
|
+
|
73
|
+
rx_some = @trans.readpartial( DEFAULT_RDBLKSZ )
|
74
|
+
|
75
|
+
rx_buf += rx_some
|
76
|
+
break if rx_buf.match( on_re )
|
77
|
+
|
78
|
+
rescue EOFError # End of file reached
|
79
|
+
rx_buf = nil if rx_buf == ''
|
80
|
+
break # out of outer 'until' loop
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
rx_buf
|
85
|
+
end
|
86
|
+
|
87
|
+
end # class: IOProc
|
88
|
+
end # module: Netconf
|
data/lib/net/netconf/jnpr.rb
CHANGED
@@ -0,0 +1,104 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2012 Juniper Networks, Inc.
|
3
|
+
# All Rights Reserved
|
4
|
+
#
|
5
|
+
# JUNIPER PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
6
|
+
|
7
|
+
module Netconf
|
8
|
+
|
9
|
+
class JunosConfig
|
10
|
+
|
11
|
+
DELETE = { :delete => 'delete' }
|
12
|
+
REPLACE = { :replace => 'replace' }
|
13
|
+
|
14
|
+
attr_reader :doc
|
15
|
+
attr_reader :collection
|
16
|
+
|
17
|
+
def initialize( options )
|
18
|
+
@doc_ele = "configuration"
|
19
|
+
|
20
|
+
if options == :TOP
|
21
|
+
@doc = Nokogiri::XML("<#{@doc_ele}/>")
|
22
|
+
return
|
23
|
+
end
|
24
|
+
|
25
|
+
unless options[:TOP].nil?
|
26
|
+
@doc_ele = options[:TOP]
|
27
|
+
@doc = Nokogiri::XML("<#{@doc_ele}/>")
|
28
|
+
return
|
29
|
+
end
|
30
|
+
|
31
|
+
unless defined? @collection
|
32
|
+
edit = "#{@doc_ele}/#{options[:edit].strip}"
|
33
|
+
@at_name = edit[edit.rindex('/') + 1, edit.length]
|
34
|
+
@edit_path = edit
|
35
|
+
@collection = Hash.new
|
36
|
+
@to_xml = options[:build]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def <<( obj )
|
41
|
+
if defined? @collection
|
42
|
+
@collection[obj[:name]] = obj
|
43
|
+
elsif defined? @doc
|
44
|
+
obj.build_xml( @doc )
|
45
|
+
else
|
46
|
+
# TBD:error
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def build_xml( ng_xml, &block )
|
51
|
+
at_ele = ng_xml.at( @edit_path )
|
52
|
+
if at_ele.nil?
|
53
|
+
# no xpath anchor point, so we need to create it
|
54
|
+
at_ele = edit_path( ng_xml, @edit_path )
|
55
|
+
end
|
56
|
+
build_proc = (block_given?) ? block : @to_xml
|
57
|
+
|
58
|
+
@collection.each do |k,v|
|
59
|
+
with( at_ele ) do |e|
|
60
|
+
build_proc.call( e, v )
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def edit_path( ng_xml, xpath )
|
66
|
+
# junos configuration always begins with
|
67
|
+
# the 'configuration' element, so don't make
|
68
|
+
# the user enter it all the time
|
69
|
+
|
70
|
+
cfg_xpath = xpath
|
71
|
+
dot = ng_xml.at( cfg_xpath )
|
72
|
+
return dot if dot
|
73
|
+
|
74
|
+
# we need to determine how much of the xpath
|
75
|
+
# we need to create. walk down the xpath
|
76
|
+
# children to determine what exists and
|
77
|
+
# what needs to be added
|
78
|
+
|
79
|
+
xpath_a = cfg_xpath.split('/')
|
80
|
+
need_a = []
|
81
|
+
until xpath_a.empty? or dot
|
82
|
+
need_a.unshift xpath_a.pop
|
83
|
+
check_xpath = xpath_a.join('/')
|
84
|
+
dot = ng_xml.at( check_xpath )
|
85
|
+
end
|
86
|
+
|
87
|
+
# start at the deepest level of what
|
88
|
+
# actually exists and then start adding
|
89
|
+
# the children that were missing
|
90
|
+
|
91
|
+
dot = ng_xml.at(xpath_a.join('/'))
|
92
|
+
need_a.each do |ele|
|
93
|
+
dot = dot.add_child( Nokogiri::XML::Node.new( ele, ng_xml ))
|
94
|
+
end
|
95
|
+
return dot
|
96
|
+
end
|
97
|
+
|
98
|
+
def with( ng_xml, &block )
|
99
|
+
Nokogiri::XML::Builder.with( ng_xml, &block )
|
100
|
+
end
|
101
|
+
end
|
102
|
+
#-- class end
|
103
|
+
end
|
104
|
+
|
data/lib/net/netconf/jnpr/rpc.rb
CHANGED
@@ -14,7 +14,7 @@
|
|
14
14
|
|
15
15
|
module Netconf
|
16
16
|
module RPC
|
17
|
-
module
|
17
|
+
module Junos
|
18
18
|
|
19
19
|
def lock_configuration
|
20
20
|
lock( 'candidate' )
|
@@ -55,9 +55,8 @@ module Netconf
|
|
55
55
|
yield( xml )
|
56
56
|
}}
|
57
57
|
elsif filter
|
58
|
-
|
59
|
-
|
60
|
-
rpc.first_element_child << f_node
|
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
|
61
60
|
end
|
62
61
|
|
63
62
|
@trans.rpc_exec( rpc )
|
@@ -69,7 +68,7 @@ module Netconf
|
|
69
68
|
|
70
69
|
# default format is XML
|
71
70
|
attrs = { :format => 'xml' }
|
72
|
-
|
71
|
+
|
73
72
|
while arg = args.shift
|
74
73
|
case arg.class.to_s
|
75
74
|
when /^Nokogiri/
|
@@ -78,7 +77,7 @@ module Netconf
|
|
78
77
|
when Nokogiri::XML::Document then arg.root
|
79
78
|
else arg
|
80
79
|
end
|
81
|
-
when 'Hash' then attrs
|
80
|
+
when 'Hash' then attrs.merge! arg
|
82
81
|
when 'Array' then config = arg.join("\n")
|
83
82
|
when 'String' then config = arg
|
84
83
|
end
|
@@ -93,8 +92,8 @@ module Netconf
|
|
93
92
|
toplevel = 'configuration-text'
|
94
93
|
when 'xml'
|
95
94
|
toplevel = 'configuration'
|
96
|
-
end
|
97
|
-
|
95
|
+
end
|
96
|
+
|
98
97
|
rpc = Nokogiri::XML('<rpc><load-configuration/></rpc>').root
|
99
98
|
ld_cfg = rpc.first_element_child
|
100
99
|
Netconf::RPC.add_attributes( ld_cfg, attrs ) if attrs
|
@@ -112,14 +111,15 @@ module Netconf
|
|
112
111
|
end
|
113
112
|
|
114
113
|
if config
|
115
|
-
c_node = Nokogiri::XML::Node.new( toplevel, rpc )
|
116
114
|
if attrs[:format] == 'xml'
|
117
|
-
|
115
|
+
# config assumes toplevel = <configuration> given
|
116
|
+
ld_cfg << config.dup # duplicate the config so as to not distrupt it
|
118
117
|
else
|
119
|
-
# config is stringy, so just add it as the text node
|
118
|
+
# config is stringy, so just add it as the text node
|
119
|
+
c_node = Nokogiri::XML::Node.new( toplevel, rpc )
|
120
120
|
c_node.content = config
|
121
|
+
ld_cfg << c_node
|
121
122
|
end
|
122
|
-
ld_cfg << c_node
|
123
123
|
end
|
124
124
|
|
125
125
|
# set a specific exception class on this RPC so it can be
|
@@ -3,15 +3,13 @@ require 'net/netconf/serial'
|
|
3
3
|
require 'net/netconf/jnpr'
|
4
4
|
|
5
5
|
module Netconf
|
6
|
-
module
|
7
|
-
module
|
8
|
-
|
6
|
+
module Junos
|
7
|
+
module TransSerial
|
9
8
|
def trans_start_netconf( last_console )
|
10
9
|
last_console.match(/[^%]\s+$/)
|
11
|
-
netconf_cmd = ($1 == '%') ? Netconf::
|
10
|
+
netconf_cmd = ($1 == '%') ? Netconf::Junos::NETCONF_SHELL : Netconf::Junos::NETCONF_CLI
|
12
11
|
puts netconf_cmd
|
13
|
-
end
|
14
|
-
|
12
|
+
end
|
15
13
|
end
|
16
14
|
end
|
17
15
|
end
|
@@ -3,14 +3,14 @@ require 'net/netconf/telnet'
|
|
3
3
|
require 'net/netconf/jnpr'
|
4
4
|
|
5
5
|
module Netconf
|
6
|
-
module
|
7
|
-
module
|
6
|
+
module Junos
|
7
|
+
module TransTelnet
|
8
8
|
|
9
9
|
def trans_login
|
10
10
|
l_rsp = @trans.login( @args[:username], @args[:password] )
|
11
11
|
# @@@/JLS: need to rescue the timeout ... ???
|
12
12
|
l_rsp.match("([>%])\s+$")
|
13
|
-
@exec_netconf = ($1 == '%') ? Netconf::
|
13
|
+
@exec_netconf = ($1 == '%') ? Netconf::Junos::NETCONF_SHELL : Netconf::Junos::NETCONF_CLI
|
14
14
|
end
|
15
15
|
|
16
16
|
def trans_start_netconf
|
data/lib/net/netconf/serial.rb
CHANGED
@@ -26,7 +26,7 @@ module Netconf
|
|
26
26
|
# this must be provided! if the caller does not, this will
|
27
27
|
# throw a NameError exception.
|
28
28
|
|
29
|
-
extend Netconf::
|
29
|
+
extend Netconf::const_get( os_type )::TransSerial
|
30
30
|
|
31
31
|
@trans_timeout = @args[:timeout] || Netconf::DEFAULT_TIMEOUT
|
32
32
|
@trans_waitio = @args[:waitio] || Netconf::DEFAULT_WAITIO
|
@@ -86,7 +86,6 @@ module Netconf
|
|
86
86
|
|
87
87
|
def trans_send( cmd_str )
|
88
88
|
@trans.write( cmd_str )
|
89
|
-
@trans.fsync
|
90
89
|
end
|
91
90
|
|
92
91
|
def trans_receive
|
@@ -98,7 +97,6 @@ module Netconf
|
|
98
97
|
|
99
98
|
def puts( str = nil )
|
100
99
|
@trans.puts str
|
101
|
-
@trans.fsync
|
102
100
|
end
|
103
101
|
|
104
102
|
def waitfor( this_re = nil )
|
@@ -121,8 +119,6 @@ module Netconf
|
|
121
119
|
|
122
120
|
rx_some = @trans.readpartial( DEFAULT_RDBLKSZ )
|
123
121
|
|
124
|
-
$stdout.puts rx_some
|
125
|
-
|
126
122
|
rx_buf += rx_some
|
127
123
|
break if rx_buf.match( on_re )
|
128
124
|
|
data/lib/net/netconf/telnet.rb
CHANGED
@@ -11,7 +11,7 @@ module Netconf
|
|
11
11
|
# extend this instance with the capabilities of the specific console
|
12
12
|
# type; it needs to define #login and #start_netconf session
|
13
13
|
begin
|
14
|
-
extend Netconf::
|
14
|
+
extend Netconf::const_get( os_type )::TransTelnet
|
15
15
|
rescue NameError
|
16
16
|
# no extensions available ...
|
17
17
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: netconf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.5
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2013-01-
|
13
|
+
date: 2013-01-29 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: nokogiri
|
@@ -51,11 +51,13 @@ extensions: []
|
|
51
51
|
extra_rdoc_files: []
|
52
52
|
files:
|
53
53
|
- lib/net/netconf/exception.rb
|
54
|
+
- lib/net/netconf/ioproc.rb
|
55
|
+
- lib/net/netconf/jnpr/ioproc.rb
|
56
|
+
- lib/net/netconf/jnpr/junos_config.rb
|
54
57
|
- lib/net/netconf/jnpr/rpc.rb
|
55
58
|
- lib/net/netconf/jnpr/serial.rb
|
56
59
|
- lib/net/netconf/jnpr/telnet.rb
|
57
60
|
- lib/net/netconf/jnpr.rb
|
58
|
-
- lib/net/netconf/localhost.rb
|
59
61
|
- lib/net/netconf/rpc.rb
|
60
62
|
- lib/net/netconf/rpc_std.rb
|
61
63
|
- lib/net/netconf/serial.rb
|