ios_facts: Gather CDP neighbor data (#49129)

* ios_facts: Gather CDP neighbor data

* ios_facts: Create tests for ansible_net_neighbors
This commit is contained in:
Paul Neumann 2018-11-29 20:05:17 +01:00 committed by Nathaniel Case
commit a914f494a8
6 changed files with 162 additions and 3 deletions

View file

@ -142,7 +142,9 @@ ansible_net_interfaces:
returned: when interfaces is configured
type: dict
ansible_net_neighbors:
description: The list of LLDP neighbors from the remote device
description:
- The list of CDP and LLDP neighbors from the remote device. If both,
CDP and LLDP neighbor data is present on one port, CDP is preferred.
returned: when interfaces is configured
type: dict
"""
@ -150,6 +152,7 @@ import re
from ansible.module_utils.network.ios.ios import run_commands
from ansible.module_utils.network.ios.ios import ios_argument_spec, check_args
from ansible.module_utils.network.ios.ios import normalize_interface
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.six import iteritems
from ansible.module_utils.six.moves import zip
@ -294,7 +297,8 @@ class Interfaces(FactsBase):
'show interfaces',
'show ip interface',
'show ipv6 interface',
'show lldp'
'show lldp',
'show cdp'
]
def populate(self):
@ -302,6 +306,7 @@ class Interfaces(FactsBase):
self.facts['all_ipv4_addresses'] = list()
self.facts['all_ipv6_addresses'] = list()
self.facts['neighbors'] = {}
data = self.responses[0]
if data:
@ -324,7 +329,15 @@ class Interfaces(FactsBase):
if data and not any(err in data for err in lldp_errs):
neighbors = self.run(['show lldp neighbors detail'])
if neighbors:
self.facts['neighbors'] = self.parse_neighbors(neighbors[0])
self.facts['neighbors'].update(self.parse_neighbors(neighbors[0]))
data = self.responses[4]
cdp_errs = ['CDP is not enabled']
if data and not any(err in data for err in cdp_errs):
cdp_neighbors = self.run(['show cdp neighbors detail'])
if cdp_neighbors:
self.facts['neighbors'].update(self.parse_cdp_neighbors(cdp_neighbors[0]))
def populate_interfaces(self, interfaces):
facts = dict()
@ -387,6 +400,7 @@ class Interfaces(FactsBase):
intf = self.parse_lldp_intf(entry)
if intf is None:
return facts
intf = normalize_interface(intf)
if intf not in facts:
facts[intf] = list()
fact = dict()
@ -395,6 +409,23 @@ class Interfaces(FactsBase):
facts[intf].append(fact)
return facts
def parse_cdp_neighbors(self, neighbors):
facts = dict()
for entry in neighbors.split('-------------------------'):
if entry == '':
continue
intf_port = self.parse_cdp_intf_port(entry)
if intf_port is None:
return facts
intf, port = intf_port
if intf not in facts:
facts[intf] = list()
fact = dict()
fact['host'] = self.parse_cdp_host(entry)
fact['port'] = port
facts[intf].append(fact)
return facts
def parse_interfaces(self, data):
parsed = dict()
key = ''
@ -476,6 +507,16 @@ class Interfaces(FactsBase):
if match:
return match.group(1)
def parse_cdp_intf_port(self, data):
match = re.search(r'^Interface: (.+), Port ID \(outgoing port\): (.+)$', data, re.M)
if match:
return match.group(1), match.group(2)
def parse_cdp_host(self, data):
match = re.search(r'^Device ID: (.+)$', data, re.M)
if match:
return match.group(1)
FACT_SUBSETS = dict(
default=Default,