Skip to content
This repository has been archived by the owner on Jan 16, 2019. It is now read-only.

Implemented get_cdp_neighbors() and modified get_lldp_neighbors() #185

Open
wants to merge 3 commits into
base: develop
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 52 additions & 4 deletions napalm_ios/ios.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ def __init__(self, hostname, username, password, timeout=60, optional_args=None)
self.password = password
self.timeout = timeout

self.transport = optional_args.get('transport', 'ssh')

# Retrieve file names
self.candidate_cfg = optional_args.get('candidate_cfg', 'candidate_config.txt')
self.merge_cfg = optional_args.get('merge_cfg', 'merge_config.txt')
Expand Down Expand Up @@ -128,7 +130,7 @@ def __init__(self, hostname, username, password, timeout=60, optional_args=None)

def open(self):
"""Open a connection to the device."""
self.device = ConnectHandler(device_type='cisco_ios',
self.device = ConnectHandler(device_type='cisco_ios',,
host=self.hostname,
username=self.username,
password=self.password,
Expand Down Expand Up @@ -670,15 +672,61 @@ def get_optics(self):

return optics_detail

def _get_cdp_neighbors(self):
"""IOS implementation of get_cdp_neighbors."""
cdp = {}
command = 'show cdp neighbors'
output = self._send_command(command)

# Check if router supports the command
if '% Invalid input' in output:
return {}

# Process the output to obtain just the CDP entries
try:
split_output = re.split(r'^Device ID.*$', output, flags=re.M)[1]
split_output = re.split(r'^Total cdp entries displayed.*$', split_output, flags=re.M)[0]
except IndexError:
return {}

split_output = split_output.strip()

partial_line = False # When true, the hostname is on a different line than the other entries
for cdp_entry in split_output.splitlines():
# Example, Router3 Eth 0/2 138 R B Linux Uni Eth 0/1
# We can't use the same method as for LLDP because there are spaces between items
# belonging in the same column. Instead we parse the output using the column lenghts,
# hoping these have a fixed size between different IOS versions.
if len(cdp_entry.split()) == 1:
# Only one field means the hostname was too long and this line belongs with the next one
# Retrieve the
device_id = cdp_entry.strip()
partial_line = True
continue
if partial_line == False:
device_id = cdp_entry[:16].strip()
device_id = device_id.split('.')[0] # We want only the hostname, not the FQDN
local_int_brief = cdp_entry[17:35].strip()
hold_time = cdp_entry[35:46].strip()
capability = cdp_entry[46:58].strip()
remote_port = cdp_entry[68:].strip()
platform_tmp = cdp_entry[58:68].strip() # We might want to retrieve the non-truncated version should we decide to return this information
local_port = self._expand_interface_name(local_int_brief)
entry = {'port': remote_port, 'hostname': device_id}
cdp.setdefault(local_port, [])
cdp[local_port].append(entry)
partial_line = False
return cdp

def get_lldp_neighbors(self):
"""IOS implementation of get_lldp_neighbors."""
lldp = {}
command = 'show lldp neighbors'
output = self._send_command(command)

# Check if router supports the command
if '% Invalid input' in output:
return {}
if '% Invalid input' in output or '% LLDP is not enabled' in output:
return self._get_cdp_neighbors()

# Process the output to obtain just the LLDP entries
try:
Expand Down