Skip to content

Instantly share code, notes, and snippets.

@jeremyschulman
Last active December 11, 2015 04:39
Show Gist options
  • Save jeremyschulman/4546586 to your computer and use it in GitHub Desktop.
Save jeremyschulman/4546586 to your computer and use it in GitHub Desktop.
Simple demonstration of "walking LLDP" in a Junos network to create a connection map
require 'highline/import'
require 'net/netconf/jnpr'
start_at = ARGV[0] || begin
puts "You need to specify a starting target ip/host"
exit 1
end
my_username = ENV["USER"]
puts "login: #{my_username}"
my_password = ask("password: "){|a| a.echo = false}
class ScannerLLDP
attr_reader :network_lldp, :devices_ip, :devices_nc
def initialize( name, password )
@network_lldp = {}
@devices_nc = {}
@devices_ip = {}
@visit_list = []
@login = {}
@login[:username] = name
@login[:password] = password
end
def lldp_visit( target_ip )
@login[:target] = target_ip
puts "Connecting to #{target_ip} ..."
dev = Netconf::SSH.new( @login )
dev.open
# record where I am now
my_lldp = dev.rpc.get_lldp_local_info
my_lldp_name = my_lldp.xpath('lldp-local-system-name').text
@devices_nc[my_lldp_name] = dev
@devices_ip[my_lldp_name] = target_ip
puts "Connected to #{my_lldp_name}"
my_cnx_grid = []
# find the places I need to visit
nei_nbs = dev.rpc.get_lldp_neighbors_information
nei_nbs = nei_nbs.xpath('lldp-neighbor-information')
nei_ports = nei_nbs.xpath('lldp-local-interface | lldp-local-port-id')
nei_ports.each do |nei|
if_name = nei.text
# get details on the specific interface
rsp = dev.rpc.command "show lldp neighbors interface #{if_name}"
if_nei = rsp.xpath('lldp-neighbor-information')
rmt_sysname = if_nei.xpath('lldp-remote-system-name').text
rmt_ip = if_nei.xpath('lldp-remote-management-address').text
puts "found #{rmt_sysname}"
my_cnx_grid << { :ifd => if_name, :rmtsys => rmt_sysname }
unless @devices_ip[rmt_sysname]
puts "--> ADDING #{rmt_sysname}"
@devices_ip[rmt_sysname] = rmt_ip
@visit_list << rmt_sysname
end
end
@network_lldp[my_lldp_name] = my_cnx_grid
dev.close
end # lldp_visit
def startat( target_ip )
while target_ip
lldp_visit( target_ip )
target_ip = @devices_ip[@visit_list.pop]
end
end
def devices
@devices_nc.keys
end
def ncopen( name )
unless ncdev = @devices_nc[name]
puts "Invalid name: #{name}"
end
ncdev.open
ncdev
end
end #class
scanner = ScannerLLDP.new( my_username, my_password )
scanner.startat start_at
# At this point you can examine the network connectivity
# by looking at scanner.network_lldp.
# You can connect to any device using scanner.ncopen <name-learned-via-LLDP>
# and then perform any RPC as normally done using the NETCONF gem
# see https://www.github.com/Juniper-Workflow/net-netconf for more details
[2] pry(main)> scanner.network_lldp
=> {"EX4200-153"=>
[{:ifd=>"xe-1/1/1.0", :rmtsys=>"MX240-R132-re0"},
{:ifd=>"xe-0/1/0.0", :rmtsys=>"MX240-R130-re0"}],
"MX240-R130-re0"=>
[{:ifd=>"xe-2/1/2", :rmtsys=>"EX4200-153"},
{:ifd=>"xe-2/0/2", :rmtsys=>"MX240-R178"},
{:ifd=>"xe-2/0/3", :rmtsys=>"MX240-R176-re0"},
{:ifd=>"xe-2/1/0", :rmtsys=>"MX240-R176-re0"},
{:ifd=>"xe-2/0/0", :rmtsys=>"MX240-R132-re0"},
{:ifd=>"xe-2/0/1", :rmtsys=>"MX240-R132-re0"}],
"MX240-R176-re0"=>
[{:ifd=>"xe-2/1/0", :rmtsys=>"MX480-R244"},
{:ifd=>"xe-2/1/1", :rmtsys=>"EX4200-139"},
{:ifd=>"xe-2/0/0", :rmtsys=>"MX240-R132-re0"},
{:ifd=>"xe-2/0/1", :rmtsys=>"MX240-R132-re0"},
{:ifd=>"xe-2/0/2", :rmtsys=>"MX240-R130-re0"},
{:ifd=>"xe-2/0/3", :rmtsys=>"MX240-R130-re0"}],
"EX4200-139"=>[{:ifd=>"xe-1/1/0.0", :rmtsys=>"MX240-R176-re0"}],
"MX480-R244"=>[{:ifd=>"xe-5/0/1", :rmtsys=>"MX240-R176-re0"}],
"MX240-R178"=>[{:ifd=>"xe-2/0/0", :rmtsys=>"MX240-R130-re0"}],
"MX240-R132-re0"=>
[{:ifd=>"xe-2/1/0", :rmtsys=>"EX4200-153"},
{:ifd=>"xe-2/0/2", :rmtsys=>"MX240-R176-re0"},
{:ifd=>"xe-2/0/3", :rmtsys=>"MX240-R176-re0"},
{:ifd=>"xe-2/0/0", :rmtsys=>"MX240-R130-re0"},
{:ifd=>"xe-2/0/1", :rmtsys=>"MX240-R130-re0"}]}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment