mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
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:
parent
a51eca364f
commit
a914f494a8
6 changed files with 162 additions and 3 deletions
|
@ -142,7 +142,9 @@ ansible_net_interfaces:
|
||||||
returned: when interfaces is configured
|
returned: when interfaces is configured
|
||||||
type: dict
|
type: dict
|
||||||
ansible_net_neighbors:
|
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
|
returned: when interfaces is configured
|
||||||
type: dict
|
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 run_commands
|
||||||
from ansible.module_utils.network.ios.ios import ios_argument_spec, check_args
|
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.basic import AnsibleModule
|
||||||
from ansible.module_utils.six import iteritems
|
from ansible.module_utils.six import iteritems
|
||||||
from ansible.module_utils.six.moves import zip
|
from ansible.module_utils.six.moves import zip
|
||||||
|
@ -294,7 +297,8 @@ class Interfaces(FactsBase):
|
||||||
'show interfaces',
|
'show interfaces',
|
||||||
'show ip interface',
|
'show ip interface',
|
||||||
'show ipv6 interface',
|
'show ipv6 interface',
|
||||||
'show lldp'
|
'show lldp',
|
||||||
|
'show cdp'
|
||||||
]
|
]
|
||||||
|
|
||||||
def populate(self):
|
def populate(self):
|
||||||
|
@ -302,6 +306,7 @@ class Interfaces(FactsBase):
|
||||||
|
|
||||||
self.facts['all_ipv4_addresses'] = list()
|
self.facts['all_ipv4_addresses'] = list()
|
||||||
self.facts['all_ipv6_addresses'] = list()
|
self.facts['all_ipv6_addresses'] = list()
|
||||||
|
self.facts['neighbors'] = {}
|
||||||
|
|
||||||
data = self.responses[0]
|
data = self.responses[0]
|
||||||
if data:
|
if data:
|
||||||
|
@ -324,7 +329,15 @@ class Interfaces(FactsBase):
|
||||||
if data and not any(err in data for err in lldp_errs):
|
if data and not any(err in data for err in lldp_errs):
|
||||||
neighbors = self.run(['show lldp neighbors detail'])
|
neighbors = self.run(['show lldp neighbors detail'])
|
||||||
if neighbors:
|
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):
|
def populate_interfaces(self, interfaces):
|
||||||
facts = dict()
|
facts = dict()
|
||||||
|
@ -387,6 +400,7 @@ class Interfaces(FactsBase):
|
||||||
intf = self.parse_lldp_intf(entry)
|
intf = self.parse_lldp_intf(entry)
|
||||||
if intf is None:
|
if intf is None:
|
||||||
return facts
|
return facts
|
||||||
|
intf = normalize_interface(intf)
|
||||||
if intf not in facts:
|
if intf not in facts:
|
||||||
facts[intf] = list()
|
facts[intf] = list()
|
||||||
fact = dict()
|
fact = dict()
|
||||||
|
@ -395,6 +409,23 @@ class Interfaces(FactsBase):
|
||||||
facts[intf].append(fact)
|
facts[intf].append(fact)
|
||||||
return facts
|
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):
|
def parse_interfaces(self, data):
|
||||||
parsed = dict()
|
parsed = dict()
|
||||||
key = ''
|
key = ''
|
||||||
|
@ -476,6 +507,16 @@ class Interfaces(FactsBase):
|
||||||
if match:
|
if match:
|
||||||
return match.group(1)
|
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(
|
FACT_SUBSETS = dict(
|
||||||
default=Default,
|
default=Default,
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
Global CDP information:
|
||||||
|
Sending CDP packets every 60 seconds
|
||||||
|
Sending a holdtime value of 180 seconds
|
||||||
|
Sending CDPv2 advertisements is enabled
|
|
@ -0,0 +1,40 @@
|
||||||
|
-------------------------
|
||||||
|
Device ID: R2
|
||||||
|
Entry address(es):
|
||||||
|
IP address: 10.0.0.3
|
||||||
|
Platform: cisco CSR1000V, Capabilities: Router IGMP
|
||||||
|
Interface: GigabitEthernet1, Port ID (outgoing port): GigabitEthernet2
|
||||||
|
Holdtime : 149 sec
|
||||||
|
|
||||||
|
Version :
|
||||||
|
Cisco IOS Software [Everest], Virtual XE Software (X86_64_LINUX_IOSD-UNIVERSALK9-M), Version 16.6.4, RELEASE SOFTWARE (fc3)
|
||||||
|
Technical Support: http://www.cisco.com/techsupport
|
||||||
|
Copyright (c) 1986-2018 by Cisco Systems, Inc.
|
||||||
|
Compiled Sun 08-Jul-18 04:30 by mcpre
|
||||||
|
|
||||||
|
advertisement version: 2
|
||||||
|
Duplex: full
|
||||||
|
Management address(es):
|
||||||
|
IP address: 10.0.0.3
|
||||||
|
|
||||||
|
-------------------------
|
||||||
|
Device ID: R3
|
||||||
|
Entry address(es):
|
||||||
|
IP address: 10.0.0.4
|
||||||
|
Platform: cisco CSR1000V, Capabilities: Router IGMP
|
||||||
|
Interface: GigabitEthernet1, Port ID (outgoing port): GigabitEthernet3
|
||||||
|
Holdtime : 149 sec
|
||||||
|
|
||||||
|
Version :
|
||||||
|
Cisco IOS Software [Everest], Virtual XE Software (X86_64_LINUX_IOSD-UNIVERSALK9-M), Version 16.6.4, RELEASE SOFTWARE (fc3)
|
||||||
|
Technical Support: http://www.cisco.com/techsupport
|
||||||
|
Copyright (c) 1986-2018 by Cisco Systems, Inc.
|
||||||
|
Compiled Sun 08-Jul-18 04:30 by mcpre
|
||||||
|
|
||||||
|
advertisement version: 2
|
||||||
|
Duplex: full
|
||||||
|
Management address(es):
|
||||||
|
IP address: 10.0.0.4
|
||||||
|
|
||||||
|
|
||||||
|
Total cdp entries displayed : 2
|
|
@ -0,0 +1,6 @@
|
||||||
|
|
||||||
|
Global LLDP Information:
|
||||||
|
Status: ACTIVE
|
||||||
|
LLDP advertisements are sent every 30 seconds
|
||||||
|
LLDP hold time advertised is 120 seconds
|
||||||
|
LLDP interface reinitialisation delay is 2 seconds
|
|
@ -0,0 +1,50 @@
|
||||||
|
------------------------------------------------
|
||||||
|
Local Intf: Gi1
|
||||||
|
Chassis id: 001e.14d4.5300
|
||||||
|
Port id: Gi3
|
||||||
|
Port Description: GigabitEthernet3
|
||||||
|
System Name: R3
|
||||||
|
|
||||||
|
System Description:
|
||||||
|
Cisco IOS Software [Everest], Virtual XE Software (X86_64_LINUX_IOSD-UNIVERSALK9-M), Version 16.6.4, RELEASE SOFTWARE (fc3)
|
||||||
|
Technical Support: http://www.cisco.com/techsupport
|
||||||
|
Copyright (c) 1986-2018 by Cisco Systems, Inc.
|
||||||
|
Compiled Sun 08-Jul-18 04:30 by
|
||||||
|
|
||||||
|
Time remaining: 116 seconds
|
||||||
|
System Capabilities: B,R
|
||||||
|
Enabled Capabilities: R
|
||||||
|
Management Addresses:
|
||||||
|
IP: 10.0.0.4
|
||||||
|
Auto Negotiation - not supported
|
||||||
|
Physical media capabilities - not advertised
|
||||||
|
Media Attachment Unit type - not advertised
|
||||||
|
Vlan ID: - not advertised
|
||||||
|
|
||||||
|
------------------------------------------------
|
||||||
|
Local Intf: Gi3
|
||||||
|
Chassis id: 001e.e6c9.6d00
|
||||||
|
Port id: Gi1
|
||||||
|
Port Description: GigabitEthernet1
|
||||||
|
System Name: Rtest
|
||||||
|
|
||||||
|
System Description:
|
||||||
|
Cisco IOS Software [Everest], Virtual XE Software (X86_64_LINUX_IOSD-UNIVERSALK9-M), Version 16.6.4, RELEASE SOFTWARE (fc3)
|
||||||
|
Technical Support: http://www.cisco.com/techsupport
|
||||||
|
Copyright (c) 1986-2018 by Cisco Systems, Inc.
|
||||||
|
Compiled Sun 08-Jul-18 04:30 by
|
||||||
|
|
||||||
|
Time remaining: 116 seconds
|
||||||
|
System Capabilities: B,R
|
||||||
|
Enabled Capabilities: R
|
||||||
|
Management Addresses:
|
||||||
|
IP: 10.3.0.3
|
||||||
|
Auto Negotiation - not supported
|
||||||
|
Physical media capabilities - not advertised
|
||||||
|
Media Attachment Unit type - not advertised
|
||||||
|
Vlan ID: - not advertised
|
||||||
|
|
||||||
|
|
||||||
|
Total entries displayed: 2
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ __metaclass__ = type
|
||||||
|
|
||||||
from units.compat.mock import patch
|
from units.compat.mock import patch
|
||||||
from ansible.modules.network.ios import ios_facts
|
from ansible.modules.network.ios import ios_facts
|
||||||
|
from ansible.module_utils.six import assertCountEqual
|
||||||
from units.modules.utils import set_module_args
|
from units.modules.utils import set_module_args
|
||||||
from .ios_module import TestIosModule, load_fixture
|
from .ios_module import TestIosModule, load_fixture
|
||||||
|
|
||||||
|
@ -87,3 +88,20 @@ class TestIosFactsModule(TestIosModule):
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
result['ansible_facts']['ansible_net_filesystems_info']['bootflash:']['spacefree_kb'], 6453180.0
|
result['ansible_facts']['ansible_net_filesystems_info']['bootflash:']['spacefree_kb'], 6453180.0
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_ios_facts_neighbors(self):
|
||||||
|
set_module_args(dict(gather_subset='interfaces'))
|
||||||
|
result = self.execute_module()
|
||||||
|
assertCountEqual(
|
||||||
|
self,
|
||||||
|
result['ansible_facts']['ansible_net_neighbors'].keys(), ['GigabitEthernet1', 'GigabitEthernet3']
|
||||||
|
)
|
||||||
|
assertCountEqual(
|
||||||
|
self,
|
||||||
|
result['ansible_facts']['ansible_net_neighbors']['GigabitEthernet1'],
|
||||||
|
[{'host': 'R2', 'port': 'GigabitEthernet2'}, {'host': 'R3', 'port': 'GigabitEthernet3'}]
|
||||||
|
)
|
||||||
|
assertCountEqual(
|
||||||
|
self,
|
||||||
|
result['ansible_facts']['ansible_net_neighbors']['GigabitEthernet3'], [{'host': 'Rtest', 'port': 'Gi1'}]
|
||||||
|
)
|
||||||
|
|
Loading…
Add table
Reference in a new issue