net-netconf 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,49 @@
1
+ require 'net/netconf'
2
+
3
+ puts "NETCONF v.#{Netconf::VERSION}"
4
+
5
+ login = { :target => 'vsrx', :username => "jeremy", :password => "jeremy1" }
6
+
7
+ puts "Connecting to device: #{login[:target]}"
8
+
9
+ Netconf::SSH.new( login ){ |dev|
10
+ puts "Connected."
11
+
12
+ # ----------------------------------------------------------------------
13
+ # retrieve the full config. Default source is 'running'
14
+ # Alternatively you can pass the source name as a string parameter
15
+ # to #get_config
16
+
17
+ puts "Retrieving full config, please wait ... "
18
+ cfgall = dev.rpc.get_config
19
+ puts "Showing 'system' hierarchy ..."
20
+ puts cfgall.xpath('configuration/system') # JUNOS toplevel config element is <configuration>
21
+
22
+ # ----------------------------------------------------------------------
23
+ # specifying a filter as a block to get_config
24
+
25
+ cfgsvc1 = dev.rpc.get_config{ |x|
26
+ x.configuration { x.system { x.services }}
27
+ }
28
+
29
+ puts "Retrieved services as BLOCK:"
30
+ cfgsvc1.xpath('//services/*').each{|s| puts s.name }
31
+
32
+ # ----------------------------------------------------------------------
33
+ # specifying a filter as a parameter to get_config
34
+
35
+ filter = Nokogiri::XML::Builder.new{ |x|
36
+ x.configuration { x.system { x.services }}
37
+ }
38
+
39
+ cfgsvc2 = dev.rpc.get_config( filter )
40
+ puts "Retrieved services as PARAM:"
41
+ cfgsvc2.xpath('//services/*').each{|s| puts s.name }
42
+
43
+ cfgsvc3 = dev.rpc.get_config( filter )
44
+ puts "Retrieved services as PARAM, re-used filter"
45
+ cfgsvc3.xpath('//services/*').each{|s| puts s.name }
46
+ }
47
+
48
+
49
+
@@ -0,0 +1,27 @@
1
+ require 'net/netconf/jnpr/serial'
2
+
3
+ puts "NETCONF v.#{Netconf::VERSION}"
4
+
5
+ login = {
6
+ :port => '/dev/ttyS4',
7
+ :username => "root", :password => "juniper1"
8
+ }
9
+
10
+ # we want to mount the USB drive, so we need to explicity
11
+ # do something special when opening the serial console ...
12
+ # therefore, we can *NOT* pass a block directly to new()
13
+
14
+ dev = Netconf::Serial.new( login )
15
+ dev.open { |con|
16
+ # login has occurred successfully
17
+
18
+ con.puts 'mount_msdosfs /dev/da1s1 /mnt'
19
+
20
+ # netconf will be started once block completes
21
+ }
22
+
23
+ inv = dev.rpc.get_chassis_inventory
24
+
25
+ dev.close
26
+
27
+
@@ -0,0 +1,25 @@
1
+ require 'net/netconf/jnpr/serial'
2
+
3
+ puts "NETCONF v.#{Netconf::VERSION}"
4
+
5
+ serial_port = '/dev/ttyS4'
6
+
7
+ login = { :port => serial_port,
8
+ :username => "jeremy", :password => "jeremy1" }
9
+
10
+ puts "Connecting to SERIAL: #{serial_port} ... please wait."
11
+
12
+ Netconf::Serial.new( login ){ |dev|
13
+
14
+ puts "Connected."
15
+ puts "Nabbing Inventory ..."
16
+
17
+ inv = dev.rpc.get_chassis_inventory
18
+
19
+ puts "Chassis: " + inv.xpath('chassis/description').text
20
+ puts "Chassis Serial-Number: " + inv.xpath('chassis/serial-number').text
21
+
22
+ }
23
+
24
+
25
+
@@ -0,0 +1,14 @@
1
+ require 'net/netconf/jnpr/telnet'
2
+
3
+ puts "NETCONF v#{Netconf::VERSION}"
4
+
5
+ login = { :target => 'vsrx', :username => "jeremy", :password => "jeremy1" }
6
+
7
+ Netconf::Telnet.new( login ){ |dev|
8
+ inv = dev.rpc.get_chassis_inventory
9
+ puts "Chassis: " + inv.xpath('chassis/description').text
10
+ puts "Chassis Serial-Number: " + inv.xpath('chassis/serial-number').text
11
+
12
+ }
13
+
14
+
@@ -0,0 +1,16 @@
1
+ require 'net/netconf'
2
+
3
+ puts "NETCONF v#{Netconf::VERSION}"
4
+
5
+ login = { :target => 'vsrx', :username => "jeremy", :password => "jeremy1" }
6
+
7
+ Netconf::SSH.new( login ){ |dev|
8
+
9
+ inv = dev.rpc.get_chassis_inventory
10
+
11
+ puts "Chassis: " + inv.xpath('chassis/description').text
12
+ puts "Chassis Serial-Number: " + inv.xpath('chassis/serial-number').text
13
+ }
14
+
15
+
16
+
@@ -0,0 +1,22 @@
1
+ require 'net/netconf'
2
+ require 'net/scp'
3
+
4
+ login = { :target => 'vsrx', :username => "jeremy", :password => "jeremy1" }
5
+
6
+ file_name = __FILE__
7
+
8
+ Netconf::SSH.new( login ){ |dev|
9
+
10
+ inv = dev.rpc.get_chassis_inventory
11
+
12
+ puts "Chassis: " + inv.xpath('chassis/description').text
13
+ puts "Chassis Serial-Number: " + inv.xpath('chassis/serial-number').text
14
+
15
+ puts "Copying file #{file_name} to home directory ..."
16
+ dev.scp.upload! file_name, file_name
17
+
18
+ puts "Copying latest config file from target to local machine ..."
19
+
20
+ dev.scp.download! "/config/juniper.conf.gz", "/var/tmp/config.gz"
21
+ }
22
+
@@ -0,0 +1,24 @@
1
+ require 'nokogiri'
2
+
3
+ require 'net/netconf/version'
4
+ require 'net/netconf/rpc'
5
+ require 'net/netconf/exception'
6
+ require 'net/netconf/transport'
7
+ require 'net/netconf/ssh'
8
+
9
+ module Netconf
10
+ NAMESPACE = "urn:ietf:params:xml:ns:netconf:base:1.0"
11
+ DEFAULT_OS_TYPE = :Junos
12
+ DEFAULT_TIMEOUT = 10
13
+ DEFAULT_WAITIO = 0
14
+
15
+ @raise_on_warning = false # rpc-error with <error-severity> = 'warning' will not raise RpcError excption
16
+
17
+ def self.raise_on_warning=( bool )
18
+ @raise_on_warning = bool
19
+ end
20
+ def self.raise_on_warning
21
+ @raise_on_warning
22
+ end
23
+
24
+ end
@@ -0,0 +1,38 @@
1
+ module Netconf
2
+
3
+ class InitError < StandardError
4
+ end
5
+
6
+ class StateError < StandardError
7
+ end
8
+
9
+ class OpenError < StandardError
10
+ end
11
+
12
+ class RpcError < StandardError
13
+ attr_reader :trans
14
+ attr_reader :cmd, :rsp
15
+
16
+ def initialize( trans, cmd, rsp )
17
+ @trans = trans
18
+ @cmd = cmd; @rsp = rsp;
19
+ end
20
+
21
+ def to_s
22
+ "RPC command error: #{cmd.first_element_child.name}\n#{rsp.to_xml}"
23
+ end
24
+ end
25
+
26
+ class EditError < Netconf::RpcError
27
+ end
28
+
29
+ class LockError < Netconf::RpcError
30
+ end
31
+
32
+ class CommitError < Netconf::RpcError
33
+ end
34
+
35
+ class ValidateError < Netconf::RpcError
36
+ end
37
+
38
+ 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
@@ -0,0 +1,9 @@
1
+ require 'net/netconf'
2
+ require 'net/netconf/jnpr/rpc'
3
+ require 'net/netconf/jnpr/junos_config'
4
+
5
+ module Netconf::Junos
6
+ NETCONF_CLI = "junoscript netconf need-trailer"
7
+ NETCONF_SHELL = "exec xml-mode netconf need-trailer"
8
+ end
9
+
@@ -0,0 +1,14 @@
1
+ require 'net/netconf'
2
+ require 'net/netconf/ioproc'
3
+ require 'net/netconf/jnpr'
4
+
5
+ module Netconf
6
+ module Junos
7
+ module IOProc
8
+ def trans_open
9
+ @trans = IO.popen( "xml-mode netconf need-trailer", "r+")
10
+ self
11
+ end
12
+ end
13
+ end
14
+ end
@@ -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
+